| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright 2014 The Chromium Authors. All rights reserved. |  | 
|    2 // Use of this source code is governed by a BSD-style license that can be |  | 
|    3 // found in the LICENSE file. |  | 
|    4  |  | 
|    5 #include "components/display_compositor/buffer_queue.h" |  | 
|    6  |  | 
|    7 #include <stddef.h> |  | 
|    8 #include <stdint.h> |  | 
|    9  |  | 
|   10 #include <set> |  | 
|   11 #include <utility> |  | 
|   12  |  | 
|   13 #include "base/memory/ptr_util.h" |  | 
|   14 #include "cc/test/test_context_provider.h" |  | 
|   15 #include "cc/test/test_gpu_memory_buffer_manager.h" |  | 
|   16 #include "cc/test/test_web_graphics_context_3d.h" |  | 
|   17 #include "components/display_compositor/gl_helper.h" |  | 
|   18 #include "gpu/GLES2/gl2extchromium.h" |  | 
|   19 #include "testing/gmock/include/gmock/gmock.h" |  | 
|   20 #include "testing/gtest/include/gtest/gtest.h" |  | 
|   21 #include "third_party/khronos/GLES2/gl2ext.h" |  | 
|   22 #include "ui/display/types/display_snapshot.h" |  | 
|   23  |  | 
|   24 using ::testing::_; |  | 
|   25 using ::testing::Expectation; |  | 
|   26 using ::testing::Ne; |  | 
|   27 using ::testing::Return; |  | 
|   28  |  | 
|   29 namespace display_compositor { |  | 
|   30  |  | 
|   31 class StubGpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { |  | 
|   32  public: |  | 
|   33   StubGpuMemoryBufferImpl(size_t* set_color_space_count) |  | 
|   34       : set_color_space_count_(set_color_space_count) {} |  | 
|   35  |  | 
|   36   // Overridden from gfx::GpuMemoryBuffer: |  | 
|   37   bool Map() override { return false; } |  | 
|   38   void* memory(size_t plane) override { return nullptr; } |  | 
|   39   void Unmap() override {} |  | 
|   40   gfx::Size GetSize() const override { return gfx::Size(); } |  | 
|   41   gfx::BufferFormat GetFormat() const override { |  | 
|   42     return gfx::BufferFormat::BGRX_8888; |  | 
|   43   } |  | 
|   44   int stride(size_t plane) const override { return 0; } |  | 
|   45   gfx::GpuMemoryBufferId GetId() const override { |  | 
|   46     return gfx::GpuMemoryBufferId(0); |  | 
|   47   } |  | 
|   48   void SetColorSpaceForScanout(const gfx::ColorSpace& color_space) override { |  | 
|   49     *set_color_space_count_ += 1; |  | 
|   50   } |  | 
|   51   gfx::GpuMemoryBufferHandle GetHandle() const override { |  | 
|   52     return gfx::GpuMemoryBufferHandle(); |  | 
|   53   } |  | 
|   54   ClientBuffer AsClientBuffer() override { |  | 
|   55     return reinterpret_cast<ClientBuffer>(this); |  | 
|   56   } |  | 
|   57  |  | 
|   58   size_t* set_color_space_count_; |  | 
|   59 }; |  | 
|   60  |  | 
|   61 class StubGpuMemoryBufferManager : public cc::TestGpuMemoryBufferManager { |  | 
|   62  public: |  | 
|   63   StubGpuMemoryBufferManager() : allocate_succeeds_(true) {} |  | 
|   64  |  | 
|   65   size_t set_color_space_count() const { return set_color_space_count_; } |  | 
|   66  |  | 
|   67   void set_allocate_succeeds(bool value) { allocate_succeeds_ = value; } |  | 
|   68  |  | 
|   69   std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( |  | 
|   70       const gfx::Size& size, |  | 
|   71       gfx::BufferFormat format, |  | 
|   72       gfx::BufferUsage usage, |  | 
|   73       gpu::SurfaceHandle surface_handle) override { |  | 
|   74     if (!surface_handle) { |  | 
|   75       return TestGpuMemoryBufferManager::CreateGpuMemoryBuffer( |  | 
|   76           size, format, usage, surface_handle); |  | 
|   77     } |  | 
|   78     if (allocate_succeeds_) |  | 
|   79       return base::WrapUnique<gfx::GpuMemoryBuffer>( |  | 
|   80           new StubGpuMemoryBufferImpl(&set_color_space_count_)); |  | 
|   81     return nullptr; |  | 
|   82   } |  | 
|   83  |  | 
|   84  private: |  | 
|   85   bool allocate_succeeds_; |  | 
|   86   size_t set_color_space_count_ = 0; |  | 
|   87 }; |  | 
|   88  |  | 
|   89 #if defined(OS_WIN) |  | 
|   90 const gpu::SurfaceHandle kFakeSurfaceHandle = |  | 
|   91     reinterpret_cast<gpu::SurfaceHandle>(1); |  | 
|   92 #else |  | 
|   93 const gpu::SurfaceHandle kFakeSurfaceHandle = 1; |  | 
|   94 #endif |  | 
|   95  |  | 
|   96 class MockBufferQueue : public BufferQueue { |  | 
|   97  public: |  | 
|   98   MockBufferQueue(gpu::gles2::GLES2Interface* gl, |  | 
|   99                   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, |  | 
|  100                   unsigned int target, |  | 
|  101                   unsigned int internalformat) |  | 
|  102       : BufferQueue(gl, |  | 
|  103                     target, |  | 
|  104                     internalformat, |  | 
|  105                     display::DisplaySnapshot::PrimaryFormat(), |  | 
|  106                     nullptr, |  | 
|  107                     gpu_memory_buffer_manager, |  | 
|  108                     kFakeSurfaceHandle) {} |  | 
|  109   MOCK_METHOD4(CopyBufferDamage, |  | 
|  110                void(int, int, const gfx::Rect&, const gfx::Rect&)); |  | 
|  111 }; |  | 
|  112  |  | 
|  113 class BufferQueueTest : public ::testing::Test { |  | 
|  114  public: |  | 
|  115   BufferQueueTest() : doublebuffering_(true), first_frame_(true) {} |  | 
|  116  |  | 
|  117   void SetUp() override { |  | 
|  118     InitWithContext(cc::TestWebGraphicsContext3D::Create()); |  | 
|  119   } |  | 
|  120  |  | 
|  121   void InitWithContext(std::unique_ptr<cc::TestWebGraphicsContext3D> context) { |  | 
|  122     context_provider_ = cc::TestContextProvider::Create(std::move(context)); |  | 
|  123     context_provider_->BindToCurrentThread(); |  | 
|  124     gpu_memory_buffer_manager_.reset(new StubGpuMemoryBufferManager); |  | 
|  125     mock_output_surface_ = new MockBufferQueue(context_provider_->ContextGL(), |  | 
|  126                                                gpu_memory_buffer_manager_.get(), |  | 
|  127                                                GL_TEXTURE_2D, GL_RGB); |  | 
|  128     output_surface_.reset(mock_output_surface_); |  | 
|  129     output_surface_->Initialize(); |  | 
|  130   } |  | 
|  131  |  | 
|  132   unsigned current_surface() { |  | 
|  133     return output_surface_->current_surface_ |  | 
|  134                ? output_surface_->current_surface_->image |  | 
|  135                : 0; |  | 
|  136   } |  | 
|  137   const std::vector<std::unique_ptr<BufferQueue::AllocatedSurface>>& |  | 
|  138   available_surfaces() { |  | 
|  139     return output_surface_->available_surfaces_; |  | 
|  140   } |  | 
|  141   std::deque<std::unique_ptr<BufferQueue::AllocatedSurface>>& |  | 
|  142   in_flight_surfaces() { |  | 
|  143     return output_surface_->in_flight_surfaces_; |  | 
|  144   } |  | 
|  145  |  | 
|  146   const BufferQueue::AllocatedSurface* displayed_frame() { |  | 
|  147     return output_surface_->displayed_surface_.get(); |  | 
|  148   } |  | 
|  149   const BufferQueue::AllocatedSurface* current_frame() { |  | 
|  150     return output_surface_->current_surface_.get(); |  | 
|  151   } |  | 
|  152   const BufferQueue::AllocatedSurface* next_frame() { |  | 
|  153     return output_surface_->available_surfaces_.back().get(); |  | 
|  154   } |  | 
|  155   const gfx::Size size() { return output_surface_->size_; } |  | 
|  156  |  | 
|  157   int CountBuffers() { |  | 
|  158     int n = available_surfaces().size() + in_flight_surfaces().size() + |  | 
|  159             (displayed_frame() ? 1 : 0); |  | 
|  160     if (current_surface()) |  | 
|  161       n++; |  | 
|  162     return n; |  | 
|  163   } |  | 
|  164  |  | 
|  165   // Check that each buffer is unique if present. |  | 
|  166   void CheckUnique() { |  | 
|  167     std::set<unsigned> buffers; |  | 
|  168     EXPECT_TRUE(InsertUnique(&buffers, current_surface())); |  | 
|  169     if (displayed_frame()) |  | 
|  170       EXPECT_TRUE(InsertUnique(&buffers, displayed_frame()->image)); |  | 
|  171     for (auto& surface : available_surfaces()) |  | 
|  172       EXPECT_TRUE(InsertUnique(&buffers, surface->image)); |  | 
|  173     for (auto& surface : in_flight_surfaces()) { |  | 
|  174       if (surface) |  | 
|  175         EXPECT_TRUE(InsertUnique(&buffers, surface->image)); |  | 
|  176     } |  | 
|  177   } |  | 
|  178  |  | 
|  179   void SwapBuffers() { |  | 
|  180     output_surface_->SwapBuffers(gfx::Rect(output_surface_->size_)); |  | 
|  181   } |  | 
|  182  |  | 
|  183   void SendDamagedFrame(const gfx::Rect& damage) { |  | 
|  184     // We don't care about the GL-level implementation here, just how it uses |  | 
|  185     // damage rects. |  | 
|  186     output_surface_->BindFramebuffer(); |  | 
|  187     output_surface_->SwapBuffers(damage); |  | 
|  188     if (doublebuffering_ || !first_frame_) |  | 
|  189       output_surface_->PageFlipComplete(); |  | 
|  190     first_frame_ = false; |  | 
|  191   } |  | 
|  192  |  | 
|  193   void SendFullFrame() { SendDamagedFrame(gfx::Rect(output_surface_->size_)); } |  | 
|  194  |  | 
|  195  protected: |  | 
|  196   bool InsertUnique(std::set<unsigned>* set, unsigned value) { |  | 
|  197     if (!value) |  | 
|  198       return true; |  | 
|  199     if (set->find(value) != set->end()) |  | 
|  200       return false; |  | 
|  201     set->insert(value); |  | 
|  202     return true; |  | 
|  203   } |  | 
|  204  |  | 
|  205   scoped_refptr<cc::TestContextProvider> context_provider_; |  | 
|  206   std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager_; |  | 
|  207   std::unique_ptr<BufferQueue> output_surface_; |  | 
|  208   MockBufferQueue* mock_output_surface_; |  | 
|  209   bool doublebuffering_; |  | 
|  210   bool first_frame_; |  | 
|  211 }; |  | 
|  212  |  | 
|  213 namespace { |  | 
|  214 const gfx::Size screen_size = gfx::Size(30, 30); |  | 
|  215 const gfx::Rect screen_rect = gfx::Rect(screen_size); |  | 
|  216 const gfx::Rect small_damage = gfx::Rect(gfx::Size(10, 10)); |  | 
|  217 const gfx::Rect large_damage = gfx::Rect(gfx::Size(20, 20)); |  | 
|  218 const gfx::Rect overlapping_damage = gfx::Rect(gfx::Size(5, 20)); |  | 
|  219  |  | 
|  220 GLuint CreateImageDefault() { |  | 
|  221   static GLuint id = 0; |  | 
|  222   return ++id; |  | 
|  223 } |  | 
|  224  |  | 
|  225 class MockedContext : public cc::TestWebGraphicsContext3D { |  | 
|  226  public: |  | 
|  227   MockedContext() { |  | 
|  228     ON_CALL(*this, createImageCHROMIUM(_, _, _, _)) |  | 
|  229         .WillByDefault(testing::InvokeWithoutArgs(&CreateImageDefault)); |  | 
|  230   } |  | 
|  231   MOCK_METHOD2(bindFramebuffer, void(GLenum, GLuint)); |  | 
|  232   MOCK_METHOD2(bindTexture, void(GLenum, GLuint)); |  | 
|  233   MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint)); |  | 
|  234   MOCK_METHOD4(createImageCHROMIUM, |  | 
|  235                GLuint(ClientBuffer, GLsizei, GLsizei, GLenum)); |  | 
|  236   MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint)); |  | 
|  237   MOCK_METHOD5(framebufferTexture2D, |  | 
|  238                void(GLenum, GLenum, GLenum, GLuint, GLint)); |  | 
|  239 }; |  | 
|  240  |  | 
|  241 class BufferQueueMockedContextTest : public BufferQueueTest { |  | 
|  242  public: |  | 
|  243   void SetUp() override { |  | 
|  244     context_ = new MockedContext(); |  | 
|  245     InitWithContext(std::unique_ptr<cc::TestWebGraphicsContext3D>(context_)); |  | 
|  246   } |  | 
|  247  |  | 
|  248  protected: |  | 
|  249   MockedContext* context_; |  | 
|  250 }; |  | 
|  251  |  | 
|  252 scoped_refptr<cc::TestContextProvider> CreateMockedContextProvider( |  | 
|  253     MockedContext** context) { |  | 
|  254   std::unique_ptr<MockedContext> owned_context(new MockedContext); |  | 
|  255   *context = owned_context.get(); |  | 
|  256   scoped_refptr<cc::TestContextProvider> context_provider = |  | 
|  257       cc::TestContextProvider::Create(std::move(owned_context)); |  | 
|  258   context_provider->BindToCurrentThread(); |  | 
|  259   return context_provider; |  | 
|  260 } |  | 
|  261  |  | 
|  262 std::unique_ptr<BufferQueue> CreateBufferQueue( |  | 
|  263     unsigned int target, |  | 
|  264     gpu::gles2::GLES2Interface* gl, |  | 
|  265     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { |  | 
|  266   std::unique_ptr<BufferQueue> buffer_queue(new BufferQueue( |  | 
|  267       gl, target, GL_RGB, display::DisplaySnapshot::PrimaryFormat(), nullptr, |  | 
|  268       gpu_memory_buffer_manager, kFakeSurfaceHandle)); |  | 
|  269   buffer_queue->Initialize(); |  | 
|  270   return buffer_queue; |  | 
|  271 } |  | 
|  272  |  | 
|  273 TEST(BufferQueueStandaloneTest, FboInitialization) { |  | 
|  274   MockedContext* context; |  | 
|  275   scoped_refptr<cc::TestContextProvider> context_provider = |  | 
|  276       CreateMockedContextProvider(&context); |  | 
|  277   std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager( |  | 
|  278       new StubGpuMemoryBufferManager); |  | 
|  279   std::unique_ptr<BufferQueue> output_surface = |  | 
|  280       CreateBufferQueue(GL_TEXTURE_2D, context_provider->ContextGL(), |  | 
|  281                         gpu_memory_buffer_manager.get()); |  | 
|  282  |  | 
|  283   EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U))); |  | 
|  284   ON_CALL(*context, framebufferTexture2D(_, _, _, _, _)) |  | 
|  285       .WillByDefault(Return()); |  | 
|  286  |  | 
|  287   output_surface->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false); |  | 
|  288 } |  | 
|  289  |  | 
|  290 TEST(BufferQueueStandaloneTest, FboBinding) { |  | 
|  291   GLenum targets[] = {GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB}; |  | 
|  292   for (size_t i = 0; i < 2; ++i) { |  | 
|  293     GLenum target = targets[i]; |  | 
|  294  |  | 
|  295     MockedContext* context; |  | 
|  296     scoped_refptr<cc::TestContextProvider> context_provider = |  | 
|  297         CreateMockedContextProvider(&context); |  | 
|  298     std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager( |  | 
|  299         new StubGpuMemoryBufferManager); |  | 
|  300     std::unique_ptr<BufferQueue> output_surface = CreateBufferQueue( |  | 
|  301         target, context_provider->ContextGL(), gpu_memory_buffer_manager.get()); |  | 
|  302  |  | 
|  303     EXPECT_CALL(*context, bindTexture(target, Ne(0U))); |  | 
|  304     EXPECT_CALL(*context, destroyImageCHROMIUM(1)); |  | 
|  305     Expectation image = |  | 
|  306         EXPECT_CALL(*context, createImageCHROMIUM(_, 0, 0, GL_RGB)) |  | 
|  307             .WillOnce(Return(1)); |  | 
|  308     Expectation fb = |  | 
|  309         EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U))); |  | 
|  310     Expectation tex = EXPECT_CALL(*context, bindTexture(target, Ne(0U))); |  | 
|  311     Expectation bind_tex = |  | 
|  312         EXPECT_CALL(*context, bindTexImage2DCHROMIUM(target, 1)) |  | 
|  313             .After(tex, image); |  | 
|  314     EXPECT_CALL(*context, |  | 
|  315                 framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |  | 
|  316                                      target, Ne(0U), _)) |  | 
|  317         .After(fb, bind_tex); |  | 
|  318  |  | 
|  319     output_surface->BindFramebuffer(); |  | 
|  320   } |  | 
|  321 } |  | 
|  322  |  | 
|  323 TEST(BufferQueueStandaloneTest, CheckBoundFramebuffer) { |  | 
|  324   scoped_refptr<cc::TestContextProvider> context_provider = |  | 
|  325       cc::TestContextProvider::Create(); |  | 
|  326   context_provider->BindToCurrentThread(); |  | 
|  327   std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager; |  | 
|  328   std::unique_ptr<BufferQueue> output_surface; |  | 
|  329   gpu_memory_buffer_manager.reset(new StubGpuMemoryBufferManager); |  | 
|  330  |  | 
|  331   std::unique_ptr<GLHelper> gl_helper; |  | 
|  332   gl_helper.reset(new GLHelper(context_provider->ContextGL(), |  | 
|  333                                context_provider->ContextSupport())); |  | 
|  334  |  | 
|  335   output_surface.reset(new BufferQueue( |  | 
|  336       context_provider->ContextGL(), GL_TEXTURE_2D, GL_RGB, |  | 
|  337       display::DisplaySnapshot::PrimaryFormat(), gl_helper.get(), |  | 
|  338       gpu_memory_buffer_manager.get(), kFakeSurfaceHandle)); |  | 
|  339   output_surface->Initialize(); |  | 
|  340   output_surface->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false); |  | 
|  341   // Trigger a sub-buffer copy to exercise all paths. |  | 
|  342   output_surface->BindFramebuffer(); |  | 
|  343   output_surface->SwapBuffers(screen_rect); |  | 
|  344   output_surface->PageFlipComplete(); |  | 
|  345   output_surface->BindFramebuffer(); |  | 
|  346   output_surface->SwapBuffers(small_damage); |  | 
|  347  |  | 
|  348   int current_fbo = 0; |  | 
|  349   context_provider->ContextGL()->GetIntegerv(GL_FRAMEBUFFER_BINDING, |  | 
|  350                                              ¤t_fbo); |  | 
|  351   EXPECT_EQ(static_cast<int>(output_surface->fbo()), current_fbo); |  | 
|  352 } |  | 
|  353  |  | 
|  354 TEST_F(BufferQueueTest, PartialSwapReuse) { |  | 
|  355   output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false); |  | 
|  356   ASSERT_TRUE(doublebuffering_); |  | 
|  357   EXPECT_CALL(*mock_output_surface_, |  | 
|  358               CopyBufferDamage(_, _, small_damage, screen_rect)) |  | 
|  359       .Times(1); |  | 
|  360   EXPECT_CALL(*mock_output_surface_, |  | 
|  361               CopyBufferDamage(_, _, small_damage, small_damage)) |  | 
|  362       .Times(1); |  | 
|  363   EXPECT_CALL(*mock_output_surface_, |  | 
|  364               CopyBufferDamage(_, _, large_damage, small_damage)) |  | 
|  365       .Times(1); |  | 
|  366   SendFullFrame(); |  | 
|  367   SendDamagedFrame(small_damage); |  | 
|  368   SendDamagedFrame(small_damage); |  | 
|  369   SendDamagedFrame(large_damage); |  | 
|  370   // Verify that the damage has propagated. |  | 
|  371   EXPECT_EQ(next_frame()->damage, large_damage); |  | 
|  372 } |  | 
|  373  |  | 
|  374 TEST_F(BufferQueueTest, PartialSwapFullFrame) { |  | 
|  375   output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false); |  | 
|  376   ASSERT_TRUE(doublebuffering_); |  | 
|  377   EXPECT_CALL(*mock_output_surface_, |  | 
|  378               CopyBufferDamage(_, _, small_damage, screen_rect)) |  | 
|  379       .Times(1); |  | 
|  380   SendFullFrame(); |  | 
|  381   SendDamagedFrame(small_damage); |  | 
|  382   SendFullFrame(); |  | 
|  383   SendFullFrame(); |  | 
|  384   EXPECT_EQ(next_frame()->damage, screen_rect); |  | 
|  385 } |  | 
|  386  |  | 
|  387 TEST_F(BufferQueueTest, PartialSwapOverlapping) { |  | 
|  388   output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false); |  | 
|  389   ASSERT_TRUE(doublebuffering_); |  | 
|  390   EXPECT_CALL(*mock_output_surface_, |  | 
|  391               CopyBufferDamage(_, _, small_damage, screen_rect)) |  | 
|  392       .Times(1); |  | 
|  393   EXPECT_CALL(*mock_output_surface_, |  | 
|  394               CopyBufferDamage(_, _, overlapping_damage, small_damage)) |  | 
|  395       .Times(1); |  | 
|  396  |  | 
|  397   SendFullFrame(); |  | 
|  398   SendDamagedFrame(small_damage); |  | 
|  399   SendDamagedFrame(overlapping_damage); |  | 
|  400   EXPECT_EQ(next_frame()->damage, overlapping_damage); |  | 
|  401 } |  | 
|  402  |  | 
|  403 TEST_F(BufferQueueTest, MultipleBindCalls) { |  | 
|  404   // Check that multiple bind calls do not create or change surfaces. |  | 
|  405   output_surface_->BindFramebuffer(); |  | 
|  406   EXPECT_EQ(1, CountBuffers()); |  | 
|  407   unsigned int fb = current_surface(); |  | 
|  408   output_surface_->BindFramebuffer(); |  | 
|  409   EXPECT_EQ(1, CountBuffers()); |  | 
|  410   EXPECT_EQ(fb, current_surface()); |  | 
|  411 } |  | 
|  412  |  | 
|  413 TEST_F(BufferQueueTest, CheckDoubleBuffering) { |  | 
|  414   // Check buffer flow through double buffering path. |  | 
|  415   EXPECT_EQ(0, CountBuffers()); |  | 
|  416   output_surface_->BindFramebuffer(); |  | 
|  417   EXPECT_EQ(1, CountBuffers()); |  | 
|  418   EXPECT_NE(0U, current_surface()); |  | 
|  419   EXPECT_FALSE(displayed_frame()); |  | 
|  420   SwapBuffers(); |  | 
|  421   EXPECT_EQ(1U, in_flight_surfaces().size()); |  | 
|  422   output_surface_->PageFlipComplete(); |  | 
|  423   EXPECT_EQ(0U, in_flight_surfaces().size()); |  | 
|  424   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  425   output_surface_->BindFramebuffer(); |  | 
|  426   EXPECT_EQ(2, CountBuffers()); |  | 
|  427   CheckUnique(); |  | 
|  428   EXPECT_NE(0U, current_surface()); |  | 
|  429   EXPECT_EQ(0U, in_flight_surfaces().size()); |  | 
|  430   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  431   SwapBuffers(); |  | 
|  432   CheckUnique(); |  | 
|  433   EXPECT_EQ(1U, in_flight_surfaces().size()); |  | 
|  434   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  435   output_surface_->PageFlipComplete(); |  | 
|  436   CheckUnique(); |  | 
|  437   EXPECT_EQ(0U, in_flight_surfaces().size()); |  | 
|  438   EXPECT_EQ(1U, available_surfaces().size()); |  | 
|  439   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  440   output_surface_->BindFramebuffer(); |  | 
|  441   EXPECT_EQ(2, CountBuffers()); |  | 
|  442   CheckUnique(); |  | 
|  443   EXPECT_TRUE(available_surfaces().empty()); |  | 
|  444 } |  | 
|  445  |  | 
|  446 TEST_F(BufferQueueTest, CheckTripleBuffering) { |  | 
|  447   // Check buffer flow through triple buffering path. |  | 
|  448  |  | 
|  449   // This bit is the same sequence tested in the doublebuffering case. |  | 
|  450   output_surface_->BindFramebuffer(); |  | 
|  451   EXPECT_FALSE(displayed_frame()); |  | 
|  452   SwapBuffers(); |  | 
|  453   output_surface_->PageFlipComplete(); |  | 
|  454   output_surface_->BindFramebuffer(); |  | 
|  455   SwapBuffers(); |  | 
|  456  |  | 
|  457   EXPECT_EQ(2, CountBuffers()); |  | 
|  458   CheckUnique(); |  | 
|  459   EXPECT_EQ(1U, in_flight_surfaces().size()); |  | 
|  460   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  461   output_surface_->BindFramebuffer(); |  | 
|  462   EXPECT_EQ(3, CountBuffers()); |  | 
|  463   CheckUnique(); |  | 
|  464   EXPECT_NE(0U, current_surface()); |  | 
|  465   EXPECT_EQ(1U, in_flight_surfaces().size()); |  | 
|  466   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  467   output_surface_->PageFlipComplete(); |  | 
|  468   EXPECT_EQ(3, CountBuffers()); |  | 
|  469   CheckUnique(); |  | 
|  470   EXPECT_NE(0U, current_surface()); |  | 
|  471   EXPECT_EQ(0U, in_flight_surfaces().size()); |  | 
|  472   EXPECT_TRUE(displayed_frame()->texture); |  | 
|  473   EXPECT_EQ(1U, available_surfaces().size()); |  | 
|  474 } |  | 
|  475  |  | 
|  476 TEST_F(BufferQueueTest, CheckCorrectBufferOrdering) { |  | 
|  477   const size_t kSwapCount = 3; |  | 
|  478   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  479     output_surface_->BindFramebuffer(); |  | 
|  480     SwapBuffers(); |  | 
|  481   } |  | 
|  482  |  | 
|  483   EXPECT_EQ(kSwapCount, in_flight_surfaces().size()); |  | 
|  484   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  485     unsigned int next_texture_id = in_flight_surfaces().front()->texture; |  | 
|  486     output_surface_->PageFlipComplete(); |  | 
|  487     EXPECT_EQ(displayed_frame()->texture, next_texture_id); |  | 
|  488   } |  | 
|  489 } |  | 
|  490  |  | 
|  491 TEST_F(BufferQueueTest, ReshapeWithInFlightSurfaces) { |  | 
|  492   const size_t kSwapCount = 3; |  | 
|  493   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  494     output_surface_->BindFramebuffer(); |  | 
|  495     SwapBuffers(); |  | 
|  496   } |  | 
|  497  |  | 
|  498   output_surface_->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false); |  | 
|  499   EXPECT_EQ(3u, in_flight_surfaces().size()); |  | 
|  500  |  | 
|  501   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  502     output_surface_->PageFlipComplete(); |  | 
|  503     EXPECT_FALSE(displayed_frame()); |  | 
|  504   } |  | 
|  505  |  | 
|  506   // The dummy surfacess left should be discarded. |  | 
|  507   EXPECT_EQ(0u, available_surfaces().size()); |  | 
|  508 } |  | 
|  509  |  | 
|  510 TEST_F(BufferQueueTest, SwapAfterReshape) { |  | 
|  511   DCHECK_EQ(0u, gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  512   const size_t kSwapCount = 3; |  | 
|  513   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  514     output_surface_->BindFramebuffer(); |  | 
|  515     SwapBuffers(); |  | 
|  516   } |  | 
|  517   DCHECK_EQ(kSwapCount, gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  518  |  | 
|  519   output_surface_->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false); |  | 
|  520   DCHECK_EQ(kSwapCount, gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  521  |  | 
|  522   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  523     output_surface_->BindFramebuffer(); |  | 
|  524     SwapBuffers(); |  | 
|  525   } |  | 
|  526   DCHECK_EQ(2 * kSwapCount, |  | 
|  527             gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  528   EXPECT_EQ(2 * kSwapCount, in_flight_surfaces().size()); |  | 
|  529  |  | 
|  530   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  531     output_surface_->PageFlipComplete(); |  | 
|  532     EXPECT_FALSE(displayed_frame()); |  | 
|  533   } |  | 
|  534  |  | 
|  535   CheckUnique(); |  | 
|  536  |  | 
|  537   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  538     unsigned int next_texture_id = in_flight_surfaces().front()->texture; |  | 
|  539     output_surface_->PageFlipComplete(); |  | 
|  540     EXPECT_EQ(displayed_frame()->texture, next_texture_id); |  | 
|  541     EXPECT_TRUE(displayed_frame()); |  | 
|  542   } |  | 
|  543  |  | 
|  544   DCHECK_EQ(2 * kSwapCount, |  | 
|  545             gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  546   for (size_t i = 0; i < kSwapCount; ++i) { |  | 
|  547     output_surface_->BindFramebuffer(); |  | 
|  548     SwapBuffers(); |  | 
|  549     output_surface_->PageFlipComplete(); |  | 
|  550   } |  | 
|  551   DCHECK_EQ(2 * kSwapCount, |  | 
|  552             gpu_memory_buffer_manager_->set_color_space_count()); |  | 
|  553 } |  | 
|  554  |  | 
|  555 TEST_F(BufferQueueMockedContextTest, RecreateBuffers) { |  | 
|  556   // This setup is to easily get one frame in each of: |  | 
|  557   // - currently bound for drawing. |  | 
|  558   // - in flight to GPU. |  | 
|  559   // - currently displayed. |  | 
|  560   // - free frame. |  | 
|  561   // This tests buffers in all states. |  | 
|  562   // Bind/swap pushes frames into the in flight list, then the PageFlipComplete |  | 
|  563   // calls pull one frame into displayed and another into the free list. |  | 
|  564   output_surface_->BindFramebuffer(); |  | 
|  565   SwapBuffers(); |  | 
|  566   output_surface_->BindFramebuffer(); |  | 
|  567   SwapBuffers(); |  | 
|  568   output_surface_->BindFramebuffer(); |  | 
|  569   SwapBuffers(); |  | 
|  570   output_surface_->BindFramebuffer(); |  | 
|  571   output_surface_->PageFlipComplete(); |  | 
|  572   output_surface_->PageFlipComplete(); |  | 
|  573   // We should have one buffer in each possible state right now, including one |  | 
|  574   // being drawn to. |  | 
|  575   ASSERT_EQ(1U, in_flight_surfaces().size()); |  | 
|  576   ASSERT_EQ(1U, available_surfaces().size()); |  | 
|  577   EXPECT_TRUE(displayed_frame()); |  | 
|  578   EXPECT_TRUE(current_frame()); |  | 
|  579  |  | 
|  580   auto* current = current_frame(); |  | 
|  581   auto* displayed = displayed_frame(); |  | 
|  582   auto* in_flight = in_flight_surfaces().front().get(); |  | 
|  583   auto* available = available_surfaces().front().get(); |  | 
|  584  |  | 
|  585   // Expect all 4 images to be destroyed, 3 of the existing textures to be |  | 
|  586   // copied from and 3 new images to be created. |  | 
|  587   EXPECT_CALL(*context_, createImageCHROMIUM(_, 0, 0, GL_RGB)).Times(3); |  | 
|  588   Expectation copy1 = EXPECT_CALL(*mock_output_surface_, |  | 
|  589                                   CopyBufferDamage(_, displayed->texture, _, _)) |  | 
|  590                           .Times(1); |  | 
|  591   Expectation copy2 = EXPECT_CALL(*mock_output_surface_, |  | 
|  592                                   CopyBufferDamage(_, current->texture, _, _)) |  | 
|  593                           .Times(1); |  | 
|  594   Expectation copy3 = EXPECT_CALL(*mock_output_surface_, |  | 
|  595                                   CopyBufferDamage(_, in_flight->texture, _, _)) |  | 
|  596                           .Times(1); |  | 
|  597  |  | 
|  598   EXPECT_CALL(*context_, destroyImageCHROMIUM(displayed->image)) |  | 
|  599       .Times(1) |  | 
|  600       .After(copy1); |  | 
|  601   EXPECT_CALL(*context_, destroyImageCHROMIUM(current->image)) |  | 
|  602       .Times(1) |  | 
|  603       .After(copy2); |  | 
|  604   EXPECT_CALL(*context_, destroyImageCHROMIUM(in_flight->image)) |  | 
|  605       .Times(1) |  | 
|  606       .After(copy3); |  | 
|  607   EXPECT_CALL(*context_, destroyImageCHROMIUM(available->image)).Times(1); |  | 
|  608   // After copying, we expect the framebuffer binding to be updated. |  | 
|  609   EXPECT_CALL(*context_, bindFramebuffer(_, _)) |  | 
|  610       .After(copy1) |  | 
|  611       .After(copy2) |  | 
|  612       .After(copy3); |  | 
|  613   EXPECT_CALL(*context_, framebufferTexture2D(_, _, _, _, _)) |  | 
|  614       .After(copy1) |  | 
|  615       .After(copy2) |  | 
|  616       .After(copy3); |  | 
|  617  |  | 
|  618   output_surface_->RecreateBuffers(); |  | 
|  619   testing::Mock::VerifyAndClearExpectations(context_); |  | 
|  620   testing::Mock::VerifyAndClearExpectations(mock_output_surface_); |  | 
|  621  |  | 
|  622   // All free buffers should be destroyed, the remaining buffers should all |  | 
|  623   // be replaced but still valid. |  | 
|  624   EXPECT_EQ(1U, in_flight_surfaces().size()); |  | 
|  625   EXPECT_EQ(0U, available_surfaces().size()); |  | 
|  626   EXPECT_TRUE(displayed_frame()); |  | 
|  627   EXPECT_TRUE(current_frame()); |  | 
|  628 } |  | 
|  629  |  | 
|  630 TEST_F(BufferQueueTest, AllocateFails) { |  | 
|  631   output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false); |  | 
|  632  |  | 
|  633   // Succeed in the two swaps. |  | 
|  634   output_surface_->BindFramebuffer(); |  | 
|  635   EXPECT_TRUE(current_frame()); |  | 
|  636   output_surface_->SwapBuffers(screen_rect); |  | 
|  637  |  | 
|  638   // Fail the next surface allocation. |  | 
|  639   gpu_memory_buffer_manager_->set_allocate_succeeds(false); |  | 
|  640   output_surface_->BindFramebuffer(); |  | 
|  641   EXPECT_FALSE(current_frame()); |  | 
|  642   output_surface_->SwapBuffers(screen_rect); |  | 
|  643   EXPECT_FALSE(current_frame()); |  | 
|  644  |  | 
|  645   // Try another swap. It should copy the buffer damage from the back |  | 
|  646   // surface. |  | 
|  647   gpu_memory_buffer_manager_->set_allocate_succeeds(true); |  | 
|  648   output_surface_->BindFramebuffer(); |  | 
|  649   unsigned int source_texture = in_flight_surfaces().front()->texture; |  | 
|  650   unsigned int target_texture = current_frame()->texture; |  | 
|  651   testing::Mock::VerifyAndClearExpectations(mock_output_surface_); |  | 
|  652   EXPECT_CALL(*mock_output_surface_, |  | 
|  653               CopyBufferDamage(target_texture, source_texture, small_damage, _)) |  | 
|  654       .Times(1); |  | 
|  655   output_surface_->SwapBuffers(small_damage); |  | 
|  656   testing::Mock::VerifyAndClearExpectations(mock_output_surface_); |  | 
|  657  |  | 
|  658   // Destroy the just-created buffer, and try another swap. The copy should |  | 
|  659   // come from the displayed surface (because both in-flight surfaces are |  | 
|  660   // gone now). |  | 
|  661   output_surface_->PageFlipComplete(); |  | 
|  662   in_flight_surfaces().back().reset(); |  | 
|  663   EXPECT_EQ(2u, in_flight_surfaces().size()); |  | 
|  664   for (auto& surface : in_flight_surfaces()) |  | 
|  665     EXPECT_FALSE(surface); |  | 
|  666   output_surface_->BindFramebuffer(); |  | 
|  667   source_texture = displayed_frame()->texture; |  | 
|  668   EXPECT_TRUE(current_frame()); |  | 
|  669   EXPECT_TRUE(displayed_frame()); |  | 
|  670   target_texture = current_frame()->texture; |  | 
|  671   testing::Mock::VerifyAndClearExpectations(mock_output_surface_); |  | 
|  672   EXPECT_CALL(*mock_output_surface_, |  | 
|  673               CopyBufferDamage(target_texture, source_texture, small_damage, _)) |  | 
|  674       .Times(1); |  | 
|  675   output_surface_->SwapBuffers(small_damage); |  | 
|  676   testing::Mock::VerifyAndClearExpectations(mock_output_surface_); |  | 
|  677 } |  | 
|  678  |  | 
|  679 }  // namespace |  | 
|  680 }  // namespace display_compositor |  | 
| OLD | NEW |