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_METHOD3(produceTextureDirectCHROMIUM
,
101 void(GLuint texture
, GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM
,
103 unsigned(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 produceTextureDirectCHROMIUM(GLuint texture
,
263 const GLbyte
* mailbox
) override
{
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= UnboundTexture(texture
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 GLuint
createAndConsumeTextureCHROMIUM(GLenum target
,
275 const GLbyte
* mailbox
) override
{
276 GLuint texture_id
= createTexture();
277 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
278 scoped_refptr
<TestTexture
> texture
=
279 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
280 namespace_
->textures
.Replace(texture_id
, texture
);
284 void GetPixels(const gfx::Size
& size
,
285 ResourceFormat format
,
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
289 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
290 ASSERT_EQ(texture
->size
, size
);
291 ASSERT_EQ(texture
->format
, format
);
292 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
296 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
297 : shared_data_(shared_data
),
298 last_waited_sync_point_(0) {}
301 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
302 CheckTextureIsBound(GL_TEXTURE_2D
);
303 ResourceFormat texture_format
= RGBA_8888
;
306 texture_format
= RGBA_8888
;
309 texture_format
= BGRA_8888
;
312 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
313 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
316 void SetPixels(int xoffset
,
320 const void* pixels
) {
321 CheckTextureIsBound(GL_TEXTURE_2D
);
322 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
323 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
324 ASSERT_TRUE(texture
->data
.get());
325 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
326 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
328 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
330 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
331 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
332 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
333 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
334 for (int i
= 0; i
< height
; ++i
) {
335 memcpy(dest
, src
, in_pitch
);
341 struct PendingProduceTexture
{
342 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
343 scoped_refptr
<TestTexture
> texture
;
345 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
346 ContextSharedData
* shared_data_
;
347 GLuint last_waited_sync_point_
;
348 PendingProduceTextureList pending_produce_textures_
;
351 void GetResourcePixels(ResourceProvider
* resource_provider
,
352 ResourceProviderContext
* context
,
354 const gfx::Size
& size
,
355 ResourceFormat format
,
357 resource_provider
->WaitSyncPointIfNeeded(id
);
358 switch (resource_provider
->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
360 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
361 ASSERT_NE(0U, lock_gl
.texture_id());
362 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
363 context
->GetPixels(size
, format
, pixels
);
366 case ResourceProvider::RESOURCE_TYPE_BITMAP
: {
367 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
370 lock_software
.sk_bitmap()->getPixels(),
371 lock_software
.sk_bitmap()->getSize());
377 class ResourceProviderTest
378 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
380 explicit ResourceProviderTest(bool child_needs_sync_point
)
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL
),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
387 scoped_ptr
<ResourceProviderContext
> context3d(
388 ResourceProviderContext::Create(shared_data_
.get()));
389 context3d_
= context3d
.get();
391 scoped_refptr
<TestContextProvider
> context_provider
=
392 TestContextProvider::Create(context3d
.Pass());
394 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
396 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
397 ResourceProviderContext::Create(shared_data_
.get());
398 child_context_
= child_context_owned
.get();
399 if (child_needs_sync_point
) {
400 child_output_surface_
=
401 FakeOutputSurface::Create3d(child_context_owned
.Pass());
403 child_output_surface_
= FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned
.Pass());
408 case ResourceProvider::RESOURCE_TYPE_BITMAP
:
409 output_surface_
= FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice
));
411 child_output_surface_
= FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice
));
415 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
416 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
418 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
419 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
422 ResourceProvider::Create(output_surface_
.get(),
423 shared_bitmap_manager_
.get(),
424 gpu_memory_buffer_manager_
.get(),
425 main_thread_task_runner_
.get(),
429 child_resource_provider_
=
430 ResourceProvider::Create(child_output_surface_
.get(),
431 shared_bitmap_manager_
.get(),
432 gpu_memory_buffer_manager_
.get(),
433 main_thread_task_runner_
.get(),
439 ResourceProviderTest() : ResourceProviderTest(true) {}
441 static void CollectResources(ReturnedResourceArray
* array
,
442 const ReturnedResourceArray
& returned
,
443 BlockingTaskRunner
* main_thread_task_runner
) {
444 array
->insert(array
->end(), returned
.begin(), returned
.end());
447 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
448 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
451 static void SetResourceFilter(ResourceProvider
* resource_provider
,
454 ResourceProvider::ScopedSamplerGL
sampler(
455 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
458 ResourceProviderContext
* context() { return context3d_
; }
460 ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
462 bool* release_called
,
463 uint32
* sync_point
) {
464 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
465 unsigned texture
= child_context_
->createTexture();
466 gpu::Mailbox gpu_mailbox
;
467 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
468 child_context_
->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
,
470 *sync_point
= child_context_
->insertSyncPoint();
471 EXPECT_LT(0u, *sync_point
);
473 scoped_ptr
<SharedBitmap
> shared_bitmap
;
474 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
475 SingleReleaseCallbackImpl::Create(base::Bind(
476 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
477 release_called
, release_sync_point
, lost_resource
));
478 return child_resource_provider_
->CreateResourceFromTextureMailbox(
479 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
482 gfx::Size
size(64, 64);
483 scoped_ptr
<SharedBitmap
> shared_bitmap(
484 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
486 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
487 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
488 SingleReleaseCallbackImpl::Create(base::Bind(
489 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
490 release_called
, release_sync_point
, lost_resource
));
491 return child_resource_provider_
->CreateResourceFromTextureMailbox(
492 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
497 scoped_ptr
<ContextSharedData
> shared_data_
;
498 ResourceProviderContext
* context3d_
;
499 ResourceProviderContext
* child_context_
;
500 FakeOutputSurfaceClient output_surface_client_
;
501 FakeOutputSurfaceClient child_output_surface_client_
;
502 scoped_ptr
<OutputSurface
> output_surface_
;
503 scoped_ptr
<OutputSurface
> child_output_surface_
;
504 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
505 scoped_ptr
<ResourceProvider
> resource_provider_
;
506 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
507 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
508 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
511 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
512 ResourceProvider
* resource_provider
,
513 ResourceProviderContext
* context
) {
514 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
516 gfx::Size
size(1, 1);
517 ResourceFormat format
= RGBA_8888
;
518 size_t pixel_size
= TextureSizeBytes(size
, format
);
519 ASSERT_EQ(4U, pixel_size
);
521 ResourceId id
= resource_provider
->CreateResource(
522 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
523 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
524 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
525 EXPECT_EQ(0u, context
->NumTextures());
527 uint8_t data
[4] = { 1, 2, 3, 4 };
528 resource_provider
->CopyToResource(id
, data
, size
);
529 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
530 EXPECT_EQ(1u, context
->NumTextures());
532 uint8_t result
[4] = { 0 };
533 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
534 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
536 resource_provider
->DeleteResource(id
);
537 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
538 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
539 EXPECT_EQ(0u, context
->NumTextures());
542 TEST_P(ResourceProviderTest
, Basic
) {
543 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
546 TEST_P(ResourceProviderTest
, Upload
) {
547 gfx::Size
size(2, 2);
548 ResourceFormat format
= RGBA_8888
;
549 size_t pixel_size
= TextureSizeBytes(size
, format
);
550 ASSERT_EQ(16U, pixel_size
);
552 ResourceId id
= resource_provider_
->CreateResource(
553 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
555 uint8_t image
[16] = { 0 };
556 gfx::Rect
image_rect(size
);
557 resource_provider_
->SetPixels(
558 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
560 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
563 uint8_t result
[16] = { 0 };
565 gfx::Rect
source_rect(0, 0, 1, 1);
566 gfx::Vector2d
dest_offset(0, 0);
567 resource_provider_
->SetPixels(
568 id
, image
, image_rect
, source_rect
, dest_offset
);
570 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
572 resource_provider_
.get(), context(), id
, size
, format
, result
);
573 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
576 gfx::Rect
source_rect(0, 0, 1, 1);
577 gfx::Vector2d
dest_offset(1, 1);
578 resource_provider_
->SetPixels(
579 id
, image
, image_rect
, source_rect
, dest_offset
);
581 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
583 resource_provider_
.get(), context(), id
, size
, format
, result
);
584 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
587 gfx::Rect
source_rect(1, 0, 1, 1);
588 gfx::Vector2d
dest_offset(0, 1);
589 resource_provider_
->SetPixels(
590 id
, image
, image_rect
, source_rect
, dest_offset
);
592 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
594 resource_provider_
.get(), context(), id
, size
, format
, result
);
595 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
598 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
599 gfx::Rect
source_rect(100, 100, 1, 1);
600 gfx::Vector2d
dest_offset(1, 0);
601 resource_provider_
->SetPixels(
602 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
604 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
606 resource_provider_
.get(), context(), id
, size
, format
, result
);
607 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
610 resource_provider_
->DeleteResource(id
);
613 TEST_P(ResourceProviderTest
, SimpleUpload
) {
614 gfx::Size
size(2, 2);
615 ResourceFormat format
= RGBA_8888
;
616 size_t pixel_size
= TextureSizeBytes(size
, format
);
617 ASSERT_EQ(16U, pixel_size
);
619 ResourceId id
= resource_provider_
->CreateResource(
620 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
622 uint8_t image
[16] = {0};
623 resource_provider_
->CopyToResource(id
, image
, size
);
625 uint8_t result
[16] = {0};
626 uint8_t expected
[16] = {0};
627 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
629 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
632 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
634 resource_provider_
->CopyToResource(id
, image
, size
);
636 uint8_t result
[16] = {0};
637 uint8_t expected
[16] = {
638 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
639 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
641 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
645 TEST_P(ResourceProviderTest
, TransferGLResources
) {
646 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
648 gfx::Size
size(1, 1);
649 ResourceFormat format
= RGBA_8888
;
650 size_t pixel_size
= TextureSizeBytes(size
, format
);
651 ASSERT_EQ(4U, pixel_size
);
653 ResourceId id1
= child_resource_provider_
->CreateResource(
654 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
655 uint8_t data1
[4] = { 1, 2, 3, 4 };
656 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
658 ResourceId id2
= child_resource_provider_
->CreateResource(
659 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
660 uint8_t data2
[4] = { 5, 5, 5, 5 };
661 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
663 ResourceId id3
= child_resource_provider_
->CreateResource(
664 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
666 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
667 child_resource_provider_
.get(), id3
);
668 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
671 GLuint external_texture_id
= child_context_
->createExternalTexture();
673 gpu::Mailbox external_mailbox
;
674 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
675 child_context_
->produceTextureDirectCHROMIUM(
676 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
677 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
678 ResourceId id4
= child_resource_provider_
->CreateResourceFromTextureMailbox(
679 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
680 external_sync_point
),
681 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
683 ReturnedResourceArray returned_to_child
;
685 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
687 // Transfer some resources to the parent.
688 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
689 resource_ids_to_transfer
.push_back(id1
);
690 resource_ids_to_transfer
.push_back(id2
);
691 resource_ids_to_transfer
.push_back(id3
);
692 resource_ids_to_transfer
.push_back(id4
);
693 TransferableResourceArray list
;
694 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
696 ASSERT_EQ(4u, list
.size());
697 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
698 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
699 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
700 list
[1].mailbox_holder
.sync_point
);
701 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
702 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
703 list
[2].mailbox_holder
.sync_point
);
704 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
705 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
706 list
[0].mailbox_holder
.texture_target
);
707 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
708 list
[1].mailbox_holder
.texture_target
);
709 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
710 list
[2].mailbox_holder
.texture_target
);
711 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
712 list
[3].mailbox_holder
.texture_target
);
713 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
714 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
715 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
716 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
717 resource_provider_
->ReceiveFromChild(child_id
, list
);
718 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
719 context3d_
->last_waited_sync_point());
721 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
722 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
725 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
726 context3d_
->last_waited_sync_point());
727 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
728 resource_ids_to_receive
.insert(id1
);
729 resource_ids_to_receive
.insert(id2
);
730 resource_ids_to_receive
.insert(id3
);
731 resource_ids_to_receive
.insert(id4
);
732 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
733 resource_ids_to_receive
);
736 EXPECT_EQ(4u, resource_provider_
->num_resources());
737 ResourceProvider::ResourceIdMap resource_map
=
738 resource_provider_
->GetChildToParentMap(child_id
);
739 ResourceId mapped_id1
= resource_map
[id1
];
740 ResourceId mapped_id2
= resource_map
[id2
];
741 ResourceId mapped_id3
= resource_map
[id3
];
742 ResourceId mapped_id4
= resource_map
[id4
];
743 EXPECT_NE(0u, mapped_id1
);
744 EXPECT_NE(0u, mapped_id2
);
745 EXPECT_NE(0u, mapped_id3
);
746 EXPECT_NE(0u, mapped_id4
);
747 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
748 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
749 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
750 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
752 uint8_t result
[4] = { 0 };
754 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
755 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
758 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
759 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
762 // Check that transfering again the same resource from the child to the
764 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
765 resource_ids_to_transfer
.push_back(id1
);
766 resource_ids_to_transfer
.push_back(id2
);
767 resource_ids_to_transfer
.push_back(id3
);
768 TransferableResourceArray list
;
769 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
771 EXPECT_EQ(3u, list
.size());
772 EXPECT_EQ(id1
, list
[0].id
);
773 EXPECT_EQ(id2
, list
[1].id
);
774 EXPECT_EQ(id3
, list
[2].id
);
775 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
776 list
[0].mailbox_holder
.texture_target
);
777 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
778 list
[1].mailbox_holder
.texture_target
);
779 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
780 list
[2].mailbox_holder
.texture_target
);
781 ReturnedResourceArray returned
;
782 TransferableResource::ReturnResources(list
, &returned
);
783 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
784 // ids were exported twice, we returned them only once, they should still
786 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
787 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
788 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
791 EXPECT_EQ(0u, returned_to_child
.size());
793 // Transfer resources back from the parent to the child. Set no resources as
795 ResourceProvider::ResourceIdSet no_resources
;
796 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
798 ASSERT_EQ(4u, returned_to_child
.size());
799 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
800 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
801 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
802 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
803 EXPECT_FALSE(returned_to_child
[0].lost
);
804 EXPECT_FALSE(returned_to_child
[1].lost
);
805 EXPECT_FALSE(returned_to_child
[2].lost
);
806 EXPECT_FALSE(returned_to_child
[3].lost
);
807 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
808 returned_to_child
.clear();
810 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
811 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
812 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
813 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
816 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
817 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
819 ASSERT_NE(0U, lock
.texture_id());
820 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
821 child_context_
->GetPixels(size
, format
, result
);
822 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
825 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
826 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
828 ASSERT_NE(0U, lock
.texture_id());
829 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
830 child_context_
->GetPixels(size
, format
, result
);
831 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
834 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
835 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
837 ASSERT_NE(0U, lock
.texture_id());
838 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
841 // Transfer resources to the parent again.
842 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
843 resource_ids_to_transfer
.push_back(id1
);
844 resource_ids_to_transfer
.push_back(id2
);
845 resource_ids_to_transfer
.push_back(id3
);
846 resource_ids_to_transfer
.push_back(id4
);
847 TransferableResourceArray list
;
848 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
850 ASSERT_EQ(4u, list
.size());
851 EXPECT_EQ(id1
, list
[0].id
);
852 EXPECT_EQ(id2
, list
[1].id
);
853 EXPECT_EQ(id3
, list
[2].id
);
854 EXPECT_EQ(id4
, list
[3].id
);
855 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
856 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
857 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
858 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
859 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
860 list
[0].mailbox_holder
.texture_target
);
861 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
862 list
[1].mailbox_holder
.texture_target
);
863 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
864 list
[2].mailbox_holder
.texture_target
);
865 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
866 list
[3].mailbox_holder
.texture_target
);
867 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
868 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
869 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
870 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
871 resource_provider_
->ReceiveFromChild(child_id
, list
);
872 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
873 resource_ids_to_receive
.insert(id1
);
874 resource_ids_to_receive
.insert(id2
);
875 resource_ids_to_receive
.insert(id3
);
876 resource_ids_to_receive
.insert(id4
);
877 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
878 resource_ids_to_receive
);
881 EXPECT_EQ(0u, returned_to_child
.size());
883 EXPECT_EQ(4u, resource_provider_
->num_resources());
884 resource_provider_
->DestroyChild(child_id
);
885 EXPECT_EQ(0u, resource_provider_
->num_resources());
887 ASSERT_EQ(4u, returned_to_child
.size());
888 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
889 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
890 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
891 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
892 EXPECT_FALSE(returned_to_child
[0].lost
);
893 EXPECT_FALSE(returned_to_child
[1].lost
);
894 EXPECT_FALSE(returned_to_child
[2].lost
);
895 EXPECT_FALSE(returned_to_child
[3].lost
);
898 class ResourceProviderTestNoSyncPoint
: public ResourceProviderTest
{
900 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
901 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
, GetParam());
905 TEST_P(ResourceProviderTestNoSyncPoint
, TransferGLResources
) {
906 gfx::Size
size(1, 1);
907 ResourceFormat format
= RGBA_8888
;
908 size_t pixel_size
= TextureSizeBytes(size
, format
);
909 ASSERT_EQ(4U, pixel_size
);
911 ResourceId id1
= child_resource_provider_
->CreateResource(
912 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
913 uint8_t data1
[4] = {1, 2, 3, 4};
914 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
916 ResourceId id2
= child_resource_provider_
->CreateResource(
917 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
919 // Ensure locking the memory buffer doesn't create an unnecessary sync
921 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
922 child_resource_provider_
.get(), id2
);
923 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
926 GLuint external_texture_id
= child_context_
->createExternalTexture();
928 // A sync point is specified directly and should be used.
929 gpu::Mailbox external_mailbox
;
930 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
931 child_context_
->produceTextureDirectCHROMIUM(
932 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
933 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
934 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
935 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
936 external_sync_point
),
937 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
939 ReturnedResourceArray returned_to_child
;
941 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
942 resource_provider_
->SetChildNeedsSyncPoints(child_id
, false);
944 // Transfer some resources to the parent.
945 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
946 resource_ids_to_transfer
.push_back(id1
);
947 resource_ids_to_transfer
.push_back(id2
);
948 resource_ids_to_transfer
.push_back(id3
);
949 TransferableResourceArray list
;
950 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
952 ASSERT_EQ(3u, list
.size());
953 // Standard resources shouldn't require creating and sending a sync point.
954 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
955 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
956 // A given sync point should be passed through.
957 EXPECT_EQ(external_sync_point
, list
[2].mailbox_holder
.sync_point
);
958 resource_provider_
->ReceiveFromChild(child_id
, list
);
960 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
961 resource_ids_to_receive
.insert(id1
);
962 resource_ids_to_receive
.insert(id2
);
963 resource_ids_to_receive
.insert(id3
);
964 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
965 resource_ids_to_receive
);
969 EXPECT_EQ(0u, returned_to_child
.size());
971 // Transfer resources back from the parent to the child. Set no resources as
973 ResourceProvider::ResourceIdSet no_resources
;
974 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
976 ASSERT_EQ(3u, returned_to_child
.size());
977 std::map
<ResourceId
, unsigned int> returned_sync_points
;
978 for (const auto& returned
: returned_to_child
)
979 returned_sync_points
[returned
.id
] = returned
.sync_point
;
981 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
982 // No new sync point should be created transferring back.
983 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
984 EXPECT_EQ(0u, returned_sync_points
[id1
]);
985 EXPECT_TRUE(returned_sync_points
.find(id2
) != returned_sync_points
.end());
986 EXPECT_EQ(0u, returned_sync_points
[id2
]);
987 // Original sync point given should be returned.
988 EXPECT_TRUE(returned_sync_points
.find(id3
) != returned_sync_points
.end());
989 EXPECT_EQ(external_sync_point
, returned_sync_points
[id3
]);
990 EXPECT_FALSE(returned_to_child
[0].lost
);
991 EXPECT_FALSE(returned_to_child
[1].lost
);
992 EXPECT_FALSE(returned_to_child
[2].lost
);
993 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
994 returned_to_child
.clear();
997 resource_provider_
->DestroyChild(child_id
);
1000 INSTANTIATE_TEST_CASE_P(
1001 ResourceProviderTests
,
1002 ResourceProviderTestNoSyncPoint
,
1003 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
));
1005 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
1006 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1008 gfx::Size
size(1, 1);
1009 ResourceFormat format
= RGBA_8888
;
1011 ResourceId id1
= child_resource_provider_
->CreateResource(
1012 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1013 uint8_t data1
[4] = {1, 2, 3, 4};
1014 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1016 ReturnedResourceArray returned_to_child
;
1018 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1020 // Transfer some resources to the parent.
1021 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1022 resource_ids_to_transfer
.push_back(id1
);
1023 TransferableResourceArray list
;
1024 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1026 ASSERT_EQ(1u, list
.size());
1027 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1029 resource_provider_
->ReceiveFromChild(child_id
, list
);
1031 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
1032 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1035 resource_provider_
->DeclareUsedResourcesFromChild(
1036 child_id
, ResourceProvider::ResourceIdSet());
1037 EXPECT_EQ(0u, returned_to_child
.size());
1040 EXPECT_EQ(1u, returned_to_child
.size());
1041 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1044 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
1045 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
1047 child_resource_provider_
->DeleteResource(id1
);
1048 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1049 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1052 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1053 resource_provider_
->DestroyChild(child_id
);
1056 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
1057 // Overlays only supported on the GL path.
1058 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1061 uint32 sync_point
= 0;
1062 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1063 mailbox
.set_allow_overlay(true);
1064 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
1065 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1066 ResourceId id1
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1067 mailbox
, release_callback
.Pass());
1069 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1070 mailbox2
.set_allow_overlay(false);
1071 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
1072 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1073 ResourceId id2
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1074 mailbox2
, release_callback2
.Pass());
1076 ReturnedResourceArray returned_to_child
;
1078 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1080 // Transfer some resources to the parent.
1081 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1082 resource_ids_to_transfer
.push_back(id1
);
1083 resource_ids_to_transfer
.push_back(id2
);
1084 TransferableResourceArray list
;
1085 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1087 ASSERT_EQ(2u, list
.size());
1088 resource_provider_
->ReceiveFromChild(child_id
, list
);
1089 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
1090 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
1092 resource_provider_
->DeclareUsedResourcesFromChild(
1093 child_id
, ResourceProvider::ResourceIdSet());
1095 EXPECT_EQ(2u, returned_to_child
.size());
1096 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1098 child_resource_provider_
->DeleteResource(id1
);
1099 child_resource_provider_
->DeleteResource(id2
);
1100 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1102 resource_provider_
->DestroyChild(child_id
);
1105 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
1106 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1109 gfx::Size
size(1, 1);
1110 ResourceFormat format
= RGBA_8888
;
1111 size_t pixel_size
= TextureSizeBytes(size
, format
);
1112 ASSERT_EQ(4U, pixel_size
);
1114 ResourceId id1
= child_resource_provider_
->CreateResource(
1115 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1116 uint8_t data1
[4] = { 1, 2, 3, 4 };
1117 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1119 ResourceId id2
= child_resource_provider_
->CreateResource(
1120 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1121 uint8_t data2
[4] = { 5, 5, 5, 5 };
1122 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1124 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1125 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1126 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1127 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1128 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1129 SingleReleaseCallbackImpl::Create(base::Bind(
1130 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1132 ReturnedResourceArray returned_to_child
;
1134 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1136 // Transfer some resources to the parent.
1137 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1138 resource_ids_to_transfer
.push_back(id1
);
1139 resource_ids_to_transfer
.push_back(id2
);
1140 resource_ids_to_transfer
.push_back(id3
);
1141 TransferableResourceArray list
;
1142 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1144 ASSERT_EQ(3u, list
.size());
1145 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1146 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1147 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1148 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1149 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1150 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1151 resource_provider_
->ReceiveFromChild(child_id
, list
);
1152 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1153 resource_ids_to_receive
.insert(id1
);
1154 resource_ids_to_receive
.insert(id2
);
1155 resource_ids_to_receive
.insert(id3
);
1156 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1157 resource_ids_to_receive
);
1160 EXPECT_EQ(3u, resource_provider_
->num_resources());
1161 ResourceProvider::ResourceIdMap resource_map
=
1162 resource_provider_
->GetChildToParentMap(child_id
);
1163 ResourceId mapped_id1
= resource_map
[id1
];
1164 ResourceId mapped_id2
= resource_map
[id2
];
1165 ResourceId mapped_id3
= resource_map
[id3
];
1166 EXPECT_NE(0u, mapped_id1
);
1167 EXPECT_NE(0u, mapped_id2
);
1168 EXPECT_NE(0u, mapped_id3
);
1169 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1170 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1171 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1173 uint8_t result
[4] = { 0 };
1175 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1176 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1179 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1180 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1183 // Check that transfering again the same resource from the child to the
1185 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1186 resource_ids_to_transfer
.push_back(id1
);
1187 resource_ids_to_transfer
.push_back(id2
);
1188 TransferableResourceArray list
;
1189 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1191 EXPECT_EQ(2u, list
.size());
1192 EXPECT_EQ(id1
, list
[0].id
);
1193 EXPECT_EQ(id2
, list
[1].id
);
1194 ReturnedResourceArray returned
;
1195 TransferableResource::ReturnResources(list
, &returned
);
1196 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1197 // ids were exported twice, we returned them only once, they should still
1199 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1200 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1203 EXPECT_EQ(0u, returned_to_child
.size());
1205 // Transfer resources back from the parent to the child. Set no resources as
1207 ResourceProvider::ResourceIdSet no_resources
;
1208 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1210 ASSERT_EQ(3u, returned_to_child
.size());
1211 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1212 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1213 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1214 std::set
<ResourceId
> expected_ids
;
1215 expected_ids
.insert(id1
);
1216 expected_ids
.insert(id2
);
1217 expected_ids
.insert(id3
);
1218 std::set
<ResourceId
> returned_ids
;
1219 for (unsigned i
= 0; i
< 3; i
++)
1220 returned_ids
.insert(returned_to_child
[i
].id
);
1221 EXPECT_EQ(expected_ids
, returned_ids
);
1222 EXPECT_FALSE(returned_to_child
[0].lost
);
1223 EXPECT_FALSE(returned_to_child
[1].lost
);
1224 EXPECT_FALSE(returned_to_child
[2].lost
);
1225 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1226 returned_to_child
.clear();
1228 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1229 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1230 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1233 ResourceProvider::ScopedReadLockSoftware
lock(
1234 child_resource_provider_
.get(), id1
);
1235 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1236 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1237 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1238 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1241 ResourceProvider::ScopedReadLockSoftware
lock(
1242 child_resource_provider_
.get(), id2
);
1243 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1244 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1245 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1246 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1249 // Transfer resources to the parent again.
1250 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1251 resource_ids_to_transfer
.push_back(id1
);
1252 resource_ids_to_transfer
.push_back(id2
);
1253 resource_ids_to_transfer
.push_back(id3
);
1254 TransferableResourceArray list
;
1255 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1257 ASSERT_EQ(3u, list
.size());
1258 EXPECT_EQ(id1
, list
[0].id
);
1259 EXPECT_EQ(id2
, list
[1].id
);
1260 EXPECT_EQ(id3
, list
[2].id
);
1261 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1262 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1263 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1264 resource_provider_
->ReceiveFromChild(child_id
, list
);
1265 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1266 resource_ids_to_receive
.insert(id1
);
1267 resource_ids_to_receive
.insert(id2
);
1268 resource_ids_to_receive
.insert(id3
);
1269 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1270 resource_ids_to_receive
);
1273 EXPECT_EQ(0u, returned_to_child
.size());
1275 EXPECT_EQ(3u, resource_provider_
->num_resources());
1276 resource_provider_
->DestroyChild(child_id
);
1277 EXPECT_EQ(0u, resource_provider_
->num_resources());
1279 ASSERT_EQ(3u, returned_to_child
.size());
1280 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1281 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1282 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1283 std::set
<ResourceId
> expected_ids
;
1284 expected_ids
.insert(id1
);
1285 expected_ids
.insert(id2
);
1286 expected_ids
.insert(id3
);
1287 std::set
<ResourceId
> returned_ids
;
1288 for (unsigned i
= 0; i
< 3; i
++)
1289 returned_ids
.insert(returned_to_child
[i
].id
);
1290 EXPECT_EQ(expected_ids
, returned_ids
);
1291 EXPECT_FALSE(returned_to_child
[0].lost
);
1292 EXPECT_FALSE(returned_to_child
[1].lost
);
1293 EXPECT_FALSE(returned_to_child
[2].lost
);
1296 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1297 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1300 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1301 ResourceProviderContext::Create(shared_data_
.get()));
1303 FakeOutputSurfaceClient child_output_surface_client
;
1304 scoped_ptr
<OutputSurface
> child_output_surface(
1305 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1306 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1308 scoped_ptr
<ResourceProvider
> child_resource_provider(
1309 ResourceProvider::Create(child_output_surface
.get(),
1310 shared_bitmap_manager_
.get(),
1311 gpu_memory_buffer_manager_
.get(),
1317 gfx::Size
size(1, 1);
1318 ResourceFormat format
= RGBA_8888
;
1319 size_t pixel_size
= TextureSizeBytes(size
, format
);
1320 ASSERT_EQ(4U, pixel_size
);
1322 ResourceId id1
= child_resource_provider
->CreateResource(
1323 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1324 uint8_t data1
[4] = { 1, 2, 3, 4 };
1325 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1327 ReturnedResourceArray returned_to_child
;
1329 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1331 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1332 resource_ids_to_transfer
.push_back(id1
);
1333 TransferableResourceArray list
;
1334 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1336 ASSERT_EQ(1u, list
.size());
1337 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1338 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1339 list
[0].mailbox_holder
.texture_target
);
1340 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1341 resource_provider_
->ReceiveFromChild(child_id
, list
);
1344 EXPECT_EQ(0u, resource_provider_
->num_resources());
1345 ASSERT_EQ(1u, returned_to_child
.size());
1346 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1347 ResourceProvider::ResourceIdMap resource_map
=
1348 resource_provider_
->GetChildToParentMap(child_id
);
1349 ResourceId mapped_id1
= resource_map
[id1
];
1350 EXPECT_EQ(0u, mapped_id1
);
1352 resource_provider_
->DestroyChild(child_id
);
1353 EXPECT_EQ(0u, resource_provider_
->num_resources());
1355 ASSERT_EQ(1u, returned_to_child
.size());
1356 EXPECT_FALSE(returned_to_child
[0].lost
);
1359 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1360 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1363 gfx::Size
size(1, 1);
1364 ResourceFormat format
= RGBA_8888
;
1365 size_t pixel_size
= TextureSizeBytes(size
, format
);
1366 ASSERT_EQ(4U, pixel_size
);
1368 ResourceId id1
= child_resource_provider_
->CreateResource(
1369 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1370 uint8_t data1
[4] = { 1, 2, 3, 4 };
1371 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1373 ReturnedResourceArray returned_to_child
;
1375 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1377 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1378 resource_ids_to_transfer
.push_back(id1
);
1379 TransferableResourceArray list
;
1380 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1382 ASSERT_EQ(1u, list
.size());
1384 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1385 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1386 resource_provider_
->ReceiveFromChild(child_id
, list
);
1389 EXPECT_EQ(1u, resource_provider_
->num_resources());
1390 EXPECT_EQ(0u, returned_to_child
.size());
1392 ResourceProvider::ResourceIdMap resource_map
=
1393 resource_provider_
->GetChildToParentMap(child_id
);
1394 ResourceId mapped_id1
= resource_map
[id1
];
1395 EXPECT_NE(0u, mapped_id1
);
1397 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1399 EXPECT_FALSE(lock
.valid());
1402 resource_provider_
->DestroyChild(child_id
);
1403 EXPECT_EQ(0u, resource_provider_
->num_resources());
1405 ASSERT_EQ(1u, returned_to_child
.size());
1406 EXPECT_FALSE(returned_to_child
[0].lost
);
1409 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1410 gfx::Size
size(1, 1);
1411 ResourceFormat format
= RGBA_8888
;
1412 size_t pixel_size
= TextureSizeBytes(size
, format
);
1413 ASSERT_EQ(4U, pixel_size
);
1415 ResourceId id1
= child_resource_provider_
->CreateResource(
1416 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1417 uint8_t data1
[4] = { 1, 2, 3, 4 };
1418 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1420 ResourceId id2
= child_resource_provider_
->CreateResource(
1421 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1422 uint8_t data2
[4] = {5, 5, 5, 5};
1423 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1425 ReturnedResourceArray returned_to_child
;
1427 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1429 // Transfer some resources to the parent.
1430 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1431 resource_ids_to_transfer
.push_back(id1
);
1432 resource_ids_to_transfer
.push_back(id2
);
1433 TransferableResourceArray list
;
1434 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1436 ASSERT_EQ(2u, list
.size());
1437 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1438 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1439 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1441 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1442 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1443 resource_provider_
->ReceiveFromChild(child_id
, list
);
1444 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1445 resource_ids_to_receive
.insert(id1
);
1446 resource_ids_to_receive
.insert(id2
);
1447 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1448 resource_ids_to_receive
);
1451 EXPECT_EQ(2u, resource_provider_
->num_resources());
1452 ResourceProvider::ResourceIdMap resource_map
=
1453 resource_provider_
->GetChildToParentMap(child_id
);
1454 ResourceId mapped_id1
= resource_map
[id1
];
1455 ResourceId mapped_id2
= resource_map
[id2
];
1456 EXPECT_NE(0u, mapped_id1
);
1457 EXPECT_NE(0u, mapped_id2
);
1458 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1459 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1462 // The parent transfers the resources to the grandparent.
1463 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1464 resource_ids_to_transfer
.push_back(mapped_id1
);
1465 resource_ids_to_transfer
.push_back(mapped_id2
);
1466 TransferableResourceArray list
;
1467 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1469 ASSERT_EQ(2u, list
.size());
1470 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1471 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1472 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1474 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1475 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1477 // Release the resource in the parent. Set no resources as being in use. The
1478 // resources are exported so that can't be transferred back yet.
1479 ResourceProvider::ResourceIdSet no_resources
;
1480 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1482 EXPECT_EQ(0u, returned_to_child
.size());
1483 EXPECT_EQ(2u, resource_provider_
->num_resources());
1485 // Return the resources from the grandparent to the parent. They should be
1486 // returned to the child then.
1487 EXPECT_EQ(2u, list
.size());
1488 EXPECT_EQ(mapped_id1
, list
[0].id
);
1489 EXPECT_EQ(mapped_id2
, list
[1].id
);
1490 ReturnedResourceArray returned
;
1491 TransferableResource::ReturnResources(list
, &returned
);
1492 resource_provider_
->ReceiveReturnsFromParent(returned
);
1494 EXPECT_EQ(0u, resource_provider_
->num_resources());
1495 ASSERT_EQ(2u, returned_to_child
.size());
1496 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1497 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1498 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1500 EXPECT_FALSE(returned_to_child
[0].lost
);
1501 EXPECT_FALSE(returned_to_child
[1].lost
);
1505 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1506 gfx::Size
size(1, 1);
1507 ResourceFormat format
= RGBA_8888
;
1508 size_t pixel_size
= TextureSizeBytes(size
, format
);
1509 ASSERT_EQ(4U, pixel_size
);
1511 ResourceId id1
= child_resource_provider_
->CreateResource(
1512 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1513 uint8_t data1
[4] = {1, 2, 3, 4};
1514 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1516 ResourceId id2
= child_resource_provider_
->CreateResource(
1517 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1518 uint8_t data2
[4] = {5, 5, 5, 5};
1519 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1521 ReturnedResourceArray returned_to_child
;
1523 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1525 // Transfer some resources to the parent.
1526 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1527 resource_ids_to_transfer
.push_back(id1
);
1528 resource_ids_to_transfer
.push_back(id2
);
1529 TransferableResourceArray list
;
1530 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1532 ASSERT_EQ(2u, list
.size());
1533 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1534 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1535 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1537 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1538 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1539 resource_provider_
->ReceiveFromChild(child_id
, list
);
1540 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1541 resource_ids_to_receive
.insert(id1
);
1542 resource_ids_to_receive
.insert(id2
);
1543 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1544 resource_ids_to_receive
);
1547 EXPECT_EQ(2u, resource_provider_
->num_resources());
1548 ResourceProvider::ResourceIdMap resource_map
=
1549 resource_provider_
->GetChildToParentMap(child_id
);
1550 ResourceId mapped_id1
= resource_map
[id1
];
1551 ResourceId mapped_id2
= resource_map
[id2
];
1552 EXPECT_NE(0u, mapped_id1
);
1553 EXPECT_NE(0u, mapped_id2
);
1554 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1555 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1558 // The parent transfers the resources to the grandparent.
1559 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1560 resource_ids_to_transfer
.push_back(mapped_id1
);
1561 resource_ids_to_transfer
.push_back(mapped_id2
);
1562 TransferableResourceArray list
;
1563 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1565 ASSERT_EQ(2u, list
.size());
1566 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1567 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1568 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1570 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1571 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1573 // Release the resource in the parent. Set no resources as being in use. The
1574 // resources are exported so that can't be transferred back yet.
1575 ResourceProvider::ResourceIdSet no_resources
;
1576 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1578 // Destroy the child, the resources should not be returned yet.
1579 EXPECT_EQ(0u, returned_to_child
.size());
1580 EXPECT_EQ(2u, resource_provider_
->num_resources());
1582 resource_provider_
->DestroyChild(child_id
);
1584 EXPECT_EQ(2u, resource_provider_
->num_resources());
1585 ASSERT_EQ(0u, returned_to_child
.size());
1587 // Return a resource from the grandparent, it should be returned at this
1589 EXPECT_EQ(2u, list
.size());
1590 EXPECT_EQ(mapped_id1
, list
[0].id
);
1591 EXPECT_EQ(mapped_id2
, list
[1].id
);
1592 TransferableResourceArray return_list
;
1593 return_list
.push_back(list
[1]);
1595 ReturnedResourceArray returned
;
1596 TransferableResource::ReturnResources(return_list
, &returned
);
1597 resource_provider_
->ReceiveReturnsFromParent(returned
);
1599 EXPECT_EQ(1u, resource_provider_
->num_resources());
1600 ASSERT_EQ(1u, returned_to_child
.size());
1601 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1602 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1604 EXPECT_FALSE(returned_to_child
[0].lost
);
1605 returned_to_child
.clear();
1607 // Destroy the parent resource provider. The resource that's left should be
1608 // lost at this point, and returned.
1609 resource_provider_
= nullptr;
1610 ASSERT_EQ(1u, returned_to_child
.size());
1611 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1612 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1614 EXPECT_TRUE(returned_to_child
[0].lost
);
1618 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1619 gfx::Size
size(1, 1);
1620 ResourceFormat format
= RGBA_8888
;
1621 size_t pixel_size
= TextureSizeBytes(size
, format
);
1622 ASSERT_EQ(4U, pixel_size
);
1624 ResourceId id
= child_resource_provider_
->CreateResource(
1625 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1626 uint8_t data
[4] = { 1, 2, 3, 4 };
1627 child_resource_provider_
->CopyToResource(id
, data
, size
);
1629 ReturnedResourceArray returned_to_child
;
1631 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1633 // Transfer some resource to the parent.
1634 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1635 resource_ids_to_transfer
.push_back(id
);
1636 TransferableResourceArray list
;
1637 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1639 ASSERT_EQ(1u, list
.size());
1640 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1641 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1642 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1643 resource_provider_
->ReceiveFromChild(child_id
, list
);
1644 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1645 resource_ids_to_receive
.insert(id
);
1646 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1647 resource_ids_to_receive
);
1650 // Delete textures in the child, while they are transfered.
1651 child_resource_provider_
->DeleteResource(id
);
1652 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1654 EXPECT_EQ(0u, returned_to_child
.size());
1656 // Transfer resources back from the parent to the child. Set no resources as
1658 ResourceProvider::ResourceIdSet no_resources
;
1659 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1661 ASSERT_EQ(1u, returned_to_child
.size());
1662 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1663 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1664 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1666 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1669 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1670 gfx::Size
size(1, 1);
1671 ResourceFormat format
= RGBA_8888
;
1672 size_t pixel_size
= TextureSizeBytes(size
, format
);
1673 ASSERT_EQ(4U, pixel_size
);
1675 ResourceId id
= child_resource_provider_
->CreateResource(
1676 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1677 uint8_t data
[4] = {1, 2, 3, 4};
1678 child_resource_provider_
->CopyToResource(id
, data
, size
);
1680 ReturnedResourceArray returned_to_child
;
1682 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1683 const ResourceProvider::ResourceIdMap
& map
=
1684 resource_provider_
->GetChildToParentMap(child_id
);
1686 // Transfer some resource to the parent.
1687 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1688 resource_ids_to_transfer
.push_back(id
);
1689 TransferableResourceArray list
;
1690 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1692 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1693 resource_provider_
->ReceiveFromChild(child_id
, list
);
1694 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1695 resource_ids_to_receive
.insert(id
);
1696 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1697 resource_ids_to_receive
);
1699 TransferableResourceArray sent_to_top_level
;
1701 // Parent transfers to top-level.
1702 ASSERT_TRUE(map
.find(id
) != map
.end());
1703 ResourceId parent_id
= map
.find(id
)->second
;
1704 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1705 resource_ids_to_transfer
.push_back(parent_id
);
1706 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1707 &sent_to_top_level
);
1708 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1711 // Stop using resource.
1712 ResourceProvider::ResourceIdSet empty
;
1713 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1714 // Resource is not yet returned to the child, since it's in use by the
1716 EXPECT_TRUE(returned_to_child
.empty());
1719 // Send the resource to the parent again.
1720 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1721 resource_ids_to_transfer
.push_back(id
);
1722 TransferableResourceArray list
;
1723 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1725 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1726 resource_provider_
->ReceiveFromChild(child_id
, list
);
1727 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1728 resource_ids_to_receive
.insert(id
);
1729 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1730 resource_ids_to_receive
);
1733 // Receive returns back from top-level.
1734 ReturnedResourceArray returned
;
1735 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1736 resource_provider_
->ReceiveReturnsFromParent(returned
);
1737 // Resource is still not yet returned to the child, since it's declared used
1739 EXPECT_TRUE(returned_to_child
.empty());
1740 ASSERT_TRUE(map
.find(id
) != map
.end());
1741 ResourceId parent_id
= map
.find(id
)->second
;
1742 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1745 sent_to_top_level
.clear();
1746 // Parent transfers again to top-level.
1747 ASSERT_TRUE(map
.find(id
) != map
.end());
1748 ResourceId parent_id
= map
.find(id
)->second
;
1749 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1750 resource_ids_to_transfer
.push_back(parent_id
);
1751 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1752 &sent_to_top_level
);
1753 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1756 // Receive returns back from top-level.
1757 ReturnedResourceArray returned
;
1758 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1759 resource_provider_
->ReceiveReturnsFromParent(returned
);
1760 // Resource is still not yet returned to the child, since it's still
1761 // declared used in the parent.
1762 EXPECT_TRUE(returned_to_child
.empty());
1763 ASSERT_TRUE(map
.find(id
) != map
.end());
1764 ResourceId parent_id
= map
.find(id
)->second
;
1765 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1768 // Stop using resource.
1769 ResourceProvider::ResourceIdSet empty
;
1770 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1771 // Resource should have been returned to the child, since it's no longer in
1772 // use by the top-level.
1773 ASSERT_EQ(1u, returned_to_child
.size());
1774 EXPECT_EQ(id
, returned_to_child
[0].id
);
1775 EXPECT_EQ(2, returned_to_child
[0].count
);
1776 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1777 returned_to_child
.clear();
1778 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1782 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1784 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1785 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1786 new TextureStateTrackingContext
);
1787 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1789 FakeOutputSurfaceClient child_output_surface_client
;
1790 scoped_ptr
<OutputSurface
> child_output_surface(
1791 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1792 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1793 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1794 new TestSharedBitmapManager());
1796 scoped_ptr
<ResourceProvider
> child_resource_provider(
1797 ResourceProvider::Create(child_output_surface
.get(),
1798 shared_bitmap_manager
.get(),
1805 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1806 new TextureStateTrackingContext
);
1807 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1809 FakeOutputSurfaceClient parent_output_surface_client
;
1810 scoped_ptr
<OutputSurface
> parent_output_surface(
1811 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1812 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1814 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1815 ResourceProvider::Create(parent_output_surface
.get(),
1816 shared_bitmap_manager
.get(),
1823 gfx::Size
size(1, 1);
1824 ResourceFormat format
= RGBA_8888
;
1825 int child_texture_id
= 1;
1826 int parent_texture_id
= 2;
1828 size_t pixel_size
= TextureSizeBytes(size
, format
);
1829 ASSERT_EQ(4U, pixel_size
);
1831 ResourceId id
= child_resource_provider
->CreateResource(
1832 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1835 // The new texture is created with GL_LINEAR.
1836 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1837 .Times(2); // Once to create and once to allocate.
1838 EXPECT_CALL(*child_context
,
1839 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1840 EXPECT_CALL(*child_context
,
1841 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1844 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1847 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1848 EXPECT_CALL(*child_context
,
1849 texParameteri(GL_TEXTURE_2D
,
1850 GL_TEXTURE_POOL_CHROMIUM
,
1851 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1852 child_resource_provider
->AllocateForTesting(id
);
1853 Mock::VerifyAndClearExpectations(child_context
);
1855 uint8_t data
[4] = { 1, 2, 3, 4 };
1857 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1858 child_resource_provider
->CopyToResource(id
, data
, size
);
1859 Mock::VerifyAndClearExpectations(child_context
);
1861 // The texture is set to |child_filter| in the child.
1862 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1863 if (child_filter
!= GL_LINEAR
) {
1866 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1869 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1871 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1872 Mock::VerifyAndClearExpectations(child_context
);
1874 ReturnedResourceArray returned_to_child
;
1875 int child_id
= parent_resource_provider
->CreateChild(
1876 GetReturnCallback(&returned_to_child
));
1878 // Transfer some resource to the parent.
1879 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1880 resource_ids_to_transfer
.push_back(id
);
1881 TransferableResourceArray list
;
1883 EXPECT_CALL(*child_context
,
1884 produceTextureDirectCHROMIUM(_
, GL_TEXTURE_2D
, _
));
1885 EXPECT_CALL(*child_context
, insertSyncPoint());
1886 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1888 Mock::VerifyAndClearExpectations(child_context
);
1890 ASSERT_EQ(1u, list
.size());
1891 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1893 EXPECT_CALL(*parent_context
,
1894 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, _
))
1895 .WillOnce(Return(parent_texture_id
));
1897 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1899 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1900 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1903 Mock::VerifyAndClearExpectations(parent_context
);
1905 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1906 resource_ids_to_receive
.insert(id
);
1907 parent_resource_provider
->DeclareUsedResourcesFromChild(
1908 child_id
, resource_ids_to_receive
);
1909 Mock::VerifyAndClearExpectations(parent_context
);
1911 ResourceProvider::ResourceIdMap resource_map
=
1912 parent_resource_provider
->GetChildToParentMap(child_id
);
1913 ResourceId mapped_id
= resource_map
[id
];
1914 EXPECT_NE(0u, mapped_id
);
1916 // The texture is set to |parent_filter| in the parent.
1917 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1920 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1923 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1924 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1925 Mock::VerifyAndClearExpectations(parent_context
);
1927 // The texture should be reset to |child_filter| in the parent when it is
1928 // returned, since that is how it was received.
1929 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1932 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1935 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1938 EXPECT_EQ(0u, returned_to_child
.size());
1940 // Transfer resources back from the parent to the child. Set no resources
1942 ResourceProvider::ResourceIdSet no_resources
;
1943 EXPECT_CALL(*parent_context
, insertSyncPoint());
1944 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1946 Mock::VerifyAndClearExpectations(parent_context
);
1948 ASSERT_EQ(1u, returned_to_child
.size());
1949 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1952 // The child remembers the texture filter is set to |child_filter|.
1953 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1954 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1955 Mock::VerifyAndClearExpectations(child_context
);
1959 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1960 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1962 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1965 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1966 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1968 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1971 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1972 // Other mailbox transfers tested elsewhere.
1973 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1975 unsigned texture
= context()->createTexture();
1976 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1977 uint8_t data
[4] = { 1, 2, 3, 4 };
1978 context()->texImage2D(
1979 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1980 gpu::Mailbox mailbox
;
1981 context()->genMailboxCHROMIUM(mailbox
.name
);
1982 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
1983 uint32 sync_point
= context()->insertSyncPoint();
1985 // All the logic below assumes that the sync points are all positive.
1986 EXPECT_LT(0u, sync_point
);
1988 uint32 release_sync_point
= 0;
1989 bool lost_resource
= false;
1990 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1991 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1992 &release_sync_point
,
1994 &main_thread_task_runner
);
1995 ResourceId resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1996 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1997 SingleReleaseCallbackImpl::Create(callback
));
1998 EXPECT_EQ(1u, context()->NumTextures());
1999 EXPECT_EQ(0u, release_sync_point
);
2001 // Transfer the resource, expect the sync points to be consistent.
2002 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2003 resource_ids_to_transfer
.push_back(resource
);
2004 TransferableResourceArray list
;
2005 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2006 ASSERT_EQ(1u, list
.size());
2007 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2009 memcmp(mailbox
.name
,
2010 list
[0].mailbox_holder
.mailbox
.name
,
2011 sizeof(mailbox
.name
)));
2012 EXPECT_EQ(0u, release_sync_point
);
2014 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2015 unsigned other_texture
=
2016 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2017 uint8_t test_data
[4] = { 0 };
2018 context()->GetPixels(
2019 gfx::Size(1, 1), RGBA_8888
, test_data
);
2020 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2022 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2024 context()->deleteTexture(other_texture
);
2025 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2026 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2028 // Receive the resource, then delete it, expect the sync points to be
2030 ReturnedResourceArray returned
;
2031 TransferableResource::ReturnResources(list
, &returned
);
2032 resource_provider_
->ReceiveReturnsFromParent(returned
);
2033 EXPECT_EQ(1u, context()->NumTextures());
2034 EXPECT_EQ(0u, release_sync_point
);
2036 resource_provider_
->DeleteResource(resource
);
2037 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2038 EXPECT_FALSE(lost_resource
);
2039 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2042 // We're going to do the same thing as above, but testing the case where we
2043 // delete the resource before we receive it back.
2044 sync_point
= release_sync_point
;
2045 EXPECT_LT(0u, sync_point
);
2046 release_sync_point
= 0;
2047 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
2048 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2049 SingleReleaseCallbackImpl::Create(callback
));
2050 EXPECT_EQ(1u, context()->NumTextures());
2051 EXPECT_EQ(0u, release_sync_point
);
2053 // Transfer the resource, expect the sync points to be consistent.
2054 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2055 resource_ids_to_transfer
.push_back(resource
);
2056 TransferableResourceArray list
;
2057 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2058 ASSERT_EQ(1u, list
.size());
2059 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2061 memcmp(mailbox
.name
,
2062 list
[0].mailbox_holder
.mailbox
.name
,
2063 sizeof(mailbox
.name
)));
2064 EXPECT_EQ(0u, release_sync_point
);
2066 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2067 unsigned other_texture
=
2068 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2069 uint8_t test_data
[4] = { 0 };
2070 context()->GetPixels(
2071 gfx::Size(1, 1), RGBA_8888
, test_data
);
2072 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2074 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2076 context()->deleteTexture(other_texture
);
2077 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2078 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2080 // Delete the resource, which shouldn't do anything.
2081 resource_provider_
->DeleteResource(resource
);
2082 EXPECT_EQ(1u, context()->NumTextures());
2083 EXPECT_EQ(0u, release_sync_point
);
2085 // Then receive the resource which should release the mailbox, expect the
2086 // sync points to be consistent.
2087 ReturnedResourceArray returned
;
2088 TransferableResource::ReturnResources(list
, &returned
);
2089 resource_provider_
->ReceiveReturnsFromParent(returned
);
2090 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2091 EXPECT_FALSE(lost_resource
);
2092 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2095 context()->waitSyncPoint(release_sync_point
);
2097 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2098 context()->deleteTexture(texture
);
2101 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
2102 gfx::Size
size(1, 1);
2103 ResourceFormat format
= RGBA_8888
;
2104 ResourceId resource
= child_resource_provider_
->CreateResource(
2105 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2106 child_resource_provider_
->AllocateForTesting(resource
);
2107 // Expect a GL resource to be lost.
2108 bool should_lose_resource
=
2109 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
2111 ReturnedResourceArray returned_to_child
;
2113 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2115 // Transfer the resource to the parent.
2116 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2117 resource_ids_to_transfer
.push_back(resource
);
2118 TransferableResourceArray list
;
2119 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2121 EXPECT_EQ(1u, list
.size());
2123 resource_provider_
->ReceiveFromChild(child_id
, list
);
2124 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2125 resource_ids_to_receive
.insert(resource
);
2126 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2127 resource_ids_to_receive
);
2130 // Lose the output surface in the parent.
2131 resource_provider_
->DidLoseOutputSurface();
2134 EXPECT_EQ(0u, returned_to_child
.size());
2136 // Transfer resources back from the parent to the child. Set no resources as
2138 ResourceProvider::ResourceIdSet no_resources
;
2139 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2141 // Expect a GL resource to be lost.
2142 ASSERT_EQ(1u, returned_to_child
.size());
2143 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2144 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2145 returned_to_child
.clear();
2148 // A GL resource should be lost.
2149 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2151 // Lost resources stay in use in the parent forever.
2152 EXPECT_EQ(should_lose_resource
,
2153 child_resource_provider_
->InUseByConsumer(resource
));
2156 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2157 gfx::Size
size(1, 1);
2158 ResourceFormat format
= RGBA_8888
;
2159 ResourceId resource
= child_resource_provider_
->CreateResource(
2160 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2161 child_resource_provider_
->AllocateForTesting(resource
);
2163 ReturnedResourceArray returned_to_child
;
2165 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2167 // Transfer the resource to the parent.
2168 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2169 resource_ids_to_transfer
.push_back(resource
);
2170 TransferableResourceArray list
;
2171 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2173 EXPECT_EQ(1u, list
.size());
2175 resource_provider_
->ReceiveFromChild(child_id
, list
);
2176 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2177 resource_ids_to_receive
.insert(resource
);
2178 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2179 resource_ids_to_receive
);
2183 ResourceProvider::ResourceIdMap resource_map
=
2184 resource_provider_
->GetChildToParentMap(child_id
);
2185 ResourceId parent_resource
= resource_map
[resource
];
2186 EXPECT_NE(0u, parent_resource
);
2188 // Transfer to a grandparent.
2189 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2190 resource_ids_to_transfer
.push_back(parent_resource
);
2191 TransferableResourceArray list
;
2192 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2194 // Receive back a lost resource from the grandparent.
2195 EXPECT_EQ(1u, list
.size());
2196 EXPECT_EQ(parent_resource
, list
[0].id
);
2197 ReturnedResourceArray returned
;
2198 TransferableResource::ReturnResources(list
, &returned
);
2199 EXPECT_EQ(1u, returned
.size());
2200 EXPECT_EQ(parent_resource
, returned
[0].id
);
2201 returned
[0].lost
= true;
2202 resource_provider_
->ReceiveReturnsFromParent(returned
);
2204 // The resource should be lost.
2205 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2207 // Lost resources stay in use in the parent forever.
2208 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2212 EXPECT_EQ(0u, returned_to_child
.size());
2214 // Transfer resources back from the parent to the child. Set no resources as
2216 ResourceProvider::ResourceIdSet no_resources
;
2217 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2219 // Expect the resource to be lost.
2220 ASSERT_EQ(1u, returned_to_child
.size());
2221 EXPECT_TRUE(returned_to_child
[0].lost
);
2222 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2223 returned_to_child
.clear();
2226 // The resource should be lost.
2227 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2229 // Lost resources stay in use in the parent forever.
2230 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2233 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2234 uint32 release_sync_point
= 0;
2235 bool lost_resource
= false;
2236 bool release_called
= false;
2237 uint32 sync_point
= 0;
2238 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2239 &release_called
, &sync_point
);
2241 ReturnedResourceArray returned_to_child
;
2243 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2245 // Transfer the resource to the parent.
2246 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2247 resource_ids_to_transfer
.push_back(resource
);
2248 TransferableResourceArray list
;
2249 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2251 EXPECT_EQ(1u, list
.size());
2253 resource_provider_
->ReceiveFromChild(child_id
, list
);
2254 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2255 resource_ids_to_receive
.insert(resource
);
2256 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2257 resource_ids_to_receive
);
2260 // Lose the output surface in the parent.
2261 resource_provider_
->DidLoseOutputSurface();
2264 EXPECT_EQ(0u, returned_to_child
.size());
2266 // Transfer resources back from the parent to the child. Set no resources as
2268 ResourceProvider::ResourceIdSet no_resources
;
2269 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2271 ASSERT_EQ(1u, returned_to_child
.size());
2272 // Losing an output surface only loses hardware resources.
2273 EXPECT_EQ(returned_to_child
[0].lost
,
2274 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2275 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2276 returned_to_child
.clear();
2279 // Delete the resource in the child. Expect the resource to be lost if it's
2281 child_resource_provider_
->DeleteResource(resource
);
2282 EXPECT_EQ(lost_resource
,
2283 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2286 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2287 uint32 release_sync_point
= 0;
2288 bool lost_resource
= false;
2289 bool release_called
= false;
2290 uint32 sync_point
= 0;
2291 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2292 &release_called
, &sync_point
);
2294 ReturnedResourceArray returned_to_child
;
2296 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2298 // Transfer the resource to the parent.
2299 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2300 resource_ids_to_transfer
.push_back(resource
);
2301 TransferableResourceArray list
;
2302 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2304 EXPECT_EQ(1u, list
.size());
2306 resource_provider_
->ReceiveFromChild(child_id
, list
);
2307 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2308 resource_ids_to_receive
.insert(resource
);
2309 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2310 resource_ids_to_receive
);
2314 ResourceProvider::ResourceIdMap resource_map
=
2315 resource_provider_
->GetChildToParentMap(child_id
);
2316 ResourceId parent_resource
= resource_map
[resource
];
2317 EXPECT_NE(0u, parent_resource
);
2319 // Transfer to a grandparent.
2320 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2321 resource_ids_to_transfer
.push_back(parent_resource
);
2322 TransferableResourceArray list
;
2323 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2325 // Receive back a lost resource from the grandparent.
2326 EXPECT_EQ(1u, list
.size());
2327 EXPECT_EQ(parent_resource
, list
[0].id
);
2328 ReturnedResourceArray returned
;
2329 TransferableResource::ReturnResources(list
, &returned
);
2330 EXPECT_EQ(1u, returned
.size());
2331 EXPECT_EQ(parent_resource
, returned
[0].id
);
2332 returned
[0].lost
= true;
2333 resource_provider_
->ReceiveReturnsFromParent(returned
);
2337 EXPECT_EQ(0u, returned_to_child
.size());
2339 // Transfer resources back from the parent to the child. Set no resources as
2341 ResourceProvider::ResourceIdSet no_resources
;
2342 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2344 // Expect the resource to be lost.
2345 ASSERT_EQ(1u, returned_to_child
.size());
2346 EXPECT_TRUE(returned_to_child
[0].lost
);
2347 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2348 returned_to_child
.clear();
2351 // Delete the resource in the child. Expect the resource to be lost.
2352 child_resource_provider_
->DeleteResource(resource
);
2353 EXPECT_TRUE(lost_resource
);
2356 TEST_P(ResourceProviderTest
, Shutdown
) {
2357 uint32 release_sync_point
= 0;
2358 bool lost_resource
= false;
2359 bool release_called
= false;
2360 uint32 sync_point
= 0;
2362 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2364 EXPECT_EQ(0u, release_sync_point
);
2365 EXPECT_FALSE(lost_resource
);
2367 child_resource_provider_
= nullptr;
2369 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2370 EXPECT_LE(sync_point
, release_sync_point
);
2372 EXPECT_TRUE(release_called
);
2373 EXPECT_FALSE(lost_resource
);
2376 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2377 uint32 release_sync_point
= 0;
2378 bool lost_resource
= false;
2379 bool release_called
= false;
2380 uint32 sync_point
= 0;
2381 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2382 &release_called
, &sync_point
);
2384 // Transfer the resource, so we can't release it properly on shutdown.
2385 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2386 resource_ids_to_transfer
.push_back(resource
);
2387 TransferableResourceArray list
;
2388 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2391 EXPECT_EQ(0u, release_sync_point
);
2392 EXPECT_FALSE(lost_resource
);
2394 child_resource_provider_
= nullptr;
2396 // Since the resource is in the parent, the child considers it lost.
2397 EXPECT_EQ(0u, release_sync_point
);
2398 EXPECT_TRUE(lost_resource
);
2401 TEST_P(ResourceProviderTest
, LostContext
) {
2402 // TextureMailbox callbacks only exist for GL textures for now.
2403 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2405 unsigned texture
= context()->createTexture();
2406 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2407 gpu::Mailbox mailbox
;
2408 context()->genMailboxCHROMIUM(mailbox
.name
);
2409 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2410 uint32 sync_point
= context()->insertSyncPoint();
2412 EXPECT_LT(0u, sync_point
);
2414 uint32 release_sync_point
= 0;
2415 bool lost_resource
= false;
2416 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2417 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2418 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2419 &release_sync_point
,
2421 &main_thread_task_runner
));
2422 resource_provider_
->CreateResourceFromTextureMailbox(
2423 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2425 EXPECT_EQ(0u, release_sync_point
);
2426 EXPECT_FALSE(lost_resource
);
2427 EXPECT_EQ(NULL
, main_thread_task_runner
);
2429 resource_provider_
->DidLoseOutputSurface();
2430 resource_provider_
= nullptr;
2432 EXPECT_LE(sync_point
, release_sync_point
);
2433 EXPECT_TRUE(lost_resource
);
2434 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2437 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2438 // Sampling is only supported for GL textures.
2439 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2442 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2443 new TextureStateTrackingContext
);
2444 TextureStateTrackingContext
* context
= context_owned
.get();
2446 FakeOutputSurfaceClient output_surface_client
;
2447 scoped_ptr
<OutputSurface
> output_surface(
2448 FakeOutputSurface::Create3d(context_owned
.Pass()));
2449 CHECK(output_surface
->BindToClient(&output_surface_client
));
2451 scoped_ptr
<ResourceProvider
> resource_provider(
2452 ResourceProvider::Create(output_surface
.get(),
2453 shared_bitmap_manager_
.get(),
2454 gpu_memory_buffer_manager_
.get(),
2460 gfx::Size
size(1, 1);
2461 ResourceFormat format
= RGBA_8888
;
2464 ResourceId id
= resource_provider
->CreateResource(
2465 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2467 // Check that the texture gets created with the right sampler settings.
2468 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2469 .Times(2); // Once to create and once to allocate.
2470 EXPECT_CALL(*context
,
2471 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2472 EXPECT_CALL(*context
,
2473 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2476 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2479 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2480 EXPECT_CALL(*context
,
2481 texParameteri(GL_TEXTURE_2D
,
2482 GL_TEXTURE_POOL_CHROMIUM
,
2483 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2485 resource_provider
->AllocateForTesting(id
);
2486 Mock::VerifyAndClearExpectations(context
);
2488 // Creating a sampler with the default filter should not change any texture
2491 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2492 ResourceProvider::ScopedSamplerGL
sampler(
2493 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2494 Mock::VerifyAndClearExpectations(context
);
2497 // Using a different filter should be reflected in the texture parameters.
2499 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2502 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2505 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2506 ResourceProvider::ScopedSamplerGL
sampler(
2507 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2508 Mock::VerifyAndClearExpectations(context
);
2511 // Test resetting to the default filter.
2513 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2514 EXPECT_CALL(*context
,
2515 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2516 EXPECT_CALL(*context
,
2517 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2518 ResourceProvider::ScopedSamplerGL
sampler(
2519 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2520 Mock::VerifyAndClearExpectations(context
);
2524 TEST_P(ResourceProviderTest
, ManagedResource
) {
2525 // Sampling is only supported for GL textures.
2526 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2529 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2530 new TextureStateTrackingContext
);
2531 TextureStateTrackingContext
* context
= context_owned
.get();
2533 FakeOutputSurfaceClient output_surface_client
;
2534 scoped_ptr
<OutputSurface
> output_surface(
2535 FakeOutputSurface::Create3d(context_owned
.Pass()));
2536 CHECK(output_surface
->BindToClient(&output_surface_client
));
2538 scoped_ptr
<ResourceProvider
> resource_provider(
2539 ResourceProvider::Create(output_surface
.get(),
2540 shared_bitmap_manager_
.get(),
2541 gpu_memory_buffer_manager_
.get(),
2547 gfx::Size
size(1, 1);
2548 ResourceFormat format
= RGBA_8888
;
2551 // Check that the texture gets created with the right sampler settings.
2552 ResourceId id
= resource_provider
->CreateManagedResource(
2553 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2554 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2555 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2556 EXPECT_CALL(*context
,
2557 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2558 EXPECT_CALL(*context
,
2559 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2562 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2565 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2566 EXPECT_CALL(*context
,
2567 texParameteri(GL_TEXTURE_2D
,
2568 GL_TEXTURE_POOL_CHROMIUM
,
2569 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2570 resource_provider
->CreateForTesting(id
);
2573 Mock::VerifyAndClearExpectations(context
);
2576 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2577 // Sampling is only supported for GL textures.
2578 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2581 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2582 new TextureStateTrackingContext
);
2583 TextureStateTrackingContext
* context
= context_owned
.get();
2585 FakeOutputSurfaceClient output_surface_client
;
2586 scoped_ptr
<OutputSurface
> output_surface(
2587 FakeOutputSurface::Create3d(context_owned
.Pass()));
2588 CHECK(output_surface
->BindToClient(&output_surface_client
));
2590 scoped_ptr
<ResourceProvider
> resource_provider(
2591 ResourceProvider::Create(output_surface
.get(),
2592 shared_bitmap_manager_
.get(),
2593 gpu_memory_buffer_manager_
.get(),
2599 gfx::Size
size(1, 1);
2600 ResourceFormat format
= RGBA_8888
;
2601 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2603 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2604 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2605 // Check that the texture gets created with the right sampler settings.
2606 ResourceId id
= resource_provider
->CreateGLTexture(
2607 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2608 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2609 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2610 EXPECT_CALL(*context
,
2611 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2612 EXPECT_CALL(*context
,
2613 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2614 EXPECT_CALL(*context
,
2615 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2616 EXPECT_CALL(*context
,
2617 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2618 EXPECT_CALL(*context
,
2619 texParameteri(GL_TEXTURE_2D
,
2620 GL_TEXTURE_POOL_CHROMIUM
,
2621 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2622 resource_provider
->CreateForTesting(id
);
2625 Mock::VerifyAndClearExpectations(context
);
2629 TEST_P(ResourceProviderTest
, TextureHint
) {
2630 // Sampling is only supported for GL textures.
2631 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2634 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2635 new TextureStateTrackingContext
);
2636 TextureStateTrackingContext
* context
= context_owned
.get();
2637 context
->set_support_texture_storage(true);
2638 context
->set_support_texture_usage(true);
2640 FakeOutputSurfaceClient output_surface_client
;
2641 scoped_ptr
<OutputSurface
> output_surface(
2642 FakeOutputSurface::Create3d(context_owned
.Pass()));
2643 CHECK(output_surface
->BindToClient(&output_surface_client
));
2645 scoped_ptr
<ResourceProvider
> resource_provider(
2646 ResourceProvider::Create(output_surface
.get(),
2647 shared_bitmap_manager_
.get(),
2648 gpu_memory_buffer_manager_
.get(),
2654 gfx::Size
size(1, 1);
2655 ResourceFormat format
= RGBA_8888
;
2656 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2658 const ResourceProvider::TextureHint hints
[4] = {
2659 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2660 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2661 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2662 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2664 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2665 // Check that the texture gets created with the right sampler settings.
2666 ResourceId id
= resource_provider
->CreateGLTexture(
2667 size
, GL_TEXTURE_2D
, texture_pool
, GL_CLAMP_TO_EDGE
,
2668 hints
[texture_id
- 1], format
);
2669 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2670 EXPECT_CALL(*context
,
2671 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2672 EXPECT_CALL(*context
,
2673 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2676 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2679 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2680 EXPECT_CALL(*context
,
2681 texParameteri(GL_TEXTURE_2D
,
2682 GL_TEXTURE_POOL_CHROMIUM
,
2683 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2684 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2685 bool is_framebuffer_hint
=
2686 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2687 EXPECT_CALL(*context
,
2688 texParameteri(GL_TEXTURE_2D
,
2689 GL_TEXTURE_USAGE_ANGLE
,
2690 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2691 .Times(is_framebuffer_hint
? 1 : 0);
2692 resource_provider
->CreateForTesting(id
);
2695 Mock::VerifyAndClearExpectations(context
);
2699 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2700 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2703 gfx::Size
size(64, 64);
2704 const uint32_t kBadBeef
= 0xbadbeef;
2705 scoped_ptr
<SharedBitmap
> shared_bitmap(
2706 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2708 FakeOutputSurfaceClient output_surface_client
;
2709 scoped_ptr
<OutputSurface
> output_surface(
2710 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2711 new SoftwareOutputDevice
)));
2712 CHECK(output_surface
->BindToClient(&output_surface_client
));
2714 scoped_ptr
<ResourceProvider
> resource_provider(
2715 ResourceProvider::Create(output_surface
.get(),
2716 shared_bitmap_manager_
.get(),
2717 gpu_memory_buffer_manager_
.get(),
2718 main_thread_task_runner_
.get(),
2723 uint32 release_sync_point
= 0;
2724 bool lost_resource
= false;
2725 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2726 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2727 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2728 &release_sync_point
,
2730 &main_thread_task_runner
));
2731 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2733 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2734 mailbox
, callback
.Pass());
2738 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2739 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2740 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2741 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2742 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2745 resource_provider
->DeleteResource(id
);
2746 EXPECT_EQ(0u, release_sync_point
);
2747 EXPECT_FALSE(lost_resource
);
2748 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2751 class ResourceProviderTestTextureMailboxGLFilters
2752 : public ResourceProviderTest
{
2754 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2755 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2756 BlockingTaskRunner
* main_thread_task_runner
,
2757 bool mailbox_nearest_neighbor
,
2758 GLenum sampler_filter
) {
2759 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2760 new TextureStateTrackingContext
);
2761 TextureStateTrackingContext
* context
= context_owned
.get();
2763 FakeOutputSurfaceClient output_surface_client
;
2764 scoped_ptr
<OutputSurface
> output_surface(
2765 FakeOutputSurface::Create3d(context_owned
.Pass()));
2766 CHECK(output_surface
->BindToClient(&output_surface_client
));
2768 scoped_ptr
<ResourceProvider
> resource_provider(
2769 ResourceProvider::Create(output_surface
.get(),
2770 shared_bitmap_manager
,
2771 gpu_memory_buffer_manager
,
2772 main_thread_task_runner
,
2777 unsigned texture_id
= 1;
2778 uint32 sync_point
= 30;
2779 unsigned target
= GL_TEXTURE_2D
;
2781 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2782 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2783 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2784 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2785 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2787 gpu::Mailbox gpu_mailbox
;
2788 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2789 uint32 release_sync_point
= 0;
2790 bool lost_resource
= false;
2791 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2792 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2793 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2794 &release_sync_point
,
2796 &mailbox_task_runner
));
2798 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2799 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2801 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2802 mailbox
, callback
.Pass());
2805 Mock::VerifyAndClearExpectations(context
);
2808 // Mailbox sync point WaitSyncPoint before using the texture.
2809 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2810 resource_provider
->WaitSyncPointIfNeeded(id
);
2811 Mock::VerifyAndClearExpectations(context
);
2813 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2814 .WillOnce(Return(texture_id
));
2815 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2817 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2818 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2820 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2821 // match |sampler_filter|.
2822 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2823 EXPECT_CALL(*context
, texParameteri(
2824 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2825 EXPECT_CALL(*context
, texParameteri(
2826 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2829 ResourceProvider::ScopedSamplerGL
lock(
2830 resource_provider
.get(), id
, sampler_filter
);
2831 Mock::VerifyAndClearExpectations(context
);
2833 // When done with it, a sync point should be inserted, but no produce is
2835 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2836 EXPECT_CALL(*context
, insertSyncPoint());
2837 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2839 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2840 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2843 resource_provider
->DeleteResource(id
);
2844 EXPECT_EQ(0u, release_sync_point
);
2845 EXPECT_FALSE(lost_resource
);
2846 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2850 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2851 // Mailboxing is only supported for GL textures.
2852 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2855 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2856 shared_bitmap_manager_
.get(),
2857 gpu_memory_buffer_manager_
.get(),
2858 main_thread_task_runner_
.get(),
2863 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2864 // Mailboxing is only supported for GL textures.
2865 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2868 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2869 shared_bitmap_manager_
.get(),
2870 gpu_memory_buffer_manager_
.get(),
2871 main_thread_task_runner_
.get(),
2876 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2877 // Mailboxing is only supported for GL textures.
2878 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2881 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2882 shared_bitmap_manager_
.get(),
2883 gpu_memory_buffer_manager_
.get(),
2884 main_thread_task_runner_
.get(),
2889 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2890 // Mailboxing is only supported for GL textures.
2891 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2894 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2895 shared_bitmap_manager_
.get(),
2896 gpu_memory_buffer_manager_
.get(),
2897 main_thread_task_runner_
.get(),
2902 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2903 // Mailboxing is only supported for GL textures.
2904 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2907 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2908 new TextureStateTrackingContext
);
2909 TextureStateTrackingContext
* context
= context_owned
.get();
2911 FakeOutputSurfaceClient output_surface_client
;
2912 scoped_ptr
<OutputSurface
> output_surface(
2913 FakeOutputSurface::Create3d(context_owned
.Pass()));
2914 CHECK(output_surface
->BindToClient(&output_surface_client
));
2916 scoped_ptr
<ResourceProvider
> resource_provider(
2917 ResourceProvider::Create(output_surface
.get(),
2918 shared_bitmap_manager_
.get(),
2919 gpu_memory_buffer_manager_
.get(),
2925 uint32 sync_point
= 30;
2926 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2928 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2929 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2930 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2931 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2932 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2934 gpu::Mailbox gpu_mailbox
;
2935 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2936 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2937 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2939 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2941 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2942 mailbox
, callback
.Pass());
2945 Mock::VerifyAndClearExpectations(context
);
2948 // Mailbox sync point WaitSyncPoint before using the texture.
2949 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2950 resource_provider
->WaitSyncPointIfNeeded(id
);
2951 Mock::VerifyAndClearExpectations(context
);
2953 unsigned texture_id
= 1;
2955 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2956 .WillOnce(Return(texture_id
));
2958 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2959 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2961 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2962 Mock::VerifyAndClearExpectations(context
);
2964 // When done with it, a sync point should be inserted, but no produce is
2966 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2967 EXPECT_CALL(*context
, insertSyncPoint());
2968 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2970 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2971 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2975 TEST_P(ResourceProviderTest
,
2976 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2977 // Mailboxing is only supported for GL textures.
2978 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2981 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2982 new TextureStateTrackingContext
);
2983 TextureStateTrackingContext
* context
= context_owned
.get();
2985 FakeOutputSurfaceClient output_surface_client
;
2986 scoped_ptr
<OutputSurface
> output_surface(
2987 FakeOutputSurface::Create3d(context_owned
.Pass()));
2988 CHECK(output_surface
->BindToClient(&output_surface_client
));
2990 scoped_ptr
<ResourceProvider
> resource_provider(
2991 ResourceProvider::Create(output_surface
.get(),
2992 shared_bitmap_manager_
.get(),
2993 gpu_memory_buffer_manager_
.get(),
2999 uint32 sync_point
= 30;
3000 unsigned target
= GL_TEXTURE_2D
;
3002 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3003 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3004 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3005 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3006 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3008 gpu::Mailbox gpu_mailbox
;
3009 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3010 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3011 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3013 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3015 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
3016 mailbox
, callback
.Pass());
3019 Mock::VerifyAndClearExpectations(context
);
3022 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3023 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
3024 resource_provider
->WaitSyncPointIfNeeded(id
);
3025 Mock::VerifyAndClearExpectations(context
);
3027 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3028 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3029 resource_provider
->WaitSyncPointIfNeeded(id
);
3030 Mock::VerifyAndClearExpectations(context
);
3034 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
3035 // Mailboxing is only supported for GL textures.
3036 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3039 scoped_ptr
<TextureStateTrackingContext
> context_owned(
3040 new TextureStateTrackingContext
);
3041 TextureStateTrackingContext
* context
= context_owned
.get();
3043 FakeOutputSurfaceClient output_surface_client
;
3044 scoped_ptr
<OutputSurface
> output_surface(
3045 FakeOutputSurface::Create3d(context_owned
.Pass()));
3046 CHECK(output_surface
->BindToClient(&output_surface_client
));
3048 scoped_ptr
<ResourceProvider
> resource_provider(
3049 ResourceProvider::Create(output_surface
.get(),
3050 shared_bitmap_manager_
.get(),
3051 gpu_memory_buffer_manager_
.get(),
3057 uint32 sync_point
= 0;
3058 unsigned target
= GL_TEXTURE_2D
;
3060 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3061 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3062 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3063 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3064 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3066 gpu::Mailbox gpu_mailbox
;
3067 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3068 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3069 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3071 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3073 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
3074 mailbox
, callback
.Pass());
3077 Mock::VerifyAndClearExpectations(context
);
3080 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3081 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3082 resource_provider
->WaitSyncPointIfNeeded(id
);
3083 Mock::VerifyAndClearExpectations(context
);
3087 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
3089 MOCK_METHOD0(NextTextureId
, GLuint());
3090 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
3091 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
3092 MOCK_METHOD5(texStorage2DEXT
,
3095 GLuint internalformat
,
3098 MOCK_METHOD9(texImage2D
,
3101 GLenum internalformat
,
3107 const void* pixels
));
3108 MOCK_METHOD9(texSubImage2D
,
3117 const void* pixels
));
3118 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
3121 GLenum internalformat
,
3127 const void* pixels
));
3128 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3137 const void* pixels
));
3138 MOCK_METHOD8(compressedTexImage2D
,
3141 GLenum internalformat
,
3147 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3148 MOCK_METHOD4(createImageCHROMIUM
,
3149 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3150 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3151 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3152 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3154 // We're mocking bindTexture, so we override
3155 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3156 // currently bound texture.
3157 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3160 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3161 // Only for GL textures.
3162 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3164 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3165 new StrictMock
<AllocationTrackingContext3D
>);
3166 AllocationTrackingContext3D
* context
= context_owned
.get();
3168 FakeOutputSurfaceClient output_surface_client
;
3169 scoped_ptr
<OutputSurface
> output_surface(
3170 FakeOutputSurface::Create3d(context_owned
.Pass()));
3171 CHECK(output_surface
->BindToClient(&output_surface_client
));
3173 scoped_ptr
<ResourceProvider
> resource_provider(
3174 ResourceProvider::Create(output_surface
.get(),
3175 shared_bitmap_manager_
.get(),
3176 gpu_memory_buffer_manager_
.get(),
3182 gfx::Size
size(2, 2);
3183 gfx::Vector2d
offset(0, 0);
3184 ResourceFormat format
= RGBA_8888
;
3186 uint8_t pixels
[16] = { 0 };
3187 int texture_id
= 123;
3189 // Lazy allocation. Don't allocate when creating the resource.
3190 id
= resource_provider
->CreateResource(
3191 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3193 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3194 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3195 resource_provider
->CreateForTesting(id
);
3197 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3198 resource_provider
->DeleteResource(id
);
3200 Mock::VerifyAndClearExpectations(context
);
3202 // Do allocate when we set the pixels.
3203 id
= resource_provider
->CreateResource(
3204 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3206 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3207 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3208 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3209 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3210 resource_provider
->CopyToResource(id
, pixels
, size
);
3212 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3213 resource_provider
->DeleteResource(id
);
3215 Mock::VerifyAndClearExpectations(context
);
3217 // Same for async version.
3218 id
= resource_provider
->CreateResource(
3219 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3220 resource_provider
->AcquirePixelBuffer(id
);
3222 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3223 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3224 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3226 resource_provider
->BeginSetPixels(id
);
3227 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3229 resource_provider
->ReleasePixelBuffer(id
);
3231 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3232 resource_provider
->DeleteResource(id
);
3234 Mock::VerifyAndClearExpectations(context
);
3237 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3238 // Only for GL textures.
3239 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3241 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3242 new StrictMock
<AllocationTrackingContext3D
>);
3243 AllocationTrackingContext3D
* context
= context_owned
.get();
3244 context
->set_support_texture_storage(true);
3245 context
->set_support_texture_usage(true);
3247 FakeOutputSurfaceClient output_surface_client
;
3248 scoped_ptr
<OutputSurface
> output_surface(
3249 FakeOutputSurface::Create3d(context_owned
.Pass()));
3250 CHECK(output_surface
->BindToClient(&output_surface_client
));
3252 scoped_ptr
<ResourceProvider
> resource_provider(
3253 ResourceProvider::Create(output_surface
.get(),
3254 shared_bitmap_manager_
.get(),
3255 gpu_memory_buffer_manager_
.get(),
3261 gfx::Size
size(2, 2);
3263 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3264 const ResourceProvider::TextureHint hints
[4] = {
3265 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3266 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3267 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3268 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3270 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3271 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3272 // Lazy allocation. Don't allocate when creating the resource.
3273 ResourceId id
= resource_provider
->CreateResource(
3274 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3276 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3277 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3278 bool is_immutable_hint
=
3279 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3280 bool support_immutable_texture
=
3281 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3282 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3283 .Times(support_immutable_texture
? 1 : 0);
3284 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3285 .Times(support_immutable_texture
? 0 : 1);
3286 resource_provider
->AllocateForTesting(id
);
3288 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3289 resource_provider
->DeleteResource(id
);
3291 Mock::VerifyAndClearExpectations(context
);
3296 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3297 // Only for GL textures.
3298 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3300 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3301 new StrictMock
<AllocationTrackingContext3D
>);
3302 AllocationTrackingContext3D
* context
= context_owned
.get();
3303 context
->set_support_texture_format_bgra8888(true);
3304 context
->set_support_texture_storage(true);
3305 context
->set_support_texture_usage(true);
3307 FakeOutputSurfaceClient output_surface_client
;
3308 scoped_ptr
<OutputSurface
> output_surface(
3309 FakeOutputSurface::Create3d(context_owned
.Pass()));
3310 CHECK(output_surface
->BindToClient(&output_surface_client
));
3312 scoped_ptr
<ResourceProvider
> resource_provider(
3313 ResourceProvider::Create(output_surface
.get(),
3314 shared_bitmap_manager_
.get(),
3315 gpu_memory_buffer_manager_
.get(),
3321 gfx::Size
size(2, 2);
3322 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3324 const ResourceProvider::TextureHint hints
[4] = {
3325 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3326 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3327 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3328 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3330 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3331 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3332 // Lazy allocation. Don't allocate when creating the resource.
3333 ResourceId id
= resource_provider
->CreateResource(
3334 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3336 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3337 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3338 bool is_immutable_hint
=
3339 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3340 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3341 .Times(is_immutable_hint
? 1 : 0);
3342 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3343 .Times(is_immutable_hint
? 0 : 1);
3344 resource_provider
->AllocateForTesting(id
);
3346 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3347 resource_provider
->DeleteResource(id
);
3349 Mock::VerifyAndClearExpectations(context
);
3354 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3355 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3357 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3358 new StrictMock
<AllocationTrackingContext3D
>);
3359 AllocationTrackingContext3D
* context
= context_owned
.get();
3361 FakeOutputSurfaceClient output_surface_client
;
3362 scoped_ptr
<OutputSurface
> output_surface(
3363 FakeOutputSurface::Create3d(context_owned
.Pass()));
3364 CHECK(output_surface
->BindToClient(&output_surface_client
));
3366 gfx::Size
size(2, 2);
3367 ResourceFormat format
= RGBA_8888
;
3369 int texture_id
= 123;
3371 scoped_ptr
<ResourceProvider
> resource_provider(
3372 ResourceProvider::Create(output_surface
.get(),
3373 shared_bitmap_manager_
.get(),
3374 gpu_memory_buffer_manager_
.get(),
3380 id
= resource_provider
->CreateResource(
3381 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3382 resource_provider
->AcquirePixelBuffer(id
);
3384 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3385 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3386 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3388 resource_provider
->BeginSetPixels(id
);
3390 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3392 resource_provider
->ReleasePixelBuffer(id
);
3394 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3395 resource_provider
->DeleteResource(id
);
3397 Mock::VerifyAndClearExpectations(context
);
3400 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3401 // Only for GL textures.
3402 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3404 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3405 new StrictMock
<AllocationTrackingContext3D
>);
3406 AllocationTrackingContext3D
* context
= context_owned
.get();
3408 FakeOutputSurfaceClient output_surface_client
;
3409 scoped_ptr
<OutputSurface
> output_surface(
3410 FakeOutputSurface::Create3d(context_owned
.Pass()));
3411 CHECK(output_surface
->BindToClient(&output_surface_client
));
3413 gfx::Size
size(2, 2);
3414 ResourceFormat format
= RGBA_8888
;
3416 int texture_id
= 123;
3418 scoped_ptr
<ResourceProvider
> resource_provider(
3419 ResourceProvider::Create(output_surface
.get(),
3420 shared_bitmap_manager_
.get(),
3421 gpu_memory_buffer_manager_
.get(),
3427 id
= resource_provider
->CreateResource(
3428 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3429 resource_provider
->AcquirePixelBuffer(id
);
3431 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3432 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3433 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3435 resource_provider
->BeginSetPixels(id
);
3437 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3438 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3439 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3440 resource_provider
->ForceSetPixelsToComplete(id
);
3442 resource_provider
->ReleasePixelBuffer(id
);
3444 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3445 resource_provider
->DeleteResource(id
);
3447 Mock::VerifyAndClearExpectations(context
);
3450 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3451 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3452 new NiceMock
<AllocationTrackingContext3D
>);
3453 AllocationTrackingContext3D
* context
= context_owned
.get();
3455 FakeOutputSurfaceClient output_surface_client
;
3456 scoped_ptr
<OutputSurface
> output_surface(
3457 FakeOutputSurface::Create3d(context_owned
.Pass()));
3458 CHECK(output_surface
->BindToClient(&output_surface_client
));
3460 gfx::Size
size(2, 2);
3461 ResourceFormat format
= RGBA_8888
;
3463 int texture_id
= 123;
3465 scoped_ptr
<ResourceProvider
> resource_provider(
3466 ResourceProvider::Create(output_surface
.get(),
3467 shared_bitmap_manager_
.get(),
3468 gpu_memory_buffer_manager_
.get(),
3474 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3476 id
= resource_provider
->CreateResource(
3477 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3478 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3479 GL_INNOCENT_CONTEXT_RESET_ARB
);
3481 resource_provider
->AcquirePixelBuffer(id
);
3483 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3484 EXPECT_FALSE(buffer
);
3485 resource_provider
->UnmapPixelBuffer(id
);
3486 Mock::VerifyAndClearExpectations(context
);
3489 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3490 // Only for GL textures.
3491 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3493 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3494 new StrictMock
<AllocationTrackingContext3D
>);
3495 AllocationTrackingContext3D
* context
= context_owned
.get();
3497 FakeOutputSurfaceClient output_surface_client
;
3498 scoped_ptr
<OutputSurface
> output_surface(
3499 FakeOutputSurface::Create3d(context_owned
.Pass()));
3500 CHECK(output_surface
->BindToClient(&output_surface_client
));
3502 const int kWidth
= 2;
3503 const int kHeight
= 2;
3504 gfx::Size
size(kWidth
, kHeight
);
3505 ResourceFormat format
= RGBA_8888
;
3507 const unsigned kTextureId
= 123u;
3508 const unsigned kImageId
= 234u;
3510 scoped_ptr
<ResourceProvider
> resource_provider(
3511 ResourceProvider::Create(output_surface
.get(),
3512 shared_bitmap_manager_
.get(),
3513 gpu_memory_buffer_manager_
.get(),
3519 id
= resource_provider
->CreateResource(
3520 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3522 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3523 .WillOnce(Return(kImageId
))
3524 .RetiresOnSaturation();
3526 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3527 resource_provider
.get(), id
);
3528 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3531 EXPECT_CALL(*context
, NextTextureId())
3532 .WillOnce(Return(kTextureId
))
3533 .RetiresOnSaturation();
3534 // Once in CreateTextureId and once in BindForSampling
3535 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3536 .RetiresOnSaturation();
3537 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3539 .RetiresOnSaturation();
3541 ResourceProvider::ScopedSamplerGL
lock_gl(
3542 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3543 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3547 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3548 resource_provider
.get(), id
);
3549 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3552 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3553 .RetiresOnSaturation();
3554 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3556 .RetiresOnSaturation();
3557 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3559 .RetiresOnSaturation();
3560 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3562 .RetiresOnSaturation();
3564 ResourceProvider::ScopedSamplerGL
lock_gl(
3565 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3566 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3569 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3571 .RetiresOnSaturation();
3574 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3575 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3577 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3578 new StrictMock
<AllocationTrackingContext3D
>);
3579 AllocationTrackingContext3D
* context
= context_owned
.get();
3580 context_owned
->set_support_sync_query(true);
3582 FakeOutputSurfaceClient output_surface_client
;
3583 scoped_ptr
<OutputSurface
> output_surface(
3584 FakeOutputSurface::Create3d(context_owned
.Pass()));
3585 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3587 const int kWidth
= 2;
3588 const int kHeight
= 2;
3589 gfx::Size
size(kWidth
, kHeight
);
3590 ResourceFormat format
= RGBA_8888
;
3591 ResourceId source_id
= 0;
3592 ResourceId dest_id
= 0;
3593 const unsigned kSourceTextureId
= 123u;
3594 const unsigned kDestTextureId
= 321u;
3595 const unsigned kImageId
= 234u;
3597 scoped_ptr
<ResourceProvider
> resource_provider(
3598 ResourceProvider::Create(output_surface
.get(),
3599 shared_bitmap_manager_
.get(),
3600 gpu_memory_buffer_manager_
.get(),
3606 source_id
= resource_provider
->CreateResource(
3607 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3609 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3610 .WillOnce(Return(kImageId
))
3611 .RetiresOnSaturation();
3613 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3614 resource_provider
.get(), source_id
);
3615 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3617 Mock::VerifyAndClearExpectations(context
);
3619 dest_id
= resource_provider
->CreateResource(
3620 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3622 EXPECT_CALL(*context
, NextTextureId())
3623 .WillOnce(Return(kDestTextureId
))
3624 .RetiresOnSaturation();
3625 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3627 .RetiresOnSaturation();
3628 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3629 GL_UNSIGNED_BYTE
, nullptr))
3631 .RetiresOnSaturation();
3632 EXPECT_CALL(*context
, NextTextureId())
3633 .WillOnce(Return(kSourceTextureId
))
3634 .RetiresOnSaturation();
3635 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3637 .RetiresOnSaturation();
3638 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3640 .RetiresOnSaturation();
3641 resource_provider
->CopyResource(source_id
, dest_id
, gfx::Rect(size
));
3642 Mock::VerifyAndClearExpectations(context
);
3644 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3646 .RetiresOnSaturation();
3647 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3649 .RetiresOnSaturation();
3650 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3652 .RetiresOnSaturation();
3653 resource_provider
->DeleteResource(source_id
);
3654 resource_provider
->DeleteResource(dest_id
);
3657 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3658 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3661 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3662 new AllocationTrackingContext3D
);
3663 AllocationTrackingContext3D
* context
= context_owned
.get();
3664 context_owned
->set_support_compressed_texture_etc1(true);
3666 FakeOutputSurfaceClient output_surface_client
;
3667 scoped_ptr
<OutputSurface
> output_surface(
3668 FakeOutputSurface::Create3d(context_owned
.Pass()));
3669 CHECK(output_surface
->BindToClient(&output_surface_client
));
3671 gfx::Size
size(4, 4);
3672 scoped_ptr
<ResourceProvider
> resource_provider(
3673 ResourceProvider::Create(output_surface
.get(),
3674 shared_bitmap_manager_
.get(),
3675 gpu_memory_buffer_manager_
.get(),
3680 int texture_id
= 123;
3682 ResourceId id
= resource_provider
->CreateResource(
3683 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3685 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3686 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3687 resource_provider
->AllocateForTesting(id
);
3689 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3690 resource_provider
->DeleteResource(id
);
3693 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3694 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3697 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3698 new AllocationTrackingContext3D
);
3699 AllocationTrackingContext3D
* context
= context_owned
.get();
3700 context_owned
->set_support_compressed_texture_etc1(true);
3702 FakeOutputSurfaceClient output_surface_client
;
3703 scoped_ptr
<OutputSurface
> output_surface(
3704 FakeOutputSurface::Create3d(context_owned
.Pass()));
3705 CHECK(output_surface
->BindToClient(&output_surface_client
));
3707 gfx::Size
size(4, 4);
3708 scoped_ptr
<ResourceProvider
> resource_provider(
3709 ResourceProvider::Create(output_surface
.get(),
3710 shared_bitmap_manager_
.get(),
3711 gpu_memory_buffer_manager_
.get(),
3716 int texture_id
= 123;
3719 ResourceId id
= resource_provider
->CreateResource(
3720 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3722 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3723 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3724 EXPECT_CALL(*context
,
3725 compressedTexImage2D(
3726 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3727 resource_provider
->CopyToResource(id
, pixels
, size
);
3729 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3730 resource_provider
->DeleteResource(id
);
3733 INSTANTIATE_TEST_CASE_P(
3734 ResourceProviderTests
,
3735 ResourceProviderTest
,
3736 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3737 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3739 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3741 GLuint
NextTextureId() override
{
3742 base::AutoLock
lock(namespace_
->lock
);
3743 return namespace_
->next_texture_id
++;
3745 void RetireTextureId(GLuint
) override
{}
3746 GLuint
PeekTextureId() {
3747 base::AutoLock
lock(namespace_
->lock
);
3748 return namespace_
->next_texture_id
;
3752 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3753 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3754 new TextureIdAllocationTrackingContext
);
3755 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3757 FakeOutputSurfaceClient output_surface_client
;
3758 scoped_ptr
<OutputSurface
> output_surface(
3759 FakeOutputSurface::Create3d(context_owned
.Pass()));
3760 CHECK(output_surface
->BindToClient(&output_surface_client
));
3761 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3762 new TestSharedBitmapManager());
3764 gfx::Size
size(1, 1);
3765 ResourceFormat format
= RGBA_8888
;
3768 size_t kTextureAllocationChunkSize
= 1;
3769 scoped_ptr
<ResourceProvider
> resource_provider(
3770 ResourceProvider::Create(output_surface
.get(),
3771 shared_bitmap_manager
.get(),
3776 kTextureAllocationChunkSize
));
3778 ResourceId id
= resource_provider
->CreateResource(
3779 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3781 resource_provider
->AllocateForTesting(id
);
3782 Mock::VerifyAndClearExpectations(context
);
3784 DCHECK_EQ(2u, context
->PeekTextureId());
3785 resource_provider
->DeleteResource(id
);
3789 size_t kTextureAllocationChunkSize
= 8;
3790 scoped_ptr
<ResourceProvider
> resource_provider(
3791 ResourceProvider::Create(output_surface
.get(),
3792 shared_bitmap_manager
.get(),
3797 kTextureAllocationChunkSize
));
3799 ResourceId id
= resource_provider
->CreateResource(
3800 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3802 resource_provider
->AllocateForTesting(id
);
3803 Mock::VerifyAndClearExpectations(context
);
3805 DCHECK_EQ(10u, context
->PeekTextureId());
3806 resource_provider
->DeleteResource(id
);