| Index: Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| diff --git a/Source/platform/graphics/gpu/DrawingBuffer.cpp b/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| index 0086565fcae53f244a5284280b51edff53e6d42d..e0254864410b0dfe8179a2fd76eea549e89f1293 100644
|
| --- a/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| +++ b/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| @@ -42,20 +42,26 @@
|
| #include "public/platform/WebExternalTextureLayer.h"
|
| #include "public/platform/WebGraphicsContext3D.h"
|
| #include "public/platform/WebGraphicsContext3DProvider.h"
|
| +#ifndef NDEBUG
|
| +#include "wtf/RefCountedLeakCounter.h"
|
| +#endif
|
|
|
| using namespace std;
|
|
|
| namespace WebCore {
|
|
|
| +namespace {
|
| // 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;
|
| +const int s_maximumResourceUsePixels = 16 * 1024 * 1024;
|
| +int s_currentResourceUsePixels = 0;
|
| +const float s_resourceAdjustedRatio = 0.5;
|
| +
|
| +const bool s_allowContextEvictionOnCreate = true;
|
| +const int s_maxScaleAttempts = 3;
|
|
|
| -static const bool s_allowContextEvictionOnCreate = true;
|
| -static const int s_maxScaleAttempts = 3;
|
| +DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, drawingBufferCounter, ("DrawingBuffer"));
|
|
|
| class ScopedTextureUnit0BindingRestorer {
|
| public:
|
| @@ -78,6 +84,8 @@ private:
|
| Platform3DObject m_oldTextureUnitZeroId;
|
| };
|
|
|
| +} // namespace
|
| +
|
| PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsContext3D> context, const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager)
|
| {
|
| ASSERT(context);
|
| @@ -97,8 +105,10 @@ PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsCon
|
| extensionsUtil->ensureExtensionEnabled("GL_OES_packed_depth_stencil");
|
|
|
| RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, extensionsUtil.release(), multisampleSupported, packedDepthStencilSupported, preserve, contextEvictionManager));
|
| - if (!drawingBuffer->initialize(size))
|
| + if (!drawingBuffer->initialize(size)) {
|
| + drawingBuffer->beginDestruction();
|
| return PassRefPtr<DrawingBuffer>();
|
| + }
|
| return drawingBuffer.release();
|
| }
|
|
|
| @@ -136,15 +146,25 @@ DrawingBuffer::DrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D> context,
|
| , m_maxTextureSize(0)
|
| , m_sampleCount(0)
|
| , m_packAlignment(4)
|
| + , m_destructionInProgress(false)
|
| , m_contextEvictionManager(contextEvictionManager)
|
| {
|
| // Used by browser tests to detect the use of a DrawingBuffer.
|
| TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation");
|
| +#ifndef NDEBUG
|
| + drawingBufferCounter.increment();
|
| +#endif
|
| }
|
|
|
| DrawingBuffer::~DrawingBuffer()
|
| {
|
| - releaseResources();
|
| + ASSERT(m_destructionInProgress);
|
| + ASSERT(m_textureMailboxes.isEmpty());
|
| + m_layer.clear();
|
| + m_context.clear();
|
| +#ifndef NDEBUG
|
| + drawingBufferCounter.decrement();
|
| +#endif
|
| }
|
|
|
| void DrawingBuffer::markContentsChanged()
|
| @@ -171,6 +191,9 @@ blink::WebGraphicsContext3D* DrawingBuffer::context()
|
|
|
| bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
|
| {
|
| + // prepareMailbox() is always called after layout.
|
| + ASSERT(!m_destructionInProgress);
|
| +
|
| if (!m_contentsChanged)
|
| return false;
|
|
|
| @@ -235,6 +258,9 @@ bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox,
|
| frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint();
|
| markLayerComposited();
|
|
|
| + // set m_parentDrawingBuffer to make sure 'this' stays alive as long as it has live mailboxes
|
| + ASSERT(!frontColorBufferMailbox->m_parentDrawingBuffer);
|
| + frontColorBufferMailbox->m_parentDrawingBuffer = this;
|
| *outMailbox = frontColorBufferMailbox->mailbox;
|
| m_frontColorBuffer = frontColorBufferMailbox->textureId;
|
| return true;
|
| @@ -242,24 +268,47 @@ bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox,
|
|
|
| void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox)
|
| {
|
| + if (m_destructionInProgress) {
|
| + mailboxReleasedWhileDestructionInProgress(mailbox);
|
| + return;
|
| + }
|
| +
|
| 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))) {
|
| + if (nameEquals(mailboxInfo->mailbox, mailbox)) {
|
| mailboxInfo->mailbox.syncPoint = mailbox.syncPoint;
|
| - m_recycledMailboxes.prepend(mailboxInfo.release());
|
| + ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this);
|
| + mailboxInfo->m_parentDrawingBuffer.clear();
|
| + m_recycledMailboxQueue.prepend(mailboxInfo->mailbox);
|
| return;
|
| }
|
| }
|
| ASSERT_NOT_REACHED();
|
| }
|
|
|
| +void DrawingBuffer::mailboxReleasedWhileDestructionInProgress(const blink::WebExternalTextureMailbox& mailbox)
|
| +{
|
| + ASSERT(m_textureMailboxes.size());
|
| + m_context->makeContextCurrent();
|
| + // Ensure not to call the destructor until deleteMailbox() is completed.
|
| + RefPtr<DrawingBuffer> self = this;
|
| + deleteMailbox(mailbox);
|
| +}
|
| +
|
| PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox()
|
| {
|
| - if (m_recycledMailboxes.isEmpty())
|
| + if (m_recycledMailboxQueue.isEmpty())
|
| return PassRefPtr<MailboxInfo>();
|
|
|
| - RefPtr<MailboxInfo> mailboxInfo = m_recycledMailboxes.last().release();
|
| - m_recycledMailboxes.removeLast();
|
| + blink::WebExternalTextureMailbox mailbox = m_recycledMailboxQueue.takeLast();
|
| + RefPtr<MailboxInfo> mailboxInfo;
|
| + for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
|
| + if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) {
|
| + mailboxInfo = m_textureMailboxes[i];
|
| + break;
|
| + }
|
| + }
|
| + ASSERT(mailboxInfo);
|
|
|
| if (mailboxInfo->mailbox.syncPoint) {
|
| m_context->waitSyncPoint(mailboxInfo->mailbox.syncPoint);
|
| @@ -285,6 +334,18 @@ PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::createNewMailbox(unsigned
|
| return returnMailbox.release();
|
| }
|
|
|
| +void DrawingBuffer::deleteMailbox(const blink::WebExternalTextureMailbox& mailbox)
|
| +{
|
| + for (size_t i = 0; i < m_textureMailboxes.size(); i++) {
|
| + if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) {
|
| + m_context->deleteTexture(m_textureMailboxes[i]->textureId);
|
| + m_textureMailboxes.remove(i);
|
| + return;
|
| + }
|
| + }
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| bool DrawingBuffer::initialize(const IntSize& size)
|
| {
|
| if (!m_context->makeContextCurrent()) {
|
| @@ -489,14 +550,17 @@ void DrawingBuffer::clearPlatformLayer()
|
| m_context->flush();
|
| }
|
|
|
| -void DrawingBuffer::releaseResources()
|
| +void DrawingBuffer::beginDestruction()
|
| {
|
| + ASSERT(!m_destructionInProgress);
|
| + m_destructionInProgress = true;
|
| +
|
| m_context->makeContextCurrent();
|
|
|
| clearPlatformLayer();
|
|
|
| - for (size_t i = 0; i < m_textureMailboxes.size(); i++)
|
| - m_context->deleteTexture(m_textureMailboxes[i]->textureId);
|
| + while (!m_recycledMailboxQueue.isEmpty())
|
| + deleteMailbox(m_recycledMailboxQueue.takeLast());
|
|
|
| if (m_multisampleFBO)
|
| m_context->deleteFramebuffer(m_multisampleFBO);
|
| @@ -519,8 +583,6 @@ void DrawingBuffer::releaseResources()
|
| if (m_colorBuffer)
|
| m_context->deleteTexture(m_colorBuffer);
|
|
|
| - m_context.clear();
|
| -
|
| setSize(IntSize());
|
|
|
| m_colorBuffer = 0;
|
| @@ -533,13 +595,8 @@ void DrawingBuffer::releaseResources()
|
| m_fbo = 0;
|
| m_contextEvictionManager.clear();
|
|
|
| - m_recycledMailboxes.clear();
|
| - m_textureMailboxes.clear();
|
| -
|
| - if (m_layer) {
|
| + if (m_layer)
|
| GraphicsLayer::unregisterContentsLayer(m_layer->layer());
|
| - m_layer.clear();
|
| - }
|
| }
|
|
|
| unsigned DrawingBuffer::createColorTexture(const IntSize& size)
|
|
|