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.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
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"
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"
32 #if !defined(GL_DEPTH24_STENCIL8)
33 #define GL_DEPTH24_STENCIL8 0x88F0
36 using ::gfx::MockGLInterface
;
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
;
57 TEST_P(GLES2DecoderManualInitTest
, AsyncPixelTransfers
) {
59 init
.extensions
= "GL_CHROMIUM_async_pixel_transfers";
60 init
.bind_generates_resource
= true;
63 // Set up the texture.
64 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
65 TextureRef
* texture_ref
= GetTexture(client_texture_id_
);
66 Texture
* texture
= texture_ref
->texture();
68 // Set a mock Async delegate
69 StrictMock
<gpu::MockAsyncPixelTransferManager
>* manager
=
70 new StrictMock
<gpu::MockAsyncPixelTransferManager
>;
71 manager
->Initialize(group().texture_manager());
72 decoder_
->SetAsyncPixelTransferManagerForTest(manager
);
73 StrictMock
<gpu::MockAsyncPixelTransferDelegate
>* delegate
= NULL
;
75 // Tex(Sub)Image2D upload commands.
76 AsyncTexImage2DCHROMIUM teximage_cmd
;
77 teximage_cmd
.Init(GL_TEXTURE_2D
,
89 AsyncTexSubImage2DCHROMIUM texsubimage_cmd
;
90 texsubimage_cmd
.Init(GL_TEXTURE_2D
,
103 WaitAsyncTexImage2DCHROMIUM wait_cmd
;
104 wait_cmd
.Init(GL_TEXTURE_2D
);
105 WaitAllAsyncTexImage2DCHROMIUM wait_all_cmd
;
108 // No transfer state exists initially.
110 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
113 base::Closure bind_callback
;
117 // Create transfer state since it doesn't exist.
118 EXPECT_EQ(texture_ref
->num_observers(), 0);
119 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
121 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
122 .RetiresOnSaturation();
123 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
))
124 .WillOnce(SaveArg
<2>(&bind_callback
))
125 .RetiresOnSaturation();
127 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
128 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
131 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
133 EXPECT_TRUE(texture
->IsImmutable());
134 // The texture is safe but the level has not been defined yet.
135 EXPECT_TRUE(texture
->SafeToRenderFrom());
136 GLsizei width
, height
;
137 EXPECT_FALSE(texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &width
, &height
));
138 EXPECT_EQ(texture_ref
->num_observers(), 1);
141 // Async redefinitions are not allowed!
143 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
144 EXPECT_EQ(GL_INVALID_OPERATION
, GetGLError());
147 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
149 EXPECT_TRUE(texture
->IsImmutable());
150 EXPECT_TRUE(texture
->SafeToRenderFrom());
153 // Binding/defining of the async transfer
155 // TODO(epenner): We should check that the manager gets the
156 // BindCompletedAsyncTransfers() call, which is required to
157 // guarantee the delegate calls the bind callback.
159 // Simulate the bind callback from the delegate.
162 // After the bind callback is run, the texture is safe,
163 // and has the right size etc.
164 EXPECT_TRUE(texture
->SafeToRenderFrom());
165 GLsizei width
, height
;
166 EXPECT_TRUE(texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &width
, &height
));
168 EXPECT_EQ(height
, 8);
171 // AsyncTexSubImage2D
172 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
173 decoder_
->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest(
175 EXPECT_EQ(texture_ref
->num_observers(), 0);
176 texture
->SetImmutable(false);
178 // Create transfer state since it doesn't exist.
179 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
181 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
182 .RetiresOnSaturation();
183 EXPECT_CALL(*delegate
, AsyncTexSubImage2D(_
, _
)).RetiresOnSaturation();
185 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
186 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
189 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
191 EXPECT_TRUE(texture
->IsImmutable());
192 EXPECT_TRUE(texture
->SafeToRenderFrom());
195 // No transfer is in progress.
196 EXPECT_CALL(*delegate
, TransferIsInProgress())
197 .WillOnce(Return(false)) // texSubImage validation
198 .WillOnce(Return(false)) // async validation
199 .RetiresOnSaturation();
200 EXPECT_CALL(*delegate
, AsyncTexSubImage2D(_
, _
)).RetiresOnSaturation();
202 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
203 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
206 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
208 EXPECT_TRUE(texture
->IsImmutable());
209 EXPECT_TRUE(texture
->SafeToRenderFrom());
212 // A transfer is still in progress!
213 EXPECT_CALL(*delegate
, TransferIsInProgress())
214 .WillOnce(Return(true))
215 .RetiresOnSaturation();
216 // No async call, command fails.
217 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
218 EXPECT_EQ(GL_INVALID_OPERATION
, GetGLError());
221 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
223 EXPECT_TRUE(texture
->IsImmutable());
224 EXPECT_TRUE(texture
->SafeToRenderFrom());
227 // Delete delegate on DeleteTexture.
229 EXPECT_EQ(texture_ref
->num_observers(), 1);
230 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
231 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
233 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
240 // WaitAsyncTexImage2D
242 // Get a fresh texture since the existing texture cannot be respecified
243 // asynchronously and AsyncTexSubImage2D does not involve binding.
244 EXPECT_CALL(*gl_
, GenTextures(1, _
))
245 .WillOnce(SetArgumentPointee
<1>(kServiceTextureId
));
246 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
247 texture_ref
= GetTexture(client_texture_id_
);
248 texture
= texture_ref
->texture();
249 texture
->SetImmutable(false);
250 // Create transfer state since it doesn't exist.
251 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
253 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
254 .RetiresOnSaturation();
255 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
256 // Start async transfer.
257 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
258 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
261 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
264 EXPECT_TRUE(texture
->IsImmutable());
265 // Wait for completion.
266 EXPECT_CALL(*delegate
, WaitForTransferCompletion());
267 EXPECT_CALL(*manager
, BindCompletedAsyncTransfers());
268 EXPECT_EQ(error::kNoError
, ExecuteCmd(wait_cmd
));
269 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
272 // WaitAllAsyncTexImage2D
273 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
274 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
276 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
282 // Get a fresh texture since the existing texture cannot be respecified
283 // asynchronously and AsyncTexSubImage2D does not involve binding.
284 EXPECT_CALL(*gl_
, GenTextures(1, _
))
285 .WillOnce(SetArgumentPointee
<1>(kServiceTextureId
));
286 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
287 texture_ref
= GetTexture(client_texture_id_
);
288 texture
= texture_ref
->texture();
289 texture
->SetImmutable(false);
290 // Create transfer state since it doesn't exist.
291 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
293 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
294 .RetiresOnSaturation();
295 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
296 // Start async transfer.
297 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
298 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
301 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
304 EXPECT_TRUE(texture
->IsImmutable());
305 // Wait for completion of all uploads.
306 EXPECT_CALL(*manager
, WaitAllAsyncTexImage2D()).RetiresOnSaturation();
307 EXPECT_CALL(*manager
, BindCompletedAsyncTransfers());
308 EXPECT_EQ(error::kNoError
, ExecuteCmd(wait_all_cmd
));
309 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
312 // Remove PixelTransferManager before the decoder destroys.
313 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
314 decoder_
->ResetAsyncPixelTransferManagerForTest();
318 TEST_P(GLES2DecoderManualInitTest
, AsyncPixelTransferManager
) {
320 init
.extensions
= "GL_CHROMIUM_async_pixel_transfers";
321 init
.bind_generates_resource
= true;
324 // Set up the texture.
325 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
326 TextureRef
* texture_ref
= GetTexture(client_texture_id_
);
328 // Set a mock Async delegate.
329 StrictMock
<gpu::MockAsyncPixelTransferManager
>* manager
=
330 new StrictMock
<gpu::MockAsyncPixelTransferManager
>;
331 manager
->Initialize(group().texture_manager());
332 decoder_
->SetAsyncPixelTransferManagerForTest(manager
);
333 StrictMock
<gpu::MockAsyncPixelTransferDelegate
>* delegate
= NULL
;
335 AsyncTexImage2DCHROMIUM teximage_cmd
;
336 teximage_cmd
.Init(GL_TEXTURE_2D
,
349 // No transfer delegate exists initially.
351 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
354 // Create delegate on AsyncTexImage2D.
356 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
358 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
359 .RetiresOnSaturation();
360 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
363 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
364 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
367 // Delegate is cached.
369 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
372 // Delete delegate on manager teardown.
374 EXPECT_EQ(texture_ref
->num_observers(), 1);
375 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
376 decoder_
->ResetAsyncPixelTransferManagerForTest();
379 // Texture ref still valid.
380 EXPECT_EQ(texture_ref
, GetTexture(client_texture_id_
));
381 EXPECT_EQ(texture_ref
->num_observers(), 0);