| Index: content/browser/compositor/buffered_output_surface_unittest.cc
|
| diff --git a/content/browser/compositor/buffered_output_surface_unittest.cc b/content/browser/compositor/buffered_output_surface_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0d132d8cf0af33e7c45ad73a0428db39c54beb39
|
| --- /dev/null
|
| +++ b/content/browser/compositor/buffered_output_surface_unittest.cc
|
| @@ -0,0 +1,230 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <set>
|
| +
|
| +#include "cc/test/test_context_provider.h"
|
| +#include "cc/test/test_web_graphics_context_3d.h"
|
| +#include "content/browser/compositor/buffered_output_surface.h"
|
| +#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
|
| +#include "gpu/GLES2/gl2extchromium.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "third_party/khronos/GLES2/gl2ext.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::Expectation;
|
| +using ::testing::Ne;
|
| +using ::testing::Return;
|
| +
|
| +namespace content {
|
| +
|
| +class BufferedOutputSurfaceTest : public ::testing::Test {
|
| + public:
|
| + virtual void SetUp() OVERRIDE {
|
| + scoped_refptr<cc::TestContextProvider> context_provider =
|
| + cc::TestContextProvider::Create(cc::TestWebGraphicsContext3D::Create());
|
| + context_provider->BindToCurrentThread();
|
| + output_surface_.reset(
|
| + new BufferedOutputSurface(context_provider, GL_RGBA8_OES));
|
| + }
|
| +
|
| + unsigned current_surface() {
|
| + return output_surface_->current_surface_.second;
|
| + }
|
| + unsigned last_surface() { return output_surface_->last_surface_.second; }
|
| + const std::vector<BufferedOutputSurface::AllocatedSurface>&
|
| + available_surfaces() {
|
| + return output_surface_->available_surfaces_;
|
| + }
|
| + const std::queue<BufferedOutputSurface::AllocatedSurface>&
|
| + in_flight_surfaces() {
|
| + return output_surface_->in_flight_surfaces_;
|
| + }
|
| +
|
| + int CountBuffers() {
|
| + int n = available_surfaces().size() + in_flight_surfaces().size();
|
| + if (current_surface())
|
| + n++;
|
| + if (last_surface())
|
| + n++;
|
| + return n;
|
| + }
|
| +
|
| + // Check that each buffer is unique if present.
|
| + void CheckUnique() {
|
| + std::set<unsigned> buffers;
|
| + EXPECT_TRUE(InsertUnique(&buffers, current_surface()));
|
| + EXPECT_TRUE(InsertUnique(&buffers, last_surface()));
|
| + for (size_t i = 0; i < available_surfaces().size(); i++)
|
| + EXPECT_TRUE(InsertUnique(&buffers, available_surfaces()[i].second));
|
| + std::queue<BufferedOutputSurface::AllocatedSurface> copy =
|
| + in_flight_surfaces();
|
| + while (!copy.empty()) {
|
| + EXPECT_TRUE(InsertUnique(&buffers, copy.front().second));
|
| + copy.pop();
|
| + }
|
| + }
|
| +
|
| + protected:
|
| + bool InsertUnique(std::set<unsigned>* set, unsigned value) {
|
| + if (!value)
|
| + return true;
|
| + if (set->find(value) != set->end())
|
| + return false;
|
| + set->insert(value);
|
| + return true;
|
| + }
|
| +
|
| + scoped_ptr<BufferedOutputSurface> output_surface_;
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +class MockedContext : public cc::TestWebGraphicsContext3D {
|
| + public:
|
| + MOCK_METHOD2(bindFramebuffer, void(GLenum, GLuint));
|
| + MOCK_METHOD2(bindRenderbuffer, void(GLenum, GLuint));
|
| + MOCK_METHOD2(bindTexture, void(GLenum, GLuint));
|
| + MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
|
| + MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
|
| + MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
|
| + MOCK_METHOD4(framebufferRenderbuffer, void(GLenum, GLenum, GLenum, GLuint));
|
| + MOCK_METHOD5(framebufferTexture2D,
|
| + void(GLenum, GLenum, GLenum, GLuint, GLint));
|
| + MOCK_METHOD4(renderbufferStorage, void(GLenum, GLenum, GLsizei, GLsizei));
|
| +};
|
| +
|
| +scoped_ptr<BufferedOutputSurface> CreateOutputSurfaceWithMock(
|
| + MockedContext** context) {
|
| + *context = new MockedContext();
|
| + scoped_refptr<cc::TestContextProvider> context_provider =
|
| + cc::TestContextProvider::Create(
|
| + scoped_ptr<cc::TestWebGraphicsContext3D>(*context));
|
| + context_provider->BindToCurrentThread();
|
| + return scoped_ptr<BufferedOutputSurface>(
|
| + new BufferedOutputSurface(context_provider, GL_RGBA8_OES));
|
| +}
|
| +
|
| +TEST(BufferedOutputSurfaceStandaloneTest, FboInitialization) {
|
| + MockedContext* context;
|
| + scoped_ptr<BufferedOutputSurface> output_surface =
|
| + CreateOutputSurfaceWithMock(&context);
|
| +
|
| + Expectation rb =
|
| + EXPECT_CALL(*context, bindRenderbuffer(GL_RENDERBUFFER, Ne(0U)));
|
| + Expectation rb_storage =
|
| + EXPECT_CALL(*context,
|
| + renderbufferStorage(
|
| + GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, 10, 20))
|
| + .After(rb);
|
| + Expectation fb =
|
| + EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
|
| + EXPECT_CALL(*context,
|
| + framebufferRenderbuffer(
|
| + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Ne(0U)))
|
| + .After(fb, rb_storage);
|
| +
|
| + output_surface->Reshape(gfx::Size(10, 20), 1.0f);
|
| +}
|
| +
|
| +TEST(BufferedOutputSurfaceStandaloneTest, FboBinding) {
|
| + MockedContext* context;
|
| + scoped_ptr<BufferedOutputSurface> output_surface =
|
| + CreateOutputSurfaceWithMock(&context);
|
| + Expectation image =
|
| + EXPECT_CALL(
|
| + *context,
|
| + createImageCHROMIUM(0, 0, GL_RGBA8_OES, GL_IMAGE_SCANOUT_CHROMIUM))
|
| + .WillOnce(Return(1));
|
| + Expectation fb =
|
| + EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
|
| + Expectation tex = EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, Ne(0U)));
|
| + Expectation bind_tex =
|
| + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, 1))
|
| + .After(tex, image);
|
| + EXPECT_CALL(
|
| + *context,
|
| + framebufferTexture2D(
|
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Ne(0U), _))
|
| + .After(fb, bind_tex);
|
| + EXPECT_CALL(*context, destroyImageCHROMIUM(1));
|
| +
|
| + output_surface->BindFramebuffer();
|
| +}
|
| +
|
| +TEST_F(BufferedOutputSurfaceTest, MultipleBindCalls) {
|
| + // Check that multiple bind calls do not create or change surfaces.
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(1, CountBuffers());
|
| + unsigned int fb = current_surface();
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(1, CountBuffers());
|
| + EXPECT_EQ(fb, current_surface());
|
| +}
|
| +
|
| +TEST_F(BufferedOutputSurfaceTest, CheckDoubleBuffering) {
|
| + // Check buffer flow through double buffering path.
|
| + EXPECT_EQ(0, CountBuffers());
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(1, CountBuffers());
|
| + EXPECT_NE(0U, current_surface());
|
| + output_surface_->SwapBuffers();
|
| + EXPECT_EQ(1, CountBuffers());
|
| + EXPECT_NE(0U, last_surface());
|
| + output_surface_->PageFlipComplete();
|
| + EXPECT_EQ(1, CountBuffers());
|
| + EXPECT_NE(0U, last_surface());
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(2, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, current_surface());
|
| + EXPECT_NE(0U, last_surface());
|
| + output_surface_->SwapBuffers();
|
| + EXPECT_EQ(2, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, last_surface());
|
| + EXPECT_EQ(1U, in_flight_surfaces().size());
|
| + EXPECT_TRUE(available_surfaces().empty());
|
| + output_surface_->PageFlipComplete();
|
| + EXPECT_EQ(2, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, last_surface());
|
| + EXPECT_EQ(1U, available_surfaces().size());
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(2, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_TRUE(available_surfaces().empty());
|
| +}
|
| +
|
| +TEST_F(BufferedOutputSurfaceTest, CheckTripleBuffering) {
|
| + // Check buffer flow through triple buffering path.
|
| +
|
| + // This bit is the same sequence tested in the doublebuffering case.
|
| + output_surface_->BindFramebuffer();
|
| + output_surface_->SwapBuffers();
|
| + output_surface_->PageFlipComplete();
|
| + output_surface_->BindFramebuffer();
|
| + output_surface_->SwapBuffers();
|
| +
|
| + EXPECT_EQ(2, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, last_surface());
|
| + EXPECT_EQ(1U, in_flight_surfaces().size());
|
| + output_surface_->BindFramebuffer();
|
| + EXPECT_EQ(3, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, current_surface());
|
| + EXPECT_NE(0U, last_surface());
|
| + EXPECT_EQ(1U, in_flight_surfaces().size());
|
| + output_surface_->PageFlipComplete();
|
| + EXPECT_EQ(3, CountBuffers());
|
| + CheckUnique();
|
| + EXPECT_NE(0U, current_surface());
|
| + EXPECT_NE(0U, last_surface());
|
| + EXPECT_EQ(1U, available_surfaces().size());
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace content
|
|
|