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
.gl_version
= "3.0";
61 init
.bind_generates_resource
= true;
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();
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
;
76 // Tex(Sub)Image2D upload commands.
77 AsyncTexImage2DCHROMIUM teximage_cmd
;
78 teximage_cmd
.Init(GL_TEXTURE_2D
,
90 AsyncTexSubImage2DCHROMIUM texsubimage_cmd
;
91 texsubimage_cmd
.Init(GL_TEXTURE_2D
,
104 WaitAsyncTexImage2DCHROMIUM wait_cmd
;
105 wait_cmd
.Init(GL_TEXTURE_2D
);
106 WaitAllAsyncTexImage2DCHROMIUM wait_all_cmd
;
109 // No transfer state exists initially.
111 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
114 base::Closure bind_callback
;
118 // Create transfer state since it doesn't exist.
119 EXPECT_EQ(texture_ref
->num_observers(), 0);
120 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
122 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
123 .RetiresOnSaturation();
124 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
))
125 .WillOnce(SaveArg
<2>(&bind_callback
))
126 .RetiresOnSaturation();
128 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
129 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
132 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
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);
142 // Async redefinitions are not allowed!
144 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
145 EXPECT_EQ(GL_INVALID_OPERATION
, GetGLError());
148 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
150 EXPECT_TRUE(texture
->IsImmutable());
151 EXPECT_TRUE(texture
->SafeToRenderFrom());
154 // Binding/defining of the async transfer
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.
160 // Simulate the bind callback from the delegate.
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
));
169 EXPECT_EQ(height
, 8);
172 // AsyncTexSubImage2D
173 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
174 decoder_
->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest(
176 EXPECT_EQ(texture_ref
->num_observers(), 0);
177 texture
->SetImmutable(false);
179 // Create transfer state since it doesn't exist.
180 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
182 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
183 .RetiresOnSaturation();
184 EXPECT_CALL(*delegate
, AsyncTexSubImage2D(_
, _
)).RetiresOnSaturation();
186 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
187 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
190 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
192 EXPECT_TRUE(texture
->IsImmutable());
193 EXPECT_TRUE(texture
->SafeToRenderFrom());
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();
203 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
204 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
207 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
209 EXPECT_TRUE(texture
->IsImmutable());
210 EXPECT_TRUE(texture
->SafeToRenderFrom());
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());
222 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
224 EXPECT_TRUE(texture
->IsImmutable());
225 EXPECT_TRUE(texture
->SafeToRenderFrom());
228 // Delete delegate on DeleteTexture.
230 EXPECT_EQ(texture_ref
->num_observers(), 1);
231 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
232 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
234 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
241 // WaitAsyncTexImage2D
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
, _
))
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());
262 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
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());
273 // WaitAllAsyncTexImage2D
274 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
275 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
277 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
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
, _
))
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());
302 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
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());
313 // Remove PixelTransferManager before the decoder destroys.
314 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
315 decoder_
->ResetAsyncPixelTransferManagerForTest();
319 TEST_P(GLES2DecoderManualInitTest
, AsyncPixelTransferManager
) {
321 init
.extensions
= "GL_CHROMIUM_async_pixel_transfers";
322 init
.gl_version
= "3.0";
323 init
.bind_generates_resource
= true;
326 // Set up the texture.
327 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
328 TextureRef
* texture_ref
= GetTexture(client_texture_id_
);
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
;
337 AsyncTexImage2DCHROMIUM teximage_cmd
;
338 teximage_cmd
.Init(GL_TEXTURE_2D
,
351 // No transfer delegate exists initially.
353 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
356 // Create delegate on AsyncTexImage2D.
358 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
360 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
361 .RetiresOnSaturation();
362 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
365 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
366 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
369 // Delegate is cached.
371 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
374 // Delete delegate on manager teardown.
376 EXPECT_EQ(texture_ref
->num_observers(), 1);
377 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
378 decoder_
->ResetAsyncPixelTransferManagerForTest();
381 // Texture ref still valid.
382 EXPECT_EQ(texture_ref
, GetTexture(client_texture_id_
));
383 EXPECT_EQ(texture_ref
->num_observers(), 0);