1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
56 BlockingTaskRunner
* main_thread_task_runner
) {
57 *release_sync_point
= sync_point
;
58 *release_lost_resource
= lost_resource
;
59 *release_main_thread_task_runner
= main_thread_task_runner
;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr
<SharedBitmap
> bitmap
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr
<SharedBitmap
> shared_bitmap
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<SharedBitmap
> CreateAndFillSharedBitmap(
83 SharedBitmapManager
* manager
,
84 const gfx::Size
& size
,
86 scoped_ptr
<SharedBitmap
> shared_bitmap
= manager
->AllocateSharedBitmap(size
);
88 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_bitmap
->pixels());
90 std::fill_n(pixels
, size
.GetArea(), value
);
91 return shared_bitmap
.Pass();
94 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
96 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
97 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
98 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
99 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
100 MOCK_METHOD2(produceTextureCHROMIUM
,
101 void(GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(consumeTextureCHROMIUM
,
103 void(GLenum target
, const GLbyte
* mailbox
));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint
NextTextureId() override
{
108 base::AutoLock
lock(namespace_
->lock
);
109 return namespace_
->next_texture_id
++;
111 void RetireTextureId(GLuint
) override
{}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData
{
118 static scoped_ptr
<ContextSharedData
> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32
InsertSyncPoint() { return next_sync_point_
++; }
124 void GenMailbox(GLbyte
* mailbox
) {
125 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
126 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
130 void ProduceTexture(const GLbyte
* mailbox_name
,
132 scoped_refptr
<TestTexture
> texture
) {
133 unsigned mailbox
= 0;
134 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
135 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
136 textures_
[mailbox
] = texture
;
137 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
138 sync_point_for_mailbox_
[mailbox
] = sync_point
;
141 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
143 unsigned mailbox
= 0;
144 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
145 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
150 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
152 return scoped_refptr
<TestTexture
>();
154 return textures_
[mailbox
];
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_
;
161 unsigned next_mailbox_
;
162 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
163 TextureMap textures_
;
164 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
167 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
169 static scoped_ptr
<ResourceProviderContext
> Create(
170 ContextSharedData
* shared_data
) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
174 GLuint
insertSyncPoint() override
{
175 uint32 sync_point
= shared_data_
->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it
=
179 pending_produce_textures_
.begin();
180 it
!= pending_produce_textures_
.end();
182 shared_data_
->ProduceTexture(
183 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
185 pending_produce_textures_
.clear();
189 void waitSyncPoint(GLuint sync_point
) override
{
190 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
195 void texStorage2DEXT(GLenum target
,
197 GLuint internalformat
,
199 GLint height
) override
{
200 CheckTextureIsBound(target
);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
202 ASSERT_EQ(1, levels
);
203 GLenum format
= GL_RGBA
;
204 switch (internalformat
) {
208 format
= GL_BGRA_EXT
;
213 AllocateTexture(gfx::Size(width
, height
), format
);
216 void texImage2D(GLenum target
,
218 GLenum internalformat
,
224 const void* pixels
) override
{
225 CheckTextureIsBound(target
);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
228 ASSERT_EQ(internalformat
, format
);
229 ASSERT_FALSE(border
);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
231 AllocateTexture(gfx::Size(width
, height
), format
);
233 SetPixels(0, 0, width
, height
, pixels
);
236 void texSubImage2D(GLenum target
,
244 const void* pixels
) override
{
245 CheckTextureIsBound(target
);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
250 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
254 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
257 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
258 return shared_data_
->GenMailbox(mailbox
);
261 void produceTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
262 CheckTextureIsBound(target
);
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= BoundTexture(target
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 void consumeTextureCHROMIUM(GLenum target
, const GLbyte
* mailbox
) override
{
275 CheckTextureIsBound(target
);
276 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
277 scoped_refptr
<TestTexture
> texture
=
278 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
279 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
282 void GetPixels(const gfx::Size
& size
,
283 ResourceFormat format
,
285 CheckTextureIsBound(GL_TEXTURE_2D
);
286 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
287 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
288 ASSERT_EQ(texture
->size
, size
);
289 ASSERT_EQ(texture
->format
, format
);
290 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
294 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
295 : shared_data_(shared_data
),
296 last_waited_sync_point_(0) {}
299 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
300 CheckTextureIsBound(GL_TEXTURE_2D
);
301 ResourceFormat texture_format
= RGBA_8888
;
304 texture_format
= RGBA_8888
;
307 texture_format
= BGRA_8888
;
310 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
311 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
314 void SetPixels(int xoffset
,
318 const void* pixels
) {
319 CheckTextureIsBound(GL_TEXTURE_2D
);
320 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
321 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
322 ASSERT_TRUE(texture
->data
.get());
323 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
324 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
326 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
328 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
329 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
330 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
331 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
332 for (int i
= 0; i
< height
; ++i
) {
333 memcpy(dest
, src
, in_pitch
);
339 struct PendingProduceTexture
{
340 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
341 scoped_refptr
<TestTexture
> texture
;
343 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
344 ContextSharedData
* shared_data_
;
345 GLuint last_waited_sync_point_
;
346 PendingProduceTextureList pending_produce_textures_
;
349 void GetResourcePixels(ResourceProvider
* resource_provider
,
350 ResourceProviderContext
* context
,
351 ResourceProvider::ResourceId id
,
352 const gfx::Size
& size
,
353 ResourceFormat format
,
355 resource_provider
->WaitSyncPointIfNeeded(id
);
356 switch (resource_provider
->default_resource_type()) {
357 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
358 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
359 ASSERT_NE(0U, lock_gl
.texture_id());
360 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
361 context
->GetPixels(size
, format
, pixels
);
364 case ResourceProvider::RESOURCE_TYPE_BITMAP
: {
365 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
368 lock_software
.sk_bitmap()->getPixels(),
369 lock_software
.sk_bitmap()->getSize());
372 case ResourceProvider::RESOURCE_TYPE_INVALID
:
378 class ResourceProviderTest
379 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
381 ResourceProviderTest()
382 : shared_data_(ContextSharedData::Create()),
384 child_context_(NULL
),
385 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
386 switch (GetParam()) {
387 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
388 scoped_ptr
<ResourceProviderContext
> context3d(
389 ResourceProviderContext::Create(shared_data_
.get()));
390 context3d_
= context3d
.get();
392 scoped_refptr
<TestContextProvider
> context_provider
=
393 TestContextProvider::Create(context3d
.Pass());
395 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
397 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
398 ResourceProviderContext::Create(shared_data_
.get());
399 child_context_
= child_context_owned
.get();
400 child_output_surface_
=
401 FakeOutputSurface::Create3d(child_context_owned
.Pass());
404 case ResourceProvider::RESOURCE_TYPE_BITMAP
:
405 output_surface_
= FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice
));
407 child_output_surface_
= FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice
));
410 case ResourceProvider::RESOURCE_TYPE_INVALID
:
414 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
415 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
417 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
418 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
421 ResourceProvider::Create(output_surface_
.get(),
422 shared_bitmap_manager_
.get(),
423 gpu_memory_buffer_manager_
.get(),
424 main_thread_task_runner_
.get(),
428 child_resource_provider_
=
429 ResourceProvider::Create(child_output_surface_
.get(),
430 shared_bitmap_manager_
.get(),
431 gpu_memory_buffer_manager_
.get(),
432 main_thread_task_runner_
.get(),
438 static void CollectResources(ReturnedResourceArray
* array
,
439 const ReturnedResourceArray
& returned
,
440 BlockingTaskRunner
* main_thread_task_runner
) {
441 array
->insert(array
->end(), returned
.begin(), returned
.end());
444 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
445 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
448 static void SetResourceFilter(ResourceProvider
* resource_provider
,
449 ResourceProvider::ResourceId id
,
451 ResourceProvider::ScopedSamplerGL
sampler(
452 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
455 ResourceProviderContext
* context() { return context3d_
; }
457 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
459 bool* release_called
,
460 uint32
* sync_point
) {
461 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
462 unsigned texture
= child_context_
->createTexture();
463 gpu::Mailbox gpu_mailbox
;
464 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
465 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
466 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
467 *sync_point
= child_context_
->insertSyncPoint();
468 EXPECT_LT(0u, *sync_point
);
470 scoped_ptr
<SharedBitmap
> shared_bitmap
;
471 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
472 SingleReleaseCallbackImpl::Create(base::Bind(
473 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
474 release_called
, release_sync_point
, lost_resource
));
475 return child_resource_provider_
->CreateResourceFromTextureMailbox(
476 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
479 gfx::Size
size(64, 64);
480 scoped_ptr
<SharedBitmap
> shared_bitmap(
481 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
483 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
484 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
485 SingleReleaseCallbackImpl::Create(base::Bind(
486 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
487 release_called
, release_sync_point
, lost_resource
));
488 return child_resource_provider_
->CreateResourceFromTextureMailbox(
489 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
494 scoped_ptr
<ContextSharedData
> shared_data_
;
495 ResourceProviderContext
* context3d_
;
496 ResourceProviderContext
* child_context_
;
497 FakeOutputSurfaceClient output_surface_client_
;
498 FakeOutputSurfaceClient child_output_surface_client_
;
499 scoped_ptr
<OutputSurface
> output_surface_
;
500 scoped_ptr
<OutputSurface
> child_output_surface_
;
501 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
502 scoped_ptr
<ResourceProvider
> resource_provider_
;
503 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
504 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
505 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
508 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
509 ResourceProvider
* resource_provider
,
510 ResourceProviderContext
* context
) {
511 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
513 gfx::Size
size(1, 1);
514 ResourceFormat format
= RGBA_8888
;
515 size_t pixel_size
= TextureSizeBytes(size
, format
);
516 ASSERT_EQ(4U, pixel_size
);
518 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
519 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
520 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
521 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
522 EXPECT_EQ(0u, context
->NumTextures());
524 uint8_t data
[4] = { 1, 2, 3, 4 };
525 resource_provider
->CopyToResource(id
, data
, size
);
526 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
527 EXPECT_EQ(1u, context
->NumTextures());
529 uint8_t result
[4] = { 0 };
530 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
531 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
533 resource_provider
->DeleteResource(id
);
534 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
535 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
536 EXPECT_EQ(0u, context
->NumTextures());
539 TEST_P(ResourceProviderTest
, Basic
) {
540 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
543 TEST_P(ResourceProviderTest
, Upload
) {
544 gfx::Size
size(2, 2);
545 ResourceFormat format
= RGBA_8888
;
546 size_t pixel_size
= TextureSizeBytes(size
, format
);
547 ASSERT_EQ(16U, pixel_size
);
549 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
550 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
552 uint8_t image
[16] = { 0 };
553 gfx::Rect
image_rect(size
);
554 resource_provider_
->SetPixels(
555 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
557 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
560 uint8_t result
[16] = { 0 };
562 gfx::Rect
source_rect(0, 0, 1, 1);
563 gfx::Vector2d
dest_offset(0, 0);
564 resource_provider_
->SetPixels(
565 id
, image
, image_rect
, source_rect
, dest_offset
);
567 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
569 resource_provider_
.get(), context(), id
, size
, format
, result
);
570 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
573 gfx::Rect
source_rect(0, 0, 1, 1);
574 gfx::Vector2d
dest_offset(1, 1);
575 resource_provider_
->SetPixels(
576 id
, image
, image_rect
, source_rect
, dest_offset
);
578 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
580 resource_provider_
.get(), context(), id
, size
, format
, result
);
581 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
584 gfx::Rect
source_rect(1, 0, 1, 1);
585 gfx::Vector2d
dest_offset(0, 1);
586 resource_provider_
->SetPixels(
587 id
, image
, image_rect
, source_rect
, dest_offset
);
589 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
591 resource_provider_
.get(), context(), id
, size
, format
, result
);
592 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
595 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
596 gfx::Rect
source_rect(100, 100, 1, 1);
597 gfx::Vector2d
dest_offset(1, 0);
598 resource_provider_
->SetPixels(
599 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
601 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
603 resource_provider_
.get(), context(), id
, size
, format
, result
);
604 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
607 resource_provider_
->DeleteResource(id
);
610 TEST_P(ResourceProviderTest
, SimpleUpload
) {
611 gfx::Size
size(2, 2);
612 ResourceFormat format
= RGBA_8888
;
613 size_t pixel_size
= TextureSizeBytes(size
, format
);
614 ASSERT_EQ(16U, pixel_size
);
616 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
617 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
619 uint8_t image
[16] = {0};
620 resource_provider_
->CopyToResource(id
, image
, size
);
622 uint8_t result
[16] = {0};
623 uint8_t expected
[16] = {0};
624 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
626 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
629 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
631 resource_provider_
->CopyToResource(id
, image
, size
);
633 uint8_t result
[16] = {0};
634 uint8_t expected
[16] = {
635 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
636 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
638 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
642 TEST_P(ResourceProviderTest
, TransferGLResources
) {
643 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
645 gfx::Size
size(1, 1);
646 ResourceFormat format
= RGBA_8888
;
647 size_t pixel_size
= TextureSizeBytes(size
, format
);
648 ASSERT_EQ(4U, pixel_size
);
650 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
651 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
652 uint8_t data1
[4] = { 1, 2, 3, 4 };
653 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
655 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
656 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
657 uint8_t data2
[4] = { 5, 5, 5, 5 };
658 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
660 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
661 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
663 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
664 child_resource_provider_
.get(), id3
);
665 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
668 GLuint external_texture_id
= child_context_
->createExternalTexture();
669 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
671 gpu::Mailbox external_mailbox
;
672 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
673 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
674 external_mailbox
.name
);
675 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
676 ResourceProvider::ResourceId id4
=
677 child_resource_provider_
->CreateResourceFromTextureMailbox(
679 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
680 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
682 ReturnedResourceArray returned_to_child
;
684 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
686 // Transfer some resources to the parent.
687 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
688 resource_ids_to_transfer
.push_back(id1
);
689 resource_ids_to_transfer
.push_back(id2
);
690 resource_ids_to_transfer
.push_back(id3
);
691 resource_ids_to_transfer
.push_back(id4
);
692 TransferableResourceArray list
;
693 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
695 ASSERT_EQ(4u, list
.size());
696 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
697 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
698 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
699 list
[1].mailbox_holder
.sync_point
);
700 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
701 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
702 list
[2].mailbox_holder
.sync_point
);
703 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
704 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
705 list
[0].mailbox_holder
.texture_target
);
706 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
707 list
[1].mailbox_holder
.texture_target
);
708 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
709 list
[2].mailbox_holder
.texture_target
);
710 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
711 list
[3].mailbox_holder
.texture_target
);
712 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
713 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
714 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
715 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
716 resource_provider_
->ReceiveFromChild(child_id
, list
);
717 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
718 context3d_
->last_waited_sync_point());
720 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
721 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
724 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
725 context3d_
->last_waited_sync_point());
726 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
727 resource_ids_to_transfer
);
730 EXPECT_EQ(4u, resource_provider_
->num_resources());
731 ResourceProvider::ResourceIdMap resource_map
=
732 resource_provider_
->GetChildToParentMap(child_id
);
733 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
734 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
735 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
736 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
737 EXPECT_NE(0u, mapped_id1
);
738 EXPECT_NE(0u, mapped_id2
);
739 EXPECT_NE(0u, mapped_id3
);
740 EXPECT_NE(0u, mapped_id4
);
741 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
742 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
743 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
744 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
746 uint8_t result
[4] = { 0 };
748 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
749 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
752 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
753 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
756 // Check that transfering again the same resource from the child to the
758 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
759 resource_ids_to_transfer
.push_back(id1
);
760 resource_ids_to_transfer
.push_back(id2
);
761 resource_ids_to_transfer
.push_back(id3
);
762 TransferableResourceArray list
;
763 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
765 EXPECT_EQ(3u, list
.size());
766 EXPECT_EQ(id1
, list
[0].id
);
767 EXPECT_EQ(id2
, list
[1].id
);
768 EXPECT_EQ(id3
, list
[2].id
);
769 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
770 list
[0].mailbox_holder
.texture_target
);
771 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
772 list
[1].mailbox_holder
.texture_target
);
773 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
774 list
[2].mailbox_holder
.texture_target
);
775 ReturnedResourceArray returned
;
776 TransferableResource::ReturnResources(list
, &returned
);
777 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
778 // ids were exported twice, we returned them only once, they should still
780 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
781 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
782 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
785 EXPECT_EQ(0u, returned_to_child
.size());
787 // Transfer resources back from the parent to the child. Set no resources as
789 ResourceProvider::ResourceIdArray no_resources
;
790 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
792 ASSERT_EQ(4u, returned_to_child
.size());
793 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
794 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
795 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
796 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
797 EXPECT_FALSE(returned_to_child
[0].lost
);
798 EXPECT_FALSE(returned_to_child
[1].lost
);
799 EXPECT_FALSE(returned_to_child
[2].lost
);
800 EXPECT_FALSE(returned_to_child
[3].lost
);
801 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
802 returned_to_child
.clear();
804 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
805 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
806 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
807 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
810 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
811 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
813 ASSERT_NE(0U, lock
.texture_id());
814 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
815 child_context_
->GetPixels(size
, format
, result
);
816 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
819 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
820 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
822 ASSERT_NE(0U, lock
.texture_id());
823 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
824 child_context_
->GetPixels(size
, format
, result
);
825 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
828 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
829 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
831 ASSERT_NE(0U, lock
.texture_id());
832 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
835 // Transfer resources to the parent again.
836 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
837 resource_ids_to_transfer
.push_back(id1
);
838 resource_ids_to_transfer
.push_back(id2
);
839 resource_ids_to_transfer
.push_back(id3
);
840 resource_ids_to_transfer
.push_back(id4
);
841 TransferableResourceArray list
;
842 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
844 ASSERT_EQ(4u, list
.size());
845 EXPECT_EQ(id1
, list
[0].id
);
846 EXPECT_EQ(id2
, list
[1].id
);
847 EXPECT_EQ(id3
, list
[2].id
);
848 EXPECT_EQ(id4
, list
[3].id
);
849 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
850 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
851 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
852 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
853 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
854 list
[0].mailbox_holder
.texture_target
);
855 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
856 list
[1].mailbox_holder
.texture_target
);
857 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
858 list
[2].mailbox_holder
.texture_target
);
859 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
860 list
[3].mailbox_holder
.texture_target
);
861 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
862 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
863 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
864 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
865 resource_provider_
->ReceiveFromChild(child_id
, list
);
866 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
867 resource_ids_to_transfer
);
870 EXPECT_EQ(0u, returned_to_child
.size());
872 EXPECT_EQ(4u, resource_provider_
->num_resources());
873 resource_provider_
->DestroyChild(child_id
);
874 EXPECT_EQ(0u, resource_provider_
->num_resources());
876 ASSERT_EQ(4u, returned_to_child
.size());
877 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
878 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
879 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
880 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
881 EXPECT_FALSE(returned_to_child
[0].lost
);
882 EXPECT_FALSE(returned_to_child
[1].lost
);
883 EXPECT_FALSE(returned_to_child
[2].lost
);
884 EXPECT_FALSE(returned_to_child
[3].lost
);
887 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
888 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
890 gfx::Size
size(1, 1);
891 ResourceFormat format
= RGBA_8888
;
893 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
894 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
895 uint8_t data1
[4] = {1, 2, 3, 4};
896 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
898 ReturnedResourceArray returned_to_child
;
900 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
902 // Transfer some resources to the parent.
903 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
904 resource_ids_to_transfer
.push_back(id1
);
905 TransferableResourceArray list
;
906 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
908 ASSERT_EQ(1u, list
.size());
909 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
911 resource_provider_
->ReceiveFromChild(child_id
, list
);
913 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
914 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
917 resource_provider_
->DeclareUsedResourcesFromChild(
918 child_id
, ResourceProvider::ResourceIdArray());
919 EXPECT_EQ(0u, returned_to_child
.size());
922 EXPECT_EQ(1u, returned_to_child
.size());
923 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
926 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
927 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
929 child_resource_provider_
->DeleteResource(id1
);
930 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
931 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
934 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
935 resource_provider_
->DestroyChild(child_id
);
938 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
939 // Overlays only supported on the GL path.
940 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
943 uint32 sync_point
= 0;
944 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
945 mailbox
.set_allow_overlay(true);
946 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
947 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
948 ResourceProvider::ResourceId id1
=
949 child_resource_provider_
->CreateResourceFromTextureMailbox(
950 mailbox
, release_callback
.Pass());
952 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
953 mailbox2
.set_allow_overlay(false);
954 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
955 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
956 ResourceProvider::ResourceId id2
=
957 child_resource_provider_
->CreateResourceFromTextureMailbox(
958 mailbox2
, release_callback2
.Pass());
960 ReturnedResourceArray returned_to_child
;
962 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
964 // Transfer some resources to the parent.
965 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
966 resource_ids_to_transfer
.push_back(id1
);
967 resource_ids_to_transfer
.push_back(id2
);
968 TransferableResourceArray list
;
969 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
971 ASSERT_EQ(2u, list
.size());
972 resource_provider_
->ReceiveFromChild(child_id
, list
);
973 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
974 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
976 resource_provider_
->DeclareUsedResourcesFromChild(
977 child_id
, ResourceProvider::ResourceIdArray());
979 EXPECT_EQ(2u, returned_to_child
.size());
980 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
982 child_resource_provider_
->DeleteResource(id1
);
983 child_resource_provider_
->DeleteResource(id2
);
984 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
986 resource_provider_
->DestroyChild(child_id
);
989 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
990 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
993 gfx::Size
size(1, 1);
994 ResourceFormat format
= RGBA_8888
;
995 size_t pixel_size
= TextureSizeBytes(size
, format
);
996 ASSERT_EQ(4U, pixel_size
);
998 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
999 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1000 uint8_t data1
[4] = { 1, 2, 3, 4 };
1001 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1003 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1004 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1005 uint8_t data2
[4] = { 5, 5, 5, 5 };
1006 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1008 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1009 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1010 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1011 ResourceProvider::ResourceId id3
=
1012 child_resource_provider_
->CreateResourceFromTextureMailbox(
1013 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1014 SingleReleaseCallbackImpl::Create(base::Bind(
1015 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1017 ReturnedResourceArray returned_to_child
;
1019 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1021 // Transfer some resources to the parent.
1022 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1023 resource_ids_to_transfer
.push_back(id1
);
1024 resource_ids_to_transfer
.push_back(id2
);
1025 resource_ids_to_transfer
.push_back(id3
);
1026 TransferableResourceArray list
;
1027 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1029 ASSERT_EQ(3u, list
.size());
1030 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1031 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1032 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1033 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1034 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1035 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1036 resource_provider_
->ReceiveFromChild(child_id
, list
);
1037 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1038 resource_ids_to_transfer
);
1041 EXPECT_EQ(3u, resource_provider_
->num_resources());
1042 ResourceProvider::ResourceIdMap resource_map
=
1043 resource_provider_
->GetChildToParentMap(child_id
);
1044 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1045 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1046 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1047 EXPECT_NE(0u, mapped_id1
);
1048 EXPECT_NE(0u, mapped_id2
);
1049 EXPECT_NE(0u, mapped_id3
);
1050 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1051 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1052 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1054 uint8_t result
[4] = { 0 };
1056 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1057 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1060 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1061 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1064 // Check that transfering again the same resource from the child to the
1066 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1067 resource_ids_to_transfer
.push_back(id1
);
1068 resource_ids_to_transfer
.push_back(id2
);
1069 TransferableResourceArray list
;
1070 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1072 EXPECT_EQ(2u, list
.size());
1073 EXPECT_EQ(id1
, list
[0].id
);
1074 EXPECT_EQ(id2
, list
[1].id
);
1075 ReturnedResourceArray returned
;
1076 TransferableResource::ReturnResources(list
, &returned
);
1077 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1078 // ids were exported twice, we returned them only once, they should still
1080 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1081 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1084 EXPECT_EQ(0u, returned_to_child
.size());
1086 // Transfer resources back from the parent to the child. Set no resources as
1088 ResourceProvider::ResourceIdArray no_resources
;
1089 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1091 ASSERT_EQ(3u, returned_to_child
.size());
1092 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1093 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1094 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1095 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1096 expected_ids
.insert(id1
);
1097 expected_ids
.insert(id2
);
1098 expected_ids
.insert(id3
);
1099 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1100 for (unsigned i
= 0; i
< 3; i
++)
1101 returned_ids
.insert(returned_to_child
[i
].id
);
1102 EXPECT_EQ(expected_ids
, returned_ids
);
1103 EXPECT_FALSE(returned_to_child
[0].lost
);
1104 EXPECT_FALSE(returned_to_child
[1].lost
);
1105 EXPECT_FALSE(returned_to_child
[2].lost
);
1106 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1107 returned_to_child
.clear();
1109 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1110 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1111 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1114 ResourceProvider::ScopedReadLockSoftware
lock(
1115 child_resource_provider_
.get(), id1
);
1116 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1117 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1118 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1119 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1122 ResourceProvider::ScopedReadLockSoftware
lock(
1123 child_resource_provider_
.get(), id2
);
1124 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1125 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1126 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1127 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1130 // Transfer resources to the parent again.
1131 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1132 resource_ids_to_transfer
.push_back(id1
);
1133 resource_ids_to_transfer
.push_back(id2
);
1134 resource_ids_to_transfer
.push_back(id3
);
1135 TransferableResourceArray list
;
1136 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1138 ASSERT_EQ(3u, list
.size());
1139 EXPECT_EQ(id1
, list
[0].id
);
1140 EXPECT_EQ(id2
, list
[1].id
);
1141 EXPECT_EQ(id3
, list
[2].id
);
1142 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1143 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1144 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1145 resource_provider_
->ReceiveFromChild(child_id
, list
);
1146 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1147 resource_ids_to_transfer
);
1150 EXPECT_EQ(0u, returned_to_child
.size());
1152 EXPECT_EQ(3u, resource_provider_
->num_resources());
1153 resource_provider_
->DestroyChild(child_id
);
1154 EXPECT_EQ(0u, resource_provider_
->num_resources());
1156 ASSERT_EQ(3u, returned_to_child
.size());
1157 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1158 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1159 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1160 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1161 expected_ids
.insert(id1
);
1162 expected_ids
.insert(id2
);
1163 expected_ids
.insert(id3
);
1164 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1165 for (unsigned i
= 0; i
< 3; i
++)
1166 returned_ids
.insert(returned_to_child
[i
].id
);
1167 EXPECT_EQ(expected_ids
, returned_ids
);
1168 EXPECT_FALSE(returned_to_child
[0].lost
);
1169 EXPECT_FALSE(returned_to_child
[1].lost
);
1170 EXPECT_FALSE(returned_to_child
[2].lost
);
1173 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1174 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1177 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1178 ResourceProviderContext::Create(shared_data_
.get()));
1180 FakeOutputSurfaceClient child_output_surface_client
;
1181 scoped_ptr
<OutputSurface
> child_output_surface(
1182 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1183 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1185 scoped_ptr
<ResourceProvider
> child_resource_provider(
1186 ResourceProvider::Create(child_output_surface
.get(),
1187 shared_bitmap_manager_
.get(),
1188 gpu_memory_buffer_manager_
.get(),
1194 gfx::Size
size(1, 1);
1195 ResourceFormat format
= RGBA_8888
;
1196 size_t pixel_size
= TextureSizeBytes(size
, format
);
1197 ASSERT_EQ(4U, pixel_size
);
1199 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1200 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1201 uint8_t data1
[4] = { 1, 2, 3, 4 };
1202 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1204 ReturnedResourceArray returned_to_child
;
1206 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1208 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1209 resource_ids_to_transfer
.push_back(id1
);
1210 TransferableResourceArray list
;
1211 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1213 ASSERT_EQ(1u, list
.size());
1214 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1215 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1216 list
[0].mailbox_holder
.texture_target
);
1217 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1218 resource_provider_
->ReceiveFromChild(child_id
, list
);
1221 EXPECT_EQ(0u, resource_provider_
->num_resources());
1222 ASSERT_EQ(1u, returned_to_child
.size());
1223 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1224 ResourceProvider::ResourceIdMap resource_map
=
1225 resource_provider_
->GetChildToParentMap(child_id
);
1226 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1227 EXPECT_EQ(0u, mapped_id1
);
1229 resource_provider_
->DestroyChild(child_id
);
1230 EXPECT_EQ(0u, resource_provider_
->num_resources());
1232 ASSERT_EQ(1u, returned_to_child
.size());
1233 EXPECT_FALSE(returned_to_child
[0].lost
);
1236 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1237 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1240 gfx::Size
size(1, 1);
1241 ResourceFormat format
= RGBA_8888
;
1242 size_t pixel_size
= TextureSizeBytes(size
, format
);
1243 ASSERT_EQ(4U, pixel_size
);
1245 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1246 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1247 uint8_t data1
[4] = { 1, 2, 3, 4 };
1248 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1250 ReturnedResourceArray returned_to_child
;
1252 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1254 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1255 resource_ids_to_transfer
.push_back(id1
);
1256 TransferableResourceArray list
;
1257 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1259 ASSERT_EQ(1u, list
.size());
1261 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1262 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1263 resource_provider_
->ReceiveFromChild(child_id
, list
);
1266 EXPECT_EQ(1u, resource_provider_
->num_resources());
1267 EXPECT_EQ(0u, returned_to_child
.size());
1269 ResourceProvider::ResourceIdMap resource_map
=
1270 resource_provider_
->GetChildToParentMap(child_id
);
1271 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1272 EXPECT_NE(0u, mapped_id1
);
1274 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1276 EXPECT_FALSE(lock
.valid());
1279 resource_provider_
->DestroyChild(child_id
);
1280 EXPECT_EQ(0u, resource_provider_
->num_resources());
1282 ASSERT_EQ(1u, returned_to_child
.size());
1283 EXPECT_FALSE(returned_to_child
[0].lost
);
1286 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1287 gfx::Size
size(1, 1);
1288 ResourceFormat format
= RGBA_8888
;
1289 size_t pixel_size
= TextureSizeBytes(size
, format
);
1290 ASSERT_EQ(4U, pixel_size
);
1292 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1293 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1294 uint8_t data1
[4] = { 1, 2, 3, 4 };
1295 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1297 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1298 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1299 uint8_t data2
[4] = {5, 5, 5, 5};
1300 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1302 ReturnedResourceArray returned_to_child
;
1304 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1306 // Transfer some resources to the parent.
1307 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1308 resource_ids_to_transfer
.push_back(id1
);
1309 resource_ids_to_transfer
.push_back(id2
);
1310 TransferableResourceArray list
;
1311 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1313 ASSERT_EQ(2u, list
.size());
1314 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1315 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1316 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1318 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1319 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1320 resource_provider_
->ReceiveFromChild(child_id
, list
);
1321 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1322 resource_ids_to_transfer
);
1325 EXPECT_EQ(2u, resource_provider_
->num_resources());
1326 ResourceProvider::ResourceIdMap resource_map
=
1327 resource_provider_
->GetChildToParentMap(child_id
);
1328 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1329 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1330 EXPECT_NE(0u, mapped_id1
);
1331 EXPECT_NE(0u, mapped_id2
);
1332 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1333 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1336 // The parent transfers the resources to the grandparent.
1337 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1338 resource_ids_to_transfer
.push_back(mapped_id1
);
1339 resource_ids_to_transfer
.push_back(mapped_id2
);
1340 TransferableResourceArray list
;
1341 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1343 ASSERT_EQ(2u, list
.size());
1344 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1345 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1346 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1348 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1349 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1351 // Release the resource in the parent. Set no resources as being in use. The
1352 // resources are exported so that can't be transferred back yet.
1353 ResourceProvider::ResourceIdArray no_resources
;
1354 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1356 EXPECT_EQ(0u, returned_to_child
.size());
1357 EXPECT_EQ(2u, resource_provider_
->num_resources());
1359 // Return the resources from the grandparent to the parent. They should be
1360 // returned to the child then.
1361 EXPECT_EQ(2u, list
.size());
1362 EXPECT_EQ(mapped_id1
, list
[0].id
);
1363 EXPECT_EQ(mapped_id2
, list
[1].id
);
1364 ReturnedResourceArray returned
;
1365 TransferableResource::ReturnResources(list
, &returned
);
1366 resource_provider_
->ReceiveReturnsFromParent(returned
);
1368 EXPECT_EQ(0u, resource_provider_
->num_resources());
1369 ASSERT_EQ(2u, returned_to_child
.size());
1370 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1371 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1372 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1374 EXPECT_FALSE(returned_to_child
[0].lost
);
1375 EXPECT_FALSE(returned_to_child
[1].lost
);
1379 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1380 gfx::Size
size(1, 1);
1381 ResourceFormat format
= RGBA_8888
;
1382 size_t pixel_size
= TextureSizeBytes(size
, format
);
1383 ASSERT_EQ(4U, pixel_size
);
1385 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1386 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1387 uint8_t data1
[4] = {1, 2, 3, 4};
1388 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1390 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1391 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1392 uint8_t data2
[4] = {5, 5, 5, 5};
1393 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1395 ReturnedResourceArray returned_to_child
;
1397 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1399 // Transfer some resources to the parent.
1400 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1401 resource_ids_to_transfer
.push_back(id1
);
1402 resource_ids_to_transfer
.push_back(id2
);
1403 TransferableResourceArray list
;
1404 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1406 ASSERT_EQ(2u, list
.size());
1407 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1408 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1409 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1411 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1412 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1413 resource_provider_
->ReceiveFromChild(child_id
, list
);
1414 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1415 resource_ids_to_transfer
);
1418 EXPECT_EQ(2u, resource_provider_
->num_resources());
1419 ResourceProvider::ResourceIdMap resource_map
=
1420 resource_provider_
->GetChildToParentMap(child_id
);
1421 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1422 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1423 EXPECT_NE(0u, mapped_id1
);
1424 EXPECT_NE(0u, mapped_id2
);
1425 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1426 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1429 // The parent transfers the resources to the grandparent.
1430 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1431 resource_ids_to_transfer
.push_back(mapped_id1
);
1432 resource_ids_to_transfer
.push_back(mapped_id2
);
1433 TransferableResourceArray list
;
1434 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1436 ASSERT_EQ(2u, list
.size());
1437 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1438 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1439 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1441 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1442 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1444 // Release the resource in the parent. Set no resources as being in use. The
1445 // resources are exported so that can't be transferred back yet.
1446 ResourceProvider::ResourceIdArray no_resources
;
1447 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1449 // Destroy the child, the resources should not be returned yet.
1450 EXPECT_EQ(0u, returned_to_child
.size());
1451 EXPECT_EQ(2u, resource_provider_
->num_resources());
1453 resource_provider_
->DestroyChild(child_id
);
1455 EXPECT_EQ(2u, resource_provider_
->num_resources());
1456 ASSERT_EQ(0u, returned_to_child
.size());
1458 // Return a resource from the grandparent, it should be returned at this
1460 EXPECT_EQ(2u, list
.size());
1461 EXPECT_EQ(mapped_id1
, list
[0].id
);
1462 EXPECT_EQ(mapped_id2
, list
[1].id
);
1463 TransferableResourceArray return_list
;
1464 return_list
.push_back(list
[1]);
1466 ReturnedResourceArray returned
;
1467 TransferableResource::ReturnResources(return_list
, &returned
);
1468 resource_provider_
->ReceiveReturnsFromParent(returned
);
1470 EXPECT_EQ(1u, resource_provider_
->num_resources());
1471 ASSERT_EQ(1u, returned_to_child
.size());
1472 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1473 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1475 EXPECT_FALSE(returned_to_child
[0].lost
);
1476 returned_to_child
.clear();
1478 // Destroy the parent resource provider. The resource that's left should be
1479 // lost at this point, and returned.
1480 resource_provider_
= nullptr;
1481 ASSERT_EQ(1u, returned_to_child
.size());
1482 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1483 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1485 EXPECT_TRUE(returned_to_child
[0].lost
);
1489 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1490 gfx::Size
size(1, 1);
1491 ResourceFormat format
= RGBA_8888
;
1492 size_t pixel_size
= TextureSizeBytes(size
, format
);
1493 ASSERT_EQ(4U, pixel_size
);
1495 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1496 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1497 uint8_t data
[4] = { 1, 2, 3, 4 };
1498 child_resource_provider_
->CopyToResource(id
, data
, size
);
1500 ReturnedResourceArray returned_to_child
;
1502 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1504 // Transfer some resource to the parent.
1505 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1506 resource_ids_to_transfer
.push_back(id
);
1507 TransferableResourceArray list
;
1508 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1510 ASSERT_EQ(1u, list
.size());
1511 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1512 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1513 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1514 resource_provider_
->ReceiveFromChild(child_id
, list
);
1515 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1516 resource_ids_to_transfer
);
1519 // Delete textures in the child, while they are transfered.
1520 child_resource_provider_
->DeleteResource(id
);
1521 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1523 EXPECT_EQ(0u, returned_to_child
.size());
1525 // Transfer resources back from the parent to the child. Set no resources as
1527 ResourceProvider::ResourceIdArray no_resources
;
1528 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1530 ASSERT_EQ(1u, returned_to_child
.size());
1531 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1532 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1533 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1535 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1538 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1539 gfx::Size
size(1, 1);
1540 ResourceFormat format
= RGBA_8888
;
1541 size_t pixel_size
= TextureSizeBytes(size
, format
);
1542 ASSERT_EQ(4U, pixel_size
);
1544 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1545 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1546 uint8_t data
[4] = {1, 2, 3, 4};
1547 child_resource_provider_
->CopyToResource(id
, data
, size
);
1549 ReturnedResourceArray returned_to_child
;
1551 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1552 const ResourceProvider::ResourceIdMap
& map
=
1553 resource_provider_
->GetChildToParentMap(child_id
);
1555 // Transfer some resource to the parent.
1556 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1557 resource_ids_to_transfer
.push_back(id
);
1558 TransferableResourceArray list
;
1559 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1561 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1562 resource_provider_
->ReceiveFromChild(child_id
, list
);
1563 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1564 resource_ids_to_transfer
);
1566 TransferableResourceArray sent_to_top_level
;
1568 // Parent transfers to top-level.
1569 ASSERT_TRUE(map
.find(id
) != map
.end());
1570 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1571 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1572 resource_ids_to_transfer
.push_back(parent_id
);
1573 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1574 &sent_to_top_level
);
1575 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1578 // Stop using resource.
1579 ResourceProvider::ResourceIdArray empty
;
1580 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1581 // Resource is not yet returned to the child, since it's in use by the
1583 EXPECT_TRUE(returned_to_child
.empty());
1586 // Send the resource to the parent again.
1587 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1588 resource_ids_to_transfer
.push_back(id
);
1589 TransferableResourceArray list
;
1590 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1592 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1593 resource_provider_
->ReceiveFromChild(child_id
, list
);
1594 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1595 resource_ids_to_transfer
);
1598 // Receive returns back from top-level.
1599 ReturnedResourceArray returned
;
1600 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1601 resource_provider_
->ReceiveReturnsFromParent(returned
);
1602 // Resource is still not yet returned to the child, since it's declared used
1604 EXPECT_TRUE(returned_to_child
.empty());
1605 ASSERT_TRUE(map
.find(id
) != map
.end());
1606 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1607 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1610 sent_to_top_level
.clear();
1611 // Parent transfers again to top-level.
1612 ASSERT_TRUE(map
.find(id
) != map
.end());
1613 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1614 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1615 resource_ids_to_transfer
.push_back(parent_id
);
1616 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1617 &sent_to_top_level
);
1618 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1621 // Receive returns back from top-level.
1622 ReturnedResourceArray returned
;
1623 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1624 resource_provider_
->ReceiveReturnsFromParent(returned
);
1625 // Resource is still not yet returned to the child, since it's still
1626 // declared used in the parent.
1627 EXPECT_TRUE(returned_to_child
.empty());
1628 ASSERT_TRUE(map
.find(id
) != map
.end());
1629 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1630 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1633 // Stop using resource.
1634 ResourceProvider::ResourceIdArray empty
;
1635 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1636 // Resource should have been returned to the child, since it's no longer in
1637 // use by the top-level.
1638 ASSERT_EQ(1u, returned_to_child
.size());
1639 EXPECT_EQ(id
, returned_to_child
[0].id
);
1640 EXPECT_EQ(2, returned_to_child
[0].count
);
1641 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1642 returned_to_child
.clear();
1643 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1647 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1649 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1650 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1651 new TextureStateTrackingContext
);
1652 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1654 FakeOutputSurfaceClient child_output_surface_client
;
1655 scoped_ptr
<OutputSurface
> child_output_surface(
1656 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1657 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1658 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1659 new TestSharedBitmapManager());
1661 scoped_ptr
<ResourceProvider
> child_resource_provider(
1662 ResourceProvider::Create(child_output_surface
.get(),
1663 shared_bitmap_manager
.get(),
1670 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1671 new TextureStateTrackingContext
);
1672 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1674 FakeOutputSurfaceClient parent_output_surface_client
;
1675 scoped_ptr
<OutputSurface
> parent_output_surface(
1676 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1677 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1679 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1680 ResourceProvider::Create(parent_output_surface
.get(),
1681 shared_bitmap_manager
.get(),
1688 gfx::Size
size(1, 1);
1689 ResourceFormat format
= RGBA_8888
;
1690 int child_texture_id
= 1;
1691 int parent_texture_id
= 2;
1693 size_t pixel_size
= TextureSizeBytes(size
, format
);
1694 ASSERT_EQ(4U, pixel_size
);
1696 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1697 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1700 // The new texture is created with GL_LINEAR.
1701 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1702 .Times(2); // Once to create and once to allocate.
1703 EXPECT_CALL(*child_context
,
1704 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1705 EXPECT_CALL(*child_context
,
1706 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1709 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1712 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1713 EXPECT_CALL(*child_context
,
1714 texParameteri(GL_TEXTURE_2D
,
1715 GL_TEXTURE_POOL_CHROMIUM
,
1716 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1717 child_resource_provider
->AllocateForTesting(id
);
1718 Mock::VerifyAndClearExpectations(child_context
);
1720 uint8_t data
[4] = { 1, 2, 3, 4 };
1722 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1723 child_resource_provider
->CopyToResource(id
, data
, size
);
1724 Mock::VerifyAndClearExpectations(child_context
);
1726 // The texture is set to |child_filter| in the child.
1727 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1728 if (child_filter
!= GL_LINEAR
) {
1731 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1734 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1736 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1737 Mock::VerifyAndClearExpectations(child_context
);
1739 ReturnedResourceArray returned_to_child
;
1740 int child_id
= parent_resource_provider
->CreateChild(
1741 GetReturnCallback(&returned_to_child
));
1743 // Transfer some resource to the parent.
1744 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1745 resource_ids_to_transfer
.push_back(id
);
1746 TransferableResourceArray list
;
1748 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1749 EXPECT_CALL(*child_context
,
1750 produceTextureCHROMIUM(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 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1761 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1762 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1764 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1765 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1768 Mock::VerifyAndClearExpectations(parent_context
);
1770 parent_resource_provider
->DeclareUsedResourcesFromChild(
1771 child_id
, resource_ids_to_transfer
);
1772 Mock::VerifyAndClearExpectations(parent_context
);
1774 ResourceProvider::ResourceIdMap resource_map
=
1775 parent_resource_provider
->GetChildToParentMap(child_id
);
1776 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1777 EXPECT_NE(0u, mapped_id
);
1779 // The texture is set to |parent_filter| in the parent.
1780 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1783 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1786 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1787 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1788 Mock::VerifyAndClearExpectations(parent_context
);
1790 // The texture should be reset to |child_filter| in the parent when it is
1791 // returned, since that is how it was received.
1792 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1795 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1798 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1801 EXPECT_EQ(0u, returned_to_child
.size());
1803 // Transfer resources back from the parent to the child. Set no resources
1805 ResourceProvider::ResourceIdArray no_resources
;
1806 EXPECT_CALL(*parent_context
, insertSyncPoint());
1807 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1809 Mock::VerifyAndClearExpectations(parent_context
);
1811 ASSERT_EQ(1u, returned_to_child
.size());
1812 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1815 // The child remembers the texture filter is set to |child_filter|.
1816 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1817 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1818 Mock::VerifyAndClearExpectations(child_context
);
1822 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1823 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1825 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1828 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1829 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1831 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1834 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1835 // Other mailbox transfers tested elsewhere.
1836 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1838 unsigned texture
= context()->createTexture();
1839 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1840 uint8_t data
[4] = { 1, 2, 3, 4 };
1841 context()->texImage2D(
1842 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1843 gpu::Mailbox mailbox
;
1844 context()->genMailboxCHROMIUM(mailbox
.name
);
1845 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1846 uint32 sync_point
= context()->insertSyncPoint();
1848 // All the logic below assumes that the sync points are all positive.
1849 EXPECT_LT(0u, sync_point
);
1851 uint32 release_sync_point
= 0;
1852 bool lost_resource
= false;
1853 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1854 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1855 &release_sync_point
,
1857 &main_thread_task_runner
);
1858 ResourceProvider::ResourceId resource
=
1859 resource_provider_
->CreateResourceFromTextureMailbox(
1860 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1861 SingleReleaseCallbackImpl::Create(callback
));
1862 EXPECT_EQ(1u, context()->NumTextures());
1863 EXPECT_EQ(0u, release_sync_point
);
1865 // Transfer the resource, expect the sync points to be consistent.
1866 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1867 resource_ids_to_transfer
.push_back(resource
);
1868 TransferableResourceArray list
;
1869 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1870 ASSERT_EQ(1u, list
.size());
1871 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1873 memcmp(mailbox
.name
,
1874 list
[0].mailbox_holder
.mailbox
.name
,
1875 sizeof(mailbox
.name
)));
1876 EXPECT_EQ(0u, release_sync_point
);
1878 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1879 unsigned other_texture
= context()->createTexture();
1880 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1881 context()->consumeTextureCHROMIUM(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
)));
1886 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1887 context()->deleteTexture(other_texture
);
1888 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1889 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1891 // Receive the resource, then delete it, expect the sync points to be
1893 ReturnedResourceArray returned
;
1894 TransferableResource::ReturnResources(list
, &returned
);
1895 resource_provider_
->ReceiveReturnsFromParent(returned
);
1896 EXPECT_EQ(1u, context()->NumTextures());
1897 EXPECT_EQ(0u, release_sync_point
);
1899 resource_provider_
->DeleteResource(resource
);
1900 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1901 EXPECT_FALSE(lost_resource
);
1902 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1905 // We're going to do the same thing as above, but testing the case where we
1906 // delete the resource before we receive it back.
1907 sync_point
= release_sync_point
;
1908 EXPECT_LT(0u, sync_point
);
1909 release_sync_point
= 0;
1910 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1911 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1912 SingleReleaseCallbackImpl::Create(callback
));
1913 EXPECT_EQ(1u, context()->NumTextures());
1914 EXPECT_EQ(0u, release_sync_point
);
1916 // Transfer the resource, expect the sync points to be consistent.
1917 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1918 resource_ids_to_transfer
.push_back(resource
);
1919 TransferableResourceArray list
;
1920 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1921 ASSERT_EQ(1u, list
.size());
1922 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1924 memcmp(mailbox
.name
,
1925 list
[0].mailbox_holder
.mailbox
.name
,
1926 sizeof(mailbox
.name
)));
1927 EXPECT_EQ(0u, release_sync_point
);
1929 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1930 unsigned other_texture
= context()->createTexture();
1931 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1932 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1933 uint8_t test_data
[4] = { 0 };
1934 context()->GetPixels(
1935 gfx::Size(1, 1), RGBA_8888
, test_data
);
1936 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1937 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1938 context()->deleteTexture(other_texture
);
1939 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1940 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1942 // Delete the resource, which shouldn't do anything.
1943 resource_provider_
->DeleteResource(resource
);
1944 EXPECT_EQ(1u, context()->NumTextures());
1945 EXPECT_EQ(0u, release_sync_point
);
1947 // Then receive the resource which should release the mailbox, expect the
1948 // sync points to be consistent.
1949 ReturnedResourceArray returned
;
1950 TransferableResource::ReturnResources(list
, &returned
);
1951 resource_provider_
->ReceiveReturnsFromParent(returned
);
1952 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1953 EXPECT_FALSE(lost_resource
);
1954 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1957 context()->waitSyncPoint(release_sync_point
);
1958 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1959 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1960 context()->deleteTexture(texture
);
1963 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1964 gfx::Size
size(1, 1);
1965 ResourceFormat format
= RGBA_8888
;
1966 ResourceProvider::ResourceId resource
=
1967 child_resource_provider_
->CreateResource(
1968 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1970 child_resource_provider_
->AllocateForTesting(resource
);
1971 // Expect a GL resource to be lost.
1972 bool should_lose_resource
=
1973 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
1975 ReturnedResourceArray returned_to_child
;
1977 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1979 // Transfer the resource to the parent.
1980 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1981 resource_ids_to_transfer
.push_back(resource
);
1982 TransferableResourceArray list
;
1983 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1985 EXPECT_EQ(1u, list
.size());
1987 resource_provider_
->ReceiveFromChild(child_id
, list
);
1988 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1989 resource_ids_to_transfer
);
1992 // Lose the output surface in the parent.
1993 resource_provider_
->DidLoseOutputSurface();
1996 EXPECT_EQ(0u, returned_to_child
.size());
1998 // Transfer resources back from the parent to the child. Set no resources as
2000 ResourceProvider::ResourceIdArray no_resources
;
2001 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2003 // Expect a GL resource to be lost.
2004 ASSERT_EQ(1u, returned_to_child
.size());
2005 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2006 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2007 returned_to_child
.clear();
2010 // A GL resource should be lost.
2011 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2013 // Lost resources stay in use in the parent forever.
2014 EXPECT_EQ(should_lose_resource
,
2015 child_resource_provider_
->InUseByConsumer(resource
));
2018 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2019 gfx::Size
size(1, 1);
2020 ResourceFormat format
= RGBA_8888
;
2021 ResourceProvider::ResourceId resource
=
2022 child_resource_provider_
->CreateResource(
2023 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2025 child_resource_provider_
->AllocateForTesting(resource
);
2027 ReturnedResourceArray returned_to_child
;
2029 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2031 // Transfer the resource to the parent.
2032 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2033 resource_ids_to_transfer
.push_back(resource
);
2034 TransferableResourceArray list
;
2035 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2037 EXPECT_EQ(1u, list
.size());
2039 resource_provider_
->ReceiveFromChild(child_id
, list
);
2040 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2041 resource_ids_to_transfer
);
2045 ResourceProvider::ResourceIdMap resource_map
=
2046 resource_provider_
->GetChildToParentMap(child_id
);
2047 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2048 EXPECT_NE(0u, parent_resource
);
2050 // Transfer to a grandparent.
2051 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2052 resource_ids_to_transfer
.push_back(parent_resource
);
2053 TransferableResourceArray list
;
2054 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2056 // Receive back a lost resource from the grandparent.
2057 EXPECT_EQ(1u, list
.size());
2058 EXPECT_EQ(parent_resource
, list
[0].id
);
2059 ReturnedResourceArray returned
;
2060 TransferableResource::ReturnResources(list
, &returned
);
2061 EXPECT_EQ(1u, returned
.size());
2062 EXPECT_EQ(parent_resource
, returned
[0].id
);
2063 returned
[0].lost
= true;
2064 resource_provider_
->ReceiveReturnsFromParent(returned
);
2066 // The resource should be lost.
2067 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2069 // Lost resources stay in use in the parent forever.
2070 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2074 EXPECT_EQ(0u, returned_to_child
.size());
2076 // Transfer resources back from the parent to the child. Set no resources as
2078 ResourceProvider::ResourceIdArray no_resources
;
2079 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2081 // Expect the resource to be lost.
2082 ASSERT_EQ(1u, returned_to_child
.size());
2083 EXPECT_TRUE(returned_to_child
[0].lost
);
2084 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2085 returned_to_child
.clear();
2088 // The resource should be lost.
2089 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2091 // Lost resources stay in use in the parent forever.
2092 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2095 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2096 uint32 release_sync_point
= 0;
2097 bool lost_resource
= false;
2098 bool release_called
= false;
2099 uint32 sync_point
= 0;
2100 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2101 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2103 ReturnedResourceArray returned_to_child
;
2105 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2107 // Transfer the resource to the parent.
2108 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2109 resource_ids_to_transfer
.push_back(resource
);
2110 TransferableResourceArray list
;
2111 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2113 EXPECT_EQ(1u, list
.size());
2115 resource_provider_
->ReceiveFromChild(child_id
, list
);
2116 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2117 resource_ids_to_transfer
);
2120 // Lose the output surface in the parent.
2121 resource_provider_
->DidLoseOutputSurface();
2124 EXPECT_EQ(0u, returned_to_child
.size());
2126 // Transfer resources back from the parent to the child. Set no resources as
2128 ResourceProvider::ResourceIdArray no_resources
;
2129 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2131 ASSERT_EQ(1u, returned_to_child
.size());
2132 // Losing an output surface only loses hardware resources.
2133 EXPECT_EQ(returned_to_child
[0].lost
,
2134 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2135 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2136 returned_to_child
.clear();
2139 // Delete the resource in the child. Expect the resource to be lost if it's
2141 child_resource_provider_
->DeleteResource(resource
);
2142 EXPECT_EQ(lost_resource
,
2143 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2146 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2147 uint32 release_sync_point
= 0;
2148 bool lost_resource
= false;
2149 bool release_called
= false;
2150 uint32 sync_point
= 0;
2151 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2152 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2154 ReturnedResourceArray returned_to_child
;
2156 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2158 // Transfer the resource to the parent.
2159 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2160 resource_ids_to_transfer
.push_back(resource
);
2161 TransferableResourceArray list
;
2162 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2164 EXPECT_EQ(1u, list
.size());
2166 resource_provider_
->ReceiveFromChild(child_id
, list
);
2167 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2168 resource_ids_to_transfer
);
2172 ResourceProvider::ResourceIdMap resource_map
=
2173 resource_provider_
->GetChildToParentMap(child_id
);
2174 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2175 EXPECT_NE(0u, parent_resource
);
2177 // Transfer to a grandparent.
2178 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2179 resource_ids_to_transfer
.push_back(parent_resource
);
2180 TransferableResourceArray list
;
2181 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2183 // Receive back a lost resource from the grandparent.
2184 EXPECT_EQ(1u, list
.size());
2185 EXPECT_EQ(parent_resource
, list
[0].id
);
2186 ReturnedResourceArray returned
;
2187 TransferableResource::ReturnResources(list
, &returned
);
2188 EXPECT_EQ(1u, returned
.size());
2189 EXPECT_EQ(parent_resource
, returned
[0].id
);
2190 returned
[0].lost
= true;
2191 resource_provider_
->ReceiveReturnsFromParent(returned
);
2195 EXPECT_EQ(0u, returned_to_child
.size());
2197 // Transfer resources back from the parent to the child. Set no resources as
2199 ResourceProvider::ResourceIdArray no_resources
;
2200 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2202 // Expect the resource to be lost.
2203 ASSERT_EQ(1u, returned_to_child
.size());
2204 EXPECT_TRUE(returned_to_child
[0].lost
);
2205 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2206 returned_to_child
.clear();
2209 // Delete the resource in the child. Expect the resource to be lost.
2210 child_resource_provider_
->DeleteResource(resource
);
2211 EXPECT_TRUE(lost_resource
);
2214 TEST_P(ResourceProviderTest
, Shutdown
) {
2215 uint32 release_sync_point
= 0;
2216 bool lost_resource
= false;
2217 bool release_called
= false;
2218 uint32 sync_point
= 0;
2220 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2222 EXPECT_EQ(0u, release_sync_point
);
2223 EXPECT_FALSE(lost_resource
);
2225 child_resource_provider_
= nullptr;
2227 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2228 EXPECT_LE(sync_point
, release_sync_point
);
2230 EXPECT_TRUE(release_called
);
2231 EXPECT_FALSE(lost_resource
);
2234 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2235 uint32 release_sync_point
= 0;
2236 bool lost_resource
= false;
2237 bool release_called
= false;
2238 uint32 sync_point
= 0;
2239 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2240 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2242 // Transfer the resource, so we can't release it properly on shutdown.
2243 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2244 resource_ids_to_transfer
.push_back(resource
);
2245 TransferableResourceArray list
;
2246 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2249 EXPECT_EQ(0u, release_sync_point
);
2250 EXPECT_FALSE(lost_resource
);
2252 child_resource_provider_
= nullptr;
2254 // Since the resource is in the parent, the child considers it lost.
2255 EXPECT_EQ(0u, release_sync_point
);
2256 EXPECT_TRUE(lost_resource
);
2259 TEST_P(ResourceProviderTest
, LostContext
) {
2260 // TextureMailbox callbacks only exist for GL textures for now.
2261 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2263 unsigned texture
= context()->createTexture();
2264 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2265 gpu::Mailbox mailbox
;
2266 context()->genMailboxCHROMIUM(mailbox
.name
);
2267 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2268 uint32 sync_point
= context()->insertSyncPoint();
2270 EXPECT_LT(0u, sync_point
);
2272 uint32 release_sync_point
= 0;
2273 bool lost_resource
= false;
2274 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2275 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2276 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2277 &release_sync_point
,
2279 &main_thread_task_runner
));
2280 resource_provider_
->CreateResourceFromTextureMailbox(
2281 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2283 EXPECT_EQ(0u, release_sync_point
);
2284 EXPECT_FALSE(lost_resource
);
2285 EXPECT_EQ(NULL
, main_thread_task_runner
);
2287 resource_provider_
->DidLoseOutputSurface();
2288 resource_provider_
= nullptr;
2290 EXPECT_LE(sync_point
, release_sync_point
);
2291 EXPECT_TRUE(lost_resource
);
2292 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2295 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2296 // Sampling is only supported for GL textures.
2297 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2300 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2301 new TextureStateTrackingContext
);
2302 TextureStateTrackingContext
* context
= context_owned
.get();
2304 FakeOutputSurfaceClient output_surface_client
;
2305 scoped_ptr
<OutputSurface
> output_surface(
2306 FakeOutputSurface::Create3d(context_owned
.Pass()));
2307 CHECK(output_surface
->BindToClient(&output_surface_client
));
2309 scoped_ptr
<ResourceProvider
> resource_provider(
2310 ResourceProvider::Create(output_surface
.get(),
2311 shared_bitmap_manager_
.get(),
2312 gpu_memory_buffer_manager_
.get(),
2318 gfx::Size
size(1, 1);
2319 ResourceFormat format
= RGBA_8888
;
2322 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2323 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2325 // Check that the texture gets created with the right sampler settings.
2326 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2327 .Times(2); // Once to create and once to allocate.
2328 EXPECT_CALL(*context
,
2329 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2330 EXPECT_CALL(*context
,
2331 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2334 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2337 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2338 EXPECT_CALL(*context
,
2339 texParameteri(GL_TEXTURE_2D
,
2340 GL_TEXTURE_POOL_CHROMIUM
,
2341 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2343 resource_provider
->AllocateForTesting(id
);
2344 Mock::VerifyAndClearExpectations(context
);
2346 // Creating a sampler with the default filter should not change any texture
2349 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2350 ResourceProvider::ScopedSamplerGL
sampler(
2351 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2352 Mock::VerifyAndClearExpectations(context
);
2355 // Using a different filter should be reflected in the texture parameters.
2357 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2360 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2363 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2364 ResourceProvider::ScopedSamplerGL
sampler(
2365 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2366 Mock::VerifyAndClearExpectations(context
);
2369 // Test resetting to the default filter.
2371 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2372 EXPECT_CALL(*context
,
2373 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2374 EXPECT_CALL(*context
,
2375 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2376 ResourceProvider::ScopedSamplerGL
sampler(
2377 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2378 Mock::VerifyAndClearExpectations(context
);
2382 TEST_P(ResourceProviderTest
, ManagedResource
) {
2383 // Sampling is only supported for GL textures.
2384 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2387 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2388 new TextureStateTrackingContext
);
2389 TextureStateTrackingContext
* context
= context_owned
.get();
2391 FakeOutputSurfaceClient output_surface_client
;
2392 scoped_ptr
<OutputSurface
> output_surface(
2393 FakeOutputSurface::Create3d(context_owned
.Pass()));
2394 CHECK(output_surface
->BindToClient(&output_surface_client
));
2396 scoped_ptr
<ResourceProvider
> resource_provider(
2397 ResourceProvider::Create(output_surface
.get(),
2398 shared_bitmap_manager_
.get(),
2399 gpu_memory_buffer_manager_
.get(),
2405 gfx::Size
size(1, 1);
2406 ResourceFormat format
= RGBA_8888
;
2409 // Check that the texture gets created with the right sampler settings.
2410 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2411 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2412 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2413 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2414 EXPECT_CALL(*context
,
2415 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2416 EXPECT_CALL(*context
,
2417 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2420 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2423 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2424 EXPECT_CALL(*context
,
2425 texParameteri(GL_TEXTURE_2D
,
2426 GL_TEXTURE_POOL_CHROMIUM
,
2427 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2428 resource_provider
->CreateForTesting(id
);
2431 Mock::VerifyAndClearExpectations(context
);
2434 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2435 // Sampling is only supported for GL textures.
2436 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2439 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2440 new TextureStateTrackingContext
);
2441 TextureStateTrackingContext
* context
= context_owned
.get();
2443 FakeOutputSurfaceClient output_surface_client
;
2444 scoped_ptr
<OutputSurface
> output_surface(
2445 FakeOutputSurface::Create3d(context_owned
.Pass()));
2446 CHECK(output_surface
->BindToClient(&output_surface_client
));
2448 scoped_ptr
<ResourceProvider
> resource_provider(
2449 ResourceProvider::Create(output_surface
.get(),
2450 shared_bitmap_manager_
.get(),
2451 gpu_memory_buffer_manager_
.get(),
2457 gfx::Size
size(1, 1);
2458 ResourceFormat format
= RGBA_8888
;
2459 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2461 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2462 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2463 // Check that the texture gets created with the right sampler settings.
2464 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2465 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2466 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2467 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2468 EXPECT_CALL(*context
,
2469 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2470 EXPECT_CALL(*context
,
2471 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2472 EXPECT_CALL(*context
,
2473 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2474 EXPECT_CALL(*context
,
2475 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2476 EXPECT_CALL(*context
,
2477 texParameteri(GL_TEXTURE_2D
,
2478 GL_TEXTURE_POOL_CHROMIUM
,
2479 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2480 resource_provider
->CreateForTesting(id
);
2483 Mock::VerifyAndClearExpectations(context
);
2487 TEST_P(ResourceProviderTest
, TextureHint
) {
2488 // Sampling is only supported for GL textures.
2489 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2492 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2493 new TextureStateTrackingContext
);
2494 TextureStateTrackingContext
* context
= context_owned
.get();
2495 context
->set_support_texture_storage(true);
2496 context
->set_support_texture_usage(true);
2498 FakeOutputSurfaceClient output_surface_client
;
2499 scoped_ptr
<OutputSurface
> output_surface(
2500 FakeOutputSurface::Create3d(context_owned
.Pass()));
2501 CHECK(output_surface
->BindToClient(&output_surface_client
));
2503 scoped_ptr
<ResourceProvider
> resource_provider(
2504 ResourceProvider::Create(output_surface
.get(),
2505 shared_bitmap_manager_
.get(),
2506 gpu_memory_buffer_manager_
.get(),
2512 gfx::Size
size(1, 1);
2513 ResourceFormat format
= RGBA_8888
;
2514 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2516 const ResourceProvider::TextureHint hints
[4] = {
2517 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2518 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2519 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2520 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2522 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2523 // Check that the texture gets created with the right sampler settings.
2524 ResourceProvider::ResourceId id
=
2525 resource_provider
->CreateGLTexture(size
,
2529 hints
[texture_id
- 1],
2531 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2532 EXPECT_CALL(*context
,
2533 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2534 EXPECT_CALL(*context
,
2535 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2538 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2541 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2542 EXPECT_CALL(*context
,
2543 texParameteri(GL_TEXTURE_2D
,
2544 GL_TEXTURE_POOL_CHROMIUM
,
2545 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2546 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2547 bool is_framebuffer_hint
=
2548 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2549 EXPECT_CALL(*context
,
2550 texParameteri(GL_TEXTURE_2D
,
2551 GL_TEXTURE_USAGE_ANGLE
,
2552 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2553 .Times(is_framebuffer_hint
? 1 : 0);
2554 resource_provider
->CreateForTesting(id
);
2557 Mock::VerifyAndClearExpectations(context
);
2561 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2562 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2565 gfx::Size
size(64, 64);
2566 const uint32_t kBadBeef
= 0xbadbeef;
2567 scoped_ptr
<SharedBitmap
> shared_bitmap(
2568 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2570 FakeOutputSurfaceClient output_surface_client
;
2571 scoped_ptr
<OutputSurface
> output_surface(
2572 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2573 new SoftwareOutputDevice
)));
2574 CHECK(output_surface
->BindToClient(&output_surface_client
));
2576 scoped_ptr
<ResourceProvider
> resource_provider(
2577 ResourceProvider::Create(output_surface
.get(),
2578 shared_bitmap_manager_
.get(),
2579 gpu_memory_buffer_manager_
.get(),
2580 main_thread_task_runner_
.get(),
2585 uint32 release_sync_point
= 0;
2586 bool lost_resource
= false;
2587 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2588 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2589 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2590 &release_sync_point
,
2592 &main_thread_task_runner
));
2593 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2595 ResourceProvider::ResourceId id
=
2596 resource_provider
->CreateResourceFromTextureMailbox(
2597 mailbox
, callback
.Pass());
2601 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2602 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2603 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2604 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2605 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2608 resource_provider
->DeleteResource(id
);
2609 EXPECT_EQ(0u, release_sync_point
);
2610 EXPECT_FALSE(lost_resource
);
2611 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2614 class ResourceProviderTestTextureMailboxGLFilters
2615 : public ResourceProviderTest
{
2617 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2618 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2619 BlockingTaskRunner
* main_thread_task_runner
,
2620 bool mailbox_nearest_neighbor
,
2621 GLenum sampler_filter
) {
2622 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2623 new TextureStateTrackingContext
);
2624 TextureStateTrackingContext
* context
= context_owned
.get();
2626 FakeOutputSurfaceClient output_surface_client
;
2627 scoped_ptr
<OutputSurface
> output_surface(
2628 FakeOutputSurface::Create3d(context_owned
.Pass()));
2629 CHECK(output_surface
->BindToClient(&output_surface_client
));
2631 scoped_ptr
<ResourceProvider
> resource_provider(
2632 ResourceProvider::Create(output_surface
.get(),
2633 shared_bitmap_manager
,
2634 gpu_memory_buffer_manager
,
2635 main_thread_task_runner
,
2640 unsigned texture_id
= 1;
2641 uint32 sync_point
= 30;
2642 unsigned target
= GL_TEXTURE_2D
;
2644 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2645 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2646 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2647 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2648 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2650 gpu::Mailbox gpu_mailbox
;
2651 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2652 uint32 release_sync_point
= 0;
2653 bool lost_resource
= false;
2654 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2655 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2656 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2657 &release_sync_point
,
2659 &mailbox_task_runner
));
2661 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2662 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2664 ResourceProvider::ResourceId id
=
2665 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2669 Mock::VerifyAndClearExpectations(context
);
2672 // Mailbox sync point WaitSyncPoint before using the texture.
2673 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2674 resource_provider
->WaitSyncPointIfNeeded(id
);
2675 Mock::VerifyAndClearExpectations(context
);
2677 // Using the texture does a consume of the mailbox.
2678 EXPECT_CALL(*context
, bindTexture(target
, texture_id
)).Times(2);
2679 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2681 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2682 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2684 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2685 // match |sampler_filter|.
2686 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2687 EXPECT_CALL(*context
, texParameteri(
2688 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2689 EXPECT_CALL(*context
, texParameteri(
2690 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2693 ResourceProvider::ScopedSamplerGL
lock(
2694 resource_provider
.get(), id
, sampler_filter
);
2695 Mock::VerifyAndClearExpectations(context
);
2697 // When done with it, a sync point should be inserted, but no produce is
2699 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2700 EXPECT_CALL(*context
, insertSyncPoint());
2701 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2703 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2704 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2707 resource_provider
->DeleteResource(id
);
2708 EXPECT_EQ(0u, release_sync_point
);
2709 EXPECT_FALSE(lost_resource
);
2710 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2714 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2715 // Mailboxing is only supported for GL textures.
2716 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2719 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2720 shared_bitmap_manager_
.get(),
2721 gpu_memory_buffer_manager_
.get(),
2722 main_thread_task_runner_
.get(),
2727 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2728 // Mailboxing is only supported for GL textures.
2729 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2732 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2733 shared_bitmap_manager_
.get(),
2734 gpu_memory_buffer_manager_
.get(),
2735 main_thread_task_runner_
.get(),
2740 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2741 // Mailboxing is only supported for GL textures.
2742 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2745 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2746 shared_bitmap_manager_
.get(),
2747 gpu_memory_buffer_manager_
.get(),
2748 main_thread_task_runner_
.get(),
2753 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2754 // Mailboxing is only supported for GL textures.
2755 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2758 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2759 shared_bitmap_manager_
.get(),
2760 gpu_memory_buffer_manager_
.get(),
2761 main_thread_task_runner_
.get(),
2766 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2767 // Mailboxing is only supported for GL textures.
2768 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2771 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2772 new TextureStateTrackingContext
);
2773 TextureStateTrackingContext
* context
= context_owned
.get();
2775 FakeOutputSurfaceClient output_surface_client
;
2776 scoped_ptr
<OutputSurface
> output_surface(
2777 FakeOutputSurface::Create3d(context_owned
.Pass()));
2778 CHECK(output_surface
->BindToClient(&output_surface_client
));
2780 scoped_ptr
<ResourceProvider
> resource_provider(
2781 ResourceProvider::Create(output_surface
.get(),
2782 shared_bitmap_manager_
.get(),
2783 gpu_memory_buffer_manager_
.get(),
2789 unsigned texture_id
= 1;
2790 uint32 sync_point
= 30;
2791 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2793 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2794 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2795 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2796 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2797 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2799 gpu::Mailbox gpu_mailbox
;
2800 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2801 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2802 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2804 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2806 ResourceProvider::ResourceId id
=
2807 resource_provider
->CreateResourceFromTextureMailbox(
2808 mailbox
, callback
.Pass());
2811 Mock::VerifyAndClearExpectations(context
);
2814 // Mailbox sync point WaitSyncPoint before using the texture.
2815 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2816 resource_provider
->WaitSyncPointIfNeeded(id
);
2817 Mock::VerifyAndClearExpectations(context
);
2819 // Using the texture does a consume of the mailbox.
2820 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2821 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2823 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2824 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2826 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2827 Mock::VerifyAndClearExpectations(context
);
2829 // When done with it, a sync point should be inserted, but no produce is
2831 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2832 EXPECT_CALL(*context
, insertSyncPoint());
2833 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2835 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2836 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2840 TEST_P(ResourceProviderTest
,
2841 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2842 // Mailboxing is only supported for GL textures.
2843 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2846 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2847 new TextureStateTrackingContext
);
2848 TextureStateTrackingContext
* context
= context_owned
.get();
2850 FakeOutputSurfaceClient output_surface_client
;
2851 scoped_ptr
<OutputSurface
> output_surface(
2852 FakeOutputSurface::Create3d(context_owned
.Pass()));
2853 CHECK(output_surface
->BindToClient(&output_surface_client
));
2855 scoped_ptr
<ResourceProvider
> resource_provider(
2856 ResourceProvider::Create(output_surface
.get(),
2857 shared_bitmap_manager_
.get(),
2858 gpu_memory_buffer_manager_
.get(),
2864 uint32 sync_point
= 30;
2865 unsigned target
= GL_TEXTURE_2D
;
2867 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2868 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2869 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2870 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2871 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2873 gpu::Mailbox gpu_mailbox
;
2874 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2875 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2876 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2878 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2880 ResourceProvider::ResourceId id
=
2881 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2885 Mock::VerifyAndClearExpectations(context
);
2888 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2889 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2890 resource_provider
->WaitSyncPointIfNeeded(id
);
2891 Mock::VerifyAndClearExpectations(context
);
2893 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2894 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2895 resource_provider
->WaitSyncPointIfNeeded(id
);
2896 Mock::VerifyAndClearExpectations(context
);
2900 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2901 // Mailboxing is only supported for GL textures.
2902 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2905 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2906 new TextureStateTrackingContext
);
2907 TextureStateTrackingContext
* context
= context_owned
.get();
2909 FakeOutputSurfaceClient output_surface_client
;
2910 scoped_ptr
<OutputSurface
> output_surface(
2911 FakeOutputSurface::Create3d(context_owned
.Pass()));
2912 CHECK(output_surface
->BindToClient(&output_surface_client
));
2914 scoped_ptr
<ResourceProvider
> resource_provider(
2915 ResourceProvider::Create(output_surface
.get(),
2916 shared_bitmap_manager_
.get(),
2917 gpu_memory_buffer_manager_
.get(),
2923 uint32 sync_point
= 0;
2924 unsigned target
= GL_TEXTURE_2D
;
2926 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2927 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2928 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2929 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2930 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2932 gpu::Mailbox gpu_mailbox
;
2933 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2934 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2935 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2937 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2939 ResourceProvider::ResourceId id
=
2940 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2944 Mock::VerifyAndClearExpectations(context
);
2947 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2948 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2949 resource_provider
->WaitSyncPointIfNeeded(id
);
2950 Mock::VerifyAndClearExpectations(context
);
2954 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2956 MOCK_METHOD0(NextTextureId
, GLuint());
2957 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2958 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2959 MOCK_METHOD5(texStorage2DEXT
,
2962 GLuint internalformat
,
2965 MOCK_METHOD9(texImage2D
,
2968 GLenum internalformat
,
2974 const void* pixels
));
2975 MOCK_METHOD9(texSubImage2D
,
2984 const void* pixels
));
2985 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2988 GLenum internalformat
,
2994 const void* pixels
));
2995 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3004 const void* pixels
));
3005 MOCK_METHOD8(compressedTexImage2D
,
3008 GLenum internalformat
,
3014 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3015 MOCK_METHOD4(createImageCHROMIUM
,
3016 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3017 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3018 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3019 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3021 // We're mocking bindTexture, so we override
3022 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3023 // currently bound texture.
3024 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3027 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3028 // Only for GL textures.
3029 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3031 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3032 new StrictMock
<AllocationTrackingContext3D
>);
3033 AllocationTrackingContext3D
* context
= context_owned
.get();
3035 FakeOutputSurfaceClient output_surface_client
;
3036 scoped_ptr
<OutputSurface
> output_surface(
3037 FakeOutputSurface::Create3d(context_owned
.Pass()));
3038 CHECK(output_surface
->BindToClient(&output_surface_client
));
3040 scoped_ptr
<ResourceProvider
> resource_provider(
3041 ResourceProvider::Create(output_surface
.get(),
3042 shared_bitmap_manager_
.get(),
3043 gpu_memory_buffer_manager_
.get(),
3049 gfx::Size
size(2, 2);
3050 gfx::Vector2d
offset(0, 0);
3051 ResourceFormat format
= RGBA_8888
;
3052 ResourceProvider::ResourceId id
= 0;
3053 uint8_t pixels
[16] = { 0 };
3054 int texture_id
= 123;
3056 // Lazy allocation. Don't allocate when creating the resource.
3057 id
= resource_provider
->CreateResource(
3058 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3060 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3061 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3062 resource_provider
->CreateForTesting(id
);
3064 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3065 resource_provider
->DeleteResource(id
);
3067 Mock::VerifyAndClearExpectations(context
);
3069 // Do allocate when we set the pixels.
3070 id
= resource_provider
->CreateResource(
3071 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3073 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3074 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3075 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3076 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3077 resource_provider
->CopyToResource(id
, pixels
, size
);
3079 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3080 resource_provider
->DeleteResource(id
);
3082 Mock::VerifyAndClearExpectations(context
);
3084 // Same for async version.
3085 id
= resource_provider
->CreateResource(
3086 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3087 resource_provider
->AcquirePixelBuffer(id
);
3089 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3090 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3091 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3093 resource_provider
->BeginSetPixels(id
);
3094 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3096 resource_provider
->ReleasePixelBuffer(id
);
3098 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3099 resource_provider
->DeleteResource(id
);
3101 Mock::VerifyAndClearExpectations(context
);
3104 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3105 // Only for GL textures.
3106 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3108 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3109 new StrictMock
<AllocationTrackingContext3D
>);
3110 AllocationTrackingContext3D
* context
= context_owned
.get();
3111 context
->set_support_texture_storage(true);
3112 context
->set_support_texture_usage(true);
3114 FakeOutputSurfaceClient output_surface_client
;
3115 scoped_ptr
<OutputSurface
> output_surface(
3116 FakeOutputSurface::Create3d(context_owned
.Pass()));
3117 CHECK(output_surface
->BindToClient(&output_surface_client
));
3119 scoped_ptr
<ResourceProvider
> resource_provider(
3120 ResourceProvider::Create(output_surface
.get(),
3121 shared_bitmap_manager_
.get(),
3122 gpu_memory_buffer_manager_
.get(),
3128 gfx::Size
size(2, 2);
3130 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3131 const ResourceProvider::TextureHint hints
[4] = {
3132 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3133 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3134 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3135 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3137 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3138 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3139 // Lazy allocation. Don't allocate when creating the resource.
3140 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3141 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3143 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3144 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3145 bool is_immutable_hint
=
3146 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3147 bool support_immutable_texture
=
3148 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3149 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3150 .Times(support_immutable_texture
? 1 : 0);
3151 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3152 .Times(support_immutable_texture
? 0 : 1);
3153 resource_provider
->AllocateForTesting(id
);
3155 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3156 resource_provider
->DeleteResource(id
);
3158 Mock::VerifyAndClearExpectations(context
);
3163 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3164 // Only for GL textures.
3165 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3167 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3168 new StrictMock
<AllocationTrackingContext3D
>);
3169 AllocationTrackingContext3D
* context
= context_owned
.get();
3170 context
->set_support_texture_format_bgra8888(true);
3171 context
->set_support_texture_storage(true);
3172 context
->set_support_texture_usage(true);
3174 FakeOutputSurfaceClient output_surface_client
;
3175 scoped_ptr
<OutputSurface
> output_surface(
3176 FakeOutputSurface::Create3d(context_owned
.Pass()));
3177 CHECK(output_surface
->BindToClient(&output_surface_client
));
3179 scoped_ptr
<ResourceProvider
> resource_provider(
3180 ResourceProvider::Create(output_surface
.get(),
3181 shared_bitmap_manager_
.get(),
3182 gpu_memory_buffer_manager_
.get(),
3188 gfx::Size
size(2, 2);
3189 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3191 const ResourceProvider::TextureHint hints
[4] = {
3192 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3193 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3194 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3195 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3197 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3198 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3199 // Lazy allocation. Don't allocate when creating the resource.
3200 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3201 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3203 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3204 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3205 bool is_immutable_hint
=
3206 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3207 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3208 .Times(is_immutable_hint
? 1 : 0);
3209 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3210 .Times(is_immutable_hint
? 0 : 1);
3211 resource_provider
->AllocateForTesting(id
);
3213 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3214 resource_provider
->DeleteResource(id
);
3216 Mock::VerifyAndClearExpectations(context
);
3221 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3222 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3224 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3225 new StrictMock
<AllocationTrackingContext3D
>);
3226 AllocationTrackingContext3D
* context
= context_owned
.get();
3228 FakeOutputSurfaceClient output_surface_client
;
3229 scoped_ptr
<OutputSurface
> output_surface(
3230 FakeOutputSurface::Create3d(context_owned
.Pass()));
3231 CHECK(output_surface
->BindToClient(&output_surface_client
));
3233 gfx::Size
size(2, 2);
3234 ResourceFormat format
= RGBA_8888
;
3235 ResourceProvider::ResourceId id
= 0;
3236 int texture_id
= 123;
3238 scoped_ptr
<ResourceProvider
> resource_provider(
3239 ResourceProvider::Create(output_surface
.get(),
3240 shared_bitmap_manager_
.get(),
3241 gpu_memory_buffer_manager_
.get(),
3247 id
= resource_provider
->CreateResource(
3248 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3249 resource_provider
->AcquirePixelBuffer(id
);
3251 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3252 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3253 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3255 resource_provider
->BeginSetPixels(id
);
3257 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3259 resource_provider
->ReleasePixelBuffer(id
);
3261 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3262 resource_provider
->DeleteResource(id
);
3264 Mock::VerifyAndClearExpectations(context
);
3267 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3268 // Only for GL textures.
3269 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3271 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3272 new StrictMock
<AllocationTrackingContext3D
>);
3273 AllocationTrackingContext3D
* context
= context_owned
.get();
3275 FakeOutputSurfaceClient output_surface_client
;
3276 scoped_ptr
<OutputSurface
> output_surface(
3277 FakeOutputSurface::Create3d(context_owned
.Pass()));
3278 CHECK(output_surface
->BindToClient(&output_surface_client
));
3280 gfx::Size
size(2, 2);
3281 ResourceFormat format
= RGBA_8888
;
3282 ResourceProvider::ResourceId id
= 0;
3283 int texture_id
= 123;
3285 scoped_ptr
<ResourceProvider
> resource_provider(
3286 ResourceProvider::Create(output_surface
.get(),
3287 shared_bitmap_manager_
.get(),
3288 gpu_memory_buffer_manager_
.get(),
3294 id
= resource_provider
->CreateResource(
3295 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3296 resource_provider
->AcquirePixelBuffer(id
);
3298 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3299 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3300 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3302 resource_provider
->BeginSetPixels(id
);
3304 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3305 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3306 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3307 resource_provider
->ForceSetPixelsToComplete(id
);
3309 resource_provider
->ReleasePixelBuffer(id
);
3311 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3312 resource_provider
->DeleteResource(id
);
3314 Mock::VerifyAndClearExpectations(context
);
3317 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3318 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3319 new NiceMock
<AllocationTrackingContext3D
>);
3320 AllocationTrackingContext3D
* context
= context_owned
.get();
3322 FakeOutputSurfaceClient output_surface_client
;
3323 scoped_ptr
<OutputSurface
> output_surface(
3324 FakeOutputSurface::Create3d(context_owned
.Pass()));
3325 CHECK(output_surface
->BindToClient(&output_surface_client
));
3327 gfx::Size
size(2, 2);
3328 ResourceFormat format
= RGBA_8888
;
3329 ResourceProvider::ResourceId id
= 0;
3330 int texture_id
= 123;
3332 scoped_ptr
<ResourceProvider
> resource_provider(
3333 ResourceProvider::Create(output_surface
.get(),
3334 shared_bitmap_manager_
.get(),
3335 gpu_memory_buffer_manager_
.get(),
3341 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3343 id
= resource_provider
->CreateResource(
3344 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3345 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3346 GL_INNOCENT_CONTEXT_RESET_ARB
);
3348 resource_provider
->AcquirePixelBuffer(id
);
3350 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3351 EXPECT_FALSE(buffer
);
3352 resource_provider
->UnmapPixelBuffer(id
);
3353 Mock::VerifyAndClearExpectations(context
);
3356 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3357 // Only for GL textures.
3358 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3360 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3361 new StrictMock
<AllocationTrackingContext3D
>);
3362 AllocationTrackingContext3D
* context
= context_owned
.get();
3364 FakeOutputSurfaceClient output_surface_client
;
3365 scoped_ptr
<OutputSurface
> output_surface(
3366 FakeOutputSurface::Create3d(context_owned
.Pass()));
3367 CHECK(output_surface
->BindToClient(&output_surface_client
));
3369 const int kWidth
= 2;
3370 const int kHeight
= 2;
3371 gfx::Size
size(kWidth
, kHeight
);
3372 ResourceFormat format
= RGBA_8888
;
3373 ResourceProvider::ResourceId id
= 0;
3374 const unsigned kTextureId
= 123u;
3375 const unsigned kImageId
= 234u;
3377 scoped_ptr
<ResourceProvider
> resource_provider(
3378 ResourceProvider::Create(output_surface
.get(),
3379 shared_bitmap_manager_
.get(),
3380 gpu_memory_buffer_manager_
.get(),
3386 id
= resource_provider
->CreateResource(
3387 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3389 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3390 .WillOnce(Return(kImageId
))
3391 .RetiresOnSaturation();
3393 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3394 resource_provider
.get(), id
);
3395 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3398 EXPECT_CALL(*context
, NextTextureId())
3399 .WillOnce(Return(kTextureId
))
3400 .RetiresOnSaturation();
3401 // Once in CreateTextureId and once in BindForSampling
3402 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3403 .RetiresOnSaturation();
3404 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3406 .RetiresOnSaturation();
3408 ResourceProvider::ScopedSamplerGL
lock_gl(
3409 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3410 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3414 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3415 resource_provider
.get(), id
);
3416 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3419 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3420 .RetiresOnSaturation();
3421 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3429 .RetiresOnSaturation();
3431 ResourceProvider::ScopedSamplerGL
lock_gl(
3432 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3433 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3436 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3438 .RetiresOnSaturation();
3441 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3442 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3444 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3445 new StrictMock
<AllocationTrackingContext3D
>);
3446 AllocationTrackingContext3D
* context
= context_owned
.get();
3447 context_owned
->set_support_sync_query(true);
3449 FakeOutputSurfaceClient output_surface_client
;
3450 scoped_ptr
<OutputSurface
> output_surface(
3451 FakeOutputSurface::Create3d(context_owned
.Pass()));
3452 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3454 const int kWidth
= 2;
3455 const int kHeight
= 2;
3456 gfx::Size
size(kWidth
, kHeight
);
3457 ResourceFormat format
= RGBA_8888
;
3458 ResourceProvider::ResourceId source_id
= 0;
3459 ResourceProvider::ResourceId dest_id
= 0;
3460 const unsigned kSourceTextureId
= 123u;
3461 const unsigned kDestTextureId
= 321u;
3462 const unsigned kImageId
= 234u;
3464 scoped_ptr
<ResourceProvider
> resource_provider(
3465 ResourceProvider::Create(output_surface
.get(),
3466 shared_bitmap_manager_
.get(),
3467 gpu_memory_buffer_manager_
.get(),
3473 source_id
= resource_provider
->CreateResource(
3474 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3476 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3477 .WillOnce(Return(kImageId
))
3478 .RetiresOnSaturation();
3480 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3481 resource_provider
.get(), source_id
);
3482 EXPECT_TRUE(!!lock
.GetGpuMemoryBuffer());
3484 Mock::VerifyAndClearExpectations(context
);
3486 dest_id
= resource_provider
->CreateResource(
3487 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3489 EXPECT_CALL(*context
, NextTextureId())
3490 .WillOnce(Return(kDestTextureId
))
3491 .RetiresOnSaturation();
3492 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3494 .RetiresOnSaturation();
3495 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3496 GL_UNSIGNED_BYTE
, nullptr))
3498 .RetiresOnSaturation();
3499 EXPECT_CALL(*context
, NextTextureId())
3500 .WillOnce(Return(kSourceTextureId
))
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3507 .RetiresOnSaturation();
3508 resource_provider
->CopyResource(source_id
, dest_id
);
3509 Mock::VerifyAndClearExpectations(context
);
3511 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3513 .RetiresOnSaturation();
3514 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3516 .RetiresOnSaturation();
3517 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3519 .RetiresOnSaturation();
3520 resource_provider
->DeleteResource(source_id
);
3521 resource_provider
->DeleteResource(dest_id
);
3524 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3525 ResourceProvider
* resource_provider
,
3526 FakeOutputSurface
* output_surface
) {
3527 scoped_ptr
<ResourceProviderContext
> context_owned
=
3528 ResourceProviderContext::Create(shared_data
);
3529 ResourceProviderContext
* context
= context_owned
.get();
3531 scoped_refptr
<TestContextProvider
> context_provider
=
3532 TestContextProvider::Create(context_owned
.Pass());
3533 output_surface
->InitializeAndSetContext3d(context_provider
, nullptr);
3534 resource_provider
->InitializeGL();
3536 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3537 resource_provider
, context
);
3540 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3541 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3542 bool delegated_rendering
= false;
3543 scoped_ptr
<FakeOutputSurface
> output_surface(
3544 FakeOutputSurface::CreateDeferredGL(
3545 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3546 delegated_rendering
));
3547 FakeOutputSurfaceClient
client(output_surface
.get());
3548 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3549 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3550 new TestSharedBitmapManager());
3551 scoped_ptr
<ResourceProvider
> resource_provider(
3552 ResourceProvider::Create(output_surface
.get(),
3553 shared_bitmap_manager
.get(),
3560 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP
,
3561 resource_provider
.get(), NULL
);
3563 InitializeGLAndCheck(shared_data
.get(),
3564 resource_provider
.get(),
3565 output_surface
.get());
3567 resource_provider
->InitializeSoftware();
3568 output_surface
->ReleaseGL();
3569 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP
,
3570 resource_provider
.get(), NULL
);
3572 InitializeGLAndCheck(shared_data
.get(),
3573 resource_provider
.get(),
3574 output_surface
.get());
3577 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3578 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3581 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3582 new AllocationTrackingContext3D
);
3583 AllocationTrackingContext3D
* context
= context_owned
.get();
3584 context_owned
->set_support_compressed_texture_etc1(true);
3586 FakeOutputSurfaceClient output_surface_client
;
3587 scoped_ptr
<OutputSurface
> output_surface(
3588 FakeOutputSurface::Create3d(context_owned
.Pass()));
3589 CHECK(output_surface
->BindToClient(&output_surface_client
));
3591 gfx::Size
size(4, 4);
3592 scoped_ptr
<ResourceProvider
> resource_provider(
3593 ResourceProvider::Create(output_surface
.get(),
3594 shared_bitmap_manager_
.get(),
3595 gpu_memory_buffer_manager_
.get(),
3600 int texture_id
= 123;
3602 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3603 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3605 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3606 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3607 resource_provider
->AllocateForTesting(id
);
3609 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3610 resource_provider
->DeleteResource(id
);
3613 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3614 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3617 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3618 new AllocationTrackingContext3D
);
3619 AllocationTrackingContext3D
* context
= context_owned
.get();
3620 context_owned
->set_support_compressed_texture_etc1(true);
3622 FakeOutputSurfaceClient output_surface_client
;
3623 scoped_ptr
<OutputSurface
> output_surface(
3624 FakeOutputSurface::Create3d(context_owned
.Pass()));
3625 CHECK(output_surface
->BindToClient(&output_surface_client
));
3627 gfx::Size
size(4, 4);
3628 scoped_ptr
<ResourceProvider
> resource_provider(
3629 ResourceProvider::Create(output_surface
.get(),
3630 shared_bitmap_manager_
.get(),
3631 gpu_memory_buffer_manager_
.get(),
3636 int texture_id
= 123;
3639 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3640 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3642 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3643 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3644 EXPECT_CALL(*context
,
3645 compressedTexImage2D(
3646 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3647 resource_provider
->CopyToResource(id
, pixels
, size
);
3649 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3650 resource_provider
->DeleteResource(id
);
3653 INSTANTIATE_TEST_CASE_P(
3654 ResourceProviderTests
,
3655 ResourceProviderTest
,
3656 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3657 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3659 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3661 GLuint
NextTextureId() override
{
3662 base::AutoLock
lock(namespace_
->lock
);
3663 return namespace_
->next_texture_id
++;
3665 void RetireTextureId(GLuint
) override
{}
3666 GLuint
PeekTextureId() {
3667 base::AutoLock
lock(namespace_
->lock
);
3668 return namespace_
->next_texture_id
;
3672 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3673 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3674 new TextureIdAllocationTrackingContext
);
3675 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3677 FakeOutputSurfaceClient output_surface_client
;
3678 scoped_ptr
<OutputSurface
> output_surface(
3679 FakeOutputSurface::Create3d(context_owned
.Pass()));
3680 CHECK(output_surface
->BindToClient(&output_surface_client
));
3681 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3682 new TestSharedBitmapManager());
3684 gfx::Size
size(1, 1);
3685 ResourceFormat format
= RGBA_8888
;
3688 size_t kTextureAllocationChunkSize
= 1;
3689 scoped_ptr
<ResourceProvider
> resource_provider(
3690 ResourceProvider::Create(output_surface
.get(),
3691 shared_bitmap_manager
.get(),
3696 kTextureAllocationChunkSize
));
3698 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3699 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3701 resource_provider
->AllocateForTesting(id
);
3702 Mock::VerifyAndClearExpectations(context
);
3704 DCHECK_EQ(2u, context
->PeekTextureId());
3705 resource_provider
->DeleteResource(id
);
3709 size_t kTextureAllocationChunkSize
= 8;
3710 scoped_ptr
<ResourceProvider
> resource_provider(
3711 ResourceProvider::Create(output_surface
.get(),
3712 shared_bitmap_manager
.get(),
3717 kTextureAllocationChunkSize
));
3719 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3720 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3722 resource_provider
->AllocateForTesting(id
);
3723 Mock::VerifyAndClearExpectations(context
);
3725 DCHECK_EQ(10u, context
->PeekTextureId());
3726 resource_provider
->DeleteResource(id
);