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..04359987fca92defc591d68320f6f9cee693f9fc 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,13 @@ private: |
Platform3DObject m_oldTextureUnitZeroId; |
}; |
+inline bool operator==(const blink::WebExternalTextureMailbox& a, const blink::WebExternalTextureMailbox& b) |
Ken Russell (switch to Gerrit)
2014/04/20 00:27:41
This really belongs in public/platform/WebExternal
|
+{ |
+ return !memcmp(a.name, b.name, sizeof(a.name)); |
+} |
+ |
+} // namespace |
+ |
PassRefPtr<DrawingBuffer> DrawingBuffer::create(PassOwnPtr<blink::WebGraphicsContext3D> context, const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr<ContextEvictionManager> contextEvictionManager) |
{ |
ASSERT(context); |
@@ -93,8 +106,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 +145,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() |
@@ -165,6 +190,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 +257,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,24 +267,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 (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 (m_textureMailboxes[i]->mailbox == mailbox) { |
+ mailboxInfo = m_textureMailboxes[i]; |
+ break; |
+ } |
+ } |
+ ASSERT(mailboxInfo); |
if (mailboxInfo->mailbox.syncPoint) { |
m_context->waitSyncPoint(mailboxInfo->mailbox.syncPoint); |
@@ -279,6 +333,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 (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) |
{ |
m_attributes = m_context->getContextAttributes(); |
@@ -473,14 +539,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()); |
dshwang
2014/04/19 00:58:06
now m_recycledMailboxQueue just keeps mailbox name
|
if (m_multisampleFBO) |
m_context->deleteFramebuffer(m_multisampleFBO); |
@@ -503,8 +572,6 @@ void DrawingBuffer::releaseResources() |
if (m_colorBuffer) |
m_context->deleteTexture(m_colorBuffer); |
- m_context.clear(); |
- |
setSize(IntSize()); |
m_colorBuffer = 0; |
@@ -517,13 +584,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) |