| Index: third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| index 3f203e79ab4e1599738b39018414a486acfb5f5c..9ba469948d72a2b9a97fab0cd50a2f9c12282000 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
|
| @@ -60,36 +60,13 @@ namespace {
|
|
|
| const float s_resourceAdjustedRatio = 0.5;
|
|
|
| -class ScopedTextureUnit0BindingRestorer {
|
| - STACK_ALLOCATED();
|
| - WTF_MAKE_NONCOPYABLE(ScopedTextureUnit0BindingRestorer);
|
| -
|
| - public:
|
| - ScopedTextureUnit0BindingRestorer(gpu::gles2::GLES2Interface* gl,
|
| - GLenum activeTextureUnit,
|
| - GLuint textureUnitZeroId)
|
| - : m_gl(gl),
|
| - m_oldActiveTextureUnit(activeTextureUnit),
|
| - m_oldTextureUnitZeroId(textureUnitZeroId) {
|
| - m_gl->ActiveTexture(GL_TEXTURE0);
|
| - }
|
| - ~ScopedTextureUnit0BindingRestorer() {
|
| - m_gl->BindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId);
|
| - m_gl->ActiveTexture(m_oldActiveTextureUnit);
|
| - }
|
| -
|
| - private:
|
| - gpu::gles2::GLES2Interface* m_gl;
|
| - GLenum m_oldActiveTextureUnit;
|
| - GLuint m_oldTextureUnitZeroId;
|
| -};
|
| -
|
| static bool shouldFailDrawingBufferCreationForTesting = false;
|
|
|
| } // namespace
|
|
|
| PassRefPtr<DrawingBuffer> DrawingBuffer::create(
|
| std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
|
| + DrawingBufferStateTracker* drawingBufferRestoreSource,
|
| const IntSize& size,
|
| bool premultipliedAlpha,
|
| bool wantAlphaChannel,
|
| @@ -137,9 +114,9 @@ PassRefPtr<DrawingBuffer> DrawingBuffer::create(
|
|
|
| RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(
|
| std::move(contextProvider), std::move(extensionsUtil),
|
| - discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha,
|
| - preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer,
|
| - chromiumImageUsage));
|
| + drawingBufferRestoreSource, discardFramebufferSupported, wantAlphaChannel,
|
| + premultipliedAlpha, preserve, webGLVersion, wantDepthBuffer,
|
| + wantStencilBuffer, chromiumImageUsage));
|
| if (!drawingBuffer->initialize(size, multisampleSupported)) {
|
| drawingBuffer->beginDestruction();
|
| return PassRefPtr<DrawingBuffer>();
|
| @@ -154,6 +131,7 @@ void DrawingBuffer::forceNextDrawingBufferCreationToFail() {
|
| DrawingBuffer::DrawingBuffer(
|
| std::unique_ptr<WebGraphicsContext3DProvider> contextProvider,
|
| std::unique_ptr<Extensions3DUtil> extensionsUtil,
|
| + DrawingBufferStateTracker* stateTracker,
|
| bool discardFramebufferSupported,
|
| bool wantAlphaChannel,
|
| bool premultipliedAlpha,
|
| @@ -162,7 +140,8 @@ DrawingBuffer::DrawingBuffer(
|
| bool wantDepth,
|
| bool wantStencil,
|
| ChromiumImageUsage chromiumImageUsage)
|
| - : m_preserveDrawingBuffer(preserve),
|
| + : m_stateTracker(stateTracker),
|
| + m_preserveDrawingBuffer(preserve),
|
| m_webGLVersion(webGLVersion),
|
| m_contextProvider(std::move(contextProvider)),
|
| m_gl(m_contextProvider->contextGL()),
|
| @@ -174,8 +153,6 @@ DrawingBuffer::DrawingBuffer(
|
| m_wantDepth(wantDepth),
|
| m_wantStencil(wantStencil),
|
| m_chromiumImageUsage(chromiumImageUsage) {
|
| - memset(m_colorMask, 0, 4 * sizeof(GLboolean));
|
| - memset(m_clearColor, 0, 4 * sizeof(GLfloat));
|
| // Used by browser tests to detect the use of a DrawingBuffer.
|
| TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation",
|
| TRACE_EVENT_SCOPE_GLOBAL);
|
| @@ -217,7 +194,7 @@ void DrawingBuffer::setIsHidden(bool hidden) {
|
| return;
|
| m_isHidden = hidden;
|
| if (m_isHidden)
|
| - m_recycledMailboxQueue.clear();
|
| + m_recycledColorBufferQueue.clear();
|
| }
|
|
|
| void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) {
|
| @@ -229,7 +206,9 @@ void DrawingBuffer::setFilterQuality(SkFilterQuality filterQuality) {
|
| }
|
|
|
| bool DrawingBuffer::requiresAlphaChannelToBePreserved() {
|
| - return !m_drawFramebufferBinding &&
|
| + DrawingBufferRestoreState restoreState;
|
| + m_stateTracker->GetDrawingBufferRestoreState(&restoreState);
|
| + return !restoreState.drawFramebufferBinding &&
|
| defaultBufferRequiresAlphaChannelToBePreserved();
|
| }
|
|
|
| @@ -265,6 +244,7 @@ std::unique_ptr<cc::SharedBitmap> DrawingBuffer::createOrRecycleBitmap() {
|
| bool DrawingBuffer::PrepareTextureMailbox(
|
| cc::TextureMailbox* outMailbox,
|
| std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| bool forceGpuResult = false;
|
| return prepareTextureMailboxInternal(outMailbox, outReleaseCallback,
|
| forceGpuResult);
|
| @@ -299,107 +279,124 @@ bool DrawingBuffer::prepareTextureMailboxInternal(
|
|
|
| // Resolve the multisampled buffer into m_backColorBuffer texture.
|
| if (m_antiAliasingMode != None)
|
| - commit();
|
| + resolveMultisampleFramebufferInternal();
|
|
|
| if (m_softwareRendering && !forceGpuResult) {
|
| - std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap();
|
| - if (!bitmap)
|
| - return false;
|
| + return finishPrepareTextureMailboxSoftware(outMailbox, outReleaseCallback);
|
| + } else {
|
| + return finishPrepareTextureMailboxGpu(outMailbox, outReleaseCallback);
|
| + }
|
| +}
|
| +
|
| +bool DrawingBuffer::finishPrepareTextureMailboxSoftware(
|
| + cc::TextureMailbox* outMailbox,
|
| + std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
|
| + std::unique_ptr<cc::SharedBitmap> bitmap = createOrRecycleBitmap();
|
| + if (!bitmap)
|
| + return false;
|
| +
|
| + // Read the framebuffer into |bitmap|.
|
| + {
|
| unsigned char* pixels = bitmap->pixels();
|
| DCHECK(pixels);
|
| -
|
| bool needPremultiply = m_wantAlphaChannel && !m_premultipliedAlpha;
|
| WebGLImageConversion::AlphaOp op =
|
| needPremultiply ? WebGLImageConversion::AlphaDoPremultiply
|
| : WebGLImageConversion::AlphaDoNothing;
|
| readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia,
|
| op);
|
| + }
|
|
|
| - *outMailbox = cc::TextureMailbox(bitmap.get(), m_size);
|
| + *outMailbox = cc::TextureMailbox(bitmap.get(), m_size);
|
|
|
| - // This holds a ref on the DrawingBuffer that will keep it alive until the
|
| - // mailbox is released (and while the release callback is running). It also
|
| - // owns the SharedBitmap.
|
| - auto func = WTF::bind(&DrawingBuffer::softwareMailboxReleased,
|
| - RefPtr<DrawingBuffer>(this),
|
| - WTF::passed(std::move(bitmap)), m_size);
|
| - *outReleaseCallback = cc::SingleReleaseCallback::Create(
|
| - convertToBaseCallback(std::move(func)));
|
| - return true;
|
| - }
|
| + // This holds a ref on the DrawingBuffer that will keep it alive until the
|
| + // mailbox is released (and while the release callback is running). It also
|
| + // owns the SharedBitmap.
|
| + auto func = WTF::bind(&DrawingBuffer::mailboxReleasedSoftware,
|
| + RefPtr<DrawingBuffer>(this),
|
| + WTF::passed(std::move(bitmap)), m_size);
|
| + *outReleaseCallback =
|
| + cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
|
| + return true;
|
| +}
|
|
|
| +bool DrawingBuffer::finishPrepareTextureMailboxGpu(
|
| + cc::TextureMailbox* outMailbox,
|
| + std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) {
|
| if (m_webGLVersion > WebGL1) {
|
| + m_stateRestorer->setPixelUnpackBufferBindingDirty();
|
| m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
| }
|
|
|
| - // We must restore the texture binding since creating new textures,
|
| - // consuming and producing mailboxes changes it.
|
| - ScopedTextureUnit0BindingRestorer restorer(m_gl, m_activeTextureUnit,
|
| - m_texture2DBinding);
|
| -
|
| - // First try to recycle an old buffer.
|
| - RefPtr<ColorBuffer> colorBufferForMailbox = takeRecycledMailbox();
|
| -
|
| - // No buffer available to recycle, create a new one.
|
| - if (!colorBufferForMailbox)
|
| - colorBufferForMailbox = createTextureAndAllocateMemory(m_size);
|
| -
|
| + // Specify the buffer that we will put in the mailbox.
|
| + RefPtr<ColorBuffer> colorBufferForMailbox;
|
| if (m_preserveDrawingBuffer == Discard) {
|
| - std::swap(colorBufferForMailbox, m_backColorBuffer);
|
| + // If we can discard the backbuffer, send the old backbuffer directly
|
| + // into the mailbox, and allocate (or recycle) a new backbuffer.
|
| + colorBufferForMailbox = m_backColorBuffer;
|
| + m_backColorBuffer = createOrRecycleColorBuffer();
|
| attachColorBufferToReadFramebuffer();
|
|
|
| + // Explicitly specify that m_fbo (which is now bound to the just-allocated
|
| + // m_backColorBuffer) is not initialized, to save GPU memory bandwidth for
|
| + // tile-based GPU architectures.
|
| if (m_discardFramebufferSupported) {
|
| - // Explicitly discard the framebuffer to save GPU memory bandwidth for
|
| - // tile-based GPU arch.
|
| const GLenum attachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
|
| GL_STENCIL_ATTACHMENT};
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
|
| }
|
| } else {
|
| + // If we can't discard the backbuffer, create (or recycle) a buffer to put
|
| + // in the mailbox, and copy backbuffer's contents there.
|
| + colorBufferForMailbox = createOrRecycleColorBuffer();
|
| m_gl->CopySubTextureCHROMIUM(
|
| m_backColorBuffer->textureId, colorBufferForMailbox->textureId, 0, 0, 0,
|
| 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE);
|
| }
|
|
|
| - restoreFramebufferBindings();
|
| - restorePixelUnpackBufferBindings();
|
| - m_contentsChanged = false;
|
| -
|
| - m_gl->ProduceTextureDirectCHROMIUM(colorBufferForMailbox->textureId,
|
| - colorBufferForMailbox->parameters.target,
|
| - colorBufferForMailbox->mailbox.name);
|
| - const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM();
|
| + // Put colorBufferForMailbox into its mailbox, and populate its
|
| + // produceSyncToken with that point.
|
| + {
|
| + m_gl->ProduceTextureDirectCHROMIUM(colorBufferForMailbox->textureId,
|
| + colorBufferForMailbox->parameters.target,
|
| + colorBufferForMailbox->mailbox.name);
|
| + const GLuint64 fenceSync = m_gl->InsertFenceSyncCHROMIUM();
|
| #if OS(MACOSX)
|
| - m_gl->DescheduleUntilFinishedCHROMIUM();
|
| + m_gl->DescheduleUntilFinishedCHROMIUM();
|
| #endif
|
| - m_gl->Flush();
|
| - gpu::SyncToken syncToken;
|
| - m_gl->GenSyncTokenCHROMIUM(fenceSync, syncToken.GetData());
|
| + m_gl->Flush();
|
| + m_gl->GenSyncTokenCHROMIUM(
|
| + fenceSync, colorBufferForMailbox->produceSyncToken.GetData());
|
| + }
|
|
|
| - bool isOverlayCandidate = colorBufferForMailbox->imageId != 0;
|
| - bool secureOutputOnly = false;
|
| - *outMailbox = cc::TextureMailbox(colorBufferForMailbox->mailbox, syncToken,
|
| - colorBufferForMailbox->parameters.target,
|
| - gfx::Size(m_size.width(), m_size.height()),
|
| - isOverlayCandidate, secureOutputOnly);
|
| + // Populate the output mailbox and callback.
|
| + {
|
| + bool isOverlayCandidate = colorBufferForMailbox->imageId != 0;
|
| + bool secureOutputOnly = false;
|
| + *outMailbox = cc::TextureMailbox(
|
| + colorBufferForMailbox->mailbox, colorBufferForMailbox->produceSyncToken,
|
| + colorBufferForMailbox->parameters.target, gfx::Size(m_size),
|
| + isOverlayCandidate, secureOutputOnly);
|
|
|
| - // This holds a ref on the DrawingBuffer that will keep it alive until the
|
| - // mailbox is released (and while the release callback is running).
|
| - auto func = WTF::bind(&DrawingBuffer::gpuMailboxReleased,
|
| - RefPtr<DrawingBuffer>(this), colorBufferForMailbox);
|
| - *outReleaseCallback =
|
| - cc::SingleReleaseCallback::Create(convertToBaseCallback(std::move(func)));
|
| + // This holds a ref on the DrawingBuffer that will keep it alive until the
|
| + // mailbox is released (and while the release callback is running).
|
| + auto func = WTF::bind(&DrawingBuffer::mailboxReleasedGpu,
|
| + RefPtr<DrawingBuffer>(this), colorBufferForMailbox);
|
| + *outReleaseCallback = cc::SingleReleaseCallback::Create(
|
| + convertToBaseCallback(std::move(func)));
|
| + }
|
|
|
| - // Point |m_frontColorBuffer| to the buffer that we are presenting, and
|
| - // update its sync token.
|
| - colorBufferForMailbox->produceSyncToken = syncToken;
|
| + // Point |m_frontColorBuffer| to the buffer that we are now presenting.
|
| m_frontColorBuffer = colorBufferForMailbox;
|
| +
|
| + m_contentsChanged = false;
|
| setBufferClearNeeded(true);
|
| return true;
|
| }
|
|
|
| -void DrawingBuffer::gpuMailboxReleased(RefPtr<ColorBuffer> colorBuffer,
|
| +void DrawingBuffer::mailboxReleasedGpu(RefPtr<ColorBuffer> colorBuffer,
|
| const gpu::SyncToken& syncToken,
|
| bool lostResource) {
|
| // If the mailbox has been returned by the compositor then it is no
|
| @@ -422,13 +419,13 @@ void DrawingBuffer::gpuMailboxReleased(RefPtr<ColorBuffer> colorBuffer,
|
| size_t cacheLimit = 1;
|
| if (shouldUseChromiumImage())
|
| cacheLimit = 4;
|
| - while (m_recycledMailboxQueue.size() >= cacheLimit)
|
| - m_recycledMailboxQueue.takeLast();
|
| + while (m_recycledColorBufferQueue.size() >= cacheLimit)
|
| + m_recycledColorBufferQueue.takeLast();
|
|
|
| - m_recycledMailboxQueue.prepend(colorBuffer);
|
| + m_recycledColorBufferQueue.prepend(colorBuffer);
|
| }
|
|
|
| -void DrawingBuffer::softwareMailboxReleased(
|
| +void DrawingBuffer::mailboxReleasedSoftware(
|
| std::unique_ptr<cc::SharedBitmap> bitmap,
|
| const IntSize& size,
|
| const gpu::SyncToken& syncToken,
|
| @@ -442,6 +439,8 @@ void DrawingBuffer::softwareMailboxReleased(
|
| }
|
|
|
| PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| +
|
| // This can be null if the context is lost before the first call to
|
| // grContext().
|
| GrContext* grContext = m_contextProvider->grContext();
|
| @@ -514,12 +513,12 @@ PassRefPtr<StaticBitmapImage> DrawingBuffer::transferToStaticBitmapImage() {
|
| std::move(skImage), skImageMailbox, skImageSyncToken);
|
| }
|
|
|
| -DrawingBuffer::TextureParameters
|
| -DrawingBuffer::chromiumImageTextureParameters() {
|
| +DrawingBuffer::ColorBufferParameters
|
| +DrawingBuffer::gpuMemoryBufferColorBufferParameters() {
|
| #if OS(MACOSX)
|
| // A CHROMIUM_image backed texture requires a specialized set of parameters
|
| // on OSX.
|
| - TextureParameters parameters;
|
| + ColorBufferParameters parameters;
|
| parameters.target = GC3D_TEXTURE_RECTANGLE_ARB;
|
|
|
| if (m_wantAlphaChannel) {
|
| @@ -541,12 +540,13 @@ DrawingBuffer::chromiumImageTextureParameters() {
|
| parameters.colorFormat = 0;
|
| return parameters;
|
| #else
|
| - return defaultTextureParameters();
|
| + return textureColorBufferParameters();
|
| #endif
|
| }
|
|
|
| -DrawingBuffer::TextureParameters DrawingBuffer::defaultTextureParameters() {
|
| - TextureParameters parameters;
|
| +DrawingBuffer::ColorBufferParameters
|
| +DrawingBuffer::textureColorBufferParameters() {
|
| + ColorBufferParameters parameters;
|
| parameters.target = GL_TEXTURE_2D;
|
| if (m_wantAlphaChannel) {
|
| parameters.internalColorFormat = GL_RGBA;
|
| @@ -568,37 +568,65 @@ DrawingBuffer::TextureParameters DrawingBuffer::defaultTextureParameters() {
|
| return parameters;
|
| }
|
|
|
| -PassRefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::takeRecycledMailbox() {
|
| - if (m_recycledMailboxQueue.isEmpty())
|
| - return nullptr;
|
| -
|
| - RefPtr<ColorBuffer> recycled = m_recycledMailboxQueue.takeLast();
|
| - DCHECK(recycled->size == m_size);
|
| - if (recycled->receiveSyncToken.HasData())
|
| - m_gl->WaitSyncTokenCHROMIUM(recycled->receiveSyncToken.GetData());
|
| - return recycled;
|
| +PassRefPtr<DrawingBuffer::ColorBuffer>
|
| +DrawingBuffer::createOrRecycleColorBuffer() {
|
| + if (!m_recycledColorBufferQueue.isEmpty()) {
|
| + RefPtr<ColorBuffer> recycled = m_recycledColorBufferQueue.takeLast();
|
| + if (recycled->receiveSyncToken.HasData())
|
| + m_gl->WaitSyncTokenCHROMIUM(recycled->receiveSyncToken.GetData());
|
| + DCHECK(recycled->size == m_size);
|
| + return recycled;
|
| + }
|
| + return createColorBuffer(m_size);
|
| }
|
|
|
| DrawingBuffer::ColorBuffer::ColorBuffer(DrawingBuffer* drawingBuffer,
|
| - const TextureParameters& parameters,
|
| - const IntSize& size)
|
| - : drawingBuffer(drawingBuffer), parameters(parameters), size(size) {
|
| + const ColorBufferParameters& parameters,
|
| + const IntSize& size,
|
| + GLuint textureId,
|
| + GLuint imageId)
|
| + : drawingBuffer(drawingBuffer),
|
| + parameters(parameters),
|
| + size(size),
|
| + textureId(textureId),
|
| + imageId(imageId) {
|
| drawingBuffer->contextGL()->GenMailboxCHROMIUM(mailbox.name);
|
| }
|
|
|
| DrawingBuffer::ColorBuffer::~ColorBuffer() {
|
| - gpu::gles2::GLES2Interface* gl = drawingBuffer->contextGL();
|
| + gpu::gles2::GLES2Interface* gl = drawingBuffer->m_gl;
|
| if (receiveSyncToken.HasData())
|
| gl->WaitSyncTokenCHROMIUM(receiveSyncToken.GetConstData());
|
| if (imageId) {
|
| gl->BindTexture(parameters.target, textureId);
|
| gl->ReleaseTexImage2DCHROMIUM(parameters.target, imageId);
|
| gl->DestroyImageCHROMIUM(imageId);
|
| + switch (parameters.target) {
|
| + case GL_TEXTURE_2D:
|
| + // Restore the texture binding for GL_TEXTURE_2D, since the client will
|
| + // expect the previous state.
|
| + if (drawingBuffer->m_stateTracker) {
|
| + DrawingBufferRestoreState restoreState;
|
| + drawingBuffer->m_stateTracker->GetDrawingBufferRestoreState(
|
| + &restoreState);
|
| + gl->BindTexture(GL_TEXTURE_2D, restoreState.activeTexture2DBinding);
|
| + }
|
| + break;
|
| + case GC3D_TEXTURE_RECTANGLE_ARB:
|
| + // Rectangle textures aren't exposed to WebGL, so don't bother
|
| + // restoring this state (there is no meaningful way to restore it).
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| }
|
| gl->DeleteTextures(1, &textureId);
|
| }
|
|
|
| bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| +
|
| if (m_gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
|
| // Need to try to restore the context again later.
|
| return false;
|
| @@ -630,6 +658,7 @@ bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
|
| m_antiAliasingMode == ScreenSpaceAntialiasing;
|
| m_sampleCount = std::min(4, maxSampleCount);
|
|
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| m_gl->GenFramebuffers(1, &m_fbo);
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| if (wantExplicitResolve()) {
|
| @@ -637,7 +666,7 @@ bool DrawingBuffer::initialize(const IntSize& size, bool useMultisampling) {
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
|
| m_gl->GenRenderbuffers(1, &m_multisampleRenderbuffer);
|
| }
|
| - if (!reset(size))
|
| + if (!resizeFramebufferInternal(size))
|
| return false;
|
|
|
| if (m_depthStencilBuffer) {
|
| @@ -662,11 +691,11 @@ bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
|
| bool premultiplyAlpha,
|
| bool flipY,
|
| SourceDrawingBuffer sourceBuffer) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| +
|
| if (m_contentsChanged) {
|
| - if (m_antiAliasingMode != None) {
|
| - commit();
|
| - restoreFramebufferBindings();
|
| - }
|
| + if (m_antiAliasingMode != None)
|
| + resolveMultisampleFramebufferInternal();
|
| m_gl->Flush();
|
| }
|
|
|
| @@ -722,10 +751,6 @@ bool DrawingBuffer::copyToPlatformTexture(gpu::gles2::GLES2Interface* gl,
|
| return true;
|
| }
|
|
|
| -GLuint DrawingBuffer::framebuffer() const {
|
| - return m_fbo;
|
| -}
|
| -
|
| WebLayer* DrawingBuffer::platformLayer() {
|
| if (!m_layer) {
|
| m_layer = wrapUnique(
|
| @@ -754,7 +779,7 @@ void DrawingBuffer::beginDestruction() {
|
| m_destructionInProgress = true;
|
|
|
| clearPlatformLayer();
|
| - m_recycledMailboxQueue.clear();
|
| + m_recycledColorBufferQueue.clear();
|
|
|
| if (m_multisampleFBO)
|
| m_gl->DeleteFramebuffers(1, &m_multisampleFBO);
|
| @@ -779,26 +804,19 @@ void DrawingBuffer::beginDestruction() {
|
|
|
| if (m_layer)
|
| GraphicsLayer::unregisterContentsLayer(m_layer->layer());
|
| -}
|
|
|
| -GLuint DrawingBuffer::createColorTexture(const TextureParameters& parameters) {
|
| - GLuint offscreenColorTexture;
|
| - m_gl->GenTextures(1, &offscreenColorTexture);
|
| - m_gl->BindTexture(parameters.target, offscreenColorTexture);
|
| - m_gl->TexParameteri(parameters.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
| - m_gl->TexParameteri(parameters.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
| - m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| - m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| - return offscreenColorTexture;
|
| + m_stateTracker = nullptr;
|
| }
|
|
|
| bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
|
| // Recreate m_backColorBuffer.
|
| - m_backColorBuffer = createTextureAndAllocateMemory(size);
|
| + m_backColorBuffer = createColorBuffer(size);
|
|
|
| attachColorBufferToReadFramebuffer();
|
|
|
| if (wantExplicitResolve()) {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| + m_stateRestorer->setRenderbufferBindingDirty();
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
|
| m_gl->BindRenderbuffer(GL_RENDERBUFFER, m_multisampleRenderbuffer);
|
| m_gl->RenderbufferStorageMultisampleCHROMIUM(
|
| @@ -813,6 +831,8 @@ bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
|
| }
|
|
|
| if (wantDepthOrStencil()) {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| + m_stateRestorer->setRenderbufferBindingDirty();
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER,
|
| m_multisampleFBO ? m_multisampleFBO : m_fbo);
|
| if (!m_depthStencilBuffer)
|
| @@ -839,17 +859,25 @@ bool DrawingBuffer::resizeDefaultFramebuffer(const IntSize& size) {
|
| }
|
|
|
| if (wantExplicitResolve()) {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
|
| if (m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
| return false;
|
| }
|
|
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| return m_gl->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
|
| GL_FRAMEBUFFER_COMPLETE;
|
| }
|
|
|
| void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| + clearFramebuffersInternal(clearMask);
|
| +}
|
| +
|
| +void DrawingBuffer::clearFramebuffersInternal(GLbitfield clearMask) {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| // We will clear the multisample FBO, but we also need to clear the
|
| // non-multisampled buffer.
|
| if (m_multisampleFBO) {
|
| @@ -878,7 +906,12 @@ IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize,
|
| return adjustedSize;
|
| }
|
|
|
| -bool DrawingBuffer::reset(const IntSize& newSize) {
|
| +bool DrawingBuffer::resize(const IntSize& newSize) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| + return resizeFramebufferInternal(newSize);
|
| +}
|
| +
|
| +bool DrawingBuffer::resizeFramebufferInternal(const IntSize& newSize) {
|
| CHECK(!newSize.isEmpty());
|
| IntSize adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize);
|
| if (adjustedSize.isEmpty())
|
| @@ -896,13 +929,14 @@ bool DrawingBuffer::reset(const IntSize& newSize) {
|
| m_size = adjustedSize;
|
| // Free all mailboxes, because they are now of the wrong size. Only the
|
| // first call in this loop has any effect.
|
| - m_recycledMailboxQueue.clear();
|
| + m_recycledColorBufferQueue.clear();
|
| m_recycledBitmaps.clear();
|
|
|
| if (adjustedSize.isEmpty())
|
| return false;
|
| }
|
|
|
| + m_stateRestorer->setClearStateDirty();
|
| m_gl->Disable(GL_SCISSOR_TEST);
|
| m_gl->ClearColor(0, 0, 0,
|
| defaultBufferRequiresAlphaChannelToBePreserved() ? 1 : 0);
|
| @@ -920,17 +954,25 @@ bool DrawingBuffer::reset(const IntSize& newSize) {
|
| m_gl->StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
|
| }
|
|
|
| - clearFramebuffers(clearMask);
|
| + clearFramebuffersInternal(clearMask);
|
| return true;
|
| }
|
|
|
| -void DrawingBuffer::commit() {
|
| +void DrawingBuffer::resolveAndBindForReadAndDraw() {
|
| + {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| + resolveMultisampleFramebufferInternal();
|
| + }
|
| + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| +}
|
| +
|
| +void DrawingBuffer::resolveMultisampleFramebufferInternal() {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| if (wantExplicitResolve() && !m_contentsChangeCommitted) {
|
| + m_stateRestorer->setClearStateDirty();
|
| m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
|
| m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
|
| -
|
| - if (m_scissorEnabled)
|
| - m_gl->Disable(GL_SCISSOR_TEST);
|
| + m_gl->Disable(GL_SCISSOR_TEST);
|
|
|
| int width = m_size.width();
|
| int height = m_size.height();
|
| @@ -949,52 +991,18 @@ void DrawingBuffer::commit() {
|
| .disable_multisampling_color_mask_usage) {
|
| m_gl->ClearColor(0, 0, 0, 1);
|
| m_gl->ColorMask(false, false, false, true);
|
| - m_gl->Clear(GL_COLOR_BUFFER_BIT);
|
| -
|
| - m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
|
| - m_clearColor[3]);
|
| - m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
|
| - m_colorMask[3]);
|
| }
|
| -
|
| - if (m_scissorEnabled)
|
| - m_gl->Enable(GL_SCISSOR_TEST);
|
| }
|
|
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| - if (m_antiAliasingMode == ScreenSpaceAntialiasing) {
|
| + if (m_antiAliasingMode == ScreenSpaceAntialiasing)
|
| m_gl->ApplyScreenSpaceAntialiasingCHROMIUM();
|
| - }
|
| m_contentsChangeCommitted = true;
|
| }
|
|
|
| -void DrawingBuffer::restorePixelUnpackBufferBindings() {
|
| - if (m_webGLVersion > WebGL1) {
|
| - m_gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pixelUnpackBufferBinding);
|
| - }
|
| -}
|
| -
|
| void DrawingBuffer::restoreFramebufferBindings() {
|
| - if (m_drawFramebufferBinding && m_readFramebufferBinding) {
|
| - if (m_drawFramebufferBinding == m_readFramebufferBinding) {
|
| - m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_readFramebufferBinding);
|
| - } else {
|
| - m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
|
| - m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
|
| - }
|
| - return;
|
| - }
|
| - if (!m_drawFramebufferBinding && !m_readFramebufferBinding) {
|
| - bind(GL_FRAMEBUFFER);
|
| - return;
|
| - }
|
| - if (!m_drawFramebufferBinding) {
|
| - bind(GL_DRAW_FRAMEBUFFER);
|
| - m_gl->BindFramebuffer(GL_READ_FRAMEBUFFER, m_readFramebufferBinding);
|
| - } else {
|
| - bind(GL_READ_FRAMEBUFFER);
|
| - m_gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFramebufferBinding);
|
| - }
|
| + DrawingBufferRestoreState restoreState;
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| }
|
|
|
| bool DrawingBuffer::multisample() const {
|
| @@ -1006,15 +1014,13 @@ void DrawingBuffer::bind(GLenum target) {
|
| wantExplicitResolve() ? m_multisampleFBO : m_fbo);
|
| }
|
|
|
| -void DrawingBuffer::setPackAlignment(GLint param) {
|
| - m_packAlignment = param;
|
| -}
|
| -
|
| bool DrawingBuffer::paintRenderingResultsToImageData(
|
| int& width,
|
| int& height,
|
| SourceDrawingBuffer sourceBuffer,
|
| WTF::ArrayBufferContents& contents) {
|
| + ScopedStateRestorer scopedStateRestorer(this);
|
| +
|
| ASSERT(!m_premultipliedAlpha);
|
| width = size().width();
|
| height = size().height();
|
| @@ -1030,6 +1036,7 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
|
| WTF::ArrayBufferContents::DontInitialize);
|
|
|
| GLuint fbo = 0;
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| if (sourceBuffer == FrontBuffer && m_frontColorBuffer) {
|
| m_gl->GenFramebuffers(1, &fbo);
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
| @@ -1037,7 +1044,7 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
|
| m_frontColorBuffer->parameters.target,
|
| m_frontColorBuffer->textureId, 0);
|
| } else {
|
| - m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer());
|
| + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
| }
|
|
|
| readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height,
|
| @@ -1050,8 +1057,6 @@ bool DrawingBuffer::paintRenderingResultsToImageData(
|
| m_gl->DeleteFramebuffers(1, &fbo);
|
| }
|
|
|
| - restoreFramebufferBindings();
|
| -
|
| pixels.transfer(contents);
|
| return true;
|
| }
|
| @@ -1061,11 +1066,9 @@ void DrawingBuffer::readBackFramebuffer(unsigned char* pixels,
|
| int height,
|
| ReadbackOrder readbackOrder,
|
| WebGLImageConversion::AlphaOp op) {
|
| - if (m_packAlignment > 4)
|
| - m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
|
| + m_stateRestorer->setPixelPackAlignmentDirty();
|
| + m_gl->PixelStorei(GL_PACK_ALIGNMENT, 1);
|
| m_gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
| - if (m_packAlignment > 4)
|
| - m_gl->PixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
|
|
|
| size_t bufferSize = 4 * width * height;
|
|
|
| @@ -1093,100 +1096,96 @@ void DrawingBuffer::readBackFramebuffer(unsigned char* pixels,
|
| void DrawingBuffer::flipVertically(uint8_t* framebuffer,
|
| int width,
|
| int height) {
|
| - m_scanline.resize(width * 4);
|
| - uint8_t* scanline = &m_scanline[0];
|
| + std::vector<uint8_t> scanline(width * 4);
|
| unsigned rowBytes = width * 4;
|
| unsigned count = height / 2;
|
| for (unsigned i = 0; i < count; i++) {
|
| uint8_t* rowA = framebuffer + i * rowBytes;
|
| uint8_t* rowB = framebuffer + (height - i - 1) * rowBytes;
|
| - memcpy(scanline, rowB, rowBytes);
|
| + memcpy(scanline.data(), rowB, rowBytes);
|
| memcpy(rowB, rowA, rowBytes);
|
| - memcpy(rowA, scanline, rowBytes);
|
| + memcpy(rowA, scanline.data(), rowBytes);
|
| }
|
| }
|
|
|
| -void DrawingBuffer::allocateConditionallyImmutableTexture(GLenum target,
|
| - GLenum internalformat,
|
| - GLsizei width,
|
| - GLsizei height,
|
| - GLint border,
|
| - GLenum format,
|
| - GLenum type) {
|
| - if (m_storageTextureSupported) {
|
| - GLenum internalStorageFormat = GL_NONE;
|
| - if (internalformat == GL_RGB) {
|
| - internalStorageFormat = GL_RGB8;
|
| - } else if (internalformat == GL_RGBA) {
|
| - internalStorageFormat = GL_RGBA8;
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| - m_gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, internalStorageFormat, width,
|
| - height);
|
| - return;
|
| +RefPtr<DrawingBuffer::ColorBuffer> DrawingBuffer::createColorBuffer(
|
| + const IntSize& size) {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| + m_stateRestorer->setTextureBindingDirty();
|
| +
|
| + // Select the Parameters for the texture object. Allocate the backing
|
| + // GpuMemoryBuffer and GLImage, if one is going to be used.
|
| + ColorBufferParameters parameters;
|
| + GLuint imageId = 0;
|
| + if (shouldUseChromiumImage()) {
|
| + parameters = gpuMemoryBufferColorBufferParameters();
|
| + imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(
|
| + size.width(), size.height(), parameters.creationInternalColorFormat,
|
| + GC3D_SCANOUT_CHROMIUM);
|
| + } else {
|
| + parameters = textureColorBufferParameters();
|
| }
|
| - m_gl->TexImage2D(target, 0, internalformat, width, height, border, format,
|
| - type, 0);
|
| -}
|
| -
|
| -void DrawingBuffer::clearChromiumImageAlpha(const ColorBuffer& info) {
|
| - if (m_wantAlphaChannel)
|
| - return;
|
| - if (!contextProvider()->getCapabilities().chromium_image_rgb_emulation)
|
| - return;
|
| -
|
| - GLuint fbo = 0;
|
| - m_gl->GenFramebuffers(1, &fbo);
|
| - m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
| - m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| - info.parameters.target, info.textureId, 0);
|
| - m_gl->ClearColor(0, 0, 0, 1);
|
| - m_gl->ColorMask(false, false, false, true);
|
| - m_gl->Clear(GL_COLOR_BUFFER_BIT);
|
| - m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| - info.parameters.target, 0, 0);
|
| - m_gl->DeleteFramebuffers(1, &fbo);
|
| - restoreFramebufferBindings();
|
| - m_gl->ClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2],
|
| - m_clearColor[3]);
|
| - m_gl->ColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2],
|
| - m_colorMask[3]);
|
| -}
|
|
|
| -RefPtr<DrawingBuffer::ColorBuffer>
|
| -DrawingBuffer::createTextureAndAllocateMemory(const IntSize& size) {
|
| - if (!shouldUseChromiumImage())
|
| - return createDefaultTextureAndAllocateMemory(size);
|
| + // Allocate the texture for this object.
|
| + GLuint textureId = 0;
|
| + {
|
| + m_gl->GenTextures(1, &textureId);
|
| + m_gl->BindTexture(parameters.target, textureId);
|
| + m_gl->TexParameteri(parameters.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
| + m_gl->TexParameteri(parameters.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
| + m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| + m_gl->TexParameteri(parameters.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| + }
|
|
|
| - TextureParameters parameters = chromiumImageTextureParameters();
|
| - GLuint imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(
|
| - size.width(), size.height(), parameters.creationInternalColorFormat,
|
| - GC3D_SCANOUT_CHROMIUM);
|
| - GLuint textureId = createColorTexture(parameters);
|
| + // If this is GpuMemoryBuffer-backed, then bind the texture to the
|
| + // GpuMemoryBuffer's GLImage. Otherwise, allocate ordinary texture storage.
|
| if (imageId) {
|
| m_gl->BindTexImage2DCHROMIUM(parameters.target, imageId);
|
| + } else {
|
| + if (m_storageTextureSupported) {
|
| + GLenum internalStorageFormat = GL_NONE;
|
| + if (parameters.creationInternalColorFormat == GL_RGB) {
|
| + internalStorageFormat = GL_RGB8;
|
| + } else if (parameters.creationInternalColorFormat == GL_RGBA) {
|
| + internalStorageFormat = GL_RGBA8;
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + m_gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, internalStorageFormat,
|
| + size.width(), size.height());
|
| + } else {
|
| + m_gl->TexImage2D(parameters.target, 0,
|
| + parameters.creationInternalColorFormat, size.width(),
|
| + size.height(), 0, parameters.colorFormat,
|
| + GL_UNSIGNED_BYTE, 0);
|
| + }
|
| }
|
|
|
| - RefPtr<ColorBuffer> info(adoptRef(new ColorBuffer(this, parameters, size)));
|
| - info->textureId = textureId;
|
| - info->imageId = imageId;
|
| - clearChromiumImageAlpha(*info);
|
| - return info;
|
| -}
|
| + // Clear the alpha channel if this is RGB emulated.
|
| + if (imageId && !m_wantAlphaChannel &&
|
| + contextProvider()->getCapabilities().chromium_image_rgb_emulation) {
|
| + GLuint fbo = 0;
|
|
|
| -RefPtr<DrawingBuffer::ColorBuffer>
|
| -DrawingBuffer::createDefaultTextureAndAllocateMemory(const IntSize& size) {
|
| - TextureParameters parameters = defaultTextureParameters();
|
| - RefPtr<ColorBuffer> info(adoptRef(new ColorBuffer(this, parameters, size)));
|
| - info->textureId = createColorTexture(parameters);
|
| - allocateConditionallyImmutableTexture(
|
| - parameters.target, parameters.creationInternalColorFormat, size.width(),
|
| - size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE);
|
| - return info;
|
| + m_stateRestorer->setClearStateDirty();
|
| + m_gl->GenFramebuffers(1, &fbo);
|
| + m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
| + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| + parameters.target, textureId, 0);
|
| + m_gl->ClearColor(0, 0, 0, 1);
|
| + m_gl->ColorMask(false, false, false, true);
|
| + m_gl->Clear(GL_COLOR_BUFFER_BIT);
|
| + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
| + parameters.target, 0, 0);
|
| + m_gl->DeleteFramebuffers(1, &fbo);
|
| + }
|
| +
|
| + return adoptRef(new ColorBuffer(this, parameters, size, textureId, imageId));
|
| }
|
|
|
| void DrawingBuffer::attachColorBufferToReadFramebuffer() {
|
| + m_stateRestorer->setFramebufferBindingDirty();
|
| + m_stateRestorer->setTextureBindingDirty();
|
| +
|
| m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
|
|
| GLenum target = m_backColorBuffer->parameters.target;
|
| @@ -1200,9 +1199,6 @@ void DrawingBuffer::attachColorBufferToReadFramebuffer() {
|
| else
|
| m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, id,
|
| 0);
|
| -
|
| - restoreTextureBindings();
|
| - restoreFramebufferBindings();
|
| }
|
|
|
| bool DrawingBuffer::wantExplicitResolve() {
|
| @@ -1227,11 +1223,58 @@ GLenum DrawingBuffer::getMultisampledRenderbufferFormat() {
|
| return GL_RGB8_OES;
|
| }
|
|
|
| -void DrawingBuffer::restoreTextureBindings() {
|
| - // This class potentially modifies the bindings for GL_TEXTURE_2D and
|
| - // GL_TEXTURE_RECTANGLE. Only GL_TEXTURE_2D needs to be restored since
|
| - // the public interface for WebGL does not support GL_TEXTURE_RECTANGLE.
|
| - m_gl->BindTexture(GL_TEXTURE_2D, m_texture2DBinding);
|
| +DrawingBuffer::ScopedStateRestorer::ScopedStateRestorer(
|
| + DrawingBuffer* drawingBuffer)
|
| + : m_drawingBuffer(drawingBuffer) {
|
| + DCHECK(!m_drawingBuffer->m_stateRestorer);
|
| + m_drawingBuffer->m_stateRestorer = this;
|
| +}
|
| +
|
| +DrawingBuffer::ScopedStateRestorer::~ScopedStateRestorer() {
|
| + m_drawingBuffer->m_stateRestorer = nullptr;
|
| + if (!m_drawingBuffer->m_stateTracker)
|
| + return;
|
| +
|
| + gpu::gles2::GLES2Interface* gl = m_drawingBuffer->m_gl;
|
| + DrawingBufferRestoreState restoreState;
|
| + m_drawingBuffer->m_stateTracker->GetDrawingBufferRestoreState(&restoreState);
|
| +
|
| + if (m_clearStateDirty) {
|
| + if (restoreState.scissorEnabled)
|
| + gl->Enable(GL_SCISSOR_TEST);
|
| + else
|
| + gl->Disable(GL_SCISSOR_TEST);
|
| + gl->ClearColor(restoreState.clearColor[0], restoreState.clearColor[1],
|
| + restoreState.clearColor[2], restoreState.clearColor[3]);
|
| + gl->ClearDepthf(restoreState.clearDepth);
|
| + gl->ClearStencil(restoreState.clearStencil);
|
| +
|
| + gl->ColorMask(restoreState.colorMask[0], restoreState.colorMask[1],
|
| + restoreState.colorMask[2], restoreState.colorMask[3]);
|
| + gl->DepthMask(restoreState.depthMask);
|
| + gl->StencilMaskSeparate(GL_FRONT, restoreState.stencilMask);
|
| + }
|
| + if (m_pixelPackAlignmentDirty)
|
| + gl->PixelStorei(GL_PACK_ALIGNMENT, restoreState.packAlignment);
|
| + if (m_textureBindingDirty)
|
| + gl->BindTexture(GL_TEXTURE_2D, restoreState.activeTexture2DBinding);
|
| + if (m_renderbufferBindingDirty)
|
| + gl->BindRenderbuffer(GL_RENDERBUFFER, restoreState.renderbufferBinding);
|
| + if (m_framebufferBindingDirty) {
|
| + if (restoreState.drawFramebufferBinding ==
|
| + restoreState.readFramebufferBinding) {
|
| + gl->BindFramebuffer(GL_FRAMEBUFFER, restoreState.drawFramebufferBinding);
|
| + } else {
|
| + gl->BindFramebuffer(GL_READ_FRAMEBUFFER,
|
| + restoreState.readFramebufferBinding);
|
| + gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER,
|
| + restoreState.drawFramebufferBinding);
|
| + }
|
| + }
|
| + if (m_pixelUnpackBufferBindingDirty) {
|
| + gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER,
|
| + restoreState.pixelUnpackBufferBinding);
|
| + }
|
| }
|
|
|
| bool DrawingBuffer::shouldUseChromiumImage() {
|
|
|