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