1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
56 BlockingTaskRunner
* main_thread_task_runner
) {
57 *release_sync_point
= sync_point
;
58 *release_lost_resource
= lost_resource
;
59 *release_main_thread_task_runner
= main_thread_task_runner
;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr
<SharedBitmap
> bitmap
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr
<SharedBitmap
> shared_bitmap
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<SharedBitmap
> CreateAndFillSharedBitmap(
83 SharedBitmapManager
* manager
,
84 const gfx::Size
& size
,
86 scoped_ptr
<SharedBitmap
> shared_bitmap
= manager
->AllocateSharedBitmap(size
);
88 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_bitmap
->pixels());
90 std::fill_n(pixels
, size
.GetArea(), value
);
91 return shared_bitmap
.Pass();
94 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
96 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
97 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
98 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
99 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
100 MOCK_METHOD2(produceTextureCHROMIUM
,
101 void(GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(consumeTextureCHROMIUM
,
103 void(GLenum target
, const GLbyte
* mailbox
));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint
NextTextureId() override
{
108 base::AutoLock
lock(namespace_
->lock
);
109 return namespace_
->next_texture_id
++;
111 void RetireTextureId(GLuint
) override
{}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData
{
118 static scoped_ptr
<ContextSharedData
> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32
InsertSyncPoint() { return next_sync_point_
++; }
124 void GenMailbox(GLbyte
* mailbox
) {
125 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
126 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
130 void ProduceTexture(const GLbyte
* mailbox_name
,
132 scoped_refptr
<TestTexture
> texture
) {
133 unsigned mailbox
= 0;
134 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
135 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
136 textures_
[mailbox
] = texture
;
137 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
138 sync_point_for_mailbox_
[mailbox
] = sync_point
;
141 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
143 unsigned mailbox
= 0;
144 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
145 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
150 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
152 return scoped_refptr
<TestTexture
>();
154 return textures_
[mailbox
];
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_
;
161 unsigned next_mailbox_
;
162 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
163 TextureMap textures_
;
164 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
167 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
169 static scoped_ptr
<ResourceProviderContext
> Create(
170 ContextSharedData
* shared_data
) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
174 GLuint
insertSyncPoint() override
{
175 uint32 sync_point
= shared_data_
->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it
=
179 pending_produce_textures_
.begin();
180 it
!= pending_produce_textures_
.end();
182 shared_data_
->ProduceTexture(
183 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
185 pending_produce_textures_
.clear();
189 void waitSyncPoint(GLuint sync_point
) override
{
190 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
195 void texStorage2DEXT(GLenum target
,
197 GLuint internalformat
,
199 GLint height
) override
{
200 CheckTextureIsBound(target
);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
202 ASSERT_EQ(1, levels
);
203 GLenum format
= GL_RGBA
;
204 switch (internalformat
) {
208 format
= GL_BGRA_EXT
;
213 AllocateTexture(gfx::Size(width
, height
), format
);
216 void texImage2D(GLenum target
,
218 GLenum internalformat
,
224 const void* pixels
) override
{
225 CheckTextureIsBound(target
);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
228 ASSERT_EQ(internalformat
, format
);
229 ASSERT_FALSE(border
);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
231 AllocateTexture(gfx::Size(width
, height
), format
);
233 SetPixels(0, 0, width
, height
, pixels
);
236 void texSubImage2D(GLenum target
,
244 const void* pixels
) override
{
245 CheckTextureIsBound(target
);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
250 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
254 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
257 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
258 return shared_data_
->GenMailbox(mailbox
);
261 void produceTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
262 CheckTextureIsBound(target
);
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= BoundTexture(target
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 void consumeTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
275 CheckTextureIsBound(target
);
276 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
277 scoped_refptr
<TestTexture
> texture
=
278 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
279 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
282 void GetPixels(const gfx::Size
& size
,
283 ResourceFormat format
,
285 CheckTextureIsBound(GL_TEXTURE_2D
);
286 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
287 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
288 ASSERT_EQ(texture
->size
, size
);
289 ASSERT_EQ(texture
->format
, format
);
290 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
294 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
295 : shared_data_(shared_data
),
296 last_waited_sync_point_(0) {}
299 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
300 CheckTextureIsBound(GL_TEXTURE_2D
);
301 ResourceFormat texture_format
= RGBA_8888
;
304 texture_format
= RGBA_8888
;
307 texture_format
= BGRA_8888
;
310 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
311 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
314 void SetPixels(int xoffset
,
318 const void* pixels
) {
319 CheckTextureIsBound(GL_TEXTURE_2D
);
320 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
321 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
322 ASSERT_TRUE(texture
->data
.get());
323 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
324 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
326 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
328 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
329 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
330 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
331 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
332 for (int i
= 0; i
< height
; ++i
) {
333 memcpy(dest
, src
, in_pitch
);
339 struct PendingProduceTexture
{
340 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
341 scoped_refptr
<TestTexture
> texture
;
343 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
344 ContextSharedData
* shared_data_
;
345 GLuint last_waited_sync_point_
;
346 PendingProduceTextureList pending_produce_textures_
;
349 void GetResourcePixels(ResourceProvider
* resource_provider
,
350 ResourceProviderContext
* context
,
351 ResourceProvider::ResourceId id
,
352 const gfx::Size
& size
,
353 ResourceFormat format
,
355 resource_provider
->WaitSyncPointIfNeeded(id
);
356 switch (resource_provider
->default_resource_type()) {
357 case ResourceProvider::GLTexture
: {
358 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
359 ASSERT_NE(0U, lock_gl
.texture_id());
360 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
361 context
->GetPixels(size
, format
, pixels
);
364 case ResourceProvider::Bitmap
: {
365 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
368 lock_software
.sk_bitmap()->getPixels(),
369 lock_software
.sk_bitmap()->getSize());
372 case ResourceProvider::InvalidType
:
378 class ResourceProviderTest
379 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
381 ResourceProviderTest()
382 : shared_data_(ContextSharedData::Create()),
384 child_context_(NULL
),
385 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
386 switch (GetParam()) {
387 case ResourceProvider::GLTexture
: {
388 scoped_ptr
<ResourceProviderContext
> context3d(
389 ResourceProviderContext::Create(shared_data_
.get()));
390 context3d_
= context3d
.get();
392 scoped_refptr
<TestContextProvider
> context_provider
=
393 TestContextProvider::Create(context3d
.Pass());
395 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
397 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
398 ResourceProviderContext::Create(shared_data_
.get());
399 child_context_
= child_context_owned
.get();
400 child_output_surface_
=
401 FakeOutputSurface::Create3d(child_context_owned
.Pass());
404 case ResourceProvider::Bitmap
:
405 output_surface_
= FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice
));
407 child_output_surface_
= FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice
));
410 case ResourceProvider::InvalidType
:
414 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
415 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
417 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
418 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
421 ResourceProvider::Create(output_surface_
.get(),
422 shared_bitmap_manager_
.get(),
423 gpu_memory_buffer_manager_
.get(),
424 main_thread_task_runner_
.get(),
428 child_resource_provider_
=
429 ResourceProvider::Create(child_output_surface_
.get(),
430 shared_bitmap_manager_
.get(),
431 gpu_memory_buffer_manager_
.get(),
432 main_thread_task_runner_
.get(),
438 static void CollectResources(ReturnedResourceArray
* array
,
439 const ReturnedResourceArray
& returned
,
440 BlockingTaskRunner
* main_thread_task_runner
) {
441 array
->insert(array
->end(), returned
.begin(), returned
.end());
444 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
445 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
448 static void SetResourceFilter(ResourceProvider
* resource_provider
,
449 ResourceProvider::ResourceId id
,
451 ResourceProvider::ScopedSamplerGL
sampler(
452 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
455 ResourceProviderContext
* context() { return context3d_
; }
457 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
459 bool* release_called
,
460 uint32
* sync_point
) {
461 if (GetParam() == ResourceProvider::GLTexture
) {
462 unsigned texture
= child_context_
->createTexture();
463 gpu::Mailbox gpu_mailbox
;
464 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
465 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
466 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
467 *sync_point
= child_context_
->insertSyncPoint();
468 EXPECT_LT(0u, *sync_point
);
470 scoped_ptr
<SharedBitmap
> shared_bitmap
;
471 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
472 SingleReleaseCallbackImpl::Create(base::Bind(
473 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
474 release_called
, release_sync_point
, lost_resource
));
475 return child_resource_provider_
->CreateResourceFromTextureMailbox(
476 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
479 gfx::Size
size(64, 64);
480 scoped_ptr
<SharedBitmap
> shared_bitmap(
481 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
483 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
484 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
485 SingleReleaseCallbackImpl::Create(base::Bind(
486 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
487 release_called
, release_sync_point
, lost_resource
));
488 return child_resource_provider_
->CreateResourceFromTextureMailbox(
489 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
494 scoped_ptr
<ContextSharedData
> shared_data_
;
495 ResourceProviderContext
* context3d_
;
496 ResourceProviderContext
* child_context_
;
497 FakeOutputSurfaceClient output_surface_client_
;
498 FakeOutputSurfaceClient child_output_surface_client_
;
499 scoped_ptr
<OutputSurface
> output_surface_
;
500 scoped_ptr
<OutputSurface
> child_output_surface_
;
501 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
502 scoped_ptr
<ResourceProvider
> resource_provider_
;
503 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
504 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
505 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
508 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
509 ResourceProvider
* resource_provider
,
510 ResourceProviderContext
* context
) {
511 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
513 gfx::Size
size(1, 1);
514 ResourceFormat format
= RGBA_8888
;
515 size_t pixel_size
= TextureSizeBytes(size
, format
);
516 ASSERT_EQ(4U, pixel_size
);
518 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
519 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
520 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
521 if (expected_default_type
== ResourceProvider::GLTexture
)
522 EXPECT_EQ(0u, context
->NumTextures());
524 uint8_t data
[4] = { 1, 2, 3, 4 };
525 gfx::Rect
rect(size
);
526 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
527 if (expected_default_type
== ResourceProvider::GLTexture
)
528 EXPECT_EQ(1u, context
->NumTextures());
530 uint8_t result
[4] = { 0 };
531 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
532 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
534 resource_provider
->DeleteResource(id
);
535 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
536 if (expected_default_type
== ResourceProvider::GLTexture
)
537 EXPECT_EQ(0u, context
->NumTextures());
540 TEST_P(ResourceProviderTest
, Basic
) {
541 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
544 TEST_P(ResourceProviderTest
, Upload
) {
545 gfx::Size
size(2, 2);
546 ResourceFormat format
= RGBA_8888
;
547 size_t pixel_size
= TextureSizeBytes(size
, format
);
548 ASSERT_EQ(16U, pixel_size
);
550 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
551 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
553 uint8_t image
[16] = { 0 };
554 gfx::Rect
image_rect(size
);
555 resource_provider_
->SetPixels(
556 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
558 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
561 uint8_t result
[16] = { 0 };
563 gfx::Rect
source_rect(0, 0, 1, 1);
564 gfx::Vector2d
dest_offset(0, 0);
565 resource_provider_
->SetPixels(
566 id
, image
, image_rect
, source_rect
, dest_offset
);
568 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
570 resource_provider_
.get(), context(), id
, size
, format
, result
);
571 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
574 gfx::Rect
source_rect(0, 0, 1, 1);
575 gfx::Vector2d
dest_offset(1, 1);
576 resource_provider_
->SetPixels(
577 id
, image
, image_rect
, source_rect
, dest_offset
);
579 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
581 resource_provider_
.get(), context(), id
, size
, format
, result
);
582 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
585 gfx::Rect
source_rect(1, 0, 1, 1);
586 gfx::Vector2d
dest_offset(0, 1);
587 resource_provider_
->SetPixels(
588 id
, image
, image_rect
, source_rect
, dest_offset
);
590 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
592 resource_provider_
.get(), context(), id
, size
, format
, result
);
593 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
596 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
597 gfx::Rect
source_rect(100, 100, 1, 1);
598 gfx::Vector2d
dest_offset(1, 0);
599 resource_provider_
->SetPixels(
600 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
602 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
604 resource_provider_
.get(), context(), id
, size
, format
, result
);
605 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
608 resource_provider_
->DeleteResource(id
);
611 TEST_P(ResourceProviderTest
, TransferGLResources
) {
612 if (GetParam() != ResourceProvider::GLTexture
)
614 gfx::Size
size(1, 1);
615 ResourceFormat format
= RGBA_8888
;
616 size_t pixel_size
= TextureSizeBytes(size
, format
);
617 ASSERT_EQ(4U, pixel_size
);
619 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
620 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
621 uint8_t data1
[4] = { 1, 2, 3, 4 };
622 gfx::Rect
rect(size
);
623 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
625 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
626 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
627 uint8_t data2
[4] = { 5, 5, 5, 5 };
628 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
630 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
631 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
633 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
634 child_resource_provider_
.get(), id3
);
635 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
638 GLuint external_texture_id
= child_context_
->createExternalTexture();
639 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
641 gpu::Mailbox external_mailbox
;
642 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
643 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
644 external_mailbox
.name
);
645 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
646 ResourceProvider::ResourceId id4
=
647 child_resource_provider_
->CreateResourceFromTextureMailbox(
649 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
650 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
652 ReturnedResourceArray returned_to_child
;
654 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
656 // Transfer some resources to the parent.
657 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
658 resource_ids_to_transfer
.push_back(id1
);
659 resource_ids_to_transfer
.push_back(id2
);
660 resource_ids_to_transfer
.push_back(id3
);
661 resource_ids_to_transfer
.push_back(id4
);
662 TransferableResourceArray list
;
663 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
665 ASSERT_EQ(4u, list
.size());
666 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
667 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
668 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
669 list
[1].mailbox_holder
.sync_point
);
670 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
671 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
672 list
[2].mailbox_holder
.sync_point
);
673 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
674 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
675 list
[0].mailbox_holder
.texture_target
);
676 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
677 list
[1].mailbox_holder
.texture_target
);
678 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
679 list
[2].mailbox_holder
.texture_target
);
680 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
681 list
[3].mailbox_holder
.texture_target
);
682 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
683 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
684 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
685 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
686 resource_provider_
->ReceiveFromChild(child_id
, list
);
687 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
688 context3d_
->last_waited_sync_point());
690 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
691 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
694 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
695 context3d_
->last_waited_sync_point());
696 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
697 resource_ids_to_transfer
);
700 EXPECT_EQ(4u, resource_provider_
->num_resources());
701 ResourceProvider::ResourceIdMap resource_map
=
702 resource_provider_
->GetChildToParentMap(child_id
);
703 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
704 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
705 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
706 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
707 EXPECT_NE(0u, mapped_id1
);
708 EXPECT_NE(0u, mapped_id2
);
709 EXPECT_NE(0u, mapped_id3
);
710 EXPECT_NE(0u, mapped_id4
);
711 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
712 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
713 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
714 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
716 uint8_t result
[4] = { 0 };
718 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
719 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
722 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
723 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
726 // Check that transfering again the same resource from the child to the
728 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
729 resource_ids_to_transfer
.push_back(id1
);
730 resource_ids_to_transfer
.push_back(id2
);
731 resource_ids_to_transfer
.push_back(id3
);
732 TransferableResourceArray list
;
733 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
735 EXPECT_EQ(3u, list
.size());
736 EXPECT_EQ(id1
, list
[0].id
);
737 EXPECT_EQ(id2
, list
[1].id
);
738 EXPECT_EQ(id3
, list
[2].id
);
739 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
740 list
[0].mailbox_holder
.texture_target
);
741 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
742 list
[1].mailbox_holder
.texture_target
);
743 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
744 list
[2].mailbox_holder
.texture_target
);
745 ReturnedResourceArray returned
;
746 TransferableResource::ReturnResources(list
, &returned
);
747 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
748 // ids were exported twice, we returned them only once, they should still
750 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
751 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
752 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
755 EXPECT_EQ(0u, returned_to_child
.size());
757 // Transfer resources back from the parent to the child. Set no resources as
759 ResourceProvider::ResourceIdArray no_resources
;
760 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
762 ASSERT_EQ(4u, returned_to_child
.size());
763 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
764 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
765 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
766 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
767 EXPECT_FALSE(returned_to_child
[0].lost
);
768 EXPECT_FALSE(returned_to_child
[1].lost
);
769 EXPECT_FALSE(returned_to_child
[2].lost
);
770 EXPECT_FALSE(returned_to_child
[3].lost
);
771 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
772 returned_to_child
.clear();
774 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
775 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
776 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
777 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
780 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
781 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
783 ASSERT_NE(0U, lock
.texture_id());
784 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
785 child_context_
->GetPixels(size
, format
, result
);
786 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
789 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
790 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
792 ASSERT_NE(0U, lock
.texture_id());
793 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
794 child_context_
->GetPixels(size
, format
, result
);
795 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
798 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
799 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
801 ASSERT_NE(0U, lock
.texture_id());
802 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
805 // Transfer resources to the parent again.
806 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
807 resource_ids_to_transfer
.push_back(id1
);
808 resource_ids_to_transfer
.push_back(id2
);
809 resource_ids_to_transfer
.push_back(id3
);
810 resource_ids_to_transfer
.push_back(id4
);
811 TransferableResourceArray list
;
812 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
814 ASSERT_EQ(4u, list
.size());
815 EXPECT_EQ(id1
, list
[0].id
);
816 EXPECT_EQ(id2
, list
[1].id
);
817 EXPECT_EQ(id3
, list
[2].id
);
818 EXPECT_EQ(id4
, list
[3].id
);
819 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
820 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
821 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
822 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
823 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
824 list
[0].mailbox_holder
.texture_target
);
825 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
826 list
[1].mailbox_holder
.texture_target
);
827 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
828 list
[2].mailbox_holder
.texture_target
);
829 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
830 list
[3].mailbox_holder
.texture_target
);
831 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
832 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
833 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
834 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
835 resource_provider_
->ReceiveFromChild(child_id
, list
);
836 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
837 resource_ids_to_transfer
);
840 EXPECT_EQ(0u, returned_to_child
.size());
842 EXPECT_EQ(4u, resource_provider_
->num_resources());
843 resource_provider_
->DestroyChild(child_id
);
844 EXPECT_EQ(0u, resource_provider_
->num_resources());
846 ASSERT_EQ(4u, returned_to_child
.size());
847 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
848 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
849 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
850 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
851 EXPECT_FALSE(returned_to_child
[0].lost
);
852 EXPECT_FALSE(returned_to_child
[1].lost
);
853 EXPECT_FALSE(returned_to_child
[2].lost
);
854 EXPECT_FALSE(returned_to_child
[3].lost
);
857 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
858 if (GetParam() != ResourceProvider::GLTexture
)
860 gfx::Size
size(1, 1);
861 ResourceFormat format
= RGBA_8888
;
863 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
864 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
865 uint8_t data1
[4] = {1, 2, 3, 4};
866 gfx::Rect
rect(size
);
867 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
869 ReturnedResourceArray returned_to_child
;
871 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
873 // Transfer some resources to the parent.
874 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
875 resource_ids_to_transfer
.push_back(id1
);
876 TransferableResourceArray list
;
877 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
879 ASSERT_EQ(1u, list
.size());
880 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
882 resource_provider_
->ReceiveFromChild(child_id
, list
);
884 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
885 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
888 resource_provider_
->DeclareUsedResourcesFromChild(
889 child_id
, ResourceProvider::ResourceIdArray());
890 EXPECT_EQ(0u, returned_to_child
.size());
893 EXPECT_EQ(1u, returned_to_child
.size());
894 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
897 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
898 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
900 child_resource_provider_
->DeleteResource(id1
);
901 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
902 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
905 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
906 resource_provider_
->DestroyChild(child_id
);
909 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
910 // Overlays only supported on the GL path.
911 if (GetParam() != ResourceProvider::GLTexture
)
914 uint32 sync_point
= 0;
915 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
916 mailbox
.set_allow_overlay(true);
917 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
918 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
919 ResourceProvider::ResourceId id1
=
920 child_resource_provider_
->CreateResourceFromTextureMailbox(
921 mailbox
, release_callback
.Pass());
923 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
924 mailbox2
.set_allow_overlay(false);
925 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
926 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
927 ResourceProvider::ResourceId id2
=
928 child_resource_provider_
->CreateResourceFromTextureMailbox(
929 mailbox2
, release_callback2
.Pass());
931 ReturnedResourceArray returned_to_child
;
933 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
935 // Transfer some resources to the parent.
936 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
937 resource_ids_to_transfer
.push_back(id1
);
938 resource_ids_to_transfer
.push_back(id2
);
939 TransferableResourceArray list
;
940 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
942 ASSERT_EQ(2u, list
.size());
943 resource_provider_
->ReceiveFromChild(child_id
, list
);
944 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
945 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
947 resource_provider_
->DeclareUsedResourcesFromChild(
948 child_id
, ResourceProvider::ResourceIdArray());
950 EXPECT_EQ(2u, returned_to_child
.size());
951 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
953 child_resource_provider_
->DeleteResource(id1
);
954 child_resource_provider_
->DeleteResource(id2
);
955 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
957 resource_provider_
->DestroyChild(child_id
);
960 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
961 if (GetParam() != ResourceProvider::Bitmap
)
964 gfx::Size
size(1, 1);
965 ResourceFormat format
= RGBA_8888
;
966 size_t pixel_size
= TextureSizeBytes(size
, format
);
967 ASSERT_EQ(4U, pixel_size
);
969 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
970 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
971 uint8_t data1
[4] = { 1, 2, 3, 4 };
972 gfx::Rect
rect(size
);
973 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
975 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
976 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
977 uint8_t data2
[4] = { 5, 5, 5, 5 };
978 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
980 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
981 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
982 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
983 ResourceProvider::ResourceId id3
=
984 child_resource_provider_
->CreateResourceFromTextureMailbox(
985 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
986 SingleReleaseCallbackImpl::Create(base::Bind(
987 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
989 ReturnedResourceArray returned_to_child
;
991 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
993 // Transfer some resources to the parent.
994 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
995 resource_ids_to_transfer
.push_back(id1
);
996 resource_ids_to_transfer
.push_back(id2
);
997 resource_ids_to_transfer
.push_back(id3
);
998 TransferableResourceArray list
;
999 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1001 ASSERT_EQ(3u, list
.size());
1002 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1003 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1004 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1005 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1006 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1007 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1008 resource_provider_
->ReceiveFromChild(child_id
, list
);
1009 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1010 resource_ids_to_transfer
);
1013 EXPECT_EQ(3u, resource_provider_
->num_resources());
1014 ResourceProvider::ResourceIdMap resource_map
=
1015 resource_provider_
->GetChildToParentMap(child_id
);
1016 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1017 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1018 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1019 EXPECT_NE(0u, mapped_id1
);
1020 EXPECT_NE(0u, mapped_id2
);
1021 EXPECT_NE(0u, mapped_id3
);
1022 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1023 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1024 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1026 uint8_t result
[4] = { 0 };
1028 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1029 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1032 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1033 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1036 // Check that transfering again the same resource from the child to the
1038 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1039 resource_ids_to_transfer
.push_back(id1
);
1040 resource_ids_to_transfer
.push_back(id2
);
1041 TransferableResourceArray list
;
1042 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1044 EXPECT_EQ(2u, list
.size());
1045 EXPECT_EQ(id1
, list
[0].id
);
1046 EXPECT_EQ(id2
, list
[1].id
);
1047 ReturnedResourceArray returned
;
1048 TransferableResource::ReturnResources(list
, &returned
);
1049 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1050 // ids were exported twice, we returned them only once, they should still
1052 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1053 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1056 EXPECT_EQ(0u, returned_to_child
.size());
1058 // Transfer resources back from the parent to the child. Set no resources as
1060 ResourceProvider::ResourceIdArray no_resources
;
1061 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1063 ASSERT_EQ(3u, returned_to_child
.size());
1064 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1065 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1066 EXPECT_EQ(0u, returned_to_child
[2].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 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1072 for (unsigned i
= 0; i
< 3; i
++)
1073 returned_ids
.insert(returned_to_child
[i
].id
);
1074 EXPECT_EQ(expected_ids
, returned_ids
);
1075 EXPECT_FALSE(returned_to_child
[0].lost
);
1076 EXPECT_FALSE(returned_to_child
[1].lost
);
1077 EXPECT_FALSE(returned_to_child
[2].lost
);
1078 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1079 returned_to_child
.clear();
1081 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1082 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1083 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1086 ResourceProvider::ScopedReadLockSoftware
lock(
1087 child_resource_provider_
.get(), id1
);
1088 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1089 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1090 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1091 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1094 ResourceProvider::ScopedReadLockSoftware
lock(
1095 child_resource_provider_
.get(), id2
);
1096 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1097 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1098 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1099 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1102 // Transfer resources to the parent again.
1103 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1104 resource_ids_to_transfer
.push_back(id1
);
1105 resource_ids_to_transfer
.push_back(id2
);
1106 resource_ids_to_transfer
.push_back(id3
);
1107 TransferableResourceArray list
;
1108 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1110 ASSERT_EQ(3u, list
.size());
1111 EXPECT_EQ(id1
, list
[0].id
);
1112 EXPECT_EQ(id2
, list
[1].id
);
1113 EXPECT_EQ(id3
, list
[2].id
);
1114 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1115 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1116 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1117 resource_provider_
->ReceiveFromChild(child_id
, list
);
1118 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1119 resource_ids_to_transfer
);
1122 EXPECT_EQ(0u, returned_to_child
.size());
1124 EXPECT_EQ(3u, resource_provider_
->num_resources());
1125 resource_provider_
->DestroyChild(child_id
);
1126 EXPECT_EQ(0u, resource_provider_
->num_resources());
1128 ASSERT_EQ(3u, returned_to_child
.size());
1129 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1130 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1131 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1132 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1133 expected_ids
.insert(id1
);
1134 expected_ids
.insert(id2
);
1135 expected_ids
.insert(id3
);
1136 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1137 for (unsigned i
= 0; i
< 3; i
++)
1138 returned_ids
.insert(returned_to_child
[i
].id
);
1139 EXPECT_EQ(expected_ids
, returned_ids
);
1140 EXPECT_FALSE(returned_to_child
[0].lost
);
1141 EXPECT_FALSE(returned_to_child
[1].lost
);
1142 EXPECT_FALSE(returned_to_child
[2].lost
);
1145 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1146 if (GetParam() != ResourceProvider::Bitmap
)
1149 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1150 ResourceProviderContext::Create(shared_data_
.get()));
1152 FakeOutputSurfaceClient child_output_surface_client
;
1153 scoped_ptr
<OutputSurface
> child_output_surface(
1154 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1155 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1157 scoped_ptr
<ResourceProvider
> child_resource_provider(
1158 ResourceProvider::Create(child_output_surface
.get(),
1159 shared_bitmap_manager_
.get(),
1160 gpu_memory_buffer_manager_
.get(),
1166 gfx::Size
size(1, 1);
1167 ResourceFormat format
= RGBA_8888
;
1168 size_t pixel_size
= TextureSizeBytes(size
, format
);
1169 ASSERT_EQ(4U, pixel_size
);
1171 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1172 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1173 uint8_t data1
[4] = { 1, 2, 3, 4 };
1174 gfx::Rect
rect(size
);
1175 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1177 ReturnedResourceArray returned_to_child
;
1179 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1181 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1182 resource_ids_to_transfer
.push_back(id1
);
1183 TransferableResourceArray list
;
1184 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1186 ASSERT_EQ(1u, list
.size());
1187 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1188 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1189 list
[0].mailbox_holder
.texture_target
);
1190 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1191 resource_provider_
->ReceiveFromChild(child_id
, list
);
1194 EXPECT_EQ(0u, resource_provider_
->num_resources());
1195 ASSERT_EQ(1u, returned_to_child
.size());
1196 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1197 ResourceProvider::ResourceIdMap resource_map
=
1198 resource_provider_
->GetChildToParentMap(child_id
);
1199 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1200 EXPECT_EQ(0u, mapped_id1
);
1202 resource_provider_
->DestroyChild(child_id
);
1203 EXPECT_EQ(0u, resource_provider_
->num_resources());
1205 ASSERT_EQ(1u, returned_to_child
.size());
1206 EXPECT_FALSE(returned_to_child
[0].lost
);
1209 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1210 if (GetParam() != ResourceProvider::Bitmap
)
1213 gfx::Size
size(1, 1);
1214 ResourceFormat format
= RGBA_8888
;
1215 size_t pixel_size
= TextureSizeBytes(size
, format
);
1216 ASSERT_EQ(4U, pixel_size
);
1218 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1219 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1220 uint8_t data1
[4] = { 1, 2, 3, 4 };
1221 gfx::Rect
rect(size
);
1222 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1224 ReturnedResourceArray returned_to_child
;
1226 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1228 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1229 resource_ids_to_transfer
.push_back(id1
);
1230 TransferableResourceArray list
;
1231 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1233 ASSERT_EQ(1u, list
.size());
1235 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1236 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1237 resource_provider_
->ReceiveFromChild(child_id
, list
);
1240 EXPECT_EQ(1u, resource_provider_
->num_resources());
1241 EXPECT_EQ(0u, returned_to_child
.size());
1243 ResourceProvider::ResourceIdMap resource_map
=
1244 resource_provider_
->GetChildToParentMap(child_id
);
1245 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1246 EXPECT_NE(0u, mapped_id1
);
1248 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1250 EXPECT_FALSE(lock
.valid());
1253 resource_provider_
->DestroyChild(child_id
);
1254 EXPECT_EQ(0u, resource_provider_
->num_resources());
1256 ASSERT_EQ(1u, returned_to_child
.size());
1257 EXPECT_FALSE(returned_to_child
[0].lost
);
1260 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1261 gfx::Size
size(1, 1);
1262 ResourceFormat format
= RGBA_8888
;
1263 size_t pixel_size
= TextureSizeBytes(size
, format
);
1264 ASSERT_EQ(4U, pixel_size
);
1266 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1267 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1268 uint8_t data1
[4] = { 1, 2, 3, 4 };
1269 gfx::Rect
rect(size
);
1270 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1272 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1273 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1274 uint8_t data2
[4] = {5, 5, 5, 5};
1275 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1277 ReturnedResourceArray returned_to_child
;
1279 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1281 // Transfer some resources to the parent.
1282 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1283 resource_ids_to_transfer
.push_back(id1
);
1284 resource_ids_to_transfer
.push_back(id2
);
1285 TransferableResourceArray list
;
1286 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1288 ASSERT_EQ(2u, list
.size());
1289 if (GetParam() == ResourceProvider::GLTexture
) {
1290 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1291 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1293 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1294 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1295 resource_provider_
->ReceiveFromChild(child_id
, list
);
1296 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1297 resource_ids_to_transfer
);
1300 EXPECT_EQ(2u, resource_provider_
->num_resources());
1301 ResourceProvider::ResourceIdMap resource_map
=
1302 resource_provider_
->GetChildToParentMap(child_id
);
1303 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1304 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1305 EXPECT_NE(0u, mapped_id1
);
1306 EXPECT_NE(0u, mapped_id2
);
1307 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1308 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1311 // The parent transfers the resources to the grandparent.
1312 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1313 resource_ids_to_transfer
.push_back(mapped_id1
);
1314 resource_ids_to_transfer
.push_back(mapped_id2
);
1315 TransferableResourceArray list
;
1316 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1318 ASSERT_EQ(2u, list
.size());
1319 if (GetParam() == ResourceProvider::GLTexture
) {
1320 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1321 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1323 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1324 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1326 // Release the resource in the parent. Set no resources as being in use. The
1327 // resources are exported so that can't be transferred back yet.
1328 ResourceProvider::ResourceIdArray no_resources
;
1329 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1331 EXPECT_EQ(0u, returned_to_child
.size());
1332 EXPECT_EQ(2u, resource_provider_
->num_resources());
1334 // Return the resources from the grandparent to the parent. They should be
1335 // returned to the child then.
1336 EXPECT_EQ(2u, list
.size());
1337 EXPECT_EQ(mapped_id1
, list
[0].id
);
1338 EXPECT_EQ(mapped_id2
, list
[1].id
);
1339 ReturnedResourceArray returned
;
1340 TransferableResource::ReturnResources(list
, &returned
);
1341 resource_provider_
->ReceiveReturnsFromParent(returned
);
1343 EXPECT_EQ(0u, resource_provider_
->num_resources());
1344 ASSERT_EQ(2u, returned_to_child
.size());
1345 if (GetParam() == ResourceProvider::GLTexture
) {
1346 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1347 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1349 EXPECT_FALSE(returned_to_child
[0].lost
);
1350 EXPECT_FALSE(returned_to_child
[1].lost
);
1354 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1355 gfx::Size
size(1, 1);
1356 ResourceFormat format
= RGBA_8888
;
1357 size_t pixel_size
= TextureSizeBytes(size
, format
);
1358 ASSERT_EQ(4U, pixel_size
);
1360 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1361 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1362 uint8_t data1
[4] = {1, 2, 3, 4};
1363 gfx::Rect
rect(size
);
1364 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1366 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1367 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1368 uint8_t data2
[4] = {5, 5, 5, 5};
1369 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1371 ReturnedResourceArray returned_to_child
;
1373 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1375 // Transfer some resources to the parent.
1376 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1377 resource_ids_to_transfer
.push_back(id1
);
1378 resource_ids_to_transfer
.push_back(id2
);
1379 TransferableResourceArray list
;
1380 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1382 ASSERT_EQ(2u, list
.size());
1383 if (GetParam() == ResourceProvider::GLTexture
) {
1384 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1385 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1387 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1388 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1389 resource_provider_
->ReceiveFromChild(child_id
, list
);
1390 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1391 resource_ids_to_transfer
);
1394 EXPECT_EQ(2u, resource_provider_
->num_resources());
1395 ResourceProvider::ResourceIdMap resource_map
=
1396 resource_provider_
->GetChildToParentMap(child_id
);
1397 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1398 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1399 EXPECT_NE(0u, mapped_id1
);
1400 EXPECT_NE(0u, mapped_id2
);
1401 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1402 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1405 // The parent transfers the resources to the grandparent.
1406 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1407 resource_ids_to_transfer
.push_back(mapped_id1
);
1408 resource_ids_to_transfer
.push_back(mapped_id2
);
1409 TransferableResourceArray list
;
1410 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1412 ASSERT_EQ(2u, list
.size());
1413 if (GetParam() == ResourceProvider::GLTexture
) {
1414 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1415 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1417 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1418 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1420 // Release the resource in the parent. Set no resources as being in use. The
1421 // resources are exported so that can't be transferred back yet.
1422 ResourceProvider::ResourceIdArray no_resources
;
1423 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1425 // Destroy the child, the resources should not be returned yet.
1426 EXPECT_EQ(0u, returned_to_child
.size());
1427 EXPECT_EQ(2u, resource_provider_
->num_resources());
1429 resource_provider_
->DestroyChild(child_id
);
1431 EXPECT_EQ(2u, resource_provider_
->num_resources());
1432 ASSERT_EQ(0u, returned_to_child
.size());
1434 // Return a resource from the grandparent, it should be returned at this
1436 EXPECT_EQ(2u, list
.size());
1437 EXPECT_EQ(mapped_id1
, list
[0].id
);
1438 EXPECT_EQ(mapped_id2
, list
[1].id
);
1439 TransferableResourceArray return_list
;
1440 return_list
.push_back(list
[1]);
1442 ReturnedResourceArray returned
;
1443 TransferableResource::ReturnResources(return_list
, &returned
);
1444 resource_provider_
->ReceiveReturnsFromParent(returned
);
1446 EXPECT_EQ(1u, resource_provider_
->num_resources());
1447 ASSERT_EQ(1u, returned_to_child
.size());
1448 if (GetParam() == ResourceProvider::GLTexture
) {
1449 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1451 EXPECT_FALSE(returned_to_child
[0].lost
);
1452 returned_to_child
.clear();
1454 // Destroy the parent resource provider. The resource that's left should be
1455 // lost at this point, and returned.
1456 resource_provider_
= nullptr;
1457 ASSERT_EQ(1u, returned_to_child
.size());
1458 if (GetParam() == ResourceProvider::GLTexture
) {
1459 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1461 EXPECT_TRUE(returned_to_child
[0].lost
);
1465 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1466 gfx::Size
size(1, 1);
1467 ResourceFormat format
= RGBA_8888
;
1468 size_t pixel_size
= TextureSizeBytes(size
, format
);
1469 ASSERT_EQ(4U, pixel_size
);
1471 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1472 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1473 uint8_t data
[4] = { 1, 2, 3, 4 };
1474 gfx::Rect
rect(size
);
1475 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1477 ReturnedResourceArray returned_to_child
;
1479 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1481 // Transfer some resource to the parent.
1482 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1483 resource_ids_to_transfer
.push_back(id
);
1484 TransferableResourceArray list
;
1485 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1487 ASSERT_EQ(1u, list
.size());
1488 if (GetParam() == ResourceProvider::GLTexture
)
1489 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1490 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1491 resource_provider_
->ReceiveFromChild(child_id
, list
);
1492 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1493 resource_ids_to_transfer
);
1496 // Delete textures in the child, while they are transfered.
1497 child_resource_provider_
->DeleteResource(id
);
1498 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1500 EXPECT_EQ(0u, returned_to_child
.size());
1502 // Transfer resources back from the parent to the child. Set no resources as
1504 ResourceProvider::ResourceIdArray no_resources
;
1505 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1507 ASSERT_EQ(1u, returned_to_child
.size());
1508 if (GetParam() == ResourceProvider::GLTexture
)
1509 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1510 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1512 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1515 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1516 gfx::Size
size(1, 1);
1517 ResourceFormat format
= RGBA_8888
;
1518 size_t pixel_size
= TextureSizeBytes(size
, format
);
1519 ASSERT_EQ(4U, pixel_size
);
1521 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1522 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1523 uint8_t data
[4] = {1, 2, 3, 4};
1524 gfx::Rect
rect(size
);
1525 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1527 ReturnedResourceArray returned_to_child
;
1529 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1530 const ResourceProvider::ResourceIdMap
& map
=
1531 resource_provider_
->GetChildToParentMap(child_id
);
1533 // Transfer some resource to the parent.
1534 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1535 resource_ids_to_transfer
.push_back(id
);
1536 TransferableResourceArray list
;
1537 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1539 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1540 resource_provider_
->ReceiveFromChild(child_id
, list
);
1541 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1542 resource_ids_to_transfer
);
1544 TransferableResourceArray sent_to_top_level
;
1546 // Parent transfers to top-level.
1547 ASSERT_TRUE(map
.find(id
) != map
.end());
1548 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1549 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1550 resource_ids_to_transfer
.push_back(parent_id
);
1551 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1552 &sent_to_top_level
);
1553 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1556 // Stop using resource.
1557 ResourceProvider::ResourceIdArray empty
;
1558 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1559 // Resource is not yet returned to the child, since it's in use by the
1561 EXPECT_TRUE(returned_to_child
.empty());
1564 // Send the resource to the parent again.
1565 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1566 resource_ids_to_transfer
.push_back(id
);
1567 TransferableResourceArray list
;
1568 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1570 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1571 resource_provider_
->ReceiveFromChild(child_id
, list
);
1572 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1573 resource_ids_to_transfer
);
1576 // Receive returns back from top-level.
1577 ReturnedResourceArray returned
;
1578 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1579 resource_provider_
->ReceiveReturnsFromParent(returned
);
1580 // Resource is still not yet returned to the child, since it's declared used
1582 EXPECT_TRUE(returned_to_child
.empty());
1583 ASSERT_TRUE(map
.find(id
) != map
.end());
1584 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1585 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1588 sent_to_top_level
.clear();
1589 // Parent transfers again to top-level.
1590 ASSERT_TRUE(map
.find(id
) != map
.end());
1591 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1592 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1593 resource_ids_to_transfer
.push_back(parent_id
);
1594 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1595 &sent_to_top_level
);
1596 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1599 // Receive returns back from top-level.
1600 ReturnedResourceArray returned
;
1601 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1602 resource_provider_
->ReceiveReturnsFromParent(returned
);
1603 // Resource is still not yet returned to the child, since it's still
1604 // declared used in the parent.
1605 EXPECT_TRUE(returned_to_child
.empty());
1606 ASSERT_TRUE(map
.find(id
) != map
.end());
1607 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1608 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1611 // Stop using resource.
1612 ResourceProvider::ResourceIdArray empty
;
1613 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1614 // Resource should have been returned to the child, since it's no longer in
1615 // use by the top-level.
1616 ASSERT_EQ(1u, returned_to_child
.size());
1617 EXPECT_EQ(id
, returned_to_child
[0].id
);
1618 EXPECT_EQ(2, returned_to_child
[0].count
);
1619 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1620 returned_to_child
.clear();
1621 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1625 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1627 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1628 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1629 new TextureStateTrackingContext
);
1630 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1632 FakeOutputSurfaceClient child_output_surface_client
;
1633 scoped_ptr
<OutputSurface
> child_output_surface(
1634 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1635 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1636 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1637 new TestSharedBitmapManager());
1639 scoped_ptr
<ResourceProvider
> child_resource_provider(
1640 ResourceProvider::Create(child_output_surface
.get(),
1641 shared_bitmap_manager
.get(),
1648 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1649 new TextureStateTrackingContext
);
1650 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1652 FakeOutputSurfaceClient parent_output_surface_client
;
1653 scoped_ptr
<OutputSurface
> parent_output_surface(
1654 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1655 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1657 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1658 ResourceProvider::Create(parent_output_surface
.get(),
1659 shared_bitmap_manager
.get(),
1666 gfx::Size
size(1, 1);
1667 ResourceFormat format
= RGBA_8888
;
1668 int child_texture_id
= 1;
1669 int parent_texture_id
= 2;
1671 size_t pixel_size
= TextureSizeBytes(size
, format
);
1672 ASSERT_EQ(4U, pixel_size
);
1674 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1675 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1677 // The new texture is created with GL_LINEAR.
1678 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1679 .Times(2); // Once to create and once to allocate.
1680 EXPECT_CALL(*child_context
,
1681 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1682 EXPECT_CALL(*child_context
,
1683 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1686 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1689 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1690 EXPECT_CALL(*child_context
,
1691 texParameteri(GL_TEXTURE_2D
,
1692 GL_TEXTURE_POOL_CHROMIUM
,
1693 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1694 child_resource_provider
->AllocateForTesting(id
);
1695 Mock::VerifyAndClearExpectations(child_context
);
1697 uint8_t data
[4] = { 1, 2, 3, 4 };
1698 gfx::Rect
rect(size
);
1700 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1701 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1702 Mock::VerifyAndClearExpectations(child_context
);
1704 // The texture is set to |child_filter| in the child.
1705 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1706 if (child_filter
!= GL_LINEAR
) {
1709 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1712 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1714 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1715 Mock::VerifyAndClearExpectations(child_context
);
1717 ReturnedResourceArray returned_to_child
;
1718 int child_id
= parent_resource_provider
->CreateChild(
1719 GetReturnCallback(&returned_to_child
));
1721 // Transfer some resource to the parent.
1722 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1723 resource_ids_to_transfer
.push_back(id
);
1724 TransferableResourceArray list
;
1726 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1727 EXPECT_CALL(*child_context
,
1728 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1729 EXPECT_CALL(*child_context
, insertSyncPoint());
1730 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1732 Mock::VerifyAndClearExpectations(child_context
);
1734 ASSERT_EQ(1u, list
.size());
1735 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1737 EXPECT_CALL(*parent_context
,
1738 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1739 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1740 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1742 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1743 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1746 Mock::VerifyAndClearExpectations(parent_context
);
1748 parent_resource_provider
->DeclareUsedResourcesFromChild(
1749 child_id
, resource_ids_to_transfer
);
1750 Mock::VerifyAndClearExpectations(parent_context
);
1752 ResourceProvider::ResourceIdMap resource_map
=
1753 parent_resource_provider
->GetChildToParentMap(child_id
);
1754 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1755 EXPECT_NE(0u, mapped_id
);
1757 // The texture is set to |parent_filter| in the parent.
1758 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1761 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1764 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1765 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1766 Mock::VerifyAndClearExpectations(parent_context
);
1768 // The texture should be reset to |child_filter| in the parent when it is
1769 // returned, since that is how it was received.
1770 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1773 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1776 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1779 EXPECT_EQ(0u, returned_to_child
.size());
1781 // Transfer resources back from the parent to the child. Set no resources
1783 ResourceProvider::ResourceIdArray no_resources
;
1784 EXPECT_CALL(*parent_context
, insertSyncPoint());
1785 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1787 Mock::VerifyAndClearExpectations(parent_context
);
1789 ASSERT_EQ(1u, returned_to_child
.size());
1790 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1793 // The child remembers the texture filter is set to |child_filter|.
1794 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1795 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1796 Mock::VerifyAndClearExpectations(child_context
);
1800 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1801 if (GetParam() != ResourceProvider::GLTexture
)
1803 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1806 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1807 if (GetParam() != ResourceProvider::GLTexture
)
1809 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1812 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1813 // Other mailbox transfers tested elsewhere.
1814 if (GetParam() != ResourceProvider::GLTexture
)
1816 unsigned texture
= context()->createTexture();
1817 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1818 uint8_t data
[4] = { 1, 2, 3, 4 };
1819 context()->texImage2D(
1820 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1821 gpu::Mailbox mailbox
;
1822 context()->genMailboxCHROMIUM(mailbox
.name
);
1823 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1824 uint32 sync_point
= context()->insertSyncPoint();
1826 // All the logic below assumes that the sync points are all positive.
1827 EXPECT_LT(0u, sync_point
);
1829 uint32 release_sync_point
= 0;
1830 bool lost_resource
= false;
1831 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1832 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1833 &release_sync_point
,
1835 &main_thread_task_runner
);
1836 ResourceProvider::ResourceId resource
=
1837 resource_provider_
->CreateResourceFromTextureMailbox(
1838 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1839 SingleReleaseCallbackImpl::Create(callback
));
1840 EXPECT_EQ(1u, context()->NumTextures());
1841 EXPECT_EQ(0u, release_sync_point
);
1843 // Transfer the resource, expect the sync points to be consistent.
1844 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1845 resource_ids_to_transfer
.push_back(resource
);
1846 TransferableResourceArray list
;
1847 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1848 ASSERT_EQ(1u, list
.size());
1849 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1851 memcmp(mailbox
.name
,
1852 list
[0].mailbox_holder
.mailbox
.name
,
1853 sizeof(mailbox
.name
)));
1854 EXPECT_EQ(0u, release_sync_point
);
1856 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1857 unsigned other_texture
= context()->createTexture();
1858 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1859 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1860 uint8_t test_data
[4] = { 0 };
1861 context()->GetPixels(
1862 gfx::Size(1, 1), RGBA_8888
, test_data
);
1863 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1864 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1865 context()->deleteTexture(other_texture
);
1866 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1867 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1869 // Receive the resource, then delete it, expect the sync points to be
1871 ReturnedResourceArray returned
;
1872 TransferableResource::ReturnResources(list
, &returned
);
1873 resource_provider_
->ReceiveReturnsFromParent(returned
);
1874 EXPECT_EQ(1u, context()->NumTextures());
1875 EXPECT_EQ(0u, release_sync_point
);
1877 resource_provider_
->DeleteResource(resource
);
1878 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1879 EXPECT_FALSE(lost_resource
);
1880 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1883 // We're going to do the same thing as above, but testing the case where we
1884 // delete the resource before we receive it back.
1885 sync_point
= release_sync_point
;
1886 EXPECT_LT(0u, sync_point
);
1887 release_sync_point
= 0;
1888 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1889 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1890 SingleReleaseCallbackImpl::Create(callback
));
1891 EXPECT_EQ(1u, context()->NumTextures());
1892 EXPECT_EQ(0u, release_sync_point
);
1894 // Transfer the resource, expect the sync points to be consistent.
1895 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1896 resource_ids_to_transfer
.push_back(resource
);
1897 TransferableResourceArray list
;
1898 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1899 ASSERT_EQ(1u, list
.size());
1900 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1902 memcmp(mailbox
.name
,
1903 list
[0].mailbox_holder
.mailbox
.name
,
1904 sizeof(mailbox
.name
)));
1905 EXPECT_EQ(0u, release_sync_point
);
1907 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1908 unsigned other_texture
= context()->createTexture();
1909 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1910 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1911 uint8_t test_data
[4] = { 0 };
1912 context()->GetPixels(
1913 gfx::Size(1, 1), RGBA_8888
, test_data
);
1914 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1915 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1916 context()->deleteTexture(other_texture
);
1917 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1918 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1920 // Delete the resource, which shouldn't do anything.
1921 resource_provider_
->DeleteResource(resource
);
1922 EXPECT_EQ(1u, context()->NumTextures());
1923 EXPECT_EQ(0u, release_sync_point
);
1925 // Then receive the resource which should release the mailbox, expect the
1926 // sync points to be consistent.
1927 ReturnedResourceArray returned
;
1928 TransferableResource::ReturnResources(list
, &returned
);
1929 resource_provider_
->ReceiveReturnsFromParent(returned
);
1930 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1931 EXPECT_FALSE(lost_resource
);
1932 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1935 context()->waitSyncPoint(release_sync_point
);
1936 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1937 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1938 context()->deleteTexture(texture
);
1941 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1942 gfx::Size
size(1, 1);
1943 ResourceFormat format
= RGBA_8888
;
1944 ResourceProvider::ResourceId resource
=
1945 child_resource_provider_
->CreateResource(
1948 ResourceProvider::TextureHintImmutable
,
1950 child_resource_provider_
->AllocateForTesting(resource
);
1951 // Expect a GL resource to be lost.
1952 bool should_lose_resource
= GetParam() == ResourceProvider::GLTexture
;
1954 ReturnedResourceArray returned_to_child
;
1956 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1958 // Transfer the resource to the parent.
1959 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1960 resource_ids_to_transfer
.push_back(resource
);
1961 TransferableResourceArray list
;
1962 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1964 EXPECT_EQ(1u, list
.size());
1966 resource_provider_
->ReceiveFromChild(child_id
, list
);
1967 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1968 resource_ids_to_transfer
);
1971 // Lose the output surface in the parent.
1972 resource_provider_
->DidLoseOutputSurface();
1975 EXPECT_EQ(0u, returned_to_child
.size());
1977 // Transfer resources back from the parent to the child. Set no resources as
1979 ResourceProvider::ResourceIdArray no_resources
;
1980 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1982 // Expect a GL resource to be lost.
1983 ASSERT_EQ(1u, returned_to_child
.size());
1984 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
1985 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1986 returned_to_child
.clear();
1989 // A GL resource should be lost.
1990 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
1992 // Lost resources stay in use in the parent forever.
1993 EXPECT_EQ(should_lose_resource
,
1994 child_resource_provider_
->InUseByConsumer(resource
));
1997 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
1998 gfx::Size
size(1, 1);
1999 ResourceFormat format
= RGBA_8888
;
2000 ResourceProvider::ResourceId resource
=
2001 child_resource_provider_
->CreateResource(
2004 ResourceProvider::TextureHintImmutable
,
2006 child_resource_provider_
->AllocateForTesting(resource
);
2008 ReturnedResourceArray returned_to_child
;
2010 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2012 // Transfer the resource to the parent.
2013 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2014 resource_ids_to_transfer
.push_back(resource
);
2015 TransferableResourceArray list
;
2016 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2018 EXPECT_EQ(1u, list
.size());
2020 resource_provider_
->ReceiveFromChild(child_id
, list
);
2021 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2022 resource_ids_to_transfer
);
2026 ResourceProvider::ResourceIdMap resource_map
=
2027 resource_provider_
->GetChildToParentMap(child_id
);
2028 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2029 EXPECT_NE(0u, parent_resource
);
2031 // Transfer to a grandparent.
2032 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2033 resource_ids_to_transfer
.push_back(parent_resource
);
2034 TransferableResourceArray list
;
2035 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2037 // Receive back a lost resource from the grandparent.
2038 EXPECT_EQ(1u, list
.size());
2039 EXPECT_EQ(parent_resource
, list
[0].id
);
2040 ReturnedResourceArray returned
;
2041 TransferableResource::ReturnResources(list
, &returned
);
2042 EXPECT_EQ(1u, returned
.size());
2043 EXPECT_EQ(parent_resource
, returned
[0].id
);
2044 returned
[0].lost
= true;
2045 resource_provider_
->ReceiveReturnsFromParent(returned
);
2047 // The resource should be lost.
2048 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2050 // Lost resources stay in use in the parent forever.
2051 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2055 EXPECT_EQ(0u, returned_to_child
.size());
2057 // Transfer resources back from the parent to the child. Set no resources as
2059 ResourceProvider::ResourceIdArray no_resources
;
2060 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2062 // Expect the resource to be lost.
2063 ASSERT_EQ(1u, returned_to_child
.size());
2064 EXPECT_TRUE(returned_to_child
[0].lost
);
2065 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2066 returned_to_child
.clear();
2069 // The resource should be lost.
2070 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2072 // Lost resources stay in use in the parent forever.
2073 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2076 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2077 uint32 release_sync_point
= 0;
2078 bool lost_resource
= false;
2079 bool release_called
= false;
2080 uint32 sync_point
= 0;
2081 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2082 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2084 ReturnedResourceArray returned_to_child
;
2086 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2088 // Transfer the resource to the parent.
2089 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2090 resource_ids_to_transfer
.push_back(resource
);
2091 TransferableResourceArray list
;
2092 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2094 EXPECT_EQ(1u, list
.size());
2096 resource_provider_
->ReceiveFromChild(child_id
, list
);
2097 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2098 resource_ids_to_transfer
);
2101 // Lose the output surface in the parent.
2102 resource_provider_
->DidLoseOutputSurface();
2105 EXPECT_EQ(0u, returned_to_child
.size());
2107 // Transfer resources back from the parent to the child. Set no resources as
2109 ResourceProvider::ResourceIdArray no_resources
;
2110 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2112 ASSERT_EQ(1u, returned_to_child
.size());
2113 // Losing an output surface only loses hardware resources.
2114 EXPECT_EQ(returned_to_child
[0].lost
,
2115 GetParam() == ResourceProvider::GLTexture
);
2116 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2117 returned_to_child
.clear();
2120 // Delete the resource in the child. Expect the resource to be lost if it's
2122 child_resource_provider_
->DeleteResource(resource
);
2123 EXPECT_EQ(lost_resource
, GetParam() == ResourceProvider::GLTexture
);
2126 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2127 uint32 release_sync_point
= 0;
2128 bool lost_resource
= false;
2129 bool release_called
= false;
2130 uint32 sync_point
= 0;
2131 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2132 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2134 ReturnedResourceArray returned_to_child
;
2136 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2138 // Transfer the resource to the parent.
2139 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2140 resource_ids_to_transfer
.push_back(resource
);
2141 TransferableResourceArray list
;
2142 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2144 EXPECT_EQ(1u, list
.size());
2146 resource_provider_
->ReceiveFromChild(child_id
, list
);
2147 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2148 resource_ids_to_transfer
);
2152 ResourceProvider::ResourceIdMap resource_map
=
2153 resource_provider_
->GetChildToParentMap(child_id
);
2154 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2155 EXPECT_NE(0u, parent_resource
);
2157 // Transfer to a grandparent.
2158 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2159 resource_ids_to_transfer
.push_back(parent_resource
);
2160 TransferableResourceArray list
;
2161 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2163 // Receive back a lost resource from the grandparent.
2164 EXPECT_EQ(1u, list
.size());
2165 EXPECT_EQ(parent_resource
, list
[0].id
);
2166 ReturnedResourceArray returned
;
2167 TransferableResource::ReturnResources(list
, &returned
);
2168 EXPECT_EQ(1u, returned
.size());
2169 EXPECT_EQ(parent_resource
, returned
[0].id
);
2170 returned
[0].lost
= true;
2171 resource_provider_
->ReceiveReturnsFromParent(returned
);
2175 EXPECT_EQ(0u, returned_to_child
.size());
2177 // Transfer resources back from the parent to the child. Set no resources as
2179 ResourceProvider::ResourceIdArray no_resources
;
2180 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2182 // Expect the resource to be lost.
2183 ASSERT_EQ(1u, returned_to_child
.size());
2184 EXPECT_TRUE(returned_to_child
[0].lost
);
2185 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2186 returned_to_child
.clear();
2189 // Delete the resource in the child. Expect the resource to be lost.
2190 child_resource_provider_
->DeleteResource(resource
);
2191 EXPECT_TRUE(lost_resource
);
2194 TEST_P(ResourceProviderTest
, Shutdown
) {
2195 uint32 release_sync_point
= 0;
2196 bool lost_resource
= false;
2197 bool release_called
= false;
2198 uint32 sync_point
= 0;
2200 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2202 EXPECT_EQ(0u, release_sync_point
);
2203 EXPECT_FALSE(lost_resource
);
2205 child_resource_provider_
= nullptr;
2207 if (GetParam() == ResourceProvider::GLTexture
) {
2208 EXPECT_LE(sync_point
, release_sync_point
);
2210 EXPECT_TRUE(release_called
);
2211 EXPECT_FALSE(lost_resource
);
2214 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2215 uint32 release_sync_point
= 0;
2216 bool lost_resource
= false;
2217 bool release_called
= false;
2218 uint32 sync_point
= 0;
2219 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2220 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2222 // Transfer the resource, so we can't release it properly on shutdown.
2223 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2224 resource_ids_to_transfer
.push_back(resource
);
2225 TransferableResourceArray list
;
2226 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2229 EXPECT_EQ(0u, release_sync_point
);
2230 EXPECT_FALSE(lost_resource
);
2232 child_resource_provider_
= nullptr;
2234 // Since the resource is in the parent, the child considers it lost.
2235 EXPECT_EQ(0u, release_sync_point
);
2236 EXPECT_TRUE(lost_resource
);
2239 TEST_P(ResourceProviderTest
, LostContext
) {
2240 // TextureMailbox callbacks only exist for GL textures for now.
2241 if (GetParam() != ResourceProvider::GLTexture
)
2243 unsigned texture
= context()->createTexture();
2244 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2245 gpu::Mailbox mailbox
;
2246 context()->genMailboxCHROMIUM(mailbox
.name
);
2247 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2248 uint32 sync_point
= context()->insertSyncPoint();
2250 EXPECT_LT(0u, sync_point
);
2252 uint32 release_sync_point
= 0;
2253 bool lost_resource
= false;
2254 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2255 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2256 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2257 &release_sync_point
,
2259 &main_thread_task_runner
));
2260 resource_provider_
->CreateResourceFromTextureMailbox(
2261 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2263 EXPECT_EQ(0u, release_sync_point
);
2264 EXPECT_FALSE(lost_resource
);
2265 EXPECT_EQ(NULL
, main_thread_task_runner
);
2267 resource_provider_
->DidLoseOutputSurface();
2268 resource_provider_
= nullptr;
2270 EXPECT_LE(sync_point
, release_sync_point
);
2271 EXPECT_TRUE(lost_resource
);
2272 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2275 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2276 // Sampling is only supported for GL textures.
2277 if (GetParam() != ResourceProvider::GLTexture
)
2280 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2281 new TextureStateTrackingContext
);
2282 TextureStateTrackingContext
* context
= context_owned
.get();
2284 FakeOutputSurfaceClient output_surface_client
;
2285 scoped_ptr
<OutputSurface
> output_surface(
2286 FakeOutputSurface::Create3d(context_owned
.Pass()));
2287 CHECK(output_surface
->BindToClient(&output_surface_client
));
2289 scoped_ptr
<ResourceProvider
> resource_provider(
2290 ResourceProvider::Create(output_surface
.get(),
2291 shared_bitmap_manager_
.get(),
2292 gpu_memory_buffer_manager_
.get(),
2298 gfx::Size
size(1, 1);
2299 ResourceFormat format
= RGBA_8888
;
2302 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2303 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2305 // Check that the texture gets created with the right sampler settings.
2306 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2307 .Times(2); // Once to create and once to allocate.
2308 EXPECT_CALL(*context
,
2309 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2310 EXPECT_CALL(*context
,
2311 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2314 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2317 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2318 EXPECT_CALL(*context
,
2319 texParameteri(GL_TEXTURE_2D
,
2320 GL_TEXTURE_POOL_CHROMIUM
,
2321 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2323 resource_provider
->AllocateForTesting(id
);
2324 Mock::VerifyAndClearExpectations(context
);
2326 // Creating a sampler with the default filter should not change any texture
2329 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2330 ResourceProvider::ScopedSamplerGL
sampler(
2331 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2332 Mock::VerifyAndClearExpectations(context
);
2335 // Using a different filter should be reflected in the texture parameters.
2337 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2340 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2343 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2344 ResourceProvider::ScopedSamplerGL
sampler(
2345 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2346 Mock::VerifyAndClearExpectations(context
);
2349 // Test resetting to the default filter.
2351 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2352 EXPECT_CALL(*context
,
2353 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2354 EXPECT_CALL(*context
,
2355 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2356 ResourceProvider::ScopedSamplerGL
sampler(
2357 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2358 Mock::VerifyAndClearExpectations(context
);
2362 TEST_P(ResourceProviderTest
, ManagedResource
) {
2363 // Sampling is only supported for GL textures.
2364 if (GetParam() != ResourceProvider::GLTexture
)
2367 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2368 new TextureStateTrackingContext
);
2369 TextureStateTrackingContext
* context
= context_owned
.get();
2371 FakeOutputSurfaceClient output_surface_client
;
2372 scoped_ptr
<OutputSurface
> output_surface(
2373 FakeOutputSurface::Create3d(context_owned
.Pass()));
2374 CHECK(output_surface
->BindToClient(&output_surface_client
));
2376 scoped_ptr
<ResourceProvider
> resource_provider(
2377 ResourceProvider::Create(output_surface
.get(),
2378 shared_bitmap_manager_
.get(),
2379 gpu_memory_buffer_manager_
.get(),
2385 gfx::Size
size(1, 1);
2386 ResourceFormat format
= RGBA_8888
;
2389 // Check that the texture gets created with the right sampler settings.
2390 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2394 ResourceProvider::TextureHintImmutable
,
2396 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2397 EXPECT_CALL(*context
,
2398 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2399 EXPECT_CALL(*context
,
2400 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2403 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2406 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2407 EXPECT_CALL(*context
,
2408 texParameteri(GL_TEXTURE_2D
,
2409 GL_TEXTURE_POOL_CHROMIUM
,
2410 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2411 resource_provider
->CreateForTesting(id
);
2414 Mock::VerifyAndClearExpectations(context
);
2417 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2418 // Sampling is only supported for GL textures.
2419 if (GetParam() != ResourceProvider::GLTexture
)
2422 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2423 new TextureStateTrackingContext
);
2424 TextureStateTrackingContext
* context
= context_owned
.get();
2426 FakeOutputSurfaceClient output_surface_client
;
2427 scoped_ptr
<OutputSurface
> output_surface(
2428 FakeOutputSurface::Create3d(context_owned
.Pass()));
2429 CHECK(output_surface
->BindToClient(&output_surface_client
));
2431 scoped_ptr
<ResourceProvider
> resource_provider(
2432 ResourceProvider::Create(output_surface
.get(),
2433 shared_bitmap_manager_
.get(),
2434 gpu_memory_buffer_manager_
.get(),
2440 gfx::Size
size(1, 1);
2441 ResourceFormat format
= RGBA_8888
;
2442 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2444 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2445 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2446 // Check that the texture gets created with the right sampler settings.
2447 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2452 ResourceProvider::TextureHintImmutable
,
2454 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2455 EXPECT_CALL(*context
,
2456 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2457 EXPECT_CALL(*context
,
2458 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2459 EXPECT_CALL(*context
,
2460 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2461 EXPECT_CALL(*context
,
2462 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2463 EXPECT_CALL(*context
,
2464 texParameteri(GL_TEXTURE_2D
,
2465 GL_TEXTURE_POOL_CHROMIUM
,
2466 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2467 resource_provider
->CreateForTesting(id
);
2470 Mock::VerifyAndClearExpectations(context
);
2474 TEST_P(ResourceProviderTest
, TextureHint
) {
2475 // Sampling is only supported for GL textures.
2476 if (GetParam() != ResourceProvider::GLTexture
)
2479 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2480 new TextureStateTrackingContext
);
2481 TextureStateTrackingContext
* context
= context_owned
.get();
2482 context
->set_support_texture_storage(true);
2483 context
->set_support_texture_usage(true);
2485 FakeOutputSurfaceClient output_surface_client
;
2486 scoped_ptr
<OutputSurface
> output_surface(
2487 FakeOutputSurface::Create3d(context_owned
.Pass()));
2488 CHECK(output_surface
->BindToClient(&output_surface_client
));
2490 scoped_ptr
<ResourceProvider
> resource_provider(
2491 ResourceProvider::Create(output_surface
.get(),
2492 shared_bitmap_manager_
.get(),
2493 gpu_memory_buffer_manager_
.get(),
2499 gfx::Size
size(1, 1);
2500 ResourceFormat format
= RGBA_8888
;
2501 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2503 const ResourceProvider::TextureHint hints
[4] = {
2504 ResourceProvider::TextureHintDefault
,
2505 ResourceProvider::TextureHintImmutable
,
2506 ResourceProvider::TextureHintFramebuffer
,
2507 ResourceProvider::TextureHintImmutableFramebuffer
,
2509 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2510 // Check that the texture gets created with the right sampler settings.
2511 ResourceProvider::ResourceId id
=
2512 resource_provider
->CreateGLTexture(size
,
2516 hints
[texture_id
- 1],
2518 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2519 EXPECT_CALL(*context
,
2520 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2521 EXPECT_CALL(*context
,
2522 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2525 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2528 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2529 EXPECT_CALL(*context
,
2530 texParameteri(GL_TEXTURE_2D
,
2531 GL_TEXTURE_POOL_CHROMIUM
,
2532 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2533 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2534 bool is_framebuffer_hint
=
2535 hints
[texture_id
- 1] & ResourceProvider::TextureHintFramebuffer
;
2536 EXPECT_CALL(*context
,
2537 texParameteri(GL_TEXTURE_2D
,
2538 GL_TEXTURE_USAGE_ANGLE
,
2539 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2540 .Times(is_framebuffer_hint
? 1 : 0);
2541 resource_provider
->CreateForTesting(id
);
2544 Mock::VerifyAndClearExpectations(context
);
2548 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2549 if (GetParam() != ResourceProvider::Bitmap
)
2552 gfx::Size
size(64, 64);
2553 const uint32_t kBadBeef
= 0xbadbeef;
2554 scoped_ptr
<SharedBitmap
> shared_bitmap(
2555 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2557 FakeOutputSurfaceClient output_surface_client
;
2558 scoped_ptr
<OutputSurface
> output_surface(
2559 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2560 new SoftwareOutputDevice
)));
2561 CHECK(output_surface
->BindToClient(&output_surface_client
));
2563 scoped_ptr
<ResourceProvider
> resource_provider(
2564 ResourceProvider::Create(output_surface
.get(),
2565 shared_bitmap_manager_
.get(),
2566 gpu_memory_buffer_manager_
.get(),
2567 main_thread_task_runner_
.get(),
2572 uint32 release_sync_point
= 0;
2573 bool lost_resource
= false;
2574 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2575 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2576 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2577 &release_sync_point
,
2579 &main_thread_task_runner
));
2580 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2582 ResourceProvider::ResourceId id
=
2583 resource_provider
->CreateResourceFromTextureMailbox(
2584 mailbox
, callback
.Pass());
2588 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2589 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2590 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2591 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2592 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2595 resource_provider
->DeleteResource(id
);
2596 EXPECT_EQ(0u, release_sync_point
);
2597 EXPECT_FALSE(lost_resource
);
2598 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2601 class ResourceProviderTestTextureMailboxGLFilters
2602 : public ResourceProviderTest
{
2604 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2605 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2606 BlockingTaskRunner
* main_thread_task_runner
,
2607 bool mailbox_nearest_neighbor
,
2608 GLenum sampler_filter
) {
2609 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2610 new TextureStateTrackingContext
);
2611 TextureStateTrackingContext
* context
= context_owned
.get();
2613 FakeOutputSurfaceClient output_surface_client
;
2614 scoped_ptr
<OutputSurface
> output_surface(
2615 FakeOutputSurface::Create3d(context_owned
.Pass()));
2616 CHECK(output_surface
->BindToClient(&output_surface_client
));
2618 scoped_ptr
<ResourceProvider
> resource_provider(
2619 ResourceProvider::Create(output_surface
.get(),
2620 shared_bitmap_manager
,
2621 gpu_memory_buffer_manager
,
2622 main_thread_task_runner
,
2627 unsigned texture_id
= 1;
2628 uint32 sync_point
= 30;
2629 unsigned target
= GL_TEXTURE_2D
;
2631 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2632 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2633 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2634 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2635 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2637 gpu::Mailbox gpu_mailbox
;
2638 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2639 uint32 release_sync_point
= 0;
2640 bool lost_resource
= false;
2641 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2642 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2643 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2644 &release_sync_point
,
2646 &mailbox_task_runner
));
2648 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2649 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2651 ResourceProvider::ResourceId id
=
2652 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2656 Mock::VerifyAndClearExpectations(context
);
2659 // Mailbox sync point WaitSyncPoint before using the texture.
2660 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2661 resource_provider
->WaitSyncPointIfNeeded(id
);
2662 Mock::VerifyAndClearExpectations(context
);
2664 // Using the texture does a consume of the mailbox.
2665 EXPECT_CALL(*context
, bindTexture(target
, texture_id
)).Times(2);
2666 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2668 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2669 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2671 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2672 // match |sampler_filter|.
2673 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2674 EXPECT_CALL(*context
, texParameteri(
2675 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2676 EXPECT_CALL(*context
, texParameteri(
2677 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2680 ResourceProvider::ScopedSamplerGL
lock(
2681 resource_provider
.get(), id
, sampler_filter
);
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);
2694 resource_provider
->DeleteResource(id
);
2695 EXPECT_EQ(0u, release_sync_point
);
2696 EXPECT_FALSE(lost_resource
);
2697 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2701 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2702 // Mailboxing is only supported for GL textures.
2703 if (GetParam() != ResourceProvider::GLTexture
)
2706 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2707 shared_bitmap_manager_
.get(),
2708 gpu_memory_buffer_manager_
.get(),
2709 main_thread_task_runner_
.get(),
2714 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2715 // Mailboxing is only supported for GL textures.
2716 if (GetParam() != ResourceProvider::GLTexture
)
2719 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2720 shared_bitmap_manager_
.get(),
2721 gpu_memory_buffer_manager_
.get(),
2722 main_thread_task_runner_
.get(),
2727 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2728 // Mailboxing is only supported for GL textures.
2729 if (GetParam() != ResourceProvider::GLTexture
)
2732 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2733 shared_bitmap_manager_
.get(),
2734 gpu_memory_buffer_manager_
.get(),
2735 main_thread_task_runner_
.get(),
2740 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2741 // Mailboxing is only supported for GL textures.
2742 if (GetParam() != ResourceProvider::GLTexture
)
2745 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2746 shared_bitmap_manager_
.get(),
2747 gpu_memory_buffer_manager_
.get(),
2748 main_thread_task_runner_
.get(),
2753 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2754 // Mailboxing is only supported for GL textures.
2755 if (GetParam() != ResourceProvider::GLTexture
)
2758 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2759 new TextureStateTrackingContext
);
2760 TextureStateTrackingContext
* context
= context_owned
.get();
2762 FakeOutputSurfaceClient output_surface_client
;
2763 scoped_ptr
<OutputSurface
> output_surface(
2764 FakeOutputSurface::Create3d(context_owned
.Pass()));
2765 CHECK(output_surface
->BindToClient(&output_surface_client
));
2767 scoped_ptr
<ResourceProvider
> resource_provider(
2768 ResourceProvider::Create(output_surface
.get(),
2769 shared_bitmap_manager_
.get(),
2770 gpu_memory_buffer_manager_
.get(),
2776 unsigned texture_id
= 1;
2777 uint32 sync_point
= 30;
2778 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2780 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2781 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2782 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2783 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2784 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2786 gpu::Mailbox gpu_mailbox
;
2787 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2788 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2789 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2791 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2793 ResourceProvider::ResourceId id
=
2794 resource_provider
->CreateResourceFromTextureMailbox(
2795 mailbox
, callback
.Pass());
2798 Mock::VerifyAndClearExpectations(context
);
2801 // Mailbox sync point WaitSyncPoint before using the texture.
2802 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2803 resource_provider
->WaitSyncPointIfNeeded(id
);
2804 Mock::VerifyAndClearExpectations(context
);
2806 // Using the texture does a consume of the mailbox.
2807 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2808 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2810 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2811 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2813 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2814 Mock::VerifyAndClearExpectations(context
);
2816 // When done with it, a sync point should be inserted, but no produce is
2818 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2819 EXPECT_CALL(*context
, insertSyncPoint());
2820 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2822 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2823 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2827 TEST_P(ResourceProviderTest
,
2828 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2829 // Mailboxing is only supported for GL textures.
2830 if (GetParam() != ResourceProvider::GLTexture
)
2833 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2834 new TextureStateTrackingContext
);
2835 TextureStateTrackingContext
* context
= context_owned
.get();
2837 FakeOutputSurfaceClient output_surface_client
;
2838 scoped_ptr
<OutputSurface
> output_surface(
2839 FakeOutputSurface::Create3d(context_owned
.Pass()));
2840 CHECK(output_surface
->BindToClient(&output_surface_client
));
2842 scoped_ptr
<ResourceProvider
> resource_provider(
2843 ResourceProvider::Create(output_surface
.get(),
2844 shared_bitmap_manager_
.get(),
2845 gpu_memory_buffer_manager_
.get(),
2851 uint32 sync_point
= 30;
2852 unsigned target
= GL_TEXTURE_2D
;
2854 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2855 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2856 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2857 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2858 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2860 gpu::Mailbox gpu_mailbox
;
2861 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2862 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2863 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2865 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2867 ResourceProvider::ResourceId id
=
2868 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2872 Mock::VerifyAndClearExpectations(context
);
2875 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2876 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2877 resource_provider
->WaitSyncPointIfNeeded(id
);
2878 Mock::VerifyAndClearExpectations(context
);
2880 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2881 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2882 resource_provider
->WaitSyncPointIfNeeded(id
);
2883 Mock::VerifyAndClearExpectations(context
);
2887 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2888 // Mailboxing is only supported for GL textures.
2889 if (GetParam() != ResourceProvider::GLTexture
)
2892 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2893 new TextureStateTrackingContext
);
2894 TextureStateTrackingContext
* context
= context_owned
.get();
2896 FakeOutputSurfaceClient output_surface_client
;
2897 scoped_ptr
<OutputSurface
> output_surface(
2898 FakeOutputSurface::Create3d(context_owned
.Pass()));
2899 CHECK(output_surface
->BindToClient(&output_surface_client
));
2901 scoped_ptr
<ResourceProvider
> resource_provider(
2902 ResourceProvider::Create(output_surface
.get(),
2903 shared_bitmap_manager_
.get(),
2904 gpu_memory_buffer_manager_
.get(),
2910 uint32 sync_point
= 0;
2911 unsigned target
= GL_TEXTURE_2D
;
2913 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2914 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2915 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2916 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2917 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2919 gpu::Mailbox gpu_mailbox
;
2920 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2921 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2922 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2924 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2926 ResourceProvider::ResourceId id
=
2927 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2931 Mock::VerifyAndClearExpectations(context
);
2934 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2935 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2936 resource_provider
->WaitSyncPointIfNeeded(id
);
2937 Mock::VerifyAndClearExpectations(context
);
2941 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2943 MOCK_METHOD0(NextTextureId
, GLuint());
2944 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2945 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2946 MOCK_METHOD5(texStorage2DEXT
,
2949 GLuint internalformat
,
2952 MOCK_METHOD9(texImage2D
,
2955 GLenum internalformat
,
2961 const void* pixels
));
2962 MOCK_METHOD9(texSubImage2D
,
2971 const void* pixels
));
2972 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2975 GLenum internalformat
,
2981 const void* pixels
));
2982 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2991 const void* pixels
));
2992 MOCK_METHOD8(compressedTexImage2D
,
2995 GLenum internalformat
,
3001 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3002 MOCK_METHOD4(createImageCHROMIUM
,
3003 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3004 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3005 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3006 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3008 // We're mocking bindTexture, so we override
3009 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3010 // currently bound texture.
3011 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3014 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3015 // Only for GL textures.
3016 if (GetParam() != ResourceProvider::GLTexture
)
3018 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3019 new StrictMock
<AllocationTrackingContext3D
>);
3020 AllocationTrackingContext3D
* context
= context_owned
.get();
3022 FakeOutputSurfaceClient output_surface_client
;
3023 scoped_ptr
<OutputSurface
> output_surface(
3024 FakeOutputSurface::Create3d(context_owned
.Pass()));
3025 CHECK(output_surface
->BindToClient(&output_surface_client
));
3027 scoped_ptr
<ResourceProvider
> resource_provider(
3028 ResourceProvider::Create(output_surface
.get(),
3029 shared_bitmap_manager_
.get(),
3030 gpu_memory_buffer_manager_
.get(),
3036 gfx::Size
size(2, 2);
3037 gfx::Vector2d
offset(0, 0);
3038 gfx::Rect
rect(0, 0, 2, 2);
3039 ResourceFormat format
= RGBA_8888
;
3040 ResourceProvider::ResourceId id
= 0;
3041 uint8_t pixels
[16] = { 0 };
3042 int texture_id
= 123;
3044 // Lazy allocation. Don't allocate when creating the resource.
3045 id
= resource_provider
->CreateResource(
3046 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3048 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3049 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3050 resource_provider
->CreateForTesting(id
);
3052 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3053 resource_provider
->DeleteResource(id
);
3055 Mock::VerifyAndClearExpectations(context
);
3057 // Do allocate when we set the pixels.
3058 id
= resource_provider
->CreateResource(
3059 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3061 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3062 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3063 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3064 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3065 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
3067 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3068 resource_provider
->DeleteResource(id
);
3070 Mock::VerifyAndClearExpectations(context
);
3072 // Same for async version.
3073 id
= resource_provider
->CreateResource(
3074 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3075 resource_provider
->AcquirePixelBuffer(id
);
3077 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3078 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3079 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3081 resource_provider
->BeginSetPixels(id
);
3082 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3084 resource_provider
->ReleasePixelBuffer(id
);
3086 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3087 resource_provider
->DeleteResource(id
);
3089 Mock::VerifyAndClearExpectations(context
);
3092 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3093 // Only for GL textures.
3094 if (GetParam() != ResourceProvider::GLTexture
)
3096 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3097 new StrictMock
<AllocationTrackingContext3D
>);
3098 AllocationTrackingContext3D
* context
= context_owned
.get();
3099 context
->set_support_texture_storage(true);
3100 context
->set_support_texture_usage(true);
3102 FakeOutputSurfaceClient output_surface_client
;
3103 scoped_ptr
<OutputSurface
> output_surface(
3104 FakeOutputSurface::Create3d(context_owned
.Pass()));
3105 CHECK(output_surface
->BindToClient(&output_surface_client
));
3107 scoped_ptr
<ResourceProvider
> resource_provider(
3108 ResourceProvider::Create(output_surface
.get(),
3109 shared_bitmap_manager_
.get(),
3110 gpu_memory_buffer_manager_
.get(),
3116 gfx::Size
size(2, 2);
3118 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3119 const ResourceProvider::TextureHint hints
[4] = {
3120 ResourceProvider::TextureHintDefault
,
3121 ResourceProvider::TextureHintImmutable
,
3122 ResourceProvider::TextureHintFramebuffer
,
3123 ResourceProvider::TextureHintImmutableFramebuffer
,
3125 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3126 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3127 // Lazy allocation. Don't allocate when creating the resource.
3128 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3129 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3131 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3132 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3133 bool is_immutable_hint
=
3134 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3135 bool support_immutable_texture
=
3136 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3137 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3138 .Times(support_immutable_texture
? 1 : 0);
3139 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3140 .Times(support_immutable_texture
? 0 : 1);
3141 resource_provider
->AllocateForTesting(id
);
3143 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3144 resource_provider
->DeleteResource(id
);
3146 Mock::VerifyAndClearExpectations(context
);
3151 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3152 // Only for GL textures.
3153 if (GetParam() != ResourceProvider::GLTexture
)
3155 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3156 new StrictMock
<AllocationTrackingContext3D
>);
3157 AllocationTrackingContext3D
* context
= context_owned
.get();
3158 context
->set_support_texture_format_bgra8888(true);
3159 context
->set_support_texture_storage(true);
3160 context
->set_support_texture_usage(true);
3162 FakeOutputSurfaceClient output_surface_client
;
3163 scoped_ptr
<OutputSurface
> output_surface(
3164 FakeOutputSurface::Create3d(context_owned
.Pass()));
3165 CHECK(output_surface
->BindToClient(&output_surface_client
));
3167 scoped_ptr
<ResourceProvider
> resource_provider(
3168 ResourceProvider::Create(output_surface
.get(),
3169 shared_bitmap_manager_
.get(),
3170 gpu_memory_buffer_manager_
.get(),
3176 gfx::Size
size(2, 2);
3177 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3179 const ResourceProvider::TextureHint hints
[4] = {
3180 ResourceProvider::TextureHintDefault
,
3181 ResourceProvider::TextureHintImmutable
,
3182 ResourceProvider::TextureHintFramebuffer
,
3183 ResourceProvider::TextureHintImmutableFramebuffer
,
3185 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3186 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3187 // Lazy allocation. Don't allocate when creating the resource.
3188 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3189 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3191 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3192 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3193 bool is_immutable_hint
=
3194 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3195 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3196 .Times(is_immutable_hint
? 1 : 0);
3197 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3198 .Times(is_immutable_hint
? 0 : 1);
3199 resource_provider
->AllocateForTesting(id
);
3201 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3202 resource_provider
->DeleteResource(id
);
3204 Mock::VerifyAndClearExpectations(context
);
3209 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3210 if (GetParam() != ResourceProvider::GLTexture
)
3212 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3213 new StrictMock
<AllocationTrackingContext3D
>);
3214 AllocationTrackingContext3D
* context
= context_owned
.get();
3216 FakeOutputSurfaceClient output_surface_client
;
3217 scoped_ptr
<OutputSurface
> output_surface(
3218 FakeOutputSurface::Create3d(context_owned
.Pass()));
3219 CHECK(output_surface
->BindToClient(&output_surface_client
));
3221 gfx::Size
size(2, 2);
3222 ResourceFormat format
= RGBA_8888
;
3223 ResourceProvider::ResourceId id
= 0;
3224 int texture_id
= 123;
3226 scoped_ptr
<ResourceProvider
> resource_provider(
3227 ResourceProvider::Create(output_surface
.get(),
3228 shared_bitmap_manager_
.get(),
3229 gpu_memory_buffer_manager_
.get(),
3235 id
= resource_provider
->CreateResource(
3236 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3237 resource_provider
->AcquirePixelBuffer(id
);
3239 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3240 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3241 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3243 resource_provider
->BeginSetPixels(id
);
3245 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3247 resource_provider
->ReleasePixelBuffer(id
);
3249 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3250 resource_provider
->DeleteResource(id
);
3252 Mock::VerifyAndClearExpectations(context
);
3255 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3256 // Only for GL textures.
3257 if (GetParam() != ResourceProvider::GLTexture
)
3259 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3260 new StrictMock
<AllocationTrackingContext3D
>);
3261 AllocationTrackingContext3D
* context
= context_owned
.get();
3263 FakeOutputSurfaceClient output_surface_client
;
3264 scoped_ptr
<OutputSurface
> output_surface(
3265 FakeOutputSurface::Create3d(context_owned
.Pass()));
3266 CHECK(output_surface
->BindToClient(&output_surface_client
));
3268 gfx::Size
size(2, 2);
3269 ResourceFormat format
= RGBA_8888
;
3270 ResourceProvider::ResourceId id
= 0;
3271 int texture_id
= 123;
3273 scoped_ptr
<ResourceProvider
> resource_provider(
3274 ResourceProvider::Create(output_surface
.get(),
3275 shared_bitmap_manager_
.get(),
3276 gpu_memory_buffer_manager_
.get(),
3282 id
= resource_provider
->CreateResource(
3283 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3284 resource_provider
->AcquirePixelBuffer(id
);
3286 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3287 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3288 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3290 resource_provider
->BeginSetPixels(id
);
3292 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3293 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3294 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3295 resource_provider
->ForceSetPixelsToComplete(id
);
3297 resource_provider
->ReleasePixelBuffer(id
);
3299 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3300 resource_provider
->DeleteResource(id
);
3302 Mock::VerifyAndClearExpectations(context
);
3305 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3306 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3307 new NiceMock
<AllocationTrackingContext3D
>);
3308 AllocationTrackingContext3D
* context
= context_owned
.get();
3310 FakeOutputSurfaceClient output_surface_client
;
3311 scoped_ptr
<OutputSurface
> output_surface(
3312 FakeOutputSurface::Create3d(context_owned
.Pass()));
3313 CHECK(output_surface
->BindToClient(&output_surface_client
));
3315 gfx::Size
size(2, 2);
3316 ResourceFormat format
= RGBA_8888
;
3317 ResourceProvider::ResourceId id
= 0;
3318 int texture_id
= 123;
3320 scoped_ptr
<ResourceProvider
> resource_provider(
3321 ResourceProvider::Create(output_surface
.get(),
3322 shared_bitmap_manager_
.get(),
3323 gpu_memory_buffer_manager_
.get(),
3329 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3331 id
= resource_provider
->CreateResource(
3332 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3333 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3334 GL_INNOCENT_CONTEXT_RESET_ARB
);
3336 resource_provider
->AcquirePixelBuffer(id
);
3338 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3339 EXPECT_FALSE(buffer
);
3340 resource_provider
->UnmapPixelBuffer(id
);
3341 Mock::VerifyAndClearExpectations(context
);
3344 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3345 // Only for GL textures.
3346 if (GetParam() != ResourceProvider::GLTexture
)
3348 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3349 new StrictMock
<AllocationTrackingContext3D
>);
3350 AllocationTrackingContext3D
* context
= context_owned
.get();
3352 FakeOutputSurfaceClient output_surface_client
;
3353 scoped_ptr
<OutputSurface
> output_surface(
3354 FakeOutputSurface::Create3d(context_owned
.Pass()));
3355 CHECK(output_surface
->BindToClient(&output_surface_client
));
3357 const int kWidth
= 2;
3358 const int kHeight
= 2;
3359 gfx::Size
size(kWidth
, kHeight
);
3360 ResourceFormat format
= RGBA_8888
;
3361 ResourceProvider::ResourceId id
= 0;
3362 const unsigned kTextureId
= 123u;
3363 const unsigned kImageId
= 234u;
3365 scoped_ptr
<ResourceProvider
> resource_provider(
3366 ResourceProvider::Create(output_surface
.get(),
3367 shared_bitmap_manager_
.get(),
3368 gpu_memory_buffer_manager_
.get(),
3374 id
= resource_provider
->CreateResource(
3375 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3377 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3378 .WillOnce(Return(kImageId
))
3379 .RetiresOnSaturation();
3381 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3382 resource_provider
.get(), id
);
3383 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3386 EXPECT_CALL(*context
, NextTextureId())
3387 .WillOnce(Return(kTextureId
))
3388 .RetiresOnSaturation();
3389 // Once in CreateTextureId and once in BindForSampling
3390 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3391 .RetiresOnSaturation();
3392 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3394 .RetiresOnSaturation();
3396 ResourceProvider::ScopedSamplerGL
lock_gl(
3397 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3398 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3402 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3403 resource_provider
.get(), id
);
3404 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3407 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3408 .RetiresOnSaturation();
3409 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3411 .RetiresOnSaturation();
3412 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3414 .RetiresOnSaturation();
3415 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3417 .RetiresOnSaturation();
3419 ResourceProvider::ScopedSamplerGL
lock_gl(
3420 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3421 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3424 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3426 .RetiresOnSaturation();
3429 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3430 if (GetParam() != ResourceProvider::GLTexture
)
3432 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3433 new StrictMock
<AllocationTrackingContext3D
>);
3434 AllocationTrackingContext3D
* context
= context_owned
.get();
3435 context_owned
->set_support_sync_query(true);
3437 FakeOutputSurfaceClient output_surface_client
;
3438 scoped_ptr
<OutputSurface
> output_surface(
3439 FakeOutputSurface::Create3d(context_owned
.Pass()));
3440 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3442 const int kWidth
= 2;
3443 const int kHeight
= 2;
3444 gfx::Size
size(kWidth
, kHeight
);
3445 ResourceFormat format
= RGBA_8888
;
3446 ResourceProvider::ResourceId source_id
= 0;
3447 ResourceProvider::ResourceId dest_id
= 0;
3448 const unsigned kSourceTextureId
= 123u;
3449 const unsigned kDestTextureId
= 321u;
3450 const unsigned kImageId
= 234u;
3452 scoped_ptr
<ResourceProvider
> resource_provider(
3453 ResourceProvider::Create(output_surface
.get(),
3454 shared_bitmap_manager_
.get(),
3455 gpu_memory_buffer_manager_
.get(),
3461 source_id
= resource_provider
->CreateResource(
3462 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3464 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3465 .WillOnce(Return(kImageId
))
3466 .RetiresOnSaturation();
3468 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3469 resource_provider
.get(), source_id
);
3470 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3472 Mock::VerifyAndClearExpectations(context
);
3474 dest_id
= resource_provider
->CreateResource(
3475 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3477 EXPECT_CALL(*context
, NextTextureId())
3478 .WillOnce(Return(kDestTextureId
))
3479 .RetiresOnSaturation();
3480 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3482 .RetiresOnSaturation();
3483 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3484 GL_UNSIGNED_BYTE
, nullptr))
3486 .RetiresOnSaturation();
3487 EXPECT_CALL(*context
, NextTextureId())
3488 .WillOnce(Return(kSourceTextureId
))
3489 .RetiresOnSaturation();
3490 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3492 .RetiresOnSaturation();
3493 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3495 .RetiresOnSaturation();
3496 resource_provider
->CopyResource(source_id
, dest_id
);
3497 Mock::VerifyAndClearExpectations(context
);
3499 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3507 .RetiresOnSaturation();
3508 resource_provider
->DeleteResource(source_id
);
3509 resource_provider
->DeleteResource(dest_id
);
3512 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3513 ResourceProvider
* resource_provider
,
3514 FakeOutputSurface
* output_surface
) {
3515 scoped_ptr
<ResourceProviderContext
> context_owned
=
3516 ResourceProviderContext::Create(shared_data
);
3517 ResourceProviderContext
* context
= context_owned
.get();
3519 scoped_refptr
<TestContextProvider
> context_provider
=
3520 TestContextProvider::Create(context_owned
.Pass());
3521 output_surface
->InitializeAndSetContext3d(context_provider
);
3522 resource_provider
->InitializeGL();
3524 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3527 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3528 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3529 bool delegated_rendering
= false;
3530 scoped_ptr
<FakeOutputSurface
> output_surface(
3531 FakeOutputSurface::CreateDeferredGL(
3532 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3533 delegated_rendering
));
3534 FakeOutputSurfaceClient
client(output_surface
.get());
3535 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3536 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3537 new TestSharedBitmapManager());
3538 scoped_ptr
<ResourceProvider
> resource_provider(
3539 ResourceProvider::Create(output_surface
.get(),
3540 shared_bitmap_manager
.get(),
3547 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3549 InitializeGLAndCheck(shared_data
.get(),
3550 resource_provider
.get(),
3551 output_surface
.get());
3553 resource_provider
->InitializeSoftware();
3554 output_surface
->ReleaseGL();
3555 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3557 InitializeGLAndCheck(shared_data
.get(),
3558 resource_provider
.get(),
3559 output_surface
.get());
3562 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3563 if (GetParam() != ResourceProvider::GLTexture
)
3566 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3567 new AllocationTrackingContext3D
);
3568 AllocationTrackingContext3D
* context
= context_owned
.get();
3569 context_owned
->set_support_compressed_texture_etc1(true);
3571 FakeOutputSurfaceClient output_surface_client
;
3572 scoped_ptr
<OutputSurface
> output_surface(
3573 FakeOutputSurface::Create3d(context_owned
.Pass()));
3574 CHECK(output_surface
->BindToClient(&output_surface_client
));
3576 gfx::Size
size(4, 4);
3577 scoped_ptr
<ResourceProvider
> resource_provider(
3578 ResourceProvider::Create(output_surface
.get(),
3579 shared_bitmap_manager_
.get(),
3580 gpu_memory_buffer_manager_
.get(),
3585 int texture_id
= 123;
3587 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3588 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3590 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3591 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3592 resource_provider
->AllocateForTesting(id
);
3594 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3595 resource_provider
->DeleteResource(id
);
3598 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3599 if (GetParam() != ResourceProvider::GLTexture
)
3602 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3603 new AllocationTrackingContext3D
);
3604 AllocationTrackingContext3D
* context
= context_owned
.get();
3605 context_owned
->set_support_compressed_texture_etc1(true);
3607 FakeOutputSurfaceClient output_surface_client
;
3608 scoped_ptr
<OutputSurface
> output_surface(
3609 FakeOutputSurface::Create3d(context_owned
.Pass()));
3610 CHECK(output_surface
->BindToClient(&output_surface_client
));
3612 gfx::Size
size(4, 4);
3613 scoped_ptr
<ResourceProvider
> resource_provider(
3614 ResourceProvider::Create(output_surface
.get(),
3615 shared_bitmap_manager_
.get(),
3616 gpu_memory_buffer_manager_
.get(),
3621 int texture_id
= 123;
3624 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3625 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3627 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3628 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3629 EXPECT_CALL(*context
,
3630 compressedTexImage2D(
3631 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3632 resource_provider
->SetPixels(
3633 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3635 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3636 resource_provider
->DeleteResource(id
);
3639 INSTANTIATE_TEST_CASE_P(
3640 ResourceProviderTests
,
3641 ResourceProviderTest
,
3642 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3644 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3646 GLuint
NextTextureId() override
{
3647 base::AutoLock
lock(namespace_
->lock
);
3648 return namespace_
->next_texture_id
++;
3650 void RetireTextureId(GLuint
) override
{}
3651 GLuint
PeekTextureId() {
3652 base::AutoLock
lock(namespace_
->lock
);
3653 return namespace_
->next_texture_id
;
3657 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3658 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3659 new TextureIdAllocationTrackingContext
);
3660 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3662 FakeOutputSurfaceClient output_surface_client
;
3663 scoped_ptr
<OutputSurface
> output_surface(
3664 FakeOutputSurface::Create3d(context_owned
.Pass()));
3665 CHECK(output_surface
->BindToClient(&output_surface_client
));
3666 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3667 new TestSharedBitmapManager());
3669 gfx::Size
size(1, 1);
3670 ResourceFormat format
= RGBA_8888
;
3673 size_t kTextureAllocationChunkSize
= 1;
3674 scoped_ptr
<ResourceProvider
> resource_provider(
3675 ResourceProvider::Create(output_surface
.get(),
3676 shared_bitmap_manager
.get(),
3681 kTextureAllocationChunkSize
));
3683 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3684 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3685 resource_provider
->AllocateForTesting(id
);
3686 Mock::VerifyAndClearExpectations(context
);
3688 DCHECK_EQ(2u, context
->PeekTextureId());
3689 resource_provider
->DeleteResource(id
);
3693 size_t kTextureAllocationChunkSize
= 8;
3694 scoped_ptr
<ResourceProvider
> resource_provider(
3695 ResourceProvider::Create(output_surface
.get(),
3696 shared_bitmap_manager
.get(),
3701 kTextureAllocationChunkSize
));
3703 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3704 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3705 resource_provider
->AllocateForTesting(id
);
3706 Mock::VerifyAndClearExpectations(context
);
3708 DCHECK_EQ(10u, context
->PeekTextureId());
3709 resource_provider
->DeleteResource(id
);