| Index: Source/core/platform/graphics/gpu/DrawingBuffer.cpp
|
| diff --git a/Source/core/platform/graphics/gpu/DrawingBuffer.cpp b/Source/core/platform/graphics/gpu/DrawingBuffer.cpp
|
| deleted file mode 100644
|
| index 1ce2937c2821f36dfac495fe2aced77f37cb41dc..0000000000000000000000000000000000000000
|
| --- a/Source/core/platform/graphics/gpu/DrawingBuffer.cpp
|
| +++ /dev/null
|
| @@ -1,761 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2010, Google Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions are
|
| - * met:
|
| - *
|
| - * * Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * * Redistributions in binary form must reproduce the above
|
| - * copyright notice, this list of conditions and the following disclaimer
|
| - * in the documentation and/or other materials provided with the
|
| - * distribution.
|
| - * * Neither the name of Google Inc. nor the names of its
|
| - * contributors may be used to endorse or promote products derived from
|
| - * this software without specific prior written permission.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "config.h"
|
| -
|
| -#include "core/platform/graphics/gpu/DrawingBuffer.h"
|
| -
|
| -#include <algorithm>
|
| -#include "core/platform/graphics/Extensions3D.h"
|
| -#include "core/platform/graphics/GraphicsLayer.h"
|
| -#include "platform/TraceEvent.h"
|
| -#include "public/platform/Platform.h"
|
| -#include "public/platform/WebCompositorSupport.h"
|
| -#include "public/platform/WebExternalBitmap.h"
|
| -#include "public/platform/WebExternalTextureLayer.h"
|
| -#include "public/platform/WebGraphicsContext3D.h"
|
| -
|
| -using namespace std;
|
| -
|
| -namespace WebCore {
|
| -
|
| -// Global resource ceiling (expressed in terms of pixels) for DrawingBuffer creation and resize.
|
| -// When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() calls that would
|
| -// exceed the global cap will instead clear the buffer.
|
| -static const int s_maximumResourceUsePixels = 16 * 1024 * 1024;
|
| -static int s_currentResourceUsePixels = 0;
|
| -static const float s_resourceAdjustedRatio = 0.5;
|
| -
|
| -static const bool s_allowContextEvictionOnCreate = true;
|
| -static const int s_maxScaleAttempts = 3;
|
| -
|
| -class ScopedTextureUnit0BindingRestorer {
|
| -public:
|
| - ScopedTextureUnit0BindingRestorer(GraphicsContext3D* context, GC3Denum activeTextureUnit, Platform3DObject textureUnitZeroId)
|
| - : m_context(context)
|
| - , m_oldActiveTextureUnit(activeTextureUnit)
|
| - , m_oldTextureUnitZeroId(textureUnitZeroId)
|
| - {
|
| - m_context->activeTexture(GraphicsContext3D::TEXTURE0);
|
| - }
|
| - ~ScopedTextureUnit0BindingRestorer()
|
| - {
|
| - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_oldTextureUnitZeroId);
|
| - m_context->activeTexture(m_oldActiveTextureUnit);
|
| - }
|
| -
|
| -private:
|
| - GraphicsContext3D* m_context;
|
| - GC3Denum m_oldActiveTextureUnit;
|
| - Platform3DObject m_oldTextureUnitZeroId;
|
| -};
|
| -
|
| -PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager)
|
| -{
|
| - Extensions3D* extensions = context->extensions();
|
| - bool multisampleSupported = 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, contextEvictionManager));
|
| - return drawingBuffer.release();
|
| -}
|
| -
|
| -DrawingBuffer::DrawingBuffer(GraphicsContext3D* context,
|
| - const IntSize& size,
|
| - bool multisampleExtensionSupported,
|
| - bool packedDepthStencilExtensionSupported,
|
| - PreserveDrawingBuffer preserve,
|
| - PassRefPtr<ContextEvictionManager> contextEvictionManager)
|
| - : m_preserveDrawingBuffer(preserve)
|
| - , m_scissorEnabled(false)
|
| - , m_texture2DBinding(0)
|
| - , m_framebufferBinding(0)
|
| - , m_activeTextureUnit(GraphicsContext3D::TEXTURE0)
|
| - , m_context(context)
|
| - , m_size(-1, -1)
|
| - , m_multisampleExtensionSupported(multisampleExtensionSupported)
|
| - , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported)
|
| - , m_fbo(0)
|
| - , m_colorBuffer(0)
|
| - , m_frontColorBuffer(0)
|
| - , m_depthStencilBuffer(0)
|
| - , m_depthBuffer(0)
|
| - , m_stencilBuffer(0)
|
| - , m_multisampleFBO(0)
|
| - , m_multisampleColorBuffer(0)
|
| - , m_contentsChanged(true)
|
| - , m_contentsChangeCommitted(false)
|
| - , m_internalColorFormat(0)
|
| - , m_colorFormat(0)
|
| - , m_internalRenderbufferFormat(0)
|
| - , m_maxTextureSize(0)
|
| - , m_contextEvictionManager(contextEvictionManager)
|
| -{
|
| - // Used by browser tests to detect the use of a DrawingBuffer.
|
| - TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation");
|
| - initialize(size);
|
| -}
|
| -
|
| -DrawingBuffer::~DrawingBuffer()
|
| -{
|
| - releaseResources();
|
| -}
|
| -
|
| -void DrawingBuffer::markContentsChanged()
|
| -{
|
| - m_contentsChanged = true;
|
| - m_contentsChangeCommitted = false;
|
| -}
|
| -
|
| -blink::WebGraphicsContext3D* DrawingBuffer::context()
|
| -{
|
| - if (!m_context)
|
| - return 0;
|
| - return m_context->webContext();
|
| -}
|
| -
|
| -bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
|
| -{
|
| - 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();
|
| -
|
| - if (bitmap) {
|
| - bitmap->setSize(size());
|
| -
|
| - unsigned char* pixels = bitmap->pixels();
|
| - bool needPremultiply = m_attributes.alpha && !m_attributes.premultipliedAlpha;
|
| - GraphicsContext3D::AlphaOp op = needPremultiply ? GraphicsContext3D::AlphaDoPremultiply : GraphicsContext3D::AlphaDoNothing;
|
| - if (pixels)
|
| - m_context->readBackFramebuffer(pixels, size().width(), size().height(), GraphicsContext3D::ReadbackSkia, op);
|
| - }
|
| -
|
| - // 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 = recycledMailbox();
|
| -
|
| - // 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->extensions();
|
| - 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;
|
| -}
|
| -
|
| -void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox)
|
| -{
|
| - for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
|
| - RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i];
|
| - if (!memcmp(mailboxInfo->mailbox.name, mailbox.name, sizeof(mailbox.name))) {
|
| - mailboxInfo->mailbox.syncPoint = mailbox.syncPoint;
|
| - m_recycledMailboxes.append(mailboxInfo.release());
|
| - return;
|
| - }
|
| - }
|
| - ASSERT_NOT_REACHED();
|
| -}
|
| -
|
| -PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox()
|
| -{
|
| - if (!m_context || m_recycledMailboxes.isEmpty())
|
| - return PassRefPtr<MailboxInfo>();
|
| -
|
| - RefPtr<MailboxInfo> mailboxInfo = m_recycledMailboxes.last().release();
|
| - m_recycledMailboxes.removeLast();
|
| -
|
| - if (mailboxInfo->mailbox.syncPoint) {
|
| - context()->waitSyncPoint(mailboxInfo->mailbox.syncPoint);
|
| - mailboxInfo->mailbox.syncPoint = 0;
|
| - }
|
| -
|
| - context()->bindTexture(GraphicsContext3D::TEXTURE_2D, mailboxInfo->textureId);
|
| - context()->consumeTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, mailboxInfo->mailbox.name);
|
| -
|
| - if (mailboxInfo->size != m_size) {
|
| - m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_internalColorFormat, m_size.width(), m_size.height(), 0, m_colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
|
| - mailboxInfo->size = m_size;
|
| - }
|
| -
|
| - return mailboxInfo.release();
|
| -}
|
| -
|
| -PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(unsigned textureId)
|
| -{
|
| - RefPtr<MailboxInfo> returnMailbox = adoptRef(new MailboxInfo());
|
| - context()->genMailboxCHROMIUM(returnMailbox->mailbox.name);
|
| - returnMailbox->textureId = textureId;
|
| - returnMailbox->size = m_size;
|
| - m_textureMailboxes.append(returnMailbox);
|
| - return returnMailbox.release();
|
| -}
|
| -
|
| -void DrawingBuffer::initialize(const IntSize& size)
|
| -{
|
| - ASSERT(m_context);
|
| - m_attributes = m_context->getContextAttributes();
|
| -
|
| - if (m_attributes.alpha) {
|
| - m_internalColorFormat = GraphicsContext3D::RGBA;
|
| - m_colorFormat = GraphicsContext3D::RGBA;
|
| - m_internalRenderbufferFormat = Extensions3D::RGBA8_OES;
|
| - } else {
|
| - m_internalColorFormat = GraphicsContext3D::RGB;
|
| - m_colorFormat = GraphicsContext3D::RGB;
|
| - m_internalRenderbufferFormat = Extensions3D::RGB8_OES;
|
| - }
|
| -
|
| - m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
|
| -
|
| - m_fbo = m_context->createFramebuffer();
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
|
| - m_colorBuffer = createColorTexture();
|
| - m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0);
|
| - createSecondaryBuffers();
|
| - reset(size);
|
| - m_lastColorBuffer = createNewMailbox(m_colorBuffer);
|
| -}
|
| -
|
| -unsigned DrawingBuffer::frontColorBuffer() const
|
| -{
|
| - return m_frontColorBuffer;
|
| -}
|
| -
|
| -bool DrawingBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DObject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool premultiplyAlpha, bool flipY)
|
| -{
|
| - if (!m_context || !m_context->makeContextCurrent())
|
| - return false;
|
| - if (m_contentsChanged) {
|
| - if (multisample()) {
|
| - commit();
|
| - if (!m_framebufferBinding)
|
| - bind();
|
| - else
|
| - restoreFramebufferBinding();
|
| - }
|
| - m_context->flush();
|
| - }
|
| - Platform3DObject sourceTexture = colorBuffer();
|
| -
|
| - if (!context.makeContextCurrent())
|
| - return false;
|
| - Extensions3D* extensions = context.extensions();
|
| - if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->supports("GL_CHROMIUM_flipy")
|
| - || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, level))
|
| - return false;
|
| -
|
| - bool unpackPremultiplyAlphaNeeded = false;
|
| - bool unpackUnpremultiplyAlphaNeeded = false;
|
| - if (m_attributes.alpha && m_attributes.premultipliedAlpha && !premultiplyAlpha)
|
| - unpackUnpremultiplyAlphaNeeded = true;
|
| - else if (m_attributes.alpha && !m_attributes.premultipliedAlpha && premultiplyAlpha)
|
| - unpackPremultiplyAlphaNeeded = true;
|
| -
|
| - context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, unpackUnpremultiplyAlphaNeeded);
|
| - context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, unpackPremultiplyAlphaNeeded);
|
| - context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, flipY);
|
| - extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
|
| - context.pixelStorei(Extensions3D::UNPACK_FLIP_Y_CHROMIUM, false);
|
| - context.pixelStorei(Extensions3D::UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
|
| - context.pixelStorei(Extensions3D::UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -Platform3DObject DrawingBuffer::framebuffer() const
|
| -{
|
| - return m_fbo;
|
| -}
|
| -
|
| -blink::WebLayer* DrawingBuffer::platformLayer()
|
| -{
|
| - if (!m_context)
|
| - return 0;
|
| -
|
| - if (!m_layer) {
|
| - m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
|
| -
|
| - m_layer->setOpaque(!m_attributes.alpha);
|
| - m_layer->setBlendBackgroundColor(m_attributes.alpha);
|
| - m_layer->setPremultipliedAlpha(m_attributes.premultipliedAlpha);
|
| - GraphicsLayer::registerContentsLayer(m_layer->layer());
|
| - }
|
| -
|
| - return m_layer->layer();
|
| -}
|
| -
|
| -void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
|
| -{
|
| - if (!m_context || !m_context->makeContextCurrent() || m_context->extensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR)
|
| - return;
|
| -
|
| - Extensions3D* extensions = m_context->extensions();
|
| -
|
| - if (!imageBuffer)
|
| - return;
|
| - Platform3DObject tex = imageBuffer->getBackingTexture();
|
| - if (tex) {
|
| - extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer,
|
| - tex, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
|
| - return;
|
| - }
|
| -
|
| - // 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.
|
| - // FIXME: That's not true any more, provided we don't change texture
|
| - // parameters.
|
| - unsigned sourceTexture = createColorTexture(m_size);
|
| - extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
|
| -
|
| - // 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);
|
| - m_context->deleteTexture(sourceTexture);
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer);
|
| -}
|
| -
|
| -void DrawingBuffer::clearPlatformLayer()
|
| -{
|
| - if (m_layer)
|
| - m_layer->clearTexture();
|
| -
|
| - if (m_context)
|
| - m_context->flush();
|
| -}
|
| -
|
| -void DrawingBuffer::releaseResources()
|
| -{
|
| - if (m_context) {
|
| - m_context->makeContextCurrent();
|
| -
|
| - clearPlatformLayer();
|
| -
|
| - for (size_t i = 0; i < m_textureMailboxes.size(); i++)
|
| - m_context->deleteTexture(m_textureMailboxes[i]->textureId);
|
| -
|
| - if (m_multisampleColorBuffer)
|
| - m_context->deleteRenderbuffer(m_multisampleColorBuffer);
|
| -
|
| - if (m_depthStencilBuffer)
|
| - m_context->deleteRenderbuffer(m_depthStencilBuffer);
|
| -
|
| - if (m_depthBuffer)
|
| - m_context->deleteRenderbuffer(m_depthBuffer);
|
| -
|
| - if (m_stencilBuffer)
|
| - m_context->deleteRenderbuffer(m_stencilBuffer);
|
| -
|
| - if (m_multisampleFBO)
|
| - m_context->deleteFramebuffer(m_multisampleFBO);
|
| -
|
| - if (m_fbo)
|
| - m_context->deleteFramebuffer(m_fbo);
|
| -
|
| - m_context.clear();
|
| - }
|
| -
|
| - setSize(IntSize());
|
| -
|
| - m_colorBuffer = 0;
|
| - m_frontColorBuffer = 0;
|
| - m_multisampleColorBuffer = 0;
|
| - m_depthStencilBuffer = 0;
|
| - m_depthBuffer = 0;
|
| - m_stencilBuffer = 0;
|
| - m_multisampleFBO = 0;
|
| - m_fbo = 0;
|
| - m_contextEvictionManager.clear();
|
| -
|
| - m_lastColorBuffer.clear();
|
| - m_recycledMailboxes.clear();
|
| - m_textureMailboxes.clear();
|
| -
|
| - if (m_layer) {
|
| - GraphicsLayer::unregisterContentsLayer(m_layer->layer());
|
| - m_layer.clear();
|
| - }
|
| -}
|
| -
|
| -unsigned DrawingBuffer::createColorTexture(const IntSize& size)
|
| -{
|
| - if (!m_context)
|
| - return 0;
|
| -
|
| - unsigned offscreenColorTexture = m_context->createTexture();
|
| - if (!offscreenColorTexture)
|
| - return 0;
|
| -
|
| - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture);
|
| - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
|
| - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
|
| - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
|
| - m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
|
| - if (!size.isEmpty())
|
| - m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
|
| -
|
| - return offscreenColorTexture;
|
| -}
|
| -
|
| -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();
|
| - }
|
| -}
|
| -
|
| -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);
|
| -
|
| - 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;
|
| -}
|
| -
|
| -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->extensions()->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;
|
| -}
|
| -
|
| -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::clearFramebuffers(GC3Dbitfield clearMask)
|
| -{
|
| - if (!m_context)
|
| - return;
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
|
| -
|
| - m_context->clear(clearMask);
|
| -
|
| - // The multisample fbo was just cleared, but we also need to clear the non-multisampled buffer too.
|
| - if (m_multisampleFBO) {
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
|
| - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
|
| - }
|
| -}
|
| -
|
| -void DrawingBuffer::setSize(const IntSize& size) {
|
| - if (m_size == size)
|
| - return;
|
| -
|
| - s_currentResourceUsePixels += pixelDelta(size);
|
| - m_size = size;
|
| -}
|
| -
|
| -int DrawingBuffer::pixelDelta(const IntSize& size) {
|
| - return (max(0, size.width()) * max(0, size.height())) - (max(0, m_size.width()) * max(0, m_size.height()));
|
| -}
|
| -
|
| -IntSize DrawingBuffer::adjustSize(const IntSize& size) {
|
| - IntSize adjustedSize = size;
|
| -
|
| - // Clamp if the desired size is greater than the maximum texture size for the device.
|
| - if (adjustedSize.height() > m_maxTextureSize)
|
| - adjustedSize.setHeight(m_maxTextureSize);
|
| -
|
| - if (adjustedSize.width() > m_maxTextureSize)
|
| - adjustedSize.setWidth(m_maxTextureSize);
|
| -
|
| - // Try progressively smaller sizes until we find a size that fits or reach a scale limit.
|
| - int scaleAttempts = 0;
|
| - while ((s_currentResourceUsePixels + pixelDelta(adjustedSize)) > s_maximumResourceUsePixels) {
|
| - scaleAttempts++;
|
| - if (scaleAttempts > s_maxScaleAttempts)
|
| - return IntSize();
|
| -
|
| - adjustedSize.scale(s_resourceAdjustedRatio);
|
| -
|
| - if (adjustedSize.isEmpty())
|
| - return IntSize();
|
| - }
|
| -
|
| - return adjustedSize;
|
| -}
|
| -
|
| -IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext) {
|
| - IntSize adjustedSize = adjustSize(size);
|
| - if (!adjustedSize.isEmpty()) {
|
| - evictContext = false;
|
| - return adjustedSize; // Buffer fits without evicting a context.
|
| - }
|
| -
|
| - // Speculatively adjust the pixel budget to see if the buffer would fit should the oldest context be evicted.
|
| - IntSize oldestSize = m_contextEvictionManager->oldestContextSize();
|
| - int pixelDelta = oldestSize.width() * oldestSize.height();
|
| -
|
| - s_currentResourceUsePixels -= pixelDelta;
|
| - adjustedSize = adjustSize(size);
|
| - s_currentResourceUsePixels += pixelDelta;
|
| -
|
| - evictContext = !adjustedSize.isEmpty();
|
| - return adjustedSize;
|
| -}
|
| -
|
| -void DrawingBuffer::reset(const IntSize& newSize)
|
| -{
|
| - if (!m_context)
|
| - return;
|
| -
|
| - IntSize adjustedSize;
|
| - bool evictContext = false;
|
| - bool isNewContext = m_size.isEmpty();
|
| - if (s_allowContextEvictionOnCreate && isNewContext)
|
| - adjustedSize = adjustSizeWithContextEviction(newSize, evictContext);
|
| - else
|
| - adjustedSize = adjustSize(newSize);
|
| -
|
| - if (adjustedSize.isEmpty())
|
| - return;
|
| -
|
| - if (evictContext)
|
| - m_contextEvictionManager->forciblyLoseOldestContext("WARNING: WebGL contexts have exceeded the maximum allowed backbuffer area. Oldest context will be lost.");
|
| -
|
| - if (adjustedSize != m_size) {
|
| - do {
|
| - // resize multisample FBO
|
| - if (!resizeMultisampleFramebuffer(adjustedSize) || !resizeFramebuffer(adjustedSize)) {
|
| - adjustedSize.scale(s_resourceAdjustedRatio);
|
| - continue;
|
| - }
|
| - break;
|
| - } while (!adjustedSize.isEmpty());
|
| -
|
| - setSize(adjustedSize);
|
| -
|
| - if (adjustedSize.isEmpty())
|
| - return;
|
| - }
|
| -
|
| - 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 (m_attributes.depth) {
|
| - m_context->clearDepth(1.0f);
|
| - clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
|
| - m_context->depthMask(true);
|
| - }
|
| - if (m_attributes.stencil) {
|
| - m_context->clearStencil(0);
|
| - clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
|
| - m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
|
| - }
|
| -
|
| - clearFramebuffers(clearMask);
|
| -}
|
| -
|
| -void DrawingBuffer::commit(long x, long y, long width, long height)
|
| -{
|
| - if (!m_context)
|
| - return;
|
| -
|
| - if (width < 0)
|
| - width = m_size.width();
|
| - if (height < 0)
|
| - height = m_size.height();
|
| -
|
| - m_context->makeContextCurrent();
|
| -
|
| - if (m_multisampleFBO && !m_contentsChangeCommitted) {
|
| - m_context->bindFramebuffer(Extensions3D::READ_FRAMEBUFFER, m_multisampleFBO);
|
| - m_context->bindFramebuffer(Extensions3D::DRAW_FRAMEBUFFER, m_fbo);
|
| -
|
| - if (m_scissorEnabled)
|
| - m_context->disable(GraphicsContext3D::SCISSOR_TEST);
|
| -
|
| - // Use NEAREST, because there is no scale performed during the blit.
|
| - m_context->extensions()->blitFramebuffer(x, y, width, height, x, y, width, height, GraphicsContext3D::COLOR_BUFFER_BIT, GraphicsContext3D::NEAREST);
|
| -
|
| - if (m_scissorEnabled)
|
| - m_context->enable(GraphicsContext3D::SCISSOR_TEST);
|
| - }
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
|
| - m_contentsChangeCommitted = true;
|
| -}
|
| -
|
| -void DrawingBuffer::restoreFramebufferBinding()
|
| -{
|
| - if (!m_context || !m_framebufferBinding)
|
| - return;
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding);
|
| -}
|
| -
|
| -bool DrawingBuffer::multisample() const
|
| -{
|
| - return m_attributes.antialias && m_multisampleExtensionSupported;
|
| -}
|
| -
|
| -void DrawingBuffer::bind()
|
| -{
|
| - if (!m_context)
|
| - return;
|
| -
|
| - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo);
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|