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_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "gpu/GLES2/gl2extchromium.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/khronos/GLES2/gl2.h"
29 #include "third_party/khronos/GLES2/gl2ext.h"
30 #include "ui/gfx/rect.h"
33 using testing::NiceMock
;
34 using testing::Return
;
35 using testing::SetArgPointee
;
36 using testing::StrictMock
;
42 static void EmptyReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
44 static void SharedMemoryReleaseCallback(scoped_ptr
<base::SharedMemory
> memory
,
46 bool lost_resource
) {}
48 static void ReleaseTextureMailbox(uint32
* release_sync_point
,
49 bool* release_lost_resource
,
52 *release_sync_point
= sync_point
;
53 *release_lost_resource
= lost_resource
;
56 static void ReleaseSharedMemoryCallback(
57 scoped_ptr
<base::SharedMemory
> shared_memory
,
59 uint32
* release_sync_point
,
60 bool* lost_resource_result
,
63 *release_called
= true;
64 *release_sync_point
= sync_point
;
65 *lost_resource_result
= lost_resource
;
68 static scoped_ptr
<base::SharedMemory
> CreateAndFillSharedMemory(
69 const gfx::Size
& size
,
71 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
72 CHECK(shared_memory
->CreateAndMapAnonymous(4 * size
.GetArea()));
73 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_memory
->memory());
75 std::fill_n(pixels
, size
.GetArea(), value
);
76 return shared_memory
.Pass();
79 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
81 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
82 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
83 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
84 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
85 MOCK_METHOD2(produceTextureCHROMIUM
,
86 void(GLenum target
, const GLbyte
* mailbox
));
87 MOCK_METHOD2(consumeTextureCHROMIUM
,
88 void(GLenum target
, const GLbyte
* mailbox
));
90 // Force all textures to be consecutive numbers starting at "1",
91 // so we easily can test for them.
92 virtual GLuint
NextTextureId() OVERRIDE
{
93 base::AutoLock
lock(namespace_
->lock
);
94 return namespace_
->next_texture_id
++;
96 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
99 // Shared data between multiple ResourceProviderContext. This contains mailbox
100 // contents as well as information about sync points.
101 class ContextSharedData
{
103 static scoped_ptr
<ContextSharedData
> Create() {
104 return make_scoped_ptr(new ContextSharedData());
107 uint32
InsertSyncPoint() { return next_sync_point_
++; }
109 void GenMailbox(GLbyte
* mailbox
) {
110 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
111 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
115 void ProduceTexture(const GLbyte
* mailbox_name
,
117 scoped_refptr
<TestTexture
> texture
) {
118 unsigned mailbox
= 0;
119 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
120 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
121 textures_
[mailbox
] = texture
;
122 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
123 sync_point_for_mailbox_
[mailbox
] = sync_point
;
126 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
128 unsigned mailbox
= 0;
129 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
130 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
132 // If the latest sync point the context has waited on is before the sync
133 // point for when the mailbox was set, pretend we never saw that
135 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
137 return scoped_refptr
<TestTexture
>();
139 return textures_
[mailbox
];
143 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
145 uint32 next_sync_point_
;
146 unsigned next_mailbox_
;
147 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
> > TextureMap
;
148 TextureMap textures_
;
149 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
152 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
154 static scoped_ptr
<ResourceProviderContext
> Create(
155 ContextSharedData
* shared_data
) {
156 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
159 virtual GLuint
insertSyncPoint() OVERRIDE
{
160 uint32 sync_point
= shared_data_
->InsertSyncPoint();
161 // Commit the produceTextureCHROMIUM calls at this point, so that
162 // they're associated with the sync point.
163 for (PendingProduceTextureList::iterator it
=
164 pending_produce_textures_
.begin();
165 it
!= pending_produce_textures_
.end();
167 shared_data_
->ProduceTexture(
168 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
170 pending_produce_textures_
.clear();
174 virtual void waitSyncPoint(GLuint sync_point
) OVERRIDE
{
175 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
178 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
180 virtual void texStorage2DEXT(GLenum target
,
182 GLuint internalformat
,
184 GLint height
) OVERRIDE
{
185 CheckTextureIsBound(target
);
186 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
187 ASSERT_EQ(1, levels
);
188 GLenum format
= GL_RGBA
;
189 switch (internalformat
) {
193 format
= GL_BGRA_EXT
;
198 AllocateTexture(gfx::Size(width
, height
), format
);
201 virtual void texImage2D(GLenum target
,
203 GLenum internalformat
,
209 const void* pixels
) OVERRIDE
{
210 CheckTextureIsBound(target
);
211 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
213 ASSERT_EQ(internalformat
, format
);
214 ASSERT_FALSE(border
);
215 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
216 AllocateTexture(gfx::Size(width
, height
), format
);
218 SetPixels(0, 0, width
, height
, pixels
);
221 virtual void texSubImage2D(GLenum target
,
229 const void* pixels
) OVERRIDE
{
230 CheckTextureIsBound(target
);
231 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
233 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
235 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
236 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
239 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
242 virtual void genMailboxCHROMIUM(GLbyte
* mailbox
) OVERRIDE
{
243 return shared_data_
->GenMailbox(mailbox
);
246 virtual void produceTextureCHROMIUM(GLenum target
,
247 const GLbyte
* mailbox
) OVERRIDE
{
248 CheckTextureIsBound(target
);
250 // Delay moving the texture into the mailbox until the next
251 // InsertSyncPoint, so that it is not visible to other contexts that
252 // haven't waited on that sync point.
253 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
254 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
255 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
256 pending
->texture
= BoundTexture(target
);
257 pending_produce_textures_
.push_back(pending
.Pass());
260 virtual void consumeTextureCHROMIUM(GLenum target
,
261 const GLbyte
* mailbox
) OVERRIDE
{
262 CheckTextureIsBound(target
);
263 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
264 scoped_refptr
<TestTexture
> texture
=
265 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
266 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
269 void GetPixels(const gfx::Size
& size
,
270 ResourceFormat format
,
272 CheckTextureIsBound(GL_TEXTURE_2D
);
273 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
274 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
275 ASSERT_EQ(texture
->size
, size
);
276 ASSERT_EQ(texture
->format
, format
);
277 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
281 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
282 : shared_data_(shared_data
),
283 last_waited_sync_point_(0) {}
286 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 ResourceFormat texture_format
= RGBA_8888
;
291 texture_format
= RGBA_8888
;
294 texture_format
= BGRA_8888
;
297 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
298 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
301 void SetPixels(int xoffset
,
305 const void* pixels
) {
306 CheckTextureIsBound(GL_TEXTURE_2D
);
307 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
308 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
309 ASSERT_TRUE(texture
->data
.get());
310 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
311 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
313 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
315 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
316 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
317 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
318 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
319 for (int i
= 0; i
< height
; ++i
) {
320 memcpy(dest
, src
, in_pitch
);
326 struct PendingProduceTexture
{
327 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
328 scoped_refptr
<TestTexture
> texture
;
330 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
331 ContextSharedData
* shared_data_
;
332 GLuint last_waited_sync_point_
;
333 PendingProduceTextureList pending_produce_textures_
;
336 void GetResourcePixels(ResourceProvider
* resource_provider
,
337 ResourceProviderContext
* context
,
338 ResourceProvider::ResourceId id
,
339 const gfx::Size
& size
,
340 ResourceFormat format
,
342 resource_provider
->WaitSyncPointIfNeeded(id
);
343 switch (resource_provider
->default_resource_type()) {
344 case ResourceProvider::GLTexture
: {
345 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
346 ASSERT_NE(0U, lock_gl
.texture_id());
347 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
348 context
->GetPixels(size
, format
, pixels
);
351 case ResourceProvider::Bitmap
: {
352 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
355 lock_software
.sk_bitmap()->getPixels(),
356 lock_software
.sk_bitmap()->getSize());
359 case ResourceProvider::InvalidType
:
365 class ResourceProviderTest
366 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
368 ResourceProviderTest()
369 : shared_data_(ContextSharedData::Create()),
371 child_context_(NULL
) {
372 switch (GetParam()) {
373 case ResourceProvider::GLTexture
: {
374 scoped_ptr
<ResourceProviderContext
> context3d(
375 ResourceProviderContext::Create(shared_data_
.get()));
376 context3d_
= context3d
.get();
378 scoped_refptr
<TestContextProvider
> context_provider
=
379 TestContextProvider::Create(
380 context3d
.PassAs
<TestWebGraphicsContext3D
>());
382 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
384 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
385 ResourceProviderContext::Create(shared_data_
.get());
386 child_context_
= child_context_owned
.get();
387 child_output_surface_
= FakeOutputSurface::Create3d(
388 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>());
391 case ResourceProvider::Bitmap
:
392 output_surface_
= FakeOutputSurface::CreateSoftware(
393 make_scoped_ptr(new SoftwareOutputDevice
));
394 child_output_surface_
= FakeOutputSurface::CreateSoftware(
395 make_scoped_ptr(new SoftwareOutputDevice
));
397 case ResourceProvider::InvalidType
:
401 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
402 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
404 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
406 resource_provider_
= ResourceProvider::Create(
407 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
409 child_resource_provider_
= ResourceProvider::Create(
410 child_output_surface_
.get(),
411 shared_bitmap_manager_
.get(),
418 static void CollectResources(ReturnedResourceArray
* array
,
419 const ReturnedResourceArray
& returned
) {
420 array
->insert(array
->end(), returned
.begin(), returned
.end());
423 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
424 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
427 static void SetResourceFilter(ResourceProvider
* resource_provider
,
428 ResourceProvider::ResourceId id
,
430 ResourceProvider::ScopedSamplerGL
sampler(
431 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
434 ResourceProviderContext
* context() { return context3d_
; }
436 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
438 bool* release_called
,
439 uint32
* sync_point
) {
440 if (GetParam() == ResourceProvider::GLTexture
) {
441 unsigned texture
= child_context_
->createTexture();
442 gpu::Mailbox gpu_mailbox
;
443 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
444 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
445 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
446 *sync_point
= child_context_
->insertSyncPoint();
447 EXPECT_LT(0u, *sync_point
);
449 scoped_ptr
<base::SharedMemory
> shared_memory
;
450 scoped_ptr
<SingleReleaseCallback
> callback
=
451 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
452 base::Passed(&shared_memory
),
456 return child_resource_provider_
->CreateResourceFromTextureMailbox(
457 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
460 gfx::Size
size(64, 64);
461 scoped_ptr
<base::SharedMemory
> shared_memory(
462 CreateAndFillSharedMemory(size
, 0));
464 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
465 scoped_ptr
<SingleReleaseCallback
> callback
=
466 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
467 base::Passed(&shared_memory
),
471 return child_resource_provider_
->CreateResourceFromTextureMailbox(
472 TextureMailbox(shared_memory_ptr
, size
), callback
.Pass());
477 scoped_ptr
<ContextSharedData
> shared_data_
;
478 ResourceProviderContext
* context3d_
;
479 ResourceProviderContext
* child_context_
;
480 FakeOutputSurfaceClient output_surface_client_
;
481 FakeOutputSurfaceClient child_output_surface_client_
;
482 scoped_ptr
<OutputSurface
> output_surface_
;
483 scoped_ptr
<OutputSurface
> child_output_surface_
;
484 scoped_ptr
<ResourceProvider
> resource_provider_
;
485 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
486 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
489 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
490 ResourceProvider
* resource_provider
,
491 ResourceProviderContext
* context
) {
492 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
494 gfx::Size
size(1, 1);
495 ResourceFormat format
= RGBA_8888
;
496 size_t pixel_size
= TextureSizeBytes(size
, format
);
497 ASSERT_EQ(4U, pixel_size
);
499 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
500 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
501 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
502 if (expected_default_type
== ResourceProvider::GLTexture
)
503 EXPECT_EQ(0u, context
->NumTextures());
505 uint8_t data
[4] = { 1, 2, 3, 4 };
506 gfx::Rect
rect(size
);
507 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
508 if (expected_default_type
== ResourceProvider::GLTexture
)
509 EXPECT_EQ(1u, context
->NumTextures());
511 uint8_t result
[4] = { 0 };
512 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
513 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
515 resource_provider
->DeleteResource(id
);
516 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
517 if (expected_default_type
== ResourceProvider::GLTexture
)
518 EXPECT_EQ(0u, context
->NumTextures());
521 TEST_P(ResourceProviderTest
, Basic
) {
522 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
525 TEST_P(ResourceProviderTest
, Upload
) {
526 gfx::Size
size(2, 2);
527 ResourceFormat format
= RGBA_8888
;
528 size_t pixel_size
= TextureSizeBytes(size
, format
);
529 ASSERT_EQ(16U, pixel_size
);
531 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
532 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
534 uint8_t image
[16] = { 0 };
535 gfx::Rect
image_rect(size
);
536 resource_provider_
->SetPixels(
537 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
539 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
542 uint8_t result
[16] = { 0 };
544 gfx::Rect
source_rect(0, 0, 1, 1);
545 gfx::Vector2d
dest_offset(0, 0);
546 resource_provider_
->SetPixels(
547 id
, image
, image_rect
, source_rect
, dest_offset
);
549 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
551 resource_provider_
.get(), context(), id
, size
, format
, result
);
552 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
555 gfx::Rect
source_rect(0, 0, 1, 1);
556 gfx::Vector2d
dest_offset(1, 1);
557 resource_provider_
->SetPixels(
558 id
, image
, image_rect
, source_rect
, dest_offset
);
560 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
562 resource_provider_
.get(), context(), id
, size
, format
, result
);
563 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
566 gfx::Rect
source_rect(1, 0, 1, 1);
567 gfx::Vector2d
dest_offset(0, 1);
568 resource_provider_
->SetPixels(
569 id
, image
, image_rect
, source_rect
, dest_offset
);
571 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
573 resource_provider_
.get(), context(), id
, size
, format
, result
);
574 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
577 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
578 gfx::Rect
source_rect(100, 100, 1, 1);
579 gfx::Vector2d
dest_offset(1, 0);
580 resource_provider_
->SetPixels(
581 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
583 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
585 resource_provider_
.get(), context(), id
, size
, format
, result
);
586 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
589 resource_provider_
->DeleteResource(id
);
592 TEST_P(ResourceProviderTest
, TransferGLResources
) {
593 if (GetParam() != ResourceProvider::GLTexture
)
595 gfx::Size
size(1, 1);
596 ResourceFormat format
= RGBA_8888
;
597 size_t pixel_size
= TextureSizeBytes(size
, format
);
598 ASSERT_EQ(4U, pixel_size
);
600 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
601 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
602 uint8_t data1
[4] = { 1, 2, 3, 4 };
603 gfx::Rect
rect(size
);
604 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
606 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
607 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
608 uint8_t data2
[4] = { 5, 5, 5, 5 };
609 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
611 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
612 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
613 child_resource_provider_
->MapImageRasterBuffer(id3
);
614 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
616 GLuint external_texture_id
= child_context_
->createExternalTexture();
617 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
619 gpu::Mailbox external_mailbox
;
620 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
621 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
622 external_mailbox
.name
);
623 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
624 ResourceProvider::ResourceId id4
=
625 child_resource_provider_
->CreateResourceFromTextureMailbox(
627 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
628 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
)));
630 ReturnedResourceArray returned_to_child
;
632 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
634 // Transfer some resources to the parent.
635 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
636 resource_ids_to_transfer
.push_back(id1
);
637 resource_ids_to_transfer
.push_back(id2
);
638 resource_ids_to_transfer
.push_back(id3
);
639 resource_ids_to_transfer
.push_back(id4
);
640 TransferableResourceArray list
;
641 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
643 ASSERT_EQ(4u, list
.size());
644 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
645 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
646 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
647 list
[1].mailbox_holder
.sync_point
);
648 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
649 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
650 list
[2].mailbox_holder
.sync_point
);
651 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
652 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
653 list
[0].mailbox_holder
.texture_target
);
654 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
655 list
[1].mailbox_holder
.texture_target
);
656 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
657 list
[2].mailbox_holder
.texture_target
);
658 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
659 list
[3].mailbox_holder
.texture_target
);
660 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
661 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
662 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
663 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
664 resource_provider_
->ReceiveFromChild(child_id
, list
);
665 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
666 context3d_
->last_waited_sync_point());
668 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
669 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
672 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
673 context3d_
->last_waited_sync_point());
674 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
675 resource_ids_to_transfer
);
678 EXPECT_EQ(4u, resource_provider_
->num_resources());
679 ResourceProvider::ResourceIdMap resource_map
=
680 resource_provider_
->GetChildToParentMap(child_id
);
681 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
682 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
683 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
684 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
685 EXPECT_NE(0u, mapped_id1
);
686 EXPECT_NE(0u, mapped_id2
);
687 EXPECT_NE(0u, mapped_id3
);
688 EXPECT_NE(0u, mapped_id4
);
689 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
690 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
691 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
692 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
694 uint8_t result
[4] = { 0 };
696 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
697 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
700 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
701 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
704 // Check that transfering again the same resource from the child to the
706 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
707 resource_ids_to_transfer
.push_back(id1
);
708 resource_ids_to_transfer
.push_back(id2
);
709 resource_ids_to_transfer
.push_back(id3
);
710 TransferableResourceArray list
;
711 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
713 EXPECT_EQ(3u, list
.size());
714 EXPECT_EQ(id1
, list
[0].id
);
715 EXPECT_EQ(id2
, list
[1].id
);
716 EXPECT_EQ(id3
, list
[2].id
);
717 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
718 list
[0].mailbox_holder
.texture_target
);
719 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
720 list
[1].mailbox_holder
.texture_target
);
721 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
722 list
[2].mailbox_holder
.texture_target
);
723 ReturnedResourceArray returned
;
724 TransferableResource::ReturnResources(list
, &returned
);
725 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
726 // ids were exported twice, we returned them only once, they should still
728 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
729 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
730 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
733 EXPECT_EQ(0u, returned_to_child
.size());
735 // Transfer resources back from the parent to the child. Set no resources as
737 ResourceProvider::ResourceIdArray no_resources
;
738 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
740 ASSERT_EQ(4u, returned_to_child
.size());
741 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
742 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
743 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
744 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
745 EXPECT_FALSE(returned_to_child
[0].lost
);
746 EXPECT_FALSE(returned_to_child
[1].lost
);
747 EXPECT_FALSE(returned_to_child
[2].lost
);
748 EXPECT_FALSE(returned_to_child
[3].lost
);
749 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
750 returned_to_child
.clear();
752 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
753 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
754 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
755 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
758 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
759 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
761 ASSERT_NE(0U, lock
.texture_id());
762 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
763 child_context_
->GetPixels(size
, format
, result
);
764 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
767 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
768 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
770 ASSERT_NE(0U, lock
.texture_id());
771 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
772 child_context_
->GetPixels(size
, format
, result
);
773 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
776 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
777 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
779 ASSERT_NE(0U, lock
.texture_id());
780 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
783 // Transfer resources to the parent again.
784 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
785 resource_ids_to_transfer
.push_back(id1
);
786 resource_ids_to_transfer
.push_back(id2
);
787 resource_ids_to_transfer
.push_back(id3
);
788 resource_ids_to_transfer
.push_back(id4
);
789 TransferableResourceArray list
;
790 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
792 ASSERT_EQ(4u, list
.size());
793 EXPECT_EQ(id1
, list
[0].id
);
794 EXPECT_EQ(id2
, list
[1].id
);
795 EXPECT_EQ(id3
, list
[2].id
);
796 EXPECT_EQ(id4
, list
[3].id
);
797 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
798 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
799 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
800 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
801 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
802 list
[0].mailbox_holder
.texture_target
);
803 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
804 list
[1].mailbox_holder
.texture_target
);
805 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
806 list
[2].mailbox_holder
.texture_target
);
807 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
808 list
[3].mailbox_holder
.texture_target
);
809 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
810 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
811 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
812 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
813 resource_provider_
->ReceiveFromChild(child_id
, list
);
814 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
815 resource_ids_to_transfer
);
818 EXPECT_EQ(0u, returned_to_child
.size());
820 EXPECT_EQ(4u, resource_provider_
->num_resources());
821 resource_provider_
->DestroyChild(child_id
);
822 EXPECT_EQ(0u, resource_provider_
->num_resources());
824 ASSERT_EQ(4u, returned_to_child
.size());
825 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
826 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
827 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
828 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
829 EXPECT_FALSE(returned_to_child
[0].lost
);
830 EXPECT_FALSE(returned_to_child
[1].lost
);
831 EXPECT_FALSE(returned_to_child
[2].lost
);
832 EXPECT_FALSE(returned_to_child
[3].lost
);
835 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
836 if (GetParam() != ResourceProvider::GLTexture
)
838 gfx::Size
size(1, 1);
839 ResourceFormat format
= RGBA_8888
;
841 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
842 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
843 uint8_t data1
[4] = {1, 2, 3, 4};
844 gfx::Rect
rect(size
);
845 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
847 ReturnedResourceArray returned_to_child
;
849 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
851 // Transfer some resources to the parent.
852 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
853 resource_ids_to_transfer
.push_back(id1
);
854 TransferableResourceArray list
;
855 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
857 ASSERT_EQ(1u, list
.size());
858 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
860 resource_provider_
->ReceiveFromChild(child_id
, list
);
862 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
863 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
866 resource_provider_
->DeclareUsedResourcesFromChild(
867 child_id
, ResourceProvider::ResourceIdArray());
868 EXPECT_EQ(0u, returned_to_child
.size());
871 EXPECT_EQ(1u, returned_to_child
.size());
872 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
875 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
876 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
878 child_resource_provider_
->DeleteResource(id1
);
879 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
880 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
883 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
884 resource_provider_
->DestroyChild(child_id
);
887 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
888 // Overlays only supported on the GL path.
889 if (GetParam() != ResourceProvider::GLTexture
)
892 uint32 sync_point
= 0;
893 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
894 mailbox
.set_allow_overlay(true);
895 scoped_ptr
<SingleReleaseCallback
> release_callback
=
896 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
));
897 ResourceProvider::ResourceId id1
=
898 child_resource_provider_
->CreateResourceFromTextureMailbox(
899 mailbox
, release_callback
.Pass());
901 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
902 mailbox2
.set_allow_overlay(false);
903 scoped_ptr
<SingleReleaseCallback
> release_callback2
=
904 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
));
905 ResourceProvider::ResourceId id2
=
906 child_resource_provider_
->CreateResourceFromTextureMailbox(
907 mailbox2
, release_callback2
.Pass());
909 ReturnedResourceArray returned_to_child
;
911 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
913 // Transfer some resources to the parent.
914 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
915 resource_ids_to_transfer
.push_back(id1
);
916 resource_ids_to_transfer
.push_back(id2
);
917 TransferableResourceArray list
;
918 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
920 ASSERT_EQ(2u, list
.size());
921 resource_provider_
->ReceiveFromChild(child_id
, list
);
922 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
923 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
925 resource_provider_
->DeclareUsedResourcesFromChild(
926 child_id
, ResourceProvider::ResourceIdArray());
928 EXPECT_EQ(2u, returned_to_child
.size());
929 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
931 child_resource_provider_
->DeleteResource(id1
);
932 child_resource_provider_
->DeleteResource(id2
);
933 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
935 resource_provider_
->DestroyChild(child_id
);
938 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
939 if (GetParam() != ResourceProvider::Bitmap
)
942 gfx::Size
size(1, 1);
943 ResourceFormat format
= RGBA_8888
;
944 size_t pixel_size
= TextureSizeBytes(size
, format
);
945 ASSERT_EQ(4U, pixel_size
);
947 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
948 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
949 uint8_t data1
[4] = { 1, 2, 3, 4 };
950 gfx::Rect
rect(size
);
951 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
953 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
954 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
955 uint8_t data2
[4] = { 5, 5, 5, 5 };
956 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
958 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
959 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
960 uint8_t data3
[4] = { 6, 7, 8, 9 };
961 SkImageInfo info
= SkImageInfo::MakeN32Premul(size
.width(), size
.height());
962 SkCanvas
* raster_canvas
= child_resource_provider_
->MapImageRasterBuffer(id3
);
963 raster_canvas
->writePixels(info
, data3
, info
.minRowBytes(), 0, 0);
964 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
966 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
967 shared_memory
->CreateAndMapAnonymous(1);
968 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
969 ResourceProvider::ResourceId id4
=
970 child_resource_provider_
->CreateResourceFromTextureMailbox(
971 TextureMailbox(shared_memory_ptr
, gfx::Size(1, 1)),
972 SingleReleaseCallback::Create(base::Bind(
973 &SharedMemoryReleaseCallback
, base::Passed(&shared_memory
))));
975 ReturnedResourceArray returned_to_child
;
977 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
979 // Transfer some resources to the parent.
980 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
981 resource_ids_to_transfer
.push_back(id1
);
982 resource_ids_to_transfer
.push_back(id2
);
983 resource_ids_to_transfer
.push_back(id3
);
984 resource_ids_to_transfer
.push_back(id4
);
985 TransferableResourceArray list
;
986 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
988 ASSERT_EQ(4u, list
.size());
989 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
990 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
991 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
992 EXPECT_EQ(0u, list
[3].mailbox_holder
.sync_point
);
993 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
994 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
995 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
996 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
997 resource_provider_
->ReceiveFromChild(child_id
, list
);
998 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
999 resource_ids_to_transfer
);
1002 EXPECT_EQ(4u, resource_provider_
->num_resources());
1003 ResourceProvider::ResourceIdMap resource_map
=
1004 resource_provider_
->GetChildToParentMap(child_id
);
1005 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1006 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1007 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1008 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
1009 EXPECT_NE(0u, mapped_id1
);
1010 EXPECT_NE(0u, mapped_id2
);
1011 EXPECT_NE(0u, mapped_id3
);
1012 EXPECT_NE(0u, mapped_id4
);
1013 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1014 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1015 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1016 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
1018 uint8_t result
[4] = { 0 };
1020 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1021 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1024 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1025 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1028 resource_provider_
.get(), context(), mapped_id3
, size
, format
, result
);
1029 EXPECT_EQ(0, memcmp(data3
, result
, pixel_size
));
1032 // Check that transfering again the same resource from the child to the
1034 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1035 resource_ids_to_transfer
.push_back(id1
);
1036 resource_ids_to_transfer
.push_back(id2
);
1037 resource_ids_to_transfer
.push_back(id3
);
1038 TransferableResourceArray list
;
1039 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1041 EXPECT_EQ(3u, list
.size());
1042 EXPECT_EQ(id1
, list
[0].id
);
1043 EXPECT_EQ(id2
, list
[1].id
);
1044 EXPECT_EQ(id3
, list
[2].id
);
1045 ReturnedResourceArray returned
;
1046 TransferableResource::ReturnResources(list
, &returned
);
1047 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1048 // ids were exported twice, we returned them only once, they should still
1050 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1051 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1052 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1055 EXPECT_EQ(0u, returned_to_child
.size());
1057 // Transfer resources back from the parent to the child. Set no resources as
1059 ResourceProvider::ResourceIdArray no_resources
;
1060 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1062 ASSERT_EQ(4u, returned_to_child
.size());
1063 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1064 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1065 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1066 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1067 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1068 expected_ids
.insert(id1
);
1069 expected_ids
.insert(id2
);
1070 expected_ids
.insert(id3
);
1071 expected_ids
.insert(id4
);
1072 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1073 for (unsigned i
= 0; i
< 4; i
++)
1074 returned_ids
.insert(returned_to_child
[i
].id
);
1075 EXPECT_EQ(expected_ids
, returned_ids
);
1076 EXPECT_FALSE(returned_to_child
[0].lost
);
1077 EXPECT_FALSE(returned_to_child
[1].lost
);
1078 EXPECT_FALSE(returned_to_child
[2].lost
);
1079 EXPECT_FALSE(returned_to_child
[3].lost
);
1080 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1081 returned_to_child
.clear();
1083 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1084 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1085 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1086 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
1089 ResourceProvider::ScopedReadLockSoftware
lock(
1090 child_resource_provider_
.get(), id1
);
1091 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1092 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1093 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1094 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1097 ResourceProvider::ScopedReadLockSoftware
lock(
1098 child_resource_provider_
.get(), id2
);
1099 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1100 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1101 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1102 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1105 ResourceProvider::ScopedReadLockSoftware
lock(
1106 child_resource_provider_
.get(), id3
);
1107 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1108 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1109 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1110 EXPECT_EQ(0, memcmp(data3
, sk_bitmap
->getPixels(), pixel_size
));
1113 // Transfer resources to the parent again.
1114 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1115 resource_ids_to_transfer
.push_back(id1
);
1116 resource_ids_to_transfer
.push_back(id2
);
1117 resource_ids_to_transfer
.push_back(id3
);
1118 resource_ids_to_transfer
.push_back(id4
);
1119 TransferableResourceArray list
;
1120 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1122 ASSERT_EQ(4u, list
.size());
1123 EXPECT_EQ(id1
, list
[0].id
);
1124 EXPECT_EQ(id2
, list
[1].id
);
1125 EXPECT_EQ(id3
, list
[2].id
);
1126 EXPECT_EQ(id4
, list
[3].id
);
1127 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1128 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1129 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1130 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
1131 resource_provider_
->ReceiveFromChild(child_id
, list
);
1132 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1133 resource_ids_to_transfer
);
1136 EXPECT_EQ(0u, returned_to_child
.size());
1138 EXPECT_EQ(4u, resource_provider_
->num_resources());
1139 resource_provider_
->DestroyChild(child_id
);
1140 EXPECT_EQ(0u, resource_provider_
->num_resources());
1142 ASSERT_EQ(4u, returned_to_child
.size());
1143 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1144 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1145 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1146 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1147 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1148 expected_ids
.insert(id1
);
1149 expected_ids
.insert(id2
);
1150 expected_ids
.insert(id3
);
1151 expected_ids
.insert(id4
);
1152 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1153 for (unsigned i
= 0; i
< 4; i
++)
1154 returned_ids
.insert(returned_to_child
[i
].id
);
1155 EXPECT_EQ(expected_ids
, returned_ids
);
1156 EXPECT_FALSE(returned_to_child
[0].lost
);
1157 EXPECT_FALSE(returned_to_child
[1].lost
);
1158 EXPECT_FALSE(returned_to_child
[2].lost
);
1159 EXPECT_FALSE(returned_to_child
[3].lost
);
1162 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1163 if (GetParam() != ResourceProvider::Bitmap
)
1166 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1167 ResourceProviderContext::Create(shared_data_
.get()));
1169 FakeOutputSurfaceClient child_output_surface_client
;
1170 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1171 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1172 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1174 scoped_ptr
<ResourceProvider
> child_resource_provider(ResourceProvider::Create(
1175 child_output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
1178 gfx::Size
size(1, 1);
1179 ResourceFormat format
= RGBA_8888
;
1180 size_t pixel_size
= TextureSizeBytes(size
, format
);
1181 ASSERT_EQ(4U, pixel_size
);
1183 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1184 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1185 uint8_t data1
[4] = { 1, 2, 3, 4 };
1186 gfx::Rect
rect(size
);
1187 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1189 ReturnedResourceArray returned_to_child
;
1191 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1193 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1194 resource_ids_to_transfer
.push_back(id1
);
1195 TransferableResourceArray list
;
1196 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1198 ASSERT_EQ(1u, list
.size());
1199 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1200 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1201 list
[0].mailbox_holder
.texture_target
);
1202 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1203 resource_provider_
->ReceiveFromChild(child_id
, list
);
1206 EXPECT_EQ(0u, resource_provider_
->num_resources());
1207 ASSERT_EQ(1u, returned_to_child
.size());
1208 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1209 ResourceProvider::ResourceIdMap resource_map
=
1210 resource_provider_
->GetChildToParentMap(child_id
);
1211 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1212 EXPECT_EQ(0u, mapped_id1
);
1214 resource_provider_
->DestroyChild(child_id
);
1215 EXPECT_EQ(0u, resource_provider_
->num_resources());
1217 ASSERT_EQ(1u, returned_to_child
.size());
1218 EXPECT_FALSE(returned_to_child
[0].lost
);
1221 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1222 if (GetParam() != ResourceProvider::Bitmap
)
1225 gfx::Size
size(1, 1);
1226 ResourceFormat format
= RGBA_8888
;
1227 size_t pixel_size
= TextureSizeBytes(size
, format
);
1228 ASSERT_EQ(4U, pixel_size
);
1230 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1231 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1232 uint8_t data1
[4] = { 1, 2, 3, 4 };
1233 gfx::Rect
rect(size
);
1234 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1236 ReturnedResourceArray returned_to_child
;
1238 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1240 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1241 resource_ids_to_transfer
.push_back(id1
);
1242 TransferableResourceArray list
;
1243 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1245 ASSERT_EQ(1u, list
.size());
1247 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1248 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1249 resource_provider_
->ReceiveFromChild(child_id
, list
);
1252 EXPECT_EQ(1u, resource_provider_
->num_resources());
1253 EXPECT_EQ(0u, returned_to_child
.size());
1255 ResourceProvider::ResourceIdMap resource_map
=
1256 resource_provider_
->GetChildToParentMap(child_id
);
1257 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1258 EXPECT_NE(0u, mapped_id1
);
1260 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1262 EXPECT_FALSE(lock
.valid());
1265 resource_provider_
->DestroyChild(child_id
);
1266 EXPECT_EQ(0u, resource_provider_
->num_resources());
1268 ASSERT_EQ(1u, returned_to_child
.size());
1269 EXPECT_FALSE(returned_to_child
[0].lost
);
1272 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1273 gfx::Size
size(1, 1);
1274 ResourceFormat format
= RGBA_8888
;
1275 size_t pixel_size
= TextureSizeBytes(size
, format
);
1276 ASSERT_EQ(4U, pixel_size
);
1278 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1279 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1280 uint8_t data1
[4] = { 1, 2, 3, 4 };
1281 gfx::Rect
rect(size
);
1282 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1284 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1285 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1286 uint8_t data2
[4] = {5, 5, 5, 5};
1287 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1289 ReturnedResourceArray returned_to_child
;
1291 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1293 // Transfer some resources to the parent.
1294 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1295 resource_ids_to_transfer
.push_back(id1
);
1296 resource_ids_to_transfer
.push_back(id2
);
1297 TransferableResourceArray list
;
1298 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1300 ASSERT_EQ(2u, list
.size());
1301 if (GetParam() == ResourceProvider::GLTexture
) {
1302 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1303 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1305 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1306 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1307 resource_provider_
->ReceiveFromChild(child_id
, list
);
1308 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1309 resource_ids_to_transfer
);
1312 EXPECT_EQ(2u, resource_provider_
->num_resources());
1313 ResourceProvider::ResourceIdMap resource_map
=
1314 resource_provider_
->GetChildToParentMap(child_id
);
1315 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1316 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1317 EXPECT_NE(0u, mapped_id1
);
1318 EXPECT_NE(0u, mapped_id2
);
1319 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1320 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1323 // The parent transfers the resources to the grandparent.
1324 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1325 resource_ids_to_transfer
.push_back(mapped_id1
);
1326 resource_ids_to_transfer
.push_back(mapped_id2
);
1327 TransferableResourceArray list
;
1328 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1330 ASSERT_EQ(2u, list
.size());
1331 if (GetParam() == ResourceProvider::GLTexture
) {
1332 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1333 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1335 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1336 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1338 // Release the resource in the parent. Set no resources as being in use. The
1339 // resources are exported so that can't be transferred back yet.
1340 ResourceProvider::ResourceIdArray no_resources
;
1341 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1343 EXPECT_EQ(0u, returned_to_child
.size());
1344 EXPECT_EQ(2u, resource_provider_
->num_resources());
1346 // Return the resources from the grandparent to the parent. They should be
1347 // returned to the child then.
1348 EXPECT_EQ(2u, list
.size());
1349 EXPECT_EQ(mapped_id1
, list
[0].id
);
1350 EXPECT_EQ(mapped_id2
, list
[1].id
);
1351 ReturnedResourceArray returned
;
1352 TransferableResource::ReturnResources(list
, &returned
);
1353 resource_provider_
->ReceiveReturnsFromParent(returned
);
1355 EXPECT_EQ(0u, resource_provider_
->num_resources());
1356 ASSERT_EQ(2u, returned_to_child
.size());
1357 if (GetParam() == ResourceProvider::GLTexture
) {
1358 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1359 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1361 EXPECT_FALSE(returned_to_child
[0].lost
);
1362 EXPECT_FALSE(returned_to_child
[1].lost
);
1366 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1367 gfx::Size
size(1, 1);
1368 ResourceFormat format
= RGBA_8888
;
1369 size_t pixel_size
= TextureSizeBytes(size
, format
);
1370 ASSERT_EQ(4U, pixel_size
);
1372 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1373 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1374 uint8_t data1
[4] = {1, 2, 3, 4};
1375 gfx::Rect
rect(size
);
1376 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1378 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1379 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1380 uint8_t data2
[4] = {5, 5, 5, 5};
1381 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1383 ReturnedResourceArray returned_to_child
;
1385 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1387 // Transfer some resources to the parent.
1388 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1389 resource_ids_to_transfer
.push_back(id1
);
1390 resource_ids_to_transfer
.push_back(id2
);
1391 TransferableResourceArray list
;
1392 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1394 ASSERT_EQ(2u, list
.size());
1395 if (GetParam() == ResourceProvider::GLTexture
) {
1396 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1397 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1399 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1400 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1401 resource_provider_
->ReceiveFromChild(child_id
, list
);
1402 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1403 resource_ids_to_transfer
);
1406 EXPECT_EQ(2u, resource_provider_
->num_resources());
1407 ResourceProvider::ResourceIdMap resource_map
=
1408 resource_provider_
->GetChildToParentMap(child_id
);
1409 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1410 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1411 EXPECT_NE(0u, mapped_id1
);
1412 EXPECT_NE(0u, mapped_id2
);
1413 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1414 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1417 // The parent transfers the resources to the grandparent.
1418 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1419 resource_ids_to_transfer
.push_back(mapped_id1
);
1420 resource_ids_to_transfer
.push_back(mapped_id2
);
1421 TransferableResourceArray list
;
1422 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1424 ASSERT_EQ(2u, list
.size());
1425 if (GetParam() == ResourceProvider::GLTexture
) {
1426 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1427 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1429 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1430 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1432 // Release the resource in the parent. Set no resources as being in use. The
1433 // resources are exported so that can't be transferred back yet.
1434 ResourceProvider::ResourceIdArray no_resources
;
1435 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1437 // Destroy the child, the resources should not be returned yet.
1438 EXPECT_EQ(0u, returned_to_child
.size());
1439 EXPECT_EQ(2u, resource_provider_
->num_resources());
1441 resource_provider_
->DestroyChild(child_id
);
1443 EXPECT_EQ(2u, resource_provider_
->num_resources());
1444 ASSERT_EQ(0u, returned_to_child
.size());
1446 // Return a resource from the grandparent, it should be returned at this
1448 EXPECT_EQ(2u, list
.size());
1449 EXPECT_EQ(mapped_id1
, list
[0].id
);
1450 EXPECT_EQ(mapped_id2
, list
[1].id
);
1451 TransferableResourceArray return_list
;
1452 return_list
.push_back(list
[1]);
1454 ReturnedResourceArray returned
;
1455 TransferableResource::ReturnResources(return_list
, &returned
);
1456 resource_provider_
->ReceiveReturnsFromParent(returned
);
1458 EXPECT_EQ(1u, resource_provider_
->num_resources());
1459 ASSERT_EQ(1u, returned_to_child
.size());
1460 if (GetParam() == ResourceProvider::GLTexture
) {
1461 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1463 EXPECT_FALSE(returned_to_child
[0].lost
);
1464 returned_to_child
.clear();
1466 // Destroy the parent resource provider. The resource that's left should be
1467 // lost at this point, and returned.
1468 resource_provider_
.reset();
1469 ASSERT_EQ(1u, returned_to_child
.size());
1470 if (GetParam() == ResourceProvider::GLTexture
) {
1471 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1473 EXPECT_TRUE(returned_to_child
[0].lost
);
1477 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1478 gfx::Size
size(1, 1);
1479 ResourceFormat format
= RGBA_8888
;
1480 size_t pixel_size
= TextureSizeBytes(size
, format
);
1481 ASSERT_EQ(4U, pixel_size
);
1483 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1484 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1485 uint8_t data
[4] = { 1, 2, 3, 4 };
1486 gfx::Rect
rect(size
);
1487 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1489 ReturnedResourceArray returned_to_child
;
1491 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1493 // Transfer some resource to the parent.
1494 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1495 resource_ids_to_transfer
.push_back(id
);
1496 TransferableResourceArray list
;
1497 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1499 ASSERT_EQ(1u, list
.size());
1500 if (GetParam() == ResourceProvider::GLTexture
)
1501 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1502 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1503 resource_provider_
->ReceiveFromChild(child_id
, list
);
1504 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1505 resource_ids_to_transfer
);
1508 // Delete textures in the child, while they are transfered.
1509 child_resource_provider_
->DeleteResource(id
);
1510 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1512 EXPECT_EQ(0u, returned_to_child
.size());
1514 // Transfer resources back from the parent to the child. Set no resources as
1516 ResourceProvider::ResourceIdArray no_resources
;
1517 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1519 ASSERT_EQ(1u, returned_to_child
.size());
1520 if (GetParam() == ResourceProvider::GLTexture
)
1521 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1522 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1524 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1527 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1528 gfx::Size
size(1, 1);
1529 ResourceFormat format
= RGBA_8888
;
1530 size_t pixel_size
= TextureSizeBytes(size
, format
);
1531 ASSERT_EQ(4U, pixel_size
);
1533 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1534 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1535 uint8_t data
[4] = {1, 2, 3, 4};
1536 gfx::Rect
rect(size
);
1537 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1539 ReturnedResourceArray returned_to_child
;
1541 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1542 const ResourceProvider::ResourceIdMap
& map
=
1543 resource_provider_
->GetChildToParentMap(child_id
);
1545 // Transfer some resource to the parent.
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1547 resource_ids_to_transfer
.push_back(id
);
1548 TransferableResourceArray list
;
1549 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1551 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1552 resource_provider_
->ReceiveFromChild(child_id
, list
);
1553 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1554 resource_ids_to_transfer
);
1556 TransferableResourceArray sent_to_top_level
;
1558 // Parent transfers to top-level.
1559 ASSERT_TRUE(map
.find(id
) != map
.end());
1560 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1561 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1562 resource_ids_to_transfer
.push_back(parent_id
);
1563 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1564 &sent_to_top_level
);
1565 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1568 // Stop using resource.
1569 ResourceProvider::ResourceIdArray empty
;
1570 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1571 // Resource is not yet returned to the child, since it's in use by the
1573 EXPECT_TRUE(returned_to_child
.empty());
1576 // Send the resource to the parent again.
1577 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1578 resource_ids_to_transfer
.push_back(id
);
1579 TransferableResourceArray list
;
1580 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1582 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1583 resource_provider_
->ReceiveFromChild(child_id
, list
);
1584 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1585 resource_ids_to_transfer
);
1588 // Receive returns back from top-level.
1589 ReturnedResourceArray returned
;
1590 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1591 resource_provider_
->ReceiveReturnsFromParent(returned
);
1592 // Resource is still not yet returned to the child, since it's declared used
1594 EXPECT_TRUE(returned_to_child
.empty());
1595 ASSERT_TRUE(map
.find(id
) != map
.end());
1596 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1597 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1600 sent_to_top_level
.clear();
1601 // Parent transfers again to top-level.
1602 ASSERT_TRUE(map
.find(id
) != map
.end());
1603 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1604 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1605 resource_ids_to_transfer
.push_back(parent_id
);
1606 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1607 &sent_to_top_level
);
1608 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1611 // Receive returns back from top-level.
1612 ReturnedResourceArray returned
;
1613 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1614 resource_provider_
->ReceiveReturnsFromParent(returned
);
1615 // Resource is still not yet returned to the child, since it's still
1616 // declared used in the parent.
1617 EXPECT_TRUE(returned_to_child
.empty());
1618 ASSERT_TRUE(map
.find(id
) != map
.end());
1619 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1620 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1623 // Stop using resource.
1624 ResourceProvider::ResourceIdArray empty
;
1625 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1626 // Resource should have been returned to the child, since it's no longer in
1627 // use by the top-level.
1628 ASSERT_EQ(1u, returned_to_child
.size());
1629 EXPECT_EQ(id
, returned_to_child
[0].id
);
1630 EXPECT_EQ(2, returned_to_child
[0].count
);
1631 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1632 returned_to_child
.clear();
1633 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1637 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1639 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1640 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1641 new TextureStateTrackingContext
);
1642 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1644 FakeOutputSurfaceClient child_output_surface_client
;
1645 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1646 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1647 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1648 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1649 new TestSharedBitmapManager());
1651 scoped_ptr
<ResourceProvider
> child_resource_provider(
1652 ResourceProvider::Create(child_output_surface
.get(),
1653 shared_bitmap_manager
.get(),
1659 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1660 new TextureStateTrackingContext
);
1661 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1663 FakeOutputSurfaceClient parent_output_surface_client
;
1664 scoped_ptr
<OutputSurface
> parent_output_surface(FakeOutputSurface::Create3d(
1665 parent_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1666 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1668 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1669 ResourceProvider::Create(parent_output_surface
.get(),
1670 shared_bitmap_manager
.get(),
1676 gfx::Size
size(1, 1);
1677 ResourceFormat format
= RGBA_8888
;
1678 int child_texture_id
= 1;
1679 int parent_texture_id
= 2;
1681 size_t pixel_size
= TextureSizeBytes(size
, format
);
1682 ASSERT_EQ(4U, pixel_size
);
1684 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1685 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1687 // The new texture is created with GL_LINEAR.
1688 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1689 .Times(2); // Once to create and once to allocate.
1690 EXPECT_CALL(*child_context
,
1691 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1692 EXPECT_CALL(*child_context
,
1693 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1696 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1699 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1700 EXPECT_CALL(*child_context
,
1701 texParameteri(GL_TEXTURE_2D
,
1702 GL_TEXTURE_POOL_CHROMIUM
,
1703 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1704 child_resource_provider
->AllocateForTesting(id
);
1705 Mock::VerifyAndClearExpectations(child_context
);
1707 uint8_t data
[4] = { 1, 2, 3, 4 };
1708 gfx::Rect
rect(size
);
1710 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1711 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1712 Mock::VerifyAndClearExpectations(child_context
);
1714 // The texture is set to |child_filter| in the child.
1715 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1716 if (child_filter
!= GL_LINEAR
) {
1719 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1722 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1724 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1725 Mock::VerifyAndClearExpectations(child_context
);
1727 ReturnedResourceArray returned_to_child
;
1728 int child_id
= parent_resource_provider
->CreateChild(
1729 GetReturnCallback(&returned_to_child
));
1731 // Transfer some resource to the parent.
1732 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1733 resource_ids_to_transfer
.push_back(id
);
1734 TransferableResourceArray list
;
1736 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1737 EXPECT_CALL(*child_context
,
1738 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1739 EXPECT_CALL(*child_context
, insertSyncPoint());
1740 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1742 Mock::VerifyAndClearExpectations(child_context
);
1744 ASSERT_EQ(1u, list
.size());
1745 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1747 EXPECT_CALL(*parent_context
,
1748 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1749 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1750 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1752 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1753 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1756 Mock::VerifyAndClearExpectations(parent_context
);
1758 parent_resource_provider
->DeclareUsedResourcesFromChild(
1759 child_id
, resource_ids_to_transfer
);
1760 Mock::VerifyAndClearExpectations(parent_context
);
1762 ResourceProvider::ResourceIdMap resource_map
=
1763 parent_resource_provider
->GetChildToParentMap(child_id
);
1764 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1765 EXPECT_NE(0u, mapped_id
);
1767 // The texture is set to |parent_filter| in the parent.
1768 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1771 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1774 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1775 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1776 Mock::VerifyAndClearExpectations(parent_context
);
1778 // The texture should be reset to |child_filter| in the parent when it is
1779 // returned, since that is how it was received.
1780 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1783 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1786 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1789 EXPECT_EQ(0u, returned_to_child
.size());
1791 // Transfer resources back from the parent to the child. Set no resources
1793 ResourceProvider::ResourceIdArray no_resources
;
1794 EXPECT_CALL(*parent_context
, insertSyncPoint());
1795 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1797 Mock::VerifyAndClearExpectations(parent_context
);
1799 ASSERT_EQ(1u, returned_to_child
.size());
1800 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1803 // The child remembers the texture filter is set to |child_filter|.
1804 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1805 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1806 Mock::VerifyAndClearExpectations(child_context
);
1810 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1811 if (GetParam() != ResourceProvider::GLTexture
)
1813 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1816 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1817 if (GetParam() != ResourceProvider::GLTexture
)
1819 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1822 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1823 // Other mailbox transfers tested elsewhere.
1824 if (GetParam() != ResourceProvider::GLTexture
)
1826 unsigned texture
= context()->createTexture();
1827 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1828 uint8_t data
[4] = { 1, 2, 3, 4 };
1829 context()->texImage2D(
1830 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1831 gpu::Mailbox mailbox
;
1832 context()->genMailboxCHROMIUM(mailbox
.name
);
1833 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1834 uint32 sync_point
= context()->insertSyncPoint();
1836 // All the logic below assumes that the sync points are all positive.
1837 EXPECT_LT(0u, sync_point
);
1839 uint32 release_sync_point
= 0;
1840 bool lost_resource
= false;
1841 ReleaseCallback callback
=
1842 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
);
1843 ResourceProvider::ResourceId resource
=
1844 resource_provider_
->CreateResourceFromTextureMailbox(
1845 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1846 SingleReleaseCallback::Create(callback
));
1847 EXPECT_EQ(1u, context()->NumTextures());
1848 EXPECT_EQ(0u, release_sync_point
);
1850 // Transfer the resource, expect the sync points to be consistent.
1851 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1852 resource_ids_to_transfer
.push_back(resource
);
1853 TransferableResourceArray list
;
1854 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1855 ASSERT_EQ(1u, list
.size());
1856 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1858 memcmp(mailbox
.name
,
1859 list
[0].mailbox_holder
.mailbox
.name
,
1860 sizeof(mailbox
.name
)));
1861 EXPECT_EQ(0u, release_sync_point
);
1863 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1864 unsigned other_texture
= context()->createTexture();
1865 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1866 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1867 uint8_t test_data
[4] = { 0 };
1868 context()->GetPixels(
1869 gfx::Size(1, 1), RGBA_8888
, test_data
);
1870 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1871 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1872 context()->deleteTexture(other_texture
);
1873 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1874 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1876 // Receive the resource, then delete it, expect the sync points to be
1878 ReturnedResourceArray returned
;
1879 TransferableResource::ReturnResources(list
, &returned
);
1880 resource_provider_
->ReceiveReturnsFromParent(returned
);
1881 EXPECT_EQ(1u, context()->NumTextures());
1882 EXPECT_EQ(0u, release_sync_point
);
1884 resource_provider_
->DeleteResource(resource
);
1885 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1886 EXPECT_FALSE(lost_resource
);
1889 // We're going to do the same thing as above, but testing the case where we
1890 // delete the resource before we receive it back.
1891 sync_point
= release_sync_point
;
1892 EXPECT_LT(0u, sync_point
);
1893 release_sync_point
= 0;
1894 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1895 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1896 SingleReleaseCallback::Create(callback
));
1897 EXPECT_EQ(1u, context()->NumTextures());
1898 EXPECT_EQ(0u, release_sync_point
);
1900 // Transfer the resource, expect the sync points to be consistent.
1901 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1902 resource_ids_to_transfer
.push_back(resource
);
1903 TransferableResourceArray list
;
1904 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1905 ASSERT_EQ(1u, list
.size());
1906 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1908 memcmp(mailbox
.name
,
1909 list
[0].mailbox_holder
.mailbox
.name
,
1910 sizeof(mailbox
.name
)));
1911 EXPECT_EQ(0u, release_sync_point
);
1913 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1914 unsigned other_texture
= context()->createTexture();
1915 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1916 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1917 uint8_t test_data
[4] = { 0 };
1918 context()->GetPixels(
1919 gfx::Size(1, 1), RGBA_8888
, test_data
);
1920 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1921 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1922 context()->deleteTexture(other_texture
);
1923 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1924 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1926 // Delete the resource, which shouldn't do anything.
1927 resource_provider_
->DeleteResource(resource
);
1928 EXPECT_EQ(1u, context()->NumTextures());
1929 EXPECT_EQ(0u, release_sync_point
);
1931 // Then receive the resource which should release the mailbox, expect the
1932 // sync points to be consistent.
1933 ReturnedResourceArray returned
;
1934 TransferableResource::ReturnResources(list
, &returned
);
1935 resource_provider_
->ReceiveReturnsFromParent(returned
);
1936 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1937 EXPECT_FALSE(lost_resource
);
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_
.reset();
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_
.reset();
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 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2260 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
));
2261 resource_provider_
->CreateResourceFromTextureMailbox(
2262 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2264 EXPECT_EQ(0u, release_sync_point
);
2265 EXPECT_FALSE(lost_resource
);
2267 resource_provider_
->DidLoseOutputSurface();
2268 resource_provider_
.reset();
2270 EXPECT_LE(sync_point
, release_sync_point
);
2271 EXPECT_TRUE(lost_resource
);
2274 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2275 // Sampling is only supported for GL textures.
2276 if (GetParam() != ResourceProvider::GLTexture
)
2279 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2280 new TextureStateTrackingContext
);
2281 TextureStateTrackingContext
* context
= context_owned
.get();
2283 FakeOutputSurfaceClient output_surface_client
;
2284 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2285 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2286 CHECK(output_surface
->BindToClient(&output_surface_client
));
2288 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2289 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2291 gfx::Size
size(1, 1);
2292 ResourceFormat format
= RGBA_8888
;
2295 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2296 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2298 // Check that the texture gets created with the right sampler settings.
2299 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2300 .Times(2); // Once to create and once to allocate.
2301 EXPECT_CALL(*context
,
2302 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2303 EXPECT_CALL(*context
,
2304 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2307 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2310 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2311 EXPECT_CALL(*context
,
2312 texParameteri(GL_TEXTURE_2D
,
2313 GL_TEXTURE_POOL_CHROMIUM
,
2314 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2316 resource_provider
->AllocateForTesting(id
);
2317 Mock::VerifyAndClearExpectations(context
);
2319 // Creating a sampler with the default filter should not change any texture
2322 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2323 ResourceProvider::ScopedSamplerGL
sampler(
2324 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2325 Mock::VerifyAndClearExpectations(context
);
2328 // Using a different filter should be reflected in the texture parameters.
2330 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2333 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2336 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2337 ResourceProvider::ScopedSamplerGL
sampler(
2338 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2339 Mock::VerifyAndClearExpectations(context
);
2342 // Test resetting to the default filter.
2344 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2345 EXPECT_CALL(*context
,
2346 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2347 EXPECT_CALL(*context
,
2348 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2349 ResourceProvider::ScopedSamplerGL
sampler(
2350 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2351 Mock::VerifyAndClearExpectations(context
);
2355 TEST_P(ResourceProviderTest
, ManagedResource
) {
2356 // Sampling is only supported for GL textures.
2357 if (GetParam() != ResourceProvider::GLTexture
)
2360 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2361 new TextureStateTrackingContext
);
2362 TextureStateTrackingContext
* context
= context_owned
.get();
2364 FakeOutputSurfaceClient output_surface_client
;
2365 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2366 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2367 CHECK(output_surface
->BindToClient(&output_surface_client
));
2369 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2370 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2372 gfx::Size
size(1, 1);
2373 ResourceFormat format
= RGBA_8888
;
2376 // Check that the texture gets created with the right sampler settings.
2377 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2381 ResourceProvider::TextureHintImmutable
,
2383 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2384 EXPECT_CALL(*context
,
2385 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2386 EXPECT_CALL(*context
,
2387 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2390 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2393 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2394 EXPECT_CALL(*context
,
2395 texParameteri(GL_TEXTURE_2D
,
2396 GL_TEXTURE_POOL_CHROMIUM
,
2397 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2398 resource_provider
->CreateForTesting(id
);
2401 Mock::VerifyAndClearExpectations(context
);
2404 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2405 // Sampling is only supported for GL textures.
2406 if (GetParam() != ResourceProvider::GLTexture
)
2409 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2410 new TextureStateTrackingContext
);
2411 TextureStateTrackingContext
* context
= context_owned
.get();
2413 FakeOutputSurfaceClient output_surface_client
;
2414 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2415 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2416 CHECK(output_surface
->BindToClient(&output_surface_client
));
2418 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2419 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2421 gfx::Size
size(1, 1);
2422 ResourceFormat format
= RGBA_8888
;
2423 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2425 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2426 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2427 // Check that the texture gets created with the right sampler settings.
2428 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2433 ResourceProvider::TextureHintImmutable
,
2435 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2436 EXPECT_CALL(*context
,
2437 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2438 EXPECT_CALL(*context
,
2439 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2440 EXPECT_CALL(*context
,
2441 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2442 EXPECT_CALL(*context
,
2443 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2444 EXPECT_CALL(*context
,
2445 texParameteri(GL_TEXTURE_2D
,
2446 GL_TEXTURE_POOL_CHROMIUM
,
2447 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2448 resource_provider
->CreateForTesting(id
);
2451 Mock::VerifyAndClearExpectations(context
);
2455 TEST_P(ResourceProviderTest
, TextureHint
) {
2456 // Sampling is only supported for GL textures.
2457 if (GetParam() != ResourceProvider::GLTexture
)
2460 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2461 new TextureStateTrackingContext
);
2462 TextureStateTrackingContext
* context
= context_owned
.get();
2463 context
->set_support_texture_storage(true);
2464 context
->set_support_texture_usage(true);
2466 FakeOutputSurfaceClient output_surface_client
;
2467 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2468 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2469 CHECK(output_surface
->BindToClient(&output_surface_client
));
2471 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2472 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2474 gfx::Size
size(1, 1);
2475 ResourceFormat format
= RGBA_8888
;
2476 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2478 const ResourceProvider::TextureHint hints
[4] = {
2479 ResourceProvider::TextureHintDefault
,
2480 ResourceProvider::TextureHintImmutable
,
2481 ResourceProvider::TextureHintFramebuffer
,
2482 ResourceProvider::TextureHintImmutableFramebuffer
,
2484 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2485 // Check that the texture gets created with the right sampler settings.
2486 ResourceProvider::ResourceId id
=
2487 resource_provider
->CreateGLTexture(size
,
2491 hints
[texture_id
- 1],
2493 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2494 EXPECT_CALL(*context
,
2495 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2496 EXPECT_CALL(*context
,
2497 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2500 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2503 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2504 EXPECT_CALL(*context
,
2505 texParameteri(GL_TEXTURE_2D
,
2506 GL_TEXTURE_POOL_CHROMIUM
,
2507 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2508 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2509 bool is_framebuffer_hint
=
2510 hints
[texture_id
- 1] & ResourceProvider::TextureHintFramebuffer
;
2511 EXPECT_CALL(*context
,
2512 texParameteri(GL_TEXTURE_2D
,
2513 GL_TEXTURE_USAGE_ANGLE
,
2514 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2515 .Times(is_framebuffer_hint
? 1 : 0);
2516 resource_provider
->CreateForTesting(id
);
2519 Mock::VerifyAndClearExpectations(context
);
2523 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2524 if (GetParam() != ResourceProvider::Bitmap
)
2527 gfx::Size
size(64, 64);
2528 const uint32_t kBadBeef
= 0xbadbeef;
2529 scoped_ptr
<base::SharedMemory
> shared_memory(
2530 CreateAndFillSharedMemory(size
, kBadBeef
));
2532 FakeOutputSurfaceClient output_surface_client
;
2533 scoped_ptr
<OutputSurface
> output_surface(
2534 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2535 new SoftwareOutputDevice
)));
2536 CHECK(output_surface
->BindToClient(&output_surface_client
));
2538 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2539 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2541 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2542 base::Bind(&EmptyReleaseCallback
));
2543 TextureMailbox
mailbox(shared_memory
.get(), size
);
2545 ResourceProvider::ResourceId id
=
2546 resource_provider
->CreateResourceFromTextureMailbox(
2547 mailbox
, callback
.Pass());
2551 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2552 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2553 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2554 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2555 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2559 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D
) {
2560 // Mailboxing is only supported for GL textures.
2561 if (GetParam() != ResourceProvider::GLTexture
)
2564 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2565 new TextureStateTrackingContext
);
2566 TextureStateTrackingContext
* context
= context_owned
.get();
2568 FakeOutputSurfaceClient output_surface_client
;
2569 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2570 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2571 CHECK(output_surface
->BindToClient(&output_surface_client
));
2573 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2574 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2576 unsigned texture_id
= 1;
2577 uint32 sync_point
= 30;
2578 unsigned target
= GL_TEXTURE_2D
;
2580 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2581 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2582 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2583 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2584 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2586 gpu::Mailbox gpu_mailbox
;
2587 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2588 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2589 base::Bind(&EmptyReleaseCallback
));
2591 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2593 ResourceProvider::ResourceId id
=
2594 resource_provider
->CreateResourceFromTextureMailbox(
2595 mailbox
, callback
.Pass());
2598 Mock::VerifyAndClearExpectations(context
);
2601 // Mailbox sync point WaitSyncPoint before using the texture.
2602 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2603 resource_provider
->WaitSyncPointIfNeeded(id
);
2604 Mock::VerifyAndClearExpectations(context
);
2606 // Using the texture does a consume of the mailbox.
2607 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2608 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2610 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2611 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2613 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2614 Mock::VerifyAndClearExpectations(context
);
2616 // When done with it, a sync point should be inserted, but no produce is
2618 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2619 EXPECT_CALL(*context
, insertSyncPoint());
2620 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2622 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2623 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2627 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2628 // Mailboxing is only supported for GL textures.
2629 if (GetParam() != ResourceProvider::GLTexture
)
2632 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2633 new TextureStateTrackingContext
);
2634 TextureStateTrackingContext
* context
= context_owned
.get();
2636 FakeOutputSurfaceClient output_surface_client
;
2637 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2638 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2639 CHECK(output_surface
->BindToClient(&output_surface_client
));
2641 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2642 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2644 unsigned texture_id
= 1;
2645 uint32 sync_point
= 30;
2646 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2648 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2649 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2650 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2651 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2652 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2654 gpu::Mailbox gpu_mailbox
;
2655 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2656 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2657 base::Bind(&EmptyReleaseCallback
));
2659 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2661 ResourceProvider::ResourceId id
=
2662 resource_provider
->CreateResourceFromTextureMailbox(
2663 mailbox
, callback
.Pass());
2666 Mock::VerifyAndClearExpectations(context
);
2669 // Mailbox sync point WaitSyncPoint before using the texture.
2670 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2671 resource_provider
->WaitSyncPointIfNeeded(id
);
2672 Mock::VerifyAndClearExpectations(context
);
2674 // Using the texture does a consume of the mailbox.
2675 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2676 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2678 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2679 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2681 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2682 Mock::VerifyAndClearExpectations(context
);
2684 // When done with it, a sync point should be inserted, but no produce is
2686 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2687 EXPECT_CALL(*context
, insertSyncPoint());
2688 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2690 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2691 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2695 TEST_P(ResourceProviderTest
,
2696 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2697 // Mailboxing is only supported for GL textures.
2698 if (GetParam() != ResourceProvider::GLTexture
)
2701 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2702 new TextureStateTrackingContext
);
2703 TextureStateTrackingContext
* context
= context_owned
.get();
2705 FakeOutputSurfaceClient output_surface_client
;
2706 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2707 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2708 CHECK(output_surface
->BindToClient(&output_surface_client
));
2710 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2711 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2713 uint32 sync_point
= 30;
2714 unsigned target
= GL_TEXTURE_2D
;
2716 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2717 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2718 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2719 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2720 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2722 gpu::Mailbox gpu_mailbox
;
2723 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2724 scoped_ptr
<SingleReleaseCallback
> callback
=
2725 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
));
2727 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2729 ResourceProvider::ResourceId id
=
2730 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2734 Mock::VerifyAndClearExpectations(context
);
2737 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2738 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2739 resource_provider
->WaitSyncPointIfNeeded(id
);
2740 Mock::VerifyAndClearExpectations(context
);
2742 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2743 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2744 resource_provider
->WaitSyncPointIfNeeded(id
);
2745 Mock::VerifyAndClearExpectations(context
);
2749 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2750 // Mailboxing is only supported for GL textures.
2751 if (GetParam() != ResourceProvider::GLTexture
)
2754 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2755 new TextureStateTrackingContext
);
2756 TextureStateTrackingContext
* context
= context_owned
.get();
2758 FakeOutputSurfaceClient output_surface_client
;
2759 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2760 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2761 CHECK(output_surface
->BindToClient(&output_surface_client
));
2763 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2764 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2766 uint32 sync_point
= 0;
2767 unsigned target
= GL_TEXTURE_2D
;
2769 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2770 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2771 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2772 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2773 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2775 gpu::Mailbox gpu_mailbox
;
2776 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2777 scoped_ptr
<SingleReleaseCallback
> callback
=
2778 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
));
2780 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2782 ResourceProvider::ResourceId id
=
2783 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2787 Mock::VerifyAndClearExpectations(context
);
2790 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2791 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2792 resource_provider
->WaitSyncPointIfNeeded(id
);
2793 Mock::VerifyAndClearExpectations(context
);
2797 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2799 MOCK_METHOD0(NextTextureId
, GLuint());
2800 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2801 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2802 MOCK_METHOD5(texStorage2DEXT
,
2805 GLuint internalformat
,
2808 MOCK_METHOD9(texImage2D
,
2811 GLenum internalformat
,
2817 const void* pixels
));
2818 MOCK_METHOD9(texSubImage2D
,
2827 const void* pixels
));
2828 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2831 GLenum internalformat
,
2837 const void* pixels
));
2838 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2847 const void* pixels
));
2848 MOCK_METHOD8(compressedTexImage2D
,
2851 GLenum internalformat
,
2857 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
2858 MOCK_METHOD4(createImageCHROMIUM
, GLuint(GLsizei
, GLsizei
, GLenum
, GLenum
));
2859 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
2860 MOCK_METHOD1(mapImageCHROMIUM
, void*(GLuint
));
2861 MOCK_METHOD3(getImageParameterivCHROMIUM
, void(GLuint
, GLenum
, GLint
*));
2862 MOCK_METHOD1(unmapImageCHROMIUM
, void(GLuint
));
2863 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2864 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2866 // We're mocking bindTexture, so we override
2867 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2868 // currently bound texture.
2869 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
2872 TEST_P(ResourceProviderTest
, TextureAllocation
) {
2873 // Only for GL textures.
2874 if (GetParam() != ResourceProvider::GLTexture
)
2876 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2877 new StrictMock
<AllocationTrackingContext3D
>);
2878 AllocationTrackingContext3D
* context
= context_owned
.get();
2880 FakeOutputSurfaceClient output_surface_client
;
2881 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2882 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2883 CHECK(output_surface
->BindToClient(&output_surface_client
));
2885 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2886 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2888 gfx::Size
size(2, 2);
2889 gfx::Vector2d
offset(0, 0);
2890 gfx::Rect
rect(0, 0, 2, 2);
2891 ResourceFormat format
= RGBA_8888
;
2892 ResourceProvider::ResourceId id
= 0;
2893 uint8_t pixels
[16] = { 0 };
2894 int texture_id
= 123;
2896 // Lazy allocation. Don't allocate when creating the resource.
2897 id
= resource_provider
->CreateResource(
2898 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2900 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2901 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2902 resource_provider
->CreateForTesting(id
);
2904 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2905 resource_provider
->DeleteResource(id
);
2907 Mock::VerifyAndClearExpectations(context
);
2909 // Do allocate when we set the pixels.
2910 id
= resource_provider
->CreateResource(
2911 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2913 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2914 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
2915 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
2916 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
2917 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
2919 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2920 resource_provider
->DeleteResource(id
);
2922 Mock::VerifyAndClearExpectations(context
);
2924 // Same for async version.
2925 id
= resource_provider
->CreateResource(
2926 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2927 resource_provider
->AcquirePixelRasterBuffer(id
);
2929 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2930 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2931 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2933 resource_provider
->BeginSetPixels(id
);
2934 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
2936 resource_provider
->ReleasePixelRasterBuffer(id
);
2938 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2939 resource_provider
->DeleteResource(id
);
2941 Mock::VerifyAndClearExpectations(context
);
2944 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
2945 // Only for GL textures.
2946 if (GetParam() != ResourceProvider::GLTexture
)
2948 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2949 new StrictMock
<AllocationTrackingContext3D
>);
2950 AllocationTrackingContext3D
* context
= context_owned
.get();
2951 context
->set_support_texture_storage(true);
2952 context
->set_support_texture_usage(true);
2954 FakeOutputSurfaceClient output_surface_client
;
2955 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2956 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2957 CHECK(output_surface
->BindToClient(&output_surface_client
));
2959 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2960 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2962 gfx::Size
size(2, 2);
2963 ResourceFormat format
= RGBA_8888
;
2965 const ResourceProvider::TextureHint hints
[4] = {
2966 ResourceProvider::TextureHintDefault
,
2967 ResourceProvider::TextureHintImmutable
,
2968 ResourceProvider::TextureHintFramebuffer
,
2969 ResourceProvider::TextureHintImmutableFramebuffer
,
2971 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2972 // Lazy allocation. Don't allocate when creating the resource.
2973 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2974 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], format
);
2976 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2977 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2978 bool is_immutable_hint
=
2979 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
2980 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
2981 .Times(is_immutable_hint
? 1 : 0);
2982 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2983 .Times(is_immutable_hint
? 0 : 1);
2984 resource_provider
->AllocateForTesting(id
);
2986 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2987 resource_provider
->DeleteResource(id
);
2989 Mock::VerifyAndClearExpectations(context
);
2993 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
2994 if (GetParam() != ResourceProvider::GLTexture
)
2996 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2997 new StrictMock
<AllocationTrackingContext3D
>);
2998 AllocationTrackingContext3D
* context
= context_owned
.get();
3000 FakeOutputSurfaceClient output_surface_client
;
3001 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3002 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3003 CHECK(output_surface
->BindToClient(&output_surface_client
));
3005 gfx::Size
size(2, 2);
3006 ResourceFormat format
= RGBA_8888
;
3007 ResourceProvider::ResourceId id
= 0;
3008 int texture_id
= 123;
3010 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3011 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3013 id
= resource_provider
->CreateResource(
3014 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3015 resource_provider
->AcquirePixelRasterBuffer(id
);
3017 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3018 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3019 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3021 resource_provider
->BeginSetPixels(id
);
3023 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3025 resource_provider
->ReleasePixelRasterBuffer(id
);
3027 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3028 resource_provider
->DeleteResource(id
);
3030 Mock::VerifyAndClearExpectations(context
);
3033 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3034 // Only for GL textures.
3035 if (GetParam() != ResourceProvider::GLTexture
)
3037 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3038 new StrictMock
<AllocationTrackingContext3D
>);
3039 AllocationTrackingContext3D
* context
= context_owned
.get();
3041 FakeOutputSurfaceClient output_surface_client
;
3042 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3043 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3044 CHECK(output_surface
->BindToClient(&output_surface_client
));
3046 gfx::Size
size(2, 2);
3047 ResourceFormat format
= RGBA_8888
;
3048 ResourceProvider::ResourceId id
= 0;
3049 int texture_id
= 123;
3051 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3052 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3054 id
= resource_provider
->CreateResource(
3055 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3056 resource_provider
->AcquirePixelRasterBuffer(id
);
3058 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3059 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3060 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3062 resource_provider
->BeginSetPixels(id
);
3064 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3065 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3066 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3067 resource_provider
->ForceSetPixelsToComplete(id
);
3069 resource_provider
->ReleasePixelRasterBuffer(id
);
3071 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3072 resource_provider
->DeleteResource(id
);
3074 Mock::VerifyAndClearExpectations(context
);
3077 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3078 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3079 new NiceMock
<AllocationTrackingContext3D
>);
3080 AllocationTrackingContext3D
* context
= context_owned
.get();
3082 FakeOutputSurfaceClient output_surface_client
;
3083 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3084 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3085 CHECK(output_surface
->BindToClient(&output_surface_client
));
3087 gfx::Size
size(2, 2);
3088 ResourceFormat format
= RGBA_8888
;
3089 ResourceProvider::ResourceId id
= 0;
3090 int texture_id
= 123;
3092 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3093 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3095 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3097 id
= resource_provider
->CreateResource(
3098 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3099 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3100 GL_INNOCENT_CONTEXT_RESET_ARB
);
3102 resource_provider
->AcquirePixelRasterBuffer(id
);
3103 SkCanvas
* raster_canvas
= resource_provider
->MapPixelRasterBuffer(id
);
3104 EXPECT_TRUE(raster_canvas
== NULL
);
3105 resource_provider
->UnmapPixelRasterBuffer(id
);
3106 resource_provider
->ReleasePixelRasterBuffer(id
);
3107 Mock::VerifyAndClearExpectations(context
);
3110 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3111 // Only for GL textures.
3112 if (GetParam() != ResourceProvider::GLTexture
)
3114 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3115 new StrictMock
<AllocationTrackingContext3D
>);
3116 AllocationTrackingContext3D
* context
= context_owned
.get();
3118 FakeOutputSurfaceClient output_surface_client
;
3119 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3120 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3121 CHECK(output_surface
->BindToClient(&output_surface_client
));
3123 const int kWidth
= 2;
3124 const int kHeight
= 2;
3125 gfx::Size
size(kWidth
, kHeight
);
3126 ResourceFormat format
= RGBA_8888
;
3127 ResourceProvider::ResourceId id
= 0;
3128 const unsigned kTextureId
= 123u;
3129 const unsigned kImageId
= 234u;
3131 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3132 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3134 id
= resource_provider
->CreateResource(
3135 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3137 const int kStride
= 4;
3138 void* dummy_mapped_buffer_address
= NULL
;
3141 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
3142 .WillOnce(Return(kImageId
))
3143 .RetiresOnSaturation();
3144 EXPECT_CALL(*context
, getImageParameterivCHROMIUM(kImageId
,
3145 GL_IMAGE_ROWBYTES_CHROMIUM
,
3147 .WillOnce(SetArgPointee
<2>(kStride
))
3148 .RetiresOnSaturation();
3149 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3150 .WillOnce(Return(dummy_mapped_buffer_address
))
3151 .RetiresOnSaturation();
3152 resource_provider
->MapImageRasterBuffer(id
);
3154 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
3156 .RetiresOnSaturation();
3157 resource_provider
->UnmapImageRasterBuffer(id
);
3159 EXPECT_CALL(*context
, NextTextureId())
3160 .WillOnce(Return(kTextureId
))
3161 .RetiresOnSaturation();
3162 // Once in CreateTextureId and once in BindForSampling
3163 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3164 .RetiresOnSaturation();
3165 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3167 .RetiresOnSaturation();
3169 ResourceProvider::ScopedSamplerGL
lock_gl(
3170 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3171 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3176 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
3177 .WillOnce(SetArgPointee
<2>(kStride
))
3178 .RetiresOnSaturation();
3179 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3180 .WillOnce(Return(dummy_mapped_buffer_address
))
3181 .RetiresOnSaturation();
3182 resource_provider
->MapImageRasterBuffer(id
);
3184 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
3186 .RetiresOnSaturation();
3187 resource_provider
->UnmapImageRasterBuffer(id
);
3189 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3190 .RetiresOnSaturation();
3191 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3193 .RetiresOnSaturation();
3194 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3196 .RetiresOnSaturation();
3197 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3199 .RetiresOnSaturation();
3201 ResourceProvider::ScopedSamplerGL
lock_gl(
3202 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3203 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3206 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3208 .RetiresOnSaturation();
3211 TEST_P(ResourceProviderTest
, Image_Bitmap
) {
3212 if (GetParam() != ResourceProvider::Bitmap
)
3214 FakeOutputSurfaceClient output_surface_client
;
3215 scoped_ptr
<OutputSurface
> output_surface(
3216 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3217 new SoftwareOutputDevice
)));
3218 CHECK(output_surface
->BindToClient(&output_surface_client
));
3220 gfx::Size
size(1, 1);
3221 ResourceFormat format
= RGBA_8888
;
3222 ResourceProvider::ResourceId id
= 0;
3223 const uint32_t kBadBeef
= 0xbadbeef;
3225 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3226 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3228 id
= resource_provider
->CreateResource(
3229 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3232 bitmap
.allocN32Pixels(size
.width(), size
.height());
3233 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3234 SkCanvas
* canvas
= resource_provider
->MapImageRasterBuffer(id
);
3235 ASSERT_TRUE(!!canvas
);
3236 canvas
->writePixels(bitmap
, 0, 0);
3237 resource_provider
->UnmapImageRasterBuffer(id
);
3240 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
3241 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3242 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3243 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3244 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3247 resource_provider
->DeleteResource(id
);
3250 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3251 if (GetParam() != ResourceProvider::GLTexture
)
3253 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3254 new StrictMock
<AllocationTrackingContext3D
>);
3255 AllocationTrackingContext3D
* context
= context_owned
.get();
3256 context_owned
->set_support_sync_query(true);
3258 FakeOutputSurfaceClient output_surface_client
;
3259 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3260 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3261 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3263 const int kWidth
= 2;
3264 const int kHeight
= 2;
3265 gfx::Size
size(kWidth
, kHeight
);
3266 ResourceFormat format
= RGBA_8888
;
3267 ResourceProvider::ResourceId source_id
= 0;
3268 ResourceProvider::ResourceId dest_id
= 0;
3269 const unsigned kSourceTextureId
= 123u;
3270 const unsigned kDestTextureId
= 321u;
3271 const unsigned kImageId
= 234u;
3273 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3274 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3276 source_id
= resource_provider
->CreateResource(
3277 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3279 const int kStride
= 4;
3280 void* dummy_mapped_buffer_address
= NULL
;
3283 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
3284 .WillOnce(Return(kImageId
))
3285 .RetiresOnSaturation();
3288 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
3289 .WillOnce(SetArgPointee
<2>(kStride
))
3290 .RetiresOnSaturation();
3291 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3292 .WillOnce(Return(dummy_mapped_buffer_address
))
3293 .RetiresOnSaturation();
3294 resource_provider
->MapImageRasterBuffer(source_id
);
3295 Mock::VerifyAndClearExpectations(context
);
3297 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
3299 .RetiresOnSaturation();
3300 resource_provider
->UnmapImageRasterBuffer(source_id
);
3301 Mock::VerifyAndClearExpectations(context
);
3303 dest_id
= resource_provider
->CreateResource(
3304 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3306 EXPECT_CALL(*context
, NextTextureId())
3307 .WillOnce(Return(kDestTextureId
))
3308 .RetiresOnSaturation();
3309 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3311 .RetiresOnSaturation();
3312 EXPECT_CALL(*context
, NextTextureId())
3313 .WillOnce(Return(kSourceTextureId
))
3314 .RetiresOnSaturation();
3315 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3317 .RetiresOnSaturation();
3318 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3320 .RetiresOnSaturation();
3321 resource_provider
->CopyResource(source_id
, dest_id
);
3322 Mock::VerifyAndClearExpectations(context
);
3324 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3326 .RetiresOnSaturation();
3327 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3329 .RetiresOnSaturation();
3330 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3332 .RetiresOnSaturation();
3333 resource_provider
->DeleteResource(source_id
);
3334 resource_provider
->DeleteResource(dest_id
);
3337 TEST_P(ResourceProviderTest
, CopyResource_Bitmap
) {
3338 if (GetParam() != ResourceProvider::Bitmap
)
3340 FakeOutputSurfaceClient output_surface_client
;
3341 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::CreateSoftware(
3342 make_scoped_ptr(new SoftwareOutputDevice
)));
3343 CHECK(output_surface
->BindToClient(&output_surface_client
));
3345 gfx::Size
size(1, 1);
3346 ResourceFormat format
= RGBA_8888
;
3347 ResourceProvider::ResourceId source_id
= 0;
3348 ResourceProvider::ResourceId dest_id
= 0;
3349 const uint32_t kBadBeef
= 0xbadbeef;
3351 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3352 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3354 source_id
= resource_provider
->CreateResource(
3355 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3358 bitmap
.allocN32Pixels(size
.width(), size
.height());
3359 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3360 SkCanvas
* canvas
= resource_provider
->MapImageRasterBuffer(source_id
);
3361 ASSERT_TRUE(!!canvas
);
3362 canvas
->writePixels(bitmap
, 0, 0);
3363 resource_provider
->UnmapImageRasterBuffer(source_id
);
3365 dest_id
= resource_provider
->CreateResource(
3366 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3368 resource_provider
->CopyResource(source_id
, dest_id
);
3371 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(),
3373 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3374 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3375 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3376 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3379 resource_provider
->DeleteResource(source_id
);
3380 resource_provider
->DeleteResource(dest_id
);
3383 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3384 ResourceProvider
* resource_provider
,
3385 FakeOutputSurface
* output_surface
) {
3386 scoped_ptr
<ResourceProviderContext
> context_owned
=
3387 ResourceProviderContext::Create(shared_data
);
3388 ResourceProviderContext
* context
= context_owned
.get();
3390 scoped_refptr
<TestContextProvider
> context_provider
=
3391 TestContextProvider::Create(
3392 context_owned
.PassAs
<TestWebGraphicsContext3D
>());
3393 output_surface
->InitializeAndSetContext3d(context_provider
);
3394 resource_provider
->InitializeGL();
3396 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3399 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3400 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3401 bool delegated_rendering
= false;
3402 scoped_ptr
<FakeOutputSurface
> output_surface(
3403 FakeOutputSurface::CreateDeferredGL(
3404 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3405 delegated_rendering
));
3406 FakeOutputSurfaceClient
client(output_surface
.get());
3407 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3408 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3409 new TestSharedBitmapManager());
3410 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3411 output_surface
.get(), shared_bitmap_manager
.get(), 0, false, 1, false));
3413 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3415 InitializeGLAndCheck(shared_data
.get(),
3416 resource_provider
.get(),
3417 output_surface
.get());
3419 resource_provider
->InitializeSoftware();
3420 output_surface
->ReleaseGL();
3421 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3423 InitializeGLAndCheck(shared_data
.get(),
3424 resource_provider
.get(),
3425 output_surface
.get());
3428 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3429 if (GetParam() != ResourceProvider::GLTexture
)
3432 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3433 new AllocationTrackingContext3D
);
3434 AllocationTrackingContext3D
* context
= context_owned
.get();
3435 context_owned
->set_support_compressed_texture_etc1(true);
3437 FakeOutputSurfaceClient output_surface_client
;
3438 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3439 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3440 CHECK(output_surface
->BindToClient(&output_surface_client
));
3442 gfx::Size
size(4, 4);
3443 scoped_ptr
<ResourceProvider
> resource_provider(
3444 ResourceProvider::Create(output_surface
.get(),
3445 shared_bitmap_manager_
.get(),
3450 int texture_id
= 123;
3452 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3453 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3455 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3456 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3457 resource_provider
->AllocateForTesting(id
);
3459 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3460 resource_provider
->DeleteResource(id
);
3463 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3464 if (GetParam() != ResourceProvider::GLTexture
)
3467 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3468 new AllocationTrackingContext3D
);
3469 AllocationTrackingContext3D
* context
= context_owned
.get();
3470 context_owned
->set_support_compressed_texture_etc1(true);
3472 FakeOutputSurfaceClient output_surface_client
;
3473 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3474 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3475 CHECK(output_surface
->BindToClient(&output_surface_client
));
3477 gfx::Size
size(4, 4);
3478 scoped_ptr
<ResourceProvider
> resource_provider(
3479 ResourceProvider::Create(output_surface
.get(),
3480 shared_bitmap_manager_
.get(),
3485 int texture_id
= 123;
3488 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3489 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3491 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3492 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3493 EXPECT_CALL(*context
,
3494 compressedTexImage2D(
3495 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3496 resource_provider
->SetPixels(
3497 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3499 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3500 resource_provider
->DeleteResource(id
);
3503 INSTANTIATE_TEST_CASE_P(
3504 ResourceProviderTests
,
3505 ResourceProviderTest
,
3506 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3508 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3510 virtual GLuint
NextTextureId() OVERRIDE
{
3511 base::AutoLock
lock(namespace_
->lock
);
3512 return namespace_
->next_texture_id
++;
3514 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
3515 GLuint
PeekTextureId() {
3516 base::AutoLock
lock(namespace_
->lock
);
3517 return namespace_
->next_texture_id
;
3521 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3522 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3523 new TextureIdAllocationTrackingContext
);
3524 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3526 FakeOutputSurfaceClient output_surface_client
;
3527 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3528 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3529 CHECK(output_surface
->BindToClient(&output_surface_client
));
3530 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3531 new TestSharedBitmapManager());
3533 gfx::Size
size(1, 1);
3534 ResourceFormat format
= RGBA_8888
;
3537 size_t kTextureAllocationChunkSize
= 1;
3538 scoped_ptr
<ResourceProvider
> resource_provider(
3539 ResourceProvider::Create(output_surface
.get(),
3540 shared_bitmap_manager
.get(),
3543 kTextureAllocationChunkSize
,
3546 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3547 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3548 resource_provider
->AllocateForTesting(id
);
3549 Mock::VerifyAndClearExpectations(context
);
3551 DCHECK_EQ(2u, context
->PeekTextureId());
3552 resource_provider
->DeleteResource(id
);
3556 size_t kTextureAllocationChunkSize
= 8;
3557 scoped_ptr
<ResourceProvider
> resource_provider(
3558 ResourceProvider::Create(output_surface
.get(),
3559 shared_bitmap_manager
.get(),
3562 kTextureAllocationChunkSize
,
3565 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3566 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3567 resource_provider
->AllocateForTesting(id
);
3568 Mock::VerifyAndClearExpectations(context
);
3570 DCHECK_EQ(10u, context
->PeekTextureId());
3571 resource_provider
->DeleteResource(id
);