void DrawingBuffer::prepareBackBuffer() { if (!m_context || !m_contentsChanged) return; m_context->makeContextCurrent(); if (multisample()) commit(); if (m_preserveDrawingBuffer == Discard && m_separateFrontTexture) { swap(m_frontColorBuffer, 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(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); } if (multisample() && !m_framebufferBinding) bind(); else restoreFramebufferBinding(); m_contentsChanged = false; }
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; }
bool DrawingBuffer::resizeFramebuffer(const IntSize& size) { // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContext3D::UNSIGNED_BYTE); if (m_lastColorBuffer) m_lastColorBuffer->size = m_size; m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); // resize the front color buffer if (m_separateFrontTexture) { m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer); m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContext3D::UNSIGNED_BYTE); } m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(size, 0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) return false; return true; }
void DrawingBuffer::createSecondaryBuffers() { // create a multisample FBO if (multisample()) { m_multisampleFBO = m_context->createFramebuffer(); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_multisampleColorBuffer = m_context->createRenderbuffer(); } }
void DrawingBuffer::resizeDepthStencil(int sampleCount) { #if PLATFORM(JS) webkitTrace(); #endif const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); if (attributes.depth && attributes.stencil && m_packedDepthStencilExtensionSupported) { if (!m_depthStencilBuffer) m_depthStencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); if (multisample()) m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, m_size.width(), m_size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); } else { if (attributes.depth) { if (!m_depthBuffer) m_depthBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); if (multisample()) m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, m_size.width(), m_size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); } if (attributes.stencil) { if (!m_stencilBuffer) m_stencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); if (multisample()) m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, m_size.width(), m_size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); } } m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); }
void DrawingBuffer::resizeDepthStencil(const IntSize& size, int sampleCount) { if (m_attributes.depth && m_attributes.stencil && m_packedDepthStencilExtensionSupported) { if (!m_depthStencilBuffer) m_depthStencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, Extensions3D::DEPTH24_STENCIL8, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthStencilBuffer); } else { if (m_attributes.depth) { if (!m_depthBuffer) m_depthBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::DEPTH_COMPONENT16, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); } if (m_attributes.stencil) { if (!m_stencilBuffer) m_stencilBuffer = m_context->createRenderbuffer(); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); if (multisample()) m_context->extensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); else m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, size.width(), size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); } } m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); }
void DrawingBuffer::publishToPlatformLayer() { if (!m_context) return; if (m_callback) m_callback->willPublish(); if (multisample()) commit(); unsigned parentTexture = m_internal->platformLayer->textureId(); // FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to // other commands in the child context. This ensures that the parent texture always contains a complete // frame and not some intermediate result. However, there is no synchronization to ensure that this copy // happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this // would insert a fence into the child command stream that the compositor could wait for. m_context->makeContextCurrent(); #if ENABLE(SKIA_GPU) GetGlobalGrContext()->flush(false); #endif static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture); m_context->flush(); }
bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size) { if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(4, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, m_internalRenderbufferFormat, size.width(), size.height()); if (m_context->getError() == GraphicsContext3D::OUT_OF_MEMORY) return false; m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(size, sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) return false; } return true; }
bool DrawingBuffer::reset(const IntSize& newSize) { if (!m_context) return false; m_context->makeContextCurrent(); int maxTextureSize = 0; m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); if (newSize.height() > maxTextureSize || newSize.width() > maxTextureSize) { clear(); return false; } int pixelDelta = newSize.width() * newSize.height(); int oldSize = 0; if (!m_size.isEmpty()) { oldSize = m_size.width() * m_size.height(); pixelDelta -= oldSize; } IntSize adjustedSize = newSize; if (s_maximumResourceUsePixels) { while ((s_currentResourceUsePixels + pixelDelta) > s_maximumResourceUsePixels) { adjustedSize.scale(s_resourceAdjustedRatio); if (adjustedSize.isEmpty()) { clear(); return false; } pixelDelta = adjustedSize.width() * adjustedSize.height(); pixelDelta -= oldSize; } } const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); if (adjustedSize != m_size) { unsigned internalColorFormat, colorFormat, internalRenderbufferFormat; if (attributes.alpha) { internalColorFormat = GraphicsContext3D::RGBA; colorFormat = GraphicsContext3D::RGBA; internalRenderbufferFormat = Extensions3D::RGBA8_OES; } else { internalColorFormat = GraphicsContext3D::RGB; colorFormat = GraphicsContext3D::RGB; internalRenderbufferFormat = Extensions3D::RGB8_OES; } do { m_size = adjustedSize; // resize multisample FBO if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(4, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { adjustedSize.scale(s_resourceAdjustedRatio); continue; } } // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); // resize the front color buffer if (m_separateFrontTexture) { m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer); m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); } m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE) break; adjustedSize.scale(s_resourceAdjustedRatio); } while (!adjustedSize.isEmpty()); pixelDelta = m_size.width() * m_size.height(); pixelDelta -= oldSize; s_currentResourceUsePixels += pixelDelta; if (!newSize.isEmpty() && adjustedSize.isEmpty()) { clear(); return false; } } m_context->disable(GraphicsContext3D::SCISSOR_TEST); m_context->clearColor(0, 0, 0, 0); m_context->colorMask(true, true, true, true); GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT; if (attributes.depth) { m_context->clearDepth(1.0f); clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT; m_context->depthMask(true); } if (attributes.stencil) { m_context->clearStencil(0); clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT; m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF); } clearFramebuffers(clearMask); return true; }
bool DrawingBuffer::reset(const IntSize& newSize) { #if 0 if (!m_context) return false; m_context->makeContextCurrent(); int maxTextureSize = 0; m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); if (newSize.height() > maxTextureSize || newSize.width() > maxTextureSize) { clear(); return false; } const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); if (newSize != m_size) { m_size = newSize; unsigned long internalColorFormat, colorFormat, internalRenderbufferFormat; if (attributes.alpha) { internalColorFormat = GraphicsContext3D::RGBA; colorFormat = GraphicsContext3D::RGBA; internalRenderbufferFormat = Extensions3D::RGBA8_OES; } else { internalColorFormat = GraphicsContext3D::RGB; colorFormat = GraphicsContext3D::RGB; internalRenderbufferFormat = Extensions3D::RGB8_OES; } // resize multisample FBO if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(8, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } clearFramebuffer(); didReset(); #endif return true; }
void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); if (fetch_depth) { if (!mDepth) { allocateDepth(); } gGL.getTexUnit(0)->bind(this); glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); } else { stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); if (mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE_ARB); stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); stop_glerror(); check_framebuffer_status(); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI) { glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); } else glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); stop_glerror(); if (mTex.size() > 1) { for (U32 i = 1; i < mTex.size(); ++i) { glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); stop_glerror(); glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } for (U32 i = 0; i < mTex.size(); ++i) { glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); stop_glerror(); } } } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } }
void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); stop_glerror(); if (fetch_depth) { if (!mDepth) { allocateDepth(); } gGL.getTexUnit(0)->bind(this,true); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); stop_glerror(); //glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); } else { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); if (mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); check_framebuffer_status(); glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI) { glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); } else { glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); } stop_glerror(); //Following case never currently evalutes true, but it's still good to have. if (mTex.size() > 1) { for (U32 i = 1; i < mTex.size(); ++i) { glDrawBuffer(GL_COLOR_ATTACHMENT0 + i); glReadBuffer(GL_COLOR_ATTACHMENT0 + i); stop_glerror(); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } /*for (U32 i = 1; i < mTex.size(); ++i) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } for (U32 i = 0; i < mTex.size(); ++i) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); }*/ } glBindFramebuffer(GL_FRAMEBUFFER, 0); } } }
bool DrawingBuffer::reset(const IntSize& newSize) { if (!m_context) return false; m_context->makeContextCurrent(); int maxTextureSize = 0; m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); if (newSize.height() > maxTextureSize || newSize.width() > maxTextureSize) { clear(); return false; } int pixelDelta = newSize.width() * newSize.height(); if (!m_size.isEmpty()) pixelDelta -= m_size.width() * m_size.height(); if (s_maximumResourceUsePixels && (s_currentResourceUsePixels + pixelDelta) > s_maximumResourceUsePixels) { clear(); return false; } s_currentResourceUsePixels += pixelDelta; const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); if (newSize != m_size) { m_size = newSize; unsigned internalColorFormat, colorFormat, internalRenderbufferFormat; if (attributes.alpha) { internalColorFormat = GraphicsContext3D::RGBA; colorFormat = GraphicsContext3D::RGBA; internalRenderbufferFormat = Extensions3D::RGBA8_OES; } else { internalColorFormat = GraphicsContext3D::RGB; colorFormat = GraphicsContext3D::RGB; internalRenderbufferFormat = Extensions3D::RGB8_OES; } // resize multisample FBO if (multisample()) { int maxSampleCount = 0; m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); int sampleCount = std::min(4, maxSampleCount); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); resizeDepthStencil(sampleCount); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } // resize regular FBO m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); // resize the backing color buffer if (m_separateBackingTexture) { m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_backingColorBuffer); m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); } m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); if (!multisample()) resizeDepthStencil(0); if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { // Cleanup clear(); return false; } } clearFramebuffer(); return true; }