1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
56 BlockingTaskRunner
* main_thread_task_runner
) {
57 *release_sync_point
= sync_point
;
58 *release_lost_resource
= lost_resource
;
59 *release_main_thread_task_runner
= main_thread_task_runner
;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr
<SharedBitmap
> bitmap
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr
<SharedBitmap
> shared_bitmap
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<SharedBitmap
> CreateAndFillSharedBitmap(
83 SharedBitmapManager
* manager
,
84 const gfx::Size
& size
,
86 scoped_ptr
<SharedBitmap
> shared_bitmap
= manager
->AllocateSharedBitmap(size
);
88 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_bitmap
->pixels());
90 std::fill_n(pixels
, size
.GetArea(), value
);
91 return shared_bitmap
.Pass();
94 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
96 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
97 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
98 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
99 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM
,
101 void(GLuint texture
, GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM
,
103 unsigned(GLenum target
, const GLbyte
* mailbox
));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint
NextTextureId() override
{
108 base::AutoLock
lock(namespace_
->lock
);
109 return namespace_
->next_texture_id
++;
111 void RetireTextureId(GLuint
) override
{}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData
{
118 static scoped_ptr
<ContextSharedData
> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32
InsertSyncPoint() { return next_sync_point_
++; }
124 void GenMailbox(GLbyte
* mailbox
) {
125 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
126 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
130 void ProduceTexture(const GLbyte
* mailbox_name
,
132 scoped_refptr
<TestTexture
> texture
) {
133 unsigned mailbox
= 0;
134 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
135 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
136 textures_
[mailbox
] = texture
;
137 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
138 sync_point_for_mailbox_
[mailbox
] = sync_point
;
141 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
143 unsigned mailbox
= 0;
144 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
145 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
150 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
152 return scoped_refptr
<TestTexture
>();
154 return textures_
[mailbox
];
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_
;
161 unsigned next_mailbox_
;
162 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
163 TextureMap textures_
;
164 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
167 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
169 static scoped_ptr
<ResourceProviderContext
> Create(
170 ContextSharedData
* shared_data
) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
174 GLuint
insertSyncPoint() override
{
175 uint32 sync_point
= shared_data_
->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it
=
179 pending_produce_textures_
.begin();
180 it
!= pending_produce_textures_
.end();
182 shared_data_
->ProduceTexture(
183 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
185 pending_produce_textures_
.clear();
189 void waitSyncPoint(GLuint sync_point
) override
{
190 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
195 void texStorage2DEXT(GLenum target
,
197 GLuint internalformat
,
199 GLint height
) override
{
200 CheckTextureIsBound(target
);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
202 ASSERT_EQ(1, levels
);
203 GLenum format
= GL_RGBA
;
204 switch (internalformat
) {
208 format
= GL_BGRA_EXT
;
213 AllocateTexture(gfx::Size(width
, height
), format
);
216 void texImage2D(GLenum target
,
218 GLenum internalformat
,
224 const void* pixels
) override
{
225 CheckTextureIsBound(target
);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
228 ASSERT_EQ(internalformat
, format
);
229 ASSERT_FALSE(border
);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
231 AllocateTexture(gfx::Size(width
, height
), format
);
233 SetPixels(0, 0, width
, height
, pixels
);
236 void texSubImage2D(GLenum target
,
244 const void* pixels
) override
{
245 CheckTextureIsBound(target
);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
250 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
254 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
257 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
258 return shared_data_
->GenMailbox(mailbox
);
261 void produceTextureDirectCHROMIUM(GLuint texture
,
263 const GLbyte
* mailbox
) override
{
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= UnboundTexture(texture
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 GLuint
createAndConsumeTextureCHROMIUM(GLenum target
,
275 const GLbyte
* mailbox
) override
{
276 GLuint texture_id
= createTexture();
277 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
278 scoped_refptr
<TestTexture
> texture
=
279 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
280 namespace_
->textures
.Replace(texture_id
, texture
);
284 void GetPixels(const gfx::Size
& size
,
285 ResourceFormat format
,
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
289 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
290 ASSERT_EQ(texture
->size
, size
);
291 ASSERT_EQ(texture
->format
, format
);
292 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
296 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
297 : shared_data_(shared_data
),
298 last_waited_sync_point_(0) {}
301 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
302 CheckTextureIsBound(GL_TEXTURE_2D
);
303 ResourceFormat texture_format
= RGBA_8888
;
306 texture_format
= RGBA_8888
;
309 texture_format
= BGRA_8888
;
312 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
313 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
316 void SetPixels(int xoffset
,
320 const void* pixels
) {
321 CheckTextureIsBound(GL_TEXTURE_2D
);
322 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
323 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
324 ASSERT_TRUE(texture
->data
.get());
325 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
326 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
328 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
330 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
331 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
332 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
333 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
334 for (int i
= 0; i
< height
; ++i
) {
335 memcpy(dest
, src
, in_pitch
);
341 struct PendingProduceTexture
{
342 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
343 scoped_refptr
<TestTexture
> texture
;
345 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
346 ContextSharedData
* shared_data_
;
347 GLuint last_waited_sync_point_
;
348 PendingProduceTextureList pending_produce_textures_
;
351 void GetResourcePixels(ResourceProvider
* resource_provider
,
352 ResourceProviderContext
* context
,
354 const gfx::Size
& size
,
355 ResourceFormat format
,
357 resource_provider
->WaitSyncPointIfNeeded(id
);
358 switch (resource_provider
->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
360 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
361 ASSERT_NE(0U, lock_gl
.texture_id());
362 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
363 context
->GetPixels(size
, format
, pixels
);
366 case ResourceProvider::RESOURCE_TYPE_BITMAP
: {
367 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
370 lock_software
.sk_bitmap()->getPixels(),
371 lock_software
.sk_bitmap()->getSize());
377 class ResourceProviderTest
378 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
380 explicit ResourceProviderTest(bool child_needs_sync_point
)
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL
),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
387 scoped_ptr
<ResourceProviderContext
> context3d(
388 ResourceProviderContext::Create(shared_data_
.get()));
389 context3d_
= context3d
.get();
391 scoped_refptr
<TestContextProvider
> context_provider
=
392 TestContextProvider::Create(context3d
.Pass());
394 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
396 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
397 ResourceProviderContext::Create(shared_data_
.get());
398 child_context_
= child_context_owned
.get();
399 if (child_needs_sync_point
) {
400 child_output_surface_
=
401 FakeOutputSurface::Create3d(child_context_owned
.Pass());
403 child_output_surface_
= FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned
.Pass());
408 case ResourceProvider::RESOURCE_TYPE_BITMAP
:
409 output_surface_
= FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice
));
411 child_output_surface_
= FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice
));
415 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
416 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
418 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
419 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
421 resource_provider_
= ResourceProvider::Create(
422 output_surface_
.get(), shared_bitmap_manager_
.get(),
423 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
425 child_resource_provider_
= ResourceProvider::Create(
426 child_output_surface_
.get(), shared_bitmap_manager_
.get(),
427 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
431 ResourceProviderTest() : ResourceProviderTest(true) {}
433 static void CollectResources(ReturnedResourceArray
* array
,
434 const ReturnedResourceArray
& returned
,
435 BlockingTaskRunner
* main_thread_task_runner
) {
436 array
->insert(array
->end(), returned
.begin(), returned
.end());
439 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
440 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
443 static void SetResourceFilter(ResourceProvider
* resource_provider
,
446 ResourceProvider::ScopedSamplerGL
sampler(
447 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
450 ResourceProviderContext
* context() { return context3d_
; }
452 ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
454 bool* release_called
,
455 uint32
* sync_point
) {
456 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
457 unsigned texture
= child_context_
->createTexture();
458 gpu::Mailbox gpu_mailbox
;
459 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
460 child_context_
->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
,
462 *sync_point
= child_context_
->insertSyncPoint();
463 EXPECT_LT(0u, *sync_point
);
465 scoped_ptr
<SharedBitmap
> shared_bitmap
;
466 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
467 SingleReleaseCallbackImpl::Create(base::Bind(
468 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
469 release_called
, release_sync_point
, lost_resource
));
470 return child_resource_provider_
->CreateResourceFromTextureMailbox(
471 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
474 gfx::Size
size(64, 64);
475 scoped_ptr
<SharedBitmap
> shared_bitmap(
476 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
478 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
479 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
480 SingleReleaseCallbackImpl::Create(base::Bind(
481 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
482 release_called
, release_sync_point
, lost_resource
));
483 return child_resource_provider_
->CreateResourceFromTextureMailbox(
484 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
489 scoped_ptr
<ContextSharedData
> shared_data_
;
490 ResourceProviderContext
* context3d_
;
491 ResourceProviderContext
* child_context_
;
492 FakeOutputSurfaceClient output_surface_client_
;
493 FakeOutputSurfaceClient child_output_surface_client_
;
494 scoped_ptr
<OutputSurface
> output_surface_
;
495 scoped_ptr
<OutputSurface
> child_output_surface_
;
496 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
497 scoped_ptr
<ResourceProvider
> resource_provider_
;
498 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
499 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
500 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
503 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
504 ResourceProvider
* resource_provider
,
505 ResourceProviderContext
* context
) {
506 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
508 gfx::Size
size(1, 1);
509 ResourceFormat format
= RGBA_8888
;
510 size_t pixel_size
= TextureSizeBytes(size
, format
);
511 ASSERT_EQ(4U, pixel_size
);
513 ResourceId id
= resource_provider
->CreateResource(
514 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
515 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
516 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
517 EXPECT_EQ(0u, context
->NumTextures());
519 uint8_t data
[4] = { 1, 2, 3, 4 };
520 resource_provider
->CopyToResource(id
, data
, size
);
521 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
522 EXPECT_EQ(1u, context
->NumTextures());
524 uint8_t result
[4] = { 0 };
525 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
526 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
528 resource_provider
->DeleteResource(id
);
529 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
530 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
531 EXPECT_EQ(0u, context
->NumTextures());
534 TEST_P(ResourceProviderTest
, Basic
) {
535 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
538 TEST_P(ResourceProviderTest
, SimpleUpload
) {
539 gfx::Size
size(2, 2);
540 ResourceFormat format
= RGBA_8888
;
541 size_t pixel_size
= TextureSizeBytes(size
, format
);
542 ASSERT_EQ(16U, pixel_size
);
544 ResourceId id
= resource_provider_
->CreateResource(
545 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
547 uint8_t image
[16] = {0};
548 resource_provider_
->CopyToResource(id
, image
, size
);
550 uint8_t result
[16] = {0};
551 uint8_t expected
[16] = {0};
552 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
554 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
557 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
559 resource_provider_
->CopyToResource(id
, image
, size
);
561 uint8_t result
[16] = {0};
562 uint8_t expected
[16] = {
563 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
564 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
566 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
570 TEST_P(ResourceProviderTest
, TransferGLResources
) {
571 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
573 gfx::Size
size(1, 1);
574 ResourceFormat format
= RGBA_8888
;
575 size_t pixel_size
= TextureSizeBytes(size
, format
);
576 ASSERT_EQ(4U, pixel_size
);
578 ResourceId id1
= child_resource_provider_
->CreateResource(
579 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
580 uint8_t data1
[4] = { 1, 2, 3, 4 };
581 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
583 ResourceId id2
= child_resource_provider_
->CreateResource(
584 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
585 uint8_t data2
[4] = { 5, 5, 5, 5 };
586 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
588 ResourceId id3
= child_resource_provider_
->CreateResource(
589 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
591 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
592 child_resource_provider_
.get(), id3
);
593 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
596 GLuint external_texture_id
= child_context_
->createExternalTexture();
598 gpu::Mailbox external_mailbox
;
599 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
600 child_context_
->produceTextureDirectCHROMIUM(
601 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
602 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
603 ResourceId id4
= child_resource_provider_
->CreateResourceFromTextureMailbox(
604 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
605 external_sync_point
),
606 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
608 ReturnedResourceArray returned_to_child
;
610 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
612 // Transfer some resources to the parent.
613 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
614 resource_ids_to_transfer
.push_back(id1
);
615 resource_ids_to_transfer
.push_back(id2
);
616 resource_ids_to_transfer
.push_back(id3
);
617 resource_ids_to_transfer
.push_back(id4
);
618 TransferableResourceArray list
;
619 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
621 ASSERT_EQ(4u, list
.size());
622 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
623 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
624 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
625 list
[1].mailbox_holder
.sync_point
);
626 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
627 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
628 list
[2].mailbox_holder
.sync_point
);
629 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
630 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
631 list
[0].mailbox_holder
.texture_target
);
632 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
633 list
[1].mailbox_holder
.texture_target
);
634 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
635 list
[2].mailbox_holder
.texture_target
);
636 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
637 list
[3].mailbox_holder
.texture_target
);
638 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
639 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
640 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
641 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
642 resource_provider_
->ReceiveFromChild(child_id
, list
);
643 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
644 context3d_
->last_waited_sync_point());
646 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
647 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
650 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
651 context3d_
->last_waited_sync_point());
652 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
653 resource_ids_to_receive
.insert(id1
);
654 resource_ids_to_receive
.insert(id2
);
655 resource_ids_to_receive
.insert(id3
);
656 resource_ids_to_receive
.insert(id4
);
657 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
658 resource_ids_to_receive
);
661 EXPECT_EQ(4u, resource_provider_
->num_resources());
662 ResourceProvider::ResourceIdMap resource_map
=
663 resource_provider_
->GetChildToParentMap(child_id
);
664 ResourceId mapped_id1
= resource_map
[id1
];
665 ResourceId mapped_id2
= resource_map
[id2
];
666 ResourceId mapped_id3
= resource_map
[id3
];
667 ResourceId mapped_id4
= resource_map
[id4
];
668 EXPECT_NE(0u, mapped_id1
);
669 EXPECT_NE(0u, mapped_id2
);
670 EXPECT_NE(0u, mapped_id3
);
671 EXPECT_NE(0u, mapped_id4
);
672 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
673 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
674 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
675 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
677 uint8_t result
[4] = { 0 };
679 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
680 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
683 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
684 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
687 // Check that transfering again the same resource from the child to the
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 TransferableResourceArray list
;
694 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
696 EXPECT_EQ(3u, list
.size());
697 EXPECT_EQ(id1
, list
[0].id
);
698 EXPECT_EQ(id2
, list
[1].id
);
699 EXPECT_EQ(id3
, list
[2].id
);
700 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
701 list
[0].mailbox_holder
.texture_target
);
702 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
703 list
[1].mailbox_holder
.texture_target
);
704 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
705 list
[2].mailbox_holder
.texture_target
);
706 ReturnedResourceArray returned
;
707 TransferableResource::ReturnResources(list
, &returned
);
708 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
709 // ids were exported twice, we returned them only once, they should still
711 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
712 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
713 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
716 EXPECT_EQ(0u, returned_to_child
.size());
718 // Transfer resources back from the parent to the child. Set no resources as
720 ResourceProvider::ResourceIdSet no_resources
;
721 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
723 ASSERT_EQ(4u, returned_to_child
.size());
724 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
725 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
726 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
727 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
728 EXPECT_FALSE(returned_to_child
[0].lost
);
729 EXPECT_FALSE(returned_to_child
[1].lost
);
730 EXPECT_FALSE(returned_to_child
[2].lost
);
731 EXPECT_FALSE(returned_to_child
[3].lost
);
732 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
733 returned_to_child
.clear();
735 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
736 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
737 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
738 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
741 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
742 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
744 ASSERT_NE(0U, lock
.texture_id());
745 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
746 child_context_
->GetPixels(size
, format
, result
);
747 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
750 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
751 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
753 ASSERT_NE(0U, lock
.texture_id());
754 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
755 child_context_
->GetPixels(size
, format
, result
);
756 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
759 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
760 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
762 ASSERT_NE(0U, lock
.texture_id());
763 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
766 // Transfer resources to the parent again.
767 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
768 resource_ids_to_transfer
.push_back(id1
);
769 resource_ids_to_transfer
.push_back(id2
);
770 resource_ids_to_transfer
.push_back(id3
);
771 resource_ids_to_transfer
.push_back(id4
);
772 TransferableResourceArray list
;
773 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
775 ASSERT_EQ(4u, list
.size());
776 EXPECT_EQ(id1
, list
[0].id
);
777 EXPECT_EQ(id2
, list
[1].id
);
778 EXPECT_EQ(id3
, list
[2].id
);
779 EXPECT_EQ(id4
, list
[3].id
);
780 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
781 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
782 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
783 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
784 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
785 list
[0].mailbox_holder
.texture_target
);
786 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
787 list
[1].mailbox_holder
.texture_target
);
788 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
789 list
[2].mailbox_holder
.texture_target
);
790 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
791 list
[3].mailbox_holder
.texture_target
);
792 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
793 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
794 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
795 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
796 resource_provider_
->ReceiveFromChild(child_id
, list
);
797 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
798 resource_ids_to_receive
.insert(id1
);
799 resource_ids_to_receive
.insert(id2
);
800 resource_ids_to_receive
.insert(id3
);
801 resource_ids_to_receive
.insert(id4
);
802 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
803 resource_ids_to_receive
);
806 EXPECT_EQ(0u, returned_to_child
.size());
808 EXPECT_EQ(4u, resource_provider_
->num_resources());
809 resource_provider_
->DestroyChild(child_id
);
810 EXPECT_EQ(0u, resource_provider_
->num_resources());
812 ASSERT_EQ(4u, returned_to_child
.size());
813 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
814 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
815 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
816 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
817 EXPECT_FALSE(returned_to_child
[0].lost
);
818 EXPECT_FALSE(returned_to_child
[1].lost
);
819 EXPECT_FALSE(returned_to_child
[2].lost
);
820 EXPECT_FALSE(returned_to_child
[3].lost
);
823 class ResourceProviderTestNoSyncPoint
: public ResourceProviderTest
{
825 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
826 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
, GetParam());
830 TEST_P(ResourceProviderTestNoSyncPoint
, TransferGLResources
) {
831 gfx::Size
size(1, 1);
832 ResourceFormat format
= RGBA_8888
;
833 size_t pixel_size
= TextureSizeBytes(size
, format
);
834 ASSERT_EQ(4U, pixel_size
);
836 ResourceId id1
= child_resource_provider_
->CreateResource(
837 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
838 uint8_t data1
[4] = {1, 2, 3, 4};
839 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
841 ResourceId id2
= child_resource_provider_
->CreateResource(
842 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
844 // Ensure locking the memory buffer doesn't create an unnecessary sync
846 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
847 child_resource_provider_
.get(), id2
);
848 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
851 GLuint external_texture_id
= child_context_
->createExternalTexture();
853 // A sync point is specified directly and should be used.
854 gpu::Mailbox external_mailbox
;
855 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
856 child_context_
->produceTextureDirectCHROMIUM(
857 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
858 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
859 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
860 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
861 external_sync_point
),
862 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
864 ReturnedResourceArray returned_to_child
;
866 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
867 resource_provider_
->SetChildNeedsSyncPoints(child_id
, false);
869 // Transfer some resources to the parent.
870 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
871 resource_ids_to_transfer
.push_back(id1
);
872 resource_ids_to_transfer
.push_back(id2
);
873 resource_ids_to_transfer
.push_back(id3
);
874 TransferableResourceArray list
;
875 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
877 ASSERT_EQ(3u, list
.size());
878 // Standard resources shouldn't require creating and sending a sync point.
879 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
880 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
881 // A given sync point should be passed through.
882 EXPECT_EQ(external_sync_point
, list
[2].mailbox_holder
.sync_point
);
883 resource_provider_
->ReceiveFromChild(child_id
, list
);
885 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
886 resource_ids_to_receive
.insert(id1
);
887 resource_ids_to_receive
.insert(id2
);
888 resource_ids_to_receive
.insert(id3
);
889 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
890 resource_ids_to_receive
);
894 EXPECT_EQ(0u, returned_to_child
.size());
896 // Transfer resources back from the parent to the child. Set no resources as
898 ResourceProvider::ResourceIdSet no_resources
;
899 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
901 ASSERT_EQ(3u, returned_to_child
.size());
902 std::map
<ResourceId
, unsigned int> returned_sync_points
;
903 for (const auto& returned
: returned_to_child
)
904 returned_sync_points
[returned
.id
] = returned
.sync_point
;
906 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
907 // No new sync point should be created transferring back.
908 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
909 EXPECT_EQ(0u, returned_sync_points
[id1
]);
910 EXPECT_TRUE(returned_sync_points
.find(id2
) != returned_sync_points
.end());
911 EXPECT_EQ(0u, returned_sync_points
[id2
]);
912 // Original sync point given should be returned.
913 EXPECT_TRUE(returned_sync_points
.find(id3
) != returned_sync_points
.end());
914 EXPECT_EQ(external_sync_point
, returned_sync_points
[id3
]);
915 EXPECT_FALSE(returned_to_child
[0].lost
);
916 EXPECT_FALSE(returned_to_child
[1].lost
);
917 EXPECT_FALSE(returned_to_child
[2].lost
);
918 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
919 returned_to_child
.clear();
922 resource_provider_
->DestroyChild(child_id
);
925 INSTANTIATE_TEST_CASE_P(
926 ResourceProviderTests
,
927 ResourceProviderTestNoSyncPoint
,
928 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
));
930 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
931 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
933 gfx::Size
size(1, 1);
934 ResourceFormat format
= RGBA_8888
;
936 ResourceId id1
= child_resource_provider_
->CreateResource(
937 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
938 uint8_t data1
[4] = {1, 2, 3, 4};
939 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
941 ReturnedResourceArray returned_to_child
;
943 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
945 // Transfer some resources to the parent.
946 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
947 resource_ids_to_transfer
.push_back(id1
);
948 TransferableResourceArray list
;
949 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
951 ASSERT_EQ(1u, list
.size());
952 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
954 resource_provider_
->ReceiveFromChild(child_id
, list
);
956 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
957 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
960 resource_provider_
->DeclareUsedResourcesFromChild(
961 child_id
, ResourceProvider::ResourceIdSet());
962 EXPECT_EQ(0u, returned_to_child
.size());
965 EXPECT_EQ(1u, returned_to_child
.size());
966 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
969 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
970 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
972 child_resource_provider_
->DeleteResource(id1
);
973 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
974 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
977 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
978 resource_provider_
->DestroyChild(child_id
);
981 class TestFence
: public ResourceProvider::Fence
{
985 void Set() override
{}
986 bool HasPassed() override
{ return passed
; }
987 void Wait() override
{}
992 ~TestFence() override
{}
995 TEST_P(ResourceProviderTest
, ReadLockFenceStopsReturnToChildOrDelete
) {
996 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
998 gfx::Size
size(1, 1);
999 ResourceFormat format
= RGBA_8888
;
1001 ResourceId id1
= child_resource_provider_
->CreateResource(
1002 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1003 uint8_t data1
[4] = {1, 2, 3, 4};
1004 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1005 child_resource_provider_
->EnableReadLockFencesForTesting(id1
);
1006 ReturnedResourceArray returned_to_child
;
1008 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1010 // Transfer some resources to the parent.
1011 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1012 resource_ids_to_transfer
.push_back(id1
);
1013 TransferableResourceArray list
;
1014 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1016 ASSERT_EQ(1u, list
.size());
1017 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1018 EXPECT_TRUE(list
[0].read_lock_fences_enabled
);
1020 resource_provider_
->ReceiveFromChild(child_id
, list
);
1022 scoped_refptr
<TestFence
> fence(new TestFence
);
1023 resource_provider_
->SetReadLockFence(fence
.get());
1025 unsigned parent_id
= list
.front().id
;
1026 resource_provider_
->WaitSyncPointIfNeeded(parent_id
);
1027 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1030 resource_provider_
->DeclareUsedResourcesFromChild(
1031 child_id
, ResourceProvider::ResourceIdSet());
1032 EXPECT_EQ(0u, returned_to_child
.size());
1034 resource_provider_
->DeclareUsedResourcesFromChild(
1035 child_id
, ResourceProvider::ResourceIdSet());
1036 EXPECT_EQ(0u, returned_to_child
.size());
1037 fence
->passed
= true;
1039 resource_provider_
->DeclareUsedResourcesFromChild(
1040 child_id
, ResourceProvider::ResourceIdSet());
1041 EXPECT_EQ(1u, returned_to_child
.size());
1043 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1044 child_resource_provider_
->DeleteResource(id1
);
1045 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1048 TEST_P(ResourceProviderTest
, ReadLockFenceDestroyChild
) {
1049 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1051 gfx::Size
size(1, 1);
1052 ResourceFormat format
= RGBA_8888
;
1054 ResourceId id1
= child_resource_provider_
->CreateResource(
1055 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1056 uint8_t data
[4] = {1, 2, 3, 4};
1057 child_resource_provider_
->CopyToResource(id1
, data
, size
);
1058 child_resource_provider_
->EnableReadLockFencesForTesting(id1
);
1060 ResourceId id2
= child_resource_provider_
->CreateResource(
1061 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1062 child_resource_provider_
->CopyToResource(id2
, data
, size
);
1064 ReturnedResourceArray returned_to_child
;
1066 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1068 // Transfer resources to the parent.
1069 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1070 resource_ids_to_transfer
.push_back(id1
);
1071 resource_ids_to_transfer
.push_back(id2
);
1072 TransferableResourceArray list
;
1073 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1075 ASSERT_EQ(2u, list
.size());
1076 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1077 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1079 resource_provider_
->ReceiveFromChild(child_id
, list
);
1081 scoped_refptr
<TestFence
> fence(new TestFence
);
1082 resource_provider_
->SetReadLockFence(fence
.get());
1084 for (size_t i
= 0; i
< list
.size(); i
++) {
1085 unsigned parent_id
= list
[i
].id
;
1086 resource_provider_
->WaitSyncPointIfNeeded(parent_id
);
1087 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1091 EXPECT_EQ(0u, returned_to_child
.size());
1093 EXPECT_EQ(2u, resource_provider_
->num_resources());
1095 resource_provider_
->DestroyChild(child_id
);
1097 EXPECT_EQ(0u, resource_provider_
->num_resources());
1098 EXPECT_EQ(2u, returned_to_child
.size());
1100 // id1 should be lost and id2 should not.
1101 EXPECT_EQ(returned_to_child
[0].lost
, returned_to_child
[0].id
== id1
);
1102 EXPECT_EQ(returned_to_child
[1].lost
, returned_to_child
[1].id
== id1
);
1104 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1105 child_resource_provider_
->DeleteResource(id1
);
1106 child_resource_provider_
->DeleteResource(id2
);
1107 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1110 TEST_P(ResourceProviderTest
, ReadLockFenceContextLost
) {
1111 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1113 gfx::Size
size(1, 1);
1114 ResourceFormat format
= RGBA_8888
;
1116 ResourceId id1
= child_resource_provider_
->CreateResource(
1117 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1118 uint8_t data
[4] = {1, 2, 3, 4};
1119 child_resource_provider_
->CopyToResource(id1
, data
, size
);
1120 child_resource_provider_
->EnableReadLockFencesForTesting(id1
);
1122 ResourceId id2
= child_resource_provider_
->CreateResource(
1123 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1124 child_resource_provider_
->CopyToResource(id2
, data
, size
);
1126 ReturnedResourceArray returned_to_child
;
1128 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1130 // Transfer resources to the parent.
1131 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1132 resource_ids_to_transfer
.push_back(id1
);
1133 resource_ids_to_transfer
.push_back(id2
);
1134 TransferableResourceArray list
;
1135 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1137 ASSERT_EQ(2u, list
.size());
1138 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1139 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1141 resource_provider_
->ReceiveFromChild(child_id
, list
);
1143 scoped_refptr
<TestFence
> fence(new TestFence
);
1144 resource_provider_
->SetReadLockFence(fence
.get());
1146 for (size_t i
= 0; i
< list
.size(); i
++) {
1147 unsigned parent_id
= list
[i
].id
;
1148 resource_provider_
->WaitSyncPointIfNeeded(parent_id
);
1149 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1153 EXPECT_EQ(0u, returned_to_child
.size());
1155 EXPECT_EQ(2u, resource_provider_
->num_resources());
1156 resource_provider_
->DidLoseOutputSurface();
1157 resource_provider_
= nullptr;
1159 EXPECT_EQ(2u, returned_to_child
.size());
1161 EXPECT_TRUE(returned_to_child
[0].lost
);
1162 EXPECT_TRUE(returned_to_child
[1].lost
);
1165 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
1166 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1169 gfx::Size
size(1, 1);
1170 ResourceFormat format
= RGBA_8888
;
1171 size_t pixel_size
= TextureSizeBytes(size
, format
);
1172 ASSERT_EQ(4U, pixel_size
);
1174 ResourceId id1
= child_resource_provider_
->CreateResource(
1175 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1176 uint8_t data1
[4] = { 1, 2, 3, 4 };
1177 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1179 ResourceId id2
= child_resource_provider_
->CreateResource(
1180 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1181 uint8_t data2
[4] = { 5, 5, 5, 5 };
1182 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1184 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1185 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1186 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1187 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1188 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1189 SingleReleaseCallbackImpl::Create(base::Bind(
1190 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1192 ReturnedResourceArray returned_to_child
;
1194 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1196 // Transfer some resources to the parent.
1197 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1198 resource_ids_to_transfer
.push_back(id1
);
1199 resource_ids_to_transfer
.push_back(id2
);
1200 resource_ids_to_transfer
.push_back(id3
);
1201 TransferableResourceArray list
;
1202 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1204 ASSERT_EQ(3u, list
.size());
1205 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1206 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1207 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1208 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1209 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1210 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1211 resource_provider_
->ReceiveFromChild(child_id
, list
);
1212 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1213 resource_ids_to_receive
.insert(id1
);
1214 resource_ids_to_receive
.insert(id2
);
1215 resource_ids_to_receive
.insert(id3
);
1216 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1217 resource_ids_to_receive
);
1220 EXPECT_EQ(3u, resource_provider_
->num_resources());
1221 ResourceProvider::ResourceIdMap resource_map
=
1222 resource_provider_
->GetChildToParentMap(child_id
);
1223 ResourceId mapped_id1
= resource_map
[id1
];
1224 ResourceId mapped_id2
= resource_map
[id2
];
1225 ResourceId mapped_id3
= resource_map
[id3
];
1226 EXPECT_NE(0u, mapped_id1
);
1227 EXPECT_NE(0u, mapped_id2
);
1228 EXPECT_NE(0u, mapped_id3
);
1229 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1230 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1231 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1233 uint8_t result
[4] = { 0 };
1235 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1236 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1239 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1240 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1243 // Check that transfering again the same resource from the child to the
1245 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1246 resource_ids_to_transfer
.push_back(id1
);
1247 resource_ids_to_transfer
.push_back(id2
);
1248 TransferableResourceArray list
;
1249 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1251 EXPECT_EQ(2u, list
.size());
1252 EXPECT_EQ(id1
, list
[0].id
);
1253 EXPECT_EQ(id2
, list
[1].id
);
1254 ReturnedResourceArray returned
;
1255 TransferableResource::ReturnResources(list
, &returned
);
1256 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1257 // ids were exported twice, we returned them only once, they should still
1259 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1260 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1263 EXPECT_EQ(0u, returned_to_child
.size());
1265 // Transfer resources back from the parent to the child. Set no resources as
1267 ResourceProvider::ResourceIdSet no_resources
;
1268 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1270 ASSERT_EQ(3u, returned_to_child
.size());
1271 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1272 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1273 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1274 std::set
<ResourceId
> expected_ids
;
1275 expected_ids
.insert(id1
);
1276 expected_ids
.insert(id2
);
1277 expected_ids
.insert(id3
);
1278 std::set
<ResourceId
> returned_ids
;
1279 for (unsigned i
= 0; i
< 3; i
++)
1280 returned_ids
.insert(returned_to_child
[i
].id
);
1281 EXPECT_EQ(expected_ids
, returned_ids
);
1282 EXPECT_FALSE(returned_to_child
[0].lost
);
1283 EXPECT_FALSE(returned_to_child
[1].lost
);
1284 EXPECT_FALSE(returned_to_child
[2].lost
);
1285 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1286 returned_to_child
.clear();
1288 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1289 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1290 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1293 ResourceProvider::ScopedReadLockSoftware
lock(
1294 child_resource_provider_
.get(), id1
);
1295 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1296 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1297 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1298 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1301 ResourceProvider::ScopedReadLockSoftware
lock(
1302 child_resource_provider_
.get(), id2
);
1303 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1304 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1305 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1306 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1309 // Transfer resources to the parent again.
1310 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1311 resource_ids_to_transfer
.push_back(id1
);
1312 resource_ids_to_transfer
.push_back(id2
);
1313 resource_ids_to_transfer
.push_back(id3
);
1314 TransferableResourceArray list
;
1315 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1317 ASSERT_EQ(3u, list
.size());
1318 EXPECT_EQ(id1
, list
[0].id
);
1319 EXPECT_EQ(id2
, list
[1].id
);
1320 EXPECT_EQ(id3
, list
[2].id
);
1321 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1322 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1323 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1324 resource_provider_
->ReceiveFromChild(child_id
, list
);
1325 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1326 resource_ids_to_receive
.insert(id1
);
1327 resource_ids_to_receive
.insert(id2
);
1328 resource_ids_to_receive
.insert(id3
);
1329 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1330 resource_ids_to_receive
);
1333 EXPECT_EQ(0u, returned_to_child
.size());
1335 EXPECT_EQ(3u, resource_provider_
->num_resources());
1336 resource_provider_
->DestroyChild(child_id
);
1337 EXPECT_EQ(0u, resource_provider_
->num_resources());
1339 ASSERT_EQ(3u, returned_to_child
.size());
1340 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1341 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1342 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1343 std::set
<ResourceId
> expected_ids
;
1344 expected_ids
.insert(id1
);
1345 expected_ids
.insert(id2
);
1346 expected_ids
.insert(id3
);
1347 std::set
<ResourceId
> returned_ids
;
1348 for (unsigned i
= 0; i
< 3; i
++)
1349 returned_ids
.insert(returned_to_child
[i
].id
);
1350 EXPECT_EQ(expected_ids
, returned_ids
);
1351 EXPECT_FALSE(returned_to_child
[0].lost
);
1352 EXPECT_FALSE(returned_to_child
[1].lost
);
1353 EXPECT_FALSE(returned_to_child
[2].lost
);
1356 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1357 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1360 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1361 ResourceProviderContext::Create(shared_data_
.get()));
1363 FakeOutputSurfaceClient child_output_surface_client
;
1364 scoped_ptr
<OutputSurface
> child_output_surface(
1365 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1366 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1368 scoped_ptr
<ResourceProvider
> child_resource_provider(ResourceProvider::Create(
1369 child_output_surface
.get(), shared_bitmap_manager_
.get(),
1370 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
1372 gfx::Size
size(1, 1);
1373 ResourceFormat format
= RGBA_8888
;
1374 size_t pixel_size
= TextureSizeBytes(size
, format
);
1375 ASSERT_EQ(4U, pixel_size
);
1377 ResourceId id1
= child_resource_provider
->CreateResource(
1378 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1379 uint8_t data1
[4] = { 1, 2, 3, 4 };
1380 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1382 ReturnedResourceArray returned_to_child
;
1384 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1386 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1387 resource_ids_to_transfer
.push_back(id1
);
1388 TransferableResourceArray list
;
1389 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1391 ASSERT_EQ(1u, list
.size());
1392 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1393 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1394 list
[0].mailbox_holder
.texture_target
);
1395 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1396 resource_provider_
->ReceiveFromChild(child_id
, list
);
1399 EXPECT_EQ(0u, resource_provider_
->num_resources());
1400 ASSERT_EQ(1u, returned_to_child
.size());
1401 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1402 ResourceProvider::ResourceIdMap resource_map
=
1403 resource_provider_
->GetChildToParentMap(child_id
);
1404 ResourceId mapped_id1
= resource_map
[id1
];
1405 EXPECT_EQ(0u, mapped_id1
);
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
, TransferInvalidSoftware
) {
1415 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1418 gfx::Size
size(1, 1);
1419 ResourceFormat format
= RGBA_8888
;
1420 size_t pixel_size
= TextureSizeBytes(size
, format
);
1421 ASSERT_EQ(4U, pixel_size
);
1423 ResourceId id1
= child_resource_provider_
->CreateResource(
1424 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1425 uint8_t data1
[4] = { 1, 2, 3, 4 };
1426 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1428 ReturnedResourceArray returned_to_child
;
1430 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1432 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1433 resource_ids_to_transfer
.push_back(id1
);
1434 TransferableResourceArray list
;
1435 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1437 ASSERT_EQ(1u, list
.size());
1439 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1440 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1441 resource_provider_
->ReceiveFromChild(child_id
, list
);
1444 EXPECT_EQ(1u, resource_provider_
->num_resources());
1445 EXPECT_EQ(0u, returned_to_child
.size());
1447 ResourceProvider::ResourceIdMap resource_map
=
1448 resource_provider_
->GetChildToParentMap(child_id
);
1449 ResourceId mapped_id1
= resource_map
[id1
];
1450 EXPECT_NE(0u, mapped_id1
);
1452 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1454 EXPECT_FALSE(lock
.valid());
1457 resource_provider_
->DestroyChild(child_id
);
1458 EXPECT_EQ(0u, resource_provider_
->num_resources());
1460 ASSERT_EQ(1u, returned_to_child
.size());
1461 EXPECT_FALSE(returned_to_child
[0].lost
);
1464 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1465 gfx::Size
size(1, 1);
1466 ResourceFormat format
= RGBA_8888
;
1467 size_t pixel_size
= TextureSizeBytes(size
, format
);
1468 ASSERT_EQ(4U, pixel_size
);
1470 ResourceId id1
= child_resource_provider_
->CreateResource(
1471 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1472 uint8_t data1
[4] = { 1, 2, 3, 4 };
1473 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1475 ResourceId id2
= child_resource_provider_
->CreateResource(
1476 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1477 uint8_t data2
[4] = {5, 5, 5, 5};
1478 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1480 ReturnedResourceArray returned_to_child
;
1482 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1484 // Transfer some resources to the parent.
1485 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1486 resource_ids_to_transfer
.push_back(id1
);
1487 resource_ids_to_transfer
.push_back(id2
);
1488 TransferableResourceArray list
;
1489 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1491 ASSERT_EQ(2u, list
.size());
1492 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1493 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1494 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1496 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1497 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1498 resource_provider_
->ReceiveFromChild(child_id
, list
);
1499 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1500 resource_ids_to_receive
.insert(id1
);
1501 resource_ids_to_receive
.insert(id2
);
1502 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1503 resource_ids_to_receive
);
1506 EXPECT_EQ(2u, resource_provider_
->num_resources());
1507 ResourceProvider::ResourceIdMap resource_map
=
1508 resource_provider_
->GetChildToParentMap(child_id
);
1509 ResourceId mapped_id1
= resource_map
[id1
];
1510 ResourceId mapped_id2
= resource_map
[id2
];
1511 EXPECT_NE(0u, mapped_id1
);
1512 EXPECT_NE(0u, mapped_id2
);
1513 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1514 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1517 // The parent transfers the resources to the grandparent.
1518 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1519 resource_ids_to_transfer
.push_back(mapped_id1
);
1520 resource_ids_to_transfer
.push_back(mapped_id2
);
1521 TransferableResourceArray list
;
1522 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1524 ASSERT_EQ(2u, list
.size());
1525 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1526 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1527 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1529 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1530 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1532 // Release the resource in the parent. Set no resources as being in use. The
1533 // resources are exported so that can't be transferred back yet.
1534 ResourceProvider::ResourceIdSet no_resources
;
1535 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1537 EXPECT_EQ(0u, returned_to_child
.size());
1538 EXPECT_EQ(2u, resource_provider_
->num_resources());
1540 // Return the resources from the grandparent to the parent. They should be
1541 // returned to the child then.
1542 EXPECT_EQ(2u, list
.size());
1543 EXPECT_EQ(mapped_id1
, list
[0].id
);
1544 EXPECT_EQ(mapped_id2
, list
[1].id
);
1545 ReturnedResourceArray returned
;
1546 TransferableResource::ReturnResources(list
, &returned
);
1547 resource_provider_
->ReceiveReturnsFromParent(returned
);
1549 EXPECT_EQ(0u, resource_provider_
->num_resources());
1550 ASSERT_EQ(2u, returned_to_child
.size());
1551 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1552 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1553 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1555 EXPECT_FALSE(returned_to_child
[0].lost
);
1556 EXPECT_FALSE(returned_to_child
[1].lost
);
1560 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1561 gfx::Size
size(1, 1);
1562 ResourceFormat format
= RGBA_8888
;
1563 size_t pixel_size
= TextureSizeBytes(size
, format
);
1564 ASSERT_EQ(4U, pixel_size
);
1566 ResourceId id1
= child_resource_provider_
->CreateResource(
1567 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1568 uint8_t data1
[4] = {1, 2, 3, 4};
1569 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1571 ResourceId id2
= child_resource_provider_
->CreateResource(
1572 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1573 uint8_t data2
[4] = {5, 5, 5, 5};
1574 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1576 ReturnedResourceArray returned_to_child
;
1578 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1580 // Transfer some resources to the parent.
1581 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1582 resource_ids_to_transfer
.push_back(id1
);
1583 resource_ids_to_transfer
.push_back(id2
);
1584 TransferableResourceArray list
;
1585 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1587 ASSERT_EQ(2u, list
.size());
1588 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1589 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1590 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1592 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1593 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1594 resource_provider_
->ReceiveFromChild(child_id
, list
);
1595 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1596 resource_ids_to_receive
.insert(id1
);
1597 resource_ids_to_receive
.insert(id2
);
1598 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1599 resource_ids_to_receive
);
1602 EXPECT_EQ(2u, resource_provider_
->num_resources());
1603 ResourceProvider::ResourceIdMap resource_map
=
1604 resource_provider_
->GetChildToParentMap(child_id
);
1605 ResourceId mapped_id1
= resource_map
[id1
];
1606 ResourceId mapped_id2
= resource_map
[id2
];
1607 EXPECT_NE(0u, mapped_id1
);
1608 EXPECT_NE(0u, mapped_id2
);
1609 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1610 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1613 // The parent transfers the resources to the grandparent.
1614 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1615 resource_ids_to_transfer
.push_back(mapped_id1
);
1616 resource_ids_to_transfer
.push_back(mapped_id2
);
1617 TransferableResourceArray list
;
1618 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1620 ASSERT_EQ(2u, list
.size());
1621 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1622 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1623 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1625 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1626 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1628 // Release the resource in the parent. Set no resources as being in use. The
1629 // resources are exported so that can't be transferred back yet.
1630 ResourceProvider::ResourceIdSet no_resources
;
1631 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1633 // Destroy the child, the resources should not be returned yet.
1634 EXPECT_EQ(0u, returned_to_child
.size());
1635 EXPECT_EQ(2u, resource_provider_
->num_resources());
1637 resource_provider_
->DestroyChild(child_id
);
1639 EXPECT_EQ(2u, resource_provider_
->num_resources());
1640 ASSERT_EQ(0u, returned_to_child
.size());
1642 // Return a resource from the grandparent, it should be returned at this
1644 EXPECT_EQ(2u, list
.size());
1645 EXPECT_EQ(mapped_id1
, list
[0].id
);
1646 EXPECT_EQ(mapped_id2
, list
[1].id
);
1647 TransferableResourceArray return_list
;
1648 return_list
.push_back(list
[1]);
1650 ReturnedResourceArray returned
;
1651 TransferableResource::ReturnResources(return_list
, &returned
);
1652 resource_provider_
->ReceiveReturnsFromParent(returned
);
1654 EXPECT_EQ(1u, resource_provider_
->num_resources());
1655 ASSERT_EQ(1u, returned_to_child
.size());
1656 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1657 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1659 EXPECT_FALSE(returned_to_child
[0].lost
);
1660 returned_to_child
.clear();
1662 // Destroy the parent resource provider. The resource that's left should be
1663 // lost at this point, and returned.
1664 resource_provider_
= nullptr;
1665 ASSERT_EQ(1u, returned_to_child
.size());
1666 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1667 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1669 EXPECT_TRUE(returned_to_child
[0].lost
);
1673 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1674 gfx::Size
size(1, 1);
1675 ResourceFormat format
= RGBA_8888
;
1676 size_t pixel_size
= TextureSizeBytes(size
, format
);
1677 ASSERT_EQ(4U, pixel_size
);
1679 ResourceId id
= child_resource_provider_
->CreateResource(
1680 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1681 uint8_t data
[4] = { 1, 2, 3, 4 };
1682 child_resource_provider_
->CopyToResource(id
, data
, size
);
1684 ReturnedResourceArray returned_to_child
;
1686 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1688 // Transfer some resource to the parent.
1689 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1690 resource_ids_to_transfer
.push_back(id
);
1691 TransferableResourceArray list
;
1692 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1694 ASSERT_EQ(1u, list
.size());
1695 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1696 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
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
);
1705 // Delete textures in the child, while they are transfered.
1706 child_resource_provider_
->DeleteResource(id
);
1707 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1709 EXPECT_EQ(0u, returned_to_child
.size());
1711 // Transfer resources back from the parent to the child. Set no resources as
1713 ResourceProvider::ResourceIdSet no_resources
;
1714 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1716 ASSERT_EQ(1u, returned_to_child
.size());
1717 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1718 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1719 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1721 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1724 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1725 gfx::Size
size(1, 1);
1726 ResourceFormat format
= RGBA_8888
;
1727 size_t pixel_size
= TextureSizeBytes(size
, format
);
1728 ASSERT_EQ(4U, pixel_size
);
1730 ResourceId id
= child_resource_provider_
->CreateResource(
1731 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1732 uint8_t data
[4] = {1, 2, 3, 4};
1733 child_resource_provider_
->CopyToResource(id
, data
, size
);
1735 ReturnedResourceArray returned_to_child
;
1737 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1738 const ResourceProvider::ResourceIdMap
& map
=
1739 resource_provider_
->GetChildToParentMap(child_id
);
1741 // Transfer some resource to the parent.
1742 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1743 resource_ids_to_transfer
.push_back(id
);
1744 TransferableResourceArray list
;
1745 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1747 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1748 resource_provider_
->ReceiveFromChild(child_id
, list
);
1749 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1750 resource_ids_to_receive
.insert(id
);
1751 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1752 resource_ids_to_receive
);
1754 TransferableResourceArray sent_to_top_level
;
1756 // Parent transfers to top-level.
1757 ASSERT_TRUE(map
.find(id
) != map
.end());
1758 ResourceId parent_id
= map
.find(id
)->second
;
1759 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1760 resource_ids_to_transfer
.push_back(parent_id
);
1761 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1762 &sent_to_top_level
);
1763 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1766 // Stop using resource.
1767 ResourceProvider::ResourceIdSet empty
;
1768 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1769 // Resource is not yet returned to the child, since it's in use by the
1771 EXPECT_TRUE(returned_to_child
.empty());
1774 // Send the resource to the parent again.
1775 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1776 resource_ids_to_transfer
.push_back(id
);
1777 TransferableResourceArray list
;
1778 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1780 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1781 resource_provider_
->ReceiveFromChild(child_id
, list
);
1782 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1783 resource_ids_to_receive
.insert(id
);
1784 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1785 resource_ids_to_receive
);
1788 // Receive returns back from top-level.
1789 ReturnedResourceArray returned
;
1790 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1791 resource_provider_
->ReceiveReturnsFromParent(returned
);
1792 // Resource is still not yet returned to the child, since it's declared used
1794 EXPECT_TRUE(returned_to_child
.empty());
1795 ASSERT_TRUE(map
.find(id
) != map
.end());
1796 ResourceId parent_id
= map
.find(id
)->second
;
1797 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1800 sent_to_top_level
.clear();
1801 // Parent transfers again to top-level.
1802 ASSERT_TRUE(map
.find(id
) != map
.end());
1803 ResourceId parent_id
= map
.find(id
)->second
;
1804 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1805 resource_ids_to_transfer
.push_back(parent_id
);
1806 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1807 &sent_to_top_level
);
1808 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1811 // Receive returns back from top-level.
1812 ReturnedResourceArray returned
;
1813 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1814 resource_provider_
->ReceiveReturnsFromParent(returned
);
1815 // Resource is still not yet returned to the child, since it's still
1816 // declared used in the parent.
1817 EXPECT_TRUE(returned_to_child
.empty());
1818 ASSERT_TRUE(map
.find(id
) != map
.end());
1819 ResourceId parent_id
= map
.find(id
)->second
;
1820 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1823 // Stop using resource.
1824 ResourceProvider::ResourceIdSet empty
;
1825 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1826 // Resource should have been returned to the child, since it's no longer in
1827 // use by the top-level.
1828 ASSERT_EQ(1u, returned_to_child
.size());
1829 EXPECT_EQ(id
, returned_to_child
[0].id
);
1830 EXPECT_EQ(2, returned_to_child
[0].count
);
1831 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1832 returned_to_child
.clear();
1833 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1837 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1839 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1840 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1841 new TextureStateTrackingContext
);
1842 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1844 FakeOutputSurfaceClient child_output_surface_client
;
1845 scoped_ptr
<OutputSurface
> child_output_surface(
1846 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1847 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1848 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1849 new TestSharedBitmapManager());
1851 scoped_ptr
<ResourceProvider
> child_resource_provider(
1852 ResourceProvider::Create(child_output_surface
.get(),
1853 shared_bitmap_manager
.get(), NULL
, NULL
, 0,
1856 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1857 new TextureStateTrackingContext
);
1858 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1860 FakeOutputSurfaceClient parent_output_surface_client
;
1861 scoped_ptr
<OutputSurface
> parent_output_surface(
1862 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1863 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1865 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1866 ResourceProvider::Create(parent_output_surface
.get(),
1867 shared_bitmap_manager
.get(), NULL
, NULL
, 0,
1870 gfx::Size
size(1, 1);
1871 ResourceFormat format
= RGBA_8888
;
1872 int child_texture_id
= 1;
1873 int parent_texture_id
= 2;
1875 size_t pixel_size
= TextureSizeBytes(size
, format
);
1876 ASSERT_EQ(4U, pixel_size
);
1878 ResourceId id
= child_resource_provider
->CreateResource(
1879 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1882 // The new texture is created with GL_LINEAR.
1883 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1884 .Times(2); // Once to create and once to allocate.
1885 EXPECT_CALL(*child_context
,
1886 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1887 EXPECT_CALL(*child_context
,
1888 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1891 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1894 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1895 EXPECT_CALL(*child_context
,
1896 texParameteri(GL_TEXTURE_2D
,
1897 GL_TEXTURE_POOL_CHROMIUM
,
1898 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1899 child_resource_provider
->AllocateForTesting(id
);
1900 Mock::VerifyAndClearExpectations(child_context
);
1902 uint8_t data
[4] = { 1, 2, 3, 4 };
1904 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1905 child_resource_provider
->CopyToResource(id
, data
, size
);
1906 Mock::VerifyAndClearExpectations(child_context
);
1908 // The texture is set to |child_filter| in the child.
1909 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1910 if (child_filter
!= GL_LINEAR
) {
1913 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1916 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1918 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1919 Mock::VerifyAndClearExpectations(child_context
);
1921 ReturnedResourceArray returned_to_child
;
1922 int child_id
= parent_resource_provider
->CreateChild(
1923 GetReturnCallback(&returned_to_child
));
1925 // Transfer some resource to the parent.
1926 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1927 resource_ids_to_transfer
.push_back(id
);
1928 TransferableResourceArray list
;
1930 EXPECT_CALL(*child_context
,
1931 produceTextureDirectCHROMIUM(_
, GL_TEXTURE_2D
, _
));
1932 EXPECT_CALL(*child_context
, insertSyncPoint());
1933 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1935 Mock::VerifyAndClearExpectations(child_context
);
1937 ASSERT_EQ(1u, list
.size());
1938 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1940 EXPECT_CALL(*parent_context
,
1941 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, _
))
1942 .WillOnce(Return(parent_texture_id
));
1944 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1946 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1947 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1950 Mock::VerifyAndClearExpectations(parent_context
);
1952 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1953 resource_ids_to_receive
.insert(id
);
1954 parent_resource_provider
->DeclareUsedResourcesFromChild(
1955 child_id
, resource_ids_to_receive
);
1956 Mock::VerifyAndClearExpectations(parent_context
);
1958 ResourceProvider::ResourceIdMap resource_map
=
1959 parent_resource_provider
->GetChildToParentMap(child_id
);
1960 ResourceId mapped_id
= resource_map
[id
];
1961 EXPECT_NE(0u, mapped_id
);
1963 // The texture is set to |parent_filter| in the parent.
1964 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1967 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1970 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1971 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1972 Mock::VerifyAndClearExpectations(parent_context
);
1974 // The texture should be reset to |child_filter| in the parent when it is
1975 // returned, since that is how it was received.
1976 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1979 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1982 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1985 EXPECT_EQ(0u, returned_to_child
.size());
1987 // Transfer resources back from the parent to the child. Set no resources
1989 ResourceProvider::ResourceIdSet no_resources
;
1990 EXPECT_CALL(*parent_context
, insertSyncPoint());
1991 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1993 Mock::VerifyAndClearExpectations(parent_context
);
1995 ASSERT_EQ(1u, returned_to_child
.size());
1996 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1999 // The child remembers the texture filter is set to |child_filter|.
2000 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
2001 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
2002 Mock::VerifyAndClearExpectations(child_context
);
2006 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
2007 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2009 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
2012 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
2013 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2015 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
2018 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
2019 // Other mailbox transfers tested elsewhere.
2020 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2022 unsigned texture
= context()->createTexture();
2023 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2024 uint8_t data
[4] = { 1, 2, 3, 4 };
2025 context()->texImage2D(
2026 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
2027 gpu::Mailbox mailbox
;
2028 context()->genMailboxCHROMIUM(mailbox
.name
);
2029 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2030 uint32 sync_point
= context()->insertSyncPoint();
2032 // All the logic below assumes that the sync points are all positive.
2033 EXPECT_LT(0u, sync_point
);
2035 uint32 release_sync_point
= 0;
2036 bool lost_resource
= false;
2037 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2038 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
2039 &release_sync_point
,
2041 &main_thread_task_runner
);
2042 ResourceId resource
= resource_provider_
->CreateResourceFromTextureMailbox(
2043 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2044 SingleReleaseCallbackImpl::Create(callback
));
2045 EXPECT_EQ(1u, context()->NumTextures());
2046 EXPECT_EQ(0u, release_sync_point
);
2048 // Transfer the resource, expect the sync points to be consistent.
2049 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2050 resource_ids_to_transfer
.push_back(resource
);
2051 TransferableResourceArray list
;
2052 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2053 ASSERT_EQ(1u, list
.size());
2054 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2056 memcmp(mailbox
.name
,
2057 list
[0].mailbox_holder
.mailbox
.name
,
2058 sizeof(mailbox
.name
)));
2059 EXPECT_EQ(0u, release_sync_point
);
2061 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2062 unsigned other_texture
=
2063 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2064 uint8_t test_data
[4] = { 0 };
2065 context()->GetPixels(
2066 gfx::Size(1, 1), RGBA_8888
, test_data
);
2067 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2069 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2071 context()->deleteTexture(other_texture
);
2072 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2073 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2075 // Receive the resource, then delete it, expect the sync points to be
2077 ReturnedResourceArray returned
;
2078 TransferableResource::ReturnResources(list
, &returned
);
2079 resource_provider_
->ReceiveReturnsFromParent(returned
);
2080 EXPECT_EQ(1u, context()->NumTextures());
2081 EXPECT_EQ(0u, release_sync_point
);
2083 resource_provider_
->DeleteResource(resource
);
2084 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2085 EXPECT_FALSE(lost_resource
);
2086 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2089 // We're going to do the same thing as above, but testing the case where we
2090 // delete the resource before we receive it back.
2091 sync_point
= release_sync_point
;
2092 EXPECT_LT(0u, sync_point
);
2093 release_sync_point
= 0;
2094 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
2095 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2096 SingleReleaseCallbackImpl::Create(callback
));
2097 EXPECT_EQ(1u, context()->NumTextures());
2098 EXPECT_EQ(0u, release_sync_point
);
2100 // Transfer the resource, expect the sync points to be consistent.
2101 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2102 resource_ids_to_transfer
.push_back(resource
);
2103 TransferableResourceArray list
;
2104 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2105 ASSERT_EQ(1u, list
.size());
2106 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2108 memcmp(mailbox
.name
,
2109 list
[0].mailbox_holder
.mailbox
.name
,
2110 sizeof(mailbox
.name
)));
2111 EXPECT_EQ(0u, release_sync_point
);
2113 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2114 unsigned other_texture
=
2115 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2116 uint8_t test_data
[4] = { 0 };
2117 context()->GetPixels(
2118 gfx::Size(1, 1), RGBA_8888
, test_data
);
2119 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2121 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2123 context()->deleteTexture(other_texture
);
2124 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2125 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2127 // Delete the resource, which shouldn't do anything.
2128 resource_provider_
->DeleteResource(resource
);
2129 EXPECT_EQ(1u, context()->NumTextures());
2130 EXPECT_EQ(0u, release_sync_point
);
2132 // Then receive the resource which should release the mailbox, expect the
2133 // sync points to be consistent.
2134 ReturnedResourceArray returned
;
2135 TransferableResource::ReturnResources(list
, &returned
);
2136 resource_provider_
->ReceiveReturnsFromParent(returned
);
2137 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2138 EXPECT_FALSE(lost_resource
);
2139 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2142 context()->waitSyncPoint(release_sync_point
);
2144 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2145 context()->deleteTexture(texture
);
2148 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
2149 gfx::Size
size(1, 1);
2150 ResourceFormat format
= RGBA_8888
;
2151 ResourceId resource
= child_resource_provider_
->CreateResource(
2152 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2153 child_resource_provider_
->AllocateForTesting(resource
);
2154 // Expect a GL resource to be lost.
2155 bool should_lose_resource
=
2156 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
2158 ReturnedResourceArray returned_to_child
;
2160 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2162 // Transfer the resource to the parent.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2164 resource_ids_to_transfer
.push_back(resource
);
2165 TransferableResourceArray list
;
2166 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2168 EXPECT_EQ(1u, list
.size());
2170 resource_provider_
->ReceiveFromChild(child_id
, list
);
2171 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2172 resource_ids_to_receive
.insert(resource
);
2173 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2174 resource_ids_to_receive
);
2177 // Lose the output surface in the parent.
2178 resource_provider_
->DidLoseOutputSurface();
2181 EXPECT_EQ(0u, returned_to_child
.size());
2183 // Transfer resources back from the parent to the child. Set no resources as
2185 ResourceProvider::ResourceIdSet no_resources
;
2186 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2188 // Expect a GL resource to be lost.
2189 ASSERT_EQ(1u, returned_to_child
.size());
2190 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2191 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2192 returned_to_child
.clear();
2195 // A GL resource should be lost.
2196 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2198 // Lost resources stay in use in the parent forever.
2199 EXPECT_EQ(should_lose_resource
,
2200 child_resource_provider_
->InUseByConsumer(resource
));
2203 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2204 gfx::Size
size(1, 1);
2205 ResourceFormat format
= RGBA_8888
;
2206 ResourceId resource
= child_resource_provider_
->CreateResource(
2207 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2208 child_resource_provider_
->AllocateForTesting(resource
);
2210 ReturnedResourceArray returned_to_child
;
2212 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2214 // Transfer the resource to the parent.
2215 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2216 resource_ids_to_transfer
.push_back(resource
);
2217 TransferableResourceArray list
;
2218 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2220 EXPECT_EQ(1u, list
.size());
2222 resource_provider_
->ReceiveFromChild(child_id
, list
);
2223 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2224 resource_ids_to_receive
.insert(resource
);
2225 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2226 resource_ids_to_receive
);
2230 ResourceProvider::ResourceIdMap resource_map
=
2231 resource_provider_
->GetChildToParentMap(child_id
);
2232 ResourceId parent_resource
= resource_map
[resource
];
2233 EXPECT_NE(0u, parent_resource
);
2235 // Transfer to a grandparent.
2236 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2237 resource_ids_to_transfer
.push_back(parent_resource
);
2238 TransferableResourceArray list
;
2239 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2241 // Receive back a lost resource from the grandparent.
2242 EXPECT_EQ(1u, list
.size());
2243 EXPECT_EQ(parent_resource
, list
[0].id
);
2244 ReturnedResourceArray returned
;
2245 TransferableResource::ReturnResources(list
, &returned
);
2246 EXPECT_EQ(1u, returned
.size());
2247 EXPECT_EQ(parent_resource
, returned
[0].id
);
2248 returned
[0].lost
= true;
2249 resource_provider_
->ReceiveReturnsFromParent(returned
);
2251 // The resource should be lost.
2252 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2254 // Lost resources stay in use in the parent forever.
2255 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2259 EXPECT_EQ(0u, returned_to_child
.size());
2261 // Transfer resources back from the parent to the child. Set no resources as
2263 ResourceProvider::ResourceIdSet no_resources
;
2264 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2266 // Expect the resource to be lost.
2267 ASSERT_EQ(1u, returned_to_child
.size());
2268 EXPECT_TRUE(returned_to_child
[0].lost
);
2269 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2270 returned_to_child
.clear();
2273 // The resource should be lost.
2274 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2276 // Lost resources stay in use in the parent forever.
2277 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2280 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2281 uint32 release_sync_point
= 0;
2282 bool lost_resource
= false;
2283 bool release_called
= false;
2284 uint32 sync_point
= 0;
2285 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2286 &release_called
, &sync_point
);
2288 ReturnedResourceArray returned_to_child
;
2290 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2292 // Transfer the resource to the parent.
2293 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2294 resource_ids_to_transfer
.push_back(resource
);
2295 TransferableResourceArray list
;
2296 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2298 EXPECT_EQ(1u, list
.size());
2300 resource_provider_
->ReceiveFromChild(child_id
, list
);
2301 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2302 resource_ids_to_receive
.insert(resource
);
2303 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2304 resource_ids_to_receive
);
2307 // Lose the output surface in the parent.
2308 resource_provider_
->DidLoseOutputSurface();
2311 EXPECT_EQ(0u, returned_to_child
.size());
2313 // Transfer resources back from the parent to the child. Set no resources as
2315 ResourceProvider::ResourceIdSet no_resources
;
2316 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2318 ASSERT_EQ(1u, returned_to_child
.size());
2319 // Losing an output surface only loses hardware resources.
2320 EXPECT_EQ(returned_to_child
[0].lost
,
2321 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2322 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2323 returned_to_child
.clear();
2326 // Delete the resource in the child. Expect the resource to be lost if it's
2328 child_resource_provider_
->DeleteResource(resource
);
2329 EXPECT_EQ(lost_resource
,
2330 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2333 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2334 uint32 release_sync_point
= 0;
2335 bool lost_resource
= false;
2336 bool release_called
= false;
2337 uint32 sync_point
= 0;
2338 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2339 &release_called
, &sync_point
);
2341 ReturnedResourceArray returned_to_child
;
2343 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2345 // Transfer the resource to the parent.
2346 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2347 resource_ids_to_transfer
.push_back(resource
);
2348 TransferableResourceArray list
;
2349 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2351 EXPECT_EQ(1u, list
.size());
2353 resource_provider_
->ReceiveFromChild(child_id
, list
);
2354 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2355 resource_ids_to_receive
.insert(resource
);
2356 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2357 resource_ids_to_receive
);
2361 ResourceProvider::ResourceIdMap resource_map
=
2362 resource_provider_
->GetChildToParentMap(child_id
);
2363 ResourceId parent_resource
= resource_map
[resource
];
2364 EXPECT_NE(0u, parent_resource
);
2366 // Transfer to a grandparent.
2367 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2368 resource_ids_to_transfer
.push_back(parent_resource
);
2369 TransferableResourceArray list
;
2370 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2372 // Receive back a lost resource from the grandparent.
2373 EXPECT_EQ(1u, list
.size());
2374 EXPECT_EQ(parent_resource
, list
[0].id
);
2375 ReturnedResourceArray returned
;
2376 TransferableResource::ReturnResources(list
, &returned
);
2377 EXPECT_EQ(1u, returned
.size());
2378 EXPECT_EQ(parent_resource
, returned
[0].id
);
2379 returned
[0].lost
= true;
2380 resource_provider_
->ReceiveReturnsFromParent(returned
);
2384 EXPECT_EQ(0u, returned_to_child
.size());
2386 // Transfer resources back from the parent to the child. Set no resources as
2388 ResourceProvider::ResourceIdSet no_resources
;
2389 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2391 // Expect the resource to be lost.
2392 ASSERT_EQ(1u, returned_to_child
.size());
2393 EXPECT_TRUE(returned_to_child
[0].lost
);
2394 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2395 returned_to_child
.clear();
2398 // Delete the resource in the child. Expect the resource to be lost.
2399 child_resource_provider_
->DeleteResource(resource
);
2400 EXPECT_TRUE(lost_resource
);
2403 TEST_P(ResourceProviderTest
, Shutdown
) {
2404 uint32 release_sync_point
= 0;
2405 bool lost_resource
= false;
2406 bool release_called
= false;
2407 uint32 sync_point
= 0;
2409 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2411 EXPECT_EQ(0u, release_sync_point
);
2412 EXPECT_FALSE(lost_resource
);
2414 child_resource_provider_
= nullptr;
2416 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2417 EXPECT_LE(sync_point
, release_sync_point
);
2419 EXPECT_TRUE(release_called
);
2420 EXPECT_FALSE(lost_resource
);
2423 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2424 uint32 release_sync_point
= 0;
2425 bool lost_resource
= false;
2426 bool release_called
= false;
2427 uint32 sync_point
= 0;
2428 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2429 &release_called
, &sync_point
);
2431 // Transfer the resource, so we can't release it properly on shutdown.
2432 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2433 resource_ids_to_transfer
.push_back(resource
);
2434 TransferableResourceArray list
;
2435 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2438 EXPECT_EQ(0u, release_sync_point
);
2439 EXPECT_FALSE(lost_resource
);
2441 child_resource_provider_
= nullptr;
2443 // Since the resource is in the parent, the child considers it lost.
2444 EXPECT_EQ(0u, release_sync_point
);
2445 EXPECT_TRUE(lost_resource
);
2448 TEST_P(ResourceProviderTest
, LostContext
) {
2449 // TextureMailbox callbacks only exist for GL textures for now.
2450 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2452 unsigned texture
= context()->createTexture();
2453 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2454 gpu::Mailbox mailbox
;
2455 context()->genMailboxCHROMIUM(mailbox
.name
);
2456 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2457 uint32 sync_point
= context()->insertSyncPoint();
2459 EXPECT_LT(0u, sync_point
);
2461 uint32 release_sync_point
= 0;
2462 bool lost_resource
= false;
2463 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2464 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2465 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2466 &release_sync_point
,
2468 &main_thread_task_runner
));
2469 resource_provider_
->CreateResourceFromTextureMailbox(
2470 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2472 EXPECT_EQ(0u, release_sync_point
);
2473 EXPECT_FALSE(lost_resource
);
2474 EXPECT_EQ(NULL
, main_thread_task_runner
);
2476 resource_provider_
->DidLoseOutputSurface();
2477 resource_provider_
= nullptr;
2479 EXPECT_LE(sync_point
, release_sync_point
);
2480 EXPECT_TRUE(lost_resource
);
2481 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2484 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2485 // Sampling is only supported for GL textures.
2486 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2489 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2490 new TextureStateTrackingContext
);
2491 TextureStateTrackingContext
* context
= context_owned
.get();
2493 FakeOutputSurfaceClient output_surface_client
;
2494 scoped_ptr
<OutputSurface
> output_surface(
2495 FakeOutputSurface::Create3d(context_owned
.Pass()));
2496 CHECK(output_surface
->BindToClient(&output_surface_client
));
2498 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2499 output_surface
.get(), shared_bitmap_manager_
.get(),
2500 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2502 gfx::Size
size(1, 1);
2503 ResourceFormat format
= RGBA_8888
;
2506 ResourceId id
= resource_provider
->CreateResource(
2507 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2509 // Check that the texture gets created with the right sampler settings.
2510 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2511 .Times(2); // Once to create and once to allocate.
2512 EXPECT_CALL(*context
,
2513 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2514 EXPECT_CALL(*context
,
2515 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2518 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2521 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2522 EXPECT_CALL(*context
,
2523 texParameteri(GL_TEXTURE_2D
,
2524 GL_TEXTURE_POOL_CHROMIUM
,
2525 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2527 resource_provider
->AllocateForTesting(id
);
2528 Mock::VerifyAndClearExpectations(context
);
2530 // Creating a sampler with the default filter should not change any texture
2533 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2534 ResourceProvider::ScopedSamplerGL
sampler(
2535 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2536 Mock::VerifyAndClearExpectations(context
);
2539 // Using a different filter should be reflected in the texture parameters.
2541 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2544 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2547 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2548 ResourceProvider::ScopedSamplerGL
sampler(
2549 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2550 Mock::VerifyAndClearExpectations(context
);
2553 // Test resetting to the default filter.
2555 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2556 EXPECT_CALL(*context
,
2557 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2558 EXPECT_CALL(*context
,
2559 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2560 ResourceProvider::ScopedSamplerGL
sampler(
2561 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2562 Mock::VerifyAndClearExpectations(context
);
2566 TEST_P(ResourceProviderTest
, ManagedResource
) {
2567 // Sampling is only supported for GL textures.
2568 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2571 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2572 new TextureStateTrackingContext
);
2573 TextureStateTrackingContext
* context
= context_owned
.get();
2575 FakeOutputSurfaceClient output_surface_client
;
2576 scoped_ptr
<OutputSurface
> output_surface(
2577 FakeOutputSurface::Create3d(context_owned
.Pass()));
2578 CHECK(output_surface
->BindToClient(&output_surface_client
));
2580 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2581 output_surface
.get(), shared_bitmap_manager_
.get(),
2582 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2584 gfx::Size
size(1, 1);
2585 ResourceFormat format
= RGBA_8888
;
2588 // Check that the texture gets created with the right sampler settings.
2589 ResourceId id
= resource_provider
->CreateManagedResource(
2590 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2591 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2592 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2593 EXPECT_CALL(*context
,
2594 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2595 EXPECT_CALL(*context
,
2596 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2599 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2602 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2603 EXPECT_CALL(*context
,
2604 texParameteri(GL_TEXTURE_2D
,
2605 GL_TEXTURE_POOL_CHROMIUM
,
2606 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2607 resource_provider
->CreateForTesting(id
);
2610 Mock::VerifyAndClearExpectations(context
);
2613 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2614 // Sampling is only supported for GL textures.
2615 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2618 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2619 new TextureStateTrackingContext
);
2620 TextureStateTrackingContext
* context
= context_owned
.get();
2622 FakeOutputSurfaceClient output_surface_client
;
2623 scoped_ptr
<OutputSurface
> output_surface(
2624 FakeOutputSurface::Create3d(context_owned
.Pass()));
2625 CHECK(output_surface
->BindToClient(&output_surface_client
));
2627 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2628 output_surface
.get(), shared_bitmap_manager_
.get(),
2629 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2631 gfx::Size
size(1, 1);
2632 ResourceFormat format
= RGBA_8888
;
2633 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2635 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2636 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2637 // Check that the texture gets created with the right sampler settings.
2638 ResourceId id
= resource_provider
->CreateGLTexture(
2639 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2640 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2641 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2642 EXPECT_CALL(*context
,
2643 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2644 EXPECT_CALL(*context
,
2645 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2646 EXPECT_CALL(*context
,
2647 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2648 EXPECT_CALL(*context
,
2649 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2650 EXPECT_CALL(*context
,
2651 texParameteri(GL_TEXTURE_2D
,
2652 GL_TEXTURE_POOL_CHROMIUM
,
2653 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2654 resource_provider
->CreateForTesting(id
);
2657 Mock::VerifyAndClearExpectations(context
);
2661 TEST_P(ResourceProviderTest
, TextureHint
) {
2662 // Sampling is only supported for GL textures.
2663 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2666 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2667 new TextureStateTrackingContext
);
2668 TextureStateTrackingContext
* context
= context_owned
.get();
2669 context
->set_support_texture_storage(true);
2670 context
->set_support_texture_usage(true);
2672 FakeOutputSurfaceClient output_surface_client
;
2673 scoped_ptr
<OutputSurface
> output_surface(
2674 FakeOutputSurface::Create3d(context_owned
.Pass()));
2675 CHECK(output_surface
->BindToClient(&output_surface_client
));
2677 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2678 output_surface
.get(), shared_bitmap_manager_
.get(),
2679 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2681 gfx::Size
size(1, 1);
2682 ResourceFormat format
= RGBA_8888
;
2683 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2685 const ResourceProvider::TextureHint hints
[4] = {
2686 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2687 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2688 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2689 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2691 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2692 // Check that the texture gets created with the right sampler settings.
2693 ResourceId id
= resource_provider
->CreateGLTexture(
2694 size
, GL_TEXTURE_2D
, texture_pool
, GL_CLAMP_TO_EDGE
,
2695 hints
[texture_id
- 1], format
);
2696 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2697 EXPECT_CALL(*context
,
2698 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2699 EXPECT_CALL(*context
,
2700 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2703 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2706 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2707 EXPECT_CALL(*context
,
2708 texParameteri(GL_TEXTURE_2D
,
2709 GL_TEXTURE_POOL_CHROMIUM
,
2710 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2711 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2712 bool is_framebuffer_hint
=
2713 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2714 EXPECT_CALL(*context
,
2715 texParameteri(GL_TEXTURE_2D
,
2716 GL_TEXTURE_USAGE_ANGLE
,
2717 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2718 .Times(is_framebuffer_hint
? 1 : 0);
2719 resource_provider
->CreateForTesting(id
);
2722 Mock::VerifyAndClearExpectations(context
);
2726 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2727 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2730 gfx::Size
size(64, 64);
2731 const uint32_t kBadBeef
= 0xbadbeef;
2732 scoped_ptr
<SharedBitmap
> shared_bitmap(
2733 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2735 FakeOutputSurfaceClient output_surface_client
;
2736 scoped_ptr
<OutputSurface
> output_surface(
2737 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2738 new SoftwareOutputDevice
)));
2739 CHECK(output_surface
->BindToClient(&output_surface_client
));
2741 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2742 output_surface
.get(), shared_bitmap_manager_
.get(),
2743 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
2746 uint32 release_sync_point
= 0;
2747 bool lost_resource
= false;
2748 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2749 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2750 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2751 &release_sync_point
,
2753 &main_thread_task_runner
));
2754 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2756 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2757 mailbox
, callback
.Pass());
2761 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2762 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2763 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2764 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2765 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2768 resource_provider
->DeleteResource(id
);
2769 EXPECT_EQ(0u, release_sync_point
);
2770 EXPECT_FALSE(lost_resource
);
2771 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2774 class ResourceProviderTestTextureMailboxGLFilters
2775 : public ResourceProviderTest
{
2777 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2778 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2779 BlockingTaskRunner
* main_thread_task_runner
,
2780 bool mailbox_nearest_neighbor
,
2781 GLenum sampler_filter
) {
2782 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2783 new TextureStateTrackingContext
);
2784 TextureStateTrackingContext
* context
= context_owned
.get();
2786 FakeOutputSurfaceClient output_surface_client
;
2787 scoped_ptr
<OutputSurface
> output_surface(
2788 FakeOutputSurface::Create3d(context_owned
.Pass()));
2789 CHECK(output_surface
->BindToClient(&output_surface_client
));
2791 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2792 output_surface
.get(), shared_bitmap_manager
, gpu_memory_buffer_manager
,
2793 main_thread_task_runner
, 0, false, 1, false));
2795 unsigned texture_id
= 1;
2796 uint32 sync_point
= 30;
2797 unsigned target
= GL_TEXTURE_2D
;
2799 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2800 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2801 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2802 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2803 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2805 gpu::Mailbox gpu_mailbox
;
2806 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2807 uint32 release_sync_point
= 0;
2808 bool lost_resource
= false;
2809 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2810 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2811 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2812 &release_sync_point
,
2814 &mailbox_task_runner
));
2816 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2817 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2819 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2820 mailbox
, callback
.Pass());
2823 Mock::VerifyAndClearExpectations(context
);
2826 // Mailbox sync point WaitSyncPoint before using the texture.
2827 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2828 resource_provider
->WaitSyncPointIfNeeded(id
);
2829 Mock::VerifyAndClearExpectations(context
);
2831 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2832 .WillOnce(Return(texture_id
));
2833 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2835 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2836 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2838 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2839 // match |sampler_filter|.
2840 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2841 EXPECT_CALL(*context
, texParameteri(
2842 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2843 EXPECT_CALL(*context
, texParameteri(
2844 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2847 ResourceProvider::ScopedSamplerGL
lock(
2848 resource_provider
.get(), id
, sampler_filter
);
2849 Mock::VerifyAndClearExpectations(context
);
2851 // When done with it, a sync point should be inserted, but no produce is
2853 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2854 EXPECT_CALL(*context
, insertSyncPoint());
2855 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2857 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2858 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2861 resource_provider
->DeleteResource(id
);
2862 EXPECT_EQ(0u, release_sync_point
);
2863 EXPECT_FALSE(lost_resource
);
2864 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2868 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2869 // Mailboxing is only supported for GL textures.
2870 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2873 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2874 shared_bitmap_manager_
.get(),
2875 gpu_memory_buffer_manager_
.get(),
2876 main_thread_task_runner_
.get(),
2881 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2882 // Mailboxing is only supported for GL textures.
2883 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2886 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2887 shared_bitmap_manager_
.get(),
2888 gpu_memory_buffer_manager_
.get(),
2889 main_thread_task_runner_
.get(),
2894 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2895 // Mailboxing is only supported for GL textures.
2896 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2899 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2900 shared_bitmap_manager_
.get(),
2901 gpu_memory_buffer_manager_
.get(),
2902 main_thread_task_runner_
.get(),
2907 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2908 // Mailboxing is only supported for GL textures.
2909 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2912 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2913 shared_bitmap_manager_
.get(),
2914 gpu_memory_buffer_manager_
.get(),
2915 main_thread_task_runner_
.get(),
2920 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2921 // Mailboxing is only supported for GL textures.
2922 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2925 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2926 new TextureStateTrackingContext
);
2927 TextureStateTrackingContext
* context
= context_owned
.get();
2929 FakeOutputSurfaceClient output_surface_client
;
2930 scoped_ptr
<OutputSurface
> output_surface(
2931 FakeOutputSurface::Create3d(context_owned
.Pass()));
2932 CHECK(output_surface
->BindToClient(&output_surface_client
));
2934 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2935 output_surface
.get(), shared_bitmap_manager_
.get(),
2936 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2938 uint32 sync_point
= 30;
2939 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2941 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2942 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2943 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2944 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2945 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2947 gpu::Mailbox gpu_mailbox
;
2948 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2949 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2950 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2952 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2954 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2955 mailbox
, callback
.Pass());
2958 Mock::VerifyAndClearExpectations(context
);
2961 // Mailbox sync point WaitSyncPoint before using the texture.
2962 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2963 resource_provider
->WaitSyncPointIfNeeded(id
);
2964 Mock::VerifyAndClearExpectations(context
);
2966 unsigned texture_id
= 1;
2968 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2969 .WillOnce(Return(texture_id
));
2971 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2972 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2974 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2975 Mock::VerifyAndClearExpectations(context
);
2977 // When done with it, a sync point should be inserted, but no produce is
2979 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2980 EXPECT_CALL(*context
, insertSyncPoint());
2981 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2983 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2984 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2988 TEST_P(ResourceProviderTest
,
2989 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2990 // Mailboxing is only supported for GL textures.
2991 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2994 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2995 new TextureStateTrackingContext
);
2996 TextureStateTrackingContext
* context
= context_owned
.get();
2998 FakeOutputSurfaceClient output_surface_client
;
2999 scoped_ptr
<OutputSurface
> output_surface(
3000 FakeOutputSurface::Create3d(context_owned
.Pass()));
3001 CHECK(output_surface
->BindToClient(&output_surface_client
));
3003 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3004 output_surface
.get(), shared_bitmap_manager_
.get(),
3005 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3007 uint32 sync_point
= 30;
3008 unsigned target
= GL_TEXTURE_2D
;
3010 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3011 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3012 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3013 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3014 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3016 gpu::Mailbox gpu_mailbox
;
3017 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3018 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3019 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3021 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3023 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
3024 mailbox
, callback
.Pass());
3027 Mock::VerifyAndClearExpectations(context
);
3030 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3031 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
3032 resource_provider
->WaitSyncPointIfNeeded(id
);
3033 Mock::VerifyAndClearExpectations(context
);
3035 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3036 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3037 resource_provider
->WaitSyncPointIfNeeded(id
);
3038 Mock::VerifyAndClearExpectations(context
);
3042 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
3043 // Mailboxing is only supported for GL textures.
3044 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3047 scoped_ptr
<TextureStateTrackingContext
> context_owned(
3048 new TextureStateTrackingContext
);
3049 TextureStateTrackingContext
* context
= context_owned
.get();
3051 FakeOutputSurfaceClient output_surface_client
;
3052 scoped_ptr
<OutputSurface
> output_surface(
3053 FakeOutputSurface::Create3d(context_owned
.Pass()));
3054 CHECK(output_surface
->BindToClient(&output_surface_client
));
3056 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3057 output_surface
.get(), shared_bitmap_manager_
.get(),
3058 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3060 uint32 sync_point
= 0;
3061 unsigned target
= GL_TEXTURE_2D
;
3063 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
3064 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3065 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
3066 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
3067 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3069 gpu::Mailbox gpu_mailbox
;
3070 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3071 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3072 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3074 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3076 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
3077 mailbox
, callback
.Pass());
3080 Mock::VerifyAndClearExpectations(context
);
3083 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3084 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3085 resource_provider
->WaitSyncPointIfNeeded(id
);
3086 Mock::VerifyAndClearExpectations(context
);
3090 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
3092 MOCK_METHOD0(NextTextureId
, GLuint());
3093 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
3094 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
3095 MOCK_METHOD5(texStorage2DEXT
,
3098 GLuint internalformat
,
3101 MOCK_METHOD9(texImage2D
,
3104 GLenum internalformat
,
3110 const void* pixels
));
3111 MOCK_METHOD9(texSubImage2D
,
3120 const void* pixels
));
3121 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
3124 GLenum internalformat
,
3130 const void* pixels
));
3131 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3140 const void* pixels
));
3141 MOCK_METHOD8(compressedTexImage2D
,
3144 GLenum internalformat
,
3150 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3151 MOCK_METHOD4(createImageCHROMIUM
,
3152 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3153 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3154 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3155 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3157 // We're mocking bindTexture, so we override
3158 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3159 // currently bound texture.
3160 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3163 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3164 // Only for GL textures.
3165 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3167 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3168 new StrictMock
<AllocationTrackingContext3D
>);
3169 AllocationTrackingContext3D
* context
= context_owned
.get();
3171 FakeOutputSurfaceClient output_surface_client
;
3172 scoped_ptr
<OutputSurface
> output_surface(
3173 FakeOutputSurface::Create3d(context_owned
.Pass()));
3174 CHECK(output_surface
->BindToClient(&output_surface_client
));
3176 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3177 output_surface
.get(), shared_bitmap_manager_
.get(),
3178 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3180 gfx::Size
size(2, 2);
3181 gfx::Vector2d
offset(0, 0);
3182 ResourceFormat format
= RGBA_8888
;
3184 uint8_t pixels
[16] = { 0 };
3185 int texture_id
= 123;
3187 // Lazy allocation. Don't allocate when creating the resource.
3188 id
= resource_provider
->CreateResource(
3189 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3191 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3192 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3193 resource_provider
->CreateForTesting(id
);
3195 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3196 resource_provider
->DeleteResource(id
);
3198 Mock::VerifyAndClearExpectations(context
);
3200 // Do allocate when we set the pixels.
3201 id
= resource_provider
->CreateResource(
3202 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3204 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3205 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3206 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3207 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3208 resource_provider
->CopyToResource(id
, pixels
, size
);
3210 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3211 resource_provider
->DeleteResource(id
);
3213 Mock::VerifyAndClearExpectations(context
);
3215 // Same for async version.
3216 id
= resource_provider
->CreateResource(
3217 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3218 resource_provider
->AcquirePixelBuffer(id
);
3220 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3221 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3222 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3224 resource_provider
->BeginSetPixels(id
);
3225 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3227 resource_provider
->ReleasePixelBuffer(id
);
3229 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3230 resource_provider
->DeleteResource(id
);
3232 Mock::VerifyAndClearExpectations(context
);
3235 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3236 // Only for GL textures.
3237 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3239 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3240 new StrictMock
<AllocationTrackingContext3D
>);
3241 AllocationTrackingContext3D
* context
= context_owned
.get();
3242 context
->set_support_texture_storage(true);
3243 context
->set_support_texture_usage(true);
3245 FakeOutputSurfaceClient output_surface_client
;
3246 scoped_ptr
<OutputSurface
> output_surface(
3247 FakeOutputSurface::Create3d(context_owned
.Pass()));
3248 CHECK(output_surface
->BindToClient(&output_surface_client
));
3250 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3251 output_surface
.get(), shared_bitmap_manager_
.get(),
3252 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3254 gfx::Size
size(2, 2);
3256 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3257 const ResourceProvider::TextureHint hints
[4] = {
3258 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3259 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3260 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3261 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3263 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3264 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3265 // Lazy allocation. Don't allocate when creating the resource.
3266 ResourceId id
= resource_provider
->CreateResource(
3267 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3269 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3270 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3271 bool is_immutable_hint
=
3272 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3273 bool support_immutable_texture
=
3274 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3275 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3276 .Times(support_immutable_texture
? 1 : 0);
3277 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3278 .Times(support_immutable_texture
? 0 : 1);
3279 resource_provider
->AllocateForTesting(id
);
3281 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3282 resource_provider
->DeleteResource(id
);
3284 Mock::VerifyAndClearExpectations(context
);
3289 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3290 // Only for GL textures.
3291 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3293 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3294 new StrictMock
<AllocationTrackingContext3D
>);
3295 AllocationTrackingContext3D
* context
= context_owned
.get();
3296 context
->set_support_texture_format_bgra8888(true);
3297 context
->set_support_texture_storage(true);
3298 context
->set_support_texture_usage(true);
3300 FakeOutputSurfaceClient output_surface_client
;
3301 scoped_ptr
<OutputSurface
> output_surface(
3302 FakeOutputSurface::Create3d(context_owned
.Pass()));
3303 CHECK(output_surface
->BindToClient(&output_surface_client
));
3305 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3306 output_surface
.get(), shared_bitmap_manager_
.get(),
3307 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3309 gfx::Size
size(2, 2);
3310 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3312 const ResourceProvider::TextureHint hints
[4] = {
3313 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3314 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3315 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3316 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3318 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3319 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3320 // Lazy allocation. Don't allocate when creating the resource.
3321 ResourceId id
= resource_provider
->CreateResource(
3322 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3324 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3325 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3326 bool is_immutable_hint
=
3327 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3328 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3329 .Times(is_immutable_hint
? 1 : 0);
3330 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3331 .Times(is_immutable_hint
? 0 : 1);
3332 resource_provider
->AllocateForTesting(id
);
3334 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3335 resource_provider
->DeleteResource(id
);
3337 Mock::VerifyAndClearExpectations(context
);
3342 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3343 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3345 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3346 new StrictMock
<AllocationTrackingContext3D
>);
3347 AllocationTrackingContext3D
* context
= context_owned
.get();
3349 FakeOutputSurfaceClient output_surface_client
;
3350 scoped_ptr
<OutputSurface
> output_surface(
3351 FakeOutputSurface::Create3d(context_owned
.Pass()));
3352 CHECK(output_surface
->BindToClient(&output_surface_client
));
3354 gfx::Size
size(2, 2);
3355 ResourceFormat format
= RGBA_8888
;
3357 int texture_id
= 123;
3359 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3360 output_surface
.get(), shared_bitmap_manager_
.get(),
3361 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3363 id
= resource_provider
->CreateResource(
3364 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3365 resource_provider
->AcquirePixelBuffer(id
);
3367 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3368 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3369 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3371 resource_provider
->BeginSetPixels(id
);
3373 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3375 resource_provider
->ReleasePixelBuffer(id
);
3377 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3378 resource_provider
->DeleteResource(id
);
3380 Mock::VerifyAndClearExpectations(context
);
3383 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3384 // Only for GL textures.
3385 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3387 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3388 new StrictMock
<AllocationTrackingContext3D
>);
3389 AllocationTrackingContext3D
* context
= context_owned
.get();
3391 FakeOutputSurfaceClient output_surface_client
;
3392 scoped_ptr
<OutputSurface
> output_surface(
3393 FakeOutputSurface::Create3d(context_owned
.Pass()));
3394 CHECK(output_surface
->BindToClient(&output_surface_client
));
3396 gfx::Size
size(2, 2);
3397 ResourceFormat format
= RGBA_8888
;
3399 int texture_id
= 123;
3401 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3402 output_surface
.get(), shared_bitmap_manager_
.get(),
3403 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3405 id
= resource_provider
->CreateResource(
3406 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3407 resource_provider
->AcquirePixelBuffer(id
);
3409 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3410 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3411 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3413 resource_provider
->BeginSetPixels(id
);
3415 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3416 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3417 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3418 resource_provider
->ForceSetPixelsToComplete(id
);
3420 resource_provider
->ReleasePixelBuffer(id
);
3422 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3423 resource_provider
->DeleteResource(id
);
3425 Mock::VerifyAndClearExpectations(context
);
3428 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3429 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3430 new NiceMock
<AllocationTrackingContext3D
>);
3431 AllocationTrackingContext3D
* context
= context_owned
.get();
3433 FakeOutputSurfaceClient output_surface_client
;
3434 scoped_ptr
<OutputSurface
> output_surface(
3435 FakeOutputSurface::Create3d(context_owned
.Pass()));
3436 CHECK(output_surface
->BindToClient(&output_surface_client
));
3438 gfx::Size
size(2, 2);
3439 ResourceFormat format
= RGBA_8888
;
3441 int texture_id
= 123;
3443 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3444 output_surface
.get(), shared_bitmap_manager_
.get(),
3445 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3447 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3449 id
= resource_provider
->CreateResource(
3450 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3451 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3452 GL_INNOCENT_CONTEXT_RESET_ARB
);
3454 resource_provider
->AcquirePixelBuffer(id
);
3456 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3457 EXPECT_FALSE(buffer
);
3458 resource_provider
->UnmapPixelBuffer(id
);
3459 Mock::VerifyAndClearExpectations(context
);
3462 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3463 // Only for GL textures.
3464 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3466 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3467 new StrictMock
<AllocationTrackingContext3D
>);
3468 AllocationTrackingContext3D
* context
= context_owned
.get();
3470 FakeOutputSurfaceClient output_surface_client
;
3471 scoped_ptr
<OutputSurface
> output_surface(
3472 FakeOutputSurface::Create3d(context_owned
.Pass()));
3473 CHECK(output_surface
->BindToClient(&output_surface_client
));
3475 const int kWidth
= 2;
3476 const int kHeight
= 2;
3477 gfx::Size
size(kWidth
, kHeight
);
3478 ResourceFormat format
= RGBA_8888
;
3480 const unsigned kTextureId
= 123u;
3481 const unsigned kImageId
= 234u;
3483 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3484 output_surface
.get(), shared_bitmap_manager_
.get(),
3485 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3487 id
= resource_provider
->CreateResource(
3488 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3490 EXPECT_CALL(*context
, NextTextureId())
3491 .WillOnce(Return(kTextureId
))
3492 .RetiresOnSaturation();
3493 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
))
3495 .RetiresOnSaturation();
3496 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3497 .WillOnce(Return(kImageId
))
3498 .RetiresOnSaturation();
3500 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3501 resource_provider
.get(), id
);
3502 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3505 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
))
3507 .RetiresOnSaturation();
3508 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3510 .RetiresOnSaturation();
3512 ResourceProvider::ScopedSamplerGL
lock_gl(
3513 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3514 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3518 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3519 resource_provider
.get(), id
);
3520 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3523 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3524 .RetiresOnSaturation();
3525 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3527 .RetiresOnSaturation();
3528 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3530 .RetiresOnSaturation();
3531 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3533 .RetiresOnSaturation();
3535 ResourceProvider::ScopedSamplerGL
lock_gl(
3536 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3537 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3540 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3542 .RetiresOnSaturation();
3545 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3546 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3548 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3549 new StrictMock
<AllocationTrackingContext3D
>);
3550 AllocationTrackingContext3D
* context
= context_owned
.get();
3551 context_owned
->set_support_sync_query(true);
3553 FakeOutputSurfaceClient output_surface_client
;
3554 scoped_ptr
<OutputSurface
> output_surface(
3555 FakeOutputSurface::Create3d(context_owned
.Pass()));
3556 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3558 const int kWidth
= 2;
3559 const int kHeight
= 2;
3560 gfx::Size
size(kWidth
, kHeight
);
3561 ResourceFormat format
= RGBA_8888
;
3562 ResourceId source_id
= 0;
3563 ResourceId dest_id
= 0;
3564 const unsigned kSourceTextureId
= 123u;
3565 const unsigned kDestTextureId
= 321u;
3566 const unsigned kImageId
= 234u;
3568 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3569 output_surface
.get(), shared_bitmap_manager_
.get(),
3570 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3572 source_id
= resource_provider
->CreateResource(
3573 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3575 EXPECT_CALL(*context
, NextTextureId())
3576 .WillOnce(Return(kSourceTextureId
))
3577 .RetiresOnSaturation();
3578 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3580 .RetiresOnSaturation();
3581 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3582 .WillOnce(Return(kImageId
))
3583 .RetiresOnSaturation();
3585 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3586 resource_provider
.get(), source_id
);
3587 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3589 Mock::VerifyAndClearExpectations(context
);
3591 dest_id
= resource_provider
->CreateResource(
3592 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3594 EXPECT_CALL(*context
, NextTextureId())
3595 .WillOnce(Return(kDestTextureId
))
3596 .RetiresOnSaturation();
3597 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3599 .RetiresOnSaturation();
3600 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3601 GL_UNSIGNED_BYTE
, nullptr))
3603 .RetiresOnSaturation();
3604 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3606 .RetiresOnSaturation();
3607 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3609 .RetiresOnSaturation();
3610 resource_provider
->CopyResource(source_id
, dest_id
, gfx::Rect(size
));
3611 Mock::VerifyAndClearExpectations(context
);
3613 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3615 .RetiresOnSaturation();
3616 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3618 .RetiresOnSaturation();
3619 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3621 .RetiresOnSaturation();
3622 resource_provider
->DeleteResource(source_id
);
3623 resource_provider
->DeleteResource(dest_id
);
3626 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3627 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3630 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3631 new AllocationTrackingContext3D
);
3632 AllocationTrackingContext3D
* context
= context_owned
.get();
3633 context_owned
->set_support_compressed_texture_etc1(true);
3635 FakeOutputSurfaceClient output_surface_client
;
3636 scoped_ptr
<OutputSurface
> output_surface(
3637 FakeOutputSurface::Create3d(context_owned
.Pass()));
3638 CHECK(output_surface
->BindToClient(&output_surface_client
));
3640 gfx::Size
size(4, 4);
3641 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3642 output_surface
.get(), shared_bitmap_manager_
.get(),
3643 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3644 int texture_id
= 123;
3646 ResourceId id
= resource_provider
->CreateResource(
3647 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3649 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3650 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3651 resource_provider
->AllocateForTesting(id
);
3653 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3654 resource_provider
->DeleteResource(id
);
3657 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3658 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3661 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3662 new AllocationTrackingContext3D
);
3663 AllocationTrackingContext3D
* context
= context_owned
.get();
3664 context_owned
->set_support_compressed_texture_etc1(true);
3666 FakeOutputSurfaceClient output_surface_client
;
3667 scoped_ptr
<OutputSurface
> output_surface(
3668 FakeOutputSurface::Create3d(context_owned
.Pass()));
3669 CHECK(output_surface
->BindToClient(&output_surface_client
));
3671 gfx::Size
size(4, 4);
3672 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3673 output_surface
.get(), shared_bitmap_manager_
.get(),
3674 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3675 int texture_id
= 123;
3678 ResourceId id
= resource_provider
->CreateResource(
3679 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3681 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3682 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3683 EXPECT_CALL(*context
,
3684 compressedTexImage2D(
3685 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3686 resource_provider
->CopyToResource(id
, pixels
, size
);
3688 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3689 resource_provider
->DeleteResource(id
);
3692 INSTANTIATE_TEST_CASE_P(
3693 ResourceProviderTests
,
3694 ResourceProviderTest
,
3695 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3696 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3698 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3700 GLuint
NextTextureId() override
{
3701 base::AutoLock
lock(namespace_
->lock
);
3702 return namespace_
->next_texture_id
++;
3704 void RetireTextureId(GLuint
) override
{}
3705 GLuint
PeekTextureId() {
3706 base::AutoLock
lock(namespace_
->lock
);
3707 return namespace_
->next_texture_id
;
3711 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3712 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3713 new TextureIdAllocationTrackingContext
);
3714 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3716 FakeOutputSurfaceClient output_surface_client
;
3717 scoped_ptr
<OutputSurface
> output_surface(
3718 FakeOutputSurface::Create3d(context_owned
.Pass()));
3719 CHECK(output_surface
->BindToClient(&output_surface_client
));
3720 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3721 new TestSharedBitmapManager());
3723 gfx::Size
size(1, 1);
3724 ResourceFormat format
= RGBA_8888
;
3727 size_t kTextureAllocationChunkSize
= 1;
3728 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3729 output_surface
.get(), shared_bitmap_manager
.get(), NULL
, NULL
, 0, false,
3730 kTextureAllocationChunkSize
, false));
3732 ResourceId id
= resource_provider
->CreateResource(
3733 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3735 resource_provider
->AllocateForTesting(id
);
3736 Mock::VerifyAndClearExpectations(context
);
3738 DCHECK_EQ(2u, context
->PeekTextureId());
3739 resource_provider
->DeleteResource(id
);
3743 size_t kTextureAllocationChunkSize
= 8;
3744 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3745 output_surface
.get(), shared_bitmap_manager
.get(), NULL
, NULL
, 0, false,
3746 kTextureAllocationChunkSize
, false));
3748 ResourceId id
= resource_provider
->CreateResource(
3749 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3751 resource_provider
->AllocateForTesting(id
);
3752 Mock::VerifyAndClearExpectations(context
);
3754 DCHECK_EQ(10u, context
->PeekTextureId());
3755 resource_provider
->DeleteResource(id
);