GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow) : m_currentWidth(0) , m_currentHeight(0) , m_hostWindow(hostWindow) , m_context(BlackBerry::Platform::Graphics::createWebGLContext()) , m_extensions(adoptPtr(new Extensions3DOpenGL(this))) , m_attrs(attrs) , m_texture(0) , m_fbo(0) , m_depthStencilBuffer(0) , m_boundFBO(0) , m_activeTexture(GL_TEXTURE0) , m_boundTexture0(0) , m_multisampleFBO(0) , m_multisampleDepthStencilBuffer(0) , m_multisampleColorBuffer(0) { if (!renderDirectlyToHostWindow) { #if USE(ACCELERATED_COMPOSITING) m_compositingLayer = WebGLLayerWebKitThread::create(); #endif makeContextCurrent(); Extensions3D* extensions = getExtensions(); if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) m_attrs.antialias = false; // Create a texture to render into. ::glGenTextures(1, &m_texture); ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ::glBindTexture(GL_TEXTURE_2D, 0); // Create an FBO. ::glGenFramebuffers(1, &m_fbo); ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); if (m_attrs.stencil || m_attrs.depth) ::glGenRenderbuffers(1, &m_depthStencilBuffer); m_boundFBO = m_fbo; #if USE(ACCELERATED_COMPOSITING) static_cast<WebGLLayerWebKitThread*>(m_compositingLayer.get())->setWebGLContext(this); #endif } // FIXME: If GraphicsContext3D is created with renderDirectlyToHostWindow == true, // makeContextCurrent() will make the shared context current. makeContextCurrent(); // FIXME: Do we need to enable GL_VERTEX_PROGRAM_POINT_SIZE with GL ES2? See PR #120141. ::glClearColor(0, 0, 0, 0); }
void GraphicsContext3D::validateAttributes() { validateDepthStencil("GL_OES_packed_depth_stencil"); if (m_attrs.antialias) { Extensions3D* extensions = getExtensions(); if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) m_attrs.antialias = false; } }
// static bool WebGLDrawBuffers::supported(WebGLRenderingContext* context) { #if OS(DARWIN) // https://bugs.webkit.org/show_bug.cgi?id=112486 return false; #endif Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); return (extensions->supports("GL_EXT_draw_buffers") && satisfiesWebGLRequirements(context)); }
bool LayerTextureUpdaterSkPicture::createFrameBuffer() { ASSERT(!m_fbo); ASSERT(!m_bufferSize.isEmpty()); // SKIA only needs color and stencil buffers, not depth buffer. // But it is very uncommon for cards to support color + stencil FBO config. // The most common config is color + packed-depth-stencil. // Instead of iterating through all possible FBO configs, we only try the // most common one here. // FIXME: Delegate the task of creating frame-buffer to SKIA. // It has all necessary code to iterate through all possible configs // and choose the one most suitable for its purposes. Extensions3D* extensions = context()->getExtensions(); if (!extensions->supports("GL_OES_packed_depth_stencil")) return false; extensions->ensureEnabled("GL_OES_packed_depth_stencil"); // Create and bind a frame-buffer-object. m_fbo = context()->createFramebuffer(); if (!m_fbo) return false; context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); // We just need to create a stencil buffer for FBO. // The color buffer (texture) will be provided by tiles. // SKIA does not need depth buffer. m_depthStencilBuffer = context()->createRenderbuffer(); if (!m_depthStencilBuffer) { deleteFrameBuffer(); return false; } context()->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); context()->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, m_bufferSize.width(), m_bufferSize.height()); context()->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); context()->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); // Create a skia gpu canvas. GrContext* skiaContext = m_context->grContext(); GrPlatformSurfaceDesc targetDesc; targetDesc.reset(); targetDesc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType; targetDesc.fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit; targetDesc.fWidth = m_bufferSize.width(); targetDesc.fHeight = m_bufferSize.height(); targetDesc.fConfig = kRGBA_8888_GrPixelConfig; targetDesc.fStencilBits = 8; targetDesc.fPlatformRenderTarget = m_fbo; SkAutoTUnref<GrRenderTarget> target(static_cast<GrRenderTarget*>(skiaContext->createPlatformSurface(targetDesc))); SkAutoTUnref<SkDevice> device(new SkGpuDevice(skiaContext, target.get())); m_canvas = adoptPtr(new SkCanvas(device.get())); context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); return true; }
PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, AlphaRequirement alpha) { #if PLATFORM(JS) webkitTrace(); #endif Extensions3D* extensions = context->getExtensions(); bool multisampleSupported = extensions->maySupportMultisampling() && extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample") && extensions->supports("GL_OES_rgb8_rgba8"); if (multisampleSupported) { extensions->ensureEnabled("GL_ANGLE_framebuffer_blit"); extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); extensions->ensureEnabled("GL_OES_rgb8_rgba8"); } bool packedDepthStencilSupported = extensions->supports("GL_OES_packed_depth_stencil"); if (packedDepthStencilSupported) extensions->ensureEnabled("GL_OES_packed_depth_stencil"); RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size, multisampleSupported, packedDepthStencilSupported, preserve, alpha)); return (drawingBuffer->m_context) ? drawingBuffer.release() : 0; }
void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExtension) { Extensions3D* extensions = getExtensions(); if (m_attrs.stencil) { if (extensions->supports(packedDepthStencilExtension)) { extensions->ensureEnabled(packedDepthStencilExtension); // Force depth if stencil is true. m_attrs.depth = true; } else m_attrs.stencil = false; } if (m_attrs.antialias) { bool isValidVendor = true; // Currently in Mac we only turn on antialias if vendor is NVIDIA, // or if ATI and on 10.7.2 and above. const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))) isValidVendor = false; if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); } }
bool WebGLDrawBuffers::supported(WebGLRenderingContextBase* context) { Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); return extensions->supports("GL_EXT_draw_buffers") && satisfiesWebGLRequirements(context); }
bool GraphicsContext3D::reshapeFBOs(const IntSize& size) { const int width = size.width(); const int height = size.height(); GLuint colorFormat, internalDepthStencilFormat = 0; if (m_attrs.alpha) { m_internalColorFormat = GL_RGBA8; colorFormat = GL_RGBA; } else { m_internalColorFormat = GL_RGB8; colorFormat = GL_RGB; } if (m_attrs.stencil || m_attrs.depth) { // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3D::validateAttributes. Extensions3D* extensions = getExtensions(); // Use a 24 bit depth buffer where we know we have it. if (extensions->supports("GL_EXT_packed_depth_stencil")) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else internalDepthStencilFormat = GL_DEPTH_COMPONENT; } bool mustRestoreFBO = false; // Resize multisample FBO. if (m_attrs.antialias) { GLint maxSampleCount; ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); GLint sampleCount = std::min(8, maxSampleCount); if (sampleCount > maxSampleCount) sampleCount = maxSampleCount; if (m_state.boundFBO != m_multisampleFBO) { ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); mustRestoreFBO = true; } ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height); ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); if (m_attrs.stencil) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); if (m_attrs.depth) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); } ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { // FIXME: cleanup. notImplemented(); } } // resize regular FBO if (m_state.boundFBO != m_fbo) { mustRestoreFBO = true; ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); } ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glBindTexture(GL_TEXTURE_2D, 0); if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); if (m_attrs.stencil) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); if (m_attrs.depth) ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { // FIXME: cleanup notImplemented(); } if (m_attrs.antialias) { ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); if (m_state.boundFBO == m_multisampleFBO) mustRestoreFBO = false; } return mustRestoreFBO; }
bool OESTextureFloatLinear::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->extensions(); return extensions->supports("GL_OES_texture_float_linear"); }
bool ANGLEInstancedArrays::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->extensions(); return extensions->supports("GL_ANGLE_instanced_arrays"); }
bool WebGLCompressedTextureATC::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); return extensions->supports("GL_AMD_compressed_ATC_texture"); }
bool OESStandardDerivatives::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->extensions(); return extensions->supports("GL_OES_standard_derivatives"); }
bool OESElementIndexUint::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); return extensions->supports("GL_OES_element_index_uint"); }
bool OESVertexArrayObject::supported(WebGLRenderingContext* context) { Extensions3D* extensions = context->graphicsContext3D()->extensions(); return extensions->supports("GL_OES_vertex_array_object"); }