OLD | NEW |
| (Empty) |
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.bind_generates_resource = true; | |
61 InitDecoder(init); | |
62 | |
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(); | |
67 | |
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; | |
74 | |
75 // Tex(Sub)Image2D upload commands. | |
76 AsyncTexImage2DCHROMIUM teximage_cmd; | |
77 teximage_cmd.Init(GL_TEXTURE_2D, | |
78 0, | |
79 GL_RGBA, | |
80 8, | |
81 8, | |
82 GL_RGBA, | |
83 GL_UNSIGNED_BYTE, | |
84 kSharedMemoryId, | |
85 kSharedMemoryOffset, | |
86 0, | |
87 0, | |
88 0); | |
89 AsyncTexSubImage2DCHROMIUM texsubimage_cmd; | |
90 texsubimage_cmd.Init(GL_TEXTURE_2D, | |
91 0, | |
92 0, | |
93 0, | |
94 8, | |
95 8, | |
96 GL_RGBA, | |
97 GL_UNSIGNED_BYTE, | |
98 kSharedMemoryId, | |
99 kSharedMemoryOffset, | |
100 0, | |
101 0, | |
102 0); | |
103 WaitAsyncTexImage2DCHROMIUM wait_cmd; | |
104 wait_cmd.Init(GL_TEXTURE_2D); | |
105 WaitAllAsyncTexImage2DCHROMIUM wait_all_cmd; | |
106 wait_all_cmd.Init(); | |
107 | |
108 // No transfer state exists initially. | |
109 EXPECT_FALSE( | |
110 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
111 texture_ref)); | |
112 | |
113 base::Closure bind_callback; | |
114 | |
115 // AsyncTexImage2D | |
116 { | |
117 // Create transfer state since it doesn't exist. | |
118 EXPECT_EQ(texture_ref->num_observers(), 0); | |
119 EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) | |
120 .WillOnce(Return( | |
121 delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) | |
122 .RetiresOnSaturation(); | |
123 EXPECT_CALL(*delegate, AsyncTexImage2D(_, _, _)) | |
124 .WillOnce(SaveArg<2>(&bind_callback)) | |
125 .RetiresOnSaturation(); | |
126 // Command succeeds. | |
127 EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd)); | |
128 EXPECT_EQ(GL_NO_ERROR, GetGLError()); | |
129 EXPECT_EQ( | |
130 delegate, | |
131 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
132 texture_ref)); | |
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( | |
138 texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr)); | |
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( | |
168 texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr)); | |
169 EXPECT_EQ(width, 8); | |
170 EXPECT_EQ(height, 8); | |
171 } | |
172 | |
173 // AsyncTexSubImage2D | |
174 EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); | |
175 decoder_->GetAsyncPixelTransferManager()->ClearPixelTransferDelegateForTest( | |
176 texture_ref); | |
177 EXPECT_EQ(texture_ref->num_observers(), 0); | |
178 texture->SetImmutable(false); | |
179 { | |
180 // Create transfer state since it doesn't exist. | |
181 EXPECT_CALL(*manager, CreatePixelTransferDelegateImpl(texture_ref, _)) | |
182 .WillOnce(Return( | |
183 delegate = new StrictMock<gpu::MockAsyncPixelTransferDelegate>)) | |
184 .RetiresOnSaturation(); | |
185 EXPECT_CALL(*delegate, AsyncTexSubImage2D(_, _)).RetiresOnSaturation(); | |
186 // Command succeeds. | |
187 EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); | |
188 EXPECT_EQ(GL_NO_ERROR, GetGLError()); | |
189 EXPECT_EQ( | |
190 delegate, | |
191 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
192 texture_ref)); | |
193 EXPECT_TRUE(texture->IsImmutable()); | |
194 EXPECT_TRUE(texture->SafeToRenderFrom()); | |
195 } | |
196 { | |
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(); | |
203 // Command succeeds. | |
204 EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd)); | |
205 EXPECT_EQ(GL_NO_ERROR, GetGLError()); | |
206 EXPECT_EQ( | |
207 delegate, | |
208 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
209 texture_ref)); | |
210 EXPECT_TRUE(texture->IsImmutable()); | |
211 EXPECT_TRUE(texture->SafeToRenderFrom()); | |
212 } | |
213 { | |
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()); | |
221 EXPECT_EQ( | |
222 delegate, | |
223 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
224 texture_ref)); | |
225 EXPECT_TRUE(texture->IsImmutable()); | |
226 EXPECT_TRUE(texture->SafeToRenderFrom()); | |
227 } | |
228 | |
229 // Delete delegate on DeleteTexture. | |
230 { | |
231 EXPECT_EQ(texture_ref->num_observers(), 1); | |
232 EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); | |
233 DoDeleteTexture(client_texture_id_, kServiceTextureId); | |
234 EXPECT_FALSE( | |
235 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
236 texture_ref)); | |
237 texture = NULL; | |
238 texture_ref = NULL; | |
239 delegate = NULL; | |
240 } | |
241 | |
242 // WaitAsyncTexImage2D | |
243 { | |
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, _)) | |
254 .WillOnce(Return( | |
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()); | |
261 EXPECT_EQ( | |
262 delegate, | |
263 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
264 texture_ref)); | |
265 | |
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()); | |
272 } | |
273 | |
274 // WaitAllAsyncTexImage2D | |
275 EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); | |
276 DoDeleteTexture(client_texture_id_, kServiceTextureId); | |
277 EXPECT_FALSE( | |
278 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
279 texture_ref)); | |
280 texture = NULL; | |
281 texture_ref = NULL; | |
282 delegate = NULL; | |
283 { | |
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, _)) | |
294 .WillOnce(Return( | |
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()); | |
301 EXPECT_EQ( | |
302 delegate, | |
303 decoder_->GetAsyncPixelTransferManager()->GetPixelTransferDelegate( | |
304 texture_ref)); | |
305 | |
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()); | |
312 } | |
313 | |
314 // Remove PixelTransferManager before the decoder destroys. | |
315 EXPECT_CALL(*delegate, Destroy()).RetiresOnSaturation(); | |
316 decoder_->ResetAsyncPixelTransferManagerForTest(); | |
317 manager = NULL; | |
318 } | |
319 | |
320 TEST_P(GLES2DecoderManualInitTest, AsyncPixelTransferManager) { | |
321 InitState init; | |
322 init.extensions = "GL_CHROMIUM_async_pixel_transfers"; | |
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 | |
OLD | NEW |