void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer) { if (!m_context || !m_context->makeContextCurrent() || m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR) return; Extensions3D* extensions = m_context->getExtensions(); #if ENABLE(CANVAS_USES_MAILBOX) // Since the m_frontColorBuffer was produced and sent to the compositor, it cannot be bound to an fbo. // We have to make a copy of it here and bind that copy instead. unsigned sourceTexture = createColorTexture(m_size); extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE); #else // FIXME: Re-examine general correctness of this code beacause m_colorBuffer may contain a stale copy of the data // that was sent to the compositor at some point in the past. unsigned sourceTexture = frontColorBuffer(); #endif // ENABLE(CANVAS_USES_MAILBOX) // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding). // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value // rather than querying it off of the context. GC3Dint previousFramebuffer = 0; m_context->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer); Platform3DObject framebuffer = m_context->createFramebuffer(); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, sourceTexture, 0); extensions->paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_attributes.premultipliedAlpha, imageBuffer); m_context->deleteFramebuffer(framebuffer); #if ENABLE(CANVAS_USES_MAILBOX) m_context->deleteTexture(sourceTexture); #endif // ENABLE(CANVAS_USES_MAILBOX) m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer); }
bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY) { if (!m_data.m_layerBridge || !platformLayer()) return false; Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture(); if (!context.makeContextCurrent()) return false; Extensions3D* extensions = context.getExtensions(); if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")) return false; // The canvas is stored in a premultiplied format, so unpremultiply if necessary. context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha); // The canvas is stored in an inverted position, so the flip semantics are reversed. context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, !flipY); extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, sourceTexture, texture, 0, internalFormat); context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false); context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false); context.flush(); return true; }
bool DrawingBuffer::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox) { if (!m_context || !m_contentsChanged || !m_lastColorBuffer) return false; m_context->makeContextCurrent(); // Resolve the multisampled buffer into the texture referenced by m_lastColorBuffer mailbox. if (multisample()) commit(); // We must restore the texture binding since creating new textures, // consuming and producing mailboxes changes it. ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureUnit, m_texture2DBinding); // First try to recycle an old buffer. RefPtr<MailboxInfo> nextFrontColorBuffer = getRecycledMailbox(); // No buffer available to recycle, create a new one. if (!nextFrontColorBuffer) { unsigned newColorBuffer = createColorTexture(m_size); // Bad things happened, abandon ship. if (!newColorBuffer) return false; nextFrontColorBuffer = createNewMailbox(newColorBuffer); } if (m_preserveDrawingBuffer == Discard) { m_colorBuffer = nextFrontColorBuffer->textureId; swap(nextFrontColorBuffer, m_lastColorBuffer); // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding. // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore // it after attaching the new back buffer here. m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); } else { Extensions3D* extensions = m_context->getExtensions(); extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_colorBuffer, nextFrontColorBuffer->textureId, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE); } if (multisample() && !m_framebufferBinding) bind(); else restoreFramebufferBinding(); m_contentsChanged = false; context()->bindTexture(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->textureId); context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->mailbox.name); context()->flush(); m_context->markLayerComposited(); *outMailbox = nextFrontColorBuffer->mailbox; m_frontColorBuffer = nextFrontColorBuffer->textureId; return true; }