1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
56 BlockingTaskRunner
* main_thread_task_runner
) {
57 *release_sync_point
= sync_point
;
58 *release_lost_resource
= lost_resource
;
59 *release_main_thread_task_runner
= main_thread_task_runner
;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr
<SharedBitmap
> bitmap
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr
<SharedBitmap
> shared_bitmap
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<SharedBitmap
> CreateAndFillSharedBitmap(
83 SharedBitmapManager
* manager
,
84 const gfx::Size
& size
,
86 scoped_ptr
<SharedBitmap
> shared_bitmap
= manager
->AllocateSharedBitmap(size
);
88 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_bitmap
->pixels());
90 std::fill_n(pixels
, size
.GetArea(), value
);
91 return shared_bitmap
.Pass();
94 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
96 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
97 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
98 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
99 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM
,
101 void(GLuint texture
, GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM
,
103 unsigned(GLenum target
, const GLbyte
* mailbox
));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint
NextTextureId() override
{
108 base::AutoLock
lock(namespace_
->lock
);
109 return namespace_
->next_texture_id
++;
111 void RetireTextureId(GLuint
) override
{}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData
{
118 static scoped_ptr
<ContextSharedData
> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32
InsertSyncPoint() { return next_sync_point_
++; }
124 void GenMailbox(GLbyte
* mailbox
) {
125 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
126 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
130 void ProduceTexture(const GLbyte
* mailbox_name
,
132 scoped_refptr
<TestTexture
> texture
) {
133 unsigned mailbox
= 0;
134 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
135 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
136 textures_
[mailbox
] = texture
;
137 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
138 sync_point_for_mailbox_
[mailbox
] = sync_point
;
141 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
143 unsigned mailbox
= 0;
144 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
145 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
150 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
152 return scoped_refptr
<TestTexture
>();
154 return textures_
[mailbox
];
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_
;
161 unsigned next_mailbox_
;
162 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
163 TextureMap textures_
;
164 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
167 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
169 static scoped_ptr
<ResourceProviderContext
> Create(
170 ContextSharedData
* shared_data
) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
174 GLuint
insertSyncPoint() override
{
175 uint32 sync_point
= shared_data_
->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it
=
179 pending_produce_textures_
.begin();
180 it
!= pending_produce_textures_
.end();
182 shared_data_
->ProduceTexture(
183 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
185 pending_produce_textures_
.clear();
189 void waitSyncPoint(GLuint sync_point
) override
{
190 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
195 void texStorage2DEXT(GLenum target
,
197 GLuint internalformat
,
199 GLint height
) override
{
200 CheckTextureIsBound(target
);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
202 ASSERT_EQ(1, levels
);
203 GLenum format
= GL_RGBA
;
204 switch (internalformat
) {
208 format
= GL_BGRA_EXT
;
213 AllocateTexture(gfx::Size(width
, height
), format
);
216 void texImage2D(GLenum target
,
218 GLenum internalformat
,
224 const void* pixels
) override
{
225 CheckTextureIsBound(target
);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
228 ASSERT_EQ(internalformat
, format
);
229 ASSERT_FALSE(border
);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
231 AllocateTexture(gfx::Size(width
, height
), format
);
233 SetPixels(0, 0, width
, height
, pixels
);
236 void texSubImage2D(GLenum target
,
244 const void* pixels
) override
{
245 CheckTextureIsBound(target
);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
250 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
254 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
257 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
258 return shared_data_
->GenMailbox(mailbox
);
261 void produceTextureDirectCHROMIUM(GLuint texture
,
263 const GLbyte
* mailbox
) override
{
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= UnboundTexture(texture
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 GLuint
createAndConsumeTextureCHROMIUM(GLenum target
,
275 const GLbyte
* mailbox
) override
{
276 GLuint texture_id
= createTexture();
277 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
278 scoped_refptr
<TestTexture
> texture
=
279 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
280 namespace_
->textures
.Replace(texture_id
, texture
);
284 void GetPixels(const gfx::Size
& size
,
285 ResourceFormat format
,
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
289 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
290 ASSERT_EQ(texture
->size
, size
);
291 ASSERT_EQ(texture
->format
, format
);
292 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
296 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
297 : shared_data_(shared_data
),
298 last_waited_sync_point_(0) {}
301 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
302 CheckTextureIsBound(GL_TEXTURE_2D
);
303 ResourceFormat texture_format
= RGBA_8888
;
306 texture_format
= RGBA_8888
;
309 texture_format
= BGRA_8888
;
312 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
313 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
316 void SetPixels(int xoffset
,
320 const void* pixels
) {
321 CheckTextureIsBound(GL_TEXTURE_2D
);
322 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
323 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
324 ASSERT_TRUE(texture
->data
.get());
325 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
326 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
328 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
330 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
331 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
332 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
333 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
334 for (int i
= 0; i
< height
; ++i
) {
335 memcpy(dest
, src
, in_pitch
);
341 struct PendingProduceTexture
{
342 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
343 scoped_refptr
<TestTexture
> texture
;
345 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
346 ContextSharedData
* shared_data_
;
347 GLuint last_waited_sync_point_
;
348 PendingProduceTextureList pending_produce_textures_
;
351 void GetResourcePixels(ResourceProvider
* resource_provider
,
352 ResourceProviderContext
* context
,
353 ResourceProvider::ResourceId id
,
354 const gfx::Size
& size
,
355 ResourceFormat format
,
357 resource_provider
->WaitSyncPointIfNeeded(id
);
358 switch (resource_provider
->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
360 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
361 ASSERT_NE(0U, lock_gl
.texture_id());
362 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
363 context
->GetPixels(size
, format
, pixels
);
366 case ResourceProvider::RESOURCE_TYPE_BITMAP
: {
367 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
370 lock_software
.sk_bitmap()->getPixels(),
371 lock_software
.sk_bitmap()->getSize());
374 case ResourceProvider::RESOURCE_TYPE_INVALID
:
380 class ResourceProviderTest
381 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
383 ResourceProviderTest()
384 : shared_data_(ContextSharedData::Create()),
386 child_context_(NULL
),
387 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
388 switch (GetParam()) {
389 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
390 scoped_ptr
<ResourceProviderContext
> context3d(
391 ResourceProviderContext::Create(shared_data_
.get()));
392 context3d_
= context3d
.get();
394 scoped_refptr
<TestContextProvider
> context_provider
=
395 TestContextProvider::Create(context3d
.Pass());
397 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
399 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
400 ResourceProviderContext::Create(shared_data_
.get());
401 child_context_
= child_context_owned
.get();
402 child_output_surface_
=
403 FakeOutputSurface::Create3d(child_context_owned
.Pass());
406 case ResourceProvider::RESOURCE_TYPE_BITMAP
:
407 output_surface_
= FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice
));
409 child_output_surface_
= FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice
));
412 case ResourceProvider::RESOURCE_TYPE_INVALID
:
416 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
417 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
419 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
420 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
423 ResourceProvider::Create(output_surface_
.get(),
424 shared_bitmap_manager_
.get(),
425 gpu_memory_buffer_manager_
.get(),
426 main_thread_task_runner_
.get(),
430 child_resource_provider_
=
431 ResourceProvider::Create(child_output_surface_
.get(),
432 shared_bitmap_manager_
.get(),
433 gpu_memory_buffer_manager_
.get(),
434 main_thread_task_runner_
.get(),
440 static void CollectResources(ReturnedResourceArray
* array
,
441 const ReturnedResourceArray
& returned
,
442 BlockingTaskRunner
* main_thread_task_runner
) {
443 array
->insert(array
->end(), returned
.begin(), returned
.end());
446 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
447 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
450 static void SetResourceFilter(ResourceProvider
* resource_provider
,
451 ResourceProvider::ResourceId id
,
453 ResourceProvider::ScopedSamplerGL
sampler(
454 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
457 ResourceProviderContext
* context() { return context3d_
; }
459 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
461 bool* release_called
,
462 uint32
* sync_point
) {
463 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
464 unsigned texture
= child_context_
->createTexture();
465 gpu::Mailbox gpu_mailbox
;
466 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
467 child_context_
->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
,
469 *sync_point
= child_context_
->insertSyncPoint();
470 EXPECT_LT(0u, *sync_point
);
472 scoped_ptr
<SharedBitmap
> shared_bitmap
;
473 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
474 SingleReleaseCallbackImpl::Create(base::Bind(
475 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
476 release_called
, release_sync_point
, lost_resource
));
477 return child_resource_provider_
->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
481 gfx::Size
size(64, 64);
482 scoped_ptr
<SharedBitmap
> shared_bitmap(
483 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
485 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
486 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
487 SingleReleaseCallbackImpl::Create(base::Bind(
488 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
489 release_called
, release_sync_point
, lost_resource
));
490 return child_resource_provider_
->CreateResourceFromTextureMailbox(
491 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
496 scoped_ptr
<ContextSharedData
> shared_data_
;
497 ResourceProviderContext
* context3d_
;
498 ResourceProviderContext
* child_context_
;
499 FakeOutputSurfaceClient output_surface_client_
;
500 FakeOutputSurfaceClient child_output_surface_client_
;
501 scoped_ptr
<OutputSurface
> output_surface_
;
502 scoped_ptr
<OutputSurface
> child_output_surface_
;
503 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
504 scoped_ptr
<ResourceProvider
> resource_provider_
;
505 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
506 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
507 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
510 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
511 ResourceProvider
* resource_provider
,
512 ResourceProviderContext
* context
) {
513 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
515 gfx::Size
size(1, 1);
516 ResourceFormat format
= RGBA_8888
;
517 size_t pixel_size
= TextureSizeBytes(size
, format
);
518 ASSERT_EQ(4U, pixel_size
);
520 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
521 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
522 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
523 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
524 EXPECT_EQ(0u, context
->NumTextures());
526 uint8_t data
[4] = { 1, 2, 3, 4 };
527 resource_provider
->CopyToResource(id
, data
, size
);
528 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
529 EXPECT_EQ(1u, context
->NumTextures());
531 uint8_t result
[4] = { 0 };
532 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
533 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
535 resource_provider
->DeleteResource(id
);
536 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
537 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
538 EXPECT_EQ(0u, context
->NumTextures());
541 TEST_P(ResourceProviderTest
, Basic
) {
542 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
545 TEST_P(ResourceProviderTest
, Upload
) {
546 gfx::Size
size(2, 2);
547 ResourceFormat format
= RGBA_8888
;
548 size_t pixel_size
= TextureSizeBytes(size
, format
);
549 ASSERT_EQ(16U, pixel_size
);
551 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
552 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
554 uint8_t image
[16] = { 0 };
555 gfx::Rect
image_rect(size
);
556 resource_provider_
->SetPixels(
557 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
559 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
562 uint8_t result
[16] = { 0 };
564 gfx::Rect
source_rect(0, 0, 1, 1);
565 gfx::Vector2d
dest_offset(0, 0);
566 resource_provider_
->SetPixels(
567 id
, image
, image_rect
, source_rect
, dest_offset
);
569 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
571 resource_provider_
.get(), context(), id
, size
, format
, result
);
572 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
575 gfx::Rect
source_rect(0, 0, 1, 1);
576 gfx::Vector2d
dest_offset(1, 1);
577 resource_provider_
->SetPixels(
578 id
, image
, image_rect
, source_rect
, dest_offset
);
580 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
582 resource_provider_
.get(), context(), id
, size
, format
, result
);
583 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
586 gfx::Rect
source_rect(1, 0, 1, 1);
587 gfx::Vector2d
dest_offset(0, 1);
588 resource_provider_
->SetPixels(
589 id
, image
, image_rect
, source_rect
, dest_offset
);
591 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
593 resource_provider_
.get(), context(), id
, size
, format
, result
);
594 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
597 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
598 gfx::Rect
source_rect(100, 100, 1, 1);
599 gfx::Vector2d
dest_offset(1, 0);
600 resource_provider_
->SetPixels(
601 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
603 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
605 resource_provider_
.get(), context(), id
, size
, format
, result
);
606 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
609 resource_provider_
->DeleteResource(id
);
612 TEST_P(ResourceProviderTest
, SimpleUpload
) {
613 gfx::Size
size(2, 2);
614 ResourceFormat format
= RGBA_8888
;
615 size_t pixel_size
= TextureSizeBytes(size
, format
);
616 ASSERT_EQ(16U, pixel_size
);
618 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
619 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
621 uint8_t image
[16] = {0};
622 resource_provider_
->CopyToResource(id
, image
, size
);
624 uint8_t result
[16] = {0};
625 uint8_t expected
[16] = {0};
626 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
628 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
631 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
633 resource_provider_
->CopyToResource(id
, image
, size
);
635 uint8_t result
[16] = {0};
636 uint8_t expected
[16] = {
637 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
638 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
640 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
644 TEST_P(ResourceProviderTest
, TransferGLResources
) {
645 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
647 gfx::Size
size(1, 1);
648 ResourceFormat format
= RGBA_8888
;
649 size_t pixel_size
= TextureSizeBytes(size
, format
);
650 ASSERT_EQ(4U, pixel_size
);
652 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
653 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
654 uint8_t data1
[4] = { 1, 2, 3, 4 };
655 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
657 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
658 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
659 uint8_t data2
[4] = { 5, 5, 5, 5 };
660 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
662 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
663 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
665 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
666 child_resource_provider_
.get(), id3
);
667 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
670 GLuint external_texture_id
= child_context_
->createExternalTexture();
672 gpu::Mailbox external_mailbox
;
673 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
674 child_context_
->produceTextureDirectCHROMIUM(
675 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
676 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
677 ResourceProvider::ResourceId id4
=
678 child_resource_provider_
->CreateResourceFromTextureMailbox(
680 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
681 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
683 ReturnedResourceArray returned_to_child
;
685 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
687 // Transfer some resources to the parent.
688 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
689 resource_ids_to_transfer
.push_back(id1
);
690 resource_ids_to_transfer
.push_back(id2
);
691 resource_ids_to_transfer
.push_back(id3
);
692 resource_ids_to_transfer
.push_back(id4
);
693 TransferableResourceArray list
;
694 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
696 ASSERT_EQ(4u, list
.size());
697 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
698 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
699 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
700 list
[1].mailbox_holder
.sync_point
);
701 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
702 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
703 list
[2].mailbox_holder
.sync_point
);
704 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
705 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
706 list
[0].mailbox_holder
.texture_target
);
707 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
708 list
[1].mailbox_holder
.texture_target
);
709 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
710 list
[2].mailbox_holder
.texture_target
);
711 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
712 list
[3].mailbox_holder
.texture_target
);
713 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
714 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
715 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
716 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
717 resource_provider_
->ReceiveFromChild(child_id
, list
);
718 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
719 context3d_
->last_waited_sync_point());
721 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
722 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
725 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
726 context3d_
->last_waited_sync_point());
727 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
728 resource_ids_to_transfer
);
731 EXPECT_EQ(4u, resource_provider_
->num_resources());
732 ResourceProvider::ResourceIdMap resource_map
=
733 resource_provider_
->GetChildToParentMap(child_id
);
734 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
735 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
736 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
737 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
738 EXPECT_NE(0u, mapped_id1
);
739 EXPECT_NE(0u, mapped_id2
);
740 EXPECT_NE(0u, mapped_id3
);
741 EXPECT_NE(0u, mapped_id4
);
742 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
743 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
744 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
745 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
747 uint8_t result
[4] = { 0 };
749 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
750 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
753 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
754 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
757 // Check that transfering again the same resource from the child to the
759 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
760 resource_ids_to_transfer
.push_back(id1
);
761 resource_ids_to_transfer
.push_back(id2
);
762 resource_ids_to_transfer
.push_back(id3
);
763 TransferableResourceArray list
;
764 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
766 EXPECT_EQ(3u, list
.size());
767 EXPECT_EQ(id1
, list
[0].id
);
768 EXPECT_EQ(id2
, list
[1].id
);
769 EXPECT_EQ(id3
, list
[2].id
);
770 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
771 list
[0].mailbox_holder
.texture_target
);
772 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
773 list
[1].mailbox_holder
.texture_target
);
774 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
775 list
[2].mailbox_holder
.texture_target
);
776 ReturnedResourceArray returned
;
777 TransferableResource::ReturnResources(list
, &returned
);
778 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
779 // ids were exported twice, we returned them only once, they should still
781 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
782 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
783 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
786 EXPECT_EQ(0u, returned_to_child
.size());
788 // Transfer resources back from the parent to the child. Set no resources as
790 ResourceProvider::ResourceIdArray no_resources
;
791 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
793 ASSERT_EQ(4u, returned_to_child
.size());
794 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
795 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
796 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
797 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
798 EXPECT_FALSE(returned_to_child
[0].lost
);
799 EXPECT_FALSE(returned_to_child
[1].lost
);
800 EXPECT_FALSE(returned_to_child
[2].lost
);
801 EXPECT_FALSE(returned_to_child
[3].lost
);
802 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
803 returned_to_child
.clear();
805 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
806 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
807 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
808 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
811 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
812 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
814 ASSERT_NE(0U, lock
.texture_id());
815 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
816 child_context_
->GetPixels(size
, format
, result
);
817 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
820 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
821 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
823 ASSERT_NE(0U, lock
.texture_id());
824 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
825 child_context_
->GetPixels(size
, format
, result
);
826 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
829 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
830 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
832 ASSERT_NE(0U, lock
.texture_id());
833 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
836 // Transfer resources to the parent again.
837 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
838 resource_ids_to_transfer
.push_back(id1
);
839 resource_ids_to_transfer
.push_back(id2
);
840 resource_ids_to_transfer
.push_back(id3
);
841 resource_ids_to_transfer
.push_back(id4
);
842 TransferableResourceArray list
;
843 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
845 ASSERT_EQ(4u, list
.size());
846 EXPECT_EQ(id1
, list
[0].id
);
847 EXPECT_EQ(id2
, list
[1].id
);
848 EXPECT_EQ(id3
, list
[2].id
);
849 EXPECT_EQ(id4
, list
[3].id
);
850 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
851 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
852 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
853 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
854 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
855 list
[0].mailbox_holder
.texture_target
);
856 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
857 list
[1].mailbox_holder
.texture_target
);
858 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
859 list
[2].mailbox_holder
.texture_target
);
860 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
861 list
[3].mailbox_holder
.texture_target
);
862 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
863 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
864 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
865 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
866 resource_provider_
->ReceiveFromChild(child_id
, list
);
867 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
868 resource_ids_to_transfer
);
871 EXPECT_EQ(0u, returned_to_child
.size());
873 EXPECT_EQ(4u, resource_provider_
->num_resources());
874 resource_provider_
->DestroyChild(child_id
);
875 EXPECT_EQ(0u, resource_provider_
->num_resources());
877 ASSERT_EQ(4u, returned_to_child
.size());
878 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
879 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
880 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
881 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
882 EXPECT_FALSE(returned_to_child
[0].lost
);
883 EXPECT_FALSE(returned_to_child
[1].lost
);
884 EXPECT_FALSE(returned_to_child
[2].lost
);
885 EXPECT_FALSE(returned_to_child
[3].lost
);
888 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
889 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
891 gfx::Size
size(1, 1);
892 ResourceFormat format
= RGBA_8888
;
894 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
895 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
896 uint8_t data1
[4] = {1, 2, 3, 4};
897 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
899 ReturnedResourceArray returned_to_child
;
901 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
903 // Transfer some resources to the parent.
904 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
905 resource_ids_to_transfer
.push_back(id1
);
906 TransferableResourceArray list
;
907 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
909 ASSERT_EQ(1u, list
.size());
910 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
912 resource_provider_
->ReceiveFromChild(child_id
, list
);
914 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
915 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
918 resource_provider_
->DeclareUsedResourcesFromChild(
919 child_id
, ResourceProvider::ResourceIdArray());
920 EXPECT_EQ(0u, returned_to_child
.size());
923 EXPECT_EQ(1u, returned_to_child
.size());
924 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
927 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
928 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
930 child_resource_provider_
->DeleteResource(id1
);
931 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
932 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
935 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
936 resource_provider_
->DestroyChild(child_id
);
939 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
940 // Overlays only supported on the GL path.
941 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
944 uint32 sync_point
= 0;
945 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
946 mailbox
.set_allow_overlay(true);
947 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
948 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
949 ResourceProvider::ResourceId id1
=
950 child_resource_provider_
->CreateResourceFromTextureMailbox(
951 mailbox
, release_callback
.Pass());
953 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
954 mailbox2
.set_allow_overlay(false);
955 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
956 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
957 ResourceProvider::ResourceId id2
=
958 child_resource_provider_
->CreateResourceFromTextureMailbox(
959 mailbox2
, release_callback2
.Pass());
961 ReturnedResourceArray returned_to_child
;
963 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
965 // Transfer some resources to the parent.
966 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
967 resource_ids_to_transfer
.push_back(id1
);
968 resource_ids_to_transfer
.push_back(id2
);
969 TransferableResourceArray list
;
970 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
972 ASSERT_EQ(2u, list
.size());
973 resource_provider_
->ReceiveFromChild(child_id
, list
);
974 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
975 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
977 resource_provider_
->DeclareUsedResourcesFromChild(
978 child_id
, ResourceProvider::ResourceIdArray());
980 EXPECT_EQ(2u, returned_to_child
.size());
981 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
983 child_resource_provider_
->DeleteResource(id1
);
984 child_resource_provider_
->DeleteResource(id2
);
985 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
987 resource_provider_
->DestroyChild(child_id
);
990 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
991 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
994 gfx::Size
size(1, 1);
995 ResourceFormat format
= RGBA_8888
;
996 size_t pixel_size
= TextureSizeBytes(size
, format
);
997 ASSERT_EQ(4U, pixel_size
);
999 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1000 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1001 uint8_t data1
[4] = { 1, 2, 3, 4 };
1002 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1004 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1005 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1006 uint8_t data2
[4] = { 5, 5, 5, 5 };
1007 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1009 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1010 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1011 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1012 ResourceProvider::ResourceId id3
=
1013 child_resource_provider_
->CreateResourceFromTextureMailbox(
1014 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1015 SingleReleaseCallbackImpl::Create(base::Bind(
1016 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1018 ReturnedResourceArray returned_to_child
;
1020 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1022 // Transfer some resources to the parent.
1023 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1024 resource_ids_to_transfer
.push_back(id1
);
1025 resource_ids_to_transfer
.push_back(id2
);
1026 resource_ids_to_transfer
.push_back(id3
);
1027 TransferableResourceArray list
;
1028 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1030 ASSERT_EQ(3u, list
.size());
1031 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1032 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1033 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1034 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1035 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1036 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1037 resource_provider_
->ReceiveFromChild(child_id
, list
);
1038 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1039 resource_ids_to_transfer
);
1042 EXPECT_EQ(3u, resource_provider_
->num_resources());
1043 ResourceProvider::ResourceIdMap resource_map
=
1044 resource_provider_
->GetChildToParentMap(child_id
);
1045 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1046 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1047 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1048 EXPECT_NE(0u, mapped_id1
);
1049 EXPECT_NE(0u, mapped_id2
);
1050 EXPECT_NE(0u, mapped_id3
);
1051 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1052 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1053 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1055 uint8_t result
[4] = { 0 };
1057 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1058 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1061 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1062 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1065 // Check that transfering again the same resource from the child to the
1067 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1068 resource_ids_to_transfer
.push_back(id1
);
1069 resource_ids_to_transfer
.push_back(id2
);
1070 TransferableResourceArray list
;
1071 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1073 EXPECT_EQ(2u, list
.size());
1074 EXPECT_EQ(id1
, list
[0].id
);
1075 EXPECT_EQ(id2
, list
[1].id
);
1076 ReturnedResourceArray returned
;
1077 TransferableResource::ReturnResources(list
, &returned
);
1078 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1079 // ids were exported twice, we returned them only once, they should still
1081 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1082 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1085 EXPECT_EQ(0u, returned_to_child
.size());
1087 // Transfer resources back from the parent to the child. Set no resources as
1089 ResourceProvider::ResourceIdArray no_resources
;
1090 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1092 ASSERT_EQ(3u, returned_to_child
.size());
1093 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1094 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1095 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1096 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1097 expected_ids
.insert(id1
);
1098 expected_ids
.insert(id2
);
1099 expected_ids
.insert(id3
);
1100 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1101 for (unsigned i
= 0; i
< 3; i
++)
1102 returned_ids
.insert(returned_to_child
[i
].id
);
1103 EXPECT_EQ(expected_ids
, returned_ids
);
1104 EXPECT_FALSE(returned_to_child
[0].lost
);
1105 EXPECT_FALSE(returned_to_child
[1].lost
);
1106 EXPECT_FALSE(returned_to_child
[2].lost
);
1107 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1108 returned_to_child
.clear();
1110 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1111 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1112 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1115 ResourceProvider::ScopedReadLockSoftware
lock(
1116 child_resource_provider_
.get(), id1
);
1117 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1118 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1119 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1120 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1123 ResourceProvider::ScopedReadLockSoftware
lock(
1124 child_resource_provider_
.get(), id2
);
1125 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1126 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1127 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1128 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1131 // Transfer resources to the parent again.
1132 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1133 resource_ids_to_transfer
.push_back(id1
);
1134 resource_ids_to_transfer
.push_back(id2
);
1135 resource_ids_to_transfer
.push_back(id3
);
1136 TransferableResourceArray list
;
1137 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1139 ASSERT_EQ(3u, list
.size());
1140 EXPECT_EQ(id1
, list
[0].id
);
1141 EXPECT_EQ(id2
, list
[1].id
);
1142 EXPECT_EQ(id3
, list
[2].id
);
1143 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1144 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1145 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1146 resource_provider_
->ReceiveFromChild(child_id
, list
);
1147 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1148 resource_ids_to_transfer
);
1151 EXPECT_EQ(0u, returned_to_child
.size());
1153 EXPECT_EQ(3u, resource_provider_
->num_resources());
1154 resource_provider_
->DestroyChild(child_id
);
1155 EXPECT_EQ(0u, resource_provider_
->num_resources());
1157 ASSERT_EQ(3u, returned_to_child
.size());
1158 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1159 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1160 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1161 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1162 expected_ids
.insert(id1
);
1163 expected_ids
.insert(id2
);
1164 expected_ids
.insert(id3
);
1165 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1166 for (unsigned i
= 0; i
< 3; i
++)
1167 returned_ids
.insert(returned_to_child
[i
].id
);
1168 EXPECT_EQ(expected_ids
, returned_ids
);
1169 EXPECT_FALSE(returned_to_child
[0].lost
);
1170 EXPECT_FALSE(returned_to_child
[1].lost
);
1171 EXPECT_FALSE(returned_to_child
[2].lost
);
1174 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1175 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1178 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1179 ResourceProviderContext::Create(shared_data_
.get()));
1181 FakeOutputSurfaceClient child_output_surface_client
;
1182 scoped_ptr
<OutputSurface
> child_output_surface(
1183 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1184 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1186 scoped_ptr
<ResourceProvider
> child_resource_provider(
1187 ResourceProvider::Create(child_output_surface
.get(),
1188 shared_bitmap_manager_
.get(),
1189 gpu_memory_buffer_manager_
.get(),
1195 gfx::Size
size(1, 1);
1196 ResourceFormat format
= RGBA_8888
;
1197 size_t pixel_size
= TextureSizeBytes(size
, format
);
1198 ASSERT_EQ(4U, pixel_size
);
1200 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1201 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1202 uint8_t data1
[4] = { 1, 2, 3, 4 };
1203 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1205 ReturnedResourceArray returned_to_child
;
1207 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1209 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1210 resource_ids_to_transfer
.push_back(id1
);
1211 TransferableResourceArray list
;
1212 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1214 ASSERT_EQ(1u, list
.size());
1215 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1216 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1217 list
[0].mailbox_holder
.texture_target
);
1218 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1219 resource_provider_
->ReceiveFromChild(child_id
, list
);
1222 EXPECT_EQ(0u, resource_provider_
->num_resources());
1223 ASSERT_EQ(1u, returned_to_child
.size());
1224 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1225 ResourceProvider::ResourceIdMap resource_map
=
1226 resource_provider_
->GetChildToParentMap(child_id
);
1227 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1228 EXPECT_EQ(0u, mapped_id1
);
1230 resource_provider_
->DestroyChild(child_id
);
1231 EXPECT_EQ(0u, resource_provider_
->num_resources());
1233 ASSERT_EQ(1u, returned_to_child
.size());
1234 EXPECT_FALSE(returned_to_child
[0].lost
);
1237 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1238 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1241 gfx::Size
size(1, 1);
1242 ResourceFormat format
= RGBA_8888
;
1243 size_t pixel_size
= TextureSizeBytes(size
, format
);
1244 ASSERT_EQ(4U, pixel_size
);
1246 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1247 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1248 uint8_t data1
[4] = { 1, 2, 3, 4 };
1249 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1251 ReturnedResourceArray returned_to_child
;
1253 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1255 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1256 resource_ids_to_transfer
.push_back(id1
);
1257 TransferableResourceArray list
;
1258 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1260 ASSERT_EQ(1u, list
.size());
1262 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1263 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1264 resource_provider_
->ReceiveFromChild(child_id
, list
);
1267 EXPECT_EQ(1u, resource_provider_
->num_resources());
1268 EXPECT_EQ(0u, returned_to_child
.size());
1270 ResourceProvider::ResourceIdMap resource_map
=
1271 resource_provider_
->GetChildToParentMap(child_id
);
1272 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1273 EXPECT_NE(0u, mapped_id1
);
1275 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1277 EXPECT_FALSE(lock
.valid());
1280 resource_provider_
->DestroyChild(child_id
);
1281 EXPECT_EQ(0u, resource_provider_
->num_resources());
1283 ASSERT_EQ(1u, returned_to_child
.size());
1284 EXPECT_FALSE(returned_to_child
[0].lost
);
1287 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1288 gfx::Size
size(1, 1);
1289 ResourceFormat format
= RGBA_8888
;
1290 size_t pixel_size
= TextureSizeBytes(size
, format
);
1291 ASSERT_EQ(4U, pixel_size
);
1293 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1294 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1295 uint8_t data1
[4] = { 1, 2, 3, 4 };
1296 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1298 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1299 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1300 uint8_t data2
[4] = {5, 5, 5, 5};
1301 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1303 ReturnedResourceArray returned_to_child
;
1305 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1307 // Transfer some resources to the parent.
1308 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1309 resource_ids_to_transfer
.push_back(id1
);
1310 resource_ids_to_transfer
.push_back(id2
);
1311 TransferableResourceArray list
;
1312 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1314 ASSERT_EQ(2u, list
.size());
1315 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1316 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1317 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1319 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1320 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1321 resource_provider_
->ReceiveFromChild(child_id
, list
);
1322 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1323 resource_ids_to_transfer
);
1326 EXPECT_EQ(2u, resource_provider_
->num_resources());
1327 ResourceProvider::ResourceIdMap resource_map
=
1328 resource_provider_
->GetChildToParentMap(child_id
);
1329 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1330 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1331 EXPECT_NE(0u, mapped_id1
);
1332 EXPECT_NE(0u, mapped_id2
);
1333 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1334 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1337 // The parent transfers the resources to the grandparent.
1338 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1339 resource_ids_to_transfer
.push_back(mapped_id1
);
1340 resource_ids_to_transfer
.push_back(mapped_id2
);
1341 TransferableResourceArray list
;
1342 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1344 ASSERT_EQ(2u, list
.size());
1345 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1346 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1347 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1349 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1350 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1352 // Release the resource in the parent. Set no resources as being in use. The
1353 // resources are exported so that can't be transferred back yet.
1354 ResourceProvider::ResourceIdArray no_resources
;
1355 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1357 EXPECT_EQ(0u, returned_to_child
.size());
1358 EXPECT_EQ(2u, resource_provider_
->num_resources());
1360 // Return the resources from the grandparent to the parent. They should be
1361 // returned to the child then.
1362 EXPECT_EQ(2u, list
.size());
1363 EXPECT_EQ(mapped_id1
, list
[0].id
);
1364 EXPECT_EQ(mapped_id2
, list
[1].id
);
1365 ReturnedResourceArray returned
;
1366 TransferableResource::ReturnResources(list
, &returned
);
1367 resource_provider_
->ReceiveReturnsFromParent(returned
);
1369 EXPECT_EQ(0u, resource_provider_
->num_resources());
1370 ASSERT_EQ(2u, returned_to_child
.size());
1371 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1372 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1373 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1375 EXPECT_FALSE(returned_to_child
[0].lost
);
1376 EXPECT_FALSE(returned_to_child
[1].lost
);
1380 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1381 gfx::Size
size(1, 1);
1382 ResourceFormat format
= RGBA_8888
;
1383 size_t pixel_size
= TextureSizeBytes(size
, format
);
1384 ASSERT_EQ(4U, pixel_size
);
1386 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1387 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1388 uint8_t data1
[4] = {1, 2, 3, 4};
1389 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1391 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1392 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1393 uint8_t data2
[4] = {5, 5, 5, 5};
1394 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1396 ReturnedResourceArray returned_to_child
;
1398 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1400 // Transfer some resources to the parent.
1401 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1402 resource_ids_to_transfer
.push_back(id1
);
1403 resource_ids_to_transfer
.push_back(id2
);
1404 TransferableResourceArray list
;
1405 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1407 ASSERT_EQ(2u, list
.size());
1408 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1409 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1410 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1412 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1413 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1414 resource_provider_
->ReceiveFromChild(child_id
, list
);
1415 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1416 resource_ids_to_transfer
);
1419 EXPECT_EQ(2u, resource_provider_
->num_resources());
1420 ResourceProvider::ResourceIdMap resource_map
=
1421 resource_provider_
->GetChildToParentMap(child_id
);
1422 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1423 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1424 EXPECT_NE(0u, mapped_id1
);
1425 EXPECT_NE(0u, mapped_id2
);
1426 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1427 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1430 // The parent transfers the resources to the grandparent.
1431 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1432 resource_ids_to_transfer
.push_back(mapped_id1
);
1433 resource_ids_to_transfer
.push_back(mapped_id2
);
1434 TransferableResourceArray list
;
1435 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1437 ASSERT_EQ(2u, list
.size());
1438 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1439 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1440 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1442 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1443 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1445 // Release the resource in the parent. Set no resources as being in use. The
1446 // resources are exported so that can't be transferred back yet.
1447 ResourceProvider::ResourceIdArray no_resources
;
1448 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1450 // Destroy the child, the resources should not be returned yet.
1451 EXPECT_EQ(0u, returned_to_child
.size());
1452 EXPECT_EQ(2u, resource_provider_
->num_resources());
1454 resource_provider_
->DestroyChild(child_id
);
1456 EXPECT_EQ(2u, resource_provider_
->num_resources());
1457 ASSERT_EQ(0u, returned_to_child
.size());
1459 // Return a resource from the grandparent, it should be returned at this
1461 EXPECT_EQ(2u, list
.size());
1462 EXPECT_EQ(mapped_id1
, list
[0].id
);
1463 EXPECT_EQ(mapped_id2
, list
[1].id
);
1464 TransferableResourceArray return_list
;
1465 return_list
.push_back(list
[1]);
1467 ReturnedResourceArray returned
;
1468 TransferableResource::ReturnResources(return_list
, &returned
);
1469 resource_provider_
->ReceiveReturnsFromParent(returned
);
1471 EXPECT_EQ(1u, resource_provider_
->num_resources());
1472 ASSERT_EQ(1u, returned_to_child
.size());
1473 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1474 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1476 EXPECT_FALSE(returned_to_child
[0].lost
);
1477 returned_to_child
.clear();
1479 // Destroy the parent resource provider. The resource that's left should be
1480 // lost at this point, and returned.
1481 resource_provider_
= nullptr;
1482 ASSERT_EQ(1u, returned_to_child
.size());
1483 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1484 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1486 EXPECT_TRUE(returned_to_child
[0].lost
);
1490 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1491 gfx::Size
size(1, 1);
1492 ResourceFormat format
= RGBA_8888
;
1493 size_t pixel_size
= TextureSizeBytes(size
, format
);
1494 ASSERT_EQ(4U, pixel_size
);
1496 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1497 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1498 uint8_t data
[4] = { 1, 2, 3, 4 };
1499 child_resource_provider_
->CopyToResource(id
, data
, size
);
1501 ReturnedResourceArray returned_to_child
;
1503 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1505 // Transfer some resource to the parent.
1506 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1507 resource_ids_to_transfer
.push_back(id
);
1508 TransferableResourceArray list
;
1509 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1511 ASSERT_EQ(1u, list
.size());
1512 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1513 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1514 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1515 resource_provider_
->ReceiveFromChild(child_id
, list
);
1516 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1517 resource_ids_to_transfer
);
1520 // Delete textures in the child, while they are transfered.
1521 child_resource_provider_
->DeleteResource(id
);
1522 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1524 EXPECT_EQ(0u, returned_to_child
.size());
1526 // Transfer resources back from the parent to the child. Set no resources as
1528 ResourceProvider::ResourceIdArray no_resources
;
1529 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1531 ASSERT_EQ(1u, returned_to_child
.size());
1532 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1533 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1534 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1536 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1539 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1540 gfx::Size
size(1, 1);
1541 ResourceFormat format
= RGBA_8888
;
1542 size_t pixel_size
= TextureSizeBytes(size
, format
);
1543 ASSERT_EQ(4U, pixel_size
);
1545 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1546 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1547 uint8_t data
[4] = {1, 2, 3, 4};
1548 child_resource_provider_
->CopyToResource(id
, data
, size
);
1550 ReturnedResourceArray returned_to_child
;
1552 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1553 const ResourceProvider::ResourceIdMap
& map
=
1554 resource_provider_
->GetChildToParentMap(child_id
);
1556 // Transfer some resource to the parent.
1557 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1558 resource_ids_to_transfer
.push_back(id
);
1559 TransferableResourceArray list
;
1560 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1562 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1563 resource_provider_
->ReceiveFromChild(child_id
, list
);
1564 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1565 resource_ids_to_transfer
);
1567 TransferableResourceArray sent_to_top_level
;
1569 // Parent transfers to top-level.
1570 ASSERT_TRUE(map
.find(id
) != map
.end());
1571 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1572 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1573 resource_ids_to_transfer
.push_back(parent_id
);
1574 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1575 &sent_to_top_level
);
1576 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1579 // Stop using resource.
1580 ResourceProvider::ResourceIdArray empty
;
1581 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1582 // Resource is not yet returned to the child, since it's in use by the
1584 EXPECT_TRUE(returned_to_child
.empty());
1587 // Send the resource to the parent again.
1588 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1589 resource_ids_to_transfer
.push_back(id
);
1590 TransferableResourceArray list
;
1591 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1593 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1594 resource_provider_
->ReceiveFromChild(child_id
, list
);
1595 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1596 resource_ids_to_transfer
);
1599 // Receive returns back from top-level.
1600 ReturnedResourceArray returned
;
1601 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1602 resource_provider_
->ReceiveReturnsFromParent(returned
);
1603 // Resource is still not yet returned to the child, since it's declared used
1605 EXPECT_TRUE(returned_to_child
.empty());
1606 ASSERT_TRUE(map
.find(id
) != map
.end());
1607 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1608 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1611 sent_to_top_level
.clear();
1612 // Parent transfers again to top-level.
1613 ASSERT_TRUE(map
.find(id
) != map
.end());
1614 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1615 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1616 resource_ids_to_transfer
.push_back(parent_id
);
1617 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1618 &sent_to_top_level
);
1619 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1622 // Receive returns back from top-level.
1623 ReturnedResourceArray returned
;
1624 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1625 resource_provider_
->ReceiveReturnsFromParent(returned
);
1626 // Resource is still not yet returned to the child, since it's still
1627 // declared used in the parent.
1628 EXPECT_TRUE(returned_to_child
.empty());
1629 ASSERT_TRUE(map
.find(id
) != map
.end());
1630 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1631 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1634 // Stop using resource.
1635 ResourceProvider::ResourceIdArray empty
;
1636 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1637 // Resource should have been returned to the child, since it's no longer in
1638 // use by the top-level.
1639 ASSERT_EQ(1u, returned_to_child
.size());
1640 EXPECT_EQ(id
, returned_to_child
[0].id
);
1641 EXPECT_EQ(2, returned_to_child
[0].count
);
1642 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1643 returned_to_child
.clear();
1644 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1648 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1650 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1651 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1652 new TextureStateTrackingContext
);
1653 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1655 FakeOutputSurfaceClient child_output_surface_client
;
1656 scoped_ptr
<OutputSurface
> child_output_surface(
1657 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1658 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1659 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1660 new TestSharedBitmapManager());
1662 scoped_ptr
<ResourceProvider
> child_resource_provider(
1663 ResourceProvider::Create(child_output_surface
.get(),
1664 shared_bitmap_manager
.get(),
1671 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1672 new TextureStateTrackingContext
);
1673 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1675 FakeOutputSurfaceClient parent_output_surface_client
;
1676 scoped_ptr
<OutputSurface
> parent_output_surface(
1677 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1678 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1680 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1681 ResourceProvider::Create(parent_output_surface
.get(),
1682 shared_bitmap_manager
.get(),
1689 gfx::Size
size(1, 1);
1690 ResourceFormat format
= RGBA_8888
;
1691 int child_texture_id
= 1;
1692 int parent_texture_id
= 2;
1694 size_t pixel_size
= TextureSizeBytes(size
, format
);
1695 ASSERT_EQ(4U, pixel_size
);
1697 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1698 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1701 // The new texture is created with GL_LINEAR.
1702 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1703 .Times(2); // Once to create and once to allocate.
1704 EXPECT_CALL(*child_context
,
1705 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1706 EXPECT_CALL(*child_context
,
1707 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1710 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1713 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1714 EXPECT_CALL(*child_context
,
1715 texParameteri(GL_TEXTURE_2D
,
1716 GL_TEXTURE_POOL_CHROMIUM
,
1717 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1718 child_resource_provider
->AllocateForTesting(id
);
1719 Mock::VerifyAndClearExpectations(child_context
);
1721 uint8_t data
[4] = { 1, 2, 3, 4 };
1723 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1724 child_resource_provider
->CopyToResource(id
, data
, size
);
1725 Mock::VerifyAndClearExpectations(child_context
);
1727 // The texture is set to |child_filter| in the child.
1728 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1729 if (child_filter
!= GL_LINEAR
) {
1732 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1735 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1737 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1738 Mock::VerifyAndClearExpectations(child_context
);
1740 ReturnedResourceArray returned_to_child
;
1741 int child_id
= parent_resource_provider
->CreateChild(
1742 GetReturnCallback(&returned_to_child
));
1744 // Transfer some resource to the parent.
1745 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1746 resource_ids_to_transfer
.push_back(id
);
1747 TransferableResourceArray list
;
1749 EXPECT_CALL(*child_context
,
1750 produceTextureDirectCHROMIUM(_
, GL_TEXTURE_2D
, _
));
1751 EXPECT_CALL(*child_context
, insertSyncPoint());
1752 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1754 Mock::VerifyAndClearExpectations(child_context
);
1756 ASSERT_EQ(1u, list
.size());
1757 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1759 EXPECT_CALL(*parent_context
,
1760 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, _
))
1761 .WillOnce(Return(parent_texture_id
));
1763 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1765 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1766 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1769 Mock::VerifyAndClearExpectations(parent_context
);
1771 parent_resource_provider
->DeclareUsedResourcesFromChild(
1772 child_id
, resource_ids_to_transfer
);
1773 Mock::VerifyAndClearExpectations(parent_context
);
1775 ResourceProvider::ResourceIdMap resource_map
=
1776 parent_resource_provider
->GetChildToParentMap(child_id
);
1777 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1778 EXPECT_NE(0u, mapped_id
);
1780 // The texture is set to |parent_filter| in the parent.
1781 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1784 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1787 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1788 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1789 Mock::VerifyAndClearExpectations(parent_context
);
1791 // The texture should be reset to |child_filter| in the parent when it is
1792 // returned, since that is how it was received.
1793 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1796 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1799 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1802 EXPECT_EQ(0u, returned_to_child
.size());
1804 // Transfer resources back from the parent to the child. Set no resources
1806 ResourceProvider::ResourceIdArray no_resources
;
1807 EXPECT_CALL(*parent_context
, insertSyncPoint());
1808 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1810 Mock::VerifyAndClearExpectations(parent_context
);
1812 ASSERT_EQ(1u, returned_to_child
.size());
1813 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1816 // The child remembers the texture filter is set to |child_filter|.
1817 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1818 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1819 Mock::VerifyAndClearExpectations(child_context
);
1823 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1824 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1826 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1829 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1830 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1832 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1835 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1836 // Other mailbox transfers tested elsewhere.
1837 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1839 unsigned texture
= context()->createTexture();
1840 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1841 uint8_t data
[4] = { 1, 2, 3, 4 };
1842 context()->texImage2D(
1843 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1844 gpu::Mailbox mailbox
;
1845 context()->genMailboxCHROMIUM(mailbox
.name
);
1846 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
1847 uint32 sync_point
= context()->insertSyncPoint();
1849 // All the logic below assumes that the sync points are all positive.
1850 EXPECT_LT(0u, sync_point
);
1852 uint32 release_sync_point
= 0;
1853 bool lost_resource
= false;
1854 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1855 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1856 &release_sync_point
,
1858 &main_thread_task_runner
);
1859 ResourceProvider::ResourceId resource
=
1860 resource_provider_
->CreateResourceFromTextureMailbox(
1861 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1862 SingleReleaseCallbackImpl::Create(callback
));
1863 EXPECT_EQ(1u, context()->NumTextures());
1864 EXPECT_EQ(0u, release_sync_point
);
1866 // Transfer the resource, expect the sync points to be consistent.
1867 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1868 resource_ids_to_transfer
.push_back(resource
);
1869 TransferableResourceArray list
;
1870 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1871 ASSERT_EQ(1u, list
.size());
1872 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1874 memcmp(mailbox
.name
,
1875 list
[0].mailbox_holder
.mailbox
.name
,
1876 sizeof(mailbox
.name
)));
1877 EXPECT_EQ(0u, release_sync_point
);
1879 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1880 unsigned other_texture
=
1881 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1882 uint8_t test_data
[4] = { 0 };
1883 context()->GetPixels(
1884 gfx::Size(1, 1), RGBA_8888
, test_data
);
1885 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1887 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
1889 context()->deleteTexture(other_texture
);
1890 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1891 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1893 // Receive the resource, then delete it, expect the sync points to be
1895 ReturnedResourceArray returned
;
1896 TransferableResource::ReturnResources(list
, &returned
);
1897 resource_provider_
->ReceiveReturnsFromParent(returned
);
1898 EXPECT_EQ(1u, context()->NumTextures());
1899 EXPECT_EQ(0u, release_sync_point
);
1901 resource_provider_
->DeleteResource(resource
);
1902 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1903 EXPECT_FALSE(lost_resource
);
1904 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1907 // We're going to do the same thing as above, but testing the case where we
1908 // delete the resource before we receive it back.
1909 sync_point
= release_sync_point
;
1910 EXPECT_LT(0u, sync_point
);
1911 release_sync_point
= 0;
1912 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1913 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1914 SingleReleaseCallbackImpl::Create(callback
));
1915 EXPECT_EQ(1u, context()->NumTextures());
1916 EXPECT_EQ(0u, release_sync_point
);
1918 // Transfer the resource, expect the sync points to be consistent.
1919 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1920 resource_ids_to_transfer
.push_back(resource
);
1921 TransferableResourceArray list
;
1922 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1923 ASSERT_EQ(1u, list
.size());
1924 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1926 memcmp(mailbox
.name
,
1927 list
[0].mailbox_holder
.mailbox
.name
,
1928 sizeof(mailbox
.name
)));
1929 EXPECT_EQ(0u, release_sync_point
);
1931 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1932 unsigned other_texture
=
1933 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1934 uint8_t test_data
[4] = { 0 };
1935 context()->GetPixels(
1936 gfx::Size(1, 1), RGBA_8888
, test_data
);
1937 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1939 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
1941 context()->deleteTexture(other_texture
);
1942 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1943 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1945 // Delete the resource, which shouldn't do anything.
1946 resource_provider_
->DeleteResource(resource
);
1947 EXPECT_EQ(1u, context()->NumTextures());
1948 EXPECT_EQ(0u, release_sync_point
);
1950 // Then receive the resource which should release the mailbox, expect the
1951 // sync points to be consistent.
1952 ReturnedResourceArray returned
;
1953 TransferableResource::ReturnResources(list
, &returned
);
1954 resource_provider_
->ReceiveReturnsFromParent(returned
);
1955 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1956 EXPECT_FALSE(lost_resource
);
1957 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1960 context()->waitSyncPoint(release_sync_point
);
1962 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1963 context()->deleteTexture(texture
);
1966 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1967 gfx::Size
size(1, 1);
1968 ResourceFormat format
= RGBA_8888
;
1969 ResourceProvider::ResourceId resource
=
1970 child_resource_provider_
->CreateResource(
1971 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1973 child_resource_provider_
->AllocateForTesting(resource
);
1974 // Expect a GL resource to be lost.
1975 bool should_lose_resource
=
1976 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
1978 ReturnedResourceArray returned_to_child
;
1980 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1982 // Transfer the resource to the parent.
1983 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1984 resource_ids_to_transfer
.push_back(resource
);
1985 TransferableResourceArray list
;
1986 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1988 EXPECT_EQ(1u, list
.size());
1990 resource_provider_
->ReceiveFromChild(child_id
, list
);
1991 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1992 resource_ids_to_transfer
);
1995 // Lose the output surface in the parent.
1996 resource_provider_
->DidLoseOutputSurface();
1999 EXPECT_EQ(0u, returned_to_child
.size());
2001 // Transfer resources back from the parent to the child. Set no resources as
2003 ResourceProvider::ResourceIdArray no_resources
;
2004 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2006 // Expect a GL resource to be lost.
2007 ASSERT_EQ(1u, returned_to_child
.size());
2008 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2009 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2010 returned_to_child
.clear();
2013 // A GL resource should be lost.
2014 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2016 // Lost resources stay in use in the parent forever.
2017 EXPECT_EQ(should_lose_resource
,
2018 child_resource_provider_
->InUseByConsumer(resource
));
2021 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2022 gfx::Size
size(1, 1);
2023 ResourceFormat format
= RGBA_8888
;
2024 ResourceProvider::ResourceId resource
=
2025 child_resource_provider_
->CreateResource(
2026 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2028 child_resource_provider_
->AllocateForTesting(resource
);
2030 ReturnedResourceArray returned_to_child
;
2032 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2034 // Transfer the resource to the parent.
2035 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2036 resource_ids_to_transfer
.push_back(resource
);
2037 TransferableResourceArray list
;
2038 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2040 EXPECT_EQ(1u, list
.size());
2042 resource_provider_
->ReceiveFromChild(child_id
, list
);
2043 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2044 resource_ids_to_transfer
);
2048 ResourceProvider::ResourceIdMap resource_map
=
2049 resource_provider_
->GetChildToParentMap(child_id
);
2050 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2051 EXPECT_NE(0u, parent_resource
);
2053 // Transfer to a grandparent.
2054 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2055 resource_ids_to_transfer
.push_back(parent_resource
);
2056 TransferableResourceArray list
;
2057 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2059 // Receive back a lost resource from the grandparent.
2060 EXPECT_EQ(1u, list
.size());
2061 EXPECT_EQ(parent_resource
, list
[0].id
);
2062 ReturnedResourceArray returned
;
2063 TransferableResource::ReturnResources(list
, &returned
);
2064 EXPECT_EQ(1u, returned
.size());
2065 EXPECT_EQ(parent_resource
, returned
[0].id
);
2066 returned
[0].lost
= true;
2067 resource_provider_
->ReceiveReturnsFromParent(returned
);
2069 // The resource should be lost.
2070 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2072 // Lost resources stay in use in the parent forever.
2073 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2077 EXPECT_EQ(0u, returned_to_child
.size());
2079 // Transfer resources back from the parent to the child. Set no resources as
2081 ResourceProvider::ResourceIdArray no_resources
;
2082 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2084 // Expect the resource to be lost.
2085 ASSERT_EQ(1u, returned_to_child
.size());
2086 EXPECT_TRUE(returned_to_child
[0].lost
);
2087 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2088 returned_to_child
.clear();
2091 // The resource should be lost.
2092 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2094 // Lost resources stay in use in the parent forever.
2095 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2098 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2099 uint32 release_sync_point
= 0;
2100 bool lost_resource
= false;
2101 bool release_called
= false;
2102 uint32 sync_point
= 0;
2103 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2104 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2106 ReturnedResourceArray returned_to_child
;
2108 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2110 // Transfer the resource to the parent.
2111 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2112 resource_ids_to_transfer
.push_back(resource
);
2113 TransferableResourceArray list
;
2114 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2116 EXPECT_EQ(1u, list
.size());
2118 resource_provider_
->ReceiveFromChild(child_id
, list
);
2119 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2120 resource_ids_to_transfer
);
2123 // Lose the output surface in the parent.
2124 resource_provider_
->DidLoseOutputSurface();
2127 EXPECT_EQ(0u, returned_to_child
.size());
2129 // Transfer resources back from the parent to the child. Set no resources as
2131 ResourceProvider::ResourceIdArray no_resources
;
2132 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2134 ASSERT_EQ(1u, returned_to_child
.size());
2135 // Losing an output surface only loses hardware resources.
2136 EXPECT_EQ(returned_to_child
[0].lost
,
2137 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2138 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2139 returned_to_child
.clear();
2142 // Delete the resource in the child. Expect the resource to be lost if it's
2144 child_resource_provider_
->DeleteResource(resource
);
2145 EXPECT_EQ(lost_resource
,
2146 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2149 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2150 uint32 release_sync_point
= 0;
2151 bool lost_resource
= false;
2152 bool release_called
= false;
2153 uint32 sync_point
= 0;
2154 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2155 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2157 ReturnedResourceArray returned_to_child
;
2159 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2161 // Transfer the resource to the parent.
2162 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2163 resource_ids_to_transfer
.push_back(resource
);
2164 TransferableResourceArray list
;
2165 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2167 EXPECT_EQ(1u, list
.size());
2169 resource_provider_
->ReceiveFromChild(child_id
, list
);
2170 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2171 resource_ids_to_transfer
);
2175 ResourceProvider::ResourceIdMap resource_map
=
2176 resource_provider_
->GetChildToParentMap(child_id
);
2177 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2178 EXPECT_NE(0u, parent_resource
);
2180 // Transfer to a grandparent.
2181 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2182 resource_ids_to_transfer
.push_back(parent_resource
);
2183 TransferableResourceArray list
;
2184 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2186 // Receive back a lost resource from the grandparent.
2187 EXPECT_EQ(1u, list
.size());
2188 EXPECT_EQ(parent_resource
, list
[0].id
);
2189 ReturnedResourceArray returned
;
2190 TransferableResource::ReturnResources(list
, &returned
);
2191 EXPECT_EQ(1u, returned
.size());
2192 EXPECT_EQ(parent_resource
, returned
[0].id
);
2193 returned
[0].lost
= true;
2194 resource_provider_
->ReceiveReturnsFromParent(returned
);
2198 EXPECT_EQ(0u, returned_to_child
.size());
2200 // Transfer resources back from the parent to the child. Set no resources as
2202 ResourceProvider::ResourceIdArray no_resources
;
2203 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2205 // Expect the resource to be lost.
2206 ASSERT_EQ(1u, returned_to_child
.size());
2207 EXPECT_TRUE(returned_to_child
[0].lost
);
2208 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2209 returned_to_child
.clear();
2212 // Delete the resource in the child. Expect the resource to be lost.
2213 child_resource_provider_
->DeleteResource(resource
);
2214 EXPECT_TRUE(lost_resource
);
2217 TEST_P(ResourceProviderTest
, Shutdown
) {
2218 uint32 release_sync_point
= 0;
2219 bool lost_resource
= false;
2220 bool release_called
= false;
2221 uint32 sync_point
= 0;
2223 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2225 EXPECT_EQ(0u, release_sync_point
);
2226 EXPECT_FALSE(lost_resource
);
2228 child_resource_provider_
= nullptr;
2230 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2231 EXPECT_LE(sync_point
, release_sync_point
);
2233 EXPECT_TRUE(release_called
);
2234 EXPECT_FALSE(lost_resource
);
2237 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2238 uint32 release_sync_point
= 0;
2239 bool lost_resource
= false;
2240 bool release_called
= false;
2241 uint32 sync_point
= 0;
2242 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2243 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2245 // Transfer the resource, so we can't release it properly on shutdown.
2246 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2247 resource_ids_to_transfer
.push_back(resource
);
2248 TransferableResourceArray list
;
2249 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2252 EXPECT_EQ(0u, release_sync_point
);
2253 EXPECT_FALSE(lost_resource
);
2255 child_resource_provider_
= nullptr;
2257 // Since the resource is in the parent, the child considers it lost.
2258 EXPECT_EQ(0u, release_sync_point
);
2259 EXPECT_TRUE(lost_resource
);
2262 TEST_P(ResourceProviderTest
, LostContext
) {
2263 // TextureMailbox callbacks only exist for GL textures for now.
2264 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2266 unsigned texture
= context()->createTexture();
2267 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2268 gpu::Mailbox mailbox
;
2269 context()->genMailboxCHROMIUM(mailbox
.name
);
2270 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2271 uint32 sync_point
= context()->insertSyncPoint();
2273 EXPECT_LT(0u, sync_point
);
2275 uint32 release_sync_point
= 0;
2276 bool lost_resource
= false;
2277 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2278 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2279 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2280 &release_sync_point
,
2282 &main_thread_task_runner
));
2283 resource_provider_
->CreateResourceFromTextureMailbox(
2284 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2286 EXPECT_EQ(0u, release_sync_point
);
2287 EXPECT_FALSE(lost_resource
);
2288 EXPECT_EQ(NULL
, main_thread_task_runner
);
2290 resource_provider_
->DidLoseOutputSurface();
2291 resource_provider_
= nullptr;
2293 EXPECT_LE(sync_point
, release_sync_point
);
2294 EXPECT_TRUE(lost_resource
);
2295 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2298 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2299 // Sampling is only supported for GL textures.
2300 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2303 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2304 new TextureStateTrackingContext
);
2305 TextureStateTrackingContext
* context
= context_owned
.get();
2307 FakeOutputSurfaceClient output_surface_client
;
2308 scoped_ptr
<OutputSurface
> output_surface(
2309 FakeOutputSurface::Create3d(context_owned
.Pass()));
2310 CHECK(output_surface
->BindToClient(&output_surface_client
));
2312 scoped_ptr
<ResourceProvider
> resource_provider(
2313 ResourceProvider::Create(output_surface
.get(),
2314 shared_bitmap_manager_
.get(),
2315 gpu_memory_buffer_manager_
.get(),
2321 gfx::Size
size(1, 1);
2322 ResourceFormat format
= RGBA_8888
;
2325 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2326 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2328 // Check that the texture gets created with the right sampler settings.
2329 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2330 .Times(2); // Once to create and once to allocate.
2331 EXPECT_CALL(*context
,
2332 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2333 EXPECT_CALL(*context
,
2334 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2337 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2340 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2341 EXPECT_CALL(*context
,
2342 texParameteri(GL_TEXTURE_2D
,
2343 GL_TEXTURE_POOL_CHROMIUM
,
2344 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2346 resource_provider
->AllocateForTesting(id
);
2347 Mock::VerifyAndClearExpectations(context
);
2349 // Creating a sampler with the default filter should not change any texture
2352 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2353 ResourceProvider::ScopedSamplerGL
sampler(
2354 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2355 Mock::VerifyAndClearExpectations(context
);
2358 // Using a different filter should be reflected in the texture parameters.
2360 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2363 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2366 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2367 ResourceProvider::ScopedSamplerGL
sampler(
2368 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2369 Mock::VerifyAndClearExpectations(context
);
2372 // Test resetting to the default filter.
2374 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2375 EXPECT_CALL(*context
,
2376 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2377 EXPECT_CALL(*context
,
2378 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2379 ResourceProvider::ScopedSamplerGL
sampler(
2380 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2381 Mock::VerifyAndClearExpectations(context
);
2385 TEST_P(ResourceProviderTest
, ManagedResource
) {
2386 // Sampling is only supported for GL textures.
2387 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2390 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2391 new TextureStateTrackingContext
);
2392 TextureStateTrackingContext
* context
= context_owned
.get();
2394 FakeOutputSurfaceClient output_surface_client
;
2395 scoped_ptr
<OutputSurface
> output_surface(
2396 FakeOutputSurface::Create3d(context_owned
.Pass()));
2397 CHECK(output_surface
->BindToClient(&output_surface_client
));
2399 scoped_ptr
<ResourceProvider
> resource_provider(
2400 ResourceProvider::Create(output_surface
.get(),
2401 shared_bitmap_manager_
.get(),
2402 gpu_memory_buffer_manager_
.get(),
2408 gfx::Size
size(1, 1);
2409 ResourceFormat format
= RGBA_8888
;
2412 // Check that the texture gets created with the right sampler settings.
2413 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2414 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2415 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2416 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2417 EXPECT_CALL(*context
,
2418 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2419 EXPECT_CALL(*context
,
2420 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2423 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2426 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2427 EXPECT_CALL(*context
,
2428 texParameteri(GL_TEXTURE_2D
,
2429 GL_TEXTURE_POOL_CHROMIUM
,
2430 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2431 resource_provider
->CreateForTesting(id
);
2434 Mock::VerifyAndClearExpectations(context
);
2437 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2438 // Sampling is only supported for GL textures.
2439 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2442 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2443 new TextureStateTrackingContext
);
2444 TextureStateTrackingContext
* context
= context_owned
.get();
2446 FakeOutputSurfaceClient output_surface_client
;
2447 scoped_ptr
<OutputSurface
> output_surface(
2448 FakeOutputSurface::Create3d(context_owned
.Pass()));
2449 CHECK(output_surface
->BindToClient(&output_surface_client
));
2451 scoped_ptr
<ResourceProvider
> resource_provider(
2452 ResourceProvider::Create(output_surface
.get(),
2453 shared_bitmap_manager_
.get(),
2454 gpu_memory_buffer_manager_
.get(),
2460 gfx::Size
size(1, 1);
2461 ResourceFormat format
= RGBA_8888
;
2462 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2464 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2465 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2466 // Check that the texture gets created with the right sampler settings.
2467 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2468 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2469 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2470 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2471 EXPECT_CALL(*context
,
2472 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2473 EXPECT_CALL(*context
,
2474 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2475 EXPECT_CALL(*context
,
2476 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2477 EXPECT_CALL(*context
,
2478 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2479 EXPECT_CALL(*context
,
2480 texParameteri(GL_TEXTURE_2D
,
2481 GL_TEXTURE_POOL_CHROMIUM
,
2482 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2483 resource_provider
->CreateForTesting(id
);
2486 Mock::VerifyAndClearExpectations(context
);
2490 TEST_P(ResourceProviderTest
, TextureHint
) {
2491 // Sampling is only supported for GL textures.
2492 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2495 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2496 new TextureStateTrackingContext
);
2497 TextureStateTrackingContext
* context
= context_owned
.get();
2498 context
->set_support_texture_storage(true);
2499 context
->set_support_texture_usage(true);
2501 FakeOutputSurfaceClient output_surface_client
;
2502 scoped_ptr
<OutputSurface
> output_surface(
2503 FakeOutputSurface::Create3d(context_owned
.Pass()));
2504 CHECK(output_surface
->BindToClient(&output_surface_client
));
2506 scoped_ptr
<ResourceProvider
> resource_provider(
2507 ResourceProvider::Create(output_surface
.get(),
2508 shared_bitmap_manager_
.get(),
2509 gpu_memory_buffer_manager_
.get(),
2515 gfx::Size
size(1, 1);
2516 ResourceFormat format
= RGBA_8888
;
2517 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2519 const ResourceProvider::TextureHint hints
[4] = {
2520 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2521 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2522 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2523 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2525 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2526 // Check that the texture gets created with the right sampler settings.
2527 ResourceProvider::ResourceId id
=
2528 resource_provider
->CreateGLTexture(size
,
2532 hints
[texture_id
- 1],
2534 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2535 EXPECT_CALL(*context
,
2536 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2537 EXPECT_CALL(*context
,
2538 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2541 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2544 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2545 EXPECT_CALL(*context
,
2546 texParameteri(GL_TEXTURE_2D
,
2547 GL_TEXTURE_POOL_CHROMIUM
,
2548 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2549 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2550 bool is_framebuffer_hint
=
2551 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2552 EXPECT_CALL(*context
,
2553 texParameteri(GL_TEXTURE_2D
,
2554 GL_TEXTURE_USAGE_ANGLE
,
2555 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2556 .Times(is_framebuffer_hint
? 1 : 0);
2557 resource_provider
->CreateForTesting(id
);
2560 Mock::VerifyAndClearExpectations(context
);
2564 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2565 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2568 gfx::Size
size(64, 64);
2569 const uint32_t kBadBeef
= 0xbadbeef;
2570 scoped_ptr
<SharedBitmap
> shared_bitmap(
2571 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2573 FakeOutputSurfaceClient output_surface_client
;
2574 scoped_ptr
<OutputSurface
> output_surface(
2575 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2576 new SoftwareOutputDevice
)));
2577 CHECK(output_surface
->BindToClient(&output_surface_client
));
2579 scoped_ptr
<ResourceProvider
> resource_provider(
2580 ResourceProvider::Create(output_surface
.get(),
2581 shared_bitmap_manager_
.get(),
2582 gpu_memory_buffer_manager_
.get(),
2583 main_thread_task_runner_
.get(),
2588 uint32 release_sync_point
= 0;
2589 bool lost_resource
= false;
2590 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2591 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2592 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2593 &release_sync_point
,
2595 &main_thread_task_runner
));
2596 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2598 ResourceProvider::ResourceId id
=
2599 resource_provider
->CreateResourceFromTextureMailbox(
2600 mailbox
, callback
.Pass());
2604 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2605 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2606 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2607 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2608 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2611 resource_provider
->DeleteResource(id
);
2612 EXPECT_EQ(0u, release_sync_point
);
2613 EXPECT_FALSE(lost_resource
);
2614 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2617 class ResourceProviderTestTextureMailboxGLFilters
2618 : public ResourceProviderTest
{
2620 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2621 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2622 BlockingTaskRunner
* main_thread_task_runner
,
2623 bool mailbox_nearest_neighbor
,
2624 GLenum sampler_filter
) {
2625 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2626 new TextureStateTrackingContext
);
2627 TextureStateTrackingContext
* context
= context_owned
.get();
2629 FakeOutputSurfaceClient output_surface_client
;
2630 scoped_ptr
<OutputSurface
> output_surface(
2631 FakeOutputSurface::Create3d(context_owned
.Pass()));
2632 CHECK(output_surface
->BindToClient(&output_surface_client
));
2634 scoped_ptr
<ResourceProvider
> resource_provider(
2635 ResourceProvider::Create(output_surface
.get(),
2636 shared_bitmap_manager
,
2637 gpu_memory_buffer_manager
,
2638 main_thread_task_runner
,
2643 unsigned texture_id
= 1;
2644 uint32 sync_point
= 30;
2645 unsigned target
= GL_TEXTURE_2D
;
2647 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2648 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2649 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2650 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2651 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2653 gpu::Mailbox gpu_mailbox
;
2654 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2655 uint32 release_sync_point
= 0;
2656 bool lost_resource
= false;
2657 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2658 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2659 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2660 &release_sync_point
,
2662 &mailbox_task_runner
));
2664 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2665 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2667 ResourceProvider::ResourceId id
=
2668 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2672 Mock::VerifyAndClearExpectations(context
);
2675 // Mailbox sync point WaitSyncPoint before using the texture.
2676 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2677 resource_provider
->WaitSyncPointIfNeeded(id
);
2678 Mock::VerifyAndClearExpectations(context
);
2680 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2681 .WillOnce(Return(texture_id
));
2682 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2684 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2685 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2687 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2688 // match |sampler_filter|.
2689 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2690 EXPECT_CALL(*context
, texParameteri(
2691 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2692 EXPECT_CALL(*context
, texParameteri(
2693 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2696 ResourceProvider::ScopedSamplerGL
lock(
2697 resource_provider
.get(), id
, sampler_filter
);
2698 Mock::VerifyAndClearExpectations(context
);
2700 // When done with it, a sync point should be inserted, but no produce is
2702 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2703 EXPECT_CALL(*context
, insertSyncPoint());
2704 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2706 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2707 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2710 resource_provider
->DeleteResource(id
);
2711 EXPECT_EQ(0u, release_sync_point
);
2712 EXPECT_FALSE(lost_resource
);
2713 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2717 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2718 // Mailboxing is only supported for GL textures.
2719 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2722 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2723 shared_bitmap_manager_
.get(),
2724 gpu_memory_buffer_manager_
.get(),
2725 main_thread_task_runner_
.get(),
2730 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2731 // Mailboxing is only supported for GL textures.
2732 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2735 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2736 shared_bitmap_manager_
.get(),
2737 gpu_memory_buffer_manager_
.get(),
2738 main_thread_task_runner_
.get(),
2743 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2744 // Mailboxing is only supported for GL textures.
2745 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2748 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2749 shared_bitmap_manager_
.get(),
2750 gpu_memory_buffer_manager_
.get(),
2751 main_thread_task_runner_
.get(),
2756 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2757 // Mailboxing is only supported for GL textures.
2758 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2761 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2762 shared_bitmap_manager_
.get(),
2763 gpu_memory_buffer_manager_
.get(),
2764 main_thread_task_runner_
.get(),
2769 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2770 // Mailboxing is only supported for GL textures.
2771 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2774 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2775 new TextureStateTrackingContext
);
2776 TextureStateTrackingContext
* context
= context_owned
.get();
2778 FakeOutputSurfaceClient output_surface_client
;
2779 scoped_ptr
<OutputSurface
> output_surface(
2780 FakeOutputSurface::Create3d(context_owned
.Pass()));
2781 CHECK(output_surface
->BindToClient(&output_surface_client
));
2783 scoped_ptr
<ResourceProvider
> resource_provider(
2784 ResourceProvider::Create(output_surface
.get(),
2785 shared_bitmap_manager_
.get(),
2786 gpu_memory_buffer_manager_
.get(),
2792 uint32 sync_point
= 30;
2793 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2795 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2796 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2797 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2798 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2799 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2801 gpu::Mailbox gpu_mailbox
;
2802 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2803 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2804 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2806 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2808 ResourceProvider::ResourceId id
=
2809 resource_provider
->CreateResourceFromTextureMailbox(
2810 mailbox
, callback
.Pass());
2813 Mock::VerifyAndClearExpectations(context
);
2816 // Mailbox sync point WaitSyncPoint before using the texture.
2817 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2818 resource_provider
->WaitSyncPointIfNeeded(id
);
2819 Mock::VerifyAndClearExpectations(context
);
2821 unsigned texture_id
= 1;
2823 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2824 .WillOnce(Return(texture_id
));
2826 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2827 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2829 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2830 Mock::VerifyAndClearExpectations(context
);
2832 // When done with it, a sync point should be inserted, but no produce is
2834 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2835 EXPECT_CALL(*context
, insertSyncPoint());
2836 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2838 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2839 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2843 TEST_P(ResourceProviderTest
,
2844 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2845 // Mailboxing is only supported for GL textures.
2846 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2849 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2850 new TextureStateTrackingContext
);
2851 TextureStateTrackingContext
* context
= context_owned
.get();
2853 FakeOutputSurfaceClient output_surface_client
;
2854 scoped_ptr
<OutputSurface
> output_surface(
2855 FakeOutputSurface::Create3d(context_owned
.Pass()));
2856 CHECK(output_surface
->BindToClient(&output_surface_client
));
2858 scoped_ptr
<ResourceProvider
> resource_provider(
2859 ResourceProvider::Create(output_surface
.get(),
2860 shared_bitmap_manager_
.get(),
2861 gpu_memory_buffer_manager_
.get(),
2867 uint32 sync_point
= 30;
2868 unsigned target
= GL_TEXTURE_2D
;
2870 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2871 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2872 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2873 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2874 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2876 gpu::Mailbox gpu_mailbox
;
2877 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2878 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2879 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2881 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2883 ResourceProvider::ResourceId id
=
2884 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2888 Mock::VerifyAndClearExpectations(context
);
2891 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2892 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2893 resource_provider
->WaitSyncPointIfNeeded(id
);
2894 Mock::VerifyAndClearExpectations(context
);
2896 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2897 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2898 resource_provider
->WaitSyncPointIfNeeded(id
);
2899 Mock::VerifyAndClearExpectations(context
);
2903 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2904 // Mailboxing is only supported for GL textures.
2905 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2908 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2909 new TextureStateTrackingContext
);
2910 TextureStateTrackingContext
* context
= context_owned
.get();
2912 FakeOutputSurfaceClient output_surface_client
;
2913 scoped_ptr
<OutputSurface
> output_surface(
2914 FakeOutputSurface::Create3d(context_owned
.Pass()));
2915 CHECK(output_surface
->BindToClient(&output_surface_client
));
2917 scoped_ptr
<ResourceProvider
> resource_provider(
2918 ResourceProvider::Create(output_surface
.get(),
2919 shared_bitmap_manager_
.get(),
2920 gpu_memory_buffer_manager_
.get(),
2926 uint32 sync_point
= 0;
2927 unsigned target
= GL_TEXTURE_2D
;
2929 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2930 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2931 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2932 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2933 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2935 gpu::Mailbox gpu_mailbox
;
2936 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2937 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2938 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2940 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2942 ResourceProvider::ResourceId id
=
2943 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2947 Mock::VerifyAndClearExpectations(context
);
2950 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2951 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2952 resource_provider
->WaitSyncPointIfNeeded(id
);
2953 Mock::VerifyAndClearExpectations(context
);
2957 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2959 MOCK_METHOD0(NextTextureId
, GLuint());
2960 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2961 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2962 MOCK_METHOD5(texStorage2DEXT
,
2965 GLuint internalformat
,
2968 MOCK_METHOD9(texImage2D
,
2971 GLenum internalformat
,
2977 const void* pixels
));
2978 MOCK_METHOD9(texSubImage2D
,
2987 const void* pixels
));
2988 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2991 GLenum internalformat
,
2997 const void* pixels
));
2998 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3007 const void* pixels
));
3008 MOCK_METHOD8(compressedTexImage2D
,
3011 GLenum internalformat
,
3017 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3018 MOCK_METHOD4(createImageCHROMIUM
,
3019 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3020 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3021 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3022 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3024 // We're mocking bindTexture, so we override
3025 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3026 // currently bound texture.
3027 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3030 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3031 // Only for GL textures.
3032 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3034 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3035 new StrictMock
<AllocationTrackingContext3D
>);
3036 AllocationTrackingContext3D
* context
= context_owned
.get();
3038 FakeOutputSurfaceClient output_surface_client
;
3039 scoped_ptr
<OutputSurface
> output_surface(
3040 FakeOutputSurface::Create3d(context_owned
.Pass()));
3041 CHECK(output_surface
->BindToClient(&output_surface_client
));
3043 scoped_ptr
<ResourceProvider
> resource_provider(
3044 ResourceProvider::Create(output_surface
.get(),
3045 shared_bitmap_manager_
.get(),
3046 gpu_memory_buffer_manager_
.get(),
3052 gfx::Size
size(2, 2);
3053 gfx::Vector2d
offset(0, 0);
3054 ResourceFormat format
= RGBA_8888
;
3055 ResourceProvider::ResourceId id
= 0;
3056 uint8_t pixels
[16] = { 0 };
3057 int texture_id
= 123;
3059 // Lazy allocation. Don't allocate when creating the resource.
3060 id
= resource_provider
->CreateResource(
3061 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3063 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3064 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3065 resource_provider
->CreateForTesting(id
);
3067 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3068 resource_provider
->DeleteResource(id
);
3070 Mock::VerifyAndClearExpectations(context
);
3072 // Do allocate when we set the pixels.
3073 id
= resource_provider
->CreateResource(
3074 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3076 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3077 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3078 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3079 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3080 resource_provider
->CopyToResource(id
, pixels
, size
);
3082 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3083 resource_provider
->DeleteResource(id
);
3085 Mock::VerifyAndClearExpectations(context
);
3087 // Same for async version.
3088 id
= resource_provider
->CreateResource(
3089 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3090 resource_provider
->AcquirePixelBuffer(id
);
3092 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3093 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3094 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3096 resource_provider
->BeginSetPixels(id
);
3097 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3099 resource_provider
->ReleasePixelBuffer(id
);
3101 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3102 resource_provider
->DeleteResource(id
);
3104 Mock::VerifyAndClearExpectations(context
);
3107 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3108 // Only for GL textures.
3109 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3111 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3112 new StrictMock
<AllocationTrackingContext3D
>);
3113 AllocationTrackingContext3D
* context
= context_owned
.get();
3114 context
->set_support_texture_storage(true);
3115 context
->set_support_texture_usage(true);
3117 FakeOutputSurfaceClient output_surface_client
;
3118 scoped_ptr
<OutputSurface
> output_surface(
3119 FakeOutputSurface::Create3d(context_owned
.Pass()));
3120 CHECK(output_surface
->BindToClient(&output_surface_client
));
3122 scoped_ptr
<ResourceProvider
> resource_provider(
3123 ResourceProvider::Create(output_surface
.get(),
3124 shared_bitmap_manager_
.get(),
3125 gpu_memory_buffer_manager_
.get(),
3131 gfx::Size
size(2, 2);
3133 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3134 const ResourceProvider::TextureHint hints
[4] = {
3135 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3136 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3137 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3138 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3140 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3141 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3142 // Lazy allocation. Don't allocate when creating the resource.
3143 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3144 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3146 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3147 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3148 bool is_immutable_hint
=
3149 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3150 bool support_immutable_texture
=
3151 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3152 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3153 .Times(support_immutable_texture
? 1 : 0);
3154 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3155 .Times(support_immutable_texture
? 0 : 1);
3156 resource_provider
->AllocateForTesting(id
);
3158 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3159 resource_provider
->DeleteResource(id
);
3161 Mock::VerifyAndClearExpectations(context
);
3166 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3167 // Only for GL textures.
3168 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3170 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3171 new StrictMock
<AllocationTrackingContext3D
>);
3172 AllocationTrackingContext3D
* context
= context_owned
.get();
3173 context
->set_support_texture_format_bgra8888(true);
3174 context
->set_support_texture_storage(true);
3175 context
->set_support_texture_usage(true);
3177 FakeOutputSurfaceClient output_surface_client
;
3178 scoped_ptr
<OutputSurface
> output_surface(
3179 FakeOutputSurface::Create3d(context_owned
.Pass()));
3180 CHECK(output_surface
->BindToClient(&output_surface_client
));
3182 scoped_ptr
<ResourceProvider
> resource_provider(
3183 ResourceProvider::Create(output_surface
.get(),
3184 shared_bitmap_manager_
.get(),
3185 gpu_memory_buffer_manager_
.get(),
3191 gfx::Size
size(2, 2);
3192 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3194 const ResourceProvider::TextureHint hints
[4] = {
3195 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3196 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3197 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3198 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3200 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3201 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3202 // Lazy allocation. Don't allocate when creating the resource.
3203 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3204 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3206 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3207 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3208 bool is_immutable_hint
=
3209 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3210 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3211 .Times(is_immutable_hint
? 1 : 0);
3212 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3213 .Times(is_immutable_hint
? 0 : 1);
3214 resource_provider
->AllocateForTesting(id
);
3216 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3217 resource_provider
->DeleteResource(id
);
3219 Mock::VerifyAndClearExpectations(context
);
3224 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3225 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3227 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3228 new StrictMock
<AllocationTrackingContext3D
>);
3229 AllocationTrackingContext3D
* context
= context_owned
.get();
3231 FakeOutputSurfaceClient output_surface_client
;
3232 scoped_ptr
<OutputSurface
> output_surface(
3233 FakeOutputSurface::Create3d(context_owned
.Pass()));
3234 CHECK(output_surface
->BindToClient(&output_surface_client
));
3236 gfx::Size
size(2, 2);
3237 ResourceFormat format
= RGBA_8888
;
3238 ResourceProvider::ResourceId id
= 0;
3239 int texture_id
= 123;
3241 scoped_ptr
<ResourceProvider
> resource_provider(
3242 ResourceProvider::Create(output_surface
.get(),
3243 shared_bitmap_manager_
.get(),
3244 gpu_memory_buffer_manager_
.get(),
3250 id
= resource_provider
->CreateResource(
3251 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3252 resource_provider
->AcquirePixelBuffer(id
);
3254 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3255 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3256 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3258 resource_provider
->BeginSetPixels(id
);
3260 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3262 resource_provider
->ReleasePixelBuffer(id
);
3264 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3265 resource_provider
->DeleteResource(id
);
3267 Mock::VerifyAndClearExpectations(context
);
3270 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3271 // Only for GL textures.
3272 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3274 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3275 new StrictMock
<AllocationTrackingContext3D
>);
3276 AllocationTrackingContext3D
* context
= context_owned
.get();
3278 FakeOutputSurfaceClient output_surface_client
;
3279 scoped_ptr
<OutputSurface
> output_surface(
3280 FakeOutputSurface::Create3d(context_owned
.Pass()));
3281 CHECK(output_surface
->BindToClient(&output_surface_client
));
3283 gfx::Size
size(2, 2);
3284 ResourceFormat format
= RGBA_8888
;
3285 ResourceProvider::ResourceId id
= 0;
3286 int texture_id
= 123;
3288 scoped_ptr
<ResourceProvider
> resource_provider(
3289 ResourceProvider::Create(output_surface
.get(),
3290 shared_bitmap_manager_
.get(),
3291 gpu_memory_buffer_manager_
.get(),
3297 id
= resource_provider
->CreateResource(
3298 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3299 resource_provider
->AcquirePixelBuffer(id
);
3301 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3302 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3303 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3305 resource_provider
->BeginSetPixels(id
);
3307 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3308 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3309 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3310 resource_provider
->ForceSetPixelsToComplete(id
);
3312 resource_provider
->ReleasePixelBuffer(id
);
3314 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3315 resource_provider
->DeleteResource(id
);
3317 Mock::VerifyAndClearExpectations(context
);
3320 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3321 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3322 new NiceMock
<AllocationTrackingContext3D
>);
3323 AllocationTrackingContext3D
* context
= context_owned
.get();
3325 FakeOutputSurfaceClient output_surface_client
;
3326 scoped_ptr
<OutputSurface
> output_surface(
3327 FakeOutputSurface::Create3d(context_owned
.Pass()));
3328 CHECK(output_surface
->BindToClient(&output_surface_client
));
3330 gfx::Size
size(2, 2);
3331 ResourceFormat format
= RGBA_8888
;
3332 ResourceProvider::ResourceId id
= 0;
3333 int texture_id
= 123;
3335 scoped_ptr
<ResourceProvider
> resource_provider(
3336 ResourceProvider::Create(output_surface
.get(),
3337 shared_bitmap_manager_
.get(),
3338 gpu_memory_buffer_manager_
.get(),
3344 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3346 id
= resource_provider
->CreateResource(
3347 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3348 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3349 GL_INNOCENT_CONTEXT_RESET_ARB
);
3351 resource_provider
->AcquirePixelBuffer(id
);
3353 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3354 EXPECT_FALSE(buffer
);
3355 resource_provider
->UnmapPixelBuffer(id
);
3356 Mock::VerifyAndClearExpectations(context
);
3359 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3360 // Only for GL textures.
3361 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3363 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3364 new StrictMock
<AllocationTrackingContext3D
>);
3365 AllocationTrackingContext3D
* context
= context_owned
.get();
3367 FakeOutputSurfaceClient output_surface_client
;
3368 scoped_ptr
<OutputSurface
> output_surface(
3369 FakeOutputSurface::Create3d(context_owned
.Pass()));
3370 CHECK(output_surface
->BindToClient(&output_surface_client
));
3372 const int kWidth
= 2;
3373 const int kHeight
= 2;
3374 gfx::Size
size(kWidth
, kHeight
);
3375 ResourceFormat format
= RGBA_8888
;
3376 ResourceProvider::ResourceId id
= 0;
3377 const unsigned kTextureId
= 123u;
3378 const unsigned kImageId
= 234u;
3380 scoped_ptr
<ResourceProvider
> resource_provider(
3381 ResourceProvider::Create(output_surface
.get(),
3382 shared_bitmap_manager_
.get(),
3383 gpu_memory_buffer_manager_
.get(),
3389 id
= resource_provider
->CreateResource(
3390 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3392 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3393 .WillOnce(Return(kImageId
))
3394 .RetiresOnSaturation();
3396 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3397 resource_provider
.get(), id
);
3398 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3401 EXPECT_CALL(*context
, NextTextureId())
3402 .WillOnce(Return(kTextureId
))
3403 .RetiresOnSaturation();
3404 // Once in CreateTextureId and once in BindForSampling
3405 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3406 .RetiresOnSaturation();
3407 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3409 .RetiresOnSaturation();
3411 ResourceProvider::ScopedSamplerGL
lock_gl(
3412 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3413 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3417 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3418 resource_provider
.get(), id
);
3419 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3422 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3429 .RetiresOnSaturation();
3430 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3432 .RetiresOnSaturation();
3434 ResourceProvider::ScopedSamplerGL
lock_gl(
3435 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3436 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3439 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3441 .RetiresOnSaturation();
3444 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3445 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3447 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3448 new StrictMock
<AllocationTrackingContext3D
>);
3449 AllocationTrackingContext3D
* context
= context_owned
.get();
3450 context_owned
->set_support_sync_query(true);
3452 FakeOutputSurfaceClient output_surface_client
;
3453 scoped_ptr
<OutputSurface
> output_surface(
3454 FakeOutputSurface::Create3d(context_owned
.Pass()));
3455 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3457 const int kWidth
= 2;
3458 const int kHeight
= 2;
3459 gfx::Size
size(kWidth
, kHeight
);
3460 ResourceFormat format
= RGBA_8888
;
3461 ResourceProvider::ResourceId source_id
= 0;
3462 ResourceProvider::ResourceId dest_id
= 0;
3463 const unsigned kSourceTextureId
= 123u;
3464 const unsigned kDestTextureId
= 321u;
3465 const unsigned kImageId
= 234u;
3467 scoped_ptr
<ResourceProvider
> resource_provider(
3468 ResourceProvider::Create(output_surface
.get(),
3469 shared_bitmap_manager_
.get(),
3470 gpu_memory_buffer_manager_
.get(),
3476 source_id
= resource_provider
->CreateResource(
3477 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3479 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3480 .WillOnce(Return(kImageId
))
3481 .RetiresOnSaturation();
3483 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3484 resource_provider
.get(), source_id
);
3485 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3487 Mock::VerifyAndClearExpectations(context
);
3489 dest_id
= resource_provider
->CreateResource(
3490 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3492 EXPECT_CALL(*context
, NextTextureId())
3493 .WillOnce(Return(kDestTextureId
))
3494 .RetiresOnSaturation();
3495 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3497 .RetiresOnSaturation();
3498 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3499 GL_UNSIGNED_BYTE
, nullptr))
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context
, NextTextureId())
3503 .WillOnce(Return(kSourceTextureId
))
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3507 .RetiresOnSaturation();
3508 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3510 .RetiresOnSaturation();
3511 resource_provider
->CopyResource(source_id
, dest_id
);
3512 Mock::VerifyAndClearExpectations(context
);
3514 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3516 .RetiresOnSaturation();
3517 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3519 .RetiresOnSaturation();
3520 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3522 .RetiresOnSaturation();
3523 resource_provider
->DeleteResource(source_id
);
3524 resource_provider
->DeleteResource(dest_id
);
3527 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3528 ResourceProvider
* resource_provider
,
3529 FakeOutputSurface
* output_surface
) {
3530 scoped_ptr
<ResourceProviderContext
> context_owned
=
3531 ResourceProviderContext::Create(shared_data
);
3532 ResourceProviderContext
* context
= context_owned
.get();
3534 scoped_refptr
<TestContextProvider
> context_provider
=
3535 TestContextProvider::Create(context_owned
.Pass());
3536 output_surface
->InitializeAndSetContext3d(context_provider
, nullptr);
3537 resource_provider
->InitializeGL();
3539 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3540 resource_provider
, context
);
3543 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3544 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3545 bool delegated_rendering
= false;
3546 scoped_ptr
<FakeOutputSurface
> output_surface(
3547 FakeOutputSurface::CreateDeferredGL(
3548 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3549 delegated_rendering
));
3550 FakeOutputSurfaceClient
client(output_surface
.get());
3551 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3552 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3553 new TestSharedBitmapManager());
3554 scoped_ptr
<ResourceProvider
> resource_provider(
3555 ResourceProvider::Create(output_surface
.get(),
3556 shared_bitmap_manager
.get(),
3563 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP
,
3564 resource_provider
.get(), NULL
);
3566 InitializeGLAndCheck(shared_data
.get(),
3567 resource_provider
.get(),
3568 output_surface
.get());
3570 resource_provider
->InitializeSoftware();
3571 output_surface
->ReleaseGL();
3572 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP
,
3573 resource_provider
.get(), NULL
);
3575 InitializeGLAndCheck(shared_data
.get(),
3576 resource_provider
.get(),
3577 output_surface
.get());
3580 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3581 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3584 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3585 new AllocationTrackingContext3D
);
3586 AllocationTrackingContext3D
* context
= context_owned
.get();
3587 context_owned
->set_support_compressed_texture_etc1(true);
3589 FakeOutputSurfaceClient output_surface_client
;
3590 scoped_ptr
<OutputSurface
> output_surface(
3591 FakeOutputSurface::Create3d(context_owned
.Pass()));
3592 CHECK(output_surface
->BindToClient(&output_surface_client
));
3594 gfx::Size
size(4, 4);
3595 scoped_ptr
<ResourceProvider
> resource_provider(
3596 ResourceProvider::Create(output_surface
.get(),
3597 shared_bitmap_manager_
.get(),
3598 gpu_memory_buffer_manager_
.get(),
3603 int texture_id
= 123;
3605 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3606 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3608 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3609 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3610 resource_provider
->AllocateForTesting(id
);
3612 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3613 resource_provider
->DeleteResource(id
);
3616 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3617 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3620 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3621 new AllocationTrackingContext3D
);
3622 AllocationTrackingContext3D
* context
= context_owned
.get();
3623 context_owned
->set_support_compressed_texture_etc1(true);
3625 FakeOutputSurfaceClient output_surface_client
;
3626 scoped_ptr
<OutputSurface
> output_surface(
3627 FakeOutputSurface::Create3d(context_owned
.Pass()));
3628 CHECK(output_surface
->BindToClient(&output_surface_client
));
3630 gfx::Size
size(4, 4);
3631 scoped_ptr
<ResourceProvider
> resource_provider(
3632 ResourceProvider::Create(output_surface
.get(),
3633 shared_bitmap_manager_
.get(),
3634 gpu_memory_buffer_manager_
.get(),
3639 int texture_id
= 123;
3642 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3643 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3645 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3646 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3647 EXPECT_CALL(*context
,
3648 compressedTexImage2D(
3649 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3650 resource_provider
->CopyToResource(id
, pixels
, size
);
3652 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3653 resource_provider
->DeleteResource(id
);
3656 INSTANTIATE_TEST_CASE_P(
3657 ResourceProviderTests
,
3658 ResourceProviderTest
,
3659 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3660 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3662 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3664 GLuint
NextTextureId() override
{
3665 base::AutoLock
lock(namespace_
->lock
);
3666 return namespace_
->next_texture_id
++;
3668 void RetireTextureId(GLuint
) override
{}
3669 GLuint
PeekTextureId() {
3670 base::AutoLock
lock(namespace_
->lock
);
3671 return namespace_
->next_texture_id
;
3675 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3676 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3677 new TextureIdAllocationTrackingContext
);
3678 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3680 FakeOutputSurfaceClient output_surface_client
;
3681 scoped_ptr
<OutputSurface
> output_surface(
3682 FakeOutputSurface::Create3d(context_owned
.Pass()));
3683 CHECK(output_surface
->BindToClient(&output_surface_client
));
3684 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3685 new TestSharedBitmapManager());
3687 gfx::Size
size(1, 1);
3688 ResourceFormat format
= RGBA_8888
;
3691 size_t kTextureAllocationChunkSize
= 1;
3692 scoped_ptr
<ResourceProvider
> resource_provider(
3693 ResourceProvider::Create(output_surface
.get(),
3694 shared_bitmap_manager
.get(),
3699 kTextureAllocationChunkSize
));
3701 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3702 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3704 resource_provider
->AllocateForTesting(id
);
3705 Mock::VerifyAndClearExpectations(context
);
3707 DCHECK_EQ(2u, context
->PeekTextureId());
3708 resource_provider
->DeleteResource(id
);
3712 size_t kTextureAllocationChunkSize
= 8;
3713 scoped_ptr
<ResourceProvider
> resource_provider(
3714 ResourceProvider::Create(output_surface
.get(),
3715 shared_bitmap_manager
.get(),
3720 kTextureAllocationChunkSize
));
3722 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3723 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3725 resource_provider
->AllocateForTesting(id
);
3726 Mock::VerifyAndClearExpectations(context
);
3728 DCHECK_EQ(10u, context
->PeekTextureId());
3729 resource_provider
->DeleteResource(id
);