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.
5 #include "cc/resources/resource_provider.h"
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/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.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"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
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
;
62 static void SharedMemoryReleaseCallback(
63 scoped_ptr
<base::SharedMemory
> memory
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedMemoryCallback(
70 scoped_ptr
<base::SharedMemory
> shared_memory
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<base::SharedMemory
> CreateAndFillSharedMemory(
83 const gfx::Size
& size
,
85 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
86 CHECK(shared_memory
->CreateAndMapAnonymous(4 * size
.GetArea()));
87 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_memory
->memory());
89 std::fill_n(pixels
, size
.GetArea(), value
);
90 return shared_memory
.Pass();
93 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
95 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
96 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
97 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
98 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
99 MOCK_METHOD2(produceTextureCHROMIUM
,
100 void(GLenum target
, const GLbyte
* mailbox
));
101 MOCK_METHOD2(consumeTextureCHROMIUM
,
102 void(GLenum target
, const GLbyte
* mailbox
));
104 // Force all textures to be consecutive numbers starting at "1",
105 // so we easily can test for them.
106 virtual GLuint
NextTextureId() override
{
107 base::AutoLock
lock(namespace_
->lock
);
108 return namespace_
->next_texture_id
++;
110 virtual void RetireTextureId(GLuint
) override
{}
113 // Shared data between multiple ResourceProviderContext. This contains mailbox
114 // contents as well as information about sync points.
115 class ContextSharedData
{
117 static scoped_ptr
<ContextSharedData
> Create() {
118 return make_scoped_ptr(new ContextSharedData());
121 uint32
InsertSyncPoint() { return next_sync_point_
++; }
123 void GenMailbox(GLbyte
* mailbox
) {
124 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
125 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
129 void ProduceTexture(const GLbyte
* mailbox_name
,
131 scoped_refptr
<TestTexture
> texture
) {
132 unsigned mailbox
= 0;
133 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
134 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
135 textures_
[mailbox
] = texture
;
136 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
137 sync_point_for_mailbox_
[mailbox
] = sync_point
;
140 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
142 unsigned mailbox
= 0;
143 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
144 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
146 // If the latest sync point the context has waited on is before the sync
147 // point for when the mailbox was set, pretend we never saw that
149 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
151 return scoped_refptr
<TestTexture
>();
153 return textures_
[mailbox
];
157 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
159 uint32 next_sync_point_
;
160 unsigned next_mailbox_
;
161 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
162 TextureMap textures_
;
163 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
166 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
168 static scoped_ptr
<ResourceProviderContext
> Create(
169 ContextSharedData
* shared_data
) {
170 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
173 GLuint
insertSyncPoint() override
{
174 uint32 sync_point
= shared_data_
->InsertSyncPoint();
175 // Commit the produceTextureCHROMIUM calls at this point, so that
176 // they're associated with the sync point.
177 for (PendingProduceTextureList::iterator it
=
178 pending_produce_textures_
.begin();
179 it
!= pending_produce_textures_
.end();
181 shared_data_
->ProduceTexture(
182 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
184 pending_produce_textures_
.clear();
188 void waitSyncPoint(GLuint sync_point
) override
{
189 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
192 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
194 void texStorage2DEXT(GLenum target
,
196 GLuint internalformat
,
198 GLint height
) override
{
199 CheckTextureIsBound(target
);
200 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
201 ASSERT_EQ(1, levels
);
202 GLenum format
= GL_RGBA
;
203 switch (internalformat
) {
207 format
= GL_BGRA_EXT
;
212 AllocateTexture(gfx::Size(width
, height
), format
);
215 void texImage2D(GLenum target
,
217 GLenum internalformat
,
223 const void* pixels
) override
{
224 CheckTextureIsBound(target
);
225 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
227 ASSERT_EQ(internalformat
, format
);
228 ASSERT_FALSE(border
);
229 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
230 AllocateTexture(gfx::Size(width
, height
), format
);
232 SetPixels(0, 0, width
, height
, pixels
);
235 void texSubImage2D(GLenum target
,
243 const void* pixels
) override
{
244 CheckTextureIsBound(target
);
245 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
247 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
249 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
250 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
253 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
256 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
257 return shared_data_
->GenMailbox(mailbox
);
260 void produceTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
261 CheckTextureIsBound(target
);
263 // Delay moving the texture into the mailbox until the next
264 // InsertSyncPoint, so that it is not visible to other contexts that
265 // haven't waited on that sync point.
266 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
267 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
268 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
269 pending
->texture
= BoundTexture(target
);
270 pending_produce_textures_
.push_back(pending
.Pass());
273 void consumeTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
274 CheckTextureIsBound(target
);
275 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
276 scoped_refptr
<TestTexture
> texture
=
277 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
278 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
281 void GetPixels(const gfx::Size
& size
,
282 ResourceFormat format
,
284 CheckTextureIsBound(GL_TEXTURE_2D
);
285 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
286 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
287 ASSERT_EQ(texture
->size
, size
);
288 ASSERT_EQ(texture
->format
, format
);
289 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
293 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
294 : shared_data_(shared_data
),
295 last_waited_sync_point_(0) {}
298 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
299 CheckTextureIsBound(GL_TEXTURE_2D
);
300 ResourceFormat texture_format
= RGBA_8888
;
303 texture_format
= RGBA_8888
;
306 texture_format
= BGRA_8888
;
309 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
310 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
313 void SetPixels(int xoffset
,
317 const void* pixels
) {
318 CheckTextureIsBound(GL_TEXTURE_2D
);
319 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
320 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
321 ASSERT_TRUE(texture
->data
.get());
322 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
323 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
325 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
327 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
328 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
329 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
330 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
331 for (int i
= 0; i
< height
; ++i
) {
332 memcpy(dest
, src
, in_pitch
);
338 struct PendingProduceTexture
{
339 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
340 scoped_refptr
<TestTexture
> texture
;
342 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
343 ContextSharedData
* shared_data_
;
344 GLuint last_waited_sync_point_
;
345 PendingProduceTextureList pending_produce_textures_
;
348 void GetResourcePixels(ResourceProvider
* resource_provider
,
349 ResourceProviderContext
* context
,
350 ResourceProvider::ResourceId id
,
351 const gfx::Size
& size
,
352 ResourceFormat format
,
354 resource_provider
->WaitSyncPointIfNeeded(id
);
355 switch (resource_provider
->default_resource_type()) {
356 case ResourceProvider::GLTexture
: {
357 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
358 ASSERT_NE(0U, lock_gl
.texture_id());
359 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
360 context
->GetPixels(size
, format
, pixels
);
363 case ResourceProvider::Bitmap
: {
364 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
367 lock_software
.sk_bitmap()->getPixels(),
368 lock_software
.sk_bitmap()->getSize());
371 case ResourceProvider::InvalidType
:
377 class ResourceProviderTest
378 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
380 ResourceProviderTest()
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL
),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
385 switch (GetParam()) {
386 case ResourceProvider::GLTexture
: {
387 scoped_ptr
<ResourceProviderContext
> context3d(
388 ResourceProviderContext::Create(shared_data_
.get()));
389 context3d_
= context3d
.get();
391 scoped_refptr
<TestContextProvider
> context_provider
=
392 TestContextProvider::Create(context3d
.Pass());
394 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
396 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
397 ResourceProviderContext::Create(shared_data_
.get());
398 child_context_
= child_context_owned
.get();
399 child_output_surface_
=
400 FakeOutputSurface::Create3d(child_context_owned
.Pass());
403 case ResourceProvider::Bitmap
:
404 output_surface_
= FakeOutputSurface::CreateSoftware(
405 make_scoped_ptr(new SoftwareOutputDevice
));
406 child_output_surface_
= FakeOutputSurface::CreateSoftware(
407 make_scoped_ptr(new SoftwareOutputDevice
));
409 case ResourceProvider::InvalidType
:
413 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
414 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
416 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
417 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
420 ResourceProvider::Create(output_surface_
.get(),
421 shared_bitmap_manager_
.get(),
422 gpu_memory_buffer_manager_
.get(),
423 main_thread_task_runner_
.get(),
427 child_resource_provider_
=
428 ResourceProvider::Create(child_output_surface_
.get(),
429 shared_bitmap_manager_
.get(),
430 gpu_memory_buffer_manager_
.get(),
431 main_thread_task_runner_
.get(),
437 static void CollectResources(ReturnedResourceArray
* array
,
438 const ReturnedResourceArray
& returned
,
439 BlockingTaskRunner
* main_thread_task_runner
) {
440 array
->insert(array
->end(), returned
.begin(), returned
.end());
443 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
444 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
447 static void SetResourceFilter(ResourceProvider
* resource_provider
,
448 ResourceProvider::ResourceId id
,
450 ResourceProvider::ScopedSamplerGL
sampler(
451 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
454 ResourceProviderContext
* context() { return context3d_
; }
456 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
458 bool* release_called
,
459 uint32
* sync_point
) {
460 if (GetParam() == ResourceProvider::GLTexture
) {
461 unsigned texture
= child_context_
->createTexture();
462 gpu::Mailbox gpu_mailbox
;
463 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
464 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
465 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
466 *sync_point
= child_context_
->insertSyncPoint();
467 EXPECT_LT(0u, *sync_point
);
469 scoped_ptr
<base::SharedMemory
> shared_memory
;
470 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
471 SingleReleaseCallbackImpl::Create(
472 base::Bind(ReleaseSharedMemoryCallback
,
473 base::Passed(&shared_memory
),
477 return child_resource_provider_
->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
481 gfx::Size
size(64, 64);
482 scoped_ptr
<base::SharedMemory
> shared_memory(
483 CreateAndFillSharedMemory(size
, 0));
485 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
486 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
487 SingleReleaseCallbackImpl::Create(
488 base::Bind(ReleaseSharedMemoryCallback
,
489 base::Passed(&shared_memory
),
493 return child_resource_provider_
->CreateResourceFromTextureMailbox(
494 TextureMailbox(shared_memory_ptr
, size
), callback
.Pass());
499 scoped_ptr
<ContextSharedData
> shared_data_
;
500 ResourceProviderContext
* context3d_
;
501 ResourceProviderContext
* child_context_
;
502 FakeOutputSurfaceClient output_surface_client_
;
503 FakeOutputSurfaceClient child_output_surface_client_
;
504 scoped_ptr
<OutputSurface
> output_surface_
;
505 scoped_ptr
<OutputSurface
> child_output_surface_
;
506 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
507 scoped_ptr
<ResourceProvider
> resource_provider_
;
508 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
509 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
510 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
513 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
514 ResourceProvider
* resource_provider
,
515 ResourceProviderContext
* context
) {
516 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
518 gfx::Size
size(1, 1);
519 ResourceFormat format
= RGBA_8888
;
520 size_t pixel_size
= TextureSizeBytes(size
, format
);
521 ASSERT_EQ(4U, pixel_size
);
523 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
524 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
525 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
526 if (expected_default_type
== ResourceProvider::GLTexture
)
527 EXPECT_EQ(0u, context
->NumTextures());
529 uint8_t data
[4] = { 1, 2, 3, 4 };
530 gfx::Rect
rect(size
);
531 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
532 if (expected_default_type
== ResourceProvider::GLTexture
)
533 EXPECT_EQ(1u, context
->NumTextures());
535 uint8_t result
[4] = { 0 };
536 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
537 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
539 resource_provider
->DeleteResource(id
);
540 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
541 if (expected_default_type
== ResourceProvider::GLTexture
)
542 EXPECT_EQ(0u, context
->NumTextures());
545 TEST_P(ResourceProviderTest
, Basic
) {
546 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
549 TEST_P(ResourceProviderTest
, Upload
) {
550 gfx::Size
size(2, 2);
551 ResourceFormat format
= RGBA_8888
;
552 size_t pixel_size
= TextureSizeBytes(size
, format
);
553 ASSERT_EQ(16U, pixel_size
);
555 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
556 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
558 uint8_t image
[16] = { 0 };
559 gfx::Rect
image_rect(size
);
560 resource_provider_
->SetPixels(
561 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
563 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
566 uint8_t result
[16] = { 0 };
568 gfx::Rect
source_rect(0, 0, 1, 1);
569 gfx::Vector2d
dest_offset(0, 0);
570 resource_provider_
->SetPixels(
571 id
, image
, image_rect
, source_rect
, dest_offset
);
573 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
575 resource_provider_
.get(), context(), id
, size
, format
, result
);
576 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
579 gfx::Rect
source_rect(0, 0, 1, 1);
580 gfx::Vector2d
dest_offset(1, 1);
581 resource_provider_
->SetPixels(
582 id
, image
, image_rect
, source_rect
, dest_offset
);
584 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
586 resource_provider_
.get(), context(), id
, size
, format
, result
);
587 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
590 gfx::Rect
source_rect(1, 0, 1, 1);
591 gfx::Vector2d
dest_offset(0, 1);
592 resource_provider_
->SetPixels(
593 id
, image
, image_rect
, source_rect
, dest_offset
);
595 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
597 resource_provider_
.get(), context(), id
, size
, format
, result
);
598 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
601 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
602 gfx::Rect
source_rect(100, 100, 1, 1);
603 gfx::Vector2d
dest_offset(1, 0);
604 resource_provider_
->SetPixels(
605 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
607 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
609 resource_provider_
.get(), context(), id
, size
, format
, result
);
610 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
613 resource_provider_
->DeleteResource(id
);
616 TEST_P(ResourceProviderTest
, TransferGLResources
) {
617 if (GetParam() != ResourceProvider::GLTexture
)
619 gfx::Size
size(1, 1);
620 ResourceFormat format
= RGBA_8888
;
621 size_t pixel_size
= TextureSizeBytes(size
, format
);
622 ASSERT_EQ(4U, pixel_size
);
624 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
625 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
626 uint8_t data1
[4] = { 1, 2, 3, 4 };
627 gfx::Rect
rect(size
);
628 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
630 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
631 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
632 uint8_t data2
[4] = { 5, 5, 5, 5 };
633 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
635 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
636 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
638 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
639 child_resource_provider_
.get(), id3
);
640 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
643 GLuint external_texture_id
= child_context_
->createExternalTexture();
644 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
646 gpu::Mailbox external_mailbox
;
647 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
648 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
649 external_mailbox
.name
);
650 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
651 ResourceProvider::ResourceId id4
=
652 child_resource_provider_
->CreateResourceFromTextureMailbox(
654 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
655 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
657 ReturnedResourceArray returned_to_child
;
659 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
661 // Transfer some resources to the parent.
662 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
663 resource_ids_to_transfer
.push_back(id1
);
664 resource_ids_to_transfer
.push_back(id2
);
665 resource_ids_to_transfer
.push_back(id3
);
666 resource_ids_to_transfer
.push_back(id4
);
667 TransferableResourceArray list
;
668 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
670 ASSERT_EQ(4u, list
.size());
671 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
672 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
673 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
674 list
[1].mailbox_holder
.sync_point
);
675 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
676 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
677 list
[2].mailbox_holder
.sync_point
);
678 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
679 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
680 list
[0].mailbox_holder
.texture_target
);
681 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
682 list
[1].mailbox_holder
.texture_target
);
683 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
684 list
[2].mailbox_holder
.texture_target
);
685 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
686 list
[3].mailbox_holder
.texture_target
);
687 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
688 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
689 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
690 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
691 resource_provider_
->ReceiveFromChild(child_id
, list
);
692 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
693 context3d_
->last_waited_sync_point());
695 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
696 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
699 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
700 context3d_
->last_waited_sync_point());
701 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
702 resource_ids_to_transfer
);
705 EXPECT_EQ(4u, resource_provider_
->num_resources());
706 ResourceProvider::ResourceIdMap resource_map
=
707 resource_provider_
->GetChildToParentMap(child_id
);
708 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
709 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
710 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
711 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
712 EXPECT_NE(0u, mapped_id1
);
713 EXPECT_NE(0u, mapped_id2
);
714 EXPECT_NE(0u, mapped_id3
);
715 EXPECT_NE(0u, mapped_id4
);
716 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
717 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
718 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
719 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
721 uint8_t result
[4] = { 0 };
723 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
724 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
727 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
728 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
731 // Check that transfering again the same resource from the child to the
733 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
734 resource_ids_to_transfer
.push_back(id1
);
735 resource_ids_to_transfer
.push_back(id2
);
736 resource_ids_to_transfer
.push_back(id3
);
737 TransferableResourceArray list
;
738 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
740 EXPECT_EQ(3u, list
.size());
741 EXPECT_EQ(id1
, list
[0].id
);
742 EXPECT_EQ(id2
, list
[1].id
);
743 EXPECT_EQ(id3
, list
[2].id
);
744 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
745 list
[0].mailbox_holder
.texture_target
);
746 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
747 list
[1].mailbox_holder
.texture_target
);
748 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
749 list
[2].mailbox_holder
.texture_target
);
750 ReturnedResourceArray returned
;
751 TransferableResource::ReturnResources(list
, &returned
);
752 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
753 // ids were exported twice, we returned them only once, they should still
755 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
756 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
757 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
760 EXPECT_EQ(0u, returned_to_child
.size());
762 // Transfer resources back from the parent to the child. Set no resources as
764 ResourceProvider::ResourceIdArray no_resources
;
765 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
767 ASSERT_EQ(4u, returned_to_child
.size());
768 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
769 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
770 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
771 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
772 EXPECT_FALSE(returned_to_child
[0].lost
);
773 EXPECT_FALSE(returned_to_child
[1].lost
);
774 EXPECT_FALSE(returned_to_child
[2].lost
);
775 EXPECT_FALSE(returned_to_child
[3].lost
);
776 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
777 returned_to_child
.clear();
779 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
780 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
781 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
782 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
785 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
786 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
788 ASSERT_NE(0U, lock
.texture_id());
789 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
790 child_context_
->GetPixels(size
, format
, result
);
791 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
794 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
795 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
797 ASSERT_NE(0U, lock
.texture_id());
798 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
799 child_context_
->GetPixels(size
, format
, result
);
800 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
803 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
804 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
806 ASSERT_NE(0U, lock
.texture_id());
807 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
810 // Transfer resources to the parent again.
811 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
812 resource_ids_to_transfer
.push_back(id1
);
813 resource_ids_to_transfer
.push_back(id2
);
814 resource_ids_to_transfer
.push_back(id3
);
815 resource_ids_to_transfer
.push_back(id4
);
816 TransferableResourceArray list
;
817 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
819 ASSERT_EQ(4u, list
.size());
820 EXPECT_EQ(id1
, list
[0].id
);
821 EXPECT_EQ(id2
, list
[1].id
);
822 EXPECT_EQ(id3
, list
[2].id
);
823 EXPECT_EQ(id4
, list
[3].id
);
824 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
825 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
826 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
827 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
828 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
829 list
[0].mailbox_holder
.texture_target
);
830 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
831 list
[1].mailbox_holder
.texture_target
);
832 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
833 list
[2].mailbox_holder
.texture_target
);
834 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
835 list
[3].mailbox_holder
.texture_target
);
836 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
837 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
838 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
839 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
840 resource_provider_
->ReceiveFromChild(child_id
, list
);
841 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
842 resource_ids_to_transfer
);
845 EXPECT_EQ(0u, returned_to_child
.size());
847 EXPECT_EQ(4u, resource_provider_
->num_resources());
848 resource_provider_
->DestroyChild(child_id
);
849 EXPECT_EQ(0u, resource_provider_
->num_resources());
851 ASSERT_EQ(4u, returned_to_child
.size());
852 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
853 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
854 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
855 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
856 EXPECT_FALSE(returned_to_child
[0].lost
);
857 EXPECT_FALSE(returned_to_child
[1].lost
);
858 EXPECT_FALSE(returned_to_child
[2].lost
);
859 EXPECT_FALSE(returned_to_child
[3].lost
);
862 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
863 if (GetParam() != ResourceProvider::GLTexture
)
865 gfx::Size
size(1, 1);
866 ResourceFormat format
= RGBA_8888
;
868 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
869 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
870 uint8_t data1
[4] = {1, 2, 3, 4};
871 gfx::Rect
rect(size
);
872 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
874 ReturnedResourceArray returned_to_child
;
876 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
878 // Transfer some resources to the parent.
879 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
880 resource_ids_to_transfer
.push_back(id1
);
881 TransferableResourceArray list
;
882 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
884 ASSERT_EQ(1u, list
.size());
885 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
887 resource_provider_
->ReceiveFromChild(child_id
, list
);
889 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
890 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
893 resource_provider_
->DeclareUsedResourcesFromChild(
894 child_id
, ResourceProvider::ResourceIdArray());
895 EXPECT_EQ(0u, returned_to_child
.size());
898 EXPECT_EQ(1u, returned_to_child
.size());
899 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
902 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
903 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
905 child_resource_provider_
->DeleteResource(id1
);
906 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
907 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
910 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
911 resource_provider_
->DestroyChild(child_id
);
914 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
915 // Overlays only supported on the GL path.
916 if (GetParam() != ResourceProvider::GLTexture
)
919 uint32 sync_point
= 0;
920 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
921 mailbox
.set_allow_overlay(true);
922 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
923 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
924 ResourceProvider::ResourceId id1
=
925 child_resource_provider_
->CreateResourceFromTextureMailbox(
926 mailbox
, release_callback
.Pass());
928 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
929 mailbox2
.set_allow_overlay(false);
930 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
931 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
932 ResourceProvider::ResourceId id2
=
933 child_resource_provider_
->CreateResourceFromTextureMailbox(
934 mailbox2
, release_callback2
.Pass());
936 ReturnedResourceArray returned_to_child
;
938 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
940 // Transfer some resources to the parent.
941 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
942 resource_ids_to_transfer
.push_back(id1
);
943 resource_ids_to_transfer
.push_back(id2
);
944 TransferableResourceArray list
;
945 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
947 ASSERT_EQ(2u, list
.size());
948 resource_provider_
->ReceiveFromChild(child_id
, list
);
949 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
950 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
952 resource_provider_
->DeclareUsedResourcesFromChild(
953 child_id
, ResourceProvider::ResourceIdArray());
955 EXPECT_EQ(2u, returned_to_child
.size());
956 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
958 child_resource_provider_
->DeleteResource(id1
);
959 child_resource_provider_
->DeleteResource(id2
);
960 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
962 resource_provider_
->DestroyChild(child_id
);
965 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
966 if (GetParam() != ResourceProvider::Bitmap
)
969 gfx::Size
size(1, 1);
970 ResourceFormat format
= RGBA_8888
;
971 size_t pixel_size
= TextureSizeBytes(size
, format
);
972 ASSERT_EQ(4U, pixel_size
);
974 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
975 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
976 uint8_t data1
[4] = { 1, 2, 3, 4 };
977 gfx::Rect
rect(size
);
978 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
980 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
981 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
982 uint8_t data2
[4] = { 5, 5, 5, 5 };
983 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
985 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
986 shared_memory
->CreateAndMapAnonymous(1);
987 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
988 ResourceProvider::ResourceId id3
=
989 child_resource_provider_
->CreateResourceFromTextureMailbox(
990 TextureMailbox(shared_memory_ptr
, gfx::Size(1, 1)),
991 SingleReleaseCallbackImpl::Create(base::Bind(
992 &SharedMemoryReleaseCallback
, base::Passed(&shared_memory
))));
994 ReturnedResourceArray returned_to_child
;
996 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
998 // Transfer some resources to the parent.
999 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1000 resource_ids_to_transfer
.push_back(id1
);
1001 resource_ids_to_transfer
.push_back(id2
);
1002 resource_ids_to_transfer
.push_back(id3
);
1003 TransferableResourceArray list
;
1004 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1006 ASSERT_EQ(3u, list
.size());
1007 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1008 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1009 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1010 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1011 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1012 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1013 resource_provider_
->ReceiveFromChild(child_id
, list
);
1014 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1015 resource_ids_to_transfer
);
1018 EXPECT_EQ(3u, resource_provider_
->num_resources());
1019 ResourceProvider::ResourceIdMap resource_map
=
1020 resource_provider_
->GetChildToParentMap(child_id
);
1021 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1022 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1023 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1024 EXPECT_NE(0u, mapped_id1
);
1025 EXPECT_NE(0u, mapped_id2
);
1026 EXPECT_NE(0u, mapped_id3
);
1027 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1028 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1029 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1031 uint8_t result
[4] = { 0 };
1033 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1034 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1037 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1038 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1041 // Check that transfering again the same resource from the child to the
1043 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1044 resource_ids_to_transfer
.push_back(id1
);
1045 resource_ids_to_transfer
.push_back(id2
);
1046 TransferableResourceArray list
;
1047 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1049 EXPECT_EQ(2u, list
.size());
1050 EXPECT_EQ(id1
, list
[0].id
);
1051 EXPECT_EQ(id2
, list
[1].id
);
1052 ReturnedResourceArray returned
;
1053 TransferableResource::ReturnResources(list
, &returned
);
1054 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1055 // ids were exported twice, we returned them only once, they should still
1057 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1058 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1061 EXPECT_EQ(0u, returned_to_child
.size());
1063 // Transfer resources back from the parent to the child. Set no resources as
1065 ResourceProvider::ResourceIdArray no_resources
;
1066 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1068 ASSERT_EQ(3u, returned_to_child
.size());
1069 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1070 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1071 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1072 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1073 expected_ids
.insert(id1
);
1074 expected_ids
.insert(id2
);
1075 expected_ids
.insert(id3
);
1076 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1077 for (unsigned i
= 0; i
< 3; i
++)
1078 returned_ids
.insert(returned_to_child
[i
].id
);
1079 EXPECT_EQ(expected_ids
, returned_ids
);
1080 EXPECT_FALSE(returned_to_child
[0].lost
);
1081 EXPECT_FALSE(returned_to_child
[1].lost
);
1082 EXPECT_FALSE(returned_to_child
[2].lost
);
1083 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1084 returned_to_child
.clear();
1086 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1087 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1088 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1091 ResourceProvider::ScopedReadLockSoftware
lock(
1092 child_resource_provider_
.get(), id1
);
1093 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1094 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1095 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1096 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1099 ResourceProvider::ScopedReadLockSoftware
lock(
1100 child_resource_provider_
.get(), id2
);
1101 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1102 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1103 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1104 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1107 // Transfer resources to the parent again.
1108 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1109 resource_ids_to_transfer
.push_back(id1
);
1110 resource_ids_to_transfer
.push_back(id2
);
1111 resource_ids_to_transfer
.push_back(id3
);
1112 TransferableResourceArray list
;
1113 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1115 ASSERT_EQ(3u, list
.size());
1116 EXPECT_EQ(id1
, list
[0].id
);
1117 EXPECT_EQ(id2
, list
[1].id
);
1118 EXPECT_EQ(id3
, list
[2].id
);
1119 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1120 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1121 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1122 resource_provider_
->ReceiveFromChild(child_id
, list
);
1123 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1124 resource_ids_to_transfer
);
1127 EXPECT_EQ(0u, returned_to_child
.size());
1129 EXPECT_EQ(3u, resource_provider_
->num_resources());
1130 resource_provider_
->DestroyChild(child_id
);
1131 EXPECT_EQ(0u, resource_provider_
->num_resources());
1133 ASSERT_EQ(3u, returned_to_child
.size());
1134 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1135 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1136 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1137 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1138 expected_ids
.insert(id1
);
1139 expected_ids
.insert(id2
);
1140 expected_ids
.insert(id3
);
1141 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1142 for (unsigned i
= 0; i
< 3; i
++)
1143 returned_ids
.insert(returned_to_child
[i
].id
);
1144 EXPECT_EQ(expected_ids
, returned_ids
);
1145 EXPECT_FALSE(returned_to_child
[0].lost
);
1146 EXPECT_FALSE(returned_to_child
[1].lost
);
1147 EXPECT_FALSE(returned_to_child
[2].lost
);
1150 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1151 if (GetParam() != ResourceProvider::Bitmap
)
1154 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1155 ResourceProviderContext::Create(shared_data_
.get()));
1157 FakeOutputSurfaceClient child_output_surface_client
;
1158 scoped_ptr
<OutputSurface
> child_output_surface(
1159 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1160 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1162 scoped_ptr
<ResourceProvider
> child_resource_provider(
1163 ResourceProvider::Create(child_output_surface
.get(),
1164 shared_bitmap_manager_
.get(),
1165 gpu_memory_buffer_manager_
.get(),
1171 gfx::Size
size(1, 1);
1172 ResourceFormat format
= RGBA_8888
;
1173 size_t pixel_size
= TextureSizeBytes(size
, format
);
1174 ASSERT_EQ(4U, pixel_size
);
1176 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1177 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1178 uint8_t data1
[4] = { 1, 2, 3, 4 };
1179 gfx::Rect
rect(size
);
1180 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1182 ReturnedResourceArray returned_to_child
;
1184 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1186 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1187 resource_ids_to_transfer
.push_back(id1
);
1188 TransferableResourceArray list
;
1189 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1191 ASSERT_EQ(1u, list
.size());
1192 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1193 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1194 list
[0].mailbox_holder
.texture_target
);
1195 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1196 resource_provider_
->ReceiveFromChild(child_id
, list
);
1199 EXPECT_EQ(0u, resource_provider_
->num_resources());
1200 ASSERT_EQ(1u, returned_to_child
.size());
1201 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1202 ResourceProvider::ResourceIdMap resource_map
=
1203 resource_provider_
->GetChildToParentMap(child_id
);
1204 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1205 EXPECT_EQ(0u, mapped_id1
);
1207 resource_provider_
->DestroyChild(child_id
);
1208 EXPECT_EQ(0u, resource_provider_
->num_resources());
1210 ASSERT_EQ(1u, returned_to_child
.size());
1211 EXPECT_FALSE(returned_to_child
[0].lost
);
1214 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1215 if (GetParam() != ResourceProvider::Bitmap
)
1218 gfx::Size
size(1, 1);
1219 ResourceFormat format
= RGBA_8888
;
1220 size_t pixel_size
= TextureSizeBytes(size
, format
);
1221 ASSERT_EQ(4U, pixel_size
);
1223 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1224 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1225 uint8_t data1
[4] = { 1, 2, 3, 4 };
1226 gfx::Rect
rect(size
);
1227 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1229 ReturnedResourceArray returned_to_child
;
1231 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1233 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1234 resource_ids_to_transfer
.push_back(id1
);
1235 TransferableResourceArray list
;
1236 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1238 ASSERT_EQ(1u, list
.size());
1240 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1241 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1242 resource_provider_
->ReceiveFromChild(child_id
, list
);
1245 EXPECT_EQ(1u, resource_provider_
->num_resources());
1246 EXPECT_EQ(0u, returned_to_child
.size());
1248 ResourceProvider::ResourceIdMap resource_map
=
1249 resource_provider_
->GetChildToParentMap(child_id
);
1250 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1251 EXPECT_NE(0u, mapped_id1
);
1253 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1255 EXPECT_FALSE(lock
.valid());
1258 resource_provider_
->DestroyChild(child_id
);
1259 EXPECT_EQ(0u, resource_provider_
->num_resources());
1261 ASSERT_EQ(1u, returned_to_child
.size());
1262 EXPECT_FALSE(returned_to_child
[0].lost
);
1265 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1266 gfx::Size
size(1, 1);
1267 ResourceFormat format
= RGBA_8888
;
1268 size_t pixel_size
= TextureSizeBytes(size
, format
);
1269 ASSERT_EQ(4U, pixel_size
);
1271 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1272 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1273 uint8_t data1
[4] = { 1, 2, 3, 4 };
1274 gfx::Rect
rect(size
);
1275 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1277 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1278 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1279 uint8_t data2
[4] = {5, 5, 5, 5};
1280 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1282 ReturnedResourceArray returned_to_child
;
1284 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1286 // Transfer some resources to the parent.
1287 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1288 resource_ids_to_transfer
.push_back(id1
);
1289 resource_ids_to_transfer
.push_back(id2
);
1290 TransferableResourceArray list
;
1291 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1293 ASSERT_EQ(2u, list
.size());
1294 if (GetParam() == ResourceProvider::GLTexture
) {
1295 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1296 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1298 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1299 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1300 resource_provider_
->ReceiveFromChild(child_id
, list
);
1301 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1302 resource_ids_to_transfer
);
1305 EXPECT_EQ(2u, resource_provider_
->num_resources());
1306 ResourceProvider::ResourceIdMap resource_map
=
1307 resource_provider_
->GetChildToParentMap(child_id
);
1308 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1309 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1310 EXPECT_NE(0u, mapped_id1
);
1311 EXPECT_NE(0u, mapped_id2
);
1312 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1313 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1316 // The parent transfers the resources to the grandparent.
1317 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1318 resource_ids_to_transfer
.push_back(mapped_id1
);
1319 resource_ids_to_transfer
.push_back(mapped_id2
);
1320 TransferableResourceArray list
;
1321 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1323 ASSERT_EQ(2u, list
.size());
1324 if (GetParam() == ResourceProvider::GLTexture
) {
1325 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1326 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1328 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1329 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1331 // Release the resource in the parent. Set no resources as being in use. The
1332 // resources are exported so that can't be transferred back yet.
1333 ResourceProvider::ResourceIdArray no_resources
;
1334 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1336 EXPECT_EQ(0u, returned_to_child
.size());
1337 EXPECT_EQ(2u, resource_provider_
->num_resources());
1339 // Return the resources from the grandparent to the parent. They should be
1340 // returned to the child then.
1341 EXPECT_EQ(2u, list
.size());
1342 EXPECT_EQ(mapped_id1
, list
[0].id
);
1343 EXPECT_EQ(mapped_id2
, list
[1].id
);
1344 ReturnedResourceArray returned
;
1345 TransferableResource::ReturnResources(list
, &returned
);
1346 resource_provider_
->ReceiveReturnsFromParent(returned
);
1348 EXPECT_EQ(0u, resource_provider_
->num_resources());
1349 ASSERT_EQ(2u, returned_to_child
.size());
1350 if (GetParam() == ResourceProvider::GLTexture
) {
1351 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1352 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1354 EXPECT_FALSE(returned_to_child
[0].lost
);
1355 EXPECT_FALSE(returned_to_child
[1].lost
);
1359 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1360 gfx::Size
size(1, 1);
1361 ResourceFormat format
= RGBA_8888
;
1362 size_t pixel_size
= TextureSizeBytes(size
, format
);
1363 ASSERT_EQ(4U, pixel_size
);
1365 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1366 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1367 uint8_t data1
[4] = {1, 2, 3, 4};
1368 gfx::Rect
rect(size
);
1369 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1371 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1372 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1373 uint8_t data2
[4] = {5, 5, 5, 5};
1374 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1376 ReturnedResourceArray returned_to_child
;
1378 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1380 // Transfer some resources to the parent.
1381 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1382 resource_ids_to_transfer
.push_back(id1
);
1383 resource_ids_to_transfer
.push_back(id2
);
1384 TransferableResourceArray list
;
1385 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1387 ASSERT_EQ(2u, list
.size());
1388 if (GetParam() == ResourceProvider::GLTexture
) {
1389 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1390 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1392 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1393 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1394 resource_provider_
->ReceiveFromChild(child_id
, list
);
1395 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1396 resource_ids_to_transfer
);
1399 EXPECT_EQ(2u, resource_provider_
->num_resources());
1400 ResourceProvider::ResourceIdMap resource_map
=
1401 resource_provider_
->GetChildToParentMap(child_id
);
1402 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1403 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1404 EXPECT_NE(0u, mapped_id1
);
1405 EXPECT_NE(0u, mapped_id2
);
1406 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1407 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1410 // The parent transfers the resources to the grandparent.
1411 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1412 resource_ids_to_transfer
.push_back(mapped_id1
);
1413 resource_ids_to_transfer
.push_back(mapped_id2
);
1414 TransferableResourceArray list
;
1415 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1417 ASSERT_EQ(2u, list
.size());
1418 if (GetParam() == ResourceProvider::GLTexture
) {
1419 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1420 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1422 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1423 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1425 // Release the resource in the parent. Set no resources as being in use. The
1426 // resources are exported so that can't be transferred back yet.
1427 ResourceProvider::ResourceIdArray no_resources
;
1428 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1430 // Destroy the child, the resources should not be returned yet.
1431 EXPECT_EQ(0u, returned_to_child
.size());
1432 EXPECT_EQ(2u, resource_provider_
->num_resources());
1434 resource_provider_
->DestroyChild(child_id
);
1436 EXPECT_EQ(2u, resource_provider_
->num_resources());
1437 ASSERT_EQ(0u, returned_to_child
.size());
1439 // Return a resource from the grandparent, it should be returned at this
1441 EXPECT_EQ(2u, list
.size());
1442 EXPECT_EQ(mapped_id1
, list
[0].id
);
1443 EXPECT_EQ(mapped_id2
, list
[1].id
);
1444 TransferableResourceArray return_list
;
1445 return_list
.push_back(list
[1]);
1447 ReturnedResourceArray returned
;
1448 TransferableResource::ReturnResources(return_list
, &returned
);
1449 resource_provider_
->ReceiveReturnsFromParent(returned
);
1451 EXPECT_EQ(1u, resource_provider_
->num_resources());
1452 ASSERT_EQ(1u, returned_to_child
.size());
1453 if (GetParam() == ResourceProvider::GLTexture
) {
1454 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1456 EXPECT_FALSE(returned_to_child
[0].lost
);
1457 returned_to_child
.clear();
1459 // Destroy the parent resource provider. The resource that's left should be
1460 // lost at this point, and returned.
1461 resource_provider_
= nullptr;
1462 ASSERT_EQ(1u, returned_to_child
.size());
1463 if (GetParam() == ResourceProvider::GLTexture
) {
1464 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1466 EXPECT_TRUE(returned_to_child
[0].lost
);
1470 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1471 gfx::Size
size(1, 1);
1472 ResourceFormat format
= RGBA_8888
;
1473 size_t pixel_size
= TextureSizeBytes(size
, format
);
1474 ASSERT_EQ(4U, pixel_size
);
1476 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1477 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1478 uint8_t data
[4] = { 1, 2, 3, 4 };
1479 gfx::Rect
rect(size
);
1480 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1482 ReturnedResourceArray returned_to_child
;
1484 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1486 // Transfer some resource to the parent.
1487 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1488 resource_ids_to_transfer
.push_back(id
);
1489 TransferableResourceArray list
;
1490 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1492 ASSERT_EQ(1u, list
.size());
1493 if (GetParam() == ResourceProvider::GLTexture
)
1494 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1495 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1496 resource_provider_
->ReceiveFromChild(child_id
, list
);
1497 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1498 resource_ids_to_transfer
);
1501 // Delete textures in the child, while they are transfered.
1502 child_resource_provider_
->DeleteResource(id
);
1503 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1505 EXPECT_EQ(0u, returned_to_child
.size());
1507 // Transfer resources back from the parent to the child. Set no resources as
1509 ResourceProvider::ResourceIdArray no_resources
;
1510 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1512 ASSERT_EQ(1u, returned_to_child
.size());
1513 if (GetParam() == ResourceProvider::GLTexture
)
1514 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1515 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1517 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1520 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1521 gfx::Size
size(1, 1);
1522 ResourceFormat format
= RGBA_8888
;
1523 size_t pixel_size
= TextureSizeBytes(size
, format
);
1524 ASSERT_EQ(4U, pixel_size
);
1526 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1527 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1528 uint8_t data
[4] = {1, 2, 3, 4};
1529 gfx::Rect
rect(size
);
1530 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1532 ReturnedResourceArray returned_to_child
;
1534 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1535 const ResourceProvider::ResourceIdMap
& map
=
1536 resource_provider_
->GetChildToParentMap(child_id
);
1538 // Transfer some resource to the parent.
1539 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1540 resource_ids_to_transfer
.push_back(id
);
1541 TransferableResourceArray list
;
1542 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1544 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1545 resource_provider_
->ReceiveFromChild(child_id
, list
);
1546 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1547 resource_ids_to_transfer
);
1549 TransferableResourceArray sent_to_top_level
;
1551 // Parent transfers to top-level.
1552 ASSERT_TRUE(map
.find(id
) != map
.end());
1553 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1554 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1555 resource_ids_to_transfer
.push_back(parent_id
);
1556 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1557 &sent_to_top_level
);
1558 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1561 // Stop using resource.
1562 ResourceProvider::ResourceIdArray empty
;
1563 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1564 // Resource is not yet returned to the child, since it's in use by the
1566 EXPECT_TRUE(returned_to_child
.empty());
1569 // Send the resource to the parent again.
1570 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1571 resource_ids_to_transfer
.push_back(id
);
1572 TransferableResourceArray list
;
1573 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1575 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1576 resource_provider_
->ReceiveFromChild(child_id
, list
);
1577 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1578 resource_ids_to_transfer
);
1581 // Receive returns back from top-level.
1582 ReturnedResourceArray returned
;
1583 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1584 resource_provider_
->ReceiveReturnsFromParent(returned
);
1585 // Resource is still not yet returned to the child, since it's declared used
1587 EXPECT_TRUE(returned_to_child
.empty());
1588 ASSERT_TRUE(map
.find(id
) != map
.end());
1589 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1590 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1593 sent_to_top_level
.clear();
1594 // Parent transfers again to top-level.
1595 ASSERT_TRUE(map
.find(id
) != map
.end());
1596 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1597 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1598 resource_ids_to_transfer
.push_back(parent_id
);
1599 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1600 &sent_to_top_level
);
1601 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1604 // Receive returns back from top-level.
1605 ReturnedResourceArray returned
;
1606 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1607 resource_provider_
->ReceiveReturnsFromParent(returned
);
1608 // Resource is still not yet returned to the child, since it's still
1609 // declared used in the parent.
1610 EXPECT_TRUE(returned_to_child
.empty());
1611 ASSERT_TRUE(map
.find(id
) != map
.end());
1612 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1613 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1616 // Stop using resource.
1617 ResourceProvider::ResourceIdArray empty
;
1618 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1619 // Resource should have been returned to the child, since it's no longer in
1620 // use by the top-level.
1621 ASSERT_EQ(1u, returned_to_child
.size());
1622 EXPECT_EQ(id
, returned_to_child
[0].id
);
1623 EXPECT_EQ(2, returned_to_child
[0].count
);
1624 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1625 returned_to_child
.clear();
1626 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1630 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1632 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1633 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1634 new TextureStateTrackingContext
);
1635 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1637 FakeOutputSurfaceClient child_output_surface_client
;
1638 scoped_ptr
<OutputSurface
> child_output_surface(
1639 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1640 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1641 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1642 new TestSharedBitmapManager());
1644 scoped_ptr
<ResourceProvider
> child_resource_provider(
1645 ResourceProvider::Create(child_output_surface
.get(),
1646 shared_bitmap_manager
.get(),
1653 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1654 new TextureStateTrackingContext
);
1655 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1657 FakeOutputSurfaceClient parent_output_surface_client
;
1658 scoped_ptr
<OutputSurface
> parent_output_surface(
1659 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1660 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1662 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1663 ResourceProvider::Create(parent_output_surface
.get(),
1664 shared_bitmap_manager
.get(),
1671 gfx::Size
size(1, 1);
1672 ResourceFormat format
= RGBA_8888
;
1673 int child_texture_id
= 1;
1674 int parent_texture_id
= 2;
1676 size_t pixel_size
= TextureSizeBytes(size
, format
);
1677 ASSERT_EQ(4U, pixel_size
);
1679 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1680 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1682 // The new texture is created with GL_LINEAR.
1683 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1684 .Times(2); // Once to create and once to allocate.
1685 EXPECT_CALL(*child_context
,
1686 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1687 EXPECT_CALL(*child_context
,
1688 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1691 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1694 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1695 EXPECT_CALL(*child_context
,
1696 texParameteri(GL_TEXTURE_2D
,
1697 GL_TEXTURE_POOL_CHROMIUM
,
1698 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1699 child_resource_provider
->AllocateForTesting(id
);
1700 Mock::VerifyAndClearExpectations(child_context
);
1702 uint8_t data
[4] = { 1, 2, 3, 4 };
1703 gfx::Rect
rect(size
);
1705 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1706 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1707 Mock::VerifyAndClearExpectations(child_context
);
1709 // The texture is set to |child_filter| in the child.
1710 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1711 if (child_filter
!= GL_LINEAR
) {
1714 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1717 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1719 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1720 Mock::VerifyAndClearExpectations(child_context
);
1722 ReturnedResourceArray returned_to_child
;
1723 int child_id
= parent_resource_provider
->CreateChild(
1724 GetReturnCallback(&returned_to_child
));
1726 // Transfer some resource to the parent.
1727 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1728 resource_ids_to_transfer
.push_back(id
);
1729 TransferableResourceArray list
;
1731 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1732 EXPECT_CALL(*child_context
,
1733 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1734 EXPECT_CALL(*child_context
, insertSyncPoint());
1735 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1737 Mock::VerifyAndClearExpectations(child_context
);
1739 ASSERT_EQ(1u, list
.size());
1740 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1742 EXPECT_CALL(*parent_context
,
1743 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1744 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1745 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1747 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1748 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1751 Mock::VerifyAndClearExpectations(parent_context
);
1753 parent_resource_provider
->DeclareUsedResourcesFromChild(
1754 child_id
, resource_ids_to_transfer
);
1755 Mock::VerifyAndClearExpectations(parent_context
);
1757 ResourceProvider::ResourceIdMap resource_map
=
1758 parent_resource_provider
->GetChildToParentMap(child_id
);
1759 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1760 EXPECT_NE(0u, mapped_id
);
1762 // The texture is set to |parent_filter| in the parent.
1763 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1766 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1769 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1770 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1771 Mock::VerifyAndClearExpectations(parent_context
);
1773 // The texture should be reset to |child_filter| in the parent when it is
1774 // returned, since that is how it was received.
1775 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1778 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1781 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1784 EXPECT_EQ(0u, returned_to_child
.size());
1786 // Transfer resources back from the parent to the child. Set no resources
1788 ResourceProvider::ResourceIdArray no_resources
;
1789 EXPECT_CALL(*parent_context
, insertSyncPoint());
1790 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1792 Mock::VerifyAndClearExpectations(parent_context
);
1794 ASSERT_EQ(1u, returned_to_child
.size());
1795 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1798 // The child remembers the texture filter is set to |child_filter|.
1799 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1800 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1801 Mock::VerifyAndClearExpectations(child_context
);
1805 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1806 if (GetParam() != ResourceProvider::GLTexture
)
1808 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1811 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1812 if (GetParam() != ResourceProvider::GLTexture
)
1814 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1817 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1818 // Other mailbox transfers tested elsewhere.
1819 if (GetParam() != ResourceProvider::GLTexture
)
1821 unsigned texture
= context()->createTexture();
1822 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1823 uint8_t data
[4] = { 1, 2, 3, 4 };
1824 context()->texImage2D(
1825 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1826 gpu::Mailbox mailbox
;
1827 context()->genMailboxCHROMIUM(mailbox
.name
);
1828 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1829 uint32 sync_point
= context()->insertSyncPoint();
1831 // All the logic below assumes that the sync points are all positive.
1832 EXPECT_LT(0u, sync_point
);
1834 uint32 release_sync_point
= 0;
1835 bool lost_resource
= false;
1836 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1837 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1838 &release_sync_point
,
1840 &main_thread_task_runner
);
1841 ResourceProvider::ResourceId resource
=
1842 resource_provider_
->CreateResourceFromTextureMailbox(
1843 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1844 SingleReleaseCallbackImpl::Create(callback
));
1845 EXPECT_EQ(1u, context()->NumTextures());
1846 EXPECT_EQ(0u, release_sync_point
);
1848 // Transfer the resource, expect the sync points to be consistent.
1849 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1850 resource_ids_to_transfer
.push_back(resource
);
1851 TransferableResourceArray list
;
1852 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1853 ASSERT_EQ(1u, list
.size());
1854 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1856 memcmp(mailbox
.name
,
1857 list
[0].mailbox_holder
.mailbox
.name
,
1858 sizeof(mailbox
.name
)));
1859 EXPECT_EQ(0u, release_sync_point
);
1861 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1862 unsigned other_texture
= context()->createTexture();
1863 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1864 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1865 uint8_t test_data
[4] = { 0 };
1866 context()->GetPixels(
1867 gfx::Size(1, 1), RGBA_8888
, test_data
);
1868 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1869 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1870 context()->deleteTexture(other_texture
);
1871 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1872 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1874 // Receive the resource, then delete it, expect the sync points to be
1876 ReturnedResourceArray returned
;
1877 TransferableResource::ReturnResources(list
, &returned
);
1878 resource_provider_
->ReceiveReturnsFromParent(returned
);
1879 EXPECT_EQ(1u, context()->NumTextures());
1880 EXPECT_EQ(0u, release_sync_point
);
1882 resource_provider_
->DeleteResource(resource
);
1883 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1884 EXPECT_FALSE(lost_resource
);
1885 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1888 // We're going to do the same thing as above, but testing the case where we
1889 // delete the resource before we receive it back.
1890 sync_point
= release_sync_point
;
1891 EXPECT_LT(0u, sync_point
);
1892 release_sync_point
= 0;
1893 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1894 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1895 SingleReleaseCallbackImpl::Create(callback
));
1896 EXPECT_EQ(1u, context()->NumTextures());
1897 EXPECT_EQ(0u, release_sync_point
);
1899 // Transfer the resource, expect the sync points to be consistent.
1900 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1901 resource_ids_to_transfer
.push_back(resource
);
1902 TransferableResourceArray list
;
1903 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1904 ASSERT_EQ(1u, list
.size());
1905 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1907 memcmp(mailbox
.name
,
1908 list
[0].mailbox_holder
.mailbox
.name
,
1909 sizeof(mailbox
.name
)));
1910 EXPECT_EQ(0u, release_sync_point
);
1912 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1913 unsigned other_texture
= context()->createTexture();
1914 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1915 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1916 uint8_t test_data
[4] = { 0 };
1917 context()->GetPixels(
1918 gfx::Size(1, 1), RGBA_8888
, test_data
);
1919 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1920 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1921 context()->deleteTexture(other_texture
);
1922 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1923 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1925 // Delete the resource, which shouldn't do anything.
1926 resource_provider_
->DeleteResource(resource
);
1927 EXPECT_EQ(1u, context()->NumTextures());
1928 EXPECT_EQ(0u, release_sync_point
);
1930 // Then receive the resource which should release the mailbox, expect the
1931 // sync points to be consistent.
1932 ReturnedResourceArray returned
;
1933 TransferableResource::ReturnResources(list
, &returned
);
1934 resource_provider_
->ReceiveReturnsFromParent(returned
);
1935 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1936 EXPECT_FALSE(lost_resource
);
1937 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1940 context()->waitSyncPoint(release_sync_point
);
1941 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1942 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1943 context()->deleteTexture(texture
);
1946 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1947 gfx::Size
size(1, 1);
1948 ResourceFormat format
= RGBA_8888
;
1949 ResourceProvider::ResourceId resource
=
1950 child_resource_provider_
->CreateResource(
1953 ResourceProvider::TextureHintImmutable
,
1955 child_resource_provider_
->AllocateForTesting(resource
);
1956 // Expect a GL resource to be lost.
1957 bool should_lose_resource
= GetParam() == ResourceProvider::GLTexture
;
1959 ReturnedResourceArray returned_to_child
;
1961 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1963 // Transfer the resource to the parent.
1964 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1965 resource_ids_to_transfer
.push_back(resource
);
1966 TransferableResourceArray list
;
1967 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1969 EXPECT_EQ(1u, list
.size());
1971 resource_provider_
->ReceiveFromChild(child_id
, list
);
1972 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1973 resource_ids_to_transfer
);
1976 // Lose the output surface in the parent.
1977 resource_provider_
->DidLoseOutputSurface();
1980 EXPECT_EQ(0u, returned_to_child
.size());
1982 // Transfer resources back from the parent to the child. Set no resources as
1984 ResourceProvider::ResourceIdArray no_resources
;
1985 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1987 // Expect a GL resource to be lost.
1988 ASSERT_EQ(1u, returned_to_child
.size());
1989 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
1990 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1991 returned_to_child
.clear();
1994 // A GL resource should be lost.
1995 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
1997 // Lost resources stay in use in the parent forever.
1998 EXPECT_EQ(should_lose_resource
,
1999 child_resource_provider_
->InUseByConsumer(resource
));
2002 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2003 gfx::Size
size(1, 1);
2004 ResourceFormat format
= RGBA_8888
;
2005 ResourceProvider::ResourceId resource
=
2006 child_resource_provider_
->CreateResource(
2009 ResourceProvider::TextureHintImmutable
,
2011 child_resource_provider_
->AllocateForTesting(resource
);
2013 ReturnedResourceArray returned_to_child
;
2015 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2017 // Transfer the resource to the parent.
2018 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2019 resource_ids_to_transfer
.push_back(resource
);
2020 TransferableResourceArray list
;
2021 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2023 EXPECT_EQ(1u, list
.size());
2025 resource_provider_
->ReceiveFromChild(child_id
, list
);
2026 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2027 resource_ids_to_transfer
);
2031 ResourceProvider::ResourceIdMap resource_map
=
2032 resource_provider_
->GetChildToParentMap(child_id
);
2033 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2034 EXPECT_NE(0u, parent_resource
);
2036 // Transfer to a grandparent.
2037 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2038 resource_ids_to_transfer
.push_back(parent_resource
);
2039 TransferableResourceArray list
;
2040 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2042 // Receive back a lost resource from the grandparent.
2043 EXPECT_EQ(1u, list
.size());
2044 EXPECT_EQ(parent_resource
, list
[0].id
);
2045 ReturnedResourceArray returned
;
2046 TransferableResource::ReturnResources(list
, &returned
);
2047 EXPECT_EQ(1u, returned
.size());
2048 EXPECT_EQ(parent_resource
, returned
[0].id
);
2049 returned
[0].lost
= true;
2050 resource_provider_
->ReceiveReturnsFromParent(returned
);
2052 // The resource should be lost.
2053 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2055 // Lost resources stay in use in the parent forever.
2056 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2060 EXPECT_EQ(0u, returned_to_child
.size());
2062 // Transfer resources back from the parent to the child. Set no resources as
2064 ResourceProvider::ResourceIdArray no_resources
;
2065 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2067 // Expect the resource to be lost.
2068 ASSERT_EQ(1u, returned_to_child
.size());
2069 EXPECT_TRUE(returned_to_child
[0].lost
);
2070 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2071 returned_to_child
.clear();
2074 // The resource should be lost.
2075 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2077 // Lost resources stay in use in the parent forever.
2078 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2081 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2082 uint32 release_sync_point
= 0;
2083 bool lost_resource
= false;
2084 bool release_called
= false;
2085 uint32 sync_point
= 0;
2086 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2087 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2089 ReturnedResourceArray returned_to_child
;
2091 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2093 // Transfer the resource to the parent.
2094 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2095 resource_ids_to_transfer
.push_back(resource
);
2096 TransferableResourceArray list
;
2097 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2099 EXPECT_EQ(1u, list
.size());
2101 resource_provider_
->ReceiveFromChild(child_id
, list
);
2102 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2103 resource_ids_to_transfer
);
2106 // Lose the output surface in the parent.
2107 resource_provider_
->DidLoseOutputSurface();
2110 EXPECT_EQ(0u, returned_to_child
.size());
2112 // Transfer resources back from the parent to the child. Set no resources as
2114 ResourceProvider::ResourceIdArray no_resources
;
2115 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2117 ASSERT_EQ(1u, returned_to_child
.size());
2118 // Losing an output surface only loses hardware resources.
2119 EXPECT_EQ(returned_to_child
[0].lost
,
2120 GetParam() == ResourceProvider::GLTexture
);
2121 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2122 returned_to_child
.clear();
2125 // Delete the resource in the child. Expect the resource to be lost if it's
2127 child_resource_provider_
->DeleteResource(resource
);
2128 EXPECT_EQ(lost_resource
, GetParam() == ResourceProvider::GLTexture
);
2131 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2132 uint32 release_sync_point
= 0;
2133 bool lost_resource
= false;
2134 bool release_called
= false;
2135 uint32 sync_point
= 0;
2136 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2137 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2139 ReturnedResourceArray returned_to_child
;
2141 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2143 // Transfer the resource to the parent.
2144 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2145 resource_ids_to_transfer
.push_back(resource
);
2146 TransferableResourceArray list
;
2147 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2149 EXPECT_EQ(1u, list
.size());
2151 resource_provider_
->ReceiveFromChild(child_id
, list
);
2152 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2153 resource_ids_to_transfer
);
2157 ResourceProvider::ResourceIdMap resource_map
=
2158 resource_provider_
->GetChildToParentMap(child_id
);
2159 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2160 EXPECT_NE(0u, parent_resource
);
2162 // Transfer to a grandparent.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2164 resource_ids_to_transfer
.push_back(parent_resource
);
2165 TransferableResourceArray list
;
2166 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2168 // Receive back a lost resource from the grandparent.
2169 EXPECT_EQ(1u, list
.size());
2170 EXPECT_EQ(parent_resource
, list
[0].id
);
2171 ReturnedResourceArray returned
;
2172 TransferableResource::ReturnResources(list
, &returned
);
2173 EXPECT_EQ(1u, returned
.size());
2174 EXPECT_EQ(parent_resource
, returned
[0].id
);
2175 returned
[0].lost
= true;
2176 resource_provider_
->ReceiveReturnsFromParent(returned
);
2180 EXPECT_EQ(0u, returned_to_child
.size());
2182 // Transfer resources back from the parent to the child. Set no resources as
2184 ResourceProvider::ResourceIdArray no_resources
;
2185 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2187 // Expect the resource to be lost.
2188 ASSERT_EQ(1u, returned_to_child
.size());
2189 EXPECT_TRUE(returned_to_child
[0].lost
);
2190 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2191 returned_to_child
.clear();
2194 // Delete the resource in the child. Expect the resource to be lost.
2195 child_resource_provider_
->DeleteResource(resource
);
2196 EXPECT_TRUE(lost_resource
);
2199 TEST_P(ResourceProviderTest
, Shutdown
) {
2200 uint32 release_sync_point
= 0;
2201 bool lost_resource
= false;
2202 bool release_called
= false;
2203 uint32 sync_point
= 0;
2205 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2207 EXPECT_EQ(0u, release_sync_point
);
2208 EXPECT_FALSE(lost_resource
);
2210 child_resource_provider_
= nullptr;
2212 if (GetParam() == ResourceProvider::GLTexture
) {
2213 EXPECT_LE(sync_point
, release_sync_point
);
2215 EXPECT_TRUE(release_called
);
2216 EXPECT_FALSE(lost_resource
);
2219 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2220 uint32 release_sync_point
= 0;
2221 bool lost_resource
= false;
2222 bool release_called
= false;
2223 uint32 sync_point
= 0;
2224 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2225 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2227 // Transfer the resource, so we can't release it properly on shutdown.
2228 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2229 resource_ids_to_transfer
.push_back(resource
);
2230 TransferableResourceArray list
;
2231 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2234 EXPECT_EQ(0u, release_sync_point
);
2235 EXPECT_FALSE(lost_resource
);
2237 child_resource_provider_
= nullptr;
2239 // Since the resource is in the parent, the child considers it lost.
2240 EXPECT_EQ(0u, release_sync_point
);
2241 EXPECT_TRUE(lost_resource
);
2244 TEST_P(ResourceProviderTest
, LostContext
) {
2245 // TextureMailbox callbacks only exist for GL textures for now.
2246 if (GetParam() != ResourceProvider::GLTexture
)
2248 unsigned texture
= context()->createTexture();
2249 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2250 gpu::Mailbox mailbox
;
2251 context()->genMailboxCHROMIUM(mailbox
.name
);
2252 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2253 uint32 sync_point
= context()->insertSyncPoint();
2255 EXPECT_LT(0u, sync_point
);
2257 uint32 release_sync_point
= 0;
2258 bool lost_resource
= false;
2259 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2260 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2261 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2262 &release_sync_point
,
2264 &main_thread_task_runner
));
2265 resource_provider_
->CreateResourceFromTextureMailbox(
2266 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2268 EXPECT_EQ(0u, release_sync_point
);
2269 EXPECT_FALSE(lost_resource
);
2270 EXPECT_EQ(NULL
, main_thread_task_runner
);
2272 resource_provider_
->DidLoseOutputSurface();
2273 resource_provider_
= nullptr;
2275 EXPECT_LE(sync_point
, release_sync_point
);
2276 EXPECT_TRUE(lost_resource
);
2277 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2280 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2281 // Sampling is only supported for GL textures.
2282 if (GetParam() != ResourceProvider::GLTexture
)
2285 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2286 new TextureStateTrackingContext
);
2287 TextureStateTrackingContext
* context
= context_owned
.get();
2289 FakeOutputSurfaceClient output_surface_client
;
2290 scoped_ptr
<OutputSurface
> output_surface(
2291 FakeOutputSurface::Create3d(context_owned
.Pass()));
2292 CHECK(output_surface
->BindToClient(&output_surface_client
));
2294 scoped_ptr
<ResourceProvider
> resource_provider(
2295 ResourceProvider::Create(output_surface
.get(),
2296 shared_bitmap_manager_
.get(),
2297 gpu_memory_buffer_manager_
.get(),
2303 gfx::Size
size(1, 1);
2304 ResourceFormat format
= RGBA_8888
;
2307 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2308 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2310 // Check that the texture gets created with the right sampler settings.
2311 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2312 .Times(2); // Once to create and once to allocate.
2313 EXPECT_CALL(*context
,
2314 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2315 EXPECT_CALL(*context
,
2316 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2319 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2322 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2323 EXPECT_CALL(*context
,
2324 texParameteri(GL_TEXTURE_2D
,
2325 GL_TEXTURE_POOL_CHROMIUM
,
2326 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2328 resource_provider
->AllocateForTesting(id
);
2329 Mock::VerifyAndClearExpectations(context
);
2331 // Creating a sampler with the default filter should not change any texture
2334 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2335 ResourceProvider::ScopedSamplerGL
sampler(
2336 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2337 Mock::VerifyAndClearExpectations(context
);
2340 // Using a different filter should be reflected in the texture parameters.
2342 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2345 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2348 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2349 ResourceProvider::ScopedSamplerGL
sampler(
2350 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2351 Mock::VerifyAndClearExpectations(context
);
2354 // Test resetting to the default filter.
2356 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2357 EXPECT_CALL(*context
,
2358 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2359 EXPECT_CALL(*context
,
2360 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2361 ResourceProvider::ScopedSamplerGL
sampler(
2362 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2363 Mock::VerifyAndClearExpectations(context
);
2367 TEST_P(ResourceProviderTest
, ManagedResource
) {
2368 // Sampling is only supported for GL textures.
2369 if (GetParam() != ResourceProvider::GLTexture
)
2372 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2373 new TextureStateTrackingContext
);
2374 TextureStateTrackingContext
* context
= context_owned
.get();
2376 FakeOutputSurfaceClient output_surface_client
;
2377 scoped_ptr
<OutputSurface
> output_surface(
2378 FakeOutputSurface::Create3d(context_owned
.Pass()));
2379 CHECK(output_surface
->BindToClient(&output_surface_client
));
2381 scoped_ptr
<ResourceProvider
> resource_provider(
2382 ResourceProvider::Create(output_surface
.get(),
2383 shared_bitmap_manager_
.get(),
2384 gpu_memory_buffer_manager_
.get(),
2390 gfx::Size
size(1, 1);
2391 ResourceFormat format
= RGBA_8888
;
2394 // Check that the texture gets created with the right sampler settings.
2395 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2399 ResourceProvider::TextureHintImmutable
,
2401 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2402 EXPECT_CALL(*context
,
2403 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2404 EXPECT_CALL(*context
,
2405 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2408 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2411 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2412 EXPECT_CALL(*context
,
2413 texParameteri(GL_TEXTURE_2D
,
2414 GL_TEXTURE_POOL_CHROMIUM
,
2415 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2416 resource_provider
->CreateForTesting(id
);
2419 Mock::VerifyAndClearExpectations(context
);
2422 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2423 // Sampling is only supported for GL textures.
2424 if (GetParam() != ResourceProvider::GLTexture
)
2427 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2428 new TextureStateTrackingContext
);
2429 TextureStateTrackingContext
* context
= context_owned
.get();
2431 FakeOutputSurfaceClient output_surface_client
;
2432 scoped_ptr
<OutputSurface
> output_surface(
2433 FakeOutputSurface::Create3d(context_owned
.Pass()));
2434 CHECK(output_surface
->BindToClient(&output_surface_client
));
2436 scoped_ptr
<ResourceProvider
> resource_provider(
2437 ResourceProvider::Create(output_surface
.get(),
2438 shared_bitmap_manager_
.get(),
2439 gpu_memory_buffer_manager_
.get(),
2445 gfx::Size
size(1, 1);
2446 ResourceFormat format
= RGBA_8888
;
2447 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2449 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2450 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2451 // Check that the texture gets created with the right sampler settings.
2452 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2457 ResourceProvider::TextureHintImmutable
,
2459 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2460 EXPECT_CALL(*context
,
2461 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2462 EXPECT_CALL(*context
,
2463 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2464 EXPECT_CALL(*context
,
2465 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2466 EXPECT_CALL(*context
,
2467 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2468 EXPECT_CALL(*context
,
2469 texParameteri(GL_TEXTURE_2D
,
2470 GL_TEXTURE_POOL_CHROMIUM
,
2471 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2472 resource_provider
->CreateForTesting(id
);
2475 Mock::VerifyAndClearExpectations(context
);
2479 TEST_P(ResourceProviderTest
, TextureHint
) {
2480 // Sampling is only supported for GL textures.
2481 if (GetParam() != ResourceProvider::GLTexture
)
2484 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2485 new TextureStateTrackingContext
);
2486 TextureStateTrackingContext
* context
= context_owned
.get();
2487 context
->set_support_texture_storage(true);
2488 context
->set_support_texture_usage(true);
2490 FakeOutputSurfaceClient output_surface_client
;
2491 scoped_ptr
<OutputSurface
> output_surface(
2492 FakeOutputSurface::Create3d(context_owned
.Pass()));
2493 CHECK(output_surface
->BindToClient(&output_surface_client
));
2495 scoped_ptr
<ResourceProvider
> resource_provider(
2496 ResourceProvider::Create(output_surface
.get(),
2497 shared_bitmap_manager_
.get(),
2498 gpu_memory_buffer_manager_
.get(),
2504 gfx::Size
size(1, 1);
2505 ResourceFormat format
= RGBA_8888
;
2506 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2508 const ResourceProvider::TextureHint hints
[4] = {
2509 ResourceProvider::TextureHintDefault
,
2510 ResourceProvider::TextureHintImmutable
,
2511 ResourceProvider::TextureHintFramebuffer
,
2512 ResourceProvider::TextureHintImmutableFramebuffer
,
2514 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2515 // Check that the texture gets created with the right sampler settings.
2516 ResourceProvider::ResourceId id
=
2517 resource_provider
->CreateGLTexture(size
,
2521 hints
[texture_id
- 1],
2523 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2524 EXPECT_CALL(*context
,
2525 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2526 EXPECT_CALL(*context
,
2527 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2530 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2533 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2534 EXPECT_CALL(*context
,
2535 texParameteri(GL_TEXTURE_2D
,
2536 GL_TEXTURE_POOL_CHROMIUM
,
2537 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2538 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2539 bool is_framebuffer_hint
=
2540 hints
[texture_id
- 1] & ResourceProvider::TextureHintFramebuffer
;
2541 EXPECT_CALL(*context
,
2542 texParameteri(GL_TEXTURE_2D
,
2543 GL_TEXTURE_USAGE_ANGLE
,
2544 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2545 .Times(is_framebuffer_hint
? 1 : 0);
2546 resource_provider
->CreateForTesting(id
);
2549 Mock::VerifyAndClearExpectations(context
);
2553 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2554 if (GetParam() != ResourceProvider::Bitmap
)
2557 gfx::Size
size(64, 64);
2558 const uint32_t kBadBeef
= 0xbadbeef;
2559 scoped_ptr
<base::SharedMemory
> shared_memory(
2560 CreateAndFillSharedMemory(size
, kBadBeef
));
2562 FakeOutputSurfaceClient output_surface_client
;
2563 scoped_ptr
<OutputSurface
> output_surface(
2564 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2565 new SoftwareOutputDevice
)));
2566 CHECK(output_surface
->BindToClient(&output_surface_client
));
2568 scoped_ptr
<ResourceProvider
> resource_provider(
2569 ResourceProvider::Create(output_surface
.get(),
2570 shared_bitmap_manager_
.get(),
2571 gpu_memory_buffer_manager_
.get(),
2572 main_thread_task_runner_
.get(),
2577 uint32 release_sync_point
= 0;
2578 bool lost_resource
= false;
2579 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2580 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2581 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2582 &release_sync_point
,
2584 &main_thread_task_runner
));
2585 TextureMailbox
mailbox(shared_memory
.get(), size
);
2587 ResourceProvider::ResourceId id
=
2588 resource_provider
->CreateResourceFromTextureMailbox(
2589 mailbox
, callback
.Pass());
2593 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2594 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2595 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2596 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2597 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2600 resource_provider
->DeleteResource(id
);
2601 EXPECT_EQ(0u, release_sync_point
);
2602 EXPECT_FALSE(lost_resource
);
2603 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2606 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D
) {
2607 // Mailboxing is only supported for GL textures.
2608 if (GetParam() != ResourceProvider::GLTexture
)
2611 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2612 new TextureStateTrackingContext
);
2613 TextureStateTrackingContext
* context
= context_owned
.get();
2615 FakeOutputSurfaceClient output_surface_client
;
2616 scoped_ptr
<OutputSurface
> output_surface(
2617 FakeOutputSurface::Create3d(context_owned
.Pass()));
2618 CHECK(output_surface
->BindToClient(&output_surface_client
));
2620 scoped_ptr
<ResourceProvider
> resource_provider(
2621 ResourceProvider::Create(output_surface
.get(),
2622 shared_bitmap_manager_
.get(),
2623 gpu_memory_buffer_manager_
.get(),
2624 main_thread_task_runner_
.get(),
2629 unsigned texture_id
= 1;
2630 uint32 sync_point
= 30;
2631 unsigned target
= GL_TEXTURE_2D
;
2633 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2634 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2635 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2636 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2637 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2639 gpu::Mailbox gpu_mailbox
;
2640 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2641 uint32 release_sync_point
= 0;
2642 bool lost_resource
= false;
2643 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2644 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2645 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2646 &release_sync_point
,
2648 &main_thread_task_runner
));
2650 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2652 ResourceProvider::ResourceId id
=
2653 resource_provider
->CreateResourceFromTextureMailbox(
2654 mailbox
, callback
.Pass());
2657 Mock::VerifyAndClearExpectations(context
);
2660 // Mailbox sync point WaitSyncPoint before using the texture.
2661 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2662 resource_provider
->WaitSyncPointIfNeeded(id
);
2663 Mock::VerifyAndClearExpectations(context
);
2665 // Using the texture does a consume of the mailbox.
2666 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2667 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2669 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2670 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2672 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2673 Mock::VerifyAndClearExpectations(context
);
2675 // When done with it, a sync point should be inserted, but no produce is
2677 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2678 EXPECT_CALL(*context
, insertSyncPoint());
2679 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2681 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2682 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2685 resource_provider
->DeleteResource(id
);
2686 EXPECT_EQ(0u, release_sync_point
);
2687 EXPECT_FALSE(lost_resource
);
2688 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2691 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2692 // Mailboxing is only supported for GL textures.
2693 if (GetParam() != ResourceProvider::GLTexture
)
2696 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2697 new TextureStateTrackingContext
);
2698 TextureStateTrackingContext
* context
= context_owned
.get();
2700 FakeOutputSurfaceClient output_surface_client
;
2701 scoped_ptr
<OutputSurface
> output_surface(
2702 FakeOutputSurface::Create3d(context_owned
.Pass()));
2703 CHECK(output_surface
->BindToClient(&output_surface_client
));
2705 scoped_ptr
<ResourceProvider
> resource_provider(
2706 ResourceProvider::Create(output_surface
.get(),
2707 shared_bitmap_manager_
.get(),
2708 gpu_memory_buffer_manager_
.get(),
2714 unsigned texture_id
= 1;
2715 uint32 sync_point
= 30;
2716 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2718 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2719 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2720 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2721 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2722 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2724 gpu::Mailbox gpu_mailbox
;
2725 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2726 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2727 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2729 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2731 ResourceProvider::ResourceId id
=
2732 resource_provider
->CreateResourceFromTextureMailbox(
2733 mailbox
, callback
.Pass());
2736 Mock::VerifyAndClearExpectations(context
);
2739 // Mailbox sync point WaitSyncPoint before using the texture.
2740 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2741 resource_provider
->WaitSyncPointIfNeeded(id
);
2742 Mock::VerifyAndClearExpectations(context
);
2744 // Using the texture does a consume of the mailbox.
2745 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2746 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2748 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2749 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2751 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2752 Mock::VerifyAndClearExpectations(context
);
2754 // When done with it, a sync point should be inserted, but no produce is
2756 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2757 EXPECT_CALL(*context
, insertSyncPoint());
2758 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2760 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2761 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2765 TEST_P(ResourceProviderTest
,
2766 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2767 // Mailboxing is only supported for GL textures.
2768 if (GetParam() != ResourceProvider::GLTexture
)
2771 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2772 new TextureStateTrackingContext
);
2773 TextureStateTrackingContext
* context
= context_owned
.get();
2775 FakeOutputSurfaceClient output_surface_client
;
2776 scoped_ptr
<OutputSurface
> output_surface(
2777 FakeOutputSurface::Create3d(context_owned
.Pass()));
2778 CHECK(output_surface
->BindToClient(&output_surface_client
));
2780 scoped_ptr
<ResourceProvider
> resource_provider(
2781 ResourceProvider::Create(output_surface
.get(),
2782 shared_bitmap_manager_
.get(),
2783 gpu_memory_buffer_manager_
.get(),
2789 uint32 sync_point
= 30;
2790 unsigned target
= GL_TEXTURE_2D
;
2792 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2793 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2794 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2795 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2796 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2798 gpu::Mailbox gpu_mailbox
;
2799 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2800 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2801 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2803 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2805 ResourceProvider::ResourceId id
=
2806 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2810 Mock::VerifyAndClearExpectations(context
);
2813 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2814 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2815 resource_provider
->WaitSyncPointIfNeeded(id
);
2816 Mock::VerifyAndClearExpectations(context
);
2818 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2819 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2820 resource_provider
->WaitSyncPointIfNeeded(id
);
2821 Mock::VerifyAndClearExpectations(context
);
2825 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2826 // Mailboxing is only supported for GL textures.
2827 if (GetParam() != ResourceProvider::GLTexture
)
2830 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2831 new TextureStateTrackingContext
);
2832 TextureStateTrackingContext
* context
= context_owned
.get();
2834 FakeOutputSurfaceClient output_surface_client
;
2835 scoped_ptr
<OutputSurface
> output_surface(
2836 FakeOutputSurface::Create3d(context_owned
.Pass()));
2837 CHECK(output_surface
->BindToClient(&output_surface_client
));
2839 scoped_ptr
<ResourceProvider
> resource_provider(
2840 ResourceProvider::Create(output_surface
.get(),
2841 shared_bitmap_manager_
.get(),
2842 gpu_memory_buffer_manager_
.get(),
2848 uint32 sync_point
= 0;
2849 unsigned target
= GL_TEXTURE_2D
;
2851 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2852 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2853 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2854 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2855 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2857 gpu::Mailbox gpu_mailbox
;
2858 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2859 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2860 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2862 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2864 ResourceProvider::ResourceId id
=
2865 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2869 Mock::VerifyAndClearExpectations(context
);
2872 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2873 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2874 resource_provider
->WaitSyncPointIfNeeded(id
);
2875 Mock::VerifyAndClearExpectations(context
);
2879 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2881 MOCK_METHOD0(NextTextureId
, GLuint());
2882 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2883 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2884 MOCK_METHOD5(texStorage2DEXT
,
2887 GLuint internalformat
,
2890 MOCK_METHOD9(texImage2D
,
2893 GLenum internalformat
,
2899 const void* pixels
));
2900 MOCK_METHOD9(texSubImage2D
,
2909 const void* pixels
));
2910 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2913 GLenum internalformat
,
2919 const void* pixels
));
2920 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2929 const void* pixels
));
2930 MOCK_METHOD8(compressedTexImage2D
,
2933 GLenum internalformat
,
2939 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
2940 MOCK_METHOD4(createImageCHROMIUM
,
2941 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
2942 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
2943 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2944 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2946 // We're mocking bindTexture, so we override
2947 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2948 // currently bound texture.
2949 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
2952 TEST_P(ResourceProviderTest
, TextureAllocation
) {
2953 // Only for GL textures.
2954 if (GetParam() != ResourceProvider::GLTexture
)
2956 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2957 new StrictMock
<AllocationTrackingContext3D
>);
2958 AllocationTrackingContext3D
* context
= context_owned
.get();
2960 FakeOutputSurfaceClient output_surface_client
;
2961 scoped_ptr
<OutputSurface
> output_surface(
2962 FakeOutputSurface::Create3d(context_owned
.Pass()));
2963 CHECK(output_surface
->BindToClient(&output_surface_client
));
2965 scoped_ptr
<ResourceProvider
> resource_provider(
2966 ResourceProvider::Create(output_surface
.get(),
2967 shared_bitmap_manager_
.get(),
2968 gpu_memory_buffer_manager_
.get(),
2974 gfx::Size
size(2, 2);
2975 gfx::Vector2d
offset(0, 0);
2976 gfx::Rect
rect(0, 0, 2, 2);
2977 ResourceFormat format
= RGBA_8888
;
2978 ResourceProvider::ResourceId id
= 0;
2979 uint8_t pixels
[16] = { 0 };
2980 int texture_id
= 123;
2982 // Lazy allocation. Don't allocate when creating the resource.
2983 id
= resource_provider
->CreateResource(
2984 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2986 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2987 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2988 resource_provider
->CreateForTesting(id
);
2990 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2991 resource_provider
->DeleteResource(id
);
2993 Mock::VerifyAndClearExpectations(context
);
2995 // Do allocate when we set the pixels.
2996 id
= resource_provider
->CreateResource(
2997 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2999 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3000 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3001 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3002 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3003 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
3005 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3006 resource_provider
->DeleteResource(id
);
3008 Mock::VerifyAndClearExpectations(context
);
3010 // Same for async version.
3011 id
= resource_provider
->CreateResource(
3012 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3013 resource_provider
->AcquirePixelBuffer(id
);
3015 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3016 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3017 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3019 resource_provider
->BeginSetPixels(id
);
3020 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3022 resource_provider
->ReleasePixelBuffer(id
);
3024 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3025 resource_provider
->DeleteResource(id
);
3027 Mock::VerifyAndClearExpectations(context
);
3030 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3031 // Only for GL textures.
3032 if (GetParam() != ResourceProvider::GLTexture
)
3034 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3035 new StrictMock
<AllocationTrackingContext3D
>);
3036 AllocationTrackingContext3D
* context
= context_owned
.get();
3037 context
->set_support_texture_storage(true);
3038 context
->set_support_texture_usage(true);
3040 FakeOutputSurfaceClient output_surface_client
;
3041 scoped_ptr
<OutputSurface
> output_surface(
3042 FakeOutputSurface::Create3d(context_owned
.Pass()));
3043 CHECK(output_surface
->BindToClient(&output_surface_client
));
3045 scoped_ptr
<ResourceProvider
> resource_provider(
3046 ResourceProvider::Create(output_surface
.get(),
3047 shared_bitmap_manager_
.get(),
3048 gpu_memory_buffer_manager_
.get(),
3054 gfx::Size
size(2, 2);
3056 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3057 const ResourceProvider::TextureHint hints
[4] = {
3058 ResourceProvider::TextureHintDefault
,
3059 ResourceProvider::TextureHintImmutable
,
3060 ResourceProvider::TextureHintFramebuffer
,
3061 ResourceProvider::TextureHintImmutableFramebuffer
,
3063 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3064 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3065 // Lazy allocation. Don't allocate when creating the resource.
3066 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3067 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3069 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3070 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3071 bool is_immutable_hint
=
3072 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3073 bool support_immutable_texture
=
3074 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3075 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3076 .Times(support_immutable_texture
? 1 : 0);
3077 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3078 .Times(support_immutable_texture
? 0 : 1);
3079 resource_provider
->AllocateForTesting(id
);
3081 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3082 resource_provider
->DeleteResource(id
);
3084 Mock::VerifyAndClearExpectations(context
);
3089 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3090 // Only for GL textures.
3091 if (GetParam() != ResourceProvider::GLTexture
)
3093 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3094 new StrictMock
<AllocationTrackingContext3D
>);
3095 AllocationTrackingContext3D
* context
= context_owned
.get();
3096 context
->set_support_texture_format_bgra8888(true);
3097 context
->set_support_texture_storage(true);
3098 context
->set_support_texture_usage(true);
3100 FakeOutputSurfaceClient output_surface_client
;
3101 scoped_ptr
<OutputSurface
> output_surface(
3102 FakeOutputSurface::Create3d(context_owned
.Pass()));
3103 CHECK(output_surface
->BindToClient(&output_surface_client
));
3105 scoped_ptr
<ResourceProvider
> resource_provider(
3106 ResourceProvider::Create(output_surface
.get(),
3107 shared_bitmap_manager_
.get(),
3108 gpu_memory_buffer_manager_
.get(),
3114 gfx::Size
size(2, 2);
3115 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3117 const ResourceProvider::TextureHint hints
[4] = {
3118 ResourceProvider::TextureHintDefault
,
3119 ResourceProvider::TextureHintImmutable
,
3120 ResourceProvider::TextureHintFramebuffer
,
3121 ResourceProvider::TextureHintImmutableFramebuffer
,
3123 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3124 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3125 // Lazy allocation. Don't allocate when creating the resource.
3126 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3127 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3129 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3130 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3131 bool is_immutable_hint
=
3132 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3133 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3134 .Times(is_immutable_hint
? 1 : 0);
3135 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3136 .Times(is_immutable_hint
? 0 : 1);
3137 resource_provider
->AllocateForTesting(id
);
3139 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3140 resource_provider
->DeleteResource(id
);
3142 Mock::VerifyAndClearExpectations(context
);
3147 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3148 if (GetParam() != ResourceProvider::GLTexture
)
3150 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3151 new StrictMock
<AllocationTrackingContext3D
>);
3152 AllocationTrackingContext3D
* context
= context_owned
.get();
3154 FakeOutputSurfaceClient output_surface_client
;
3155 scoped_ptr
<OutputSurface
> output_surface(
3156 FakeOutputSurface::Create3d(context_owned
.Pass()));
3157 CHECK(output_surface
->BindToClient(&output_surface_client
));
3159 gfx::Size
size(2, 2);
3160 ResourceFormat format
= RGBA_8888
;
3161 ResourceProvider::ResourceId id
= 0;
3162 int texture_id
= 123;
3164 scoped_ptr
<ResourceProvider
> resource_provider(
3165 ResourceProvider::Create(output_surface
.get(),
3166 shared_bitmap_manager_
.get(),
3167 gpu_memory_buffer_manager_
.get(),
3173 id
= resource_provider
->CreateResource(
3174 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3175 resource_provider
->AcquirePixelBuffer(id
);
3177 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3178 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3179 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3181 resource_provider
->BeginSetPixels(id
);
3183 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3185 resource_provider
->ReleasePixelBuffer(id
);
3187 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3188 resource_provider
->DeleteResource(id
);
3190 Mock::VerifyAndClearExpectations(context
);
3193 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3194 // Only for GL textures.
3195 if (GetParam() != ResourceProvider::GLTexture
)
3197 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3198 new StrictMock
<AllocationTrackingContext3D
>);
3199 AllocationTrackingContext3D
* context
= context_owned
.get();
3201 FakeOutputSurfaceClient output_surface_client
;
3202 scoped_ptr
<OutputSurface
> output_surface(
3203 FakeOutputSurface::Create3d(context_owned
.Pass()));
3204 CHECK(output_surface
->BindToClient(&output_surface_client
));
3206 gfx::Size
size(2, 2);
3207 ResourceFormat format
= RGBA_8888
;
3208 ResourceProvider::ResourceId id
= 0;
3209 int texture_id
= 123;
3211 scoped_ptr
<ResourceProvider
> resource_provider(
3212 ResourceProvider::Create(output_surface
.get(),
3213 shared_bitmap_manager_
.get(),
3214 gpu_memory_buffer_manager_
.get(),
3220 id
= resource_provider
->CreateResource(
3221 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3222 resource_provider
->AcquirePixelBuffer(id
);
3224 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3225 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3226 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3228 resource_provider
->BeginSetPixels(id
);
3230 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3231 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3232 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3233 resource_provider
->ForceSetPixelsToComplete(id
);
3235 resource_provider
->ReleasePixelBuffer(id
);
3237 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3238 resource_provider
->DeleteResource(id
);
3240 Mock::VerifyAndClearExpectations(context
);
3243 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3244 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3245 new NiceMock
<AllocationTrackingContext3D
>);
3246 AllocationTrackingContext3D
* context
= context_owned
.get();
3248 FakeOutputSurfaceClient output_surface_client
;
3249 scoped_ptr
<OutputSurface
> output_surface(
3250 FakeOutputSurface::Create3d(context_owned
.Pass()));
3251 CHECK(output_surface
->BindToClient(&output_surface_client
));
3253 gfx::Size
size(2, 2);
3254 ResourceFormat format
= RGBA_8888
;
3255 ResourceProvider::ResourceId id
= 0;
3256 int texture_id
= 123;
3258 scoped_ptr
<ResourceProvider
> resource_provider(
3259 ResourceProvider::Create(output_surface
.get(),
3260 shared_bitmap_manager_
.get(),
3261 gpu_memory_buffer_manager_
.get(),
3267 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3269 id
= resource_provider
->CreateResource(
3270 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3271 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3272 GL_INNOCENT_CONTEXT_RESET_ARB
);
3274 resource_provider
->AcquirePixelBuffer(id
);
3276 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3277 EXPECT_FALSE(buffer
);
3278 resource_provider
->UnmapPixelBuffer(id
);
3279 Mock::VerifyAndClearExpectations(context
);
3282 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3283 // Only for GL textures.
3284 if (GetParam() != ResourceProvider::GLTexture
)
3286 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3287 new StrictMock
<AllocationTrackingContext3D
>);
3288 AllocationTrackingContext3D
* context
= context_owned
.get();
3290 FakeOutputSurfaceClient output_surface_client
;
3291 scoped_ptr
<OutputSurface
> output_surface(
3292 FakeOutputSurface::Create3d(context_owned
.Pass()));
3293 CHECK(output_surface
->BindToClient(&output_surface_client
));
3295 const int kWidth
= 2;
3296 const int kHeight
= 2;
3297 gfx::Size
size(kWidth
, kHeight
);
3298 ResourceFormat format
= RGBA_8888
;
3299 ResourceProvider::ResourceId id
= 0;
3300 const unsigned kTextureId
= 123u;
3301 const unsigned kImageId
= 234u;
3303 scoped_ptr
<ResourceProvider
> resource_provider(
3304 ResourceProvider::Create(output_surface
.get(),
3305 shared_bitmap_manager_
.get(),
3306 gpu_memory_buffer_manager_
.get(),
3312 id
= resource_provider
->CreateResource(
3313 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3315 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3316 .WillOnce(Return(kImageId
))
3317 .RetiresOnSaturation();
3319 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3320 resource_provider
.get(), id
);
3321 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3324 EXPECT_CALL(*context
, NextTextureId())
3325 .WillOnce(Return(kTextureId
))
3326 .RetiresOnSaturation();
3327 // Once in CreateTextureId and once in BindForSampling
3328 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3329 .RetiresOnSaturation();
3330 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3332 .RetiresOnSaturation();
3334 ResourceProvider::ScopedSamplerGL
lock_gl(
3335 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3336 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3340 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3341 resource_provider
.get(), id
);
3342 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3345 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3346 .RetiresOnSaturation();
3347 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3349 .RetiresOnSaturation();
3350 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3352 .RetiresOnSaturation();
3353 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3355 .RetiresOnSaturation();
3357 ResourceProvider::ScopedSamplerGL
lock_gl(
3358 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3359 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3362 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3364 .RetiresOnSaturation();
3367 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3368 if (GetParam() != ResourceProvider::GLTexture
)
3370 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3371 new StrictMock
<AllocationTrackingContext3D
>);
3372 AllocationTrackingContext3D
* context
= context_owned
.get();
3373 context_owned
->set_support_sync_query(true);
3375 FakeOutputSurfaceClient output_surface_client
;
3376 scoped_ptr
<OutputSurface
> output_surface(
3377 FakeOutputSurface::Create3d(context_owned
.Pass()));
3378 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3380 const int kWidth
= 2;
3381 const int kHeight
= 2;
3382 gfx::Size
size(kWidth
, kHeight
);
3383 ResourceFormat format
= RGBA_8888
;
3384 ResourceProvider::ResourceId source_id
= 0;
3385 ResourceProvider::ResourceId dest_id
= 0;
3386 const unsigned kSourceTextureId
= 123u;
3387 const unsigned kDestTextureId
= 321u;
3388 const unsigned kImageId
= 234u;
3390 scoped_ptr
<ResourceProvider
> resource_provider(
3391 ResourceProvider::Create(output_surface
.get(),
3392 shared_bitmap_manager_
.get(),
3393 gpu_memory_buffer_manager_
.get(),
3399 source_id
= resource_provider
->CreateResource(
3400 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3402 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3403 .WillOnce(Return(kImageId
))
3404 .RetiresOnSaturation();
3406 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3407 resource_provider
.get(), source_id
);
3408 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3410 Mock::VerifyAndClearExpectations(context
);
3412 dest_id
= resource_provider
->CreateResource(
3413 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3415 EXPECT_CALL(*context
, NextTextureId())
3416 .WillOnce(Return(kDestTextureId
))
3417 .RetiresOnSaturation();
3418 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3420 .RetiresOnSaturation();
3421 EXPECT_CALL(*context
, NextTextureId())
3422 .WillOnce(Return(kSourceTextureId
))
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3429 .RetiresOnSaturation();
3430 resource_provider
->CopyResource(source_id
, dest_id
);
3431 Mock::VerifyAndClearExpectations(context
);
3433 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3435 .RetiresOnSaturation();
3436 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3438 .RetiresOnSaturation();
3439 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3441 .RetiresOnSaturation();
3442 resource_provider
->DeleteResource(source_id
);
3443 resource_provider
->DeleteResource(dest_id
);
3446 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3447 ResourceProvider
* resource_provider
,
3448 FakeOutputSurface
* output_surface
) {
3449 scoped_ptr
<ResourceProviderContext
> context_owned
=
3450 ResourceProviderContext::Create(shared_data
);
3451 ResourceProviderContext
* context
= context_owned
.get();
3453 scoped_refptr
<TestContextProvider
> context_provider
=
3454 TestContextProvider::Create(context_owned
.Pass());
3455 output_surface
->InitializeAndSetContext3d(context_provider
);
3456 resource_provider
->InitializeGL();
3458 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3461 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3462 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3463 bool delegated_rendering
= false;
3464 scoped_ptr
<FakeOutputSurface
> output_surface(
3465 FakeOutputSurface::CreateDeferredGL(
3466 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3467 delegated_rendering
));
3468 FakeOutputSurfaceClient
client(output_surface
.get());
3469 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3470 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3471 new TestSharedBitmapManager());
3472 scoped_ptr
<ResourceProvider
> resource_provider(
3473 ResourceProvider::Create(output_surface
.get(),
3474 shared_bitmap_manager
.get(),
3481 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3483 InitializeGLAndCheck(shared_data
.get(),
3484 resource_provider
.get(),
3485 output_surface
.get());
3487 resource_provider
->InitializeSoftware();
3488 output_surface
->ReleaseGL();
3489 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3491 InitializeGLAndCheck(shared_data
.get(),
3492 resource_provider
.get(),
3493 output_surface
.get());
3496 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3497 if (GetParam() != ResourceProvider::GLTexture
)
3500 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3501 new AllocationTrackingContext3D
);
3502 AllocationTrackingContext3D
* context
= context_owned
.get();
3503 context_owned
->set_support_compressed_texture_etc1(true);
3505 FakeOutputSurfaceClient output_surface_client
;
3506 scoped_ptr
<OutputSurface
> output_surface(
3507 FakeOutputSurface::Create3d(context_owned
.Pass()));
3508 CHECK(output_surface
->BindToClient(&output_surface_client
));
3510 gfx::Size
size(4, 4);
3511 scoped_ptr
<ResourceProvider
> resource_provider(
3512 ResourceProvider::Create(output_surface
.get(),
3513 shared_bitmap_manager_
.get(),
3514 gpu_memory_buffer_manager_
.get(),
3519 int texture_id
= 123;
3521 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3522 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3524 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3525 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3526 resource_provider
->AllocateForTesting(id
);
3528 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3529 resource_provider
->DeleteResource(id
);
3532 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3533 if (GetParam() != ResourceProvider::GLTexture
)
3536 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3537 new AllocationTrackingContext3D
);
3538 AllocationTrackingContext3D
* context
= context_owned
.get();
3539 context_owned
->set_support_compressed_texture_etc1(true);
3541 FakeOutputSurfaceClient output_surface_client
;
3542 scoped_ptr
<OutputSurface
> output_surface(
3543 FakeOutputSurface::Create3d(context_owned
.Pass()));
3544 CHECK(output_surface
->BindToClient(&output_surface_client
));
3546 gfx::Size
size(4, 4);
3547 scoped_ptr
<ResourceProvider
> resource_provider(
3548 ResourceProvider::Create(output_surface
.get(),
3549 shared_bitmap_manager_
.get(),
3550 gpu_memory_buffer_manager_
.get(),
3555 int texture_id
= 123;
3558 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3559 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3561 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3562 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3563 EXPECT_CALL(*context
,
3564 compressedTexImage2D(
3565 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3566 resource_provider
->SetPixels(
3567 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3569 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3570 resource_provider
->DeleteResource(id
);
3573 INSTANTIATE_TEST_CASE_P(
3574 ResourceProviderTests
,
3575 ResourceProviderTest
,
3576 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3578 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3580 GLuint
NextTextureId() override
{
3581 base::AutoLock
lock(namespace_
->lock
);
3582 return namespace_
->next_texture_id
++;
3584 void RetireTextureId(GLuint
) override
{}
3585 GLuint
PeekTextureId() {
3586 base::AutoLock
lock(namespace_
->lock
);
3587 return namespace_
->next_texture_id
;
3591 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3592 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3593 new TextureIdAllocationTrackingContext
);
3594 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3596 FakeOutputSurfaceClient output_surface_client
;
3597 scoped_ptr
<OutputSurface
> output_surface(
3598 FakeOutputSurface::Create3d(context_owned
.Pass()));
3599 CHECK(output_surface
->BindToClient(&output_surface_client
));
3600 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3601 new TestSharedBitmapManager());
3603 gfx::Size
size(1, 1);
3604 ResourceFormat format
= RGBA_8888
;
3607 size_t kTextureAllocationChunkSize
= 1;
3608 scoped_ptr
<ResourceProvider
> resource_provider(
3609 ResourceProvider::Create(output_surface
.get(),
3610 shared_bitmap_manager
.get(),
3615 kTextureAllocationChunkSize
));
3617 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3618 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3619 resource_provider
->AllocateForTesting(id
);
3620 Mock::VerifyAndClearExpectations(context
);
3622 DCHECK_EQ(2u, context
->PeekTextureId());
3623 resource_provider
->DeleteResource(id
);
3627 size_t kTextureAllocationChunkSize
= 8;
3628 scoped_ptr
<ResourceProvider
> resource_provider(
3629 ResourceProvider::Create(output_surface
.get(),
3630 shared_bitmap_manager
.get(),
3635 kTextureAllocationChunkSize
));
3637 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3638 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3639 resource_provider
->AllocateForTesting(id
);
3640 Mock::VerifyAndClearExpectations(context
);
3642 DCHECK_EQ(10u, context
->PeekTextureId());
3643 resource_provider
->DeleteResource(id
);