1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
36 using testing::NiceMock
;
37 using testing::Return
;
38 using testing::SetArgPointee
;
39 using testing::StrictMock
;
45 static void EmptyReleaseCallback(uint32 sync_point
,
47 BlockingTaskRunner
* main_thread_task_runner
) {
50 static void ReleaseCallback(
51 uint32
* release_sync_point
,
52 bool* release_lost_resource
,
53 BlockingTaskRunner
** release_main_thread_task_runner
,
56 BlockingTaskRunner
* main_thread_task_runner
) {
57 *release_sync_point
= sync_point
;
58 *release_lost_resource
= lost_resource
;
59 *release_main_thread_task_runner
= main_thread_task_runner
;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr
<SharedBitmap
> bitmap
,
66 BlockingTaskRunner
* main_thread_task_runner
) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr
<SharedBitmap
> shared_bitmap
,
72 uint32
* release_sync_point
,
73 bool* lost_resource_result
,
76 BlockingTaskRunner
* main_thread_task_runner
) {
77 *release_called
= true;
78 *release_sync_point
= sync_point
;
79 *lost_resource_result
= lost_resource
;
82 static scoped_ptr
<SharedBitmap
> CreateAndFillSharedBitmap(
83 SharedBitmapManager
* manager
,
84 const gfx::Size
& size
,
86 scoped_ptr
<SharedBitmap
> shared_bitmap
= manager
->AllocateSharedBitmap(size
);
88 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_bitmap
->pixels());
90 std::fill_n(pixels
, size
.GetArea(), value
);
91 return shared_bitmap
.Pass();
94 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
96 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
97 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
98 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
99 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM
,
101 void(GLuint texture
, GLenum target
, const GLbyte
* mailbox
));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM
,
103 unsigned(GLenum target
, const GLbyte
* mailbox
));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint
NextTextureId() override
{
108 base::AutoLock
lock(namespace_
->lock
);
109 return namespace_
->next_texture_id
++;
111 void RetireTextureId(GLuint
) override
{}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData
{
118 static scoped_ptr
<ContextSharedData
> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32
InsertSyncPoint() { return next_sync_point_
++; }
124 void GenMailbox(GLbyte
* mailbox
) {
125 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
126 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
130 void ProduceTexture(const GLbyte
* mailbox_name
,
132 scoped_refptr
<TestTexture
> texture
) {
133 unsigned mailbox
= 0;
134 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
135 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
136 textures_
[mailbox
] = texture
;
137 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
138 sync_point_for_mailbox_
[mailbox
] = sync_point
;
141 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
143 unsigned mailbox
= 0;
144 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
145 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
150 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
152 return scoped_refptr
<TestTexture
>();
154 return textures_
[mailbox
];
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_
;
161 unsigned next_mailbox_
;
162 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
>> TextureMap
;
163 TextureMap textures_
;
164 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
167 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
169 static scoped_ptr
<ResourceProviderContext
> Create(
170 ContextSharedData
* shared_data
) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
174 GLuint
insertSyncPoint() override
{
175 uint32 sync_point
= shared_data_
->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it
=
179 pending_produce_textures_
.begin();
180 it
!= pending_produce_textures_
.end();
182 shared_data_
->ProduceTexture(
183 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
185 pending_produce_textures_
.clear();
189 void waitSyncPoint(GLuint sync_point
) override
{
190 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
195 void texStorage2DEXT(GLenum target
,
197 GLuint internalformat
,
199 GLint height
) override
{
200 CheckTextureIsBound(target
);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
202 ASSERT_EQ(1, levels
);
203 GLenum format
= GL_RGBA
;
204 switch (internalformat
) {
208 format
= GL_BGRA_EXT
;
213 AllocateTexture(gfx::Size(width
, height
), format
);
216 void texImage2D(GLenum target
,
218 GLenum internalformat
,
224 const void* pixels
) override
{
225 CheckTextureIsBound(target
);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
228 ASSERT_EQ(internalformat
, format
);
229 ASSERT_FALSE(border
);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
231 AllocateTexture(gfx::Size(width
, height
), format
);
233 SetPixels(0, 0, width
, height
, pixels
);
236 void texSubImage2D(GLenum target
,
244 const void* pixels
) override
{
245 CheckTextureIsBound(target
);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
250 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
254 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
257 void genMailboxCHROMIUM(GLbyte
* mailbox
) override
{
258 return shared_data_
->GenMailbox(mailbox
);
261 void produceTextureDirectCHROMIUM(GLuint texture
,
263 const GLbyte
* mailbox
) override
{
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
268 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
269 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
270 pending
->texture
= UnboundTexture(texture
);
271 pending_produce_textures_
.push_back(pending
.Pass());
274 GLuint
createAndConsumeTextureCHROMIUM(GLenum target
,
275 const GLbyte
* mailbox
) override
{
276 GLuint texture_id
= createTexture();
277 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
278 scoped_refptr
<TestTexture
> texture
=
279 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
280 namespace_
->textures
.Replace(texture_id
, texture
);
284 void GetPixels(const gfx::Size
& size
,
285 ResourceFormat format
,
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
289 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
290 ASSERT_EQ(texture
->size
, size
);
291 ASSERT_EQ(texture
->format
, format
);
292 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
296 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
297 : shared_data_(shared_data
),
298 last_waited_sync_point_(0) {}
301 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
302 CheckTextureIsBound(GL_TEXTURE_2D
);
303 ResourceFormat texture_format
= RGBA_8888
;
306 texture_format
= RGBA_8888
;
309 texture_format
= BGRA_8888
;
312 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
313 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
316 void SetPixels(int xoffset
,
320 const void* pixels
) {
321 CheckTextureIsBound(GL_TEXTURE_2D
);
322 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
323 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
324 ASSERT_TRUE(texture
->data
.get());
325 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
326 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
328 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
330 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
331 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
332 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
333 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
334 for (int i
= 0; i
< height
; ++i
) {
335 memcpy(dest
, src
, in_pitch
);
341 struct PendingProduceTexture
{
342 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
343 scoped_refptr
<TestTexture
> texture
;
345 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
346 ContextSharedData
* shared_data_
;
347 GLuint last_waited_sync_point_
;
348 PendingProduceTextureList pending_produce_textures_
;
351 void GetResourcePixels(ResourceProvider
* resource_provider
,
352 ResourceProviderContext
* context
,
354 const gfx::Size
& size
,
355 ResourceFormat format
,
357 resource_provider
->WaitSyncPointIfNeeded(id
);
358 switch (resource_provider
->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
360 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
361 ASSERT_NE(0U, lock_gl
.texture_id());
362 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
363 context
->GetPixels(size
, format
, pixels
);
366 case ResourceProvider::RESOURCE_TYPE_BITMAP
: {
367 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
370 lock_software
.sk_bitmap()->getPixels(),
371 lock_software
.sk_bitmap()->getSize());
377 class ResourceProviderTest
378 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
380 explicit ResourceProviderTest(bool child_needs_sync_point
)
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL
),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
: {
387 scoped_ptr
<ResourceProviderContext
> context3d(
388 ResourceProviderContext::Create(shared_data_
.get()));
389 context3d_
= context3d
.get();
391 scoped_refptr
<TestContextProvider
> context_provider
=
392 TestContextProvider::Create(context3d
.Pass());
394 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
396 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
397 ResourceProviderContext::Create(shared_data_
.get());
398 child_context_
= child_context_owned
.get();
399 if (child_needs_sync_point
) {
400 child_output_surface_
=
401 FakeOutputSurface::Create3d(child_context_owned
.Pass());
403 child_output_surface_
= FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned
.Pass());
408 case ResourceProvider::RESOURCE_TYPE_BITMAP
:
409 output_surface_
= FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice
));
411 child_output_surface_
= FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice
));
415 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
416 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
418 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
419 gpu_memory_buffer_manager_
.reset(new TestGpuMemoryBufferManager
);
421 resource_provider_
= ResourceProvider::Create(
422 output_surface_
.get(), shared_bitmap_manager_
.get(),
423 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
425 child_resource_provider_
= ResourceProvider::Create(
426 child_output_surface_
.get(), shared_bitmap_manager_
.get(),
427 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
431 ResourceProviderTest() : ResourceProviderTest(true) {}
433 static void CollectResources(ReturnedResourceArray
* array
,
434 const ReturnedResourceArray
& returned
,
435 BlockingTaskRunner
* main_thread_task_runner
) {
436 array
->insert(array
->end(), returned
.begin(), returned
.end());
439 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
440 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
443 static void SetResourceFilter(ResourceProvider
* resource_provider
,
446 ResourceProvider::ScopedSamplerGL
sampler(
447 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
450 ResourceProviderContext
* context() { return context3d_
; }
452 ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
454 bool* release_called
,
455 uint32
* sync_point
) {
456 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
457 unsigned texture
= child_context_
->createTexture();
458 gpu::Mailbox gpu_mailbox
;
459 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
460 child_context_
->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
,
462 *sync_point
= child_context_
->insertSyncPoint();
463 EXPECT_LT(0u, *sync_point
);
465 scoped_ptr
<SharedBitmap
> shared_bitmap
;
466 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
467 SingleReleaseCallbackImpl::Create(base::Bind(
468 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
469 release_called
, release_sync_point
, lost_resource
));
470 return child_resource_provider_
->CreateResourceFromTextureMailbox(
471 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
474 gfx::Size
size(64, 64);
475 scoped_ptr
<SharedBitmap
> shared_bitmap(
476 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, 0));
478 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
479 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
480 SingleReleaseCallbackImpl::Create(base::Bind(
481 ReleaseSharedBitmapCallback
, base::Passed(&shared_bitmap
),
482 release_called
, release_sync_point
, lost_resource
));
483 return child_resource_provider_
->CreateResourceFromTextureMailbox(
484 TextureMailbox(shared_bitmap_ptr
, size
), callback
.Pass());
489 scoped_ptr
<ContextSharedData
> shared_data_
;
490 ResourceProviderContext
* context3d_
;
491 ResourceProviderContext
* child_context_
;
492 FakeOutputSurfaceClient output_surface_client_
;
493 FakeOutputSurfaceClient child_output_surface_client_
;
494 scoped_ptr
<OutputSurface
> output_surface_
;
495 scoped_ptr
<OutputSurface
> child_output_surface_
;
496 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
497 scoped_ptr
<ResourceProvider
> resource_provider_
;
498 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
499 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
500 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
503 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
504 ResourceProvider
* resource_provider
,
505 ResourceProviderContext
* context
) {
506 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
508 gfx::Size
size(1, 1);
509 ResourceFormat format
= RGBA_8888
;
510 size_t pixel_size
= TextureSizeBytes(size
, format
);
511 ASSERT_EQ(4U, pixel_size
);
513 ResourceId id
= resource_provider
->CreateResource(
514 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
515 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
516 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
517 EXPECT_EQ(0u, context
->NumTextures());
519 uint8_t data
[4] = { 1, 2, 3, 4 };
520 resource_provider
->CopyToResource(id
, data
, size
);
521 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
522 EXPECT_EQ(1u, context
->NumTextures());
524 uint8_t result
[4] = { 0 };
525 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
526 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
528 resource_provider
->DeleteResource(id
);
529 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
530 if (expected_default_type
== ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
531 EXPECT_EQ(0u, context
->NumTextures());
534 TEST_P(ResourceProviderTest
, Basic
) {
535 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
538 TEST_P(ResourceProviderTest
, Upload
) {
539 gfx::Size
size(2, 2);
540 ResourceFormat format
= RGBA_8888
;
541 size_t pixel_size
= TextureSizeBytes(size
, format
);
542 ASSERT_EQ(16U, pixel_size
);
544 ResourceId id
= resource_provider_
->CreateResource(
545 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
547 uint8_t image
[16] = { 0 };
548 gfx::Rect
image_rect(size
);
549 resource_provider_
->SetPixels(
550 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
552 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
555 uint8_t result
[16] = { 0 };
557 gfx::Rect
source_rect(0, 0, 1, 1);
558 gfx::Vector2d
dest_offset(0, 0);
559 resource_provider_
->SetPixels(
560 id
, image
, image_rect
, source_rect
, dest_offset
);
562 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
564 resource_provider_
.get(), context(), id
, size
, format
, result
);
565 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
568 gfx::Rect
source_rect(0, 0, 1, 1);
569 gfx::Vector2d
dest_offset(1, 1);
570 resource_provider_
->SetPixels(
571 id
, image
, image_rect
, source_rect
, dest_offset
);
573 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
575 resource_provider_
.get(), context(), id
, size
, format
, result
);
576 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
579 gfx::Rect
source_rect(1, 0, 1, 1);
580 gfx::Vector2d
dest_offset(0, 1);
581 resource_provider_
->SetPixels(
582 id
, image
, image_rect
, source_rect
, dest_offset
);
584 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
586 resource_provider_
.get(), context(), id
, size
, format
, result
);
587 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
590 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
591 gfx::Rect
source_rect(100, 100, 1, 1);
592 gfx::Vector2d
dest_offset(1, 0);
593 resource_provider_
->SetPixels(
594 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
596 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
598 resource_provider_
.get(), context(), id
, size
, format
, result
);
599 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
602 resource_provider_
->DeleteResource(id
);
605 TEST_P(ResourceProviderTest
, SimpleUpload
) {
606 gfx::Size
size(2, 2);
607 ResourceFormat format
= RGBA_8888
;
608 size_t pixel_size
= TextureSizeBytes(size
, format
);
609 ASSERT_EQ(16U, pixel_size
);
611 ResourceId id
= resource_provider_
->CreateResource(
612 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
614 uint8_t image
[16] = {0};
615 resource_provider_
->CopyToResource(id
, image
, size
);
617 uint8_t result
[16] = {0};
618 uint8_t expected
[16] = {0};
619 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
621 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
624 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
626 resource_provider_
->CopyToResource(id
, image
, size
);
628 uint8_t result
[16] = {0};
629 uint8_t expected
[16] = {
630 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
631 GetResourcePixels(resource_provider_
.get(), context(), id
, size
, format
,
633 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
637 TEST_P(ResourceProviderTest
, TransferGLResources
) {
638 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
640 gfx::Size
size(1, 1);
641 ResourceFormat format
= RGBA_8888
;
642 size_t pixel_size
= TextureSizeBytes(size
, format
);
643 ASSERT_EQ(4U, pixel_size
);
645 ResourceId id1
= child_resource_provider_
->CreateResource(
646 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
647 uint8_t data1
[4] = { 1, 2, 3, 4 };
648 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
650 ResourceId id2
= child_resource_provider_
->CreateResource(
651 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
652 uint8_t data2
[4] = { 5, 5, 5, 5 };
653 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
655 ResourceId id3
= child_resource_provider_
->CreateResource(
656 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
658 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
659 child_resource_provider_
.get(), id3
);
660 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
663 GLuint external_texture_id
= child_context_
->createExternalTexture();
665 gpu::Mailbox external_mailbox
;
666 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
667 child_context_
->produceTextureDirectCHROMIUM(
668 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
669 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
670 ResourceId id4
= child_resource_provider_
->CreateResourceFromTextureMailbox(
671 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
672 external_sync_point
),
673 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
675 ReturnedResourceArray returned_to_child
;
677 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
679 // Transfer some resources to the parent.
680 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
681 resource_ids_to_transfer
.push_back(id1
);
682 resource_ids_to_transfer
.push_back(id2
);
683 resource_ids_to_transfer
.push_back(id3
);
684 resource_ids_to_transfer
.push_back(id4
);
685 TransferableResourceArray list
;
686 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
688 ASSERT_EQ(4u, list
.size());
689 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
690 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
691 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
692 list
[1].mailbox_holder
.sync_point
);
693 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
694 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
695 list
[2].mailbox_holder
.sync_point
);
696 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
697 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
698 list
[0].mailbox_holder
.texture_target
);
699 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
700 list
[1].mailbox_holder
.texture_target
);
701 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
702 list
[2].mailbox_holder
.texture_target
);
703 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
704 list
[3].mailbox_holder
.texture_target
);
705 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
706 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
707 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
708 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
709 resource_provider_
->ReceiveFromChild(child_id
, list
);
710 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
711 context3d_
->last_waited_sync_point());
713 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
714 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
717 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
718 context3d_
->last_waited_sync_point());
719 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
720 resource_ids_to_receive
.insert(id1
);
721 resource_ids_to_receive
.insert(id2
);
722 resource_ids_to_receive
.insert(id3
);
723 resource_ids_to_receive
.insert(id4
);
724 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
725 resource_ids_to_receive
);
728 EXPECT_EQ(4u, resource_provider_
->num_resources());
729 ResourceProvider::ResourceIdMap resource_map
=
730 resource_provider_
->GetChildToParentMap(child_id
);
731 ResourceId mapped_id1
= resource_map
[id1
];
732 ResourceId mapped_id2
= resource_map
[id2
];
733 ResourceId mapped_id3
= resource_map
[id3
];
734 ResourceId mapped_id4
= resource_map
[id4
];
735 EXPECT_NE(0u, mapped_id1
);
736 EXPECT_NE(0u, mapped_id2
);
737 EXPECT_NE(0u, mapped_id3
);
738 EXPECT_NE(0u, mapped_id4
);
739 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
740 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
741 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
742 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
744 uint8_t result
[4] = { 0 };
746 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
747 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
750 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
751 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
754 // Check that transfering again the same resource from the child to the
756 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
757 resource_ids_to_transfer
.push_back(id1
);
758 resource_ids_to_transfer
.push_back(id2
);
759 resource_ids_to_transfer
.push_back(id3
);
760 TransferableResourceArray list
;
761 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
763 EXPECT_EQ(3u, list
.size());
764 EXPECT_EQ(id1
, list
[0].id
);
765 EXPECT_EQ(id2
, list
[1].id
);
766 EXPECT_EQ(id3
, list
[2].id
);
767 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
768 list
[0].mailbox_holder
.texture_target
);
769 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
770 list
[1].mailbox_holder
.texture_target
);
771 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
772 list
[2].mailbox_holder
.texture_target
);
773 ReturnedResourceArray returned
;
774 TransferableResource::ReturnResources(list
, &returned
);
775 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
776 // ids were exported twice, we returned them only once, they should still
778 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
779 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
780 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
783 EXPECT_EQ(0u, returned_to_child
.size());
785 // Transfer resources back from the parent to the child. Set no resources as
787 ResourceProvider::ResourceIdSet no_resources
;
788 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
790 ASSERT_EQ(4u, returned_to_child
.size());
791 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
792 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
793 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
794 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
795 EXPECT_FALSE(returned_to_child
[0].lost
);
796 EXPECT_FALSE(returned_to_child
[1].lost
);
797 EXPECT_FALSE(returned_to_child
[2].lost
);
798 EXPECT_FALSE(returned_to_child
[3].lost
);
799 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
800 returned_to_child
.clear();
802 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
803 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
804 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
805 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
808 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
809 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
811 ASSERT_NE(0U, lock
.texture_id());
812 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
813 child_context_
->GetPixels(size
, format
, result
);
814 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
817 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
818 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
820 ASSERT_NE(0U, lock
.texture_id());
821 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
822 child_context_
->GetPixels(size
, format
, result
);
823 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
826 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
827 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
829 ASSERT_NE(0U, lock
.texture_id());
830 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
833 // Transfer resources to the parent again.
834 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
835 resource_ids_to_transfer
.push_back(id1
);
836 resource_ids_to_transfer
.push_back(id2
);
837 resource_ids_to_transfer
.push_back(id3
);
838 resource_ids_to_transfer
.push_back(id4
);
839 TransferableResourceArray list
;
840 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
842 ASSERT_EQ(4u, list
.size());
843 EXPECT_EQ(id1
, list
[0].id
);
844 EXPECT_EQ(id2
, list
[1].id
);
845 EXPECT_EQ(id3
, list
[2].id
);
846 EXPECT_EQ(id4
, list
[3].id
);
847 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
848 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
849 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
850 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
851 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
852 list
[0].mailbox_holder
.texture_target
);
853 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
854 list
[1].mailbox_holder
.texture_target
);
855 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
856 list
[2].mailbox_holder
.texture_target
);
857 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
858 list
[3].mailbox_holder
.texture_target
);
859 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
860 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
861 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
862 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
863 resource_provider_
->ReceiveFromChild(child_id
, list
);
864 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
865 resource_ids_to_receive
.insert(id1
);
866 resource_ids_to_receive
.insert(id2
);
867 resource_ids_to_receive
.insert(id3
);
868 resource_ids_to_receive
.insert(id4
);
869 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
870 resource_ids_to_receive
);
873 EXPECT_EQ(0u, returned_to_child
.size());
875 EXPECT_EQ(4u, resource_provider_
->num_resources());
876 resource_provider_
->DestroyChild(child_id
);
877 EXPECT_EQ(0u, resource_provider_
->num_resources());
879 ASSERT_EQ(4u, returned_to_child
.size());
880 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
881 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
882 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
883 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
884 EXPECT_FALSE(returned_to_child
[0].lost
);
885 EXPECT_FALSE(returned_to_child
[1].lost
);
886 EXPECT_FALSE(returned_to_child
[2].lost
);
887 EXPECT_FALSE(returned_to_child
[3].lost
);
890 class ResourceProviderTestNoSyncPoint
: public ResourceProviderTest
{
892 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
893 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
, GetParam());
897 TEST_P(ResourceProviderTestNoSyncPoint
, TransferGLResources
) {
898 gfx::Size
size(1, 1);
899 ResourceFormat format
= RGBA_8888
;
900 size_t pixel_size
= TextureSizeBytes(size
, format
);
901 ASSERT_EQ(4U, pixel_size
);
903 ResourceId id1
= child_resource_provider_
->CreateResource(
904 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
905 uint8_t data1
[4] = {1, 2, 3, 4};
906 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
908 ResourceId id2
= child_resource_provider_
->CreateResource(
909 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
911 // Ensure locking the memory buffer doesn't create an unnecessary sync
913 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
914 child_resource_provider_
.get(), id2
);
915 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
918 GLuint external_texture_id
= child_context_
->createExternalTexture();
920 // A sync point is specified directly and should be used.
921 gpu::Mailbox external_mailbox
;
922 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
923 child_context_
->produceTextureDirectCHROMIUM(
924 external_texture_id
, GL_TEXTURE_EXTERNAL_OES
, external_mailbox
.name
);
925 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
926 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
927 TextureMailbox(external_mailbox
, GL_TEXTURE_EXTERNAL_OES
,
928 external_sync_point
),
929 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
931 ReturnedResourceArray returned_to_child
;
933 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
934 resource_provider_
->SetChildNeedsSyncPoints(child_id
, false);
936 // Transfer some resources to the parent.
937 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
938 resource_ids_to_transfer
.push_back(id1
);
939 resource_ids_to_transfer
.push_back(id2
);
940 resource_ids_to_transfer
.push_back(id3
);
941 TransferableResourceArray list
;
942 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
944 ASSERT_EQ(3u, list
.size());
945 // Standard resources shouldn't require creating and sending a sync point.
946 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
947 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
948 // A given sync point should be passed through.
949 EXPECT_EQ(external_sync_point
, list
[2].mailbox_holder
.sync_point
);
950 resource_provider_
->ReceiveFromChild(child_id
, list
);
952 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
953 resource_ids_to_receive
.insert(id1
);
954 resource_ids_to_receive
.insert(id2
);
955 resource_ids_to_receive
.insert(id3
);
956 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
957 resource_ids_to_receive
);
961 EXPECT_EQ(0u, returned_to_child
.size());
963 // Transfer resources back from the parent to the child. Set no resources as
965 ResourceProvider::ResourceIdSet no_resources
;
966 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
968 ASSERT_EQ(3u, returned_to_child
.size());
969 std::map
<ResourceId
, unsigned int> returned_sync_points
;
970 for (const auto& returned
: returned_to_child
)
971 returned_sync_points
[returned
.id
] = returned
.sync_point
;
973 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
974 // No new sync point should be created transferring back.
975 EXPECT_TRUE(returned_sync_points
.find(id1
) != returned_sync_points
.end());
976 EXPECT_EQ(0u, returned_sync_points
[id1
]);
977 EXPECT_TRUE(returned_sync_points
.find(id2
) != returned_sync_points
.end());
978 EXPECT_EQ(0u, returned_sync_points
[id2
]);
979 // Original sync point given should be returned.
980 EXPECT_TRUE(returned_sync_points
.find(id3
) != returned_sync_points
.end());
981 EXPECT_EQ(external_sync_point
, returned_sync_points
[id3
]);
982 EXPECT_FALSE(returned_to_child
[0].lost
);
983 EXPECT_FALSE(returned_to_child
[1].lost
);
984 EXPECT_FALSE(returned_to_child
[2].lost
);
985 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
986 returned_to_child
.clear();
989 resource_provider_
->DestroyChild(child_id
);
992 INSTANTIATE_TEST_CASE_P(
993 ResourceProviderTests
,
994 ResourceProviderTestNoSyncPoint
,
995 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
));
997 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
998 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1000 gfx::Size
size(1, 1);
1001 ResourceFormat format
= RGBA_8888
;
1003 ResourceId id1
= child_resource_provider_
->CreateResource(
1004 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1005 uint8_t data1
[4] = {1, 2, 3, 4};
1006 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1008 ReturnedResourceArray returned_to_child
;
1010 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1012 // Transfer some resources to the parent.
1013 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1014 resource_ids_to_transfer
.push_back(id1
);
1015 TransferableResourceArray list
;
1016 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1018 ASSERT_EQ(1u, list
.size());
1019 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1021 resource_provider_
->ReceiveFromChild(child_id
, list
);
1023 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
1024 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
1027 resource_provider_
->DeclareUsedResourcesFromChild(
1028 child_id
, ResourceProvider::ResourceIdSet());
1029 EXPECT_EQ(0u, returned_to_child
.size());
1032 EXPECT_EQ(1u, returned_to_child
.size());
1033 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1036 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
1037 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
1039 child_resource_provider_
->DeleteResource(id1
);
1040 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1041 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1044 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1045 resource_provider_
->DestroyChild(child_id
);
1048 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
1049 // Overlays only supported on the GL path.
1050 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1053 uint32 sync_point
= 0;
1054 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1055 mailbox
.set_allow_overlay(true);
1056 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
1057 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1058 ResourceId id1
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1059 mailbox
, release_callback
.Pass());
1061 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
1062 mailbox2
.set_allow_overlay(false);
1063 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
1064 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
1065 ResourceId id2
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1066 mailbox2
, release_callback2
.Pass());
1068 ReturnedResourceArray returned_to_child
;
1070 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1072 // Transfer some resources to the parent.
1073 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1074 resource_ids_to_transfer
.push_back(id1
);
1075 resource_ids_to_transfer
.push_back(id2
);
1076 TransferableResourceArray list
;
1077 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1079 ASSERT_EQ(2u, list
.size());
1080 resource_provider_
->ReceiveFromChild(child_id
, list
);
1081 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
1082 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
1084 resource_provider_
->DeclareUsedResourcesFromChild(
1085 child_id
, ResourceProvider::ResourceIdSet());
1087 EXPECT_EQ(2u, returned_to_child
.size());
1088 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1090 child_resource_provider_
->DeleteResource(id1
);
1091 child_resource_provider_
->DeleteResource(id2
);
1092 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1094 resource_provider_
->DestroyChild(child_id
);
1097 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
1098 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1101 gfx::Size
size(1, 1);
1102 ResourceFormat format
= RGBA_8888
;
1103 size_t pixel_size
= TextureSizeBytes(size
, format
);
1104 ASSERT_EQ(4U, pixel_size
);
1106 ResourceId id1
= child_resource_provider_
->CreateResource(
1107 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1108 uint8_t data1
[4] = { 1, 2, 3, 4 };
1109 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1111 ResourceId id2
= child_resource_provider_
->CreateResource(
1112 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1113 uint8_t data2
[4] = { 5, 5, 5, 5 };
1114 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1116 scoped_ptr
<SharedBitmap
> shared_bitmap(CreateAndFillSharedBitmap(
1117 shared_bitmap_manager_
.get(), gfx::Size(1, 1), 0));
1118 SharedBitmap
* shared_bitmap_ptr
= shared_bitmap
.get();
1119 ResourceId id3
= child_resource_provider_
->CreateResourceFromTextureMailbox(
1120 TextureMailbox(shared_bitmap_ptr
, gfx::Size(1, 1)),
1121 SingleReleaseCallbackImpl::Create(base::Bind(
1122 &SharedBitmapReleaseCallback
, base::Passed(&shared_bitmap
))));
1124 ReturnedResourceArray returned_to_child
;
1126 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1128 // Transfer some resources to the parent.
1129 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1130 resource_ids_to_transfer
.push_back(id1
);
1131 resource_ids_to_transfer
.push_back(id2
);
1132 resource_ids_to_transfer
.push_back(id3
);
1133 TransferableResourceArray list
;
1134 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1136 ASSERT_EQ(3u, list
.size());
1137 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1138 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1139 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1140 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1141 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1142 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1143 resource_provider_
->ReceiveFromChild(child_id
, list
);
1144 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1145 resource_ids_to_receive
.insert(id1
);
1146 resource_ids_to_receive
.insert(id2
);
1147 resource_ids_to_receive
.insert(id3
);
1148 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1149 resource_ids_to_receive
);
1152 EXPECT_EQ(3u, resource_provider_
->num_resources());
1153 ResourceProvider::ResourceIdMap resource_map
=
1154 resource_provider_
->GetChildToParentMap(child_id
);
1155 ResourceId mapped_id1
= resource_map
[id1
];
1156 ResourceId mapped_id2
= resource_map
[id2
];
1157 ResourceId mapped_id3
= resource_map
[id3
];
1158 EXPECT_NE(0u, mapped_id1
);
1159 EXPECT_NE(0u, mapped_id2
);
1160 EXPECT_NE(0u, mapped_id3
);
1161 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1162 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1163 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1165 uint8_t result
[4] = { 0 };
1167 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1168 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1171 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1172 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1175 // Check that transfering again the same resource from the child to the
1177 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1178 resource_ids_to_transfer
.push_back(id1
);
1179 resource_ids_to_transfer
.push_back(id2
);
1180 TransferableResourceArray list
;
1181 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1183 EXPECT_EQ(2u, list
.size());
1184 EXPECT_EQ(id1
, list
[0].id
);
1185 EXPECT_EQ(id2
, list
[1].id
);
1186 ReturnedResourceArray returned
;
1187 TransferableResource::ReturnResources(list
, &returned
);
1188 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1189 // ids were exported twice, we returned them only once, they should still
1191 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1192 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1195 EXPECT_EQ(0u, returned_to_child
.size());
1197 // Transfer resources back from the parent to the child. Set no resources as
1199 ResourceProvider::ResourceIdSet no_resources
;
1200 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1202 ASSERT_EQ(3u, returned_to_child
.size());
1203 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1204 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1205 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1206 std::set
<ResourceId
> expected_ids
;
1207 expected_ids
.insert(id1
);
1208 expected_ids
.insert(id2
);
1209 expected_ids
.insert(id3
);
1210 std::set
<ResourceId
> returned_ids
;
1211 for (unsigned i
= 0; i
< 3; i
++)
1212 returned_ids
.insert(returned_to_child
[i
].id
);
1213 EXPECT_EQ(expected_ids
, returned_ids
);
1214 EXPECT_FALSE(returned_to_child
[0].lost
);
1215 EXPECT_FALSE(returned_to_child
[1].lost
);
1216 EXPECT_FALSE(returned_to_child
[2].lost
);
1217 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1218 returned_to_child
.clear();
1220 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1221 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1222 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1225 ResourceProvider::ScopedReadLockSoftware
lock(
1226 child_resource_provider_
.get(), id1
);
1227 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1228 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1229 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1230 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1233 ResourceProvider::ScopedReadLockSoftware
lock(
1234 child_resource_provider_
.get(), id2
);
1235 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1236 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1237 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1238 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1241 // Transfer resources to the parent again.
1242 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1243 resource_ids_to_transfer
.push_back(id1
);
1244 resource_ids_to_transfer
.push_back(id2
);
1245 resource_ids_to_transfer
.push_back(id3
);
1246 TransferableResourceArray list
;
1247 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1249 ASSERT_EQ(3u, list
.size());
1250 EXPECT_EQ(id1
, list
[0].id
);
1251 EXPECT_EQ(id2
, list
[1].id
);
1252 EXPECT_EQ(id3
, list
[2].id
);
1253 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1254 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1255 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1256 resource_provider_
->ReceiveFromChild(child_id
, list
);
1257 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1258 resource_ids_to_receive
.insert(id1
);
1259 resource_ids_to_receive
.insert(id2
);
1260 resource_ids_to_receive
.insert(id3
);
1261 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1262 resource_ids_to_receive
);
1265 EXPECT_EQ(0u, returned_to_child
.size());
1267 EXPECT_EQ(3u, resource_provider_
->num_resources());
1268 resource_provider_
->DestroyChild(child_id
);
1269 EXPECT_EQ(0u, resource_provider_
->num_resources());
1271 ASSERT_EQ(3u, returned_to_child
.size());
1272 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1273 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1274 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1275 std::set
<ResourceId
> expected_ids
;
1276 expected_ids
.insert(id1
);
1277 expected_ids
.insert(id2
);
1278 expected_ids
.insert(id3
);
1279 std::set
<ResourceId
> returned_ids
;
1280 for (unsigned i
= 0; i
< 3; i
++)
1281 returned_ids
.insert(returned_to_child
[i
].id
);
1282 EXPECT_EQ(expected_ids
, returned_ids
);
1283 EXPECT_FALSE(returned_to_child
[0].lost
);
1284 EXPECT_FALSE(returned_to_child
[1].lost
);
1285 EXPECT_FALSE(returned_to_child
[2].lost
);
1288 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1289 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1292 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1293 ResourceProviderContext::Create(shared_data_
.get()));
1295 FakeOutputSurfaceClient child_output_surface_client
;
1296 scoped_ptr
<OutputSurface
> child_output_surface(
1297 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1298 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1300 scoped_ptr
<ResourceProvider
> child_resource_provider(ResourceProvider::Create(
1301 child_output_surface
.get(), shared_bitmap_manager_
.get(),
1302 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
1304 gfx::Size
size(1, 1);
1305 ResourceFormat format
= RGBA_8888
;
1306 size_t pixel_size
= TextureSizeBytes(size
, format
);
1307 ASSERT_EQ(4U, pixel_size
);
1309 ResourceId id1
= child_resource_provider
->CreateResource(
1310 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1311 uint8_t data1
[4] = { 1, 2, 3, 4 };
1312 child_resource_provider
->CopyToResource(id1
, data1
, size
);
1314 ReturnedResourceArray returned_to_child
;
1316 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1318 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1319 resource_ids_to_transfer
.push_back(id1
);
1320 TransferableResourceArray list
;
1321 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1323 ASSERT_EQ(1u, list
.size());
1324 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1325 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1326 list
[0].mailbox_holder
.texture_target
);
1327 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1328 resource_provider_
->ReceiveFromChild(child_id
, list
);
1331 EXPECT_EQ(0u, resource_provider_
->num_resources());
1332 ASSERT_EQ(1u, returned_to_child
.size());
1333 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1334 ResourceProvider::ResourceIdMap resource_map
=
1335 resource_provider_
->GetChildToParentMap(child_id
);
1336 ResourceId mapped_id1
= resource_map
[id1
];
1337 EXPECT_EQ(0u, mapped_id1
);
1339 resource_provider_
->DestroyChild(child_id
);
1340 EXPECT_EQ(0u, resource_provider_
->num_resources());
1342 ASSERT_EQ(1u, returned_to_child
.size());
1343 EXPECT_FALSE(returned_to_child
[0].lost
);
1346 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1347 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
1350 gfx::Size
size(1, 1);
1351 ResourceFormat format
= RGBA_8888
;
1352 size_t pixel_size
= TextureSizeBytes(size
, format
);
1353 ASSERT_EQ(4U, pixel_size
);
1355 ResourceId id1
= child_resource_provider_
->CreateResource(
1356 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1357 uint8_t data1
[4] = { 1, 2, 3, 4 };
1358 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1360 ReturnedResourceArray returned_to_child
;
1362 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1364 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1365 resource_ids_to_transfer
.push_back(id1
);
1366 TransferableResourceArray list
;
1367 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1369 ASSERT_EQ(1u, list
.size());
1371 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1372 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1373 resource_provider_
->ReceiveFromChild(child_id
, list
);
1376 EXPECT_EQ(1u, resource_provider_
->num_resources());
1377 EXPECT_EQ(0u, returned_to_child
.size());
1379 ResourceProvider::ResourceIdMap resource_map
=
1380 resource_provider_
->GetChildToParentMap(child_id
);
1381 ResourceId mapped_id1
= resource_map
[id1
];
1382 EXPECT_NE(0u, mapped_id1
);
1384 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1386 EXPECT_FALSE(lock
.valid());
1389 resource_provider_
->DestroyChild(child_id
);
1390 EXPECT_EQ(0u, resource_provider_
->num_resources());
1392 ASSERT_EQ(1u, returned_to_child
.size());
1393 EXPECT_FALSE(returned_to_child
[0].lost
);
1396 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1397 gfx::Size
size(1, 1);
1398 ResourceFormat format
= RGBA_8888
;
1399 size_t pixel_size
= TextureSizeBytes(size
, format
);
1400 ASSERT_EQ(4U, pixel_size
);
1402 ResourceId id1
= child_resource_provider_
->CreateResource(
1403 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1404 uint8_t data1
[4] = { 1, 2, 3, 4 };
1405 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1407 ResourceId id2
= child_resource_provider_
->CreateResource(
1408 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1409 uint8_t data2
[4] = {5, 5, 5, 5};
1410 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1412 ReturnedResourceArray returned_to_child
;
1414 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1416 // Transfer some resources to the parent.
1417 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1418 resource_ids_to_transfer
.push_back(id1
);
1419 resource_ids_to_transfer
.push_back(id2
);
1420 TransferableResourceArray list
;
1421 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1423 ASSERT_EQ(2u, list
.size());
1424 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1425 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1426 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1428 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1429 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1430 resource_provider_
->ReceiveFromChild(child_id
, list
);
1431 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1432 resource_ids_to_receive
.insert(id1
);
1433 resource_ids_to_receive
.insert(id2
);
1434 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1435 resource_ids_to_receive
);
1438 EXPECT_EQ(2u, resource_provider_
->num_resources());
1439 ResourceProvider::ResourceIdMap resource_map
=
1440 resource_provider_
->GetChildToParentMap(child_id
);
1441 ResourceId mapped_id1
= resource_map
[id1
];
1442 ResourceId mapped_id2
= resource_map
[id2
];
1443 EXPECT_NE(0u, mapped_id1
);
1444 EXPECT_NE(0u, mapped_id2
);
1445 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1446 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1449 // The parent transfers the resources to the grandparent.
1450 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1451 resource_ids_to_transfer
.push_back(mapped_id1
);
1452 resource_ids_to_transfer
.push_back(mapped_id2
);
1453 TransferableResourceArray list
;
1454 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1456 ASSERT_EQ(2u, list
.size());
1457 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1458 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1459 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1461 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1462 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1464 // Release the resource in the parent. Set no resources as being in use. The
1465 // resources are exported so that can't be transferred back yet.
1466 ResourceProvider::ResourceIdSet no_resources
;
1467 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1469 EXPECT_EQ(0u, returned_to_child
.size());
1470 EXPECT_EQ(2u, resource_provider_
->num_resources());
1472 // Return the resources from the grandparent to the parent. They should be
1473 // returned to the child then.
1474 EXPECT_EQ(2u, list
.size());
1475 EXPECT_EQ(mapped_id1
, list
[0].id
);
1476 EXPECT_EQ(mapped_id2
, list
[1].id
);
1477 ReturnedResourceArray returned
;
1478 TransferableResource::ReturnResources(list
, &returned
);
1479 resource_provider_
->ReceiveReturnsFromParent(returned
);
1481 EXPECT_EQ(0u, resource_provider_
->num_resources());
1482 ASSERT_EQ(2u, returned_to_child
.size());
1483 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1484 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1485 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1487 EXPECT_FALSE(returned_to_child
[0].lost
);
1488 EXPECT_FALSE(returned_to_child
[1].lost
);
1492 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1493 gfx::Size
size(1, 1);
1494 ResourceFormat format
= RGBA_8888
;
1495 size_t pixel_size
= TextureSizeBytes(size
, format
);
1496 ASSERT_EQ(4U, pixel_size
);
1498 ResourceId id1
= child_resource_provider_
->CreateResource(
1499 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1500 uint8_t data1
[4] = {1, 2, 3, 4};
1501 child_resource_provider_
->CopyToResource(id1
, data1
, size
);
1503 ResourceId id2
= child_resource_provider_
->CreateResource(
1504 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1505 uint8_t data2
[4] = {5, 5, 5, 5};
1506 child_resource_provider_
->CopyToResource(id2
, data2
, size
);
1508 ReturnedResourceArray returned_to_child
;
1510 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1512 // Transfer some resources to the parent.
1513 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1514 resource_ids_to_transfer
.push_back(id1
);
1515 resource_ids_to_transfer
.push_back(id2
);
1516 TransferableResourceArray list
;
1517 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1519 ASSERT_EQ(2u, list
.size());
1520 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1521 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1522 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1524 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1525 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1526 resource_provider_
->ReceiveFromChild(child_id
, list
);
1527 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1528 resource_ids_to_receive
.insert(id1
);
1529 resource_ids_to_receive
.insert(id2
);
1530 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1531 resource_ids_to_receive
);
1534 EXPECT_EQ(2u, resource_provider_
->num_resources());
1535 ResourceProvider::ResourceIdMap resource_map
=
1536 resource_provider_
->GetChildToParentMap(child_id
);
1537 ResourceId mapped_id1
= resource_map
[id1
];
1538 ResourceId mapped_id2
= resource_map
[id2
];
1539 EXPECT_NE(0u, mapped_id1
);
1540 EXPECT_NE(0u, mapped_id2
);
1541 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1542 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1545 // The parent transfers the resources to the grandparent.
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1547 resource_ids_to_transfer
.push_back(mapped_id1
);
1548 resource_ids_to_transfer
.push_back(mapped_id2
);
1549 TransferableResourceArray list
;
1550 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1552 ASSERT_EQ(2u, list
.size());
1553 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1554 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1555 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1557 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1558 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1560 // Release the resource in the parent. Set no resources as being in use. The
1561 // resources are exported so that can't be transferred back yet.
1562 ResourceProvider::ResourceIdSet no_resources
;
1563 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1565 // Destroy the child, the resources should not be returned yet.
1566 EXPECT_EQ(0u, returned_to_child
.size());
1567 EXPECT_EQ(2u, resource_provider_
->num_resources());
1569 resource_provider_
->DestroyChild(child_id
);
1571 EXPECT_EQ(2u, resource_provider_
->num_resources());
1572 ASSERT_EQ(0u, returned_to_child
.size());
1574 // Return a resource from the grandparent, it should be returned at this
1576 EXPECT_EQ(2u, list
.size());
1577 EXPECT_EQ(mapped_id1
, list
[0].id
);
1578 EXPECT_EQ(mapped_id2
, list
[1].id
);
1579 TransferableResourceArray return_list
;
1580 return_list
.push_back(list
[1]);
1582 ReturnedResourceArray returned
;
1583 TransferableResource::ReturnResources(return_list
, &returned
);
1584 resource_provider_
->ReceiveReturnsFromParent(returned
);
1586 EXPECT_EQ(1u, resource_provider_
->num_resources());
1587 ASSERT_EQ(1u, returned_to_child
.size());
1588 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1589 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1591 EXPECT_FALSE(returned_to_child
[0].lost
);
1592 returned_to_child
.clear();
1594 // Destroy the parent resource provider. The resource that's left should be
1595 // lost at this point, and returned.
1596 resource_provider_
= nullptr;
1597 ASSERT_EQ(1u, returned_to_child
.size());
1598 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
1599 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1601 EXPECT_TRUE(returned_to_child
[0].lost
);
1605 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1606 gfx::Size
size(1, 1);
1607 ResourceFormat format
= RGBA_8888
;
1608 size_t pixel_size
= TextureSizeBytes(size
, format
);
1609 ASSERT_EQ(4U, pixel_size
);
1611 ResourceId id
= child_resource_provider_
->CreateResource(
1612 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1613 uint8_t data
[4] = { 1, 2, 3, 4 };
1614 child_resource_provider_
->CopyToResource(id
, data
, size
);
1616 ReturnedResourceArray returned_to_child
;
1618 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1620 // Transfer some resource to the parent.
1621 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1622 resource_ids_to_transfer
.push_back(id
);
1623 TransferableResourceArray list
;
1624 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1626 ASSERT_EQ(1u, list
.size());
1627 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1628 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1629 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1630 resource_provider_
->ReceiveFromChild(child_id
, list
);
1631 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1632 resource_ids_to_receive
.insert(id
);
1633 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1634 resource_ids_to_receive
);
1637 // Delete textures in the child, while they are transfered.
1638 child_resource_provider_
->DeleteResource(id
);
1639 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1641 EXPECT_EQ(0u, returned_to_child
.size());
1643 // Transfer resources back from the parent to the child. Set no resources as
1645 ResourceProvider::ResourceIdSet no_resources
;
1646 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1648 ASSERT_EQ(1u, returned_to_child
.size());
1649 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1650 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1651 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1653 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1656 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1657 gfx::Size
size(1, 1);
1658 ResourceFormat format
= RGBA_8888
;
1659 size_t pixel_size
= TextureSizeBytes(size
, format
);
1660 ASSERT_EQ(4U, pixel_size
);
1662 ResourceId id
= child_resource_provider_
->CreateResource(
1663 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
1664 uint8_t data
[4] = {1, 2, 3, 4};
1665 child_resource_provider_
->CopyToResource(id
, data
, size
);
1667 ReturnedResourceArray returned_to_child
;
1669 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1670 const ResourceProvider::ResourceIdMap
& map
=
1671 resource_provider_
->GetChildToParentMap(child_id
);
1673 // Transfer some resource to the parent.
1674 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1675 resource_ids_to_transfer
.push_back(id
);
1676 TransferableResourceArray list
;
1677 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1679 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1680 resource_provider_
->ReceiveFromChild(child_id
, list
);
1681 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1682 resource_ids_to_receive
.insert(id
);
1683 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1684 resource_ids_to_receive
);
1686 TransferableResourceArray sent_to_top_level
;
1688 // Parent transfers to top-level.
1689 ASSERT_TRUE(map
.find(id
) != map
.end());
1690 ResourceId parent_id
= map
.find(id
)->second
;
1691 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1692 resource_ids_to_transfer
.push_back(parent_id
);
1693 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1694 &sent_to_top_level
);
1695 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1698 // Stop using resource.
1699 ResourceProvider::ResourceIdSet empty
;
1700 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1701 // Resource is not yet returned to the child, since it's in use by the
1703 EXPECT_TRUE(returned_to_child
.empty());
1706 // Send the resource to the parent again.
1707 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1708 resource_ids_to_transfer
.push_back(id
);
1709 TransferableResourceArray list
;
1710 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1712 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1713 resource_provider_
->ReceiveFromChild(child_id
, list
);
1714 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1715 resource_ids_to_receive
.insert(id
);
1716 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1717 resource_ids_to_receive
);
1720 // Receive returns back from top-level.
1721 ReturnedResourceArray returned
;
1722 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1723 resource_provider_
->ReceiveReturnsFromParent(returned
);
1724 // Resource is still not yet returned to the child, since it's declared used
1726 EXPECT_TRUE(returned_to_child
.empty());
1727 ASSERT_TRUE(map
.find(id
) != map
.end());
1728 ResourceId parent_id
= map
.find(id
)->second
;
1729 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1732 sent_to_top_level
.clear();
1733 // Parent transfers again to top-level.
1734 ASSERT_TRUE(map
.find(id
) != map
.end());
1735 ResourceId parent_id
= map
.find(id
)->second
;
1736 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1737 resource_ids_to_transfer
.push_back(parent_id
);
1738 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1739 &sent_to_top_level
);
1740 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1743 // Receive returns back from top-level.
1744 ReturnedResourceArray returned
;
1745 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1746 resource_provider_
->ReceiveReturnsFromParent(returned
);
1747 // Resource is still not yet returned to the child, since it's still
1748 // declared used in the parent.
1749 EXPECT_TRUE(returned_to_child
.empty());
1750 ASSERT_TRUE(map
.find(id
) != map
.end());
1751 ResourceId parent_id
= map
.find(id
)->second
;
1752 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1755 // Stop using resource.
1756 ResourceProvider::ResourceIdSet empty
;
1757 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1758 // Resource should have been returned to the child, since it's no longer in
1759 // use by the top-level.
1760 ASSERT_EQ(1u, returned_to_child
.size());
1761 EXPECT_EQ(id
, returned_to_child
[0].id
);
1762 EXPECT_EQ(2, returned_to_child
[0].count
);
1763 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1764 returned_to_child
.clear();
1765 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1769 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1771 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1772 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1773 new TextureStateTrackingContext
);
1774 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1776 FakeOutputSurfaceClient child_output_surface_client
;
1777 scoped_ptr
<OutputSurface
> child_output_surface(
1778 FakeOutputSurface::Create3d(child_context_owned
.Pass()));
1779 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1780 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1781 new TestSharedBitmapManager());
1783 scoped_ptr
<ResourceProvider
> child_resource_provider(
1784 ResourceProvider::Create(child_output_surface
.get(),
1785 shared_bitmap_manager
.get(), NULL
, NULL
, 0,
1788 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1789 new TextureStateTrackingContext
);
1790 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1792 FakeOutputSurfaceClient parent_output_surface_client
;
1793 scoped_ptr
<OutputSurface
> parent_output_surface(
1794 FakeOutputSurface::Create3d(parent_context_owned
.Pass()));
1795 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1797 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1798 ResourceProvider::Create(parent_output_surface
.get(),
1799 shared_bitmap_manager
.get(), NULL
, NULL
, 0,
1802 gfx::Size
size(1, 1);
1803 ResourceFormat format
= RGBA_8888
;
1804 int child_texture_id
= 1;
1805 int parent_texture_id
= 2;
1807 size_t pixel_size
= TextureSizeBytes(size
, format
);
1808 ASSERT_EQ(4U, pixel_size
);
1810 ResourceId id
= child_resource_provider
->CreateResource(
1811 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
1814 // The new texture is created with GL_LINEAR.
1815 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1816 .Times(2); // Once to create and once to allocate.
1817 EXPECT_CALL(*child_context
,
1818 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1819 EXPECT_CALL(*child_context
,
1820 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1823 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1826 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1827 EXPECT_CALL(*child_context
,
1828 texParameteri(GL_TEXTURE_2D
,
1829 GL_TEXTURE_POOL_CHROMIUM
,
1830 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1831 child_resource_provider
->AllocateForTesting(id
);
1832 Mock::VerifyAndClearExpectations(child_context
);
1834 uint8_t data
[4] = { 1, 2, 3, 4 };
1836 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1837 child_resource_provider
->CopyToResource(id
, data
, size
);
1838 Mock::VerifyAndClearExpectations(child_context
);
1840 // The texture is set to |child_filter| in the child.
1841 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1842 if (child_filter
!= GL_LINEAR
) {
1845 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1848 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1850 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1851 Mock::VerifyAndClearExpectations(child_context
);
1853 ReturnedResourceArray returned_to_child
;
1854 int child_id
= parent_resource_provider
->CreateChild(
1855 GetReturnCallback(&returned_to_child
));
1857 // Transfer some resource to the parent.
1858 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1859 resource_ids_to_transfer
.push_back(id
);
1860 TransferableResourceArray list
;
1862 EXPECT_CALL(*child_context
,
1863 produceTextureDirectCHROMIUM(_
, GL_TEXTURE_2D
, _
));
1864 EXPECT_CALL(*child_context
, insertSyncPoint());
1865 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1867 Mock::VerifyAndClearExpectations(child_context
);
1869 ASSERT_EQ(1u, list
.size());
1870 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1872 EXPECT_CALL(*parent_context
,
1873 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, _
))
1874 .WillOnce(Return(parent_texture_id
));
1876 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1878 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1879 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1882 Mock::VerifyAndClearExpectations(parent_context
);
1884 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
1885 resource_ids_to_receive
.insert(id
);
1886 parent_resource_provider
->DeclareUsedResourcesFromChild(
1887 child_id
, resource_ids_to_receive
);
1888 Mock::VerifyAndClearExpectations(parent_context
);
1890 ResourceProvider::ResourceIdMap resource_map
=
1891 parent_resource_provider
->GetChildToParentMap(child_id
);
1892 ResourceId mapped_id
= resource_map
[id
];
1893 EXPECT_NE(0u, mapped_id
);
1895 // The texture is set to |parent_filter| in the parent.
1896 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1899 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1902 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1903 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1904 Mock::VerifyAndClearExpectations(parent_context
);
1906 // The texture should be reset to |child_filter| in the parent when it is
1907 // returned, since that is how it was received.
1908 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1911 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1914 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1917 EXPECT_EQ(0u, returned_to_child
.size());
1919 // Transfer resources back from the parent to the child. Set no resources
1921 ResourceProvider::ResourceIdSet no_resources
;
1922 EXPECT_CALL(*parent_context
, insertSyncPoint());
1923 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1925 Mock::VerifyAndClearExpectations(parent_context
);
1927 ASSERT_EQ(1u, returned_to_child
.size());
1928 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1931 // The child remembers the texture filter is set to |child_filter|.
1932 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1933 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1934 Mock::VerifyAndClearExpectations(child_context
);
1938 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1939 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1941 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1944 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1945 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1947 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1950 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1951 // Other mailbox transfers tested elsewhere.
1952 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
1954 unsigned texture
= context()->createTexture();
1955 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1956 uint8_t data
[4] = { 1, 2, 3, 4 };
1957 context()->texImage2D(
1958 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1959 gpu::Mailbox mailbox
;
1960 context()->genMailboxCHROMIUM(mailbox
.name
);
1961 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
1962 uint32 sync_point
= context()->insertSyncPoint();
1964 // All the logic below assumes that the sync points are all positive.
1965 EXPECT_LT(0u, sync_point
);
1967 uint32 release_sync_point
= 0;
1968 bool lost_resource
= false;
1969 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1970 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1971 &release_sync_point
,
1973 &main_thread_task_runner
);
1974 ResourceId resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1975 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1976 SingleReleaseCallbackImpl::Create(callback
));
1977 EXPECT_EQ(1u, context()->NumTextures());
1978 EXPECT_EQ(0u, release_sync_point
);
1980 // Transfer the resource, expect the sync points to be consistent.
1981 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1982 resource_ids_to_transfer
.push_back(resource
);
1983 TransferableResourceArray list
;
1984 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1985 ASSERT_EQ(1u, list
.size());
1986 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1988 memcmp(mailbox
.name
,
1989 list
[0].mailbox_holder
.mailbox
.name
,
1990 sizeof(mailbox
.name
)));
1991 EXPECT_EQ(0u, release_sync_point
);
1993 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1994 unsigned other_texture
=
1995 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1996 uint8_t test_data
[4] = { 0 };
1997 context()->GetPixels(
1998 gfx::Size(1, 1), RGBA_8888
, test_data
);
1999 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2001 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2003 context()->deleteTexture(other_texture
);
2004 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2005 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2007 // Receive the resource, then delete it, expect the sync points to be
2009 ReturnedResourceArray returned
;
2010 TransferableResource::ReturnResources(list
, &returned
);
2011 resource_provider_
->ReceiveReturnsFromParent(returned
);
2012 EXPECT_EQ(1u, context()->NumTextures());
2013 EXPECT_EQ(0u, release_sync_point
);
2015 resource_provider_
->DeleteResource(resource
);
2016 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2017 EXPECT_FALSE(lost_resource
);
2018 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2021 // We're going to do the same thing as above, but testing the case where we
2022 // delete the resource before we receive it back.
2023 sync_point
= release_sync_point
;
2024 EXPECT_LT(0u, sync_point
);
2025 release_sync_point
= 0;
2026 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
2027 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
2028 SingleReleaseCallbackImpl::Create(callback
));
2029 EXPECT_EQ(1u, context()->NumTextures());
2030 EXPECT_EQ(0u, release_sync_point
);
2032 // Transfer the resource, expect the sync points to be consistent.
2033 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2034 resource_ids_to_transfer
.push_back(resource
);
2035 TransferableResourceArray list
;
2036 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2037 ASSERT_EQ(1u, list
.size());
2038 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
2040 memcmp(mailbox
.name
,
2041 list
[0].mailbox_holder
.mailbox
.name
,
2042 sizeof(mailbox
.name
)));
2043 EXPECT_EQ(0u, release_sync_point
);
2045 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
2046 unsigned other_texture
=
2047 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2048 uint8_t test_data
[4] = { 0 };
2049 context()->GetPixels(
2050 gfx::Size(1, 1), RGBA_8888
, test_data
);
2051 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
2053 context()->produceTextureDirectCHROMIUM(other_texture
, GL_TEXTURE_2D
,
2055 context()->deleteTexture(other_texture
);
2056 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
2057 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
2059 // Delete the resource, which shouldn't do anything.
2060 resource_provider_
->DeleteResource(resource
);
2061 EXPECT_EQ(1u, context()->NumTextures());
2062 EXPECT_EQ(0u, release_sync_point
);
2064 // Then receive the resource which should release the mailbox, expect the
2065 // sync points to be consistent.
2066 ReturnedResourceArray returned
;
2067 TransferableResource::ReturnResources(list
, &returned
);
2068 resource_provider_
->ReceiveReturnsFromParent(returned
);
2069 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
2070 EXPECT_FALSE(lost_resource
);
2071 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2074 context()->waitSyncPoint(release_sync_point
);
2076 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2077 context()->deleteTexture(texture
);
2080 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
2081 gfx::Size
size(1, 1);
2082 ResourceFormat format
= RGBA_8888
;
2083 ResourceId resource
= child_resource_provider_
->CreateResource(
2084 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2085 child_resource_provider_
->AllocateForTesting(resource
);
2086 // Expect a GL resource to be lost.
2087 bool should_lose_resource
=
2088 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
;
2090 ReturnedResourceArray returned_to_child
;
2092 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2094 // Transfer the resource to the parent.
2095 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2096 resource_ids_to_transfer
.push_back(resource
);
2097 TransferableResourceArray list
;
2098 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2100 EXPECT_EQ(1u, list
.size());
2102 resource_provider_
->ReceiveFromChild(child_id
, list
);
2103 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2104 resource_ids_to_receive
.insert(resource
);
2105 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2106 resource_ids_to_receive
);
2109 // Lose the output surface in the parent.
2110 resource_provider_
->DidLoseOutputSurface();
2113 EXPECT_EQ(0u, returned_to_child
.size());
2115 // Transfer resources back from the parent to the child. Set no resources as
2117 ResourceProvider::ResourceIdSet no_resources
;
2118 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2120 // Expect a GL resource to be lost.
2121 ASSERT_EQ(1u, returned_to_child
.size());
2122 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2123 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2124 returned_to_child
.clear();
2127 // A GL resource should be lost.
2128 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2130 // Lost resources stay in use in the parent forever.
2131 EXPECT_EQ(should_lose_resource
,
2132 child_resource_provider_
->InUseByConsumer(resource
));
2135 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2136 gfx::Size
size(1, 1);
2137 ResourceFormat format
= RGBA_8888
;
2138 ResourceId resource
= child_resource_provider_
->CreateResource(
2139 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2140 child_resource_provider_
->AllocateForTesting(resource
);
2142 ReturnedResourceArray returned_to_child
;
2144 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2146 // Transfer the resource to the parent.
2147 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2148 resource_ids_to_transfer
.push_back(resource
);
2149 TransferableResourceArray list
;
2150 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2152 EXPECT_EQ(1u, list
.size());
2154 resource_provider_
->ReceiveFromChild(child_id
, list
);
2155 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2156 resource_ids_to_receive
.insert(resource
);
2157 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2158 resource_ids_to_receive
);
2162 ResourceProvider::ResourceIdMap resource_map
=
2163 resource_provider_
->GetChildToParentMap(child_id
);
2164 ResourceId parent_resource
= resource_map
[resource
];
2165 EXPECT_NE(0u, parent_resource
);
2167 // Transfer to a grandparent.
2168 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2169 resource_ids_to_transfer
.push_back(parent_resource
);
2170 TransferableResourceArray list
;
2171 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2173 // Receive back a lost resource from the grandparent.
2174 EXPECT_EQ(1u, list
.size());
2175 EXPECT_EQ(parent_resource
, list
[0].id
);
2176 ReturnedResourceArray returned
;
2177 TransferableResource::ReturnResources(list
, &returned
);
2178 EXPECT_EQ(1u, returned
.size());
2179 EXPECT_EQ(parent_resource
, returned
[0].id
);
2180 returned
[0].lost
= true;
2181 resource_provider_
->ReceiveReturnsFromParent(returned
);
2183 // The resource should be lost.
2184 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2186 // Lost resources stay in use in the parent forever.
2187 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2191 EXPECT_EQ(0u, returned_to_child
.size());
2193 // Transfer resources back from the parent to the child. Set no resources as
2195 ResourceProvider::ResourceIdSet no_resources
;
2196 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2198 // Expect the resource to be lost.
2199 ASSERT_EQ(1u, returned_to_child
.size());
2200 EXPECT_TRUE(returned_to_child
[0].lost
);
2201 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2202 returned_to_child
.clear();
2205 // The resource should be lost.
2206 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2208 // Lost resources stay in use in the parent forever.
2209 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2212 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2213 uint32 release_sync_point
= 0;
2214 bool lost_resource
= false;
2215 bool release_called
= false;
2216 uint32 sync_point
= 0;
2217 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2218 &release_called
, &sync_point
);
2220 ReturnedResourceArray returned_to_child
;
2222 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2224 // Transfer the resource to the parent.
2225 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2226 resource_ids_to_transfer
.push_back(resource
);
2227 TransferableResourceArray list
;
2228 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2230 EXPECT_EQ(1u, list
.size());
2232 resource_provider_
->ReceiveFromChild(child_id
, list
);
2233 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2234 resource_ids_to_receive
.insert(resource
);
2235 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2236 resource_ids_to_receive
);
2239 // Lose the output surface in the parent.
2240 resource_provider_
->DidLoseOutputSurface();
2243 EXPECT_EQ(0u, returned_to_child
.size());
2245 // Transfer resources back from the parent to the child. Set no resources as
2247 ResourceProvider::ResourceIdSet no_resources
;
2248 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2250 ASSERT_EQ(1u, returned_to_child
.size());
2251 // Losing an output surface only loses hardware resources.
2252 EXPECT_EQ(returned_to_child
[0].lost
,
2253 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2254 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2255 returned_to_child
.clear();
2258 // Delete the resource in the child. Expect the resource to be lost if it's
2260 child_resource_provider_
->DeleteResource(resource
);
2261 EXPECT_EQ(lost_resource
,
2262 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
);
2265 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2266 uint32 release_sync_point
= 0;
2267 bool lost_resource
= false;
2268 bool release_called
= false;
2269 uint32 sync_point
= 0;
2270 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2271 &release_called
, &sync_point
);
2273 ReturnedResourceArray returned_to_child
;
2275 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2277 // Transfer the resource to the parent.
2278 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2279 resource_ids_to_transfer
.push_back(resource
);
2280 TransferableResourceArray list
;
2281 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2283 EXPECT_EQ(1u, list
.size());
2285 resource_provider_
->ReceiveFromChild(child_id
, list
);
2286 ResourceProvider::ResourceIdSet resource_ids_to_receive
;
2287 resource_ids_to_receive
.insert(resource
);
2288 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2289 resource_ids_to_receive
);
2293 ResourceProvider::ResourceIdMap resource_map
=
2294 resource_provider_
->GetChildToParentMap(child_id
);
2295 ResourceId parent_resource
= resource_map
[resource
];
2296 EXPECT_NE(0u, parent_resource
);
2298 // Transfer to a grandparent.
2299 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2300 resource_ids_to_transfer
.push_back(parent_resource
);
2301 TransferableResourceArray list
;
2302 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2304 // Receive back a lost resource from the grandparent.
2305 EXPECT_EQ(1u, list
.size());
2306 EXPECT_EQ(parent_resource
, list
[0].id
);
2307 ReturnedResourceArray returned
;
2308 TransferableResource::ReturnResources(list
, &returned
);
2309 EXPECT_EQ(1u, returned
.size());
2310 EXPECT_EQ(parent_resource
, returned
[0].id
);
2311 returned
[0].lost
= true;
2312 resource_provider_
->ReceiveReturnsFromParent(returned
);
2316 EXPECT_EQ(0u, returned_to_child
.size());
2318 // Transfer resources back from the parent to the child. Set no resources as
2320 ResourceProvider::ResourceIdSet no_resources
;
2321 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2323 // Expect the resource to be lost.
2324 ASSERT_EQ(1u, returned_to_child
.size());
2325 EXPECT_TRUE(returned_to_child
[0].lost
);
2326 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2327 returned_to_child
.clear();
2330 // Delete the resource in the child. Expect the resource to be lost.
2331 child_resource_provider_
->DeleteResource(resource
);
2332 EXPECT_TRUE(lost_resource
);
2335 TEST_P(ResourceProviderTest
, Shutdown
) {
2336 uint32 release_sync_point
= 0;
2337 bool lost_resource
= false;
2338 bool release_called
= false;
2339 uint32 sync_point
= 0;
2341 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2343 EXPECT_EQ(0u, release_sync_point
);
2344 EXPECT_FALSE(lost_resource
);
2346 child_resource_provider_
= nullptr;
2348 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
) {
2349 EXPECT_LE(sync_point
, release_sync_point
);
2351 EXPECT_TRUE(release_called
);
2352 EXPECT_FALSE(lost_resource
);
2355 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2356 uint32 release_sync_point
= 0;
2357 bool lost_resource
= false;
2358 bool release_called
= false;
2359 uint32 sync_point
= 0;
2360 ResourceId resource
= CreateChildMailbox(&release_sync_point
, &lost_resource
,
2361 &release_called
, &sync_point
);
2363 // Transfer the resource, so we can't release it properly on shutdown.
2364 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2365 resource_ids_to_transfer
.push_back(resource
);
2366 TransferableResourceArray list
;
2367 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2370 EXPECT_EQ(0u, release_sync_point
);
2371 EXPECT_FALSE(lost_resource
);
2373 child_resource_provider_
= nullptr;
2375 // Since the resource is in the parent, the child considers it lost.
2376 EXPECT_EQ(0u, release_sync_point
);
2377 EXPECT_TRUE(lost_resource
);
2380 TEST_P(ResourceProviderTest
, LostContext
) {
2381 // TextureMailbox callbacks only exist for GL textures for now.
2382 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2384 unsigned texture
= context()->createTexture();
2385 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2386 gpu::Mailbox mailbox
;
2387 context()->genMailboxCHROMIUM(mailbox
.name
);
2388 context()->produceTextureDirectCHROMIUM(texture
, GL_TEXTURE_2D
, mailbox
.name
);
2389 uint32 sync_point
= context()->insertSyncPoint();
2391 EXPECT_LT(0u, sync_point
);
2393 uint32 release_sync_point
= 0;
2394 bool lost_resource
= false;
2395 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2396 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2397 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2398 &release_sync_point
,
2400 &main_thread_task_runner
));
2401 resource_provider_
->CreateResourceFromTextureMailbox(
2402 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2404 EXPECT_EQ(0u, release_sync_point
);
2405 EXPECT_FALSE(lost_resource
);
2406 EXPECT_EQ(NULL
, main_thread_task_runner
);
2408 resource_provider_
->DidLoseOutputSurface();
2409 resource_provider_
= nullptr;
2411 EXPECT_LE(sync_point
, release_sync_point
);
2412 EXPECT_TRUE(lost_resource
);
2413 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2416 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2417 // Sampling is only supported for GL textures.
2418 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2421 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2422 new TextureStateTrackingContext
);
2423 TextureStateTrackingContext
* context
= context_owned
.get();
2425 FakeOutputSurfaceClient output_surface_client
;
2426 scoped_ptr
<OutputSurface
> output_surface(
2427 FakeOutputSurface::Create3d(context_owned
.Pass()));
2428 CHECK(output_surface
->BindToClient(&output_surface_client
));
2430 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2431 output_surface
.get(), shared_bitmap_manager_
.get(),
2432 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2434 gfx::Size
size(1, 1);
2435 ResourceFormat format
= RGBA_8888
;
2438 ResourceId id
= resource_provider
->CreateResource(
2439 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2441 // Check that the texture gets created with the right sampler settings.
2442 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2443 .Times(2); // Once to create and once to allocate.
2444 EXPECT_CALL(*context
,
2445 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2446 EXPECT_CALL(*context
,
2447 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2450 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2453 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2454 EXPECT_CALL(*context
,
2455 texParameteri(GL_TEXTURE_2D
,
2456 GL_TEXTURE_POOL_CHROMIUM
,
2457 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2459 resource_provider
->AllocateForTesting(id
);
2460 Mock::VerifyAndClearExpectations(context
);
2462 // Creating a sampler with the default filter should not change any texture
2465 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2466 ResourceProvider::ScopedSamplerGL
sampler(
2467 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2468 Mock::VerifyAndClearExpectations(context
);
2471 // Using a different filter should be reflected in the texture parameters.
2473 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2476 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2479 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2480 ResourceProvider::ScopedSamplerGL
sampler(
2481 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2482 Mock::VerifyAndClearExpectations(context
);
2485 // Test resetting to the default filter.
2487 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2488 EXPECT_CALL(*context
,
2489 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2490 EXPECT_CALL(*context
,
2491 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2492 ResourceProvider::ScopedSamplerGL
sampler(
2493 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2494 Mock::VerifyAndClearExpectations(context
);
2498 TEST_P(ResourceProviderTest
, ManagedResource
) {
2499 // Sampling is only supported for GL textures.
2500 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2503 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2504 new TextureStateTrackingContext
);
2505 TextureStateTrackingContext
* context
= context_owned
.get();
2507 FakeOutputSurfaceClient output_surface_client
;
2508 scoped_ptr
<OutputSurface
> output_surface(
2509 FakeOutputSurface::Create3d(context_owned
.Pass()));
2510 CHECK(output_surface
->BindToClient(&output_surface_client
));
2512 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2513 output_surface
.get(), shared_bitmap_manager_
.get(),
2514 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2516 gfx::Size
size(1, 1);
2517 ResourceFormat format
= RGBA_8888
;
2520 // Check that the texture gets created with the right sampler settings.
2521 ResourceId id
= resource_provider
->CreateManagedResource(
2522 size
, GL_TEXTURE_2D
, GL_CLAMP_TO_EDGE
,
2523 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2524 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2525 EXPECT_CALL(*context
,
2526 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2527 EXPECT_CALL(*context
,
2528 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2531 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2534 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2535 EXPECT_CALL(*context
,
2536 texParameteri(GL_TEXTURE_2D
,
2537 GL_TEXTURE_POOL_CHROMIUM
,
2538 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2539 resource_provider
->CreateForTesting(id
);
2542 Mock::VerifyAndClearExpectations(context
);
2545 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2546 // Sampling is only supported for GL textures.
2547 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2550 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2551 new TextureStateTrackingContext
);
2552 TextureStateTrackingContext
* context
= context_owned
.get();
2554 FakeOutputSurfaceClient output_surface_client
;
2555 scoped_ptr
<OutputSurface
> output_surface(
2556 FakeOutputSurface::Create3d(context_owned
.Pass()));
2557 CHECK(output_surface
->BindToClient(&output_surface_client
));
2559 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2560 output_surface
.get(), shared_bitmap_manager_
.get(),
2561 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2563 gfx::Size
size(1, 1);
2564 ResourceFormat format
= RGBA_8888
;
2565 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2567 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2568 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2569 // Check that the texture gets created with the right sampler settings.
2570 ResourceId id
= resource_provider
->CreateGLTexture(
2571 size
, GL_TEXTURE_2D
, texture_pool
, wrap_mode
,
2572 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
2573 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2574 EXPECT_CALL(*context
,
2575 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2576 EXPECT_CALL(*context
,
2577 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2578 EXPECT_CALL(*context
,
2579 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2580 EXPECT_CALL(*context
,
2581 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2582 EXPECT_CALL(*context
,
2583 texParameteri(GL_TEXTURE_2D
,
2584 GL_TEXTURE_POOL_CHROMIUM
,
2585 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2586 resource_provider
->CreateForTesting(id
);
2589 Mock::VerifyAndClearExpectations(context
);
2593 TEST_P(ResourceProviderTest
, TextureHint
) {
2594 // Sampling is only supported for GL textures.
2595 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2598 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2599 new TextureStateTrackingContext
);
2600 TextureStateTrackingContext
* context
= context_owned
.get();
2601 context
->set_support_texture_storage(true);
2602 context
->set_support_texture_usage(true);
2604 FakeOutputSurfaceClient output_surface_client
;
2605 scoped_ptr
<OutputSurface
> output_surface(
2606 FakeOutputSurface::Create3d(context_owned
.Pass()));
2607 CHECK(output_surface
->BindToClient(&output_surface_client
));
2609 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2610 output_surface
.get(), shared_bitmap_manager_
.get(),
2611 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2613 gfx::Size
size(1, 1);
2614 ResourceFormat format
= RGBA_8888
;
2615 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2617 const ResourceProvider::TextureHint hints
[4] = {
2618 ResourceProvider::TEXTURE_HINT_DEFAULT
,
2619 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
2620 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
2621 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
2623 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2624 // Check that the texture gets created with the right sampler settings.
2625 ResourceId id
= resource_provider
->CreateGLTexture(
2626 size
, GL_TEXTURE_2D
, texture_pool
, GL_CLAMP_TO_EDGE
,
2627 hints
[texture_id
- 1], format
);
2628 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2629 EXPECT_CALL(*context
,
2630 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2631 EXPECT_CALL(*context
,
2632 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2635 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2638 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2639 EXPECT_CALL(*context
,
2640 texParameteri(GL_TEXTURE_2D
,
2641 GL_TEXTURE_POOL_CHROMIUM
,
2642 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2643 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2644 bool is_framebuffer_hint
=
2645 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
;
2646 EXPECT_CALL(*context
,
2647 texParameteri(GL_TEXTURE_2D
,
2648 GL_TEXTURE_USAGE_ANGLE
,
2649 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2650 .Times(is_framebuffer_hint
? 1 : 0);
2651 resource_provider
->CreateForTesting(id
);
2654 Mock::VerifyAndClearExpectations(context
);
2658 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2659 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP
)
2662 gfx::Size
size(64, 64);
2663 const uint32_t kBadBeef
= 0xbadbeef;
2664 scoped_ptr
<SharedBitmap
> shared_bitmap(
2665 CreateAndFillSharedBitmap(shared_bitmap_manager_
.get(), size
, kBadBeef
));
2667 FakeOutputSurfaceClient output_surface_client
;
2668 scoped_ptr
<OutputSurface
> output_surface(
2669 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2670 new SoftwareOutputDevice
)));
2671 CHECK(output_surface
->BindToClient(&output_surface_client
));
2673 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2674 output_surface
.get(), shared_bitmap_manager_
.get(),
2675 gpu_memory_buffer_manager_
.get(), main_thread_task_runner_
.get(), 0,
2678 uint32 release_sync_point
= 0;
2679 bool lost_resource
= false;
2680 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2681 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2682 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2683 &release_sync_point
,
2685 &main_thread_task_runner
));
2686 TextureMailbox
mailbox(shared_bitmap
.get(), size
);
2688 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2689 mailbox
, callback
.Pass());
2693 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2694 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2695 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2696 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2697 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2700 resource_provider
->DeleteResource(id
);
2701 EXPECT_EQ(0u, release_sync_point
);
2702 EXPECT_FALSE(lost_resource
);
2703 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2706 class ResourceProviderTestTextureMailboxGLFilters
2707 : public ResourceProviderTest
{
2709 static void RunTest(TestSharedBitmapManager
* shared_bitmap_manager
,
2710 TestGpuMemoryBufferManager
* gpu_memory_buffer_manager
,
2711 BlockingTaskRunner
* main_thread_task_runner
,
2712 bool mailbox_nearest_neighbor
,
2713 GLenum sampler_filter
) {
2714 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2715 new TextureStateTrackingContext
);
2716 TextureStateTrackingContext
* context
= context_owned
.get();
2718 FakeOutputSurfaceClient output_surface_client
;
2719 scoped_ptr
<OutputSurface
> output_surface(
2720 FakeOutputSurface::Create3d(context_owned
.Pass()));
2721 CHECK(output_surface
->BindToClient(&output_surface_client
));
2723 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2724 output_surface
.get(), shared_bitmap_manager
, gpu_memory_buffer_manager
,
2725 main_thread_task_runner
, 0, false, 1, false));
2727 unsigned texture_id
= 1;
2728 uint32 sync_point
= 30;
2729 unsigned target
= GL_TEXTURE_2D
;
2731 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2732 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2733 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2734 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2735 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2737 gpu::Mailbox gpu_mailbox
;
2738 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2739 uint32 release_sync_point
= 0;
2740 bool lost_resource
= false;
2741 BlockingTaskRunner
* mailbox_task_runner
= NULL
;
2742 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2743 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2744 &release_sync_point
,
2746 &mailbox_task_runner
));
2748 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2749 mailbox
.set_nearest_neighbor(mailbox_nearest_neighbor
);
2751 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2752 mailbox
, callback
.Pass());
2755 Mock::VerifyAndClearExpectations(context
);
2758 // Mailbox sync point WaitSyncPoint before using the texture.
2759 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2760 resource_provider
->WaitSyncPointIfNeeded(id
);
2761 Mock::VerifyAndClearExpectations(context
);
2763 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2764 .WillOnce(Return(texture_id
));
2765 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2767 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2768 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2770 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2771 // match |sampler_filter|.
2772 if (mailbox_nearest_neighbor
!= (sampler_filter
== GL_NEAREST
)) {
2773 EXPECT_CALL(*context
, texParameteri(
2774 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, sampler_filter
));
2775 EXPECT_CALL(*context
, texParameteri(
2776 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, sampler_filter
));
2779 ResourceProvider::ScopedSamplerGL
lock(
2780 resource_provider
.get(), id
, sampler_filter
);
2781 Mock::VerifyAndClearExpectations(context
);
2783 // When done with it, a sync point should be inserted, but no produce is
2785 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2786 EXPECT_CALL(*context
, insertSyncPoint());
2787 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2789 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2790 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2793 resource_provider
->DeleteResource(id
);
2794 EXPECT_EQ(0u, release_sync_point
);
2795 EXPECT_FALSE(lost_resource
);
2796 EXPECT_EQ(main_thread_task_runner
, mailbox_task_runner
);
2800 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToLinear
) {
2801 // Mailboxing is only supported for GL textures.
2802 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2805 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2806 shared_bitmap_manager_
.get(),
2807 gpu_memory_buffer_manager_
.get(),
2808 main_thread_task_runner_
.get(),
2813 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToNearest
) {
2814 // Mailboxing is only supported for GL textures.
2815 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2818 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2819 shared_bitmap_manager_
.get(),
2820 gpu_memory_buffer_manager_
.get(),
2821 main_thread_task_runner_
.get(),
2826 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_NearestToLinear
) {
2827 // Mailboxing is only supported for GL textures.
2828 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2831 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2832 shared_bitmap_manager_
.get(),
2833 gpu_memory_buffer_manager_
.get(),
2834 main_thread_task_runner_
.get(),
2839 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D_LinearToNearest
) {
2840 // Mailboxing is only supported for GL textures.
2841 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2844 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2845 shared_bitmap_manager_
.get(),
2846 gpu_memory_buffer_manager_
.get(),
2847 main_thread_task_runner_
.get(),
2852 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2853 // Mailboxing is only supported for GL textures.
2854 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2857 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2858 new TextureStateTrackingContext
);
2859 TextureStateTrackingContext
* context
= context_owned
.get();
2861 FakeOutputSurfaceClient output_surface_client
;
2862 scoped_ptr
<OutputSurface
> output_surface(
2863 FakeOutputSurface::Create3d(context_owned
.Pass()));
2864 CHECK(output_surface
->BindToClient(&output_surface_client
));
2866 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2867 output_surface
.get(), shared_bitmap_manager_
.get(),
2868 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2870 uint32 sync_point
= 30;
2871 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2873 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2874 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2875 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2876 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2877 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2879 gpu::Mailbox gpu_mailbox
;
2880 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2881 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2882 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2884 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2886 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2887 mailbox
, callback
.Pass());
2890 Mock::VerifyAndClearExpectations(context
);
2893 // Mailbox sync point WaitSyncPoint before using the texture.
2894 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2895 resource_provider
->WaitSyncPointIfNeeded(id
);
2896 Mock::VerifyAndClearExpectations(context
);
2898 unsigned texture_id
= 1;
2900 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(target
, _
))
2901 .WillOnce(Return(texture_id
));
2903 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2904 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2906 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2907 Mock::VerifyAndClearExpectations(context
);
2909 // When done with it, a sync point should be inserted, but no produce is
2911 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2912 EXPECT_CALL(*context
, insertSyncPoint());
2913 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2915 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2916 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2920 TEST_P(ResourceProviderTest
,
2921 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2922 // Mailboxing is only supported for GL textures.
2923 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2926 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2927 new TextureStateTrackingContext
);
2928 TextureStateTrackingContext
* context
= context_owned
.get();
2930 FakeOutputSurfaceClient output_surface_client
;
2931 scoped_ptr
<OutputSurface
> output_surface(
2932 FakeOutputSurface::Create3d(context_owned
.Pass()));
2933 CHECK(output_surface
->BindToClient(&output_surface_client
));
2935 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2936 output_surface
.get(), shared_bitmap_manager_
.get(),
2937 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2939 uint32 sync_point
= 30;
2940 unsigned target
= GL_TEXTURE_2D
;
2942 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2943 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2944 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2945 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2946 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
2948 gpu::Mailbox gpu_mailbox
;
2949 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2950 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2951 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2953 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2955 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
2956 mailbox
, callback
.Pass());
2959 Mock::VerifyAndClearExpectations(context
);
2962 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2963 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2964 resource_provider
->WaitSyncPointIfNeeded(id
);
2965 Mock::VerifyAndClearExpectations(context
);
2967 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2968 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2969 resource_provider
->WaitSyncPointIfNeeded(id
);
2970 Mock::VerifyAndClearExpectations(context
);
2974 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2975 // Mailboxing is only supported for GL textures.
2976 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
2979 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2980 new TextureStateTrackingContext
);
2981 TextureStateTrackingContext
* context
= context_owned
.get();
2983 FakeOutputSurfaceClient output_surface_client
;
2984 scoped_ptr
<OutputSurface
> output_surface(
2985 FakeOutputSurface::Create3d(context_owned
.Pass()));
2986 CHECK(output_surface
->BindToClient(&output_surface_client
));
2988 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2989 output_surface
.get(), shared_bitmap_manager_
.get(),
2990 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
2992 uint32 sync_point
= 0;
2993 unsigned target
= GL_TEXTURE_2D
;
2995 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2996 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2997 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2998 EXPECT_CALL(*context
, produceTextureDirectCHROMIUM(_
, _
, _
)).Times(0);
2999 EXPECT_CALL(*context
, createAndConsumeTextureCHROMIUM(_
, _
)).Times(0);
3001 gpu::Mailbox gpu_mailbox
;
3002 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
3003 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
3004 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
3006 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
3008 ResourceId id
= resource_provider
->CreateResourceFromTextureMailbox(
3009 mailbox
, callback
.Pass());
3012 Mock::VerifyAndClearExpectations(context
);
3015 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3016 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
3017 resource_provider
->WaitSyncPointIfNeeded(id
);
3018 Mock::VerifyAndClearExpectations(context
);
3022 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
3024 MOCK_METHOD0(NextTextureId
, GLuint());
3025 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
3026 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
3027 MOCK_METHOD5(texStorage2DEXT
,
3030 GLuint internalformat
,
3033 MOCK_METHOD9(texImage2D
,
3036 GLenum internalformat
,
3042 const void* pixels
));
3043 MOCK_METHOD9(texSubImage2D
,
3052 const void* pixels
));
3053 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
3056 GLenum internalformat
,
3062 const void* pixels
));
3063 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
3072 const void* pixels
));
3073 MOCK_METHOD8(compressedTexImage2D
,
3076 GLenum internalformat
,
3082 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
3083 MOCK_METHOD4(createImageCHROMIUM
,
3084 GLuint(ClientBuffer
, GLsizei
, GLsizei
, GLenum
));
3085 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
3086 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3087 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
3089 // We're mocking bindTexture, so we override
3090 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3091 // currently bound texture.
3092 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
3095 TEST_P(ResourceProviderTest
, TextureAllocation
) {
3096 // Only for GL textures.
3097 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3099 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3100 new StrictMock
<AllocationTrackingContext3D
>);
3101 AllocationTrackingContext3D
* context
= context_owned
.get();
3103 FakeOutputSurfaceClient output_surface_client
;
3104 scoped_ptr
<OutputSurface
> output_surface(
3105 FakeOutputSurface::Create3d(context_owned
.Pass()));
3106 CHECK(output_surface
->BindToClient(&output_surface_client
));
3108 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3109 output_surface
.get(), shared_bitmap_manager_
.get(),
3110 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3112 gfx::Size
size(2, 2);
3113 gfx::Vector2d
offset(0, 0);
3114 ResourceFormat format
= RGBA_8888
;
3116 uint8_t pixels
[16] = { 0 };
3117 int texture_id
= 123;
3119 // Lazy allocation. Don't allocate when creating the resource.
3120 id
= resource_provider
->CreateResource(
3121 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3123 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3124 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3125 resource_provider
->CreateForTesting(id
);
3127 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3128 resource_provider
->DeleteResource(id
);
3130 Mock::VerifyAndClearExpectations(context
);
3132 // Do allocate when we set the pixels.
3133 id
= resource_provider
->CreateResource(
3134 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3136 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3137 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3138 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3139 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3140 resource_provider
->CopyToResource(id
, pixels
, size
);
3142 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3143 resource_provider
->DeleteResource(id
);
3145 Mock::VerifyAndClearExpectations(context
);
3147 // Same for async version.
3148 id
= resource_provider
->CreateResource(
3149 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3150 resource_provider
->AcquirePixelBuffer(id
);
3152 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3153 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3154 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3156 resource_provider
->BeginSetPixels(id
);
3157 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3159 resource_provider
->ReleasePixelBuffer(id
);
3161 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3162 resource_provider
->DeleteResource(id
);
3164 Mock::VerifyAndClearExpectations(context
);
3167 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3168 // Only for GL textures.
3169 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3171 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3172 new StrictMock
<AllocationTrackingContext3D
>);
3173 AllocationTrackingContext3D
* context
= context_owned
.get();
3174 context
->set_support_texture_storage(true);
3175 context
->set_support_texture_usage(true);
3177 FakeOutputSurfaceClient output_surface_client
;
3178 scoped_ptr
<OutputSurface
> output_surface(
3179 FakeOutputSurface::Create3d(context_owned
.Pass()));
3180 CHECK(output_surface
->BindToClient(&output_surface_client
));
3182 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3183 output_surface
.get(), shared_bitmap_manager_
.get(),
3184 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3186 gfx::Size
size(2, 2);
3188 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3189 const ResourceProvider::TextureHint hints
[4] = {
3190 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3191 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3192 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3193 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3195 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3196 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3197 // Lazy allocation. Don't allocate when creating the resource.
3198 ResourceId id
= resource_provider
->CreateResource(
3199 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3201 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3202 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3203 bool is_immutable_hint
=
3204 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3205 bool support_immutable_texture
=
3206 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3207 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3208 .Times(support_immutable_texture
? 1 : 0);
3209 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3210 .Times(support_immutable_texture
? 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
, TextureAllocationHint_BGRA
) {
3222 // Only for GL textures.
3223 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3225 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3226 new StrictMock
<AllocationTrackingContext3D
>);
3227 AllocationTrackingContext3D
* context
= context_owned
.get();
3228 context
->set_support_texture_format_bgra8888(true);
3229 context
->set_support_texture_storage(true);
3230 context
->set_support_texture_usage(true);
3232 FakeOutputSurfaceClient output_surface_client
;
3233 scoped_ptr
<OutputSurface
> output_surface(
3234 FakeOutputSurface::Create3d(context_owned
.Pass()));
3235 CHECK(output_surface
->BindToClient(&output_surface_client
));
3237 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3238 output_surface
.get(), shared_bitmap_manager_
.get(),
3239 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3241 gfx::Size
size(2, 2);
3242 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3244 const ResourceProvider::TextureHint hints
[4] = {
3245 ResourceProvider::TEXTURE_HINT_DEFAULT
,
3246 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3247 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER
,
3248 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER
,
3250 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3251 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3252 // Lazy allocation. Don't allocate when creating the resource.
3253 ResourceId id
= resource_provider
->CreateResource(
3254 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3256 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3257 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3258 bool is_immutable_hint
=
3259 hints
[texture_id
- 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE
;
3260 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3261 .Times(is_immutable_hint
? 1 : 0);
3262 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3263 .Times(is_immutable_hint
? 0 : 1);
3264 resource_provider
->AllocateForTesting(id
);
3266 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3267 resource_provider
->DeleteResource(id
);
3269 Mock::VerifyAndClearExpectations(context
);
3274 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3275 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3277 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3278 new StrictMock
<AllocationTrackingContext3D
>);
3279 AllocationTrackingContext3D
* context
= context_owned
.get();
3281 FakeOutputSurfaceClient output_surface_client
;
3282 scoped_ptr
<OutputSurface
> output_surface(
3283 FakeOutputSurface::Create3d(context_owned
.Pass()));
3284 CHECK(output_surface
->BindToClient(&output_surface_client
));
3286 gfx::Size
size(2, 2);
3287 ResourceFormat format
= RGBA_8888
;
3289 int texture_id
= 123;
3291 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3292 output_surface
.get(), shared_bitmap_manager_
.get(),
3293 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3295 id
= resource_provider
->CreateResource(
3296 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3297 resource_provider
->AcquirePixelBuffer(id
);
3299 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3300 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3301 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3303 resource_provider
->BeginSetPixels(id
);
3305 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3307 resource_provider
->ReleasePixelBuffer(id
);
3309 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3310 resource_provider
->DeleteResource(id
);
3312 Mock::VerifyAndClearExpectations(context
);
3315 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3316 // Only for GL textures.
3317 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3319 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3320 new StrictMock
<AllocationTrackingContext3D
>);
3321 AllocationTrackingContext3D
* context
= context_owned
.get();
3323 FakeOutputSurfaceClient output_surface_client
;
3324 scoped_ptr
<OutputSurface
> output_surface(
3325 FakeOutputSurface::Create3d(context_owned
.Pass()));
3326 CHECK(output_surface
->BindToClient(&output_surface_client
));
3328 gfx::Size
size(2, 2);
3329 ResourceFormat format
= RGBA_8888
;
3331 int texture_id
= 123;
3333 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3334 output_surface
.get(), shared_bitmap_manager_
.get(),
3335 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3337 id
= resource_provider
->CreateResource(
3338 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3339 resource_provider
->AcquirePixelBuffer(id
);
3341 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3342 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3343 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3345 resource_provider
->BeginSetPixels(id
);
3347 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3348 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3349 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3350 resource_provider
->ForceSetPixelsToComplete(id
);
3352 resource_provider
->ReleasePixelBuffer(id
);
3354 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3355 resource_provider
->DeleteResource(id
);
3357 Mock::VerifyAndClearExpectations(context
);
3360 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3361 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3362 new NiceMock
<AllocationTrackingContext3D
>);
3363 AllocationTrackingContext3D
* context
= context_owned
.get();
3365 FakeOutputSurfaceClient output_surface_client
;
3366 scoped_ptr
<OutputSurface
> output_surface(
3367 FakeOutputSurface::Create3d(context_owned
.Pass()));
3368 CHECK(output_surface
->BindToClient(&output_surface_client
));
3370 gfx::Size
size(2, 2);
3371 ResourceFormat format
= RGBA_8888
;
3373 int texture_id
= 123;
3375 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3376 output_surface
.get(), shared_bitmap_manager_
.get(),
3377 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3379 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3381 id
= resource_provider
->CreateResource(
3382 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3383 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3384 GL_INNOCENT_CONTEXT_RESET_ARB
);
3386 resource_provider
->AcquirePixelBuffer(id
);
3388 void* buffer
= resource_provider
->MapPixelBuffer(id
, &stride
);
3389 EXPECT_FALSE(buffer
);
3390 resource_provider
->UnmapPixelBuffer(id
);
3391 Mock::VerifyAndClearExpectations(context
);
3394 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3395 // Only for GL textures.
3396 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3398 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3399 new StrictMock
<AllocationTrackingContext3D
>);
3400 AllocationTrackingContext3D
* context
= context_owned
.get();
3402 FakeOutputSurfaceClient output_surface_client
;
3403 scoped_ptr
<OutputSurface
> output_surface(
3404 FakeOutputSurface::Create3d(context_owned
.Pass()));
3405 CHECK(output_surface
->BindToClient(&output_surface_client
));
3407 const int kWidth
= 2;
3408 const int kHeight
= 2;
3409 gfx::Size
size(kWidth
, kHeight
);
3410 ResourceFormat format
= RGBA_8888
;
3412 const unsigned kTextureId
= 123u;
3413 const unsigned kImageId
= 234u;
3415 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3416 output_surface
.get(), shared_bitmap_manager_
.get(),
3417 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3419 id
= resource_provider
->CreateResource(
3420 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3422 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3423 .WillOnce(Return(kImageId
))
3424 .RetiresOnSaturation();
3426 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3427 resource_provider
.get(), id
);
3428 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3431 EXPECT_CALL(*context
, NextTextureId())
3432 .WillOnce(Return(kTextureId
))
3433 .RetiresOnSaturation();
3434 // Once in CreateTextureId and once in BindForSampling
3435 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3436 .RetiresOnSaturation();
3437 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3439 .RetiresOnSaturation();
3441 ResourceProvider::ScopedSamplerGL
lock_gl(
3442 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3443 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3447 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3448 resource_provider
.get(), id
);
3449 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3452 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3453 .RetiresOnSaturation();
3454 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3456 .RetiresOnSaturation();
3457 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3459 .RetiresOnSaturation();
3460 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3462 .RetiresOnSaturation();
3464 ResourceProvider::ScopedSamplerGL
lock_gl(
3465 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3466 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3469 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3471 .RetiresOnSaturation();
3474 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3475 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3477 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3478 new StrictMock
<AllocationTrackingContext3D
>);
3479 AllocationTrackingContext3D
* context
= context_owned
.get();
3480 context_owned
->set_support_sync_query(true);
3482 FakeOutputSurfaceClient output_surface_client
;
3483 scoped_ptr
<OutputSurface
> output_surface(
3484 FakeOutputSurface::Create3d(context_owned
.Pass()));
3485 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3487 const int kWidth
= 2;
3488 const int kHeight
= 2;
3489 gfx::Size
size(kWidth
, kHeight
);
3490 ResourceFormat format
= RGBA_8888
;
3491 ResourceId source_id
= 0;
3492 ResourceId dest_id
= 0;
3493 const unsigned kSourceTextureId
= 123u;
3494 const unsigned kDestTextureId
= 321u;
3495 const unsigned kImageId
= 234u;
3497 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3498 output_surface
.get(), shared_bitmap_manager_
.get(),
3499 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3501 source_id
= resource_provider
->CreateResource(
3502 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3504 EXPECT_CALL(*context
, createImageCHROMIUM(_
, kWidth
, kHeight
, GL_RGBA
))
3505 .WillOnce(Return(kImageId
))
3506 .RetiresOnSaturation();
3508 ResourceProvider::ScopedWriteLockGpuMemoryBuffer
lock(
3509 resource_provider
.get(), source_id
);
3510 EXPECT_TRUE(lock
.GetGpuMemoryBuffer());
3512 Mock::VerifyAndClearExpectations(context
);
3514 dest_id
= resource_provider
->CreateResource(
3515 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, format
);
3517 EXPECT_CALL(*context
, NextTextureId())
3518 .WillOnce(Return(kDestTextureId
))
3519 .RetiresOnSaturation();
3520 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3522 .RetiresOnSaturation();
3523 EXPECT_CALL(*context
, texImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 2, 2, 0, GL_RGBA
,
3524 GL_UNSIGNED_BYTE
, nullptr))
3526 .RetiresOnSaturation();
3527 EXPECT_CALL(*context
, NextTextureId())
3528 .WillOnce(Return(kSourceTextureId
))
3529 .RetiresOnSaturation();
3530 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3532 .RetiresOnSaturation();
3533 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3535 .RetiresOnSaturation();
3536 resource_provider
->CopyResource(source_id
, dest_id
, gfx::Rect(size
));
3537 Mock::VerifyAndClearExpectations(context
);
3539 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3541 .RetiresOnSaturation();
3542 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3544 .RetiresOnSaturation();
3545 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3547 .RetiresOnSaturation();
3548 resource_provider
->DeleteResource(source_id
);
3549 resource_provider
->DeleteResource(dest_id
);
3552 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3553 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3556 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3557 new AllocationTrackingContext3D
);
3558 AllocationTrackingContext3D
* context
= context_owned
.get();
3559 context_owned
->set_support_compressed_texture_etc1(true);
3561 FakeOutputSurfaceClient output_surface_client
;
3562 scoped_ptr
<OutputSurface
> output_surface(
3563 FakeOutputSurface::Create3d(context_owned
.Pass()));
3564 CHECK(output_surface
->BindToClient(&output_surface_client
));
3566 gfx::Size
size(4, 4);
3567 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3568 output_surface
.get(), shared_bitmap_manager_
.get(),
3569 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3570 int texture_id
= 123;
3572 ResourceId id
= resource_provider
->CreateResource(
3573 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3575 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3576 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3577 resource_provider
->AllocateForTesting(id
);
3579 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3580 resource_provider
->DeleteResource(id
);
3583 TEST_P(ResourceProviderTest
, CompressedTextureETC1Upload
) {
3584 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
)
3587 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3588 new AllocationTrackingContext3D
);
3589 AllocationTrackingContext3D
* context
= context_owned
.get();
3590 context_owned
->set_support_compressed_texture_etc1(true);
3592 FakeOutputSurfaceClient output_surface_client
;
3593 scoped_ptr
<OutputSurface
> output_surface(
3594 FakeOutputSurface::Create3d(context_owned
.Pass()));
3595 CHECK(output_surface
->BindToClient(&output_surface_client
));
3597 gfx::Size
size(4, 4);
3598 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3599 output_surface
.get(), shared_bitmap_manager_
.get(),
3600 gpu_memory_buffer_manager_
.get(), NULL
, 0, false, 1, false));
3601 int texture_id
= 123;
3604 ResourceId id
= resource_provider
->CreateResource(
3605 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
, ETC1
);
3607 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3608 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3609 EXPECT_CALL(*context
,
3610 compressedTexImage2D(
3611 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3612 resource_provider
->CopyToResource(id
, pixels
, size
);
3614 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3615 resource_provider
->DeleteResource(id
);
3618 INSTANTIATE_TEST_CASE_P(
3619 ResourceProviderTests
,
3620 ResourceProviderTest
,
3621 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE
,
3622 ResourceProvider::RESOURCE_TYPE_BITMAP
));
3624 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3626 GLuint
NextTextureId() override
{
3627 base::AutoLock
lock(namespace_
->lock
);
3628 return namespace_
->next_texture_id
++;
3630 void RetireTextureId(GLuint
) override
{}
3631 GLuint
PeekTextureId() {
3632 base::AutoLock
lock(namespace_
->lock
);
3633 return namespace_
->next_texture_id
;
3637 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3638 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3639 new TextureIdAllocationTrackingContext
);
3640 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3642 FakeOutputSurfaceClient output_surface_client
;
3643 scoped_ptr
<OutputSurface
> output_surface(
3644 FakeOutputSurface::Create3d(context_owned
.Pass()));
3645 CHECK(output_surface
->BindToClient(&output_surface_client
));
3646 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3647 new TestSharedBitmapManager());
3649 gfx::Size
size(1, 1);
3650 ResourceFormat format
= RGBA_8888
;
3653 size_t kTextureAllocationChunkSize
= 1;
3654 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3655 output_surface
.get(), shared_bitmap_manager
.get(), NULL
, NULL
, 0, false,
3656 kTextureAllocationChunkSize
, false));
3658 ResourceId id
= resource_provider
->CreateResource(
3659 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3661 resource_provider
->AllocateForTesting(id
);
3662 Mock::VerifyAndClearExpectations(context
);
3664 DCHECK_EQ(2u, context
->PeekTextureId());
3665 resource_provider
->DeleteResource(id
);
3669 size_t kTextureAllocationChunkSize
= 8;
3670 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3671 output_surface
.get(), shared_bitmap_manager
.get(), NULL
, NULL
, 0, false,
3672 kTextureAllocationChunkSize
, false));
3674 ResourceId id
= resource_provider
->CreateResource(
3675 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
3677 resource_provider
->AllocateForTesting(id
);
3678 Mock::VerifyAndClearExpectations(context
);
3680 DCHECK_EQ(10u, context
->PeekTextureId());
3681 resource_provider
->DeleteResource(id
);