bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap) { if (!m_context || !m_contentsChanged) return false; m_context->makeContextCurrent(); // Resolve the multisampled buffer into m_colorBuffer texture. if (m_multisampleMode != None) commit(); if (bitmap) { bitmap->setSize(size()); unsigned char* pixels = bitmap->pixels(); bool needPremultiply = m_attributes.alpha && !m_attributes.premultipliedAlpha; WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing; if (pixels) readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia, op); } // We must restore the texture binding since creating new textures, // consuming and producing mailboxes changes it. ScopedTextureUnit0BindingRestorer restorer(m_context, m_activeTextureUnit, m_texture2DBinding); // First try to recycle an old buffer. RefPtr<MailboxInfo> frontColorBufferMailbox = recycledMailbox(); // No buffer available to recycle, create a new one. if (!frontColorBufferMailbox) { unsigned newColorBuffer = createColorTexture(m_size); // Bad things happened, abandon ship. if (!newColorBuffer) return false; frontColorBufferMailbox = createNewMailbox(newColorBuffer); } if (m_preserveDrawingBuffer == Discard) { swap(frontColorBufferMailbox->textureId, m_colorBuffer); // 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(GL_FRAMEBUFFER, m_fbo); if (m_multisampleMode == ImplicitResolve) m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0, m_sampleCount); else m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0); } else { m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_colorBuffer, frontColorBufferMailbox->textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE); } if (m_multisampleMode != None && !m_framebufferBinding) bind(); else restoreFramebufferBinding(); m_contentsChanged = false; m_context->bindTexture(GL_TEXTURE_2D, frontColorBufferMailbox->textureId); m_context->produceTextureCHROMIUM(GL_TEXTURE_2D, frontColorBufferMailbox->mailbox.name); m_context->flush(); frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); markLayerComposited(); *outMailbox = frontColorBufferMailbox->mailbox; m_frontColorBuffer = frontColorBufferMailbox->textureId; return true; }
void WebGPUSwapChain::present() { markLayerComposited(); }