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
,
353 ResourceProvider::ResourceId id
,
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
,
452 ResourceProvider::ResourceId id
,
454 ResourceProvider::ScopedSamplerGL
sampler(
455 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
458 ResourceProviderContext
* context() { return context3d_
; }
460 ResourceProvider::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 ResourceProvider::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 ResourceProvider::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 ResourceProvider::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 ResourceProvider::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 ResourceProvider::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 ResourceProvider::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 ResourceProvider::ResourceId id4
=
679 child_resource_provider_
->CreateResourceFromTextureMailbox(
681 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
682 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
684 ReturnedResourceArray returned_to_child
;
686 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
688 // Transfer some resources to the parent.
689 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
690 resource_ids_to_transfer
.push_back(id1
);
691 resource_ids_to_transfer
.push_back(id2
);
692 resource_ids_to_transfer
.push_back(id3
);
693 resource_ids_to_transfer
.push_back(id4
);
694 TransferableResourceArray list
;
695 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
697 ASSERT_EQ(4u, list
.size());
698 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
699 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
700 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
701 list
[1].mailbox_holder
.sync_point
);
702 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
703 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
704 list
[2].mailbox_holder
.sync_point
);
705 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
706 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
707 list
[0].mailbox_holder
.texture_target
);
708 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
709 list
[1].mailbox_holder
.texture_target
);
710 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
711 list
[2].mailbox_holder
.texture_target
);
712 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
713 list
[3].mailbox_holder
.texture_target
);
714 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
715 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
716 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
717 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
718 resource_provider_
->ReceiveFromChild(child_id
, list
);
719 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
720 context3d_
->last_waited_sync_point());
722 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
723 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
726 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
727 context3d_
->last_waited_sync_point());
728 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
729 resource_ids_to_receive
.insert(id1
);
730 resource_ids_to_receive
.insert(id2
);
731 resource_ids_to_receive
.insert(id3
);
732 resource_ids_to_receive
.insert(id4
);
733 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
734 resource_ids_to_receive
);
737 EXPECT_EQ(4u, resource_provider_
->num_resources());
738 ResourceProvider::ResourceIdMap resource_map
=
739 resource_provider_
->GetChildToParentMap(child_id
);
740 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
741 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
742 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
743 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
744 EXPECT_NE(0u, mapped_id1
);
745 EXPECT_NE(0u, mapped_id2
);
746 EXPECT_NE(0u, mapped_id3
);
747 EXPECT_NE(0u, mapped_id4
);
748 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
749 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
750 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
751 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
753 uint8_t result
[4] = { 0 };
755 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
756 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
759 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
760 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
763 // Check that transfering again the same resource from the child to the
765 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
766 resource_ids_to_transfer
.push_back(id1
);
767 resource_ids_to_transfer
.push_back(id2
);
768 resource_ids_to_transfer
.push_back(id3
);
769 TransferableResourceArray list
;
770 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
772 EXPECT_EQ(3u, list
.size());
773 EXPECT_EQ(id1
, list
[0].id
);
774 EXPECT_EQ(id2
, list
[1].id
);
775 EXPECT_EQ(id3
, list
[2].id
);
776 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
777 list
[0].mailbox_holder
.texture_target
);
778 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
779 list
[1].mailbox_holder
.texture_target
);
780 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
781 list
[2].mailbox_holder
.texture_target
);
782 ReturnedResourceArray returned
;
783 TransferableResource::ReturnResources(list
, &returned
);
784 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
785 // ids were exported twice, we returned them only once, they should still
787 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
788 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
789 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
792 EXPECT_EQ(0u, returned_to_child
.size());
794 // Transfer resources back from the parent to the child. Set no resources as
796 ResourceProvider::ResourceIdSet no_resources
;
797 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
799 ASSERT_EQ(4u, returned_to_child
.size());
800 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
801 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
802 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
803 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
804 EXPECT_FALSE(returned_to_child
[0].lost
);
805 EXPECT_FALSE(returned_to_child
[1].lost
);
806 EXPECT_FALSE(returned_to_child
[2].lost
);
807 EXPECT_FALSE(returned_to_child
[3].lost
);
808 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
809 returned_to_child
.clear();
811 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
812 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
813 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
814 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
817 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
818 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
820 ASSERT_NE(0U, lock
.texture_id());
821 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
822 child_context_
->GetPixels(size
, format
, result
);
823 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
826 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
827 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
829 ASSERT_NE(0U, lock
.texture_id());
830 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
831 child_context_
->GetPixels(size
, format
, result
);
832 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
835 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
836 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
838 ASSERT_NE(0U, lock
.texture_id());
839 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
842 // Transfer resources to the parent again.
843 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
844 resource_ids_to_transfer
.push_back(id1
);
845 resource_ids_to_transfer
.push_back(id2
);
846 resource_ids_to_transfer
.push_back(id3
);
847 resource_ids_to_transfer
.push_back(id4
);
848 TransferableResourceArray list
;
849 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
851 ASSERT_EQ(4u, list
.size());
852 EXPECT_EQ(id1
, list
[0].id
);
853 EXPECT_EQ(id2
, list
[1].id
);
854 EXPECT_EQ(id3
, list
[2].id
);
855 EXPECT_EQ(id4
, list
[3].id
);
856 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
857 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
858 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
859 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
860 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
861 list
[0].mailbox_holder
.texture_target
);
862 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
863 list
[1].mailbox_holder
.texture_target
);
864 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
865 list
[2].mailbox_holder
.texture_target
);
866 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
867 list
[3].mailbox_holder
.texture_target
);
868 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
869 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
870 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
871 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
872 resource_provider_
->ReceiveFromChild(child_id
, list
);
873 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
874 resource_ids_to_receive
.insert(id1
);
875 resource_ids_to_receive
.insert(id2
);
876 resource_ids_to_receive
.insert(id3
);
877 resource_ids_to_receive
.insert(id4
);
878 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
879 resource_ids_to_receive
);
882 EXPECT_EQ(0u, returned_to_child
.size());
884 EXPECT_EQ(4u, resource_provider_
->num_resources());
885 resource_provider_
->DestroyChild(child_id
);
886 EXPECT_EQ(0u, resource_provider_
->num_resources());
888 ASSERT_EQ(4u, returned_to_child
.size());
889 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
890 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
891 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
892 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
893 EXPECT_FALSE(returned_to_child
[0].lost
);
894 EXPECT_FALSE(returned_to_child
[1].lost
);
895 EXPECT_FALSE(returned_to_child
[2].lost
);
896 EXPECT_FALSE(returned_to_child
[3].lost
);
899 class ResourceProviderTestNoSyncPoint
: public ResourceProviderTest
{
901 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
902 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
, GetParam());
906 TEST_P(ResourceProviderTestNoSyncPoint
, TransferGLResources
) {
907 gfx::Size
size(1, 1);
908 ResourceFormat format
= RGBA_8888
;
909 size_t pixel_size
= TextureSizeBytes(size
, format
);
910 ASSERT_EQ(4U, pixel_size
);
912 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
913 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
914 uint8_t data1
[4] = {1, 2, 3, 4};
915 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
917 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
918 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
920 // Ensure locking the memory buffer doesn't create an unnecessary sync
922 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
923 child_resource_provider_
.get(), id2
);
924 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
927 GLuint external_texture_id
= child_context_
->createExternalTexture();
929 // A sync point is specified directly and should be used.
930 gpu::Mailbox external_mailbox
;
931 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
932 child_context_
->produceTextureDirectCHROMIUM(
933 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
934 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
935 ResourceProvider::ResourceId id3
=
936 child_resource_provider_
->CreateResourceFromTextureMailbox(
937 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
938 external_sync_point
),
939 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
941 ReturnedResourceArray returned_to_child
;
943 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
944 resource_provider_
->SetChildNeedsSyncPoints(child_id
, false);
946 // Transfer some resources to the parent.
947 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
948 resource_ids_to_transfer
.push_back(id1
);
949 resource_ids_to_transfer
.push_back(id2
);
950 resource_ids_to_transfer
.push_back(id3
);
951 TransferableResourceArray list
;
952 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
954 ASSERT_EQ(3u, list
.size());
955 // Standard resources shouldn't require creating and sending a sync point.
956 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
957 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
958 // A given sync point should be passed through.
959 EXPECT_EQ(external_sync_point
, list
[2].mailbox_holder
.sync_point
);
960 resource_provider_
->ReceiveFromChild(child_id
, list
);
962 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
963 resource_ids_to_receive
.insert(id1
);
964 resource_ids_to_receive
.insert(id2
);
965 resource_ids_to_receive
.insert(id3
);
966 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
967 resource_ids_to_receive
);
971 EXPECT_EQ(0u, returned_to_child
.size());
973 // Transfer resources back from the parent to the child. Set no resources as
975 ResourceProvider::ResourceIdSet no_resources
;
976 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
978 ASSERT_EQ(3u, returned_to_child
.size());
979 std::map
<ResourceProvider::ResourceId
, unsigned int> returned_sync_points
;
980 for (const auto& returned
: returned_to_child
)
981 returned_sync_points
[returned
.id
] = returned
.sync_point
;
983 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
984 // No new sync point should be created transferring back.
985 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
986 EXPECT_EQ(0u, returned_sync_points
[id1
]);
987 EXPECT_TRUE(returned_sync_points
.find(id2
) != returned_sync_points
.end());
988 EXPECT_EQ(0u, returned_sync_points
[id2
]);
989 // Original sync point given should be returned.
990 EXPECT_TRUE(returned_sync_points
.find(id3
) != returned_sync_points
.end());
991 EXPECT_EQ(external_sync_point
, returned_sync_points
[id3
]);
992 EXPECT_FALSE(returned_to_child
[0].lost
);
993 EXPECT_FALSE(returned_to_child
[1].lost
);
994 EXPECT_FALSE(returned_to_child
[2].lost
);
995 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
996 returned_to_child
.clear();
999 resource_provider_
->DestroyChild(child_id
);
1002 INSTANTIATE_TEST_CASE_P(
1003 ResourceProviderTests
,
1004 ResourceProviderTestNoSyncPoint
,
1005 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
));
1007 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
1008 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1010 gfx::Size
size(1, 1);
1011 ResourceFormat format
= RGBA_8888
;
1013 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1014 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1015 uint8_t data1
[4] = {1, 2, 3, 4};
1016 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1018 ReturnedResourceArray returned_to_child
;
1020 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1022 // Transfer some resources to the parent.
1023 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1024 resource_ids_to_transfer
.push_back(id1
);
1025 TransferableResourceArray list
;
1026 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1028 ASSERT_EQ(1u, list
.size());
1029 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1031 resource_provider_
->ReceiveFromChild(child_id
, list
);
1033 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
1034 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1037 resource_provider_
->DeclareUsedResourcesFromChild(
1038 child_id
, ResourceProvider::ResourceIdSet());
1039 EXPECT_EQ(0u, returned_to_child
.size());
1042 EXPECT_EQ(1u, returned_to_child
.size());
1043 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1046 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
1047 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
1049 child_resource_provider_
->DeleteResource(id1
);
1050 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1051 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1054 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1055 resource_provider_
->DestroyChild(child_id
);
1058 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
1059 // Overlays only supported on the GL path.
1060 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1063 uint32 sync_point
= 0;
1064 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1065 mailbox
.set_allow_overlay(true);
1066 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
1067 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1068 ResourceProvider::ResourceId id1
=
1069 child_resource_provider_
->CreateResourceFromTextureMailbox(
1070 mailbox
, release_callback
.Pass());
1072 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1073 mailbox2
.set_allow_overlay(false);
1074 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
1075 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1076 ResourceProvider::ResourceId id2
=
1077 child_resource_provider_
->CreateResourceFromTextureMailbox(
1078 mailbox2
, release_callback2
.Pass());
1080 ReturnedResourceArray returned_to_child
;
1082 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1084 // Transfer some resources to the parent.
1085 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1086 resource_ids_to_transfer
.push_back(id1
);
1087 resource_ids_to_transfer
.push_back(id2
);
1088 TransferableResourceArray list
;
1089 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1091 ASSERT_EQ(2u, list
.size());
1092 resource_provider_
->ReceiveFromChild(child_id
, list
);
1093 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
1094 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
1096 resource_provider_
->DeclareUsedResourcesFromChild(
1097 child_id
, ResourceProvider::ResourceIdSet());
1099 EXPECT_EQ(2u, returned_to_child
.size());
1100 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1102 child_resource_provider_
->DeleteResource(id1
);
1103 child_resource_provider_
->DeleteResource(id2
);
1104 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1106 resource_provider_
->DestroyChild(child_id
);
1109 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
1110 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1113 gfx::Size
size(1, 1);
1114 ResourceFormat format
= RGBA_8888
;
1115 size_t pixel_size
= TextureSizeBytes(size
, format
);
1116 ASSERT_EQ(4U, pixel_size
);
1118 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1119 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1120 uint8_t data1
[4] = { 1, 2, 3, 4 };
1121 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1123 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1124 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1125 uint8_t data2
[4] = { 5, 5, 5, 5 };
1126 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1128 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1129 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1130 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1131 ResourceProvider::ResourceId id3
=
1132 child_resource_provider_
->CreateResourceFromTextureMailbox(
1133 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1134 SingleReleaseCallbackImpl::Create(base::Bind(
1135 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1137 ReturnedResourceArray returned_to_child
;
1139 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1141 // Transfer some resources to the parent.
1142 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1143 resource_ids_to_transfer
.push_back(id1
);
1144 resource_ids_to_transfer
.push_back(id2
);
1145 resource_ids_to_transfer
.push_back(id3
);
1146 TransferableResourceArray list
;
1147 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1149 ASSERT_EQ(3u, list
.size());
1150 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1151 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1152 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1153 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1154 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1155 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1156 resource_provider_
->ReceiveFromChild(child_id
, list
);
1157 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1158 resource_ids_to_receive
.insert(id1
);
1159 resource_ids_to_receive
.insert(id2
);
1160 resource_ids_to_receive
.insert(id3
);
1161 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1162 resource_ids_to_receive
);
1165 EXPECT_EQ(3u, resource_provider_
->num_resources());
1166 ResourceProvider::ResourceIdMap resource_map
=
1167 resource_provider_
->GetChildToParentMap(child_id
);
1168 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1169 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1170 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1171 EXPECT_NE(0u, mapped_id1
);
1172 EXPECT_NE(0u, mapped_id2
);
1173 EXPECT_NE(0u, mapped_id3
);
1174 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1175 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1176 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1178 uint8_t result
[4] = { 0 };
1180 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1181 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1184 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1185 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1188 // Check that transfering again the same resource from the child to the
1190 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1191 resource_ids_to_transfer
.push_back(id1
);
1192 resource_ids_to_transfer
.push_back(id2
);
1193 TransferableResourceArray list
;
1194 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1196 EXPECT_EQ(2u, list
.size());
1197 EXPECT_EQ(id1
, list
[0].id
);
1198 EXPECT_EQ(id2
, list
[1].id
);
1199 ReturnedResourceArray returned
;
1200 TransferableResource::ReturnResources(list
, &returned
);
1201 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1202 // ids were exported twice, we returned them only once, they should still
1204 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1205 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1208 EXPECT_EQ(0u, returned_to_child
.size());
1210 // Transfer resources back from the parent to the child. Set no resources as
1212 ResourceProvider::ResourceIdSet no_resources
;
1213 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1215 ASSERT_EQ(3u, returned_to_child
.size());
1216 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1217 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1218 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1219 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1220 expected_ids
.insert(id1
);
1221 expected_ids
.insert(id2
);
1222 expected_ids
.insert(id3
);
1223 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1224 for (unsigned i
= 0; i
< 3; i
++)
1225 returned_ids
.insert(returned_to_child
[i
].id
);
1226 EXPECT_EQ(expected_ids
, returned_ids
);
1227 EXPECT_FALSE(returned_to_child
[0].lost
);
1228 EXPECT_FALSE(returned_to_child
[1].lost
);
1229 EXPECT_FALSE(returned_to_child
[2].lost
);
1230 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1231 returned_to_child
.clear();
1233 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1234 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1235 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1238 ResourceProvider::ScopedReadLockSoftware
lock(
1239 child_resource_provider_
.get(), id1
);
1240 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1241 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1242 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1243 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1246 ResourceProvider::ScopedReadLockSoftware
lock(
1247 child_resource_provider_
.get(), id2
);
1248 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1249 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1250 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1251 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1254 // Transfer resources to the parent again.
1255 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1256 resource_ids_to_transfer
.push_back(id1
);
1257 resource_ids_to_transfer
.push_back(id2
);
1258 resource_ids_to_transfer
.push_back(id3
);
1259 TransferableResourceArray list
;
1260 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1262 ASSERT_EQ(3u, list
.size());
1263 EXPECT_EQ(id1
, list
[0].id
);
1264 EXPECT_EQ(id2
, list
[1].id
);
1265 EXPECT_EQ(id3
, list
[2].id
);
1266 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1267 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1268 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1269 resource_provider_
->ReceiveFromChild(child_id
, list
);
1270 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1271 resource_ids_to_receive
.insert(id1
);
1272 resource_ids_to_receive
.insert(id2
);
1273 resource_ids_to_receive
.insert(id3
);
1274 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1275 resource_ids_to_receive
);
1278 EXPECT_EQ(0u, returned_to_child
.size());
1280 EXPECT_EQ(3u, resource_provider_
->num_resources());
1281 resource_provider_
->DestroyChild(child_id
);
1282 EXPECT_EQ(0u, resource_provider_
->num_resources());
1284 ASSERT_EQ(3u, returned_to_child
.size());
1285 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1286 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1287 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1288 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1289 expected_ids
.insert(id1
);
1290 expected_ids
.insert(id2
);
1291 expected_ids
.insert(id3
);
1292 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1293 for (unsigned i
= 0; i
< 3; i
++)
1294 returned_ids
.insert(returned_to_child
[i
].id
);
1295 EXPECT_EQ(expected_ids
, returned_ids
);
1296 EXPECT_FALSE(returned_to_child
[0].lost
);
1297 EXPECT_FALSE(returned_to_child
[1].lost
);
1298 EXPECT_FALSE(returned_to_child
[2].lost
);
1301 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1302 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1305 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1306 ResourceProviderContext::Create(shared_data_
.get()));
1308 FakeOutputSurfaceClient child_output_surface_client
;
1309 scoped_ptr
<OutputSurface
> child_output_surface(
1310 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1311 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1313 scoped_ptr
<ResourceProvider
> child_resource_provider(
1314 ResourceProvider::Create(child_output_surface
.get(),
1315 shared_bitmap_manager_
.get(),
1316 gpu_memory_buffer_manager_
.get(),
1322 gfx::Size
size(1, 1);
1323 ResourceFormat format
= RGBA_8888
;
1324 size_t pixel_size
= TextureSizeBytes(size
, format
);
1325 ASSERT_EQ(4U, pixel_size
);
1327 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1328 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1329 uint8_t data1
[4] = { 1, 2, 3, 4 };
1330 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1332 ReturnedResourceArray returned_to_child
;
1334 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1336 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1337 resource_ids_to_transfer
.push_back(id1
);
1338 TransferableResourceArray list
;
1339 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1341 ASSERT_EQ(1u, list
.size());
1342 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1343 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1344 list
[0].mailbox_holder
.texture_target
);
1345 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1346 resource_provider_
->ReceiveFromChild(child_id
, list
);
1349 EXPECT_EQ(0u, resource_provider_
->num_resources());
1350 ASSERT_EQ(1u, returned_to_child
.size());
1351 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1352 ResourceProvider::ResourceIdMap resource_map
=
1353 resource_provider_
->GetChildToParentMap(child_id
);
1354 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1355 EXPECT_EQ(0u, mapped_id1
);
1357 resource_provider_
->DestroyChild(child_id
);
1358 EXPECT_EQ(0u, resource_provider_
->num_resources());
1360 ASSERT_EQ(1u, returned_to_child
.size());
1361 EXPECT_FALSE(returned_to_child
[0].lost
);
1364 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1365 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1368 gfx::Size
size(1, 1);
1369 ResourceFormat format
= RGBA_8888
;
1370 size_t pixel_size
= TextureSizeBytes(size
, format
);
1371 ASSERT_EQ(4U, pixel_size
);
1373 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1374 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1375 uint8_t data1
[4] = { 1, 2, 3, 4 };
1376 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1378 ReturnedResourceArray returned_to_child
;
1380 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1382 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1383 resource_ids_to_transfer
.push_back(id1
);
1384 TransferableResourceArray list
;
1385 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1387 ASSERT_EQ(1u, list
.size());
1389 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1390 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1391 resource_provider_
->ReceiveFromChild(child_id
, list
);
1394 EXPECT_EQ(1u, resource_provider_
->num_resources());
1395 EXPECT_EQ(0u, returned_to_child
.size());
1397 ResourceProvider::ResourceIdMap resource_map
=
1398 resource_provider_
->GetChildToParentMap(child_id
);
1399 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1400 EXPECT_NE(0u, mapped_id1
);
1402 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1404 EXPECT_FALSE(lock
.valid());
1407 resource_provider_
->DestroyChild(child_id
);
1408 EXPECT_EQ(0u, resource_provider_
->num_resources());
1410 ASSERT_EQ(1u, returned_to_child
.size());
1411 EXPECT_FALSE(returned_to_child
[0].lost
);
1414 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1415 gfx::Size
size(1, 1);
1416 ResourceFormat format
= RGBA_8888
;
1417 size_t pixel_size
= TextureSizeBytes(size
, format
);
1418 ASSERT_EQ(4U, pixel_size
);
1420 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1421 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1422 uint8_t data1
[4] = { 1, 2, 3, 4 };
1423 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1425 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1426 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1427 uint8_t data2
[4] = {5, 5, 5, 5};
1428 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1430 ReturnedResourceArray returned_to_child
;
1432 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1434 // Transfer some resources to the parent.
1435 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1436 resource_ids_to_transfer
.push_back(id1
);
1437 resource_ids_to_transfer
.push_back(id2
);
1438 TransferableResourceArray list
;
1439 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1441 ASSERT_EQ(2u, list
.size());
1442 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1443 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1444 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1446 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1447 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1448 resource_provider_
->ReceiveFromChild(child_id
, list
);
1449 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1450 resource_ids_to_receive
.insert(id1
);
1451 resource_ids_to_receive
.insert(id2
);
1452 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1453 resource_ids_to_receive
);
1456 EXPECT_EQ(2u, resource_provider_
->num_resources());
1457 ResourceProvider::ResourceIdMap resource_map
=
1458 resource_provider_
->GetChildToParentMap(child_id
);
1459 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1460 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1461 EXPECT_NE(0u, mapped_id1
);
1462 EXPECT_NE(0u, mapped_id2
);
1463 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1464 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1467 // The parent transfers the resources to the grandparent.
1468 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1469 resource_ids_to_transfer
.push_back(mapped_id1
);
1470 resource_ids_to_transfer
.push_back(mapped_id2
);
1471 TransferableResourceArray list
;
1472 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1474 ASSERT_EQ(2u, list
.size());
1475 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1476 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1477 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1479 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1480 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1482 // Release the resource in the parent. Set no resources as being in use. The
1483 // resources are exported so that can't be transferred back yet.
1484 ResourceProvider::ResourceIdSet no_resources
;
1485 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1487 EXPECT_EQ(0u, returned_to_child
.size());
1488 EXPECT_EQ(2u, resource_provider_
->num_resources());
1490 // Return the resources from the grandparent to the parent. They should be
1491 // returned to the child then.
1492 EXPECT_EQ(2u, list
.size());
1493 EXPECT_EQ(mapped_id1
, list
[0].id
);
1494 EXPECT_EQ(mapped_id2
, list
[1].id
);
1495 ReturnedResourceArray returned
;
1496 TransferableResource::ReturnResources(list
, &returned
);
1497 resource_provider_
->ReceiveReturnsFromParent(returned
);
1499 EXPECT_EQ(0u, resource_provider_
->num_resources());
1500 ASSERT_EQ(2u, returned_to_child
.size());
1501 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1502 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1503 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1505 EXPECT_FALSE(returned_to_child
[0].lost
);
1506 EXPECT_FALSE(returned_to_child
[1].lost
);
1510 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1511 gfx::Size
size(1, 1);
1512 ResourceFormat format
= RGBA_8888
;
1513 size_t pixel_size
= TextureSizeBytes(size
, format
);
1514 ASSERT_EQ(4U, pixel_size
);
1516 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1517 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1518 uint8_t data1
[4] = {1, 2, 3, 4};
1519 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1521 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1522 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1523 uint8_t data2
[4] = {5, 5, 5, 5};
1524 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1526 ReturnedResourceArray returned_to_child
;
1528 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1530 // Transfer some resources to the parent.
1531 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1532 resource_ids_to_transfer
.push_back(id1
);
1533 resource_ids_to_transfer
.push_back(id2
);
1534 TransferableResourceArray list
;
1535 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1537 ASSERT_EQ(2u, list
.size());
1538 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1539 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1540 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1542 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1543 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1544 resource_provider_
->ReceiveFromChild(child_id
, list
);
1545 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1546 resource_ids_to_receive
.insert(id1
);
1547 resource_ids_to_receive
.insert(id2
);
1548 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1549 resource_ids_to_receive
);
1552 EXPECT_EQ(2u, resource_provider_
->num_resources());
1553 ResourceProvider::ResourceIdMap resource_map
=
1554 resource_provider_
->GetChildToParentMap(child_id
);
1555 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1556 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1557 EXPECT_NE(0u, mapped_id1
);
1558 EXPECT_NE(0u, mapped_id2
);
1559 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1560 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1563 // The parent transfers the resources to the grandparent.
1564 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1565 resource_ids_to_transfer
.push_back(mapped_id1
);
1566 resource_ids_to_transfer
.push_back(mapped_id2
);
1567 TransferableResourceArray list
;
1568 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1570 ASSERT_EQ(2u, list
.size());
1571 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1572 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1573 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1575 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1576 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1578 // Release the resource in the parent. Set no resources as being in use. The
1579 // resources are exported so that can't be transferred back yet.
1580 ResourceProvider::ResourceIdSet no_resources
;
1581 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1583 // Destroy the child, the resources should not be returned yet.
1584 EXPECT_EQ(0u, returned_to_child
.size());
1585 EXPECT_EQ(2u, resource_provider_
->num_resources());
1587 resource_provider_
->DestroyChild(child_id
);
1589 EXPECT_EQ(2u, resource_provider_
->num_resources());
1590 ASSERT_EQ(0u, returned_to_child
.size());
1592 // Return a resource from the grandparent, it should be returned at this
1594 EXPECT_EQ(2u, list
.size());
1595 EXPECT_EQ(mapped_id1
, list
[0].id
);
1596 EXPECT_EQ(mapped_id2
, list
[1].id
);
1597 TransferableResourceArray return_list
;
1598 return_list
.push_back(list
[1]);
1600 ReturnedResourceArray returned
;
1601 TransferableResource::ReturnResources(return_list
, &returned
);
1602 resource_provider_
->ReceiveReturnsFromParent(returned
);
1604 EXPECT_EQ(1u, resource_provider_
->num_resources());
1605 ASSERT_EQ(1u, returned_to_child
.size());
1606 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1607 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1609 EXPECT_FALSE(returned_to_child
[0].lost
);
1610 returned_to_child
.clear();
1612 // Destroy the parent resource provider. The resource that's left should be
1613 // lost at this point, and returned.
1614 resource_provider_
= nullptr;
1615 ASSERT_EQ(1u, returned_to_child
.size());
1616 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1617 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1619 EXPECT_TRUE(returned_to_child
[0].lost
);
1623 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1624 gfx::Size
size(1, 1);
1625 ResourceFormat format
= RGBA_8888
;
1626 size_t pixel_size
= TextureSizeBytes(size
, format
);
1627 ASSERT_EQ(4U, pixel_size
);
1629 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1630 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1631 uint8_t data
[4] = { 1, 2, 3, 4 };
1632 child_resource_provider_
->CopyToResource(id
, data
, size
);
1634 ReturnedResourceArray returned_to_child
;
1636 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1638 // Transfer some resource to the parent.
1639 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1640 resource_ids_to_transfer
.push_back(id
);
1641 TransferableResourceArray list
;
1642 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1644 ASSERT_EQ(1u, list
.size());
1645 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1646 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1647 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1648 resource_provider_
->ReceiveFromChild(child_id
, list
);
1649 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1650 resource_ids_to_receive
.insert(id
);
1651 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1652 resource_ids_to_receive
);
1655 // Delete textures in the child, while they are transfered.
1656 child_resource_provider_
->DeleteResource(id
);
1657 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1659 EXPECT_EQ(0u, returned_to_child
.size());
1661 // Transfer resources back from the parent to the child. Set no resources as
1663 ResourceProvider::ResourceIdSet no_resources
;
1664 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1666 ASSERT_EQ(1u, returned_to_child
.size());
1667 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1668 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1669 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1671 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1674 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1675 gfx::Size
size(1, 1);
1676 ResourceFormat format
= RGBA_8888
;
1677 size_t pixel_size
= TextureSizeBytes(size
, format
);
1678 ASSERT_EQ(4U, pixel_size
);
1680 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1681 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1682 uint8_t data
[4] = {1, 2, 3, 4};
1683 child_resource_provider_
->CopyToResource(id
, data
, size
);
1685 ReturnedResourceArray returned_to_child
;
1687 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1688 const ResourceProvider::ResourceIdMap
& map
=
1689 resource_provider_
->GetChildToParentMap(child_id
);
1691 // Transfer some resource to the parent.
1692 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1693 resource_ids_to_transfer
.push_back(id
);
1694 TransferableResourceArray list
;
1695 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1697 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1698 resource_provider_
->ReceiveFromChild(child_id
, list
);
1699 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1700 resource_ids_to_receive
.insert(id
);
1701 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1702 resource_ids_to_receive
);
1704 TransferableResourceArray sent_to_top_level
;
1706 // Parent transfers to top-level.
1707 ASSERT_TRUE(map
.find(id
) != map
.end());
1708 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1709 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1710 resource_ids_to_transfer
.push_back(parent_id
);
1711 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1712 &sent_to_top_level
);
1713 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1716 // Stop using resource.
1717 ResourceProvider::ResourceIdSet empty
;
1718 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1719 // Resource is not yet returned to the child, since it's in use by the
1721 EXPECT_TRUE(returned_to_child
.empty());
1724 // Send the resource to the parent again.
1725 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1726 resource_ids_to_transfer
.push_back(id
);
1727 TransferableResourceArray list
;
1728 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1730 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1731 resource_provider_
->ReceiveFromChild(child_id
, list
);
1732 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1733 resource_ids_to_receive
.insert(id
);
1734 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1735 resource_ids_to_receive
);
1738 // Receive returns back from top-level.
1739 ReturnedResourceArray returned
;
1740 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1741 resource_provider_
->ReceiveReturnsFromParent(returned
);
1742 // Resource is still not yet returned to the child, since it's declared used
1744 EXPECT_TRUE(returned_to_child
.empty());
1745 ASSERT_TRUE(map
.find(id
) != map
.end());
1746 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1747 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1750 sent_to_top_level
.clear();
1751 // Parent transfers again to top-level.
1752 ASSERT_TRUE(map
.find(id
) != map
.end());
1753 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1754 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1755 resource_ids_to_transfer
.push_back(parent_id
);
1756 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1757 &sent_to_top_level
);
1758 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1761 // Receive returns back from top-level.
1762 ReturnedResourceArray returned
;
1763 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1764 resource_provider_
->ReceiveReturnsFromParent(returned
);
1765 // Resource is still not yet returned to the child, since it's still
1766 // declared used in the parent.
1767 EXPECT_TRUE(returned_to_child
.empty());
1768 ASSERT_TRUE(map
.find(id
) != map
.end());
1769 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1770 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1773 // Stop using resource.
1774 ResourceProvider::ResourceIdSet empty
;
1775 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1776 // Resource should have been returned to the child, since it's no longer in
1777 // use by the top-level.
1778 ASSERT_EQ(1u, returned_to_child
.size());
1779 EXPECT_EQ(id
, returned_to_child
[0].id
);
1780 EXPECT_EQ(2, returned_to_child
[0].count
);
1781 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1782 returned_to_child
.clear();
1783 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1787 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1789 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1790 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1791 new TextureStateTrackingContext
);
1792 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1794 FakeOutputSurfaceClient child_output_surface_client
;
1795 scoped_ptr
<OutputSurface
> child_output_surface(
1796 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1797 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1798 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1799 new TestSharedBitmapManager());
1801 scoped_ptr
<ResourceProvider
> child_resource_provider(
1802 ResourceProvider::Create(child_output_surface
.get(),
1803 shared_bitmap_manager
.get(),
1810 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1811 new TextureStateTrackingContext
);
1812 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1814 FakeOutputSurfaceClient parent_output_surface_client
;
1815 scoped_ptr
<OutputSurface
> parent_output_surface(
1816 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1817 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1819 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1820 ResourceProvider::Create(parent_output_surface
.get(),
1821 shared_bitmap_manager
.get(),
1828 gfx::Size
size(1, 1);
1829 ResourceFormat format
= RGBA_8888
;
1830 int child_texture_id
= 1;
1831 int parent_texture_id
= 2;
1833 size_t pixel_size
= TextureSizeBytes(size
, format
);
1834 ASSERT_EQ(4U, pixel_size
);
1836 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1837 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1840 // The new texture is created with GL_LINEAR.
1841 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1842 .Times(2); // Once to create and once to allocate.
1843 EXPECT_CALL(*child_context
,
1844 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1845 EXPECT_CALL(*child_context
,
1846 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1849 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1852 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1853 EXPECT_CALL(*child_context
,
1854 texParameteri(GL_TEXTURE_2D
,
1855 GL_TEXTURE_POOL_CHROMIUM
,
1856 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1857 child_resource_provider
->AllocateForTesting(id
);
1858 Mock::VerifyAndClearExpectations(child_context
);
1860 uint8_t data
[4] = { 1, 2, 3, 4 };
1862 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1863 child_resource_provider
->CopyToResource(id
, data
, size
);
1864 Mock::VerifyAndClearExpectations(child_context
);
1866 // The texture is set to |child_filter| in the child.
1867 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1868 if (child_filter
!= GL_LINEAR
) {
1871 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1874 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1876 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1877 Mock::VerifyAndClearExpectations(child_context
);
1879 ReturnedResourceArray returned_to_child
;
1880 int child_id
= parent_resource_provider
->CreateChild(
1881 GetReturnCallback(&returned_to_child
));
1883 // Transfer some resource to the parent.
1884 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1885 resource_ids_to_transfer
.push_back(id
);
1886 TransferableResourceArray list
;
1888 EXPECT_CALL(*child_context
,
1889 produceTextureDirectCHROMIUM(_
, GL_TEXTURE_2D
, _
));
1890 EXPECT_CALL(*child_context
, insertSyncPoint());
1891 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1893 Mock::VerifyAndClearExpectations(child_context
);
1895 ASSERT_EQ(1u, list
.size());
1896 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1898 EXPECT_CALL(*parent_context
,
1899 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, _
))
1900 .WillOnce(Return(parent_texture_id
));
1902 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1904 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1905 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1908 Mock::VerifyAndClearExpectations(parent_context
);
1910 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1911 resource_ids_to_receive
.insert(id
);
1912 parent_resource_provider
->DeclareUsedResourcesFromChild(
1913 child_id
, resource_ids_to_receive
);
1914 Mock::VerifyAndClearExpectations(parent_context
);
1916 ResourceProvider::ResourceIdMap resource_map
=
1917 parent_resource_provider
->GetChildToParentMap(child_id
);
1918 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1919 EXPECT_NE(0u, mapped_id
);
1921 // The texture is set to |parent_filter| in the parent.
1922 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1925 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1928 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1929 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1930 Mock::VerifyAndClearExpectations(parent_context
);
1932 // The texture should be reset to |child_filter| in the parent when it is
1933 // returned, since that is how it was received.
1934 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1937 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1940 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1943 EXPECT_EQ(0u, returned_to_child
.size());
1945 // Transfer resources back from the parent to the child. Set no resources
1947 ResourceProvider::ResourceIdSet no_resources
;
1948 EXPECT_CALL(*parent_context
, insertSyncPoint());
1949 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1951 Mock::VerifyAndClearExpectations(parent_context
);
1953 ASSERT_EQ(1u, returned_to_child
.size());
1954 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1957 // The child remembers the texture filter is set to |child_filter|.
1958 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1959 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1960 Mock::VerifyAndClearExpectations(child_context
);
1964 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1965 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1967 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1970 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1971 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1973 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1976 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1977 // Other mailbox transfers tested elsewhere.
1978 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1980 unsigned texture
= context()->createTexture();
1981 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1982 uint8_t data
[4] = { 1, 2, 3, 4 };
1983 context()->texImage2D(
1984 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1985 gpu::Mailbox mailbox
;
1986 context()->genMailboxCHROMIUM(mailbox
.name
);
1987 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
1988 uint32 sync_point
= context()->insertSyncPoint();
1990 // All the logic below assumes that the sync points are all positive.
1991 EXPECT_LT(0u, sync_point
);
1993 uint32 release_sync_point
= 0;
1994 bool lost_resource
= false;
1995 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1996 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1997 &release_sync_point
,
1999 &main_thread_task_runner
);
2000 ResourceProvider::ResourceId resource
=
2001 resource_provider_
->CreateResourceFromTextureMailbox(
2002 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2003 SingleReleaseCallbackImpl::Create(callback
));
2004 EXPECT_EQ(1u, context()->NumTextures());
2005 EXPECT_EQ(0u, release_sync_point
);
2007 // Transfer the resource, expect the sync points to be consistent.
2008 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2009 resource_ids_to_transfer
.push_back(resource
);
2010 TransferableResourceArray list
;
2011 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2012 ASSERT_EQ(1u, list
.size());
2013 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2015 memcmp(mailbox
.name
,
2016 list
[0].mailbox_holder
.mailbox
.name
,
2017 sizeof(mailbox
.name
)));
2018 EXPECT_EQ(0u, release_sync_point
);
2020 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2021 unsigned other_texture
=
2022 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2023 uint8_t test_data
[4] = { 0 };
2024 context()->GetPixels(
2025 gfx::Size(1, 1), RGBA_8888
, test_data
);
2026 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2028 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2030 context()->deleteTexture(other_texture
);
2031 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2032 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2034 // Receive the resource, then delete it, expect the sync points to be
2036 ReturnedResourceArray returned
;
2037 TransferableResource::ReturnResources(list
, &returned
);
2038 resource_provider_
->ReceiveReturnsFromParent(returned
);
2039 EXPECT_EQ(1u, context()->NumTextures());
2040 EXPECT_EQ(0u, release_sync_point
);
2042 resource_provider_
->DeleteResource(resource
);
2043 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2044 EXPECT_FALSE(lost_resource
);
2045 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2048 // We're going to do the same thing as above, but testing the case where we
2049 // delete the resource before we receive it back.
2050 sync_point
= release_sync_point
;
2051 EXPECT_LT(0u, sync_point
);
2052 release_sync_point
= 0;
2053 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
2054 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2055 SingleReleaseCallbackImpl::Create(callback
));
2056 EXPECT_EQ(1u, context()->NumTextures());
2057 EXPECT_EQ(0u, release_sync_point
);
2059 // Transfer the resource, expect the sync points to be consistent.
2060 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2061 resource_ids_to_transfer
.push_back(resource
);
2062 TransferableResourceArray list
;
2063 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2064 ASSERT_EQ(1u, list
.size());
2065 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2067 memcmp(mailbox
.name
,
2068 list
[0].mailbox_holder
.mailbox
.name
,
2069 sizeof(mailbox
.name
)));
2070 EXPECT_EQ(0u, release_sync_point
);
2072 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2073 unsigned other_texture
=
2074 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2075 uint8_t test_data
[4] = { 0 };
2076 context()->GetPixels(
2077 gfx::Size(1, 1), RGBA_8888
, test_data
);
2078 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2080 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2082 context()->deleteTexture(other_texture
);
2083 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2084 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2086 // Delete the resource, which shouldn't do anything.
2087 resource_provider_
->DeleteResource(resource
);
2088 EXPECT_EQ(1u, context()->NumTextures());
2089 EXPECT_EQ(0u, release_sync_point
);
2091 // Then receive the resource which should release the mailbox, expect the
2092 // sync points to be consistent.
2093 ReturnedResourceArray returned
;
2094 TransferableResource::ReturnResources(list
, &returned
);
2095 resource_provider_
->ReceiveReturnsFromParent(returned
);
2096 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2097 EXPECT_FALSE(lost_resource
);
2098 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2101 context()->waitSyncPoint(release_sync_point
);
2103 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2104 context()->deleteTexture(texture
);
2107 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
2108 gfx::Size
size(1, 1);
2109 ResourceFormat format
= RGBA_8888
;
2110 ResourceProvider::ResourceId resource
=
2111 child_resource_provider_
->CreateResource(
2112 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2114 child_resource_provider_
->AllocateForTesting(resource
);
2115 // Expect a GL resource to be lost.
2116 bool should_lose_resource
=
2117 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
2119 ReturnedResourceArray returned_to_child
;
2121 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2123 // Transfer the resource to the parent.
2124 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2125 resource_ids_to_transfer
.push_back(resource
);
2126 TransferableResourceArray list
;
2127 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2129 EXPECT_EQ(1u, list
.size());
2131 resource_provider_
->ReceiveFromChild(child_id
, list
);
2132 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2133 resource_ids_to_receive
.insert(resource
);
2134 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2135 resource_ids_to_receive
);
2138 // Lose the output surface in the parent.
2139 resource_provider_
->DidLoseOutputSurface();
2142 EXPECT_EQ(0u, returned_to_child
.size());
2144 // Transfer resources back from the parent to the child. Set no resources as
2146 ResourceProvider::ResourceIdSet no_resources
;
2147 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2149 // Expect a GL resource to be lost.
2150 ASSERT_EQ(1u, returned_to_child
.size());
2151 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2152 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2153 returned_to_child
.clear();
2156 // A GL resource should be lost.
2157 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2159 // Lost resources stay in use in the parent forever.
2160 EXPECT_EQ(should_lose_resource
,
2161 child_resource_provider_
->InUseByConsumer(resource
));
2164 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2165 gfx::Size
size(1, 1);
2166 ResourceFormat format
= RGBA_8888
;
2167 ResourceProvider::ResourceId resource
=
2168 child_resource_provider_
->CreateResource(
2169 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2171 child_resource_provider_
->AllocateForTesting(resource
);
2173 ReturnedResourceArray returned_to_child
;
2175 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2177 // Transfer the resource to the parent.
2178 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2179 resource_ids_to_transfer
.push_back(resource
);
2180 TransferableResourceArray list
;
2181 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2183 EXPECT_EQ(1u, list
.size());
2185 resource_provider_
->ReceiveFromChild(child_id
, list
);
2186 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2187 resource_ids_to_receive
.insert(resource
);
2188 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2189 resource_ids_to_receive
);
2193 ResourceProvider::ResourceIdMap resource_map
=
2194 resource_provider_
->GetChildToParentMap(child_id
);
2195 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2196 EXPECT_NE(0u, parent_resource
);
2198 // Transfer to a grandparent.
2199 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2200 resource_ids_to_transfer
.push_back(parent_resource
);
2201 TransferableResourceArray list
;
2202 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2204 // Receive back a lost resource from the grandparent.
2205 EXPECT_EQ(1u, list
.size());
2206 EXPECT_EQ(parent_resource
, list
[0].id
);
2207 ReturnedResourceArray returned
;
2208 TransferableResource::ReturnResources(list
, &returned
);
2209 EXPECT_EQ(1u, returned
.size());
2210 EXPECT_EQ(parent_resource
, returned
[0].id
);
2211 returned
[0].lost
= true;
2212 resource_provider_
->ReceiveReturnsFromParent(returned
);
2214 // The resource should be lost.
2215 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2217 // Lost resources stay in use in the parent forever.
2218 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2222 EXPECT_EQ(0u, returned_to_child
.size());
2224 // Transfer resources back from the parent to the child. Set no resources as
2226 ResourceProvider::ResourceIdSet no_resources
;
2227 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2229 // Expect the resource to be lost.
2230 ASSERT_EQ(1u, returned_to_child
.size());
2231 EXPECT_TRUE(returned_to_child
[0].lost
);
2232 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2233 returned_to_child
.clear();
2236 // The resource should be lost.
2237 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2239 // Lost resources stay in use in the parent forever.
2240 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2243 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2244 uint32 release_sync_point
= 0;
2245 bool lost_resource
= false;
2246 bool release_called
= false;
2247 uint32 sync_point
= 0;
2248 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2249 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2251 ReturnedResourceArray returned_to_child
;
2253 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2255 // Transfer the resource to the parent.
2256 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2257 resource_ids_to_transfer
.push_back(resource
);
2258 TransferableResourceArray list
;
2259 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2261 EXPECT_EQ(1u, list
.size());
2263 resource_provider_
->ReceiveFromChild(child_id
, list
);
2264 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2265 resource_ids_to_receive
.insert(resource
);
2266 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2267 resource_ids_to_receive
);
2270 // Lose the output surface in the parent.
2271 resource_provider_
->DidLoseOutputSurface();
2274 EXPECT_EQ(0u, returned_to_child
.size());
2276 // Transfer resources back from the parent to the child. Set no resources as
2278 ResourceProvider::ResourceIdSet no_resources
;
2279 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2281 ASSERT_EQ(1u, returned_to_child
.size());
2282 // Losing an output surface only loses hardware resources.
2283 EXPECT_EQ(returned_to_child
[0].lost
,
2284 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2285 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2286 returned_to_child
.clear();
2289 // Delete the resource in the child. Expect the resource to be lost if it's
2291 child_resource_provider_
->DeleteResource(resource
);
2292 EXPECT_EQ(lost_resource
,
2293 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2296 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2297 uint32 release_sync_point
= 0;
2298 bool lost_resource
= false;
2299 bool release_called
= false;
2300 uint32 sync_point
= 0;
2301 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2302 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2304 ReturnedResourceArray returned_to_child
;
2306 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2308 // Transfer the resource to the parent.
2309 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2310 resource_ids_to_transfer
.push_back(resource
);
2311 TransferableResourceArray list
;
2312 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2314 EXPECT_EQ(1u, list
.size());
2316 resource_provider_
->ReceiveFromChild(child_id
, list
);
2317 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2318 resource_ids_to_receive
.insert(resource
);
2319 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2320 resource_ids_to_receive
);
2324 ResourceProvider::ResourceIdMap resource_map
=
2325 resource_provider_
->GetChildToParentMap(child_id
);
2326 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2327 EXPECT_NE(0u, parent_resource
);
2329 // Transfer to a grandparent.
2330 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2331 resource_ids_to_transfer
.push_back(parent_resource
);
2332 TransferableResourceArray list
;
2333 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2335 // Receive back a lost resource from the grandparent.
2336 EXPECT_EQ(1u, list
.size());
2337 EXPECT_EQ(parent_resource
, list
[0].id
);
2338 ReturnedResourceArray returned
;
2339 TransferableResource::ReturnResources(list
, &returned
);
2340 EXPECT_EQ(1u, returned
.size());
2341 EXPECT_EQ(parent_resource
, returned
[0].id
);
2342 returned
[0].lost
= true;
2343 resource_provider_
->ReceiveReturnsFromParent(returned
);
2347 EXPECT_EQ(0u, returned_to_child
.size());
2349 // Transfer resources back from the parent to the child. Set no resources as
2351 ResourceProvider::ResourceIdSet no_resources
;
2352 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2354 // Expect the resource to be lost.
2355 ASSERT_EQ(1u, returned_to_child
.size());
2356 EXPECT_TRUE(returned_to_child
[0].lost
);
2357 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2358 returned_to_child
.clear();
2361 // Delete the resource in the child. Expect the resource to be lost.
2362 child_resource_provider_
->DeleteResource(resource
);
2363 EXPECT_TRUE(lost_resource
);
2366 TEST_P(ResourceProviderTest
, Shutdown
) {
2367 uint32 release_sync_point
= 0;
2368 bool lost_resource
= false;
2369 bool release_called
= false;
2370 uint32 sync_point
= 0;
2372 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2374 EXPECT_EQ(0u, release_sync_point
);
2375 EXPECT_FALSE(lost_resource
);
2377 child_resource_provider_
= nullptr;
2379 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2380 EXPECT_LE(sync_point
, release_sync_point
);
2382 EXPECT_TRUE(release_called
);
2383 EXPECT_FALSE(lost_resource
);
2386 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2387 uint32 release_sync_point
= 0;
2388 bool lost_resource
= false;
2389 bool release_called
= false;
2390 uint32 sync_point
= 0;
2391 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2392 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2394 // Transfer the resource, so we can't release it properly on shutdown.
2395 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2396 resource_ids_to_transfer
.push_back(resource
);
2397 TransferableResourceArray list
;
2398 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2401 EXPECT_EQ(0u, release_sync_point
);
2402 EXPECT_FALSE(lost_resource
);
2404 child_resource_provider_
= nullptr;
2406 // Since the resource is in the parent, the child considers it lost.
2407 EXPECT_EQ(0u, release_sync_point
);
2408 EXPECT_TRUE(lost_resource
);
2411 TEST_P(ResourceProviderTest
, LostContext
) {
2412 // TextureMailbox callbacks only exist for GL textures for now.
2413 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2415 unsigned texture
= context()->createTexture();
2416 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2417 gpu::Mailbox mailbox
;
2418 context()->genMailboxCHROMIUM(mailbox
.name
);
2419 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2420 uint32 sync_point
= context()->insertSyncPoint();
2422 EXPECT_LT(0u, sync_point
);
2424 uint32 release_sync_point
= 0;
2425 bool lost_resource
= false;
2426 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2427 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2428 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2429 &release_sync_point
,
2431 &main_thread_task_runner
));
2432 resource_provider_
->CreateResourceFromTextureMailbox(
2433 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2435 EXPECT_EQ(0u, release_sync_point
);
2436 EXPECT_FALSE(lost_resource
);
2437 EXPECT_EQ(NULL
, main_thread_task_runner
);
2439 resource_provider_
->DidLoseOutputSurface();
2440 resource_provider_
= nullptr;
2442 EXPECT_LE(sync_point
, release_sync_point
);
2443 EXPECT_TRUE(lost_resource
);
2444 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2447 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2448 // Sampling is only supported for GL textures.
2449 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2452 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2453 new TextureStateTrackingContext
);
2454 TextureStateTrackingContext
* context
= context_owned
.get();
2456 FakeOutputSurfaceClient output_surface_client
;
2457 scoped_ptr
<OutputSurface
> output_surface(
2458 FakeOutputSurface::Create3d(context_owned
.Pass()));
2459 CHECK(output_surface
->BindToClient(&output_surface_client
));
2461 scoped_ptr
<ResourceProvider
> resource_provider(
2462 ResourceProvider::Create(output_surface
.get(),
2463 shared_bitmap_manager_
.get(),
2464 gpu_memory_buffer_manager_
.get(),
2470 gfx::Size
size(1, 1);
2471 ResourceFormat format
= RGBA_8888
;
2474 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2475 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2477 // Check that the texture gets created with the right sampler settings.
2478 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2479 .Times(2); // Once to create and once to allocate.
2480 EXPECT_CALL(*context
,
2481 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2482 EXPECT_CALL(*context
,
2483 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2486 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2489 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2490 EXPECT_CALL(*context
,
2491 texParameteri(GL_TEXTURE_2D
,
2492 GL_TEXTURE_POOL_CHROMIUM
,
2493 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2495 resource_provider
->AllocateForTesting(id
);
2496 Mock::VerifyAndClearExpectations(context
);
2498 // Creating a sampler with the default filter should not change any texture
2501 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2502 ResourceProvider::ScopedSamplerGL
sampler(
2503 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2504 Mock::VerifyAndClearExpectations(context
);
2507 // Using a different filter should be reflected in the texture parameters.
2509 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2512 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2515 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2516 ResourceProvider::ScopedSamplerGL
sampler(
2517 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2518 Mock::VerifyAndClearExpectations(context
);
2521 // Test resetting to the default filter.
2523 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2524 EXPECT_CALL(*context
,
2525 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2526 EXPECT_CALL(*context
,
2527 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2528 ResourceProvider::ScopedSamplerGL
sampler(
2529 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2530 Mock::VerifyAndClearExpectations(context
);
2534 TEST_P(ResourceProviderTest
, ManagedResource
) {
2535 // Sampling is only supported for GL textures.
2536 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2539 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2540 new TextureStateTrackingContext
);
2541 TextureStateTrackingContext
* context
= context_owned
.get();
2543 FakeOutputSurfaceClient output_surface_client
;
2544 scoped_ptr
<OutputSurface
> output_surface(
2545 FakeOutputSurface::Create3d(context_owned
.Pass()));
2546 CHECK(output_surface
->BindToClient(&output_surface_client
));
2548 scoped_ptr
<ResourceProvider
> resource_provider(
2549 ResourceProvider::Create(output_surface
.get(),
2550 shared_bitmap_manager_
.get(),
2551 gpu_memory_buffer_manager_
.get(),
2557 gfx::Size
size(1, 1);
2558 ResourceFormat format
= RGBA_8888
;
2561 // Check that the texture gets created with the right sampler settings.
2562 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2563 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2564 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2565 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2566 EXPECT_CALL(*context
,
2567 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2568 EXPECT_CALL(*context
,
2569 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2572 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2575 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2576 EXPECT_CALL(*context
,
2577 texParameteri(GL_TEXTURE_2D
,
2578 GL_TEXTURE_POOL_CHROMIUM
,
2579 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2580 resource_provider
->CreateForTesting(id
);
2583 Mock::VerifyAndClearExpectations(context
);
2586 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2587 // Sampling is only supported for GL textures.
2588 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2591 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2592 new TextureStateTrackingContext
);
2593 TextureStateTrackingContext
* context
= context_owned
.get();
2595 FakeOutputSurfaceClient output_surface_client
;
2596 scoped_ptr
<OutputSurface
> output_surface(
2597 FakeOutputSurface::Create3d(context_owned
.Pass()));
2598 CHECK(output_surface
->BindToClient(&output_surface_client
));
2600 scoped_ptr
<ResourceProvider
> resource_provider(
2601 ResourceProvider::Create(output_surface
.get(),
2602 shared_bitmap_manager_
.get(),
2603 gpu_memory_buffer_manager_
.get(),
2609 gfx::Size
size(1, 1);
2610 ResourceFormat format
= RGBA_8888
;
2611 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2613 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2614 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2615 // Check that the texture gets created with the right sampler settings.
2616 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2617 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2618 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2619 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2620 EXPECT_CALL(*context
,
2621 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2622 EXPECT_CALL(*context
,
2623 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2624 EXPECT_CALL(*context
,
2625 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2626 EXPECT_CALL(*context
,
2627 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2628 EXPECT_CALL(*context
,
2629 texParameteri(GL_TEXTURE_2D
,
2630 GL_TEXTURE_POOL_CHROMIUM
,
2631 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2632 resource_provider
->CreateForTesting(id
);
2635 Mock::VerifyAndClearExpectations(context
);
2639 TEST_P(ResourceProviderTest
, TextureHint
) {
2640 // Sampling is only supported for GL textures.
2641 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2644 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2645 new TextureStateTrackingContext
);
2646 TextureStateTrackingContext
* context
= context_owned
.get();
2647 context
->set_support_texture_storage(true);
2648 context
->set_support_texture_usage(true);
2650 FakeOutputSurfaceClient output_surface_client
;
2651 scoped_ptr
<OutputSurface
> output_surface(
2652 FakeOutputSurface::Create3d(context_owned
.Pass()));
2653 CHECK(output_surface
->BindToClient(&output_surface_client
));
2655 scoped_ptr
<ResourceProvider
> resource_provider(
2656 ResourceProvider::Create(output_surface
.get(),
2657 shared_bitmap_manager_
.get(),
2658 gpu_memory_buffer_manager_
.get(),
2664 gfx::Size
size(1, 1);
2665 ResourceFormat format
= RGBA_8888
;
2666 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2668 const ResourceProvider::TextureHint hints
[4] = {
2669 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2670 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2671 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2672 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2674 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2675 // Check that the texture gets created with the right sampler settings.
2676 ResourceProvider::ResourceId id
=
2677 resource_provider
->CreateGLTexture(size
,
2681 hints
[texture_id
- 1],
2683 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2684 EXPECT_CALL(*context
,
2685 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2686 EXPECT_CALL(*context
,
2687 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2690 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2693 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2694 EXPECT_CALL(*context
,
2695 texParameteri(GL_TEXTURE_2D
,
2696 GL_TEXTURE_POOL_CHROMIUM
,
2697 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2698 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2699 bool is_framebuffer_hint
=
2700 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2701 EXPECT_CALL(*context
,
2702 texParameteri(GL_TEXTURE_2D
,
2703 GL_TEXTURE_USAGE_ANGLE
,
2704 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2705 .Times(is_framebuffer_hint
? 1 : 0);
2706 resource_provider
->CreateForTesting(id
);
2709 Mock::VerifyAndClearExpectations(context
);
2713 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2714 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2717 gfx::Size
size(64, 64);
2718 const uint32_t kBadBeef
= 0xbadbeef;
2719 scoped_ptr
<SharedBitmap
> shared_bitmap(
2720 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2722 FakeOutputSurfaceClient output_surface_client
;
2723 scoped_ptr
<OutputSurface
> output_surface(
2724 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2725 new SoftwareOutputDevice
)));
2726 CHECK(output_surface
->BindToClient(&output_surface_client
));
2728 scoped_ptr
<ResourceProvider
> resource_provider(
2729 ResourceProvider::Create(output_surface
.get(),
2730 shared_bitmap_manager_
.get(),
2731 gpu_memory_buffer_manager_
.get(),
2732 main_thread_task_runner_
.get(),
2737 uint32 release_sync_point
= 0;
2738 bool lost_resource
= false;
2739 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2740 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2741 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2742 &release_sync_point
,
2744 &main_thread_task_runner
));
2745 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2747 ResourceProvider::ResourceId id
=
2748 resource_provider
->CreateResourceFromTextureMailbox(
2749 mailbox
, callback
.Pass());
2753 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2754 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2755 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2756 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2757 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2760 resource_provider
->DeleteResource(id
);
2761 EXPECT_EQ(0u, release_sync_point
);
2762 EXPECT_FALSE(lost_resource
);
2763 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2766 class ResourceProviderTestTextureMailboxGLFilters
2767 : public ResourceProviderTest
{
2769 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2770 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2771 BlockingTaskRunner
* main_thread_task_runner
,
2772 bool mailbox_nearest_neighbor
,
2773 GLenum sampler_filter
) {
2774 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2775 new TextureStateTrackingContext
);
2776 TextureStateTrackingContext
* context
= context_owned
.get();
2778 FakeOutputSurfaceClient output_surface_client
;
2779 scoped_ptr
<OutputSurface
> output_surface(
2780 FakeOutputSurface::Create3d(context_owned
.Pass()));
2781 CHECK(output_surface
->BindToClient(&output_surface_client
));
2783 scoped_ptr
<ResourceProvider
> resource_provider(
2784 ResourceProvider::Create(output_surface
.get(),
2785 shared_bitmap_manager
,
2786 gpu_memory_buffer_manager
,
2787 main_thread_task_runner
,
2792 unsigned texture_id
= 1;
2793 uint32 sync_point
= 30;
2794 unsigned target
= GL_TEXTURE_2D
;
2796 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2797 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2798 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2799 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2800 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2802 gpu::Mailbox gpu_mailbox
;
2803 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2804 uint32 release_sync_point
= 0;
2805 bool lost_resource
= false;
2806 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2807 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2808 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2809 &release_sync_point
,
2811 &mailbox_task_runner
));
2813 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2814 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2816 ResourceProvider::ResourceId id
=
2817 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2821 Mock::VerifyAndClearExpectations(context
);
2824 // Mailbox sync point WaitSyncPoint before using the texture.
2825 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2826 resource_provider
->WaitSyncPointIfNeeded(id
);
2827 Mock::VerifyAndClearExpectations(context
);
2829 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2830 .WillOnce(Return(texture_id
));
2831 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2833 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2834 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2836 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2837 // match |sampler_filter|.
2838 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2839 EXPECT_CALL(*context
, texParameteri(
2840 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2841 EXPECT_CALL(*context
, texParameteri(
2842 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2845 ResourceProvider::ScopedSamplerGL
lock(
2846 resource_provider
.get(), id
, sampler_filter
);
2847 Mock::VerifyAndClearExpectations(context
);
2849 // When done with it, a sync point should be inserted, but no produce is
2851 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2852 EXPECT_CALL(*context
, insertSyncPoint());
2853 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2855 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2856 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2859 resource_provider
->DeleteResource(id
);
2860 EXPECT_EQ(0u, release_sync_point
);
2861 EXPECT_FALSE(lost_resource
);
2862 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2866 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2867 // Mailboxing is only supported for GL textures.
2868 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2871 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2872 shared_bitmap_manager_
.get(),
2873 gpu_memory_buffer_manager_
.get(),
2874 main_thread_task_runner_
.get(),
2879 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2880 // Mailboxing is only supported for GL textures.
2881 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2884 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2885 shared_bitmap_manager_
.get(),
2886 gpu_memory_buffer_manager_
.get(),
2887 main_thread_task_runner_
.get(),
2892 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2893 // Mailboxing is only supported for GL textures.
2894 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2897 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2898 shared_bitmap_manager_
.get(),
2899 gpu_memory_buffer_manager_
.get(),
2900 main_thread_task_runner_
.get(),
2905 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2906 // Mailboxing is only supported for GL textures.
2907 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2910 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2911 shared_bitmap_manager_
.get(),
2912 gpu_memory_buffer_manager_
.get(),
2913 main_thread_task_runner_
.get(),
2918 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2919 // Mailboxing is only supported for GL textures.
2920 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2923 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2924 new TextureStateTrackingContext
);
2925 TextureStateTrackingContext
* context
= context_owned
.get();
2927 FakeOutputSurfaceClient output_surface_client
;
2928 scoped_ptr
<OutputSurface
> output_surface(
2929 FakeOutputSurface::Create3d(context_owned
.Pass()));
2930 CHECK(output_surface
->BindToClient(&output_surface_client
));
2932 scoped_ptr
<ResourceProvider
> resource_provider(
2933 ResourceProvider::Create(output_surface
.get(),
2934 shared_bitmap_manager_
.get(),
2935 gpu_memory_buffer_manager_
.get(),
2941 uint32 sync_point
= 30;
2942 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2944 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2945 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2946 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2947 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2948 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2950 gpu::Mailbox gpu_mailbox
;
2951 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2952 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2953 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2955 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2957 ResourceProvider::ResourceId id
=
2958 resource_provider
->CreateResourceFromTextureMailbox(
2959 mailbox
, callback
.Pass());
2962 Mock::VerifyAndClearExpectations(context
);
2965 // Mailbox sync point WaitSyncPoint before using the texture.
2966 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2967 resource_provider
->WaitSyncPointIfNeeded(id
);
2968 Mock::VerifyAndClearExpectations(context
);
2970 unsigned texture_id
= 1;
2972 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2973 .WillOnce(Return(texture_id
));
2975 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2976 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2978 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2979 Mock::VerifyAndClearExpectations(context
);
2981 // When done with it, a sync point should be inserted, but no produce is
2983 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2984 EXPECT_CALL(*context
, insertSyncPoint());
2985 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2987 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2988 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2992 TEST_P(ResourceProviderTest
,
2993 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2994 // Mailboxing is only supported for GL textures.
2995 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2998 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2999 new TextureStateTrackingContext
);
3000 TextureStateTrackingContext
* context
= context_owned
.get();
3002 FakeOutputSurfaceClient output_surface_client
;
3003 scoped_ptr
<OutputSurface
> output_surface(
3004 FakeOutputSurface::Create3d(context_owned
.Pass()));
3005 CHECK(output_surface
->BindToClient(&output_surface_client
));
3007 scoped_ptr
<ResourceProvider
> resource_provider(
3008 ResourceProvider::Create(output_surface
.get(),
3009 shared_bitmap_manager_
.get(),
3010 gpu_memory_buffer_manager_
.get(),
3016 uint32 sync_point
= 30;
3017 unsigned target
= GL_TEXTURE_2D
;
3019 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3020 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3021 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3022 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3023 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3025 gpu::Mailbox gpu_mailbox
;
3026 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3027 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3028 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3030 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3032 ResourceProvider::ResourceId id
=
3033 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
3037 Mock::VerifyAndClearExpectations(context
);
3040 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3041 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
3042 resource_provider
->WaitSyncPointIfNeeded(id
);
3043 Mock::VerifyAndClearExpectations(context
);
3045 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3046 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3047 resource_provider
->WaitSyncPointIfNeeded(id
);
3048 Mock::VerifyAndClearExpectations(context
);
3052 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
3053 // Mailboxing is only supported for GL textures.
3054 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3057 scoped_ptr
<TextureStateTrackingContext
> context_owned(
3058 new TextureStateTrackingContext
);
3059 TextureStateTrackingContext
* context
= context_owned
.get();
3061 FakeOutputSurfaceClient output_surface_client
;
3062 scoped_ptr
<OutputSurface
> output_surface(
3063 FakeOutputSurface::Create3d(context_owned
.Pass()));
3064 CHECK(output_surface
->BindToClient(&output_surface_client
));
3066 scoped_ptr
<ResourceProvider
> resource_provider(
3067 ResourceProvider::Create(output_surface
.get(),
3068 shared_bitmap_manager_
.get(),
3069 gpu_memory_buffer_manager_
.get(),
3075 uint32 sync_point
= 0;
3076 unsigned target
= GL_TEXTURE_2D
;
3078 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3079 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3080 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3081 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3082 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3084 gpu::Mailbox gpu_mailbox
;
3085 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3086 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3087 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3089 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3091 ResourceProvider::ResourceId id
=
3092 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
3096 Mock::VerifyAndClearExpectations(context
);
3099 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3100 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3101 resource_provider
->WaitSyncPointIfNeeded(id
);
3102 Mock::VerifyAndClearExpectations(context
);
3106 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
3108 MOCK_METHOD0(NextTextureId
, GLuint());
3109 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
3110 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
3111 MOCK_METHOD5(texStorage2DEXT
,
3114 GLuint internalformat
,
3117 MOCK_METHOD9(texImage2D
,
3120 GLenum internalformat
,
3126 const void* pixels
));
3127 MOCK_METHOD9(texSubImage2D
,
3136 const void* pixels
));
3137 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
3140 GLenum internalformat
,
3146 const void* pixels
));
3147 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3156 const void* pixels
));
3157 MOCK_METHOD8(compressedTexImage2D
,
3160 GLenum internalformat
,
3166 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3167 MOCK_METHOD4(createImageCHROMIUM
,
3168 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3169 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3170 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3171 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3173 // We're mocking bindTexture, so we override
3174 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3175 // currently bound texture.
3176 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3179 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3180 // Only for GL textures.
3181 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3183 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3184 new StrictMock
<AllocationTrackingContext3D
>);
3185 AllocationTrackingContext3D
* context
= context_owned
.get();
3187 FakeOutputSurfaceClient output_surface_client
;
3188 scoped_ptr
<OutputSurface
> output_surface(
3189 FakeOutputSurface::Create3d(context_owned
.Pass()));
3190 CHECK(output_surface
->BindToClient(&output_surface_client
));
3192 scoped_ptr
<ResourceProvider
> resource_provider(
3193 ResourceProvider::Create(output_surface
.get(),
3194 shared_bitmap_manager_
.get(),
3195 gpu_memory_buffer_manager_
.get(),
3201 gfx::Size
size(2, 2);
3202 gfx::Vector2d
offset(0, 0);
3203 ResourceFormat format
= RGBA_8888
;
3204 ResourceProvider::ResourceId id
= 0;
3205 uint8_t pixels
[16] = { 0 };
3206 int texture_id
= 123;
3208 // Lazy allocation. Don't allocate when creating the resource.
3209 id
= resource_provider
->CreateResource(
3210 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3212 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3213 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3214 resource_provider
->CreateForTesting(id
);
3216 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3217 resource_provider
->DeleteResource(id
);
3219 Mock::VerifyAndClearExpectations(context
);
3221 // Do allocate when we set the pixels.
3222 id
= resource_provider
->CreateResource(
3223 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3225 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3226 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3227 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3228 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3229 resource_provider
->CopyToResource(id
, pixels
, size
);
3231 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3232 resource_provider
->DeleteResource(id
);
3234 Mock::VerifyAndClearExpectations(context
);
3236 // Same for async version.
3237 id
= resource_provider
->CreateResource(
3238 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3239 resource_provider
->AcquirePixelBuffer(id
);
3241 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3242 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3243 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3245 resource_provider
->BeginSetPixels(id
);
3246 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3248 resource_provider
->ReleasePixelBuffer(id
);
3250 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3251 resource_provider
->DeleteResource(id
);
3253 Mock::VerifyAndClearExpectations(context
);
3256 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3257 // Only for GL textures.
3258 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3260 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3261 new StrictMock
<AllocationTrackingContext3D
>);
3262 AllocationTrackingContext3D
* context
= context_owned
.get();
3263 context
->set_support_texture_storage(true);
3264 context
->set_support_texture_usage(true);
3266 FakeOutputSurfaceClient output_surface_client
;
3267 scoped_ptr
<OutputSurface
> output_surface(
3268 FakeOutputSurface::Create3d(context_owned
.Pass()));
3269 CHECK(output_surface
->BindToClient(&output_surface_client
));
3271 scoped_ptr
<ResourceProvider
> resource_provider(
3272 ResourceProvider::Create(output_surface
.get(),
3273 shared_bitmap_manager_
.get(),
3274 gpu_memory_buffer_manager_
.get(),
3280 gfx::Size
size(2, 2);
3282 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3283 const ResourceProvider::TextureHint hints
[4] = {
3284 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3285 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3286 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3287 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3289 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3290 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3291 // Lazy allocation. Don't allocate when creating the resource.
3292 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3293 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3295 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3296 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3297 bool is_immutable_hint
=
3298 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3299 bool support_immutable_texture
=
3300 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3301 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3302 .Times(support_immutable_texture
? 1 : 0);
3303 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3304 .Times(support_immutable_texture
? 0 : 1);
3305 resource_provider
->AllocateForTesting(id
);
3307 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3308 resource_provider
->DeleteResource(id
);
3310 Mock::VerifyAndClearExpectations(context
);
3315 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3316 // Only for GL textures.
3317 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3319 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3320 new StrictMock
<AllocationTrackingContext3D
>);
3321 AllocationTrackingContext3D
* context
= context_owned
.get();
3322 context
->set_support_texture_format_bgra8888(true);
3323 context
->set_support_texture_storage(true);
3324 context
->set_support_texture_usage(true);
3326 FakeOutputSurfaceClient output_surface_client
;
3327 scoped_ptr
<OutputSurface
> output_surface(
3328 FakeOutputSurface::Create3d(context_owned
.Pass()));
3329 CHECK(output_surface
->BindToClient(&output_surface_client
));
3331 scoped_ptr
<ResourceProvider
> resource_provider(
3332 ResourceProvider::Create(output_surface
.get(),
3333 shared_bitmap_manager_
.get(),
3334 gpu_memory_buffer_manager_
.get(),
3340 gfx::Size
size(2, 2);
3341 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3343 const ResourceProvider::TextureHint hints
[4] = {
3344 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3345 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3346 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3347 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3349 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3350 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3351 // Lazy allocation. Don't allocate when creating the resource.
3352 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3353 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3355 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3356 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3357 bool is_immutable_hint
=
3358 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3359 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3360 .Times(is_immutable_hint
? 1 : 0);
3361 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3362 .Times(is_immutable_hint
? 0 : 1);
3363 resource_provider
->AllocateForTesting(id
);
3365 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3366 resource_provider
->DeleteResource(id
);
3368 Mock::VerifyAndClearExpectations(context
);
3373 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3374 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3376 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3377 new StrictMock
<AllocationTrackingContext3D
>);
3378 AllocationTrackingContext3D
* context
= context_owned
.get();
3380 FakeOutputSurfaceClient output_surface_client
;
3381 scoped_ptr
<OutputSurface
> output_surface(
3382 FakeOutputSurface::Create3d(context_owned
.Pass()));
3383 CHECK(output_surface
->BindToClient(&output_surface_client
));
3385 gfx::Size
size(2, 2);
3386 ResourceFormat format
= RGBA_8888
;
3387 ResourceProvider::ResourceId id
= 0;
3388 int texture_id
= 123;
3390 scoped_ptr
<ResourceProvider
> resource_provider(
3391 ResourceProvider::Create(output_surface
.get(),
3392 shared_bitmap_manager_
.get(),
3393 gpu_memory_buffer_manager_
.get(),
3399 id
= resource_provider
->CreateResource(
3400 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3401 resource_provider
->AcquirePixelBuffer(id
);
3403 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3404 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3405 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3407 resource_provider
->BeginSetPixels(id
);
3409 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3411 resource_provider
->ReleasePixelBuffer(id
);
3413 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3414 resource_provider
->DeleteResource(id
);
3416 Mock::VerifyAndClearExpectations(context
);
3419 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3420 // Only for GL textures.
3421 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3423 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3424 new StrictMock
<AllocationTrackingContext3D
>);
3425 AllocationTrackingContext3D
* context
= context_owned
.get();
3427 FakeOutputSurfaceClient output_surface_client
;
3428 scoped_ptr
<OutputSurface
> output_surface(
3429 FakeOutputSurface::Create3d(context_owned
.Pass()));
3430 CHECK(output_surface
->BindToClient(&output_surface_client
));
3432 gfx::Size
size(2, 2);
3433 ResourceFormat format
= RGBA_8888
;
3434 ResourceProvider::ResourceId id
= 0;
3435 int texture_id
= 123;
3437 scoped_ptr
<ResourceProvider
> resource_provider(
3438 ResourceProvider::Create(output_surface
.get(),
3439 shared_bitmap_manager_
.get(),
3440 gpu_memory_buffer_manager_
.get(),
3446 id
= resource_provider
->CreateResource(
3447 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3448 resource_provider
->AcquirePixelBuffer(id
);
3450 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3451 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3452 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3454 resource_provider
->BeginSetPixels(id
);
3456 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3457 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3458 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3459 resource_provider
->ForceSetPixelsToComplete(id
);
3461 resource_provider
->ReleasePixelBuffer(id
);
3463 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3464 resource_provider
->DeleteResource(id
);
3466 Mock::VerifyAndClearExpectations(context
);
3469 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3470 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3471 new NiceMock
<AllocationTrackingContext3D
>);
3472 AllocationTrackingContext3D
* context
= context_owned
.get();
3474 FakeOutputSurfaceClient output_surface_client
;
3475 scoped_ptr
<OutputSurface
> output_surface(
3476 FakeOutputSurface::Create3d(context_owned
.Pass()));
3477 CHECK(output_surface
->BindToClient(&output_surface_client
));
3479 gfx::Size
size(2, 2);
3480 ResourceFormat format
= RGBA_8888
;
3481 ResourceProvider::ResourceId id
= 0;
3482 int texture_id
= 123;
3484 scoped_ptr
<ResourceProvider
> resource_provider(
3485 ResourceProvider::Create(output_surface
.get(),
3486 shared_bitmap_manager_
.get(),
3487 gpu_memory_buffer_manager_
.get(),
3493 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3495 id
= resource_provider
->CreateResource(
3496 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3497 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3498 GL_INNOCENT_CONTEXT_RESET_ARB
);
3500 resource_provider
->AcquirePixelBuffer(id
);
3502 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3503 EXPECT_FALSE(buffer
);
3504 resource_provider
->UnmapPixelBuffer(id
);
3505 Mock::VerifyAndClearExpectations(context
);
3508 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3509 // Only for GL textures.
3510 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3512 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3513 new StrictMock
<AllocationTrackingContext3D
>);
3514 AllocationTrackingContext3D
* context
= context_owned
.get();
3516 FakeOutputSurfaceClient output_surface_client
;
3517 scoped_ptr
<OutputSurface
> output_surface(
3518 FakeOutputSurface::Create3d(context_owned
.Pass()));
3519 CHECK(output_surface
->BindToClient(&output_surface_client
));
3521 const int kWidth
= 2;
3522 const int kHeight
= 2;
3523 gfx::Size
size(kWidth
, kHeight
);
3524 ResourceFormat format
= RGBA_8888
;
3525 ResourceProvider::ResourceId id
= 0;
3526 const unsigned kTextureId
= 123u;
3527 const unsigned kImageId
= 234u;
3529 scoped_ptr
<ResourceProvider
> resource_provider(
3530 ResourceProvider::Create(output_surface
.get(),
3531 shared_bitmap_manager_
.get(),
3532 gpu_memory_buffer_manager_
.get(),
3538 id
= resource_provider
->CreateResource(
3539 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3541 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3542 .WillOnce(Return(kImageId
))
3543 .RetiresOnSaturation();
3545 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3546 resource_provider
.get(), id
);
3547 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3550 EXPECT_CALL(*context
, NextTextureId())
3551 .WillOnce(Return(kTextureId
))
3552 .RetiresOnSaturation();
3553 // Once in CreateTextureId and once in BindForSampling
3554 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3555 .RetiresOnSaturation();
3556 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3558 .RetiresOnSaturation();
3560 ResourceProvider::ScopedSamplerGL
lock_gl(
3561 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3562 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3566 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3567 resource_provider
.get(), id
);
3568 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3571 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3572 .RetiresOnSaturation();
3573 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3575 .RetiresOnSaturation();
3576 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3578 .RetiresOnSaturation();
3579 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3581 .RetiresOnSaturation();
3583 ResourceProvider::ScopedSamplerGL
lock_gl(
3584 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3585 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3588 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3590 .RetiresOnSaturation();
3593 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3594 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3596 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3597 new StrictMock
<AllocationTrackingContext3D
>);
3598 AllocationTrackingContext3D
* context
= context_owned
.get();
3599 context_owned
->set_support_sync_query(true);
3601 FakeOutputSurfaceClient output_surface_client
;
3602 scoped_ptr
<OutputSurface
> output_surface(
3603 FakeOutputSurface::Create3d(context_owned
.Pass()));
3604 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3606 const int kWidth
= 2;
3607 const int kHeight
= 2;
3608 gfx::Size
size(kWidth
, kHeight
);
3609 ResourceFormat format
= RGBA_8888
;
3610 ResourceProvider::ResourceId source_id
= 0;
3611 ResourceProvider::ResourceId dest_id
= 0;
3612 const unsigned kSourceTextureId
= 123u;
3613 const unsigned kDestTextureId
= 321u;
3614 const unsigned kImageId
= 234u;
3616 scoped_ptr
<ResourceProvider
> resource_provider(
3617 ResourceProvider::Create(output_surface
.get(),
3618 shared_bitmap_manager_
.get(),
3619 gpu_memory_buffer_manager_
.get(),
3625 source_id
= resource_provider
->CreateResource(
3626 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3628 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3629 .WillOnce(Return(kImageId
))
3630 .RetiresOnSaturation();
3632 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3633 resource_provider
.get(), source_id
);
3634 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3636 Mock::VerifyAndClearExpectations(context
);
3638 dest_id
= resource_provider
->CreateResource(
3639 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3641 EXPECT_CALL(*context
, NextTextureId())
3642 .WillOnce(Return(kDestTextureId
))
3643 .RetiresOnSaturation();
3644 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3646 .RetiresOnSaturation();
3647 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3648 GL_UNSIGNED_BYTE
, nullptr))
3650 .RetiresOnSaturation();
3651 EXPECT_CALL(*context
, NextTextureId())
3652 .WillOnce(Return(kSourceTextureId
))
3653 .RetiresOnSaturation();
3654 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3656 .RetiresOnSaturation();
3657 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3659 .RetiresOnSaturation();
3660 resource_provider
->CopyResource(source_id
, dest_id
);
3661 Mock::VerifyAndClearExpectations(context
);
3663 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3665 .RetiresOnSaturation();
3666 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3668 .RetiresOnSaturation();
3669 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3671 .RetiresOnSaturation();
3672 resource_provider
->DeleteResource(source_id
);
3673 resource_provider
->DeleteResource(dest_id
);
3676 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3677 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3680 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3681 new AllocationTrackingContext3D
);
3682 AllocationTrackingContext3D
* context
= context_owned
.get();
3683 context_owned
->set_support_compressed_texture_etc1(true);
3685 FakeOutputSurfaceClient output_surface_client
;
3686 scoped_ptr
<OutputSurface
> output_surface(
3687 FakeOutputSurface::Create3d(context_owned
.Pass()));
3688 CHECK(output_surface
->BindToClient(&output_surface_client
));
3690 gfx::Size
size(4, 4);
3691 scoped_ptr
<ResourceProvider
> resource_provider(
3692 ResourceProvider::Create(output_surface
.get(),
3693 shared_bitmap_manager_
.get(),
3694 gpu_memory_buffer_manager_
.get(),
3699 int texture_id
= 123;
3701 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3702 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3704 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3705 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3706 resource_provider
->AllocateForTesting(id
);
3708 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3709 resource_provider
->DeleteResource(id
);
3712 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3713 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3716 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3717 new AllocationTrackingContext3D
);
3718 AllocationTrackingContext3D
* context
= context_owned
.get();
3719 context_owned
->set_support_compressed_texture_etc1(true);
3721 FakeOutputSurfaceClient output_surface_client
;
3722 scoped_ptr
<OutputSurface
> output_surface(
3723 FakeOutputSurface::Create3d(context_owned
.Pass()));
3724 CHECK(output_surface
->BindToClient(&output_surface_client
));
3726 gfx::Size
size(4, 4);
3727 scoped_ptr
<ResourceProvider
> resource_provider(
3728 ResourceProvider::Create(output_surface
.get(),
3729 shared_bitmap_manager_
.get(),
3730 gpu_memory_buffer_manager_
.get(),
3735 int texture_id
= 123;
3738 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3739 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3741 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3742 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3743 EXPECT_CALL(*context
,
3744 compressedTexImage2D(
3745 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3746 resource_provider
->CopyToResource(id
, pixels
, size
);
3748 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3749 resource_provider
->DeleteResource(id
);
3752 INSTANTIATE_TEST_CASE_P(
3753 ResourceProviderTests
,
3754 ResourceProviderTest
,
3755 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3756 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3758 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3760 GLuint
NextTextureId() override
{
3761 base::AutoLock
lock(namespace_
->lock
);
3762 return namespace_
->next_texture_id
++;
3764 void RetireTextureId(GLuint
) override
{}
3765 GLuint
PeekTextureId() {
3766 base::AutoLock
lock(namespace_
->lock
);
3767 return namespace_
->next_texture_id
;
3771 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3772 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3773 new TextureIdAllocationTrackingContext
);
3774 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3776 FakeOutputSurfaceClient output_surface_client
;
3777 scoped_ptr
<OutputSurface
> output_surface(
3778 FakeOutputSurface::Create3d(context_owned
.Pass()));
3779 CHECK(output_surface
->BindToClient(&output_surface_client
));
3780 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3781 new TestSharedBitmapManager());
3783 gfx::Size
size(1, 1);
3784 ResourceFormat format
= RGBA_8888
;
3787 size_t kTextureAllocationChunkSize
= 1;
3788 scoped_ptr
<ResourceProvider
> resource_provider(
3789 ResourceProvider::Create(output_surface
.get(),
3790 shared_bitmap_manager
.get(),
3795 kTextureAllocationChunkSize
));
3797 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3798 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3800 resource_provider
->AllocateForTesting(id
);
3801 Mock::VerifyAndClearExpectations(context
);
3803 DCHECK_EQ(2u, context
->PeekTextureId());
3804 resource_provider
->DeleteResource(id
);
3808 size_t kTextureAllocationChunkSize
= 8;
3809 scoped_ptr
<ResourceProvider
> resource_provider(
3810 ResourceProvider::Create(output_surface
.get(),
3811 shared_bitmap_manager
.get(),
3816 kTextureAllocationChunkSize
));
3818 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3819 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3821 resource_provider
->AllocateForTesting(id
);
3822 Mock::VerifyAndClearExpectations(context
);
3824 DCHECK_EQ(10u, context
->PeekTextureId());
3825 resource_provider
->DeleteResource(id
);