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 36using ::gfx::MockGLInterface; 37using ::testing::_; 38using ::testing::DoAll; 39using ::testing::InSequence; 40using ::testing::Invoke; 41using ::testing::MatcherCast; 42using ::testing::Mock; 43using ::testing::Pointee; 44using ::testing::Return; 45using ::testing::SaveArg; 46using ::testing::SetArrayArgument; 47using ::testing::SetArgumentPointee; 48using ::testing::SetArgPointee; 49using ::testing::StrEq; 50using ::testing::StrictMock; 51 52namespace gpu { 53namespace gles2 { 54 55using namespace cmds; 56 57TEST_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 319TEST_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