Index: Source/platform/graphics/gpu/DrawingBuffer.cpp |
diff --git a/Source/platform/graphics/gpu/DrawingBuffer.cpp b/Source/platform/graphics/gpu/DrawingBuffer.cpp |
index 607a68216facf6a5eb479a95ecc0656f587caf7c..b1528e89266ac121a9bb37cf9b899d97c6374a34 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: |
@@ -77,6 +83,7 @@ private: |
GLenum m_oldActiveTextureUnit; |
Platform3DObject m_oldTextureUnitZeroId; |
}; |
+} // namespace |
PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsContext3D> context, const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager) |
{ |
@@ -93,8 +100,10 @@ PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsCon |
extensionsUtil.ensureExtensionEnabled("GL_OES_packed_depth_stencil"); |
RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, multisampleSupported, packedDepthStencilSupported, preserve, contextEvictionManager)); |
- if (!drawingBuffer->initialize(size)) |
+ if (!drawingBuffer->initialize(size)) { |
+ drawingBuffer->beginDestruction(); |
return PassRefPtr<DrawingBuffer>(); |
+ } |
return drawingBuffer.release(); |
} |
@@ -130,15 +139,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_context.clear(); |
+ m_layer.clear(); |
+#ifndef NDEBUG |
+ drawingBufferCounter.decrement(); |
+#endif |
} |
void DrawingBuffer::markContentsChanged() |
@@ -165,6 +184,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; |
@@ -229,6 +251,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; |
@@ -236,10 +261,17 @@ bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, |
void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox) |
{ |
+ if (m_destructionInProgress) { |
+ mailboxReleasedInDestructionInProgress(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))) { |
mailboxInfo->mailbox.syncPoint = mailbox.syncPoint; |
+ ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); |
+ mailboxInfo->m_parentDrawingBuffer.clear(); |
m_recycledMailboxes.prepend(mailboxInfo.release()); |
return; |
} |
@@ -247,6 +279,23 @@ void DrawingBuffer::mailboxReleased(const blink::WebExternalTextureMailbox& mail |
ASSERT_NOT_REACHED(); |
} |
+void DrawingBuffer::mailboxReleasedInDestructionInProgress(const blink::WebExternalTextureMailbox& mailbox) |
+{ |
+ ASSERT(!m_textureMailboxes.isEmpty()); |
+ for (size_t i = 0; i < m_textureMailboxes.size(); i++) { |
+ RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[i]; |
+ if (!memcmp(mailboxInfo->mailbox.name, mailbox.name, sizeof(mailboxInfo->mailbox.name))) { |
+ m_context->makeContextCurrent(); |
+ m_context->deleteTexture(mailboxInfo->textureId); |
+ m_textureMailboxes.remove(i); |
+ ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); |
+ mailboxInfo->m_parentDrawingBuffer.clear(); |
+ return; |
+ } |
+ } |
+ ASSERT_NOT_REACHED(); |
+} |
+ |
PassRefPtr<DrawingBuffer::MailboxInfo> DrawingBuffer::recycledMailbox() |
{ |
if (m_recycledMailboxes.isEmpty()) |
@@ -473,14 +522,27 @@ 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); |
+ for (size_t i = 0; i < m_recycledMailboxes.size(); i++) { |
+ m_context->deleteTexture(m_recycledMailboxes[i]->textureId); |
+ |
+ for (size_t j = 0; j < m_textureMailboxes.size(); j++) { |
+ RefPtr<MailboxInfo> mailboxInfo = m_textureMailboxes[j]; |
+ if (mailboxInfo->textureId == m_recycledMailboxes[i]->textureId) { |
+ ASSERT(!memcmp(mailboxInfo->mailbox.name, m_recycledMailboxes[i]->mailbox.name, sizeof(mailboxInfo->mailbox.name))); |
+ m_textureMailboxes.remove(j); |
Justin Novosad
2014/04/09 15:34:35
I think this is unnecessary complexity. Wouldn't i
dshwang
2014/04/09 18:05:50
Thank you for review.
As you mentioned, "nested f
Ken Russell (switch to Gerrit)
2014/04/15 02:24:02
I think keeping this code is a good idea only to e
|
+ break; |
+ } |
+ } |
+ } |
if (m_multisampleFBO) |
m_context->deleteFramebuffer(m_multisampleFBO); |
@@ -503,8 +565,6 @@ void DrawingBuffer::releaseResources() |
if (m_colorBuffer) |
m_context->deleteTexture(m_colorBuffer); |
- m_context.clear(); |
- |
setSize(IntSize()); |
m_colorBuffer = 0; |
@@ -518,10 +578,12 @@ void DrawingBuffer::releaseResources() |
m_contextEvictionManager.clear(); |
m_recycledMailboxes.clear(); |
- m_textureMailboxes.clear(); |
- if (m_layer) { |
+ if (m_layer) |
GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
+ |
+ if (m_textureMailboxes.isEmpty()) { |
+ m_context.clear(); |
m_layer.clear(); |
Ken Russell (switch to Gerrit)
2014/04/15 02:24:02
This eager clearing of m_context and m_layer adds
|
} |
} |