blob: 1e48e05dbb1b736c07f0feea27786258f1f6591a [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "platform/graphics/gpu/DrawingBuffer.h"
#include "cc/resources/single_release_callback.h"
#include "cc/resources/texture_mailbox.h"
#include "gpu/command_buffer/client/gles2_interface_stub.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/UnacceleratedImageBufferSurface.h"
#include "platform/graphics/gpu/DrawingBufferTestHelpers.h"
#include "public/platform/Platform.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/PtrUtil.h"
#include "wtf/RefPtr.h"
#include <memory>
using testing::Test;
using testing::_;
namespace blink {
class DrawingBufferTest : public Test {
protected:
void SetUp() override {
IntSize initialSize(InitialWidth, InitialHeight);
std::unique_ptr<GLES2InterfaceForTests> gl =
wrapUnique(new GLES2InterfaceForTests);
m_gl = gl.get();
std::unique_ptr<WebGraphicsContext3DProviderForTests> provider =
wrapUnique(new WebGraphicsContext3DProviderForTests(std::move(gl)));
m_drawingBuffer = DrawingBufferForTests::create(
std::move(provider), initialSize, DrawingBuffer::Preserve);
CHECK(m_drawingBuffer);
}
GLES2InterfaceForTests* m_gl;
RefPtr<DrawingBufferForTests> m_drawingBuffer;
};
TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes) {
cc::TextureMailbox textureMailbox;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
IntSize initialSize(InitialWidth, InitialHeight);
IntSize alternateSize(InitialWidth, AlternateHeight);
// Produce one mailbox at size 100x100.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
// Resize to 100x50.
m_drawingBuffer->reset(alternateSize);
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
// Produce a mailbox at this size.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(alternateSize, m_gl->mostRecentlyProducedSize());
// Reset to initial size.
m_drawingBuffer->reset(initialSize);
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
// Prepare another mailbox and verify that it's the correct size.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
// Prepare one final mailbox and verify that it's the correct size.
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->beginDestruction();
}
TEST_F(DrawingBufferTest, verifyDestructionCompleteAfterAllMailboxesReleased) {
bool live = true;
m_drawingBuffer->m_live = &live;
cc::TextureMailbox textureMailbox1;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback1;
cc::TextureMailbox textureMailbox2;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback2;
cc::TextureMailbox textureMailbox3;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback3;
IntSize initialSize(InitialWidth, InitialHeight);
// Produce mailboxes.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox1,
&releaseCallback1));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox2,
&releaseCallback2));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox3,
&releaseCallback3));
m_drawingBuffer->markContentsChanged();
releaseCallback1->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->beginDestruction();
ASSERT_EQ(live, true);
DrawingBufferForTests* rawPointer = m_drawingBuffer.get();
m_drawingBuffer.clear();
ASSERT_EQ(live, true);
rawPointer->markContentsChanged();
releaseCallback2->Run(gpu::SyncToken(), false /* lostResource */);
ASSERT_EQ(live, true);
rawPointer->markContentsChanged();
releaseCallback3->Run(gpu::SyncToken(), false /* lostResource */);
ASSERT_EQ(live, false);
}
TEST_F(DrawingBufferTest, verifyDrawingBufferStaysAliveIfResourcesAreLost) {
bool live = true;
m_drawingBuffer->m_live = &live;
cc::TextureMailbox textureMailbox1;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback1;
cc::TextureMailbox textureMailbox2;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback2;
cc::TextureMailbox textureMailbox3;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback3;
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox1,
&releaseCallback1));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox2,
&releaseCallback2));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox3,
&releaseCallback3));
m_drawingBuffer->markContentsChanged();
releaseCallback1->Run(gpu::SyncToken(), true /* lostResource */);
EXPECT_EQ(live, true);
m_drawingBuffer->beginDestruction();
EXPECT_EQ(live, true);
m_drawingBuffer->markContentsChanged();
releaseCallback2->Run(gpu::SyncToken(), false /* lostResource */);
EXPECT_EQ(live, true);
DrawingBufferForTests* rawPtr = m_drawingBuffer.get();
m_drawingBuffer.clear();
EXPECT_EQ(live, true);
rawPtr->markContentsChanged();
releaseCallback3->Run(gpu::SyncToken(), true /* lostResource */);
EXPECT_EQ(live, false);
}
TEST_F(DrawingBufferTest, verifyOnlyOneRecycledMailboxMustBeKept) {
cc::TextureMailbox textureMailbox1;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback1;
cc::TextureMailbox textureMailbox2;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback2;
cc::TextureMailbox textureMailbox3;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback3;
// Produce mailboxes.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox1,
&releaseCallback1));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox2,
&releaseCallback2));
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox3,
&releaseCallback3));
// Release mailboxes by specific order; 1, 3, 2.
m_drawingBuffer->markContentsChanged();
releaseCallback1->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->markContentsChanged();
releaseCallback3->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->markContentsChanged();
releaseCallback2->Run(gpu::SyncToken(), false /* lostResource */);
// The first recycled mailbox must be 2. 1 and 3 were deleted by FIFO order
// because DrawingBuffer never keeps more than one mailbox.
cc::TextureMailbox recycledTextureMailbox1;
std::unique_ptr<cc::SingleReleaseCallback> recycledReleaseCallback1;
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(
&recycledTextureMailbox1, &recycledReleaseCallback1));
EXPECT_EQ(textureMailbox2.mailbox(), recycledTextureMailbox1.mailbox());
// The second recycled mailbox must be a new mailbox.
cc::TextureMailbox recycledTextureMailbox2;
std::unique_ptr<cc::SingleReleaseCallback> recycledReleaseCallback2;
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(
&recycledTextureMailbox2, &recycledReleaseCallback2));
EXPECT_NE(textureMailbox1.mailbox(), recycledTextureMailbox2.mailbox());
EXPECT_NE(textureMailbox2.mailbox(), recycledTextureMailbox2.mailbox());
EXPECT_NE(textureMailbox3.mailbox(), recycledTextureMailbox2.mailbox());
recycledReleaseCallback1->Run(gpu::SyncToken(), false /* lostResource */);
recycledReleaseCallback2->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->beginDestruction();
}
TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncTokenCorrectly) {
cc::TextureMailbox textureMailbox;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
// Produce mailboxes.
m_drawingBuffer->markContentsChanged();
EXPECT_EQ(gpu::SyncToken(), m_gl->mostRecentlyWaitedSyncToken());
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
// PrepareTextureMailbox() does not wait for any sync point.
EXPECT_EQ(gpu::SyncToken(), m_gl->mostRecentlyWaitedSyncToken());
gpu::SyncToken waitSyncToken;
m_gl->GenSyncTokenCHROMIUM(m_gl->InsertFenceSyncCHROMIUM(),
waitSyncToken.GetData());
releaseCallback->Run(waitSyncToken, false /* lostResource */);
// m_drawingBuffer will wait for the sync point when recycling.
EXPECT_EQ(gpu::SyncToken(), m_gl->mostRecentlyWaitedSyncToken());
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
// m_drawingBuffer waits for the sync point when recycling in
// PrepareTextureMailbox().
EXPECT_EQ(waitSyncToken, m_gl->mostRecentlyWaitedSyncToken());
m_drawingBuffer->beginDestruction();
m_gl->GenSyncTokenCHROMIUM(m_gl->InsertFenceSyncCHROMIUM(),
waitSyncToken.GetData());
releaseCallback->Run(waitSyncToken, false /* lostResource */);
// m_drawingBuffer waits for the sync point because the destruction is in
// progress.
EXPECT_EQ(waitSyncToken, m_gl->mostRecentlyWaitedSyncToken());
}
class DrawingBufferImageChromiumTest : public DrawingBufferTest {
protected:
void SetUp() override {
IntSize initialSize(InitialWidth, InitialHeight);
std::unique_ptr<GLES2InterfaceForTests> gl =
wrapUnique(new GLES2InterfaceForTests);
m_gl = gl.get();
std::unique_ptr<WebGraphicsContext3DProviderForTests> provider =
wrapUnique(new WebGraphicsContext3DProviderForTests(std::move(gl)));
RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true);
m_imageId0 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId0)).Times(1);
m_drawingBuffer = DrawingBufferForTests::create(
std::move(provider), initialSize, DrawingBuffer::Preserve);
CHECK(m_drawingBuffer);
testing::Mock::VerifyAndClearExpectations(m_gl);
}
void TearDown() override {
RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(false);
}
GLuint m_imageId0;
};
TEST_F(DrawingBufferImageChromiumTest, verifyResizingReallocatesImages) {
cc::TextureMailbox textureMailbox;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
IntSize initialSize(InitialWidth, InitialHeight);
IntSize alternateSize(InitialWidth, AlternateHeight);
GLuint m_imageId1 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId1)).Times(1);
// Produce one mailbox at size 100x100.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
EXPECT_TRUE(textureMailbox.is_overlay_candidate());
testing::Mock::VerifyAndClearExpectations(m_gl);
GLuint m_imageId2 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId2)).Times(1);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId0)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId0)).Times(1);
// Resize to 100x50.
m_drawingBuffer->reset(alternateSize);
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
testing::Mock::VerifyAndClearExpectations(m_gl);
GLuint m_imageId3 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId3)).Times(1);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId1)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId1)).Times(1);
// Produce a mailbox at this size.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(alternateSize, m_gl->mostRecentlyProducedSize());
EXPECT_TRUE(textureMailbox.is_overlay_candidate());
testing::Mock::VerifyAndClearExpectations(m_gl);
GLuint m_imageId4 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId4)).Times(1);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId2)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId2)).Times(1);
// Reset to initial size.
m_drawingBuffer->reset(initialSize);
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
testing::Mock::VerifyAndClearExpectations(m_gl);
GLuint m_imageId5 = m_gl->nextImageIdToBeCreated();
EXPECT_CALL(*m_gl, BindTexImage2DMock(m_imageId5)).Times(1);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId3)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId3)).Times(1);
// Prepare another mailbox and verify that it's the correct size.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
EXPECT_TRUE(textureMailbox.is_overlay_candidate());
testing::Mock::VerifyAndClearExpectations(m_gl);
// Prepare one final mailbox and verify that it's the correct size.
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
EXPECT_EQ(initialSize, m_gl->mostRecentlyProducedSize());
EXPECT_TRUE(textureMailbox.is_overlay_candidate());
releaseCallback->Run(gpu::SyncToken(), false /* lostResource */);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId5)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId5)).Times(1);
EXPECT_CALL(*m_gl, DestroyImageMock(m_imageId4)).Times(1);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(m_imageId4)).Times(1);
m_drawingBuffer->beginDestruction();
testing::Mock::VerifyAndClearExpectations(m_gl);
}
TEST_F(DrawingBufferImageChromiumTest, allocationFailure) {
cc::TextureMailbox textureMailbox1;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback1;
cc::TextureMailbox textureMailbox2;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback2;
cc::TextureMailbox textureMailbox3;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback3;
// Request a mailbox. An image should already be created. Everything works
// as expected.
EXPECT_CALL(*m_gl, BindTexImage2DMock(_)).Times(1);
IntSize initialSize(InitialWidth, InitialHeight);
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox1,
&releaseCallback1));
EXPECT_TRUE(textureMailbox1.is_overlay_candidate());
testing::Mock::VerifyAndClearExpectations(m_gl);
// Force image CHROMIUM creation failure. Request another mailbox. It should
// still be provided, but this time with allowOverlay = false.
m_gl->setCreateImageChromiumFail(true);
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox2,
&releaseCallback2));
EXPECT_FALSE(textureMailbox2.is_overlay_candidate());
// Check that if image CHROMIUM starts working again, mailboxes are
// correctly created with allowOverlay = true.
EXPECT_CALL(*m_gl, BindTexImage2DMock(_)).Times(1);
m_gl->setCreateImageChromiumFail(false);
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox3,
&releaseCallback3));
EXPECT_TRUE(textureMailbox3.is_overlay_candidate());
testing::Mock::VerifyAndClearExpectations(m_gl);
releaseCallback1->Run(gpu::SyncToken(), false /* lostResource */);
releaseCallback2->Run(gpu::SyncToken(), false /* lostResource */);
releaseCallback3->Run(gpu::SyncToken(), false /* lostResource */);
EXPECT_CALL(*m_gl, DestroyImageMock(_)).Times(3);
EXPECT_CALL(*m_gl, ReleaseTexImage2DMock(_)).Times(3);
m_drawingBuffer->beginDestruction();
testing::Mock::VerifyAndClearExpectations(m_gl);
}
class DepthStencilTrackingGLES2Interface
: public gpu::gles2::GLES2InterfaceStub {
public:
void FramebufferRenderbuffer(GLenum target,
GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer) override {
switch (attachment) {
case GL_DEPTH_ATTACHMENT:
m_depthAttachment = renderbuffer;
break;
case GL_STENCIL_ATTACHMENT:
m_stencilAttachment = renderbuffer;
break;
case GL_DEPTH_STENCIL_ATTACHMENT:
m_depthStencilAttachment = renderbuffer;
break;
default:
ASSERT_NOT_REACHED();
break;
}
}
GLenum CheckFramebufferStatus(GLenum target) override {
return GL_FRAMEBUFFER_COMPLETE;
}
void GetIntegerv(GLenum ptype, GLint* value) override {
switch (ptype) {
case GL_MAX_TEXTURE_SIZE:
*value = 1024;
return;
}
}
const GLubyte* GetString(GLenum type) override {
if (type == GL_EXTENSIONS)
return reinterpret_cast<const GLubyte*>("GL_OES_packed_depth_stencil");
return reinterpret_cast<const GLubyte*>("");
}
void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override {
for (GLsizei i = 0; i < n; ++i)
renderbuffers[i] = m_nextGenRenderbufferId++;
}
GLuint stencilAttachment() const { return m_stencilAttachment; }
GLuint depthAttachment() const { return m_depthAttachment; }
GLuint depthStencilAttachment() const { return m_depthStencilAttachment; }
size_t numAllocatedRenderBuffer() const {
return m_nextGenRenderbufferId - 1;
}
private:
GLuint m_nextGenRenderbufferId = 1;
GLuint m_depthAttachment = 0;
GLuint m_stencilAttachment = 0;
GLuint m_depthStencilAttachment = 0;
};
struct DepthStencilTestCase {
DepthStencilTestCase(bool requestStencil,
bool requestDepth,
int expectedRenderBuffers,
const char* const testCaseName)
: requestStencil(requestStencil),
requestDepth(requestDepth),
expectedRenderBuffers(expectedRenderBuffers),
testCaseName(testCaseName) {}
bool requestStencil;
bool requestDepth;
size_t expectedRenderBuffers;
const char* const testCaseName;
};
// This tests that, when the packed depth+stencil extension is supported, and
// either depth or stencil is requested, DrawingBuffer always allocates a single
// packed renderbuffer and properly computes the actual context attributes as
// defined by WebGL. We always allocate a packed buffer in this case since many
// desktop OpenGL drivers that support this extension do not consider a
// framebuffer with only a depth or a stencil buffer attached to be complete.
TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) {
DepthStencilTestCase cases[] = {
DepthStencilTestCase(false, false, 0, "neither"),
DepthStencilTestCase(true, false, 1, "stencil only"),
DepthStencilTestCase(false, true, 1, "depth only"),
DepthStencilTestCase(true, true, 1, "both"),
};
for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); i++) {
SCOPED_TRACE(cases[i].testCaseName);
std::unique_ptr<DepthStencilTrackingGLES2Interface> gl =
wrapUnique(new DepthStencilTrackingGLES2Interface);
DepthStencilTrackingGLES2Interface* trackingGL = gl.get();
std::unique_ptr<WebGraphicsContext3DProviderForTests> provider =
wrapUnique(new WebGraphicsContext3DProviderForTests(std::move(gl)));
DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::Preserve;
bool premultipliedAlpha = false;
bool wantAlphaChannel = true;
bool wantDepthBuffer = cases[i].requestDepth;
bool wantStencilBuffer = cases[i].requestStencil;
bool wantAntialiasing = false;
RefPtr<DrawingBuffer> drawingBuffer = DrawingBuffer::create(
std::move(provider), IntSize(10, 10), premultipliedAlpha,
wantAlphaChannel, wantDepthBuffer, wantStencilBuffer, wantAntialiasing,
preserve, DrawingBuffer::WebGL1, DrawingBuffer::AllowChromiumImage);
// When we request a depth or a stencil buffer, we will get both.
EXPECT_EQ(cases[i].requestDepth || cases[i].requestStencil,
drawingBuffer->hasDepthBuffer());
EXPECT_EQ(cases[i].requestDepth || cases[i].requestStencil,
drawingBuffer->hasStencilBuffer());
EXPECT_EQ(cases[i].expectedRenderBuffers,
trackingGL->numAllocatedRenderBuffer());
if (cases[i].requestDepth || cases[i].requestStencil) {
EXPECT_NE(0u, trackingGL->depthStencilAttachment());
EXPECT_EQ(0u, trackingGL->depthAttachment());
EXPECT_EQ(0u, trackingGL->stencilAttachment());
} else {
EXPECT_EQ(0u, trackingGL->depthStencilAttachment());
EXPECT_EQ(0u, trackingGL->depthAttachment());
EXPECT_EQ(0u, trackingGL->stencilAttachment());
}
drawingBuffer->reset(IntSize(10, 20));
EXPECT_EQ(cases[i].requestDepth || cases[i].requestStencil,
drawingBuffer->hasDepthBuffer());
EXPECT_EQ(cases[i].requestDepth || cases[i].requestStencil,
drawingBuffer->hasStencilBuffer());
EXPECT_EQ(cases[i].expectedRenderBuffers,
trackingGL->numAllocatedRenderBuffer());
if (cases[i].requestDepth || cases[i].requestStencil) {
EXPECT_NE(0u, trackingGL->depthStencilAttachment());
EXPECT_EQ(0u, trackingGL->depthAttachment());
EXPECT_EQ(0u, trackingGL->stencilAttachment());
} else {
EXPECT_EQ(0u, trackingGL->depthStencilAttachment());
EXPECT_EQ(0u, trackingGL->depthAttachment());
EXPECT_EQ(0u, trackingGL->stencilAttachment());
}
drawingBuffer->beginDestruction();
}
}
TEST_F(DrawingBufferTest, verifySetIsHiddenProperlyAffectsMailboxes) {
cc::TextureMailbox textureMailbox;
std::unique_ptr<cc::SingleReleaseCallback> releaseCallback;
// Produce mailboxes.
m_drawingBuffer->markContentsChanged();
EXPECT_TRUE(m_drawingBuffer->PrepareTextureMailbox(&textureMailbox,
&releaseCallback));
gpu::SyncToken waitSyncToken;
m_gl->GenSyncTokenCHROMIUM(m_gl->InsertFenceSyncCHROMIUM(),
waitSyncToken.GetData());
m_drawingBuffer->setIsHidden(true);
releaseCallback->Run(waitSyncToken, false /* lostResource */);
// m_drawingBuffer deletes mailbox immediately when hidden.
EXPECT_EQ(waitSyncToken, m_gl->mostRecentlyWaitedSyncToken());
m_drawingBuffer->beginDestruction();
}
} // namespace blink