Home | History | Annotate | Download | only in service
      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 "gpu/command_buffer/service/gles2_cmd_decoder.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "gpu/command_buffer/common/gles2_cmd_format.h"
     10 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
     11 #include "gpu/command_buffer/common/id_allocator.h"
     12 #include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h"
     13 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
     14 #include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h"
     15 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
     16 #include "gpu/command_buffer/service/context_group.h"
     17 #include "gpu/command_buffer/service/context_state.h"
     18 #include "gpu/command_buffer/service/gl_surface_mock.h"
     19 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
     20 
     21 #include "gpu/command_buffer/service/gpu_switches.h"
     22 #include "gpu/command_buffer/service/image_manager.h"
     23 #include "gpu/command_buffer/service/mailbox_manager.h"
     24 #include "gpu/command_buffer/service/mocks.h"
     25 #include "gpu/command_buffer/service/program_manager.h"
     26 #include "gpu/command_buffer/service/test_helper.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 #include "ui/gl/gl_implementation.h"
     29 #include "ui/gl/gl_mock.h"
     30 #include "ui/gl/gl_surface_stub.h"
     31 
     32 #if !defined(GL_DEPTH24_STENCIL8)
     33 #define GL_DEPTH24_STENCIL8 0x88F0
     34 #endif
     35 
     36 using ::gfx::MockGLInterface;
     37 using ::testing::_;
     38 using ::testing::DoAll;
     39 using ::testing::InSequence;
     40 using ::testing::Invoke;
     41 using ::testing::MatcherCast;
     42 using ::testing::Mock;
     43 using ::testing::Pointee;
     44 using ::testing::Return;
     45 using ::testing::SaveArg;
     46 using ::testing::SetArrayArgument;
     47 using ::testing::SetArgumentPointee;
     48 using ::testing::SetArgPointee;
     49 using ::testing::StrEq;
     50 using ::testing::StrictMock;
     51 
     52 namespace gpu {
     53 namespace gles2 {
     54 
     55 using namespace cmds;
     56 
     57 TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
     58   InitState init;
     59   init.extensions = "GL_CHROMIUM_async_pixel_transfers";
     60   init.gl_version = "3.0";
     61   init.bind_generates_resource = true;
     62   InitDecoder(init);
     63 
     64   // Set up the texture.
     65   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
     66   TextureRef* texture_ref = GetTexture(client_texture_id_);
     67   Texture* texture = texture_ref->texture();
     68 
     69   // Set a mock Async delegate
     70   StrictMock<gpu::MockAsyncPixelTransferManager>* manager =
     71       new StrictMock<gpu::MockAsyncPixelTransferManager>;
     72   manager->Initialize(group().texture_manager());
     73   decoder_->SetAsyncPixelTransferManagerForTest(manager);
     74   StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL;
     75 
     76   // Tex(Sub)Image2D upload commands.
     77   AsyncTexImage2DCHROMIUM teximage_cmd;
     78   teximage_cmd.Init(GL_TEXTURE_2D,
     79                     0,
     80                     GL_RGBA,
     81                     8,
     82                     8,
     83                     GL_RGBA,
     84                     GL_UNSIGNED_BYTE,
     85                     kSharedMemoryId,
     86                     kSharedMemoryOffset,
     87                     0,
     88                     0,
     89                     0);
     90   AsyncTexSubImage2DCHROMIUM texsubimage_cmd;
     91   texsubimage_cmd.Init(GL_TEXTURE_2D,
     92                        0,
     93                        0,
     94                        0,
     95                        8,
     96                        8,
     97                        GL_RGBA,
     98                        GL_UNSIGNED_BYTE,
     99                        kSharedMemoryId,
    100                        kSharedMemoryOffset,
    101                        0,
    102                        0,
    103                        0);
    104   WaitAsyncTexImage2DCHROMIUM wait_cmd;
    105   wait_cmd.Init(GL_TEXTURE_2D);
    106   WaitAllAsyncTexImage2DCHROMIUM wait_all_cmd;
    107   wait_all_cmd.Init();
    108 
    109   // No transfer state exists initially.
    110   EXPECT_FALSE(
    111       decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    112           texture_ref));
    113 
    114   base::Closure bind_callback;
    115 
    116   // AsyncTexImage2D
    117   {
    118     // Create transfer state since it doesn't exist.
    119     EXPECT_EQ(texture_ref->num_observers(), 0);
    120     EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _))
    121         .WillOnce(Return(
    122             delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>))
    123         .RetiresOnSaturation();
    124     EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _))
    125         .WillOnce(SaveArg<2>(&bind_callback))
    126         .RetiresOnSaturation();
    127     // Command succeeds.
    128     EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
    129     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    130     EXPECT_EQ(
    131         delegate,
    132         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    133             texture_ref));
    134     EXPECT_TRUE(texture->IsImmutable());
    135     // The texture is safe but the level has not been defined yet.
    136     EXPECT_TRUE(texture->SafeToRenderFrom());
    137     GLsizei width, height;
    138     EXPECT_FALSE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
    139     EXPECT_EQ(texture_ref->num_observers(), 1);
    140   }
    141   {
    142     // Async redefinitions are not allowed!
    143     // Command fails.
    144     EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
    145     EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
    146     EXPECT_EQ(
    147         delegate,
    148         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    149             texture_ref));
    150     EXPECT_TRUE(texture->IsImmutable());
    151     EXPECT_TRUE(texture->SafeToRenderFrom());
    152   }
    153 
    154   // Binding/defining of the async transfer
    155   {
    156     // TODO(epenner): We should check that the manager gets the
    157     // BindCompletedAsyncTransfers() call, which is required to
    158     // guarantee the delegate calls the bind callback.
    159 
    160     // Simulate the bind callback from the delegate.
    161     bind_callback.Run();
    162 
    163     // After the bind callback is run, the texture is safe,
    164     // and has the right size etc.
    165     EXPECT_TRUE(texture->SafeToRenderFrom());
    166     GLsizei width, height;
    167     EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
    168     EXPECT_EQ(width, 8);
    169     EXPECT_EQ(height, 8);
    170   }
    171 
    172   // AsyncTexSubImage2D
    173   EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation();
    174   decoder_->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest(
    175       texture_ref);
    176   EXPECT_EQ(texture_ref->num_observers(), 0);
    177   texture->SetImmutable(false);
    178   {
    179     // Create transfer state since it doesn't exist.
    180     EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _))
    181         .WillOnce(Return(
    182             delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>))
    183         .RetiresOnSaturation();
    184     EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)).RetiresOnSaturation();
    185     // Command succeeds.
    186     EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
    187     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    188     EXPECT_EQ(
    189         delegate,
    190         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    191             texture_ref));
    192     EXPECT_TRUE(texture->IsImmutable());
    193     EXPECT_TRUE(texture->SafeToRenderFrom());
    194   }
    195   {
    196     // No transfer is in progress.
    197     EXPECT_CALL(*delegate, TransferIsInProgress())
    198         .WillOnce(Return(false))  // texSubImage validation
    199         .WillOnce(Return(false))  // async validation
    200         .RetiresOnSaturation();
    201     EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)).RetiresOnSaturation();
    202     // Command succeeds.
    203     EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
    204     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    205     EXPECT_EQ(
    206         delegate,
    207         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    208             texture_ref));
    209     EXPECT_TRUE(texture->IsImmutable());
    210     EXPECT_TRUE(texture->SafeToRenderFrom());
    211   }
    212   {
    213     // A transfer is still in progress!
    214     EXPECT_CALL(*delegate, TransferIsInProgress())
    215         .WillOnce(Return(true))
    216         .RetiresOnSaturation();
    217     // No async call, command fails.
    218     EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
    219     EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
    220     EXPECT_EQ(
    221         delegate,
    222         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    223             texture_ref));
    224     EXPECT_TRUE(texture->IsImmutable());
    225     EXPECT_TRUE(texture->SafeToRenderFrom());
    226   }
    227 
    228   // Delete delegate on DeleteTexture.
    229   {
    230     EXPECT_EQ(texture_ref->num_observers(), 1);
    231     EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation();
    232     DoDeleteTexture(client_texture_id_, kServiceTextureId);
    233     EXPECT_FALSE(
    234         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    235             texture_ref));
    236     texture = NULL;
    237     texture_ref = NULL;
    238     delegate = NULL;
    239   }
    240 
    241   // WaitAsyncTexImage2D
    242   {
    243     // Get a fresh texture since the existing texture cannot be respecified
    244     // asynchronously and AsyncTexSubImage2D does not involve binding.
    245     EXPECT_CALL(*gl_, GenTextures(1, _))
    246         .WillOnce(SetArgumentPointee<1>(kServiceTextureId));
    247     DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
    248     texture_ref = GetTexture(client_texture_id_);
    249     texture = texture_ref->texture();
    250     texture->SetImmutable(false);
    251     // Create transfer state since it doesn't exist.
    252     EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _))
    253         .WillOnce(Return(
    254             delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>))
    255         .RetiresOnSaturation();
    256     EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation();
    257     // Start async transfer.
    258     EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
    259     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    260     EXPECT_EQ(
    261         delegate,
    262         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    263             texture_ref));
    264 
    265     EXPECT_TRUE(texture->IsImmutable());
    266     // Wait for completion.
    267     EXPECT_CALL(*delegate, WaitForTransferCompletion());
    268     EXPECT_CALL(*manager, BindCompletedAsyncTransfers());
    269     EXPECT_EQ(error::kNoError, ExecuteCmd(wait_cmd));
    270     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    271   }
    272 
    273   // WaitAllAsyncTexImage2D
    274   EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation();
    275   DoDeleteTexture(client_texture_id_, kServiceTextureId);
    276   EXPECT_FALSE(
    277       decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    278           texture_ref));
    279   texture = NULL;
    280   texture_ref = NULL;
    281   delegate = NULL;
    282   {
    283     // Get a fresh texture since the existing texture cannot be respecified
    284     // asynchronously and AsyncTexSubImage2D does not involve binding.
    285     EXPECT_CALL(*gl_, GenTextures(1, _))
    286         .WillOnce(SetArgumentPointee<1>(kServiceTextureId));
    287     DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
    288     texture_ref = GetTexture(client_texture_id_);
    289     texture = texture_ref->texture();
    290     texture->SetImmutable(false);
    291     // Create transfer state since it doesn't exist.
    292     EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _))
    293         .WillOnce(Return(
    294             delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>))
    295         .RetiresOnSaturation();
    296     EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation();
    297     // Start async transfer.
    298     EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
    299     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    300     EXPECT_EQ(
    301         delegate,
    302         decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    303             texture_ref));
    304 
    305     EXPECT_TRUE(texture->IsImmutable());
    306     // Wait for completion of all uploads.
    307     EXPECT_CALL(*manager, WaitAllAsyncTexImage2D()).RetiresOnSaturation();
    308     EXPECT_CALL(*manager, BindCompletedAsyncTransfers());
    309     EXPECT_EQ(error::kNoError, ExecuteCmd(wait_all_cmd));
    310     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    311   }
    312 
    313   // Remove PixelTransferManager before the decoder destroys.
    314   EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation();
    315   decoder_->ResetAsyncPixelTransferManagerForTest();
    316   manager = NULL;
    317 }
    318 
    319 TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransferManager) {
    320   InitState init;
    321   init.extensions = "GL_CHROMIUM_async_pixel_transfers";
    322   init.gl_version = "3.0";
    323   init.bind_generates_resource = true;
    324   InitDecoder(init);
    325 
    326   // Set up the texture.
    327   DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
    328   TextureRef* texture_ref = GetTexture(client_texture_id_);
    329 
    330   // Set a mock Async delegate.
    331   StrictMock<gpu::MockAsyncPixelTransferManager>* manager =
    332       new StrictMock<gpu::MockAsyncPixelTransferManager>;
    333   manager->Initialize(group().texture_manager());
    334   decoder_->SetAsyncPixelTransferManagerForTest(manager);
    335   StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate = NULL;
    336 
    337   AsyncTexImage2DCHROMIUM teximage_cmd;
    338   teximage_cmd.Init(GL_TEXTURE_2D,
    339                     0,
    340                     GL_RGBA,
    341                     8,
    342                     8,
    343                     GL_RGBA,
    344                     GL_UNSIGNED_BYTE,
    345                     kSharedMemoryId,
    346                     kSharedMemoryOffset,
    347                     0,
    348                     0,
    349                     0);
    350 
    351   // No transfer delegate exists initially.
    352   EXPECT_FALSE(
    353       decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    354           texture_ref));
    355 
    356   // Create delegate on AsyncTexImage2D.
    357   {
    358     EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _))
    359         .WillOnce(Return(
    360             delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>))
    361         .RetiresOnSaturation();
    362     EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)).RetiresOnSaturation();
    363 
    364     // Command succeeds.
    365     EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
    366     EXPECT_EQ(GL_NO_ERROR, GetGLError());
    367   }
    368 
    369   // Delegate is cached.
    370   EXPECT_EQ(delegate,
    371             decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
    372                 texture_ref));
    373 
    374   // Delete delegate on manager teardown.
    375   {
    376     EXPECT_EQ(texture_ref->num_observers(), 1);
    377     EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation();
    378     decoder_->ResetAsyncPixelTransferManagerForTest();
    379     manager = NULL;
    380 
    381     // Texture ref still valid.
    382     EXPECT_EQ(texture_ref, GetTexture(client_texture_id_));
    383     EXPECT_EQ(texture_ref->num_observers(), 0);
    384   }
    385 }
    386 
    387 }  // namespace gles2
    388 }  // namespace gpu
    389