| 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..13e0e4aa1f5e7f8414d1b0cc50d4cd950e9b2d67 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);
|
| @@ -93,8 +101,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 +140,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 +185,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 +252,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 +262,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 +328,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 +534,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);
|
| @@ -503,8 +567,6 @@ void DrawingBuffer::releaseResources()
|
| if (m_colorBuffer)
|
| m_context->deleteTexture(m_colorBuffer);
|
|
|
| - m_context.clear();
|
| -
|
| setSize(IntSize());
|
|
|
| m_colorBuffer = 0;
|
| @@ -517,13 +579,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)
|
|
|