OLD | NEW |
| (Empty) |
1 // Copyright 2012 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 "cc/resources/resource_provider.h" | |
6 | |
7 #include <algorithm> | |
8 #include <map> | |
9 #include <set> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/containers/hash_tables.h" | |
13 #include "base/logging.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "cc/base/blocking_task_runner.h" | |
16 #include "cc/base/scoped_ptr_deque.h" | |
17 #include "cc/output/output_surface.h" | |
18 #include "cc/resources/returned_resource.h" | |
19 #include "cc/resources/shared_bitmap_manager.h" | |
20 #include "cc/resources/single_release_callback.h" | |
21 #include "cc/test/fake_output_surface.h" | |
22 #include "cc/test/fake_output_surface_client.h" | |
23 #include "cc/test/test_gpu_memory_buffer_manager.h" | |
24 #include "cc/test/test_shared_bitmap_manager.h" | |
25 #include "cc/test/test_texture.h" | |
26 #include "cc/test/test_web_graphics_context_3d.h" | |
27 #include "gpu/GLES2/gl2extchromium.h" | |
28 #include "testing/gmock/include/gmock/gmock.h" | |
29 #include "testing/gtest/include/gtest/gtest.h" | |
30 #include "third_party/khronos/GLES2/gl2.h" | |
31 #include "third_party/khronos/GLES2/gl2ext.h" | |
32 #include "ui/gfx/geometry/rect.h" | |
33 #include "ui/gfx/gpu_memory_buffer.h" | |
34 | |
35 using testing::Mock; | |
36 using testing::NiceMock; | |
37 using testing::Return; | |
38 using testing::SetArgPointee; | |
39 using testing::StrictMock; | |
40 using testing::_; | |
41 | |
42 namespace cc { | |
43 namespace { | |
44 | |
45 static void EmptyReleaseCallback(uint32 sync_point, | |
46 bool lost_resource, | |
47 BlockingTaskRunner* main_thread_task_runner) { | |
48 } | |
49 | |
50 static void ReleaseCallback( | |
51 uint32* release_sync_point, | |
52 bool* release_lost_resource, | |
53 BlockingTaskRunner** release_main_thread_task_runner, | |
54 uint32 sync_point, | |
55 bool lost_resource, | |
56 BlockingTaskRunner* main_thread_task_runner) { | |
57 *release_sync_point = sync_point; | |
58 *release_lost_resource = lost_resource; | |
59 *release_main_thread_task_runner = main_thread_task_runner; | |
60 } | |
61 | |
62 static void SharedBitmapReleaseCallback( | |
63 scoped_ptr<SharedBitmap> bitmap, | |
64 uint32 sync_point, | |
65 bool lost_resource, | |
66 BlockingTaskRunner* main_thread_task_runner) { | |
67 } | |
68 | |
69 static void ReleaseSharedBitmapCallback( | |
70 scoped_ptr<SharedBitmap> shared_bitmap, | |
71 bool* release_called, | |
72 uint32* release_sync_point, | |
73 bool* lost_resource_result, | |
74 uint32 sync_point, | |
75 bool lost_resource, | |
76 BlockingTaskRunner* main_thread_task_runner) { | |
77 *release_called = true; | |
78 *release_sync_point = sync_point; | |
79 *lost_resource_result = lost_resource; | |
80 } | |
81 | |
82 static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap( | |
83 SharedBitmapManager* manager, | |
84 const gfx::Size& size, | |
85 uint32_t value) { | |
86 scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size); | |
87 CHECK(shared_bitmap); | |
88 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels()); | |
89 CHECK(pixels); | |
90 std::fill_n(pixels, size.GetArea(), value); | |
91 return shared_bitmap.Pass(); | |
92 } | |
93 | |
94 class TextureStateTrackingContext : public TestWebGraphicsContext3D { | |
95 public: | |
96 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); | |
97 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); | |
98 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point)); | |
99 MOCK_METHOD0(insertSyncPoint, GLuint(void)); | |
100 MOCK_METHOD3(produceTextureDirectCHROMIUM, | |
101 void(GLuint texture, GLenum target, const GLbyte* mailbox)); | |
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM, | |
103 unsigned(GLenum target, const GLbyte* mailbox)); | |
104 | |
105 // Force all textures to be consecutive numbers starting at "1", | |
106 // so we easily can test for them. | |
107 GLuint NextTextureId() override { | |
108 base::AutoLock lock(namespace_->lock); | |
109 return namespace_->next_texture_id++; | |
110 } | |
111 void RetireTextureId(GLuint) override {} | |
112 }; | |
113 | |
114 // Shared data between multiple ResourceProviderContext. This contains mailbox | |
115 // contents as well as information about sync points. | |
116 class ContextSharedData { | |
117 public: | |
118 static scoped_ptr<ContextSharedData> Create() { | |
119 return make_scoped_ptr(new ContextSharedData()); | |
120 } | |
121 | |
122 uint32 InsertSyncPoint() { return next_sync_point_++; } | |
123 | |
124 void GenMailbox(GLbyte* mailbox) { | |
125 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM); | |
126 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_)); | |
127 ++next_mailbox_; | |
128 } | |
129 | |
130 void ProduceTexture(const GLbyte* mailbox_name, | |
131 uint32 sync_point, | |
132 scoped_refptr<TestTexture> texture) { | |
133 unsigned mailbox = 0; | |
134 memcpy(&mailbox, mailbox_name, sizeof(mailbox)); | |
135 ASSERT_TRUE(mailbox && mailbox < next_mailbox_); | |
136 textures_[mailbox] = texture; | |
137 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point); | |
138 sync_point_for_mailbox_[mailbox] = sync_point; | |
139 } | |
140 | |
141 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name, | |
142 uint32 sync_point) { | |
143 unsigned mailbox = 0; | |
144 memcpy(&mailbox, mailbox_name, sizeof(mailbox)); | |
145 DCHECK(mailbox && mailbox < next_mailbox_); | |
146 | |
147 // If the latest sync point the context has waited on is before the sync | |
148 // point for when the mailbox was set, pretend we never saw that | |
149 // ProduceTexture. | |
150 if (sync_point_for_mailbox_[mailbox] > sync_point) { | |
151 NOTREACHED(); | |
152 return scoped_refptr<TestTexture>(); | |
153 } | |
154 return textures_[mailbox]; | |
155 } | |
156 | |
157 private: | |
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {} | |
159 | |
160 uint32 next_sync_point_; | |
161 unsigned next_mailbox_; | |
162 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap; | |
163 TextureMap textures_; | |
164 base::hash_map<unsigned, uint32> sync_point_for_mailbox_; | |
165 }; | |
166 | |
167 class ResourceProviderContext : public TestWebGraphicsContext3D { | |
168 public: | |
169 static scoped_ptr<ResourceProviderContext> Create( | |
170 ContextSharedData* shared_data) { | |
171 return make_scoped_ptr(new ResourceProviderContext(shared_data)); | |
172 } | |
173 | |
174 GLuint insertSyncPoint() override { | |
175 uint32 sync_point = shared_data_->InsertSyncPoint(); | |
176 // Commit the produceTextureCHROMIUM calls at this point, so that | |
177 // they're associated with the sync point. | |
178 for (PendingProduceTextureList::iterator it = | |
179 pending_produce_textures_.begin(); | |
180 it != pending_produce_textures_.end(); | |
181 ++it) { | |
182 shared_data_->ProduceTexture( | |
183 (*it)->mailbox, sync_point, (*it)->texture); | |
184 } | |
185 pending_produce_textures_.clear(); | |
186 return sync_point; | |
187 } | |
188 | |
189 void waitSyncPoint(GLuint sync_point) override { | |
190 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_); | |
191 } | |
192 | |
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_; } | |
194 | |
195 void texStorage2DEXT(GLenum target, | |
196 GLint levels, | |
197 GLuint internalformat, | |
198 GLint width, | |
199 GLint height) override { | |
200 CheckTextureIsBound(target); | |
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); | |
202 ASSERT_EQ(1, levels); | |
203 GLenum format = GL_RGBA; | |
204 switch (internalformat) { | |
205 case GL_RGBA8_OES: | |
206 break; | |
207 case GL_BGRA8_EXT: | |
208 format = GL_BGRA_EXT; | |
209 break; | |
210 default: | |
211 NOTREACHED(); | |
212 } | |
213 AllocateTexture(gfx::Size(width, height), format); | |
214 } | |
215 | |
216 void texImage2D(GLenum target, | |
217 GLint level, | |
218 GLenum internalformat, | |
219 GLsizei width, | |
220 GLsizei height, | |
221 GLint border, | |
222 GLenum format, | |
223 GLenum type, | |
224 const void* pixels) override { | |
225 CheckTextureIsBound(target); | |
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); | |
227 ASSERT_FALSE(level); | |
228 ASSERT_EQ(internalformat, format); | |
229 ASSERT_FALSE(border); | |
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); | |
231 AllocateTexture(gfx::Size(width, height), format); | |
232 if (pixels) | |
233 SetPixels(0, 0, width, height, pixels); | |
234 } | |
235 | |
236 void texSubImage2D(GLenum target, | |
237 GLint level, | |
238 GLint xoffset, | |
239 GLint yoffset, | |
240 GLsizei width, | |
241 GLsizei height, | |
242 GLenum format, | |
243 GLenum type, | |
244 const void* pixels) override { | |
245 CheckTextureIsBound(target); | |
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); | |
247 ASSERT_FALSE(level); | |
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); | |
249 { | |
250 base::AutoLock lock_for_texture_access(namespace_->lock); | |
251 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format); | |
252 } | |
253 ASSERT_TRUE(pixels); | |
254 SetPixels(xoffset, yoffset, width, height, pixels); | |
255 } | |
256 | |
257 void genMailboxCHROMIUM(GLbyte* mailbox) override { | |
258 return shared_data_->GenMailbox(mailbox); | |
259 } | |
260 | |
261 void produceTextureDirectCHROMIUM(GLuint texture, | |
262 GLenum target, | |
263 const GLbyte* mailbox) override { | |
264 // Delay moving the texture into the mailbox until the next | |
265 // InsertSyncPoint, so that it is not visible to other contexts that | |
266 // haven't waited on that sync point. | |
267 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture); | |
268 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); | |
269 base::AutoLock lock_for_texture_access(namespace_->lock); | |
270 pending->texture = UnboundTexture(texture); | |
271 pending_produce_textures_.push_back(pending.Pass()); | |
272 } | |
273 | |
274 GLuint createAndConsumeTextureCHROMIUM(GLenum target, | |
275 const GLbyte* mailbox) override { | |
276 GLuint texture_id = createTexture(); | |
277 base::AutoLock lock_for_texture_access(namespace_->lock); | |
278 scoped_refptr<TestTexture> texture = | |
279 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_); | |
280 namespace_->textures.Replace(texture_id, texture); | |
281 return texture_id; | |
282 } | |
283 | |
284 void GetPixels(const gfx::Size& size, | |
285 ResourceFormat format, | |
286 uint8_t* pixels) { | |
287 CheckTextureIsBound(GL_TEXTURE_2D); | |
288 base::AutoLock lock_for_texture_access(namespace_->lock); | |
289 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); | |
290 ASSERT_EQ(texture->size, size); | |
291 ASSERT_EQ(texture->format, format); | |
292 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format)); | |
293 } | |
294 | |
295 protected: | |
296 explicit ResourceProviderContext(ContextSharedData* shared_data) | |
297 : shared_data_(shared_data), | |
298 last_waited_sync_point_(0) {} | |
299 | |
300 private: | |
301 void AllocateTexture(const gfx::Size& size, GLenum format) { | |
302 CheckTextureIsBound(GL_TEXTURE_2D); | |
303 ResourceFormat texture_format = RGBA_8888; | |
304 switch (format) { | |
305 case GL_RGBA: | |
306 texture_format = RGBA_8888; | |
307 break; | |
308 case GL_BGRA_EXT: | |
309 texture_format = BGRA_8888; | |
310 break; | |
311 } | |
312 base::AutoLock lock_for_texture_access(namespace_->lock); | |
313 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format); | |
314 } | |
315 | |
316 void SetPixels(int xoffset, | |
317 int yoffset, | |
318 int width, | |
319 int height, | |
320 const void* pixels) { | |
321 CheckTextureIsBound(GL_TEXTURE_2D); | |
322 base::AutoLock lock_for_texture_access(namespace_->lock); | |
323 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); | |
324 ASSERT_TRUE(texture->data.get()); | |
325 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width()); | |
326 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height()); | |
327 ASSERT_TRUE(pixels); | |
328 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format); | |
329 size_t out_pitch = | |
330 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format); | |
331 uint8_t* dest = texture->data.get() + yoffset * out_pitch + | |
332 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format); | |
333 const uint8_t* src = static_cast<const uint8_t*>(pixels); | |
334 for (int i = 0; i < height; ++i) { | |
335 memcpy(dest, src, in_pitch); | |
336 dest += out_pitch; | |
337 src += in_pitch; | |
338 } | |
339 } | |
340 | |
341 struct PendingProduceTexture { | |
342 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; | |
343 scoped_refptr<TestTexture> texture; | |
344 }; | |
345 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList; | |
346 ContextSharedData* shared_data_; | |
347 GLuint last_waited_sync_point_; | |
348 PendingProduceTextureList pending_produce_textures_; | |
349 }; | |
350 | |
351 void GetResourcePixels(ResourceProvider* resource_provider, | |
352 ResourceProviderContext* context, | |
353 ResourceProvider::ResourceId id, | |
354 const gfx::Size& size, | |
355 ResourceFormat format, | |
356 uint8_t* pixels) { | |
357 resource_provider->WaitSyncPointIfNeeded(id); | |
358 switch (resource_provider->default_resource_type()) { | |
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: { | |
360 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id); | |
361 ASSERT_NE(0U, lock_gl.texture_id()); | |
362 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id()); | |
363 context->GetPixels(size, format, pixels); | |
364 break; | |
365 } | |
366 case ResourceProvider::RESOURCE_TYPE_BITMAP: { | |
367 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider, | |
368 id); | |
369 memcpy(pixels, | |
370 lock_software.sk_bitmap()->getPixels(), | |
371 lock_software.sk_bitmap()->getSize()); | |
372 break; | |
373 } | |
374 case ResourceProvider::RESOURCE_TYPE_INVALID: | |
375 NOTREACHED(); | |
376 break; | |
377 } | |
378 } | |
379 | |
380 class ResourceProviderTest | |
381 : public testing::TestWithParam<ResourceProvider::ResourceType> { | |
382 public: | |
383 ResourceProviderTest() | |
384 : shared_data_(ContextSharedData::Create()), | |
385 context3d_(NULL), | |
386 child_context_(NULL), | |
387 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) { | |
388 switch (GetParam()) { | |
389 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: { | |
390 scoped_ptr<ResourceProviderContext> context3d( | |
391 ResourceProviderContext::Create(shared_data_.get())); | |
392 context3d_ = context3d.get(); | |
393 | |
394 scoped_refptr<TestContextProvider> context_provider = | |
395 TestContextProvider::Create(context3d.Pass()); | |
396 | |
397 output_surface_ = FakeOutputSurface::Create3d(context_provider); | |
398 | |
399 scoped_ptr<ResourceProviderContext> child_context_owned = | |
400 ResourceProviderContext::Create(shared_data_.get()); | |
401 child_context_ = child_context_owned.get(); | |
402 child_output_surface_ = | |
403 FakeOutputSurface::Create3d(child_context_owned.Pass()); | |
404 break; | |
405 } | |
406 case ResourceProvider::RESOURCE_TYPE_BITMAP: | |
407 output_surface_ = FakeOutputSurface::CreateSoftware( | |
408 make_scoped_ptr(new SoftwareOutputDevice)); | |
409 child_output_surface_ = FakeOutputSurface::CreateSoftware( | |
410 make_scoped_ptr(new SoftwareOutputDevice)); | |
411 break; | |
412 case ResourceProvider::RESOURCE_TYPE_INVALID: | |
413 NOTREACHED(); | |
414 break; | |
415 } | |
416 CHECK(output_surface_->BindToClient(&output_surface_client_)); | |
417 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_)); | |
418 | |
419 shared_bitmap_manager_.reset(new TestSharedBitmapManager); | |
420 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager); | |
421 | |
422 resource_provider_ = | |
423 ResourceProvider::Create(output_surface_.get(), | |
424 shared_bitmap_manager_.get(), | |
425 gpu_memory_buffer_manager_.get(), | |
426 main_thread_task_runner_.get(), | |
427 0, | |
428 false, | |
429 1); | |
430 child_resource_provider_ = | |
431 ResourceProvider::Create(child_output_surface_.get(), | |
432 shared_bitmap_manager_.get(), | |
433 gpu_memory_buffer_manager_.get(), | |
434 main_thread_task_runner_.get(), | |
435 0, | |
436 false, | |
437 1); | |
438 } | |
439 | |
440 static void CollectResources(ReturnedResourceArray* array, | |
441 const ReturnedResourceArray& returned, | |
442 BlockingTaskRunner* main_thread_task_runner) { | |
443 array->insert(array->end(), returned.begin(), returned.end()); | |
444 } | |
445 | |
446 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) { | |
447 return base::Bind(&ResourceProviderTest::CollectResources, array); | |
448 } | |
449 | |
450 static void SetResourceFilter(ResourceProvider* resource_provider, | |
451 ResourceProvider::ResourceId id, | |
452 GLenum filter) { | |
453 ResourceProvider::ScopedSamplerGL sampler( | |
454 resource_provider, id, GL_TEXTURE_2D, filter); | |
455 } | |
456 | |
457 ResourceProviderContext* context() { return context3d_; } | |
458 | |
459 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point, | |
460 bool* lost_resource, | |
461 bool* release_called, | |
462 uint32* sync_point) { | |
463 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
464 unsigned texture = child_context_->createTexture(); | |
465 gpu::Mailbox gpu_mailbox; | |
466 child_context_->genMailboxCHROMIUM(gpu_mailbox.name); | |
467 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, | |
468 gpu_mailbox.name); | |
469 *sync_point = child_context_->insertSyncPoint(); | |
470 EXPECT_LT(0u, *sync_point); | |
471 | |
472 scoped_ptr<SharedBitmap> shared_bitmap; | |
473 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
474 SingleReleaseCallbackImpl::Create(base::Bind( | |
475 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), | |
476 release_called, release_sync_point, lost_resource)); | |
477 return child_resource_provider_->CreateResourceFromTextureMailbox( | |
478 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point), | |
479 callback.Pass()); | |
480 } else { | |
481 gfx::Size size(64, 64); | |
482 scoped_ptr<SharedBitmap> shared_bitmap( | |
483 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0)); | |
484 | |
485 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); | |
486 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
487 SingleReleaseCallbackImpl::Create(base::Bind( | |
488 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), | |
489 release_called, release_sync_point, lost_resource)); | |
490 return child_resource_provider_->CreateResourceFromTextureMailbox( | |
491 TextureMailbox(shared_bitmap_ptr, size), callback.Pass()); | |
492 } | |
493 } | |
494 | |
495 protected: | |
496 scoped_ptr<ContextSharedData> shared_data_; | |
497 ResourceProviderContext* context3d_; | |
498 ResourceProviderContext* child_context_; | |
499 FakeOutputSurfaceClient output_surface_client_; | |
500 FakeOutputSurfaceClient child_output_surface_client_; | |
501 scoped_ptr<OutputSurface> output_surface_; | |
502 scoped_ptr<OutputSurface> child_output_surface_; | |
503 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_; | |
504 scoped_ptr<ResourceProvider> resource_provider_; | |
505 scoped_ptr<ResourceProvider> child_resource_provider_; | |
506 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_; | |
507 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_; | |
508 }; | |
509 | |
510 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type, | |
511 ResourceProvider* resource_provider, | |
512 ResourceProviderContext* context) { | |
513 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type()); | |
514 | |
515 gfx::Size size(1, 1); | |
516 ResourceFormat format = RGBA_8888; | |
517 size_t pixel_size = TextureSizeBytes(size, format); | |
518 ASSERT_EQ(4U, pixel_size); | |
519 | |
520 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
521 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
522 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources())); | |
523 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
524 EXPECT_EQ(0u, context->NumTextures()); | |
525 | |
526 uint8_t data[4] = { 1, 2, 3, 4 }; | |
527 resource_provider->CopyToResource(id, data, size); | |
528 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
529 EXPECT_EQ(1u, context->NumTextures()); | |
530 | |
531 uint8_t result[4] = { 0 }; | |
532 GetResourcePixels(resource_provider, context, id, size, format, result); | |
533 EXPECT_EQ(0, memcmp(data, result, pixel_size)); | |
534 | |
535 resource_provider->DeleteResource(id); | |
536 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources())); | |
537 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
538 EXPECT_EQ(0u, context->NumTextures()); | |
539 } | |
540 | |
541 TEST_P(ResourceProviderTest, Basic) { | |
542 CheckCreateResource(GetParam(), resource_provider_.get(), context()); | |
543 } | |
544 | |
545 TEST_P(ResourceProviderTest, Upload) { | |
546 gfx::Size size(2, 2); | |
547 ResourceFormat format = RGBA_8888; | |
548 size_t pixel_size = TextureSizeBytes(size, format); | |
549 ASSERT_EQ(16U, pixel_size); | |
550 | |
551 ResourceProvider::ResourceId id = resource_provider_->CreateResource( | |
552 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
553 | |
554 uint8_t image[16] = { 0 }; | |
555 gfx::Rect image_rect(size); | |
556 resource_provider_->SetPixels( | |
557 id, image, image_rect, image_rect, gfx::Vector2d()); | |
558 | |
559 for (uint8_t i = 0; i < pixel_size; ++i) | |
560 image[i] = i; | |
561 | |
562 uint8_t result[16] = { 0 }; | |
563 { | |
564 gfx::Rect source_rect(0, 0, 1, 1); | |
565 gfx::Vector2d dest_offset(0, 0); | |
566 resource_provider_->SetPixels( | |
567 id, image, image_rect, source_rect, dest_offset); | |
568 | |
569 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
570 GetResourcePixels( | |
571 resource_provider_.get(), context(), id, size, format, result); | |
572 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
573 } | |
574 { | |
575 gfx::Rect source_rect(0, 0, 1, 1); | |
576 gfx::Vector2d dest_offset(1, 1); | |
577 resource_provider_->SetPixels( | |
578 id, image, image_rect, source_rect, dest_offset); | |
579 | |
580 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 }; | |
581 GetResourcePixels( | |
582 resource_provider_.get(), context(), id, size, format, result); | |
583 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
584 } | |
585 { | |
586 gfx::Rect source_rect(1, 0, 1, 1); | |
587 gfx::Vector2d dest_offset(0, 1); | |
588 resource_provider_->SetPixels( | |
589 id, image, image_rect, source_rect, dest_offset); | |
590 | |
591 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 }; | |
592 GetResourcePixels( | |
593 resource_provider_.get(), context(), id, size, format, result); | |
594 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
595 } | |
596 { | |
597 gfx::Rect offset_image_rect(gfx::Point(100, 100), size); | |
598 gfx::Rect source_rect(100, 100, 1, 1); | |
599 gfx::Vector2d dest_offset(1, 0); | |
600 resource_provider_->SetPixels( | |
601 id, image, offset_image_rect, source_rect, dest_offset); | |
602 | |
603 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 }; | |
604 GetResourcePixels( | |
605 resource_provider_.get(), context(), id, size, format, result); | |
606 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
607 } | |
608 | |
609 resource_provider_->DeleteResource(id); | |
610 } | |
611 | |
612 TEST_P(ResourceProviderTest, SimpleUpload) { | |
613 gfx::Size size(2, 2); | |
614 ResourceFormat format = RGBA_8888; | |
615 size_t pixel_size = TextureSizeBytes(size, format); | |
616 ASSERT_EQ(16U, pixel_size); | |
617 | |
618 ResourceProvider::ResourceId id = resource_provider_->CreateResource( | |
619 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
620 | |
621 uint8_t image[16] = {0}; | |
622 resource_provider_->CopyToResource(id, image, size); | |
623 { | |
624 uint8_t result[16] = {0}; | |
625 uint8_t expected[16] = {0}; | |
626 GetResourcePixels(resource_provider_.get(), context(), id, size, format, | |
627 result); | |
628 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
629 } | |
630 | |
631 for (uint8_t i = 0; i < pixel_size; ++i) | |
632 image[i] = i; | |
633 resource_provider_->CopyToResource(id, image, size); | |
634 { | |
635 uint8_t result[16] = {0}; | |
636 uint8_t expected[16] = { | |
637 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; | |
638 GetResourcePixels(resource_provider_.get(), context(), id, size, format, | |
639 result); | |
640 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); | |
641 } | |
642 } | |
643 | |
644 TEST_P(ResourceProviderTest, TransferGLResources) { | |
645 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
646 return; | |
647 gfx::Size size(1, 1); | |
648 ResourceFormat format = RGBA_8888; | |
649 size_t pixel_size = TextureSizeBytes(size, format); | |
650 ASSERT_EQ(4U, pixel_size); | |
651 | |
652 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
653 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
654 uint8_t data1[4] = { 1, 2, 3, 4 }; | |
655 child_resource_provider_->CopyToResource(id1, data1, size); | |
656 | |
657 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( | |
658 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
659 uint8_t data2[4] = { 5, 5, 5, 5 }; | |
660 child_resource_provider_->CopyToResource(id2, data2, size); | |
661 | |
662 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource( | |
663 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
664 { | |
665 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( | |
666 child_resource_provider_.get(), id3); | |
667 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer()); | |
668 } | |
669 | |
670 GLuint external_texture_id = child_context_->createExternalTexture(); | |
671 | |
672 gpu::Mailbox external_mailbox; | |
673 child_context_->genMailboxCHROMIUM(external_mailbox.name); | |
674 child_context_->produceTextureDirectCHROMIUM( | |
675 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name); | |
676 const GLuint external_sync_point = child_context_->insertSyncPoint(); | |
677 ResourceProvider::ResourceId id4 = | |
678 child_resource_provider_->CreateResourceFromTextureMailbox( | |
679 TextureMailbox( | |
680 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point), | |
681 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback))); | |
682 | |
683 ReturnedResourceArray returned_to_child; | |
684 int child_id = | |
685 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
686 { | |
687 // Transfer some resources to the parent. | |
688 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
689 resource_ids_to_transfer.push_back(id1); | |
690 resource_ids_to_transfer.push_back(id2); | |
691 resource_ids_to_transfer.push_back(id3); | |
692 resource_ids_to_transfer.push_back(id4); | |
693 TransferableResourceArray list; | |
694 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
695 &list); | |
696 ASSERT_EQ(4u, list.size()); | |
697 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
698 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
699 EXPECT_EQ(list[0].mailbox_holder.sync_point, | |
700 list[1].mailbox_holder.sync_point); | |
701 EXPECT_NE(0u, list[2].mailbox_holder.sync_point); | |
702 EXPECT_EQ(list[0].mailbox_holder.sync_point, | |
703 list[2].mailbox_holder.sync_point); | |
704 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point); | |
705 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
706 list[0].mailbox_holder.texture_target); | |
707 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
708 list[1].mailbox_holder.texture_target); | |
709 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
710 list[2].mailbox_holder.texture_target); | |
711 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), | |
712 list[3].mailbox_holder.texture_target); | |
713 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
714 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
715 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); | |
716 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4)); | |
717 resource_provider_->ReceiveFromChild(child_id, list); | |
718 EXPECT_NE(list[0].mailbox_holder.sync_point, | |
719 context3d_->last_waited_sync_point()); | |
720 { | |
721 resource_provider_->WaitSyncPointIfNeeded(list[0].id); | |
722 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), | |
723 list[0].id); | |
724 } | |
725 EXPECT_EQ(list[0].mailbox_holder.sync_point, | |
726 context3d_->last_waited_sync_point()); | |
727 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
728 resource_ids_to_transfer); | |
729 } | |
730 | |
731 EXPECT_EQ(4u, resource_provider_->num_resources()); | |
732 ResourceProvider::ResourceIdMap resource_map = | |
733 resource_provider_->GetChildToParentMap(child_id); | |
734 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
735 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; | |
736 ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; | |
737 ResourceProvider::ResourceId mapped_id4 = resource_map[id4]; | |
738 EXPECT_NE(0u, mapped_id1); | |
739 EXPECT_NE(0u, mapped_id2); | |
740 EXPECT_NE(0u, mapped_id3); | |
741 EXPECT_NE(0u, mapped_id4); | |
742 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); | |
743 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); | |
744 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3)); | |
745 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4)); | |
746 | |
747 uint8_t result[4] = { 0 }; | |
748 GetResourcePixels( | |
749 resource_provider_.get(), context(), mapped_id1, size, format, result); | |
750 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); | |
751 | |
752 GetResourcePixels( | |
753 resource_provider_.get(), context(), mapped_id2, size, format, result); | |
754 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); | |
755 | |
756 { | |
757 // Check that transfering again the same resource from the child to the | |
758 // parent works. | |
759 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
760 resource_ids_to_transfer.push_back(id1); | |
761 resource_ids_to_transfer.push_back(id2); | |
762 resource_ids_to_transfer.push_back(id3); | |
763 TransferableResourceArray list; | |
764 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
765 &list); | |
766 EXPECT_EQ(3u, list.size()); | |
767 EXPECT_EQ(id1, list[0].id); | |
768 EXPECT_EQ(id2, list[1].id); | |
769 EXPECT_EQ(id3, list[2].id); | |
770 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
771 list[0].mailbox_holder.texture_target); | |
772 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
773 list[1].mailbox_holder.texture_target); | |
774 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
775 list[2].mailbox_holder.texture_target); | |
776 ReturnedResourceArray returned; | |
777 TransferableResource::ReturnResources(list, &returned); | |
778 child_resource_provider_->ReceiveReturnsFromParent(returned); | |
779 // ids were exported twice, we returned them only once, they should still | |
780 // be in-use. | |
781 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
782 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
783 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); | |
784 } | |
785 { | |
786 EXPECT_EQ(0u, returned_to_child.size()); | |
787 | |
788 // Transfer resources back from the parent to the child. Set no resources as | |
789 // being in use. | |
790 ResourceProvider::ResourceIdArray no_resources; | |
791 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
792 | |
793 ASSERT_EQ(4u, returned_to_child.size()); | |
794 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
795 EXPECT_NE(0u, returned_to_child[1].sync_point); | |
796 EXPECT_NE(0u, returned_to_child[2].sync_point); | |
797 EXPECT_NE(0u, returned_to_child[3].sync_point); | |
798 EXPECT_FALSE(returned_to_child[0].lost); | |
799 EXPECT_FALSE(returned_to_child[1].lost); | |
800 EXPECT_FALSE(returned_to_child[2].lost); | |
801 EXPECT_FALSE(returned_to_child[3].lost); | |
802 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
803 returned_to_child.clear(); | |
804 } | |
805 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); | |
806 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); | |
807 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); | |
808 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4)); | |
809 | |
810 { | |
811 child_resource_provider_->WaitSyncPointIfNeeded(id1); | |
812 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), | |
813 id1); | |
814 ASSERT_NE(0U, lock.texture_id()); | |
815 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); | |
816 child_context_->GetPixels(size, format, result); | |
817 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); | |
818 } | |
819 { | |
820 child_resource_provider_->WaitSyncPointIfNeeded(id2); | |
821 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), | |
822 id2); | |
823 ASSERT_NE(0U, lock.texture_id()); | |
824 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); | |
825 child_context_->GetPixels(size, format, result); | |
826 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); | |
827 } | |
828 { | |
829 child_resource_provider_->WaitSyncPointIfNeeded(id3); | |
830 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), | |
831 id3); | |
832 ASSERT_NE(0U, lock.texture_id()); | |
833 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); | |
834 } | |
835 { | |
836 // Transfer resources to the parent again. | |
837 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
838 resource_ids_to_transfer.push_back(id1); | |
839 resource_ids_to_transfer.push_back(id2); | |
840 resource_ids_to_transfer.push_back(id3); | |
841 resource_ids_to_transfer.push_back(id4); | |
842 TransferableResourceArray list; | |
843 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
844 &list); | |
845 ASSERT_EQ(4u, list.size()); | |
846 EXPECT_EQ(id1, list[0].id); | |
847 EXPECT_EQ(id2, list[1].id); | |
848 EXPECT_EQ(id3, list[2].id); | |
849 EXPECT_EQ(id4, list[3].id); | |
850 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
851 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
852 EXPECT_NE(0u, list[2].mailbox_holder.sync_point); | |
853 EXPECT_NE(0u, list[3].mailbox_holder.sync_point); | |
854 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
855 list[0].mailbox_holder.texture_target); | |
856 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
857 list[1].mailbox_holder.texture_target); | |
858 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
859 list[2].mailbox_holder.texture_target); | |
860 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), | |
861 list[3].mailbox_holder.texture_target); | |
862 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
863 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
864 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); | |
865 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4)); | |
866 resource_provider_->ReceiveFromChild(child_id, list); | |
867 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
868 resource_ids_to_transfer); | |
869 } | |
870 | |
871 EXPECT_EQ(0u, returned_to_child.size()); | |
872 | |
873 EXPECT_EQ(4u, resource_provider_->num_resources()); | |
874 resource_provider_->DestroyChild(child_id); | |
875 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
876 | |
877 ASSERT_EQ(4u, returned_to_child.size()); | |
878 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
879 EXPECT_NE(0u, returned_to_child[1].sync_point); | |
880 EXPECT_NE(0u, returned_to_child[2].sync_point); | |
881 EXPECT_NE(0u, returned_to_child[3].sync_point); | |
882 EXPECT_FALSE(returned_to_child[0].lost); | |
883 EXPECT_FALSE(returned_to_child[1].lost); | |
884 EXPECT_FALSE(returned_to_child[2].lost); | |
885 EXPECT_FALSE(returned_to_child[3].lost); | |
886 } | |
887 | |
888 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) { | |
889 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
890 return; | |
891 gfx::Size size(1, 1); | |
892 ResourceFormat format = RGBA_8888; | |
893 | |
894 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
895 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
896 uint8_t data1[4] = {1, 2, 3, 4}; | |
897 child_resource_provider_->CopyToResource(id1, data1, size); | |
898 | |
899 ReturnedResourceArray returned_to_child; | |
900 int child_id = | |
901 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
902 { | |
903 // Transfer some resources to the parent. | |
904 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
905 resource_ids_to_transfer.push_back(id1); | |
906 TransferableResourceArray list; | |
907 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
908 &list); | |
909 ASSERT_EQ(1u, list.size()); | |
910 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
911 | |
912 resource_provider_->ReceiveFromChild(child_id, list); | |
913 | |
914 resource_provider_->WaitSyncPointIfNeeded(list[0].id); | |
915 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(), | |
916 list[0].id); | |
917 | |
918 resource_provider_->DeclareUsedResourcesFromChild( | |
919 child_id, ResourceProvider::ResourceIdArray()); | |
920 EXPECT_EQ(0u, returned_to_child.size()); | |
921 } | |
922 | |
923 EXPECT_EQ(1u, returned_to_child.size()); | |
924 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
925 | |
926 { | |
927 child_resource_provider_->WaitSyncPointIfNeeded(id1); | |
928 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), | |
929 id1); | |
930 child_resource_provider_->DeleteResource(id1); | |
931 EXPECT_EQ(1u, child_resource_provider_->num_resources()); | |
932 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
933 } | |
934 | |
935 EXPECT_EQ(0u, child_resource_provider_->num_resources()); | |
936 resource_provider_->DestroyChild(child_id); | |
937 } | |
938 | |
939 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) { | |
940 // Overlays only supported on the GL path. | |
941 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
942 return; | |
943 | |
944 uint32 sync_point = 0; | |
945 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); | |
946 mailbox.set_allow_overlay(true); | |
947 scoped_ptr<SingleReleaseCallbackImpl> release_callback = | |
948 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); | |
949 ResourceProvider::ResourceId id1 = | |
950 child_resource_provider_->CreateResourceFromTextureMailbox( | |
951 mailbox, release_callback.Pass()); | |
952 | |
953 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); | |
954 mailbox2.set_allow_overlay(false); | |
955 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 = | |
956 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); | |
957 ResourceProvider::ResourceId id2 = | |
958 child_resource_provider_->CreateResourceFromTextureMailbox( | |
959 mailbox2, release_callback2.Pass()); | |
960 | |
961 ReturnedResourceArray returned_to_child; | |
962 int child_id = | |
963 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
964 | |
965 // Transfer some resources to the parent. | |
966 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
967 resource_ids_to_transfer.push_back(id1); | |
968 resource_ids_to_transfer.push_back(id2); | |
969 TransferableResourceArray list; | |
970 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
971 &list); | |
972 ASSERT_EQ(2u, list.size()); | |
973 resource_provider_->ReceiveFromChild(child_id, list); | |
974 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id)); | |
975 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id)); | |
976 | |
977 resource_provider_->DeclareUsedResourcesFromChild( | |
978 child_id, ResourceProvider::ResourceIdArray()); | |
979 | |
980 EXPECT_EQ(2u, returned_to_child.size()); | |
981 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
982 | |
983 child_resource_provider_->DeleteResource(id1); | |
984 child_resource_provider_->DeleteResource(id2); | |
985 EXPECT_EQ(0u, child_resource_provider_->num_resources()); | |
986 | |
987 resource_provider_->DestroyChild(child_id); | |
988 } | |
989 | |
990 TEST_P(ResourceProviderTest, TransferSoftwareResources) { | |
991 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP) | |
992 return; | |
993 | |
994 gfx::Size size(1, 1); | |
995 ResourceFormat format = RGBA_8888; | |
996 size_t pixel_size = TextureSizeBytes(size, format); | |
997 ASSERT_EQ(4U, pixel_size); | |
998 | |
999 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
1000 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1001 uint8_t data1[4] = { 1, 2, 3, 4 }; | |
1002 child_resource_provider_->CopyToResource(id1, data1, size); | |
1003 | |
1004 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( | |
1005 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1006 uint8_t data2[4] = { 5, 5, 5, 5 }; | |
1007 child_resource_provider_->CopyToResource(id2, data2, size); | |
1008 | |
1009 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap( | |
1010 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0)); | |
1011 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); | |
1012 ResourceProvider::ResourceId id3 = | |
1013 child_resource_provider_->CreateResourceFromTextureMailbox( | |
1014 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)), | |
1015 SingleReleaseCallbackImpl::Create(base::Bind( | |
1016 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap)))); | |
1017 | |
1018 ReturnedResourceArray returned_to_child; | |
1019 int child_id = | |
1020 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1021 { | |
1022 // Transfer some resources to the parent. | |
1023 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1024 resource_ids_to_transfer.push_back(id1); | |
1025 resource_ids_to_transfer.push_back(id2); | |
1026 resource_ids_to_transfer.push_back(id3); | |
1027 TransferableResourceArray list; | |
1028 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1029 &list); | |
1030 ASSERT_EQ(3u, list.size()); | |
1031 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point); | |
1032 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point); | |
1033 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point); | |
1034 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1035 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
1036 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); | |
1037 resource_provider_->ReceiveFromChild(child_id, list); | |
1038 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1039 resource_ids_to_transfer); | |
1040 } | |
1041 | |
1042 EXPECT_EQ(3u, resource_provider_->num_resources()); | |
1043 ResourceProvider::ResourceIdMap resource_map = | |
1044 resource_provider_->GetChildToParentMap(child_id); | |
1045 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
1046 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; | |
1047 ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; | |
1048 EXPECT_NE(0u, mapped_id1); | |
1049 EXPECT_NE(0u, mapped_id2); | |
1050 EXPECT_NE(0u, mapped_id3); | |
1051 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); | |
1052 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); | |
1053 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3)); | |
1054 | |
1055 uint8_t result[4] = { 0 }; | |
1056 GetResourcePixels( | |
1057 resource_provider_.get(), context(), mapped_id1, size, format, result); | |
1058 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); | |
1059 | |
1060 GetResourcePixels( | |
1061 resource_provider_.get(), context(), mapped_id2, size, format, result); | |
1062 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); | |
1063 | |
1064 { | |
1065 // Check that transfering again the same resource from the child to the | |
1066 // parent works. | |
1067 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1068 resource_ids_to_transfer.push_back(id1); | |
1069 resource_ids_to_transfer.push_back(id2); | |
1070 TransferableResourceArray list; | |
1071 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1072 &list); | |
1073 EXPECT_EQ(2u, list.size()); | |
1074 EXPECT_EQ(id1, list[0].id); | |
1075 EXPECT_EQ(id2, list[1].id); | |
1076 ReturnedResourceArray returned; | |
1077 TransferableResource::ReturnResources(list, &returned); | |
1078 child_resource_provider_->ReceiveReturnsFromParent(returned); | |
1079 // ids were exported twice, we returned them only once, they should still | |
1080 // be in-use. | |
1081 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1082 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
1083 } | |
1084 { | |
1085 EXPECT_EQ(0u, returned_to_child.size()); | |
1086 | |
1087 // Transfer resources back from the parent to the child. Set no resources as | |
1088 // being in use. | |
1089 ResourceProvider::ResourceIdArray no_resources; | |
1090 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
1091 | |
1092 ASSERT_EQ(3u, returned_to_child.size()); | |
1093 EXPECT_EQ(0u, returned_to_child[0].sync_point); | |
1094 EXPECT_EQ(0u, returned_to_child[1].sync_point); | |
1095 EXPECT_EQ(0u, returned_to_child[2].sync_point); | |
1096 std::set<ResourceProvider::ResourceId> expected_ids; | |
1097 expected_ids.insert(id1); | |
1098 expected_ids.insert(id2); | |
1099 expected_ids.insert(id3); | |
1100 std::set<ResourceProvider::ResourceId> returned_ids; | |
1101 for (unsigned i = 0; i < 3; i++) | |
1102 returned_ids.insert(returned_to_child[i].id); | |
1103 EXPECT_EQ(expected_ids, returned_ids); | |
1104 EXPECT_FALSE(returned_to_child[0].lost); | |
1105 EXPECT_FALSE(returned_to_child[1].lost); | |
1106 EXPECT_FALSE(returned_to_child[2].lost); | |
1107 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
1108 returned_to_child.clear(); | |
1109 } | |
1110 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); | |
1111 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); | |
1112 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); | |
1113 | |
1114 { | |
1115 ResourceProvider::ScopedReadLockSoftware lock( | |
1116 child_resource_provider_.get(), id1); | |
1117 const SkBitmap* sk_bitmap = lock.sk_bitmap(); | |
1118 EXPECT_EQ(sk_bitmap->width(), size.width()); | |
1119 EXPECT_EQ(sk_bitmap->height(), size.height()); | |
1120 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size)); | |
1121 } | |
1122 { | |
1123 ResourceProvider::ScopedReadLockSoftware lock( | |
1124 child_resource_provider_.get(), id2); | |
1125 const SkBitmap* sk_bitmap = lock.sk_bitmap(); | |
1126 EXPECT_EQ(sk_bitmap->width(), size.width()); | |
1127 EXPECT_EQ(sk_bitmap->height(), size.height()); | |
1128 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size)); | |
1129 } | |
1130 { | |
1131 // Transfer resources to the parent again. | |
1132 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1133 resource_ids_to_transfer.push_back(id1); | |
1134 resource_ids_to_transfer.push_back(id2); | |
1135 resource_ids_to_transfer.push_back(id3); | |
1136 TransferableResourceArray list; | |
1137 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1138 &list); | |
1139 ASSERT_EQ(3u, list.size()); | |
1140 EXPECT_EQ(id1, list[0].id); | |
1141 EXPECT_EQ(id2, list[1].id); | |
1142 EXPECT_EQ(id3, list[2].id); | |
1143 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1144 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
1145 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); | |
1146 resource_provider_->ReceiveFromChild(child_id, list); | |
1147 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1148 resource_ids_to_transfer); | |
1149 } | |
1150 | |
1151 EXPECT_EQ(0u, returned_to_child.size()); | |
1152 | |
1153 EXPECT_EQ(3u, resource_provider_->num_resources()); | |
1154 resource_provider_->DestroyChild(child_id); | |
1155 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
1156 | |
1157 ASSERT_EQ(3u, returned_to_child.size()); | |
1158 EXPECT_EQ(0u, returned_to_child[0].sync_point); | |
1159 EXPECT_EQ(0u, returned_to_child[1].sync_point); | |
1160 EXPECT_EQ(0u, returned_to_child[2].sync_point); | |
1161 std::set<ResourceProvider::ResourceId> expected_ids; | |
1162 expected_ids.insert(id1); | |
1163 expected_ids.insert(id2); | |
1164 expected_ids.insert(id3); | |
1165 std::set<ResourceProvider::ResourceId> returned_ids; | |
1166 for (unsigned i = 0; i < 3; i++) | |
1167 returned_ids.insert(returned_to_child[i].id); | |
1168 EXPECT_EQ(expected_ids, returned_ids); | |
1169 EXPECT_FALSE(returned_to_child[0].lost); | |
1170 EXPECT_FALSE(returned_to_child[1].lost); | |
1171 EXPECT_FALSE(returned_to_child[2].lost); | |
1172 } | |
1173 | |
1174 TEST_P(ResourceProviderTest, TransferGLToSoftware) { | |
1175 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP) | |
1176 return; | |
1177 | |
1178 scoped_ptr<ResourceProviderContext> child_context_owned( | |
1179 ResourceProviderContext::Create(shared_data_.get())); | |
1180 | |
1181 FakeOutputSurfaceClient child_output_surface_client; | |
1182 scoped_ptr<OutputSurface> child_output_surface( | |
1183 FakeOutputSurface::Create3d(child_context_owned.Pass())); | |
1184 CHECK(child_output_surface->BindToClient(&child_output_surface_client)); | |
1185 | |
1186 scoped_ptr<ResourceProvider> child_resource_provider( | |
1187 ResourceProvider::Create(child_output_surface.get(), | |
1188 shared_bitmap_manager_.get(), | |
1189 gpu_memory_buffer_manager_.get(), | |
1190 NULL, | |
1191 0, | |
1192 false, | |
1193 1)); | |
1194 | |
1195 gfx::Size size(1, 1); | |
1196 ResourceFormat format = RGBA_8888; | |
1197 size_t pixel_size = TextureSizeBytes(size, format); | |
1198 ASSERT_EQ(4U, pixel_size); | |
1199 | |
1200 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( | |
1201 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1202 uint8_t data1[4] = { 1, 2, 3, 4 }; | |
1203 child_resource_provider->CopyToResource(id1, data1, size); | |
1204 | |
1205 ReturnedResourceArray returned_to_child; | |
1206 int child_id = | |
1207 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1208 { | |
1209 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1210 resource_ids_to_transfer.push_back(id1); | |
1211 TransferableResourceArray list; | |
1212 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, | |
1213 &list); | |
1214 ASSERT_EQ(1u, list.size()); | |
1215 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1216 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), | |
1217 list[0].mailbox_holder.texture_target); | |
1218 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); | |
1219 resource_provider_->ReceiveFromChild(child_id, list); | |
1220 } | |
1221 | |
1222 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
1223 ASSERT_EQ(1u, returned_to_child.size()); | |
1224 EXPECT_EQ(returned_to_child[0].id, id1); | |
1225 ResourceProvider::ResourceIdMap resource_map = | |
1226 resource_provider_->GetChildToParentMap(child_id); | |
1227 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
1228 EXPECT_EQ(0u, mapped_id1); | |
1229 | |
1230 resource_provider_->DestroyChild(child_id); | |
1231 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
1232 | |
1233 ASSERT_EQ(1u, returned_to_child.size()); | |
1234 EXPECT_FALSE(returned_to_child[0].lost); | |
1235 } | |
1236 | |
1237 TEST_P(ResourceProviderTest, TransferInvalidSoftware) { | |
1238 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP) | |
1239 return; | |
1240 | |
1241 gfx::Size size(1, 1); | |
1242 ResourceFormat format = RGBA_8888; | |
1243 size_t pixel_size = TextureSizeBytes(size, format); | |
1244 ASSERT_EQ(4U, pixel_size); | |
1245 | |
1246 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
1247 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1248 uint8_t data1[4] = { 1, 2, 3, 4 }; | |
1249 child_resource_provider_->CopyToResource(id1, data1, size); | |
1250 | |
1251 ReturnedResourceArray returned_to_child; | |
1252 int child_id = | |
1253 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1254 { | |
1255 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1256 resource_ids_to_transfer.push_back(id1); | |
1257 TransferableResourceArray list; | |
1258 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1259 &list); | |
1260 ASSERT_EQ(1u, list.size()); | |
1261 // Make invalid. | |
1262 list[0].mailbox_holder.mailbox.name[1] = 5; | |
1263 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1264 resource_provider_->ReceiveFromChild(child_id, list); | |
1265 } | |
1266 | |
1267 EXPECT_EQ(1u, resource_provider_->num_resources()); | |
1268 EXPECT_EQ(0u, returned_to_child.size()); | |
1269 | |
1270 ResourceProvider::ResourceIdMap resource_map = | |
1271 resource_provider_->GetChildToParentMap(child_id); | |
1272 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
1273 EXPECT_NE(0u, mapped_id1); | |
1274 { | |
1275 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(), | |
1276 mapped_id1); | |
1277 EXPECT_FALSE(lock.valid()); | |
1278 } | |
1279 | |
1280 resource_provider_->DestroyChild(child_id); | |
1281 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
1282 | |
1283 ASSERT_EQ(1u, returned_to_child.size()); | |
1284 EXPECT_FALSE(returned_to_child[0].lost); | |
1285 } | |
1286 | |
1287 TEST_P(ResourceProviderTest, DeleteExportedResources) { | |
1288 gfx::Size size(1, 1); | |
1289 ResourceFormat format = RGBA_8888; | |
1290 size_t pixel_size = TextureSizeBytes(size, format); | |
1291 ASSERT_EQ(4U, pixel_size); | |
1292 | |
1293 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
1294 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1295 uint8_t data1[4] = { 1, 2, 3, 4 }; | |
1296 child_resource_provider_->CopyToResource(id1, data1, size); | |
1297 | |
1298 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( | |
1299 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1300 uint8_t data2[4] = {5, 5, 5, 5}; | |
1301 child_resource_provider_->CopyToResource(id2, data2, size); | |
1302 | |
1303 ReturnedResourceArray returned_to_child; | |
1304 int child_id = | |
1305 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1306 { | |
1307 // Transfer some resources to the parent. | |
1308 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1309 resource_ids_to_transfer.push_back(id1); | |
1310 resource_ids_to_transfer.push_back(id2); | |
1311 TransferableResourceArray list; | |
1312 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1313 &list); | |
1314 ASSERT_EQ(2u, list.size()); | |
1315 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1316 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1317 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
1318 } | |
1319 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1320 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
1321 resource_provider_->ReceiveFromChild(child_id, list); | |
1322 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1323 resource_ids_to_transfer); | |
1324 } | |
1325 | |
1326 EXPECT_EQ(2u, resource_provider_->num_resources()); | |
1327 ResourceProvider::ResourceIdMap resource_map = | |
1328 resource_provider_->GetChildToParentMap(child_id); | |
1329 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
1330 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; | |
1331 EXPECT_NE(0u, mapped_id1); | |
1332 EXPECT_NE(0u, mapped_id2); | |
1333 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); | |
1334 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); | |
1335 | |
1336 { | |
1337 // The parent transfers the resources to the grandparent. | |
1338 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1339 resource_ids_to_transfer.push_back(mapped_id1); | |
1340 resource_ids_to_transfer.push_back(mapped_id2); | |
1341 TransferableResourceArray list; | |
1342 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
1343 | |
1344 ASSERT_EQ(2u, list.size()); | |
1345 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1346 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1347 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
1348 } | |
1349 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); | |
1350 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); | |
1351 | |
1352 // Release the resource in the parent. Set no resources as being in use. The | |
1353 // resources are exported so that can't be transferred back yet. | |
1354 ResourceProvider::ResourceIdArray no_resources; | |
1355 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
1356 | |
1357 EXPECT_EQ(0u, returned_to_child.size()); | |
1358 EXPECT_EQ(2u, resource_provider_->num_resources()); | |
1359 | |
1360 // Return the resources from the grandparent to the parent. They should be | |
1361 // returned to the child then. | |
1362 EXPECT_EQ(2u, list.size()); | |
1363 EXPECT_EQ(mapped_id1, list[0].id); | |
1364 EXPECT_EQ(mapped_id2, list[1].id); | |
1365 ReturnedResourceArray returned; | |
1366 TransferableResource::ReturnResources(list, &returned); | |
1367 resource_provider_->ReceiveReturnsFromParent(returned); | |
1368 | |
1369 EXPECT_EQ(0u, resource_provider_->num_resources()); | |
1370 ASSERT_EQ(2u, returned_to_child.size()); | |
1371 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1372 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
1373 EXPECT_NE(0u, returned_to_child[1].sync_point); | |
1374 } | |
1375 EXPECT_FALSE(returned_to_child[0].lost); | |
1376 EXPECT_FALSE(returned_to_child[1].lost); | |
1377 } | |
1378 } | |
1379 | |
1380 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { | |
1381 gfx::Size size(1, 1); | |
1382 ResourceFormat format = RGBA_8888; | |
1383 size_t pixel_size = TextureSizeBytes(size, format); | |
1384 ASSERT_EQ(4U, pixel_size); | |
1385 | |
1386 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( | |
1387 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1388 uint8_t data1[4] = {1, 2, 3, 4}; | |
1389 child_resource_provider_->CopyToResource(id1, data1, size); | |
1390 | |
1391 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( | |
1392 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1393 uint8_t data2[4] = {5, 5, 5, 5}; | |
1394 child_resource_provider_->CopyToResource(id2, data2, size); | |
1395 | |
1396 ReturnedResourceArray returned_to_child; | |
1397 int child_id = | |
1398 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1399 { | |
1400 // Transfer some resources to the parent. | |
1401 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1402 resource_ids_to_transfer.push_back(id1); | |
1403 resource_ids_to_transfer.push_back(id2); | |
1404 TransferableResourceArray list; | |
1405 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1406 &list); | |
1407 ASSERT_EQ(2u, list.size()); | |
1408 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1409 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1410 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
1411 } | |
1412 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); | |
1413 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); | |
1414 resource_provider_->ReceiveFromChild(child_id, list); | |
1415 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1416 resource_ids_to_transfer); | |
1417 } | |
1418 | |
1419 EXPECT_EQ(2u, resource_provider_->num_resources()); | |
1420 ResourceProvider::ResourceIdMap resource_map = | |
1421 resource_provider_->GetChildToParentMap(child_id); | |
1422 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; | |
1423 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; | |
1424 EXPECT_NE(0u, mapped_id1); | |
1425 EXPECT_NE(0u, mapped_id2); | |
1426 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); | |
1427 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); | |
1428 | |
1429 { | |
1430 // The parent transfers the resources to the grandparent. | |
1431 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1432 resource_ids_to_transfer.push_back(mapped_id1); | |
1433 resource_ids_to_transfer.push_back(mapped_id2); | |
1434 TransferableResourceArray list; | |
1435 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
1436 | |
1437 ASSERT_EQ(2u, list.size()); | |
1438 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1439 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1440 EXPECT_NE(0u, list[1].mailbox_holder.sync_point); | |
1441 } | |
1442 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); | |
1443 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); | |
1444 | |
1445 // Release the resource in the parent. Set no resources as being in use. The | |
1446 // resources are exported so that can't be transferred back yet. | |
1447 ResourceProvider::ResourceIdArray no_resources; | |
1448 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
1449 | |
1450 // Destroy the child, the resources should not be returned yet. | |
1451 EXPECT_EQ(0u, returned_to_child.size()); | |
1452 EXPECT_EQ(2u, resource_provider_->num_resources()); | |
1453 | |
1454 resource_provider_->DestroyChild(child_id); | |
1455 | |
1456 EXPECT_EQ(2u, resource_provider_->num_resources()); | |
1457 ASSERT_EQ(0u, returned_to_child.size()); | |
1458 | |
1459 // Return a resource from the grandparent, it should be returned at this | |
1460 // point. | |
1461 EXPECT_EQ(2u, list.size()); | |
1462 EXPECT_EQ(mapped_id1, list[0].id); | |
1463 EXPECT_EQ(mapped_id2, list[1].id); | |
1464 TransferableResourceArray return_list; | |
1465 return_list.push_back(list[1]); | |
1466 list.pop_back(); | |
1467 ReturnedResourceArray returned; | |
1468 TransferableResource::ReturnResources(return_list, &returned); | |
1469 resource_provider_->ReceiveReturnsFromParent(returned); | |
1470 | |
1471 EXPECT_EQ(1u, resource_provider_->num_resources()); | |
1472 ASSERT_EQ(1u, returned_to_child.size()); | |
1473 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1474 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
1475 } | |
1476 EXPECT_FALSE(returned_to_child[0].lost); | |
1477 returned_to_child.clear(); | |
1478 | |
1479 // Destroy the parent resource provider. The resource that's left should be | |
1480 // lost at this point, and returned. | |
1481 resource_provider_ = nullptr; | |
1482 ASSERT_EQ(1u, returned_to_child.size()); | |
1483 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
1484 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
1485 } | |
1486 EXPECT_TRUE(returned_to_child[0].lost); | |
1487 } | |
1488 } | |
1489 | |
1490 TEST_P(ResourceProviderTest, DeleteTransferredResources) { | |
1491 gfx::Size size(1, 1); | |
1492 ResourceFormat format = RGBA_8888; | |
1493 size_t pixel_size = TextureSizeBytes(size, format); | |
1494 ASSERT_EQ(4U, pixel_size); | |
1495 | |
1496 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( | |
1497 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1498 uint8_t data[4] = { 1, 2, 3, 4 }; | |
1499 child_resource_provider_->CopyToResource(id, data, size); | |
1500 | |
1501 ReturnedResourceArray returned_to_child; | |
1502 int child_id = | |
1503 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1504 { | |
1505 // Transfer some resource to the parent. | |
1506 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1507 resource_ids_to_transfer.push_back(id); | |
1508 TransferableResourceArray list; | |
1509 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1510 &list); | |
1511 ASSERT_EQ(1u, list.size()); | |
1512 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
1513 EXPECT_NE(0u, list[0].mailbox_holder.sync_point); | |
1514 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); | |
1515 resource_provider_->ReceiveFromChild(child_id, list); | |
1516 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1517 resource_ids_to_transfer); | |
1518 } | |
1519 | |
1520 // Delete textures in the child, while they are transfered. | |
1521 child_resource_provider_->DeleteResource(id); | |
1522 EXPECT_EQ(1u, child_resource_provider_->num_resources()); | |
1523 { | |
1524 EXPECT_EQ(0u, returned_to_child.size()); | |
1525 | |
1526 // Transfer resources back from the parent to the child. Set no resources as | |
1527 // being in use. | |
1528 ResourceProvider::ResourceIdArray no_resources; | |
1529 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
1530 | |
1531 ASSERT_EQ(1u, returned_to_child.size()); | |
1532 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
1533 EXPECT_NE(0u, returned_to_child[0].sync_point); | |
1534 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
1535 } | |
1536 EXPECT_EQ(0u, child_resource_provider_->num_resources()); | |
1537 } | |
1538 | |
1539 TEST_P(ResourceProviderTest, UnuseTransferredResources) { | |
1540 gfx::Size size(1, 1); | |
1541 ResourceFormat format = RGBA_8888; | |
1542 size_t pixel_size = TextureSizeBytes(size, format); | |
1543 ASSERT_EQ(4U, pixel_size); | |
1544 | |
1545 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( | |
1546 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
1547 uint8_t data[4] = {1, 2, 3, 4}; | |
1548 child_resource_provider_->CopyToResource(id, data, size); | |
1549 | |
1550 ReturnedResourceArray returned_to_child; | |
1551 int child_id = | |
1552 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1553 const ResourceProvider::ResourceIdMap& map = | |
1554 resource_provider_->GetChildToParentMap(child_id); | |
1555 { | |
1556 // Transfer some resource to the parent. | |
1557 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1558 resource_ids_to_transfer.push_back(id); | |
1559 TransferableResourceArray list; | |
1560 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1561 &list); | |
1562 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); | |
1563 resource_provider_->ReceiveFromChild(child_id, list); | |
1564 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1565 resource_ids_to_transfer); | |
1566 } | |
1567 TransferableResourceArray sent_to_top_level; | |
1568 { | |
1569 // Parent transfers to top-level. | |
1570 ASSERT_TRUE(map.find(id) != map.end()); | |
1571 ResourceProvider::ResourceId parent_id = map.find(id)->second; | |
1572 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1573 resource_ids_to_transfer.push_back(parent_id); | |
1574 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1575 &sent_to_top_level); | |
1576 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id)); | |
1577 } | |
1578 { | |
1579 // Stop using resource. | |
1580 ResourceProvider::ResourceIdArray empty; | |
1581 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty); | |
1582 // Resource is not yet returned to the child, since it's in use by the | |
1583 // top-level. | |
1584 EXPECT_TRUE(returned_to_child.empty()); | |
1585 } | |
1586 { | |
1587 // Send the resource to the parent again. | |
1588 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1589 resource_ids_to_transfer.push_back(id); | |
1590 TransferableResourceArray list; | |
1591 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1592 &list); | |
1593 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); | |
1594 resource_provider_->ReceiveFromChild(child_id, list); | |
1595 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1596 resource_ids_to_transfer); | |
1597 } | |
1598 { | |
1599 // Receive returns back from top-level. | |
1600 ReturnedResourceArray returned; | |
1601 TransferableResource::ReturnResources(sent_to_top_level, &returned); | |
1602 resource_provider_->ReceiveReturnsFromParent(returned); | |
1603 // Resource is still not yet returned to the child, since it's declared used | |
1604 // in the parent. | |
1605 EXPECT_TRUE(returned_to_child.empty()); | |
1606 ASSERT_TRUE(map.find(id) != map.end()); | |
1607 ResourceProvider::ResourceId parent_id = map.find(id)->second; | |
1608 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id)); | |
1609 } | |
1610 { | |
1611 sent_to_top_level.clear(); | |
1612 // Parent transfers again to top-level. | |
1613 ASSERT_TRUE(map.find(id) != map.end()); | |
1614 ResourceProvider::ResourceId parent_id = map.find(id)->second; | |
1615 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1616 resource_ids_to_transfer.push_back(parent_id); | |
1617 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1618 &sent_to_top_level); | |
1619 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id)); | |
1620 } | |
1621 { | |
1622 // Receive returns back from top-level. | |
1623 ReturnedResourceArray returned; | |
1624 TransferableResource::ReturnResources(sent_to_top_level, &returned); | |
1625 resource_provider_->ReceiveReturnsFromParent(returned); | |
1626 // Resource is still not yet returned to the child, since it's still | |
1627 // declared used in the parent. | |
1628 EXPECT_TRUE(returned_to_child.empty()); | |
1629 ASSERT_TRUE(map.find(id) != map.end()); | |
1630 ResourceProvider::ResourceId parent_id = map.find(id)->second; | |
1631 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id)); | |
1632 } | |
1633 { | |
1634 // Stop using resource. | |
1635 ResourceProvider::ResourceIdArray empty; | |
1636 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty); | |
1637 // Resource should have been returned to the child, since it's no longer in | |
1638 // use by the top-level. | |
1639 ASSERT_EQ(1u, returned_to_child.size()); | |
1640 EXPECT_EQ(id, returned_to_child[0].id); | |
1641 EXPECT_EQ(2, returned_to_child[0].count); | |
1642 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
1643 returned_to_child.clear(); | |
1644 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id)); | |
1645 } | |
1646 } | |
1647 | |
1648 class ResourceProviderTestTextureFilters : public ResourceProviderTest { | |
1649 public: | |
1650 static void RunTest(GLenum child_filter, GLenum parent_filter) { | |
1651 scoped_ptr<TextureStateTrackingContext> child_context_owned( | |
1652 new TextureStateTrackingContext); | |
1653 TextureStateTrackingContext* child_context = child_context_owned.get(); | |
1654 | |
1655 FakeOutputSurfaceClient child_output_surface_client; | |
1656 scoped_ptr<OutputSurface> child_output_surface( | |
1657 FakeOutputSurface::Create3d(child_context_owned.Pass())); | |
1658 CHECK(child_output_surface->BindToClient(&child_output_surface_client)); | |
1659 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
1660 new TestSharedBitmapManager()); | |
1661 | |
1662 scoped_ptr<ResourceProvider> child_resource_provider( | |
1663 ResourceProvider::Create(child_output_surface.get(), | |
1664 shared_bitmap_manager.get(), | |
1665 NULL, | |
1666 NULL, | |
1667 0, | |
1668 false, | |
1669 1)); | |
1670 | |
1671 scoped_ptr<TextureStateTrackingContext> parent_context_owned( | |
1672 new TextureStateTrackingContext); | |
1673 TextureStateTrackingContext* parent_context = parent_context_owned.get(); | |
1674 | |
1675 FakeOutputSurfaceClient parent_output_surface_client; | |
1676 scoped_ptr<OutputSurface> parent_output_surface( | |
1677 FakeOutputSurface::Create3d(parent_context_owned.Pass())); | |
1678 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client)); | |
1679 | |
1680 scoped_ptr<ResourceProvider> parent_resource_provider( | |
1681 ResourceProvider::Create(parent_output_surface.get(), | |
1682 shared_bitmap_manager.get(), | |
1683 NULL, | |
1684 NULL, | |
1685 0, | |
1686 false, | |
1687 1)); | |
1688 | |
1689 gfx::Size size(1, 1); | |
1690 ResourceFormat format = RGBA_8888; | |
1691 int child_texture_id = 1; | |
1692 int parent_texture_id = 2; | |
1693 | |
1694 size_t pixel_size = TextureSizeBytes(size, format); | |
1695 ASSERT_EQ(4U, pixel_size); | |
1696 | |
1697 ResourceProvider::ResourceId id = child_resource_provider->CreateResource( | |
1698 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
1699 format); | |
1700 | |
1701 // The new texture is created with GL_LINEAR. | |
1702 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)) | |
1703 .Times(2); // Once to create and once to allocate. | |
1704 EXPECT_CALL(*child_context, | |
1705 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
1706 EXPECT_CALL(*child_context, | |
1707 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
1708 EXPECT_CALL( | |
1709 *child_context, | |
1710 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
1711 EXPECT_CALL( | |
1712 *child_context, | |
1713 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
1714 EXPECT_CALL(*child_context, | |
1715 texParameteri(GL_TEXTURE_2D, | |
1716 GL_TEXTURE_POOL_CHROMIUM, | |
1717 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); | |
1718 child_resource_provider->AllocateForTesting(id); | |
1719 Mock::VerifyAndClearExpectations(child_context); | |
1720 | |
1721 uint8_t data[4] = { 1, 2, 3, 4 }; | |
1722 | |
1723 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); | |
1724 child_resource_provider->CopyToResource(id, data, size); | |
1725 Mock::VerifyAndClearExpectations(child_context); | |
1726 | |
1727 // The texture is set to |child_filter| in the child. | |
1728 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); | |
1729 if (child_filter != GL_LINEAR) { | |
1730 EXPECT_CALL( | |
1731 *child_context, | |
1732 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter)); | |
1733 EXPECT_CALL( | |
1734 *child_context, | |
1735 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter)); | |
1736 } | |
1737 SetResourceFilter(child_resource_provider.get(), id, child_filter); | |
1738 Mock::VerifyAndClearExpectations(child_context); | |
1739 | |
1740 ReturnedResourceArray returned_to_child; | |
1741 int child_id = parent_resource_provider->CreateChild( | |
1742 GetReturnCallback(&returned_to_child)); | |
1743 { | |
1744 // Transfer some resource to the parent. | |
1745 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1746 resource_ids_to_transfer.push_back(id); | |
1747 TransferableResourceArray list; | |
1748 | |
1749 EXPECT_CALL(*child_context, | |
1750 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _)); | |
1751 EXPECT_CALL(*child_context, insertSyncPoint()); | |
1752 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, | |
1753 &list); | |
1754 Mock::VerifyAndClearExpectations(child_context); | |
1755 | |
1756 ASSERT_EQ(1u, list.size()); | |
1757 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter); | |
1758 | |
1759 EXPECT_CALL(*parent_context, | |
1760 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _)) | |
1761 .WillOnce(Return(parent_texture_id)); | |
1762 | |
1763 parent_resource_provider->ReceiveFromChild(child_id, list); | |
1764 { | |
1765 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id); | |
1766 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(), | |
1767 list[0].id); | |
1768 } | |
1769 Mock::VerifyAndClearExpectations(parent_context); | |
1770 | |
1771 parent_resource_provider->DeclareUsedResourcesFromChild( | |
1772 child_id, resource_ids_to_transfer); | |
1773 Mock::VerifyAndClearExpectations(parent_context); | |
1774 } | |
1775 ResourceProvider::ResourceIdMap resource_map = | |
1776 parent_resource_provider->GetChildToParentMap(child_id); | |
1777 ResourceProvider::ResourceId mapped_id = resource_map[id]; | |
1778 EXPECT_NE(0u, mapped_id); | |
1779 | |
1780 // The texture is set to |parent_filter| in the parent. | |
1781 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); | |
1782 EXPECT_CALL( | |
1783 *parent_context, | |
1784 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter)); | |
1785 EXPECT_CALL( | |
1786 *parent_context, | |
1787 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter)); | |
1788 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter); | |
1789 Mock::VerifyAndClearExpectations(parent_context); | |
1790 | |
1791 // The texture should be reset to |child_filter| in the parent when it is | |
1792 // returned, since that is how it was received. | |
1793 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); | |
1794 EXPECT_CALL( | |
1795 *parent_context, | |
1796 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter)); | |
1797 EXPECT_CALL( | |
1798 *parent_context, | |
1799 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter)); | |
1800 | |
1801 { | |
1802 EXPECT_EQ(0u, returned_to_child.size()); | |
1803 | |
1804 // Transfer resources back from the parent to the child. Set no resources | |
1805 // as being in use. | |
1806 ResourceProvider::ResourceIdArray no_resources; | |
1807 EXPECT_CALL(*parent_context, insertSyncPoint()); | |
1808 parent_resource_provider->DeclareUsedResourcesFromChild(child_id, | |
1809 no_resources); | |
1810 Mock::VerifyAndClearExpectations(parent_context); | |
1811 | |
1812 ASSERT_EQ(1u, returned_to_child.size()); | |
1813 child_resource_provider->ReceiveReturnsFromParent(returned_to_child); | |
1814 } | |
1815 | |
1816 // The child remembers the texture filter is set to |child_filter|. | |
1817 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); | |
1818 SetResourceFilter(child_resource_provider.get(), id, child_filter); | |
1819 Mock::VerifyAndClearExpectations(child_context); | |
1820 } | |
1821 }; | |
1822 | |
1823 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) { | |
1824 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
1825 return; | |
1826 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR); | |
1827 } | |
1828 | |
1829 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) { | |
1830 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
1831 return; | |
1832 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST); | |
1833 } | |
1834 | |
1835 TEST_P(ResourceProviderTest, TransferMailboxResources) { | |
1836 // Other mailbox transfers tested elsewhere. | |
1837 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
1838 return; | |
1839 unsigned texture = context()->createTexture(); | |
1840 context()->bindTexture(GL_TEXTURE_2D, texture); | |
1841 uint8_t data[4] = { 1, 2, 3, 4 }; | |
1842 context()->texImage2D( | |
1843 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); | |
1844 gpu::Mailbox mailbox; | |
1845 context()->genMailboxCHROMIUM(mailbox.name); | |
1846 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); | |
1847 uint32 sync_point = context()->insertSyncPoint(); | |
1848 | |
1849 // All the logic below assumes that the sync points are all positive. | |
1850 EXPECT_LT(0u, sync_point); | |
1851 | |
1852 uint32 release_sync_point = 0; | |
1853 bool lost_resource = false; | |
1854 BlockingTaskRunner* main_thread_task_runner = NULL; | |
1855 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback, | |
1856 &release_sync_point, | |
1857 &lost_resource, | |
1858 &main_thread_task_runner); | |
1859 ResourceProvider::ResourceId resource = | |
1860 resource_provider_->CreateResourceFromTextureMailbox( | |
1861 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), | |
1862 SingleReleaseCallbackImpl::Create(callback)); | |
1863 EXPECT_EQ(1u, context()->NumTextures()); | |
1864 EXPECT_EQ(0u, release_sync_point); | |
1865 { | |
1866 // Transfer the resource, expect the sync points to be consistent. | |
1867 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1868 resource_ids_to_transfer.push_back(resource); | |
1869 TransferableResourceArray list; | |
1870 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
1871 ASSERT_EQ(1u, list.size()); | |
1872 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point); | |
1873 EXPECT_EQ(0, | |
1874 memcmp(mailbox.name, | |
1875 list[0].mailbox_holder.mailbox.name, | |
1876 sizeof(mailbox.name))); | |
1877 EXPECT_EQ(0u, release_sync_point); | |
1878 | |
1879 context()->waitSyncPoint(list[0].mailbox_holder.sync_point); | |
1880 unsigned other_texture = | |
1881 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
1882 uint8_t test_data[4] = { 0 }; | |
1883 context()->GetPixels( | |
1884 gfx::Size(1, 1), RGBA_8888, test_data); | |
1885 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); | |
1886 | |
1887 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, | |
1888 mailbox.name); | |
1889 context()->deleteTexture(other_texture); | |
1890 list[0].mailbox_holder.sync_point = context()->insertSyncPoint(); | |
1891 EXPECT_LT(0u, list[0].mailbox_holder.sync_point); | |
1892 | |
1893 // Receive the resource, then delete it, expect the sync points to be | |
1894 // consistent. | |
1895 ReturnedResourceArray returned; | |
1896 TransferableResource::ReturnResources(list, &returned); | |
1897 resource_provider_->ReceiveReturnsFromParent(returned); | |
1898 EXPECT_EQ(1u, context()->NumTextures()); | |
1899 EXPECT_EQ(0u, release_sync_point); | |
1900 | |
1901 resource_provider_->DeleteResource(resource); | |
1902 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point); | |
1903 EXPECT_FALSE(lost_resource); | |
1904 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); | |
1905 } | |
1906 | |
1907 // We're going to do the same thing as above, but testing the case where we | |
1908 // delete the resource before we receive it back. | |
1909 sync_point = release_sync_point; | |
1910 EXPECT_LT(0u, sync_point); | |
1911 release_sync_point = 0; | |
1912 resource = resource_provider_->CreateResourceFromTextureMailbox( | |
1913 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), | |
1914 SingleReleaseCallbackImpl::Create(callback)); | |
1915 EXPECT_EQ(1u, context()->NumTextures()); | |
1916 EXPECT_EQ(0u, release_sync_point); | |
1917 { | |
1918 // Transfer the resource, expect the sync points to be consistent. | |
1919 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1920 resource_ids_to_transfer.push_back(resource); | |
1921 TransferableResourceArray list; | |
1922 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
1923 ASSERT_EQ(1u, list.size()); | |
1924 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point); | |
1925 EXPECT_EQ(0, | |
1926 memcmp(mailbox.name, | |
1927 list[0].mailbox_holder.mailbox.name, | |
1928 sizeof(mailbox.name))); | |
1929 EXPECT_EQ(0u, release_sync_point); | |
1930 | |
1931 context()->waitSyncPoint(list[0].mailbox_holder.sync_point); | |
1932 unsigned other_texture = | |
1933 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
1934 uint8_t test_data[4] = { 0 }; | |
1935 context()->GetPixels( | |
1936 gfx::Size(1, 1), RGBA_8888, test_data); | |
1937 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); | |
1938 | |
1939 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D, | |
1940 mailbox.name); | |
1941 context()->deleteTexture(other_texture); | |
1942 list[0].mailbox_holder.sync_point = context()->insertSyncPoint(); | |
1943 EXPECT_LT(0u, list[0].mailbox_holder.sync_point); | |
1944 | |
1945 // Delete the resource, which shouldn't do anything. | |
1946 resource_provider_->DeleteResource(resource); | |
1947 EXPECT_EQ(1u, context()->NumTextures()); | |
1948 EXPECT_EQ(0u, release_sync_point); | |
1949 | |
1950 // Then receive the resource which should release the mailbox, expect the | |
1951 // sync points to be consistent. | |
1952 ReturnedResourceArray returned; | |
1953 TransferableResource::ReturnResources(list, &returned); | |
1954 resource_provider_->ReceiveReturnsFromParent(returned); | |
1955 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point); | |
1956 EXPECT_FALSE(lost_resource); | |
1957 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); | |
1958 } | |
1959 | |
1960 context()->waitSyncPoint(release_sync_point); | |
1961 texture = | |
1962 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
1963 context()->deleteTexture(texture); | |
1964 } | |
1965 | |
1966 TEST_P(ResourceProviderTest, LostResourceInParent) { | |
1967 gfx::Size size(1, 1); | |
1968 ResourceFormat format = RGBA_8888; | |
1969 ResourceProvider::ResourceId resource = | |
1970 child_resource_provider_->CreateResource( | |
1971 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
1972 format); | |
1973 child_resource_provider_->AllocateForTesting(resource); | |
1974 // Expect a GL resource to be lost. | |
1975 bool should_lose_resource = | |
1976 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE; | |
1977 | |
1978 ReturnedResourceArray returned_to_child; | |
1979 int child_id = | |
1980 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
1981 { | |
1982 // Transfer the resource to the parent. | |
1983 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1984 resource_ids_to_transfer.push_back(resource); | |
1985 TransferableResourceArray list; | |
1986 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
1987 &list); | |
1988 EXPECT_EQ(1u, list.size()); | |
1989 | |
1990 resource_provider_->ReceiveFromChild(child_id, list); | |
1991 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
1992 resource_ids_to_transfer); | |
1993 } | |
1994 | |
1995 // Lose the output surface in the parent. | |
1996 resource_provider_->DidLoseOutputSurface(); | |
1997 | |
1998 { | |
1999 EXPECT_EQ(0u, returned_to_child.size()); | |
2000 | |
2001 // Transfer resources back from the parent to the child. Set no resources as | |
2002 // being in use. | |
2003 ResourceProvider::ResourceIdArray no_resources; | |
2004 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
2005 | |
2006 // Expect a GL resource to be lost. | |
2007 ASSERT_EQ(1u, returned_to_child.size()); | |
2008 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost); | |
2009 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
2010 returned_to_child.clear(); | |
2011 } | |
2012 | |
2013 // A GL resource should be lost. | |
2014 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource)); | |
2015 | |
2016 // Lost resources stay in use in the parent forever. | |
2017 EXPECT_EQ(should_lose_resource, | |
2018 child_resource_provider_->InUseByConsumer(resource)); | |
2019 } | |
2020 | |
2021 TEST_P(ResourceProviderTest, LostResourceInGrandParent) { | |
2022 gfx::Size size(1, 1); | |
2023 ResourceFormat format = RGBA_8888; | |
2024 ResourceProvider::ResourceId resource = | |
2025 child_resource_provider_->CreateResource( | |
2026 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
2027 format); | |
2028 child_resource_provider_->AllocateForTesting(resource); | |
2029 | |
2030 ReturnedResourceArray returned_to_child; | |
2031 int child_id = | |
2032 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
2033 { | |
2034 // Transfer the resource to the parent. | |
2035 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2036 resource_ids_to_transfer.push_back(resource); | |
2037 TransferableResourceArray list; | |
2038 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
2039 &list); | |
2040 EXPECT_EQ(1u, list.size()); | |
2041 | |
2042 resource_provider_->ReceiveFromChild(child_id, list); | |
2043 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
2044 resource_ids_to_transfer); | |
2045 } | |
2046 | |
2047 { | |
2048 ResourceProvider::ResourceIdMap resource_map = | |
2049 resource_provider_->GetChildToParentMap(child_id); | |
2050 ResourceProvider::ResourceId parent_resource = resource_map[resource]; | |
2051 EXPECT_NE(0u, parent_resource); | |
2052 | |
2053 // Transfer to a grandparent. | |
2054 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2055 resource_ids_to_transfer.push_back(parent_resource); | |
2056 TransferableResourceArray list; | |
2057 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
2058 | |
2059 // Receive back a lost resource from the grandparent. | |
2060 EXPECT_EQ(1u, list.size()); | |
2061 EXPECT_EQ(parent_resource, list[0].id); | |
2062 ReturnedResourceArray returned; | |
2063 TransferableResource::ReturnResources(list, &returned); | |
2064 EXPECT_EQ(1u, returned.size()); | |
2065 EXPECT_EQ(parent_resource, returned[0].id); | |
2066 returned[0].lost = true; | |
2067 resource_provider_->ReceiveReturnsFromParent(returned); | |
2068 | |
2069 // The resource should be lost. | |
2070 EXPECT_TRUE(resource_provider_->IsLost(parent_resource)); | |
2071 | |
2072 // Lost resources stay in use in the parent forever. | |
2073 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource)); | |
2074 } | |
2075 | |
2076 { | |
2077 EXPECT_EQ(0u, returned_to_child.size()); | |
2078 | |
2079 // Transfer resources back from the parent to the child. Set no resources as | |
2080 // being in use. | |
2081 ResourceProvider::ResourceIdArray no_resources; | |
2082 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
2083 | |
2084 // Expect the resource to be lost. | |
2085 ASSERT_EQ(1u, returned_to_child.size()); | |
2086 EXPECT_TRUE(returned_to_child[0].lost); | |
2087 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
2088 returned_to_child.clear(); | |
2089 } | |
2090 | |
2091 // The resource should be lost. | |
2092 EXPECT_TRUE(child_resource_provider_->IsLost(resource)); | |
2093 | |
2094 // Lost resources stay in use in the parent forever. | |
2095 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource)); | |
2096 } | |
2097 | |
2098 TEST_P(ResourceProviderTest, LostMailboxInParent) { | |
2099 uint32 release_sync_point = 0; | |
2100 bool lost_resource = false; | |
2101 bool release_called = false; | |
2102 uint32 sync_point = 0; | |
2103 ResourceProvider::ResourceId resource = CreateChildMailbox( | |
2104 &release_sync_point, &lost_resource, &release_called, &sync_point); | |
2105 | |
2106 ReturnedResourceArray returned_to_child; | |
2107 int child_id = | |
2108 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
2109 { | |
2110 // Transfer the resource to the parent. | |
2111 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2112 resource_ids_to_transfer.push_back(resource); | |
2113 TransferableResourceArray list; | |
2114 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
2115 &list); | |
2116 EXPECT_EQ(1u, list.size()); | |
2117 | |
2118 resource_provider_->ReceiveFromChild(child_id, list); | |
2119 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
2120 resource_ids_to_transfer); | |
2121 } | |
2122 | |
2123 // Lose the output surface in the parent. | |
2124 resource_provider_->DidLoseOutputSurface(); | |
2125 | |
2126 { | |
2127 EXPECT_EQ(0u, returned_to_child.size()); | |
2128 | |
2129 // Transfer resources back from the parent to the child. Set no resources as | |
2130 // being in use. | |
2131 ResourceProvider::ResourceIdArray no_resources; | |
2132 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
2133 | |
2134 ASSERT_EQ(1u, returned_to_child.size()); | |
2135 // Losing an output surface only loses hardware resources. | |
2136 EXPECT_EQ(returned_to_child[0].lost, | |
2137 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE); | |
2138 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
2139 returned_to_child.clear(); | |
2140 } | |
2141 | |
2142 // Delete the resource in the child. Expect the resource to be lost if it's | |
2143 // a GL texture. | |
2144 child_resource_provider_->DeleteResource(resource); | |
2145 EXPECT_EQ(lost_resource, | |
2146 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE); | |
2147 } | |
2148 | |
2149 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { | |
2150 uint32 release_sync_point = 0; | |
2151 bool lost_resource = false; | |
2152 bool release_called = false; | |
2153 uint32 sync_point = 0; | |
2154 ResourceProvider::ResourceId resource = CreateChildMailbox( | |
2155 &release_sync_point, &lost_resource, &release_called, &sync_point); | |
2156 | |
2157 ReturnedResourceArray returned_to_child; | |
2158 int child_id = | |
2159 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); | |
2160 { | |
2161 // Transfer the resource to the parent. | |
2162 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2163 resource_ids_to_transfer.push_back(resource); | |
2164 TransferableResourceArray list; | |
2165 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
2166 &list); | |
2167 EXPECT_EQ(1u, list.size()); | |
2168 | |
2169 resource_provider_->ReceiveFromChild(child_id, list); | |
2170 resource_provider_->DeclareUsedResourcesFromChild(child_id, | |
2171 resource_ids_to_transfer); | |
2172 } | |
2173 | |
2174 { | |
2175 ResourceProvider::ResourceIdMap resource_map = | |
2176 resource_provider_->GetChildToParentMap(child_id); | |
2177 ResourceProvider::ResourceId parent_resource = resource_map[resource]; | |
2178 EXPECT_NE(0u, parent_resource); | |
2179 | |
2180 // Transfer to a grandparent. | |
2181 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2182 resource_ids_to_transfer.push_back(parent_resource); | |
2183 TransferableResourceArray list; | |
2184 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); | |
2185 | |
2186 // Receive back a lost resource from the grandparent. | |
2187 EXPECT_EQ(1u, list.size()); | |
2188 EXPECT_EQ(parent_resource, list[0].id); | |
2189 ReturnedResourceArray returned; | |
2190 TransferableResource::ReturnResources(list, &returned); | |
2191 EXPECT_EQ(1u, returned.size()); | |
2192 EXPECT_EQ(parent_resource, returned[0].id); | |
2193 returned[0].lost = true; | |
2194 resource_provider_->ReceiveReturnsFromParent(returned); | |
2195 } | |
2196 | |
2197 { | |
2198 EXPECT_EQ(0u, returned_to_child.size()); | |
2199 | |
2200 // Transfer resources back from the parent to the child. Set no resources as | |
2201 // being in use. | |
2202 ResourceProvider::ResourceIdArray no_resources; | |
2203 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); | |
2204 | |
2205 // Expect the resource to be lost. | |
2206 ASSERT_EQ(1u, returned_to_child.size()); | |
2207 EXPECT_TRUE(returned_to_child[0].lost); | |
2208 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); | |
2209 returned_to_child.clear(); | |
2210 } | |
2211 | |
2212 // Delete the resource in the child. Expect the resource to be lost. | |
2213 child_resource_provider_->DeleteResource(resource); | |
2214 EXPECT_TRUE(lost_resource); | |
2215 } | |
2216 | |
2217 TEST_P(ResourceProviderTest, Shutdown) { | |
2218 uint32 release_sync_point = 0; | |
2219 bool lost_resource = false; | |
2220 bool release_called = false; | |
2221 uint32 sync_point = 0; | |
2222 CreateChildMailbox( | |
2223 &release_sync_point, &lost_resource, &release_called, &sync_point); | |
2224 | |
2225 EXPECT_EQ(0u, release_sync_point); | |
2226 EXPECT_FALSE(lost_resource); | |
2227 | |
2228 child_resource_provider_ = nullptr; | |
2229 | |
2230 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) { | |
2231 EXPECT_LE(sync_point, release_sync_point); | |
2232 } | |
2233 EXPECT_TRUE(release_called); | |
2234 EXPECT_FALSE(lost_resource); | |
2235 } | |
2236 | |
2237 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { | |
2238 uint32 release_sync_point = 0; | |
2239 bool lost_resource = false; | |
2240 bool release_called = false; | |
2241 uint32 sync_point = 0; | |
2242 ResourceProvider::ResourceId resource = CreateChildMailbox( | |
2243 &release_sync_point, &lost_resource, &release_called, &sync_point); | |
2244 | |
2245 // Transfer the resource, so we can't release it properly on shutdown. | |
2246 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
2247 resource_ids_to_transfer.push_back(resource); | |
2248 TransferableResourceArray list; | |
2249 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, | |
2250 &list); | |
2251 | |
2252 EXPECT_EQ(0u, release_sync_point); | |
2253 EXPECT_FALSE(lost_resource); | |
2254 | |
2255 child_resource_provider_ = nullptr; | |
2256 | |
2257 // Since the resource is in the parent, the child considers it lost. | |
2258 EXPECT_EQ(0u, release_sync_point); | |
2259 EXPECT_TRUE(lost_resource); | |
2260 } | |
2261 | |
2262 TEST_P(ResourceProviderTest, LostContext) { | |
2263 // TextureMailbox callbacks only exist for GL textures for now. | |
2264 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2265 return; | |
2266 unsigned texture = context()->createTexture(); | |
2267 context()->bindTexture(GL_TEXTURE_2D, texture); | |
2268 gpu::Mailbox mailbox; | |
2269 context()->genMailboxCHROMIUM(mailbox.name); | |
2270 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name); | |
2271 uint32 sync_point = context()->insertSyncPoint(); | |
2272 | |
2273 EXPECT_LT(0u, sync_point); | |
2274 | |
2275 uint32 release_sync_point = 0; | |
2276 bool lost_resource = false; | |
2277 BlockingTaskRunner* main_thread_task_runner = NULL; | |
2278 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2279 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback, | |
2280 &release_sync_point, | |
2281 &lost_resource, | |
2282 &main_thread_task_runner)); | |
2283 resource_provider_->CreateResourceFromTextureMailbox( | |
2284 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass()); | |
2285 | |
2286 EXPECT_EQ(0u, release_sync_point); | |
2287 EXPECT_FALSE(lost_resource); | |
2288 EXPECT_EQ(NULL, main_thread_task_runner); | |
2289 | |
2290 resource_provider_->DidLoseOutputSurface(); | |
2291 resource_provider_ = nullptr; | |
2292 | |
2293 EXPECT_LE(sync_point, release_sync_point); | |
2294 EXPECT_TRUE(lost_resource); | |
2295 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); | |
2296 } | |
2297 | |
2298 TEST_P(ResourceProviderTest, ScopedSampler) { | |
2299 // Sampling is only supported for GL textures. | |
2300 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2301 return; | |
2302 | |
2303 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2304 new TextureStateTrackingContext); | |
2305 TextureStateTrackingContext* context = context_owned.get(); | |
2306 | |
2307 FakeOutputSurfaceClient output_surface_client; | |
2308 scoped_ptr<OutputSurface> output_surface( | |
2309 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2310 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2311 | |
2312 scoped_ptr<ResourceProvider> resource_provider( | |
2313 ResourceProvider::Create(output_surface.get(), | |
2314 shared_bitmap_manager_.get(), | |
2315 gpu_memory_buffer_manager_.get(), | |
2316 NULL, | |
2317 0, | |
2318 false, | |
2319 1)); | |
2320 | |
2321 gfx::Size size(1, 1); | |
2322 ResourceFormat format = RGBA_8888; | |
2323 int texture_id = 1; | |
2324 | |
2325 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
2326 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
2327 | |
2328 // Check that the texture gets created with the right sampler settings. | |
2329 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)) | |
2330 .Times(2); // Once to create and once to allocate. | |
2331 EXPECT_CALL(*context, | |
2332 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
2333 EXPECT_CALL(*context, | |
2334 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
2335 EXPECT_CALL( | |
2336 *context, | |
2337 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
2338 EXPECT_CALL( | |
2339 *context, | |
2340 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
2341 EXPECT_CALL(*context, | |
2342 texParameteri(GL_TEXTURE_2D, | |
2343 GL_TEXTURE_POOL_CHROMIUM, | |
2344 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); | |
2345 | |
2346 resource_provider->AllocateForTesting(id); | |
2347 Mock::VerifyAndClearExpectations(context); | |
2348 | |
2349 // Creating a sampler with the default filter should not change any texture | |
2350 // parameters. | |
2351 { | |
2352 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2353 ResourceProvider::ScopedSamplerGL sampler( | |
2354 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); | |
2355 Mock::VerifyAndClearExpectations(context); | |
2356 } | |
2357 | |
2358 // Using a different filter should be reflected in the texture parameters. | |
2359 { | |
2360 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2361 EXPECT_CALL( | |
2362 *context, | |
2363 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); | |
2364 EXPECT_CALL( | |
2365 *context, | |
2366 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); | |
2367 ResourceProvider::ScopedSamplerGL sampler( | |
2368 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST); | |
2369 Mock::VerifyAndClearExpectations(context); | |
2370 } | |
2371 | |
2372 // Test resetting to the default filter. | |
2373 { | |
2374 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2375 EXPECT_CALL(*context, | |
2376 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
2377 EXPECT_CALL(*context, | |
2378 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
2379 ResourceProvider::ScopedSamplerGL sampler( | |
2380 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); | |
2381 Mock::VerifyAndClearExpectations(context); | |
2382 } | |
2383 } | |
2384 | |
2385 TEST_P(ResourceProviderTest, ManagedResource) { | |
2386 // Sampling is only supported for GL textures. | |
2387 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2388 return; | |
2389 | |
2390 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2391 new TextureStateTrackingContext); | |
2392 TextureStateTrackingContext* context = context_owned.get(); | |
2393 | |
2394 FakeOutputSurfaceClient output_surface_client; | |
2395 scoped_ptr<OutputSurface> output_surface( | |
2396 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2397 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2398 | |
2399 scoped_ptr<ResourceProvider> resource_provider( | |
2400 ResourceProvider::Create(output_surface.get(), | |
2401 shared_bitmap_manager_.get(), | |
2402 gpu_memory_buffer_manager_.get(), | |
2403 NULL, | |
2404 0, | |
2405 false, | |
2406 1)); | |
2407 | |
2408 gfx::Size size(1, 1); | |
2409 ResourceFormat format = RGBA_8888; | |
2410 int texture_id = 1; | |
2411 | |
2412 // Check that the texture gets created with the right sampler settings. | |
2413 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource( | |
2414 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, | |
2415 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
2416 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2417 EXPECT_CALL(*context, | |
2418 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
2419 EXPECT_CALL(*context, | |
2420 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
2421 EXPECT_CALL( | |
2422 *context, | |
2423 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
2424 EXPECT_CALL( | |
2425 *context, | |
2426 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
2427 EXPECT_CALL(*context, | |
2428 texParameteri(GL_TEXTURE_2D, | |
2429 GL_TEXTURE_POOL_CHROMIUM, | |
2430 GL_TEXTURE_POOL_MANAGED_CHROMIUM)); | |
2431 resource_provider->CreateForTesting(id); | |
2432 EXPECT_NE(0u, id); | |
2433 | |
2434 Mock::VerifyAndClearExpectations(context); | |
2435 } | |
2436 | |
2437 TEST_P(ResourceProviderTest, TextureWrapMode) { | |
2438 // Sampling is only supported for GL textures. | |
2439 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2440 return; | |
2441 | |
2442 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2443 new TextureStateTrackingContext); | |
2444 TextureStateTrackingContext* context = context_owned.get(); | |
2445 | |
2446 FakeOutputSurfaceClient output_surface_client; | |
2447 scoped_ptr<OutputSurface> output_surface( | |
2448 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2449 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2450 | |
2451 scoped_ptr<ResourceProvider> resource_provider( | |
2452 ResourceProvider::Create(output_surface.get(), | |
2453 shared_bitmap_manager_.get(), | |
2454 gpu_memory_buffer_manager_.get(), | |
2455 NULL, | |
2456 0, | |
2457 false, | |
2458 1)); | |
2459 | |
2460 gfx::Size size(1, 1); | |
2461 ResourceFormat format = RGBA_8888; | |
2462 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM; | |
2463 | |
2464 for (int texture_id = 1; texture_id <= 2; ++texture_id) { | |
2465 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT; | |
2466 // Check that the texture gets created with the right sampler settings. | |
2467 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture( | |
2468 size, GL_TEXTURE_2D, texture_pool, wrap_mode, | |
2469 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
2470 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2471 EXPECT_CALL(*context, | |
2472 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
2473 EXPECT_CALL(*context, | |
2474 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
2475 EXPECT_CALL(*context, | |
2476 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode)); | |
2477 EXPECT_CALL(*context, | |
2478 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode)); | |
2479 EXPECT_CALL(*context, | |
2480 texParameteri(GL_TEXTURE_2D, | |
2481 GL_TEXTURE_POOL_CHROMIUM, | |
2482 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); | |
2483 resource_provider->CreateForTesting(id); | |
2484 EXPECT_NE(0u, id); | |
2485 | |
2486 Mock::VerifyAndClearExpectations(context); | |
2487 } | |
2488 } | |
2489 | |
2490 TEST_P(ResourceProviderTest, TextureHint) { | |
2491 // Sampling is only supported for GL textures. | |
2492 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2493 return; | |
2494 | |
2495 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2496 new TextureStateTrackingContext); | |
2497 TextureStateTrackingContext* context = context_owned.get(); | |
2498 context->set_support_texture_storage(true); | |
2499 context->set_support_texture_usage(true); | |
2500 | |
2501 FakeOutputSurfaceClient output_surface_client; | |
2502 scoped_ptr<OutputSurface> output_surface( | |
2503 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2504 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2505 | |
2506 scoped_ptr<ResourceProvider> resource_provider( | |
2507 ResourceProvider::Create(output_surface.get(), | |
2508 shared_bitmap_manager_.get(), | |
2509 gpu_memory_buffer_manager_.get(), | |
2510 NULL, | |
2511 0, | |
2512 false, | |
2513 1)); | |
2514 | |
2515 gfx::Size size(1, 1); | |
2516 ResourceFormat format = RGBA_8888; | |
2517 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM; | |
2518 | |
2519 const ResourceProvider::TextureHint hints[4] = { | |
2520 ResourceProvider::TEXTURE_HINT_DEFAULT, | |
2521 ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
2522 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER, | |
2523 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, | |
2524 }; | |
2525 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { | |
2526 // Check that the texture gets created with the right sampler settings. | |
2527 ResourceProvider::ResourceId id = | |
2528 resource_provider->CreateGLTexture(size, | |
2529 GL_TEXTURE_2D, | |
2530 texture_pool, | |
2531 GL_CLAMP_TO_EDGE, | |
2532 hints[texture_id - 1], | |
2533 format); | |
2534 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); | |
2535 EXPECT_CALL(*context, | |
2536 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | |
2537 EXPECT_CALL(*context, | |
2538 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | |
2539 EXPECT_CALL( | |
2540 *context, | |
2541 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | |
2542 EXPECT_CALL( | |
2543 *context, | |
2544 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | |
2545 EXPECT_CALL(*context, | |
2546 texParameteri(GL_TEXTURE_2D, | |
2547 GL_TEXTURE_POOL_CHROMIUM, | |
2548 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); | |
2549 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE. | |
2550 bool is_framebuffer_hint = | |
2551 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER; | |
2552 EXPECT_CALL(*context, | |
2553 texParameteri(GL_TEXTURE_2D, | |
2554 GL_TEXTURE_USAGE_ANGLE, | |
2555 GL_FRAMEBUFFER_ATTACHMENT_ANGLE)) | |
2556 .Times(is_framebuffer_hint ? 1 : 0); | |
2557 resource_provider->CreateForTesting(id); | |
2558 EXPECT_NE(0u, id); | |
2559 | |
2560 Mock::VerifyAndClearExpectations(context); | |
2561 } | |
2562 } | |
2563 | |
2564 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { | |
2565 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP) | |
2566 return; | |
2567 | |
2568 gfx::Size size(64, 64); | |
2569 const uint32_t kBadBeef = 0xbadbeef; | |
2570 scoped_ptr<SharedBitmap> shared_bitmap( | |
2571 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef)); | |
2572 | |
2573 FakeOutputSurfaceClient output_surface_client; | |
2574 scoped_ptr<OutputSurface> output_surface( | |
2575 FakeOutputSurface::CreateSoftware(make_scoped_ptr( | |
2576 new SoftwareOutputDevice))); | |
2577 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2578 | |
2579 scoped_ptr<ResourceProvider> resource_provider( | |
2580 ResourceProvider::Create(output_surface.get(), | |
2581 shared_bitmap_manager_.get(), | |
2582 gpu_memory_buffer_manager_.get(), | |
2583 main_thread_task_runner_.get(), | |
2584 0, | |
2585 false, | |
2586 1)); | |
2587 | |
2588 uint32 release_sync_point = 0; | |
2589 bool lost_resource = false; | |
2590 BlockingTaskRunner* main_thread_task_runner = NULL; | |
2591 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2592 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback, | |
2593 &release_sync_point, | |
2594 &lost_resource, | |
2595 &main_thread_task_runner)); | |
2596 TextureMailbox mailbox(shared_bitmap.get(), size); | |
2597 | |
2598 ResourceProvider::ResourceId id = | |
2599 resource_provider->CreateResourceFromTextureMailbox( | |
2600 mailbox, callback.Pass()); | |
2601 EXPECT_NE(0u, id); | |
2602 | |
2603 { | |
2604 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id); | |
2605 const SkBitmap* sk_bitmap = lock.sk_bitmap(); | |
2606 EXPECT_EQ(sk_bitmap->width(), size.width()); | |
2607 EXPECT_EQ(sk_bitmap->height(), size.height()); | |
2608 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef); | |
2609 } | |
2610 | |
2611 resource_provider->DeleteResource(id); | |
2612 EXPECT_EQ(0u, release_sync_point); | |
2613 EXPECT_FALSE(lost_resource); | |
2614 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner); | |
2615 } | |
2616 | |
2617 class ResourceProviderTestTextureMailboxGLFilters | |
2618 : public ResourceProviderTest { | |
2619 public: | |
2620 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager, | |
2621 TestGpuMemoryBufferManager* gpu_memory_buffer_manager, | |
2622 BlockingTaskRunner* main_thread_task_runner, | |
2623 bool mailbox_nearest_neighbor, | |
2624 GLenum sampler_filter) { | |
2625 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2626 new TextureStateTrackingContext); | |
2627 TextureStateTrackingContext* context = context_owned.get(); | |
2628 | |
2629 FakeOutputSurfaceClient output_surface_client; | |
2630 scoped_ptr<OutputSurface> output_surface( | |
2631 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2632 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2633 | |
2634 scoped_ptr<ResourceProvider> resource_provider( | |
2635 ResourceProvider::Create(output_surface.get(), | |
2636 shared_bitmap_manager, | |
2637 gpu_memory_buffer_manager, | |
2638 main_thread_task_runner, | |
2639 0, | |
2640 false, | |
2641 1)); | |
2642 | |
2643 unsigned texture_id = 1; | |
2644 uint32 sync_point = 30; | |
2645 unsigned target = GL_TEXTURE_2D; | |
2646 | |
2647 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2648 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2649 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2650 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2651 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2652 | |
2653 gpu::Mailbox gpu_mailbox; | |
2654 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); | |
2655 uint32 release_sync_point = 0; | |
2656 bool lost_resource = false; | |
2657 BlockingTaskRunner* mailbox_task_runner = NULL; | |
2658 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2659 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback, | |
2660 &release_sync_point, | |
2661 &lost_resource, | |
2662 &mailbox_task_runner)); | |
2663 | |
2664 TextureMailbox mailbox(gpu_mailbox, target, sync_point); | |
2665 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor); | |
2666 | |
2667 ResourceProvider::ResourceId id = | |
2668 resource_provider->CreateResourceFromTextureMailbox(mailbox, | |
2669 callback.Pass()); | |
2670 EXPECT_NE(0u, id); | |
2671 | |
2672 Mock::VerifyAndClearExpectations(context); | |
2673 | |
2674 { | |
2675 // Mailbox sync point WaitSyncPoint before using the texture. | |
2676 EXPECT_CALL(*context, waitSyncPoint(sync_point)); | |
2677 resource_provider->WaitSyncPointIfNeeded(id); | |
2678 Mock::VerifyAndClearExpectations(context); | |
2679 | |
2680 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _)) | |
2681 .WillOnce(Return(texture_id)); | |
2682 EXPECT_CALL(*context, bindTexture(target, texture_id)); | |
2683 | |
2684 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2685 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2686 | |
2687 // The sampler will reset these if |mailbox_nearest_neighbor| does not | |
2688 // match |sampler_filter|. | |
2689 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) { | |
2690 EXPECT_CALL(*context, texParameteri( | |
2691 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter)); | |
2692 EXPECT_CALL(*context, texParameteri( | |
2693 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter)); | |
2694 } | |
2695 | |
2696 ResourceProvider::ScopedSamplerGL lock( | |
2697 resource_provider.get(), id, sampler_filter); | |
2698 Mock::VerifyAndClearExpectations(context); | |
2699 | |
2700 // When done with it, a sync point should be inserted, but no produce is | |
2701 // necessary. | |
2702 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2703 EXPECT_CALL(*context, insertSyncPoint()); | |
2704 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2705 | |
2706 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2707 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2708 } | |
2709 | |
2710 resource_provider->DeleteResource(id); | |
2711 EXPECT_EQ(0u, release_sync_point); | |
2712 EXPECT_FALSE(lost_resource); | |
2713 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner); | |
2714 } | |
2715 }; | |
2716 | |
2717 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) { | |
2718 // Mailboxing is only supported for GL textures. | |
2719 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2720 return; | |
2721 | |
2722 ResourceProviderTestTextureMailboxGLFilters::RunTest( | |
2723 shared_bitmap_manager_.get(), | |
2724 gpu_memory_buffer_manager_.get(), | |
2725 main_thread_task_runner_.get(), | |
2726 false, | |
2727 GL_LINEAR); | |
2728 } | |
2729 | |
2730 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) { | |
2731 // Mailboxing is only supported for GL textures. | |
2732 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2733 return; | |
2734 | |
2735 ResourceProviderTestTextureMailboxGLFilters::RunTest( | |
2736 shared_bitmap_manager_.get(), | |
2737 gpu_memory_buffer_manager_.get(), | |
2738 main_thread_task_runner_.get(), | |
2739 true, | |
2740 GL_NEAREST); | |
2741 } | |
2742 | |
2743 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) { | |
2744 // Mailboxing is only supported for GL textures. | |
2745 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2746 return; | |
2747 | |
2748 ResourceProviderTestTextureMailboxGLFilters::RunTest( | |
2749 shared_bitmap_manager_.get(), | |
2750 gpu_memory_buffer_manager_.get(), | |
2751 main_thread_task_runner_.get(), | |
2752 true, | |
2753 GL_LINEAR); | |
2754 } | |
2755 | |
2756 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) { | |
2757 // Mailboxing is only supported for GL textures. | |
2758 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2759 return; | |
2760 | |
2761 ResourceProviderTestTextureMailboxGLFilters::RunTest( | |
2762 shared_bitmap_manager_.get(), | |
2763 gpu_memory_buffer_manager_.get(), | |
2764 main_thread_task_runner_.get(), | |
2765 false, | |
2766 GL_NEAREST); | |
2767 } | |
2768 | |
2769 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { | |
2770 // Mailboxing is only supported for GL textures. | |
2771 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2772 return; | |
2773 | |
2774 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2775 new TextureStateTrackingContext); | |
2776 TextureStateTrackingContext* context = context_owned.get(); | |
2777 | |
2778 FakeOutputSurfaceClient output_surface_client; | |
2779 scoped_ptr<OutputSurface> output_surface( | |
2780 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2781 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2782 | |
2783 scoped_ptr<ResourceProvider> resource_provider( | |
2784 ResourceProvider::Create(output_surface.get(), | |
2785 shared_bitmap_manager_.get(), | |
2786 gpu_memory_buffer_manager_.get(), | |
2787 NULL, | |
2788 0, | |
2789 false, | |
2790 1)); | |
2791 | |
2792 uint32 sync_point = 30; | |
2793 unsigned target = GL_TEXTURE_EXTERNAL_OES; | |
2794 | |
2795 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2796 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2797 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2798 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2799 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2800 | |
2801 gpu::Mailbox gpu_mailbox; | |
2802 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); | |
2803 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2804 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); | |
2805 | |
2806 TextureMailbox mailbox(gpu_mailbox, target, sync_point); | |
2807 | |
2808 ResourceProvider::ResourceId id = | |
2809 resource_provider->CreateResourceFromTextureMailbox( | |
2810 mailbox, callback.Pass()); | |
2811 EXPECT_NE(0u, id); | |
2812 | |
2813 Mock::VerifyAndClearExpectations(context); | |
2814 | |
2815 { | |
2816 // Mailbox sync point WaitSyncPoint before using the texture. | |
2817 EXPECT_CALL(*context, waitSyncPoint(sync_point)); | |
2818 resource_provider->WaitSyncPointIfNeeded(id); | |
2819 Mock::VerifyAndClearExpectations(context); | |
2820 | |
2821 unsigned texture_id = 1; | |
2822 | |
2823 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _)) | |
2824 .WillOnce(Return(texture_id)); | |
2825 | |
2826 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2827 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2828 | |
2829 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id); | |
2830 Mock::VerifyAndClearExpectations(context); | |
2831 | |
2832 // When done with it, a sync point should be inserted, but no produce is | |
2833 // necessary. | |
2834 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2835 EXPECT_CALL(*context, insertSyncPoint()); | |
2836 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2837 | |
2838 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2839 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2840 } | |
2841 } | |
2842 | |
2843 TEST_P(ResourceProviderTest, | |
2844 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) { | |
2845 // Mailboxing is only supported for GL textures. | |
2846 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2847 return; | |
2848 | |
2849 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2850 new TextureStateTrackingContext); | |
2851 TextureStateTrackingContext* context = context_owned.get(); | |
2852 | |
2853 FakeOutputSurfaceClient output_surface_client; | |
2854 scoped_ptr<OutputSurface> output_surface( | |
2855 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2856 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2857 | |
2858 scoped_ptr<ResourceProvider> resource_provider( | |
2859 ResourceProvider::Create(output_surface.get(), | |
2860 shared_bitmap_manager_.get(), | |
2861 gpu_memory_buffer_manager_.get(), | |
2862 NULL, | |
2863 0, | |
2864 false, | |
2865 1)); | |
2866 | |
2867 uint32 sync_point = 30; | |
2868 unsigned target = GL_TEXTURE_2D; | |
2869 | |
2870 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2871 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2872 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2873 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2874 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2875 | |
2876 gpu::Mailbox gpu_mailbox; | |
2877 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); | |
2878 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2879 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); | |
2880 | |
2881 TextureMailbox mailbox(gpu_mailbox, target, sync_point); | |
2882 | |
2883 ResourceProvider::ResourceId id = | |
2884 resource_provider->CreateResourceFromTextureMailbox(mailbox, | |
2885 callback.Pass()); | |
2886 EXPECT_NE(0u, id); | |
2887 | |
2888 Mock::VerifyAndClearExpectations(context); | |
2889 | |
2890 { | |
2891 // First call to WaitSyncPointIfNeeded should call waitSyncPoint. | |
2892 EXPECT_CALL(*context, waitSyncPoint(sync_point)); | |
2893 resource_provider->WaitSyncPointIfNeeded(id); | |
2894 Mock::VerifyAndClearExpectations(context); | |
2895 | |
2896 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint. | |
2897 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2898 resource_provider->WaitSyncPointIfNeeded(id); | |
2899 Mock::VerifyAndClearExpectations(context); | |
2900 } | |
2901 } | |
2902 | |
2903 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { | |
2904 // Mailboxing is only supported for GL textures. | |
2905 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
2906 return; | |
2907 | |
2908 scoped_ptr<TextureStateTrackingContext> context_owned( | |
2909 new TextureStateTrackingContext); | |
2910 TextureStateTrackingContext* context = context_owned.get(); | |
2911 | |
2912 FakeOutputSurfaceClient output_surface_client; | |
2913 scoped_ptr<OutputSurface> output_surface( | |
2914 FakeOutputSurface::Create3d(context_owned.Pass())); | |
2915 CHECK(output_surface->BindToClient(&output_surface_client)); | |
2916 | |
2917 scoped_ptr<ResourceProvider> resource_provider( | |
2918 ResourceProvider::Create(output_surface.get(), | |
2919 shared_bitmap_manager_.get(), | |
2920 gpu_memory_buffer_manager_.get(), | |
2921 NULL, | |
2922 0, | |
2923 false, | |
2924 1)); | |
2925 | |
2926 uint32 sync_point = 0; | |
2927 unsigned target = GL_TEXTURE_2D; | |
2928 | |
2929 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); | |
2930 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2931 EXPECT_CALL(*context, insertSyncPoint()).Times(0); | |
2932 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0); | |
2933 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0); | |
2934 | |
2935 gpu::Mailbox gpu_mailbox; | |
2936 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); | |
2937 scoped_ptr<SingleReleaseCallbackImpl> callback = | |
2938 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)); | |
2939 | |
2940 TextureMailbox mailbox(gpu_mailbox, target, sync_point); | |
2941 | |
2942 ResourceProvider::ResourceId id = | |
2943 resource_provider->CreateResourceFromTextureMailbox(mailbox, | |
2944 callback.Pass()); | |
2945 EXPECT_NE(0u, id); | |
2946 | |
2947 Mock::VerifyAndClearExpectations(context); | |
2948 | |
2949 { | |
2950 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint. | |
2951 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); | |
2952 resource_provider->WaitSyncPointIfNeeded(id); | |
2953 Mock::VerifyAndClearExpectations(context); | |
2954 } | |
2955 } | |
2956 | |
2957 class AllocationTrackingContext3D : public TestWebGraphicsContext3D { | |
2958 public: | |
2959 MOCK_METHOD0(NextTextureId, GLuint()); | |
2960 MOCK_METHOD1(RetireTextureId, void(GLuint id)); | |
2961 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); | |
2962 MOCK_METHOD5(texStorage2DEXT, | |
2963 void(GLenum target, | |
2964 GLint levels, | |
2965 GLuint internalformat, | |
2966 GLint width, | |
2967 GLint height)); | |
2968 MOCK_METHOD9(texImage2D, | |
2969 void(GLenum target, | |
2970 GLint level, | |
2971 GLenum internalformat, | |
2972 GLsizei width, | |
2973 GLsizei height, | |
2974 GLint border, | |
2975 GLenum format, | |
2976 GLenum type, | |
2977 const void* pixels)); | |
2978 MOCK_METHOD9(texSubImage2D, | |
2979 void(GLenum target, | |
2980 GLint level, | |
2981 GLint xoffset, | |
2982 GLint yoffset, | |
2983 GLsizei width, | |
2984 GLsizei height, | |
2985 GLenum format, | |
2986 GLenum type, | |
2987 const void* pixels)); | |
2988 MOCK_METHOD9(asyncTexImage2DCHROMIUM, | |
2989 void(GLenum target, | |
2990 GLint level, | |
2991 GLenum internalformat, | |
2992 GLsizei width, | |
2993 GLsizei height, | |
2994 GLint border, | |
2995 GLenum format, | |
2996 GLenum type, | |
2997 const void* pixels)); | |
2998 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM, | |
2999 void(GLenum target, | |
3000 GLint level, | |
3001 GLint xoffset, | |
3002 GLint yoffset, | |
3003 GLsizei width, | |
3004 GLsizei height, | |
3005 GLenum format, | |
3006 GLenum type, | |
3007 const void* pixels)); | |
3008 MOCK_METHOD8(compressedTexImage2D, | |
3009 void(GLenum target, | |
3010 GLint level, | |
3011 GLenum internalformat, | |
3012 GLsizei width, | |
3013 GLsizei height, | |
3014 GLint border, | |
3015 GLsizei image_size, | |
3016 const void* data)); | |
3017 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum)); | |
3018 MOCK_METHOD4(createImageCHROMIUM, | |
3019 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum)); | |
3020 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint)); | |
3021 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint)); | |
3022 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint)); | |
3023 | |
3024 // We're mocking bindTexture, so we override | |
3025 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the | |
3026 // currently bound texture. | |
3027 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {} | |
3028 }; | |
3029 | |
3030 TEST_P(ResourceProviderTest, TextureAllocation) { | |
3031 // Only for GL textures. | |
3032 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3033 return; | |
3034 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3035 new StrictMock<AllocationTrackingContext3D>); | |
3036 AllocationTrackingContext3D* context = context_owned.get(); | |
3037 | |
3038 FakeOutputSurfaceClient output_surface_client; | |
3039 scoped_ptr<OutputSurface> output_surface( | |
3040 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3041 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3042 | |
3043 scoped_ptr<ResourceProvider> resource_provider( | |
3044 ResourceProvider::Create(output_surface.get(), | |
3045 shared_bitmap_manager_.get(), | |
3046 gpu_memory_buffer_manager_.get(), | |
3047 NULL, | |
3048 0, | |
3049 false, | |
3050 1)); | |
3051 | |
3052 gfx::Size size(2, 2); | |
3053 gfx::Vector2d offset(0, 0); | |
3054 ResourceFormat format = RGBA_8888; | |
3055 ResourceProvider::ResourceId id = 0; | |
3056 uint8_t pixels[16] = { 0 }; | |
3057 int texture_id = 123; | |
3058 | |
3059 // Lazy allocation. Don't allocate when creating the resource. | |
3060 id = resource_provider->CreateResource( | |
3061 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3062 | |
3063 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3064 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); | |
3065 resource_provider->CreateForTesting(id); | |
3066 | |
3067 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3068 resource_provider->DeleteResource(id); | |
3069 | |
3070 Mock::VerifyAndClearExpectations(context); | |
3071 | |
3072 // Do allocate when we set the pixels. | |
3073 id = resource_provider->CreateResource( | |
3074 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3075 | |
3076 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3077 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); | |
3078 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1); | |
3079 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1); | |
3080 resource_provider->CopyToResource(id, pixels, size); | |
3081 | |
3082 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3083 resource_provider->DeleteResource(id); | |
3084 | |
3085 Mock::VerifyAndClearExpectations(context); | |
3086 | |
3087 // Same for async version. | |
3088 id = resource_provider->CreateResource( | |
3089 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3090 resource_provider->AcquirePixelBuffer(id); | |
3091 | |
3092 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3093 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3094 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) | |
3095 .Times(1); | |
3096 resource_provider->BeginSetPixels(id); | |
3097 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id)); | |
3098 | |
3099 resource_provider->ReleasePixelBuffer(id); | |
3100 | |
3101 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3102 resource_provider->DeleteResource(id); | |
3103 | |
3104 Mock::VerifyAndClearExpectations(context); | |
3105 } | |
3106 | |
3107 TEST_P(ResourceProviderTest, TextureAllocationHint) { | |
3108 // Only for GL textures. | |
3109 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3110 return; | |
3111 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3112 new StrictMock<AllocationTrackingContext3D>); | |
3113 AllocationTrackingContext3D* context = context_owned.get(); | |
3114 context->set_support_texture_storage(true); | |
3115 context->set_support_texture_usage(true); | |
3116 | |
3117 FakeOutputSurfaceClient output_surface_client; | |
3118 scoped_ptr<OutputSurface> output_surface( | |
3119 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3120 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3121 | |
3122 scoped_ptr<ResourceProvider> resource_provider( | |
3123 ResourceProvider::Create(output_surface.get(), | |
3124 shared_bitmap_manager_.get(), | |
3125 gpu_memory_buffer_manager_.get(), | |
3126 NULL, | |
3127 0, | |
3128 false, | |
3129 1)); | |
3130 | |
3131 gfx::Size size(2, 2); | |
3132 | |
3133 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888}; | |
3134 const ResourceProvider::TextureHint hints[4] = { | |
3135 ResourceProvider::TEXTURE_HINT_DEFAULT, | |
3136 ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
3137 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER, | |
3138 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, | |
3139 }; | |
3140 for (size_t i = 0; i < arraysize(formats); ++i) { | |
3141 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { | |
3142 // Lazy allocation. Don't allocate when creating the resource. | |
3143 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3144 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]); | |
3145 | |
3146 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3147 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3148 bool is_immutable_hint = | |
3149 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE; | |
3150 bool support_immutable_texture = | |
3151 is_immutable_hint && formats[i] == RGBA_8888; | |
3152 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)) | |
3153 .Times(support_immutable_texture ? 1 : 0); | |
3154 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)) | |
3155 .Times(support_immutable_texture ? 0 : 1); | |
3156 resource_provider->AllocateForTesting(id); | |
3157 | |
3158 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3159 resource_provider->DeleteResource(id); | |
3160 | |
3161 Mock::VerifyAndClearExpectations(context); | |
3162 } | |
3163 } | |
3164 } | |
3165 | |
3166 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) { | |
3167 // Only for GL textures. | |
3168 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3169 return; | |
3170 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3171 new StrictMock<AllocationTrackingContext3D>); | |
3172 AllocationTrackingContext3D* context = context_owned.get(); | |
3173 context->set_support_texture_format_bgra8888(true); | |
3174 context->set_support_texture_storage(true); | |
3175 context->set_support_texture_usage(true); | |
3176 | |
3177 FakeOutputSurfaceClient output_surface_client; | |
3178 scoped_ptr<OutputSurface> output_surface( | |
3179 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3180 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3181 | |
3182 scoped_ptr<ResourceProvider> resource_provider( | |
3183 ResourceProvider::Create(output_surface.get(), | |
3184 shared_bitmap_manager_.get(), | |
3185 gpu_memory_buffer_manager_.get(), | |
3186 NULL, | |
3187 0, | |
3188 false, | |
3189 1)); | |
3190 | |
3191 gfx::Size size(2, 2); | |
3192 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888}; | |
3193 | |
3194 const ResourceProvider::TextureHint hints[4] = { | |
3195 ResourceProvider::TEXTURE_HINT_DEFAULT, | |
3196 ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
3197 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER, | |
3198 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER, | |
3199 }; | |
3200 for (size_t i = 0; i < arraysize(formats); ++i) { | |
3201 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) { | |
3202 // Lazy allocation. Don't allocate when creating the resource. | |
3203 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3204 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]); | |
3205 | |
3206 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3207 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3208 bool is_immutable_hint = | |
3209 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE; | |
3210 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)) | |
3211 .Times(is_immutable_hint ? 1 : 0); | |
3212 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)) | |
3213 .Times(is_immutable_hint ? 0 : 1); | |
3214 resource_provider->AllocateForTesting(id); | |
3215 | |
3216 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3217 resource_provider->DeleteResource(id); | |
3218 | |
3219 Mock::VerifyAndClearExpectations(context); | |
3220 } | |
3221 } | |
3222 } | |
3223 | |
3224 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { | |
3225 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3226 return; | |
3227 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3228 new StrictMock<AllocationTrackingContext3D>); | |
3229 AllocationTrackingContext3D* context = context_owned.get(); | |
3230 | |
3231 FakeOutputSurfaceClient output_surface_client; | |
3232 scoped_ptr<OutputSurface> output_surface( | |
3233 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3234 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3235 | |
3236 gfx::Size size(2, 2); | |
3237 ResourceFormat format = RGBA_8888; | |
3238 ResourceProvider::ResourceId id = 0; | |
3239 int texture_id = 123; | |
3240 | |
3241 scoped_ptr<ResourceProvider> resource_provider( | |
3242 ResourceProvider::Create(output_surface.get(), | |
3243 shared_bitmap_manager_.get(), | |
3244 gpu_memory_buffer_manager_.get(), | |
3245 NULL, | |
3246 0, | |
3247 false, | |
3248 1)); | |
3249 | |
3250 id = resource_provider->CreateResource( | |
3251 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3252 resource_provider->AcquirePixelBuffer(id); | |
3253 | |
3254 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3255 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3256 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) | |
3257 .Times(1); | |
3258 resource_provider->BeginSetPixels(id); | |
3259 | |
3260 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id)); | |
3261 | |
3262 resource_provider->ReleasePixelBuffer(id); | |
3263 | |
3264 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3265 resource_provider->DeleteResource(id); | |
3266 | |
3267 Mock::VerifyAndClearExpectations(context); | |
3268 } | |
3269 | |
3270 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { | |
3271 // Only for GL textures. | |
3272 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3273 return; | |
3274 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3275 new StrictMock<AllocationTrackingContext3D>); | |
3276 AllocationTrackingContext3D* context = context_owned.get(); | |
3277 | |
3278 FakeOutputSurfaceClient output_surface_client; | |
3279 scoped_ptr<OutputSurface> output_surface( | |
3280 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3281 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3282 | |
3283 gfx::Size size(2, 2); | |
3284 ResourceFormat format = RGBA_8888; | |
3285 ResourceProvider::ResourceId id = 0; | |
3286 int texture_id = 123; | |
3287 | |
3288 scoped_ptr<ResourceProvider> resource_provider( | |
3289 ResourceProvider::Create(output_surface.get(), | |
3290 shared_bitmap_manager_.get(), | |
3291 gpu_memory_buffer_manager_.get(), | |
3292 NULL, | |
3293 0, | |
3294 false, | |
3295 1)); | |
3296 | |
3297 id = resource_provider->CreateResource( | |
3298 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3299 resource_provider->AcquirePixelBuffer(id); | |
3300 | |
3301 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3302 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3303 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) | |
3304 .Times(1); | |
3305 resource_provider->BeginSetPixels(id); | |
3306 | |
3307 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); | |
3308 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1); | |
3309 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1); | |
3310 resource_provider->ForceSetPixelsToComplete(id); | |
3311 | |
3312 resource_provider->ReleasePixelBuffer(id); | |
3313 | |
3314 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3315 resource_provider->DeleteResource(id); | |
3316 | |
3317 Mock::VerifyAndClearExpectations(context); | |
3318 } | |
3319 | |
3320 TEST_P(ResourceProviderTest, PixelBufferLostContext) { | |
3321 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3322 new NiceMock<AllocationTrackingContext3D>); | |
3323 AllocationTrackingContext3D* context = context_owned.get(); | |
3324 | |
3325 FakeOutputSurfaceClient output_surface_client; | |
3326 scoped_ptr<OutputSurface> output_surface( | |
3327 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3328 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3329 | |
3330 gfx::Size size(2, 2); | |
3331 ResourceFormat format = RGBA_8888; | |
3332 ResourceProvider::ResourceId id = 0; | |
3333 int texture_id = 123; | |
3334 | |
3335 scoped_ptr<ResourceProvider> resource_provider( | |
3336 ResourceProvider::Create(output_surface.get(), | |
3337 shared_bitmap_manager_.get(), | |
3338 gpu_memory_buffer_manager_.get(), | |
3339 NULL, | |
3340 0, | |
3341 false, | |
3342 1)); | |
3343 | |
3344 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id)); | |
3345 | |
3346 id = resource_provider->CreateResource( | |
3347 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3348 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, | |
3349 GL_INNOCENT_CONTEXT_RESET_ARB); | |
3350 | |
3351 resource_provider->AcquirePixelBuffer(id); | |
3352 int stride; | |
3353 void* buffer = resource_provider->MapPixelBuffer(id, &stride); | |
3354 EXPECT_FALSE(buffer); | |
3355 resource_provider->UnmapPixelBuffer(id); | |
3356 Mock::VerifyAndClearExpectations(context); | |
3357 } | |
3358 | |
3359 TEST_P(ResourceProviderTest, Image_GLTexture) { | |
3360 // Only for GL textures. | |
3361 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3362 return; | |
3363 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3364 new StrictMock<AllocationTrackingContext3D>); | |
3365 AllocationTrackingContext3D* context = context_owned.get(); | |
3366 | |
3367 FakeOutputSurfaceClient output_surface_client; | |
3368 scoped_ptr<OutputSurface> output_surface( | |
3369 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3370 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3371 | |
3372 const int kWidth = 2; | |
3373 const int kHeight = 2; | |
3374 gfx::Size size(kWidth, kHeight); | |
3375 ResourceFormat format = RGBA_8888; | |
3376 ResourceProvider::ResourceId id = 0; | |
3377 const unsigned kTextureId = 123u; | |
3378 const unsigned kImageId = 234u; | |
3379 | |
3380 scoped_ptr<ResourceProvider> resource_provider( | |
3381 ResourceProvider::Create(output_surface.get(), | |
3382 shared_bitmap_manager_.get(), | |
3383 gpu_memory_buffer_manager_.get(), | |
3384 NULL, | |
3385 0, | |
3386 false, | |
3387 1)); | |
3388 | |
3389 id = resource_provider->CreateResource( | |
3390 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3391 | |
3392 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) | |
3393 .WillOnce(Return(kImageId)) | |
3394 .RetiresOnSaturation(); | |
3395 { | |
3396 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( | |
3397 resource_provider.get(), id); | |
3398 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer()); | |
3399 } | |
3400 | |
3401 EXPECT_CALL(*context, NextTextureId()) | |
3402 .WillOnce(Return(kTextureId)) | |
3403 .RetiresOnSaturation(); | |
3404 // Once in CreateTextureId and once in BindForSampling | |
3405 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2) | |
3406 .RetiresOnSaturation(); | |
3407 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) | |
3408 .Times(1) | |
3409 .RetiresOnSaturation(); | |
3410 { | |
3411 ResourceProvider::ScopedSamplerGL lock_gl( | |
3412 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); | |
3413 EXPECT_EQ(kTextureId, lock_gl.texture_id()); | |
3414 } | |
3415 | |
3416 { | |
3417 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( | |
3418 resource_provider.get(), id); | |
3419 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer()); | |
3420 } | |
3421 | |
3422 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1) | |
3423 .RetiresOnSaturation(); | |
3424 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) | |
3425 .Times(1) | |
3426 .RetiresOnSaturation(); | |
3427 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) | |
3428 .Times(1) | |
3429 .RetiresOnSaturation(); | |
3430 EXPECT_CALL(*context, RetireTextureId(kTextureId)) | |
3431 .Times(1) | |
3432 .RetiresOnSaturation(); | |
3433 { | |
3434 ResourceProvider::ScopedSamplerGL lock_gl( | |
3435 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); | |
3436 EXPECT_EQ(kTextureId, lock_gl.texture_id()); | |
3437 } | |
3438 | |
3439 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) | |
3440 .Times(1) | |
3441 .RetiresOnSaturation(); | |
3442 } | |
3443 | |
3444 TEST_P(ResourceProviderTest, CopyResource_GLTexture) { | |
3445 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3446 return; | |
3447 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3448 new StrictMock<AllocationTrackingContext3D>); | |
3449 AllocationTrackingContext3D* context = context_owned.get(); | |
3450 context_owned->set_support_sync_query(true); | |
3451 | |
3452 FakeOutputSurfaceClient output_surface_client; | |
3453 scoped_ptr<OutputSurface> output_surface( | |
3454 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3455 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client)); | |
3456 | |
3457 const int kWidth = 2; | |
3458 const int kHeight = 2; | |
3459 gfx::Size size(kWidth, kHeight); | |
3460 ResourceFormat format = RGBA_8888; | |
3461 ResourceProvider::ResourceId source_id = 0; | |
3462 ResourceProvider::ResourceId dest_id = 0; | |
3463 const unsigned kSourceTextureId = 123u; | |
3464 const unsigned kDestTextureId = 321u; | |
3465 const unsigned kImageId = 234u; | |
3466 | |
3467 scoped_ptr<ResourceProvider> resource_provider( | |
3468 ResourceProvider::Create(output_surface.get(), | |
3469 shared_bitmap_manager_.get(), | |
3470 gpu_memory_buffer_manager_.get(), | |
3471 NULL, | |
3472 0, | |
3473 false, | |
3474 1)); | |
3475 | |
3476 source_id = resource_provider->CreateResource( | |
3477 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3478 | |
3479 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) | |
3480 .WillOnce(Return(kImageId)) | |
3481 .RetiresOnSaturation(); | |
3482 { | |
3483 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( | |
3484 resource_provider.get(), source_id); | |
3485 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer()); | |
3486 } | |
3487 Mock::VerifyAndClearExpectations(context); | |
3488 | |
3489 dest_id = resource_provider->CreateResource( | |
3490 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); | |
3491 | |
3492 EXPECT_CALL(*context, NextTextureId()) | |
3493 .WillOnce(Return(kDestTextureId)) | |
3494 .RetiresOnSaturation(); | |
3495 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId)) | |
3496 .Times(2) | |
3497 .RetiresOnSaturation(); | |
3498 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, | |
3499 GL_UNSIGNED_BYTE, nullptr)) | |
3500 .Times(1) | |
3501 .RetiresOnSaturation(); | |
3502 EXPECT_CALL(*context, NextTextureId()) | |
3503 .WillOnce(Return(kSourceTextureId)) | |
3504 .RetiresOnSaturation(); | |
3505 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) | |
3506 .Times(2) | |
3507 .RetiresOnSaturation(); | |
3508 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) | |
3509 .Times(1) | |
3510 .RetiresOnSaturation(); | |
3511 resource_provider->CopyResource(source_id, dest_id); | |
3512 Mock::VerifyAndClearExpectations(context); | |
3513 | |
3514 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) | |
3515 .Times(1) | |
3516 .RetiresOnSaturation(); | |
3517 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId)) | |
3518 .Times(1) | |
3519 .RetiresOnSaturation(); | |
3520 EXPECT_CALL(*context, RetireTextureId(kDestTextureId)) | |
3521 .Times(1) | |
3522 .RetiresOnSaturation(); | |
3523 resource_provider->DeleteResource(source_id); | |
3524 resource_provider->DeleteResource(dest_id); | |
3525 } | |
3526 | |
3527 void InitializeGLAndCheck(ContextSharedData* shared_data, | |
3528 ResourceProvider* resource_provider, | |
3529 FakeOutputSurface* output_surface) { | |
3530 scoped_ptr<ResourceProviderContext> context_owned = | |
3531 ResourceProviderContext::Create(shared_data); | |
3532 ResourceProviderContext* context = context_owned.get(); | |
3533 | |
3534 scoped_refptr<TestContextProvider> context_provider = | |
3535 TestContextProvider::Create(context_owned.Pass()); | |
3536 output_surface->InitializeAndSetContext3d(context_provider, nullptr); | |
3537 resource_provider->InitializeGL(); | |
3538 | |
3539 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, | |
3540 resource_provider, context); | |
3541 } | |
3542 | |
3543 TEST(ResourceProviderTest, BasicInitializeGLSoftware) { | |
3544 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create(); | |
3545 bool delegated_rendering = false; | |
3546 scoped_ptr<FakeOutputSurface> output_surface( | |
3547 FakeOutputSurface::CreateDeferredGL( | |
3548 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice), | |
3549 delegated_rendering)); | |
3550 FakeOutputSurfaceClient client(output_surface.get()); | |
3551 EXPECT_TRUE(output_surface->BindToClient(&client)); | |
3552 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
3553 new TestSharedBitmapManager()); | |
3554 scoped_ptr<ResourceProvider> resource_provider( | |
3555 ResourceProvider::Create(output_surface.get(), | |
3556 shared_bitmap_manager.get(), | |
3557 NULL, | |
3558 NULL, | |
3559 0, | |
3560 false, | |
3561 1)); | |
3562 | |
3563 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP, | |
3564 resource_provider.get(), NULL); | |
3565 | |
3566 InitializeGLAndCheck(shared_data.get(), | |
3567 resource_provider.get(), | |
3568 output_surface.get()); | |
3569 | |
3570 resource_provider->InitializeSoftware(); | |
3571 output_surface->ReleaseGL(); | |
3572 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP, | |
3573 resource_provider.get(), NULL); | |
3574 | |
3575 InitializeGLAndCheck(shared_data.get(), | |
3576 resource_provider.get(), | |
3577 output_surface.get()); | |
3578 } | |
3579 | |
3580 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { | |
3581 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3582 return; | |
3583 | |
3584 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3585 new AllocationTrackingContext3D); | |
3586 AllocationTrackingContext3D* context = context_owned.get(); | |
3587 context_owned->set_support_compressed_texture_etc1(true); | |
3588 | |
3589 FakeOutputSurfaceClient output_surface_client; | |
3590 scoped_ptr<OutputSurface> output_surface( | |
3591 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3592 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3593 | |
3594 gfx::Size size(4, 4); | |
3595 scoped_ptr<ResourceProvider> resource_provider( | |
3596 ResourceProvider::Create(output_surface.get(), | |
3597 shared_bitmap_manager_.get(), | |
3598 gpu_memory_buffer_manager_.get(), | |
3599 NULL, | |
3600 0, | |
3601 false, | |
3602 1)); | |
3603 int texture_id = 123; | |
3604 | |
3605 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3606 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1); | |
3607 EXPECT_NE(0u, id); | |
3608 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3609 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); | |
3610 resource_provider->AllocateForTesting(id); | |
3611 | |
3612 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3613 resource_provider->DeleteResource(id); | |
3614 } | |
3615 | |
3616 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { | |
3617 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) | |
3618 return; | |
3619 | |
3620 scoped_ptr<AllocationTrackingContext3D> context_owned( | |
3621 new AllocationTrackingContext3D); | |
3622 AllocationTrackingContext3D* context = context_owned.get(); | |
3623 context_owned->set_support_compressed_texture_etc1(true); | |
3624 | |
3625 FakeOutputSurfaceClient output_surface_client; | |
3626 scoped_ptr<OutputSurface> output_surface( | |
3627 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3628 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3629 | |
3630 gfx::Size size(4, 4); | |
3631 scoped_ptr<ResourceProvider> resource_provider( | |
3632 ResourceProvider::Create(output_surface.get(), | |
3633 shared_bitmap_manager_.get(), | |
3634 gpu_memory_buffer_manager_.get(), | |
3635 NULL, | |
3636 0, | |
3637 false, | |
3638 1)); | |
3639 int texture_id = 123; | |
3640 uint8_t pixels[8]; | |
3641 | |
3642 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3643 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1); | |
3644 EXPECT_NE(0u, id); | |
3645 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); | |
3646 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); | |
3647 EXPECT_CALL(*context, | |
3648 compressedTexImage2D( | |
3649 _, 0, _, size.width(), size.height(), _, _, _)).Times(1); | |
3650 resource_provider->CopyToResource(id, pixels, size); | |
3651 | |
3652 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); | |
3653 resource_provider->DeleteResource(id); | |
3654 } | |
3655 | |
3656 INSTANTIATE_TEST_CASE_P( | |
3657 ResourceProviderTests, | |
3658 ResourceProviderTest, | |
3659 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, | |
3660 ResourceProvider::RESOURCE_TYPE_BITMAP)); | |
3661 | |
3662 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D { | |
3663 public: | |
3664 GLuint NextTextureId() override { | |
3665 base::AutoLock lock(namespace_->lock); | |
3666 return namespace_->next_texture_id++; | |
3667 } | |
3668 void RetireTextureId(GLuint) override {} | |
3669 GLuint PeekTextureId() { | |
3670 base::AutoLock lock(namespace_->lock); | |
3671 return namespace_->next_texture_id; | |
3672 } | |
3673 }; | |
3674 | |
3675 TEST(ResourceProviderTest, TextureAllocationChunkSize) { | |
3676 scoped_ptr<TextureIdAllocationTrackingContext> context_owned( | |
3677 new TextureIdAllocationTrackingContext); | |
3678 TextureIdAllocationTrackingContext* context = context_owned.get(); | |
3679 | |
3680 FakeOutputSurfaceClient output_surface_client; | |
3681 scoped_ptr<OutputSurface> output_surface( | |
3682 FakeOutputSurface::Create3d(context_owned.Pass())); | |
3683 CHECK(output_surface->BindToClient(&output_surface_client)); | |
3684 scoped_ptr<SharedBitmapManager> shared_bitmap_manager( | |
3685 new TestSharedBitmapManager()); | |
3686 | |
3687 gfx::Size size(1, 1); | |
3688 ResourceFormat format = RGBA_8888; | |
3689 | |
3690 { | |
3691 size_t kTextureAllocationChunkSize = 1; | |
3692 scoped_ptr<ResourceProvider> resource_provider( | |
3693 ResourceProvider::Create(output_surface.get(), | |
3694 shared_bitmap_manager.get(), | |
3695 NULL, | |
3696 NULL, | |
3697 0, | |
3698 false, | |
3699 kTextureAllocationChunkSize)); | |
3700 | |
3701 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3702 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
3703 format); | |
3704 resource_provider->AllocateForTesting(id); | |
3705 Mock::VerifyAndClearExpectations(context); | |
3706 | |
3707 DCHECK_EQ(2u, context->PeekTextureId()); | |
3708 resource_provider->DeleteResource(id); | |
3709 } | |
3710 | |
3711 { | |
3712 size_t kTextureAllocationChunkSize = 8; | |
3713 scoped_ptr<ResourceProvider> resource_provider( | |
3714 ResourceProvider::Create(output_surface.get(), | |
3715 shared_bitmap_manager.get(), | |
3716 NULL, | |
3717 NULL, | |
3718 0, | |
3719 false, | |
3720 kTextureAllocationChunkSize)); | |
3721 | |
3722 ResourceProvider::ResourceId id = resource_provider->CreateResource( | |
3723 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, | |
3724 format); | |
3725 resource_provider->AllocateForTesting(id); | |
3726 Mock::VerifyAndClearExpectations(context); | |
3727 | |
3728 DCHECK_EQ(10u, context->PeekTextureId()); | |
3729 resource_provider->DeleteResource(id); | |
3730 } | |
3731 } | |
3732 | |
3733 } // namespace | |
3734 } // namespace cc | |
OLD | NEW |