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
;
138 texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &width
, &height
, nullptr));
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
;
168 texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &width
, &height
, nullptr));
170 EXPECT_EQ(height
, 8);
173 // AsyncTexSubImage2D
174 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
175 decoder_
->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest(
177 EXPECT_EQ(texture_ref
->num_observers(), 0);
178 texture
->SetImmutable(false);
180 // Create transfer state since it doesn't exist.
181 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
183 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
184 .RetiresOnSaturation();
185 EXPECT_CALL(*delegate
, AsyncTexSubImage2D(_
, _
)).RetiresOnSaturation();
187 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
188 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
191 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
193 EXPECT_TRUE(texture
->IsImmutable());
194 EXPECT_TRUE(texture
->SafeToRenderFrom());
197 // No transfer is in progress.
198 EXPECT_CALL(*delegate
, TransferIsInProgress())
199 .WillOnce(Return(false)) // texSubImage validation
200 .WillOnce(Return(false)) // async validation
201 .RetiresOnSaturation();
202 EXPECT_CALL(*delegate
, AsyncTexSubImage2D(_
, _
)).RetiresOnSaturation();
204 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
205 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
208 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
210 EXPECT_TRUE(texture
->IsImmutable());
211 EXPECT_TRUE(texture
->SafeToRenderFrom());
214 // A transfer is still in progress!
215 EXPECT_CALL(*delegate
, TransferIsInProgress())
216 .WillOnce(Return(true))
217 .RetiresOnSaturation();
218 // No async call, command fails.
219 EXPECT_EQ(error::kNoError
, ExecuteCmd(texsubimage_cmd
));
220 EXPECT_EQ(GL_INVALID_OPERATION
, GetGLError());
223 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
225 EXPECT_TRUE(texture
->IsImmutable());
226 EXPECT_TRUE(texture
->SafeToRenderFrom());
229 // Delete delegate on DeleteTexture.
231 EXPECT_EQ(texture_ref
->num_observers(), 1);
232 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
233 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
235 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
242 // WaitAsyncTexImage2D
244 // Get a fresh texture since the existing texture cannot be respecified
245 // asynchronously and AsyncTexSubImage2D does not involve binding.
246 EXPECT_CALL(*gl_
, GenTextures(1, _
))
247 .WillOnce(SetArgumentPointee
<1>(kServiceTextureId
));
248 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
249 texture_ref
= GetTexture(client_texture_id_
);
250 texture
= texture_ref
->texture();
251 texture
->SetImmutable(false);
252 // Create transfer state since it doesn't exist.
253 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
255 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
256 .RetiresOnSaturation();
257 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
258 // Start async transfer.
259 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
260 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
263 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
266 EXPECT_TRUE(texture
->IsImmutable());
267 // Wait for completion.
268 EXPECT_CALL(*delegate
, WaitForTransferCompletion());
269 EXPECT_CALL(*manager
, BindCompletedAsyncTransfers());
270 EXPECT_EQ(error::kNoError
, ExecuteCmd(wait_cmd
));
271 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
274 // WaitAllAsyncTexImage2D
275 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
276 DoDeleteTexture(client_texture_id_
, kServiceTextureId
);
278 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
284 // Get a fresh texture since the existing texture cannot be respecified
285 // asynchronously and AsyncTexSubImage2D does not involve binding.
286 EXPECT_CALL(*gl_
, GenTextures(1, _
))
287 .WillOnce(SetArgumentPointee
<1>(kServiceTextureId
));
288 DoBindTexture(GL_TEXTURE_2D
, client_texture_id_
, kServiceTextureId
);
289 texture_ref
= GetTexture(client_texture_id_
);
290 texture
= texture_ref
->texture();
291 texture
->SetImmutable(false);
292 // Create transfer state since it doesn't exist.
293 EXPECT_CALL(*manager
, CreatePixelTransferDelegateImpl(texture_ref
, _
))
295 delegate
= new StrictMock
<gpu::MockAsyncPixelTransferDelegate
>))
296 .RetiresOnSaturation();
297 EXPECT_CALL(*delegate
, AsyncTexImage2D(_
, _
, _
)).RetiresOnSaturation();
298 // Start async transfer.
299 EXPECT_EQ(error::kNoError
, ExecuteCmd(teximage_cmd
));
300 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
303 decoder_
->GetAsyncPixelTransferManager()->GetPixelTransferDelegate(
306 EXPECT_TRUE(texture
->IsImmutable());
307 // Wait for completion of all uploads.
308 EXPECT_CALL(*manager
, WaitAllAsyncTexImage2D()).RetiresOnSaturation();
309 EXPECT_CALL(*manager
, BindCompletedAsyncTransfers());
310 EXPECT_EQ(error::kNoError
, ExecuteCmd(wait_all_cmd
));
311 EXPECT_EQ(GL_NO_ERROR
, GetGLError());
314 // Remove PixelTransferManager before the decoder destroys.
315 EXPECT_CALL(*delegate
, Destroy()).RetiresOnSaturation();
316 decoder_
->ResetAsyncPixelTransferManagerForTest();
320 TEST_P(GLES2DecoderManualInitTest
, AsyncPixelTransferManager
) {
322 init
.extensions
= "GL_CHROMIUM_async_pixel_transfers";
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);