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_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "gpu/GLES2/gl2extchromium.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/khronos/GLES2/gl2ext.h"
31 #include "ui/gfx/rect.h"
34 using testing::NiceMock
;
35 using testing::Return
;
36 using testing::SetArgPointee
;
37 using testing::StrictMock
;
43 static void EmptyReleaseCallback(uint32 sync_point
,
45 BlockingTaskRunner
* main_thread_task_runner
) {
48 static void ReleaseCallback(
49 uint32
* release_sync_point
,
50 bool* release_lost_resource
,
51 BlockingTaskRunner
** release_main_thread_task_runner
,
54 BlockingTaskRunner
* main_thread_task_runner
) {
55 *release_sync_point
= sync_point
;
56 *release_lost_resource
= lost_resource
;
57 *release_main_thread_task_runner
= main_thread_task_runner
;
60 static void SharedMemoryReleaseCallback(
61 scoped_ptr
<base::SharedMemory
> memory
,
64 BlockingTaskRunner
* main_thread_task_runner
) {
67 static void ReleaseSharedMemoryCallback(
68 scoped_ptr
<base::SharedMemory
> shared_memory
,
70 uint32
* release_sync_point
,
71 bool* lost_resource_result
,
74 BlockingTaskRunner
* main_thread_task_runner
) {
75 *release_called
= true;
76 *release_sync_point
= sync_point
;
77 *lost_resource_result
= lost_resource
;
80 static scoped_ptr
<base::SharedMemory
> CreateAndFillSharedMemory(
81 const gfx::Size
& size
,
83 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
84 CHECK(shared_memory
->CreateAndMapAnonymous(4 * size
.GetArea()));
85 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_memory
->memory());
87 std::fill_n(pixels
, size
.GetArea(), value
);
88 return shared_memory
.Pass();
91 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
93 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
94 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
95 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
96 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
97 MOCK_METHOD2(produceTextureCHROMIUM
,
98 void(GLenum target
, const GLbyte
* mailbox
));
99 MOCK_METHOD2(consumeTextureCHROMIUM
,
100 void(GLenum target
, const GLbyte
* mailbox
));
102 // Force all textures to be consecutive numbers starting at "1",
103 // so we easily can test for them.
104 virtual GLuint
NextTextureId() OVERRIDE
{
105 base::AutoLock
lock(namespace_
->lock
);
106 return namespace_
->next_texture_id
++;
108 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
111 // Shared data between multiple ResourceProviderContext. This contains mailbox
112 // contents as well as information about sync points.
113 class ContextSharedData
{
115 static scoped_ptr
<ContextSharedData
> Create() {
116 return make_scoped_ptr(new ContextSharedData());
119 uint32
InsertSyncPoint() { return next_sync_point_
++; }
121 void GenMailbox(GLbyte
* mailbox
) {
122 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
123 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
127 void ProduceTexture(const GLbyte
* mailbox_name
,
129 scoped_refptr
<TestTexture
> texture
) {
130 unsigned mailbox
= 0;
131 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
132 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
133 textures_
[mailbox
] = texture
;
134 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
135 sync_point_for_mailbox_
[mailbox
] = sync_point
;
138 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
140 unsigned mailbox
= 0;
141 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
142 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
144 // If the latest sync point the context has waited on is before the sync
145 // point for when the mailbox was set, pretend we never saw that
147 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
149 return scoped_refptr
<TestTexture
>();
151 return textures_
[mailbox
];
155 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
157 uint32 next_sync_point_
;
158 unsigned next_mailbox_
;
159 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
> > TextureMap
;
160 TextureMap textures_
;
161 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
164 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
166 static scoped_ptr
<ResourceProviderContext
> Create(
167 ContextSharedData
* shared_data
) {
168 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
171 virtual GLuint
insertSyncPoint() OVERRIDE
{
172 uint32 sync_point
= shared_data_
->InsertSyncPoint();
173 // Commit the produceTextureCHROMIUM calls at this point, so that
174 // they're associated with the sync point.
175 for (PendingProduceTextureList::iterator it
=
176 pending_produce_textures_
.begin();
177 it
!= pending_produce_textures_
.end();
179 shared_data_
->ProduceTexture(
180 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
182 pending_produce_textures_
.clear();
186 virtual void waitSyncPoint(GLuint sync_point
) OVERRIDE
{
187 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
190 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
192 virtual void texStorage2DEXT(GLenum target
,
194 GLuint internalformat
,
196 GLint height
) OVERRIDE
{
197 CheckTextureIsBound(target
);
198 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
199 ASSERT_EQ(1, levels
);
200 GLenum format
= GL_RGBA
;
201 switch (internalformat
) {
205 format
= GL_BGRA_EXT
;
210 AllocateTexture(gfx::Size(width
, height
), format
);
213 virtual void texImage2D(GLenum target
,
215 GLenum internalformat
,
221 const void* pixels
) OVERRIDE
{
222 CheckTextureIsBound(target
);
223 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
225 ASSERT_EQ(internalformat
, format
);
226 ASSERT_FALSE(border
);
227 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
228 AllocateTexture(gfx::Size(width
, height
), format
);
230 SetPixels(0, 0, width
, height
, pixels
);
233 virtual void texSubImage2D(GLenum target
,
241 const void* pixels
) OVERRIDE
{
242 CheckTextureIsBound(target
);
243 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
245 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
247 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
248 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
251 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
254 virtual void genMailboxCHROMIUM(GLbyte
* mailbox
) OVERRIDE
{
255 return shared_data_
->GenMailbox(mailbox
);
258 virtual void produceTextureCHROMIUM(GLenum target
,
259 const GLbyte
* mailbox
) OVERRIDE
{
260 CheckTextureIsBound(target
);
262 // Delay moving the texture into the mailbox until the next
263 // InsertSyncPoint, so that it is not visible to other contexts that
264 // haven't waited on that sync point.
265 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
266 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
267 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
268 pending
->texture
= BoundTexture(target
);
269 pending_produce_textures_
.push_back(pending
.Pass());
272 virtual void consumeTextureCHROMIUM(GLenum target
,
273 const GLbyte
* mailbox
) OVERRIDE
{
274 CheckTextureIsBound(target
);
275 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
276 scoped_refptr
<TestTexture
> texture
=
277 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
278 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
281 void GetPixels(const gfx::Size
& size
,
282 ResourceFormat format
,
284 CheckTextureIsBound(GL_TEXTURE_2D
);
285 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
286 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
287 ASSERT_EQ(texture
->size
, size
);
288 ASSERT_EQ(texture
->format
, format
);
289 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
293 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
294 : shared_data_(shared_data
),
295 last_waited_sync_point_(0) {}
298 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
299 CheckTextureIsBound(GL_TEXTURE_2D
);
300 ResourceFormat texture_format
= RGBA_8888
;
303 texture_format
= RGBA_8888
;
306 texture_format
= BGRA_8888
;
309 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
310 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
313 void SetPixels(int xoffset
,
317 const void* pixels
) {
318 CheckTextureIsBound(GL_TEXTURE_2D
);
319 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
320 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
321 ASSERT_TRUE(texture
->data
.get());
322 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
323 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
325 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
327 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
328 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
329 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
330 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
331 for (int i
= 0; i
< height
; ++i
) {
332 memcpy(dest
, src
, in_pitch
);
338 struct PendingProduceTexture
{
339 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
340 scoped_refptr
<TestTexture
> texture
;
342 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
343 ContextSharedData
* shared_data_
;
344 GLuint last_waited_sync_point_
;
345 PendingProduceTextureList pending_produce_textures_
;
348 void GetResourcePixels(ResourceProvider
* resource_provider
,
349 ResourceProviderContext
* context
,
350 ResourceProvider::ResourceId id
,
351 const gfx::Size
& size
,
352 ResourceFormat format
,
354 resource_provider
->WaitSyncPointIfNeeded(id
);
355 switch (resource_provider
->default_resource_type()) {
356 case ResourceProvider::GLTexture
: {
357 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
358 ASSERT_NE(0U, lock_gl
.texture_id());
359 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
360 context
->GetPixels(size
, format
, pixels
);
363 case ResourceProvider::Bitmap
: {
364 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
367 lock_software
.sk_bitmap()->getPixels(),
368 lock_software
.sk_bitmap()->getSize());
371 case ResourceProvider::InvalidType
:
377 class ResourceProviderTest
378 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
380 ResourceProviderTest()
381 : shared_data_(ContextSharedData::Create()),
383 child_context_(NULL
),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL
)) {
385 switch (GetParam()) {
386 case ResourceProvider::GLTexture
: {
387 scoped_ptr
<ResourceProviderContext
> context3d(
388 ResourceProviderContext::Create(shared_data_
.get()));
389 context3d_
= context3d
.get();
391 scoped_refptr
<TestContextProvider
> context_provider
=
392 TestContextProvider::Create(
393 context3d
.PassAs
<TestWebGraphicsContext3D
>());
395 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
397 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
398 ResourceProviderContext::Create(shared_data_
.get());
399 child_context_
= child_context_owned
.get();
400 child_output_surface_
= FakeOutputSurface::Create3d(
401 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>());
404 case ResourceProvider::Bitmap
:
405 output_surface_
= FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice
));
407 child_output_surface_
= FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice
));
410 case ResourceProvider::InvalidType
:
414 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
415 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
417 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
420 ResourceProvider::Create(output_surface_
.get(),
421 shared_bitmap_manager_
.get(),
422 main_thread_task_runner_
.get(),
427 child_resource_provider_
=
428 ResourceProvider::Create(child_output_surface_
.get(),
429 shared_bitmap_manager_
.get(),
430 main_thread_task_runner_
.get(),
437 static void CollectResources(ReturnedResourceArray
* array
,
438 const ReturnedResourceArray
& returned
,
439 BlockingTaskRunner
* main_thread_task_runner
) {
440 array
->insert(array
->end(), returned
.begin(), returned
.end());
443 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
444 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
447 static void SetResourceFilter(ResourceProvider
* resource_provider
,
448 ResourceProvider::ResourceId id
,
450 ResourceProvider::ScopedSamplerGL
sampler(
451 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
454 ResourceProviderContext
* context() { return context3d_
; }
456 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
458 bool* release_called
,
459 uint32
* sync_point
) {
460 if (GetParam() == ResourceProvider::GLTexture
) {
461 unsigned texture
= child_context_
->createTexture();
462 gpu::Mailbox gpu_mailbox
;
463 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
464 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
465 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
466 *sync_point
= child_context_
->insertSyncPoint();
467 EXPECT_LT(0u, *sync_point
);
469 scoped_ptr
<base::SharedMemory
> shared_memory
;
470 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
471 SingleReleaseCallbackImpl::Create(
472 base::Bind(ReleaseSharedMemoryCallback
,
473 base::Passed(&shared_memory
),
477 return child_resource_provider_
->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
481 gfx::Size
size(64, 64);
482 scoped_ptr
<base::SharedMemory
> shared_memory(
483 CreateAndFillSharedMemory(size
, 0));
485 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
486 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
487 SingleReleaseCallbackImpl::Create(
488 base::Bind(ReleaseSharedMemoryCallback
,
489 base::Passed(&shared_memory
),
493 return child_resource_provider_
->CreateResourceFromTextureMailbox(
494 TextureMailbox(shared_memory_ptr
, size
), callback
.Pass());
499 scoped_ptr
<ContextSharedData
> shared_data_
;
500 ResourceProviderContext
* context3d_
;
501 ResourceProviderContext
* child_context_
;
502 FakeOutputSurfaceClient output_surface_client_
;
503 FakeOutputSurfaceClient child_output_surface_client_
;
504 scoped_ptr
<OutputSurface
> output_surface_
;
505 scoped_ptr
<OutputSurface
> child_output_surface_
;
506 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
507 scoped_ptr
<ResourceProvider
> resource_provider_
;
508 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
509 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
512 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
513 ResourceProvider
* resource_provider
,
514 ResourceProviderContext
* context
) {
515 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
517 gfx::Size
size(1, 1);
518 ResourceFormat format
= RGBA_8888
;
519 size_t pixel_size
= TextureSizeBytes(size
, format
);
520 ASSERT_EQ(4U, pixel_size
);
522 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
523 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
524 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
525 if (expected_default_type
== ResourceProvider::GLTexture
)
526 EXPECT_EQ(0u, context
->NumTextures());
528 uint8_t data
[4] = { 1, 2, 3, 4 };
529 gfx::Rect
rect(size
);
530 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
531 if (expected_default_type
== ResourceProvider::GLTexture
)
532 EXPECT_EQ(1u, context
->NumTextures());
534 uint8_t result
[4] = { 0 };
535 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
536 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
538 resource_provider
->DeleteResource(id
);
539 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
540 if (expected_default_type
== ResourceProvider::GLTexture
)
541 EXPECT_EQ(0u, context
->NumTextures());
544 TEST_P(ResourceProviderTest
, Basic
) {
545 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
548 TEST_P(ResourceProviderTest
, Upload
) {
549 gfx::Size
size(2, 2);
550 ResourceFormat format
= RGBA_8888
;
551 size_t pixel_size
= TextureSizeBytes(size
, format
);
552 ASSERT_EQ(16U, pixel_size
);
554 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
555 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
557 uint8_t image
[16] = { 0 };
558 gfx::Rect
image_rect(size
);
559 resource_provider_
->SetPixels(
560 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
562 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
565 uint8_t result
[16] = { 0 };
567 gfx::Rect
source_rect(0, 0, 1, 1);
568 gfx::Vector2d
dest_offset(0, 0);
569 resource_provider_
->SetPixels(
570 id
, image
, image_rect
, source_rect
, dest_offset
);
572 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
574 resource_provider_
.get(), context(), id
, size
, format
, result
);
575 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
578 gfx::Rect
source_rect(0, 0, 1, 1);
579 gfx::Vector2d
dest_offset(1, 1);
580 resource_provider_
->SetPixels(
581 id
, image
, image_rect
, source_rect
, dest_offset
);
583 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
585 resource_provider_
.get(), context(), id
, size
, format
, result
);
586 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
589 gfx::Rect
source_rect(1, 0, 1, 1);
590 gfx::Vector2d
dest_offset(0, 1);
591 resource_provider_
->SetPixels(
592 id
, image
, image_rect
, source_rect
, dest_offset
);
594 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
596 resource_provider_
.get(), context(), id
, size
, format
, result
);
597 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
600 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
601 gfx::Rect
source_rect(100, 100, 1, 1);
602 gfx::Vector2d
dest_offset(1, 0);
603 resource_provider_
->SetPixels(
604 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
606 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
608 resource_provider_
.get(), context(), id
, size
, format
, result
);
609 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
612 resource_provider_
->DeleteResource(id
);
615 TEST_P(ResourceProviderTest
, TransferGLResources
) {
616 if (GetParam() != ResourceProvider::GLTexture
)
618 gfx::Size
size(1, 1);
619 ResourceFormat format
= RGBA_8888
;
620 size_t pixel_size
= TextureSizeBytes(size
, format
);
621 ASSERT_EQ(4U, pixel_size
);
623 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
624 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
625 uint8_t data1
[4] = { 1, 2, 3, 4 };
626 gfx::Rect
rect(size
);
627 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
629 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
630 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
631 uint8_t data2
[4] = { 5, 5, 5, 5 };
632 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
634 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
635 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
636 child_resource_provider_
->AcquireImageRasterBuffer(id3
);
637 child_resource_provider_
->ReleaseImageRasterBuffer(id3
);
639 GLuint external_texture_id
= child_context_
->createExternalTexture();
640 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
642 gpu::Mailbox external_mailbox
;
643 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
644 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
645 external_mailbox
.name
);
646 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
647 ResourceProvider::ResourceId id4
=
648 child_resource_provider_
->CreateResourceFromTextureMailbox(
650 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
651 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
)));
653 ReturnedResourceArray returned_to_child
;
655 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
657 // Transfer some resources to the parent.
658 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
659 resource_ids_to_transfer
.push_back(id1
);
660 resource_ids_to_transfer
.push_back(id2
);
661 resource_ids_to_transfer
.push_back(id3
);
662 resource_ids_to_transfer
.push_back(id4
);
663 TransferableResourceArray list
;
664 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
666 ASSERT_EQ(4u, list
.size());
667 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
668 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
669 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
670 list
[1].mailbox_holder
.sync_point
);
671 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
672 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
673 list
[2].mailbox_holder
.sync_point
);
674 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
675 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
676 list
[0].mailbox_holder
.texture_target
);
677 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
678 list
[1].mailbox_holder
.texture_target
);
679 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
680 list
[2].mailbox_holder
.texture_target
);
681 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
682 list
[3].mailbox_holder
.texture_target
);
683 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
684 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
685 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
686 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
687 resource_provider_
->ReceiveFromChild(child_id
, list
);
688 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
689 context3d_
->last_waited_sync_point());
691 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
692 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
695 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
696 context3d_
->last_waited_sync_point());
697 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
698 resource_ids_to_transfer
);
701 EXPECT_EQ(4u, resource_provider_
->num_resources());
702 ResourceProvider::ResourceIdMap resource_map
=
703 resource_provider_
->GetChildToParentMap(child_id
);
704 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
705 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
706 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
707 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
708 EXPECT_NE(0u, mapped_id1
);
709 EXPECT_NE(0u, mapped_id2
);
710 EXPECT_NE(0u, mapped_id3
);
711 EXPECT_NE(0u, mapped_id4
);
712 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
713 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
714 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
715 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
717 uint8_t result
[4] = { 0 };
719 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
720 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
723 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
724 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
727 // Check that transfering again the same resource from the child to the
729 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
730 resource_ids_to_transfer
.push_back(id1
);
731 resource_ids_to_transfer
.push_back(id2
);
732 resource_ids_to_transfer
.push_back(id3
);
733 TransferableResourceArray list
;
734 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
736 EXPECT_EQ(3u, list
.size());
737 EXPECT_EQ(id1
, list
[0].id
);
738 EXPECT_EQ(id2
, list
[1].id
);
739 EXPECT_EQ(id3
, list
[2].id
);
740 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
741 list
[0].mailbox_holder
.texture_target
);
742 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
743 list
[1].mailbox_holder
.texture_target
);
744 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
745 list
[2].mailbox_holder
.texture_target
);
746 ReturnedResourceArray returned
;
747 TransferableResource::ReturnResources(list
, &returned
);
748 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
749 // ids were exported twice, we returned them only once, they should still
751 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
752 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
753 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
756 EXPECT_EQ(0u, returned_to_child
.size());
758 // Transfer resources back from the parent to the child. Set no resources as
760 ResourceProvider::ResourceIdArray no_resources
;
761 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
763 ASSERT_EQ(4u, returned_to_child
.size());
764 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
765 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
766 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
767 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
768 EXPECT_FALSE(returned_to_child
[0].lost
);
769 EXPECT_FALSE(returned_to_child
[1].lost
);
770 EXPECT_FALSE(returned_to_child
[2].lost
);
771 EXPECT_FALSE(returned_to_child
[3].lost
);
772 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
773 returned_to_child
.clear();
775 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
776 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
777 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
778 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
781 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
782 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
784 ASSERT_NE(0U, lock
.texture_id());
785 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
786 child_context_
->GetPixels(size
, format
, result
);
787 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
790 child_resource_provider_
->WaitSyncPointIfNeeded(id2
);
791 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
793 ASSERT_NE(0U, lock
.texture_id());
794 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
795 child_context_
->GetPixels(size
, format
, result
);
796 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
799 child_resource_provider_
->WaitSyncPointIfNeeded(id3
);
800 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
802 ASSERT_NE(0U, lock
.texture_id());
803 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
806 // Transfer resources to the parent again.
807 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
808 resource_ids_to_transfer
.push_back(id1
);
809 resource_ids_to_transfer
.push_back(id2
);
810 resource_ids_to_transfer
.push_back(id3
);
811 resource_ids_to_transfer
.push_back(id4
);
812 TransferableResourceArray list
;
813 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
815 ASSERT_EQ(4u, list
.size());
816 EXPECT_EQ(id1
, list
[0].id
);
817 EXPECT_EQ(id2
, list
[1].id
);
818 EXPECT_EQ(id3
, list
[2].id
);
819 EXPECT_EQ(id4
, list
[3].id
);
820 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
821 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
822 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
823 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
824 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
825 list
[0].mailbox_holder
.texture_target
);
826 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
827 list
[1].mailbox_holder
.texture_target
);
828 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
829 list
[2].mailbox_holder
.texture_target
);
830 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
831 list
[3].mailbox_holder
.texture_target
);
832 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
833 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
834 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
835 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
836 resource_provider_
->ReceiveFromChild(child_id
, list
);
837 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
838 resource_ids_to_transfer
);
841 EXPECT_EQ(0u, returned_to_child
.size());
843 EXPECT_EQ(4u, resource_provider_
->num_resources());
844 resource_provider_
->DestroyChild(child_id
);
845 EXPECT_EQ(0u, resource_provider_
->num_resources());
847 ASSERT_EQ(4u, returned_to_child
.size());
848 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
849 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
850 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
851 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
852 EXPECT_FALSE(returned_to_child
[0].lost
);
853 EXPECT_FALSE(returned_to_child
[1].lost
);
854 EXPECT_FALSE(returned_to_child
[2].lost
);
855 EXPECT_FALSE(returned_to_child
[3].lost
);
858 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
859 if (GetParam() != ResourceProvider::GLTexture
)
861 gfx::Size
size(1, 1);
862 ResourceFormat format
= RGBA_8888
;
864 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
865 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
866 uint8_t data1
[4] = {1, 2, 3, 4};
867 gfx::Rect
rect(size
);
868 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
870 ReturnedResourceArray returned_to_child
;
872 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
874 // Transfer some resources to the parent.
875 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
876 resource_ids_to_transfer
.push_back(id1
);
877 TransferableResourceArray list
;
878 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
880 ASSERT_EQ(1u, list
.size());
881 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
883 resource_provider_
->ReceiveFromChild(child_id
, list
);
885 resource_provider_
->WaitSyncPointIfNeeded(list
[0].id
);
886 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
889 resource_provider_
->DeclareUsedResourcesFromChild(
890 child_id
, ResourceProvider::ResourceIdArray());
891 EXPECT_EQ(0u, returned_to_child
.size());
894 EXPECT_EQ(1u, returned_to_child
.size());
895 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
898 child_resource_provider_
->WaitSyncPointIfNeeded(id1
);
899 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
901 child_resource_provider_
->DeleteResource(id1
);
902 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
903 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
906 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
907 resource_provider_
->DestroyChild(child_id
);
910 TEST_P(ResourceProviderTest
, AllowOverlayTransfersToParent
) {
911 // Overlays only supported on the GL path.
912 if (GetParam() != ResourceProvider::GLTexture
)
915 uint32 sync_point
= 0;
916 TextureMailbox
mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
917 mailbox
.set_allow_overlay(true);
918 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback
=
919 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
920 ResourceProvider::ResourceId id1
=
921 child_resource_provider_
->CreateResourceFromTextureMailbox(
922 mailbox
, release_callback
.Pass());
924 TextureMailbox
mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D
, sync_point
);
925 mailbox2
.set_allow_overlay(false);
926 scoped_ptr
<SingleReleaseCallbackImpl
> release_callback2
=
927 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
928 ResourceProvider::ResourceId id2
=
929 child_resource_provider_
->CreateResourceFromTextureMailbox(
930 mailbox2
, release_callback2
.Pass());
932 ReturnedResourceArray returned_to_child
;
934 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
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 TransferableResourceArray list
;
941 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
943 ASSERT_EQ(2u, list
.size());
944 resource_provider_
->ReceiveFromChild(child_id
, list
);
945 EXPECT_TRUE(resource_provider_
->AllowOverlay(list
[0].id
));
946 EXPECT_FALSE(resource_provider_
->AllowOverlay(list
[1].id
));
948 resource_provider_
->DeclareUsedResourcesFromChild(
949 child_id
, ResourceProvider::ResourceIdArray());
951 EXPECT_EQ(2u, returned_to_child
.size());
952 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
954 child_resource_provider_
->DeleteResource(id1
);
955 child_resource_provider_
->DeleteResource(id2
);
956 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
958 resource_provider_
->DestroyChild(child_id
);
961 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
962 if (GetParam() != ResourceProvider::Bitmap
)
965 gfx::Size
size(1, 1);
966 ResourceFormat format
= RGBA_8888
;
967 size_t pixel_size
= TextureSizeBytes(size
, format
);
968 ASSERT_EQ(4U, pixel_size
);
970 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
971 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
972 uint8_t data1
[4] = { 1, 2, 3, 4 };
973 gfx::Rect
rect(size
);
974 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
976 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
977 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
978 uint8_t data2
[4] = { 5, 5, 5, 5 };
979 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
981 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
982 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
983 uint8_t data3
[4] = { 6, 7, 8, 9 };
984 SkImageInfo info
= SkImageInfo::MakeN32Premul(size
.width(), size
.height());
985 RasterBuffer
* raster_buffer
=
986 child_resource_provider_
->AcquireImageRasterBuffer(id3
);
987 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
988 canvas
->writePixels(info
, data3
, info
.minRowBytes(), 0, 0);
989 raster_buffer
->ReleaseSkCanvas(canvas
);
991 child_resource_provider_
->ReleaseImageRasterBuffer(id3
);
993 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
994 shared_memory
->CreateAndMapAnonymous(1);
995 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
996 ResourceProvider::ResourceId id4
=
997 child_resource_provider_
->CreateResourceFromTextureMailbox(
998 TextureMailbox(shared_memory_ptr
, gfx::Size(1, 1)),
999 SingleReleaseCallbackImpl::Create(base::Bind(
1000 &SharedMemoryReleaseCallback
, base::Passed(&shared_memory
))));
1002 ReturnedResourceArray returned_to_child
;
1004 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1006 // Transfer some resources to the parent.
1007 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1008 resource_ids_to_transfer
.push_back(id1
);
1009 resource_ids_to_transfer
.push_back(id2
);
1010 resource_ids_to_transfer
.push_back(id3
);
1011 resource_ids_to_transfer
.push_back(id4
);
1012 TransferableResourceArray list
;
1013 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1015 ASSERT_EQ(4u, list
.size());
1016 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
1017 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
1018 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
1019 EXPECT_EQ(0u, list
[3].mailbox_holder
.sync_point
);
1020 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1021 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1022 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1023 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
1024 resource_provider_
->ReceiveFromChild(child_id
, list
);
1025 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1026 resource_ids_to_transfer
);
1029 EXPECT_EQ(4u, resource_provider_
->num_resources());
1030 ResourceProvider::ResourceIdMap resource_map
=
1031 resource_provider_
->GetChildToParentMap(child_id
);
1032 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1033 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1034 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
1035 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
1036 EXPECT_NE(0u, mapped_id1
);
1037 EXPECT_NE(0u, mapped_id2
);
1038 EXPECT_NE(0u, mapped_id3
);
1039 EXPECT_NE(0u, mapped_id4
);
1040 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1041 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1042 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
1043 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
1045 uint8_t result
[4] = { 0 };
1047 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
1048 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
1051 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
1052 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
1055 resource_provider_
.get(), context(), mapped_id3
, size
, format
, result
);
1056 EXPECT_EQ(0, memcmp(data3
, result
, pixel_size
));
1059 // Check that transfering again the same resource from the child to the
1061 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1062 resource_ids_to_transfer
.push_back(id1
);
1063 resource_ids_to_transfer
.push_back(id2
);
1064 resource_ids_to_transfer
.push_back(id3
);
1065 TransferableResourceArray list
;
1066 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1068 EXPECT_EQ(3u, list
.size());
1069 EXPECT_EQ(id1
, list
[0].id
);
1070 EXPECT_EQ(id2
, list
[1].id
);
1071 EXPECT_EQ(id3
, list
[2].id
);
1072 ReturnedResourceArray returned
;
1073 TransferableResource::ReturnResources(list
, &returned
);
1074 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
1075 // ids were exported twice, we returned them only once, they should still
1077 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1078 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1079 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1082 EXPECT_EQ(0u, returned_to_child
.size());
1084 // Transfer resources back from the parent to the child. Set no resources as
1086 ResourceProvider::ResourceIdArray no_resources
;
1087 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1089 ASSERT_EQ(4u, returned_to_child
.size());
1090 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1091 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1092 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1093 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1094 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1095 expected_ids
.insert(id1
);
1096 expected_ids
.insert(id2
);
1097 expected_ids
.insert(id3
);
1098 expected_ids
.insert(id4
);
1099 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1100 for (unsigned i
= 0; i
< 4; i
++)
1101 returned_ids
.insert(returned_to_child
[i
].id
);
1102 EXPECT_EQ(expected_ids
, returned_ids
);
1103 EXPECT_FALSE(returned_to_child
[0].lost
);
1104 EXPECT_FALSE(returned_to_child
[1].lost
);
1105 EXPECT_FALSE(returned_to_child
[2].lost
);
1106 EXPECT_FALSE(returned_to_child
[3].lost
);
1107 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1108 returned_to_child
.clear();
1110 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1111 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1112 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1113 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
1116 ResourceProvider::ScopedReadLockSoftware
lock(
1117 child_resource_provider_
.get(), id1
);
1118 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1119 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1120 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1121 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1124 ResourceProvider::ScopedReadLockSoftware
lock(
1125 child_resource_provider_
.get(), id2
);
1126 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1127 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1128 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1129 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1132 ResourceProvider::ScopedReadLockSoftware
lock(
1133 child_resource_provider_
.get(), id3
);
1134 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1135 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1136 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1137 EXPECT_EQ(0, memcmp(data3
, sk_bitmap
->getPixels(), pixel_size
));
1140 // Transfer resources to the parent again.
1141 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1142 resource_ids_to_transfer
.push_back(id1
);
1143 resource_ids_to_transfer
.push_back(id2
);
1144 resource_ids_to_transfer
.push_back(id3
);
1145 resource_ids_to_transfer
.push_back(id4
);
1146 TransferableResourceArray list
;
1147 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1149 ASSERT_EQ(4u, list
.size());
1150 EXPECT_EQ(id1
, list
[0].id
);
1151 EXPECT_EQ(id2
, list
[1].id
);
1152 EXPECT_EQ(id3
, list
[2].id
);
1153 EXPECT_EQ(id4
, list
[3].id
);
1154 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1155 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1156 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1157 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
1158 resource_provider_
->ReceiveFromChild(child_id
, list
);
1159 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1160 resource_ids_to_transfer
);
1163 EXPECT_EQ(0u, returned_to_child
.size());
1165 EXPECT_EQ(4u, resource_provider_
->num_resources());
1166 resource_provider_
->DestroyChild(child_id
);
1167 EXPECT_EQ(0u, resource_provider_
->num_resources());
1169 ASSERT_EQ(4u, returned_to_child
.size());
1170 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1171 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1172 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1173 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1174 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1175 expected_ids
.insert(id1
);
1176 expected_ids
.insert(id2
);
1177 expected_ids
.insert(id3
);
1178 expected_ids
.insert(id4
);
1179 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1180 for (unsigned i
= 0; i
< 4; i
++)
1181 returned_ids
.insert(returned_to_child
[i
].id
);
1182 EXPECT_EQ(expected_ids
, returned_ids
);
1183 EXPECT_FALSE(returned_to_child
[0].lost
);
1184 EXPECT_FALSE(returned_to_child
[1].lost
);
1185 EXPECT_FALSE(returned_to_child
[2].lost
);
1186 EXPECT_FALSE(returned_to_child
[3].lost
);
1189 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1190 if (GetParam() != ResourceProvider::Bitmap
)
1193 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1194 ResourceProviderContext::Create(shared_data_
.get()));
1196 FakeOutputSurfaceClient child_output_surface_client
;
1197 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1198 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1199 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1201 scoped_ptr
<ResourceProvider
> child_resource_provider(
1202 ResourceProvider::Create(child_output_surface
.get(),
1203 shared_bitmap_manager_
.get(),
1210 gfx::Size
size(1, 1);
1211 ResourceFormat format
= RGBA_8888
;
1212 size_t pixel_size
= TextureSizeBytes(size
, format
);
1213 ASSERT_EQ(4U, pixel_size
);
1215 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1216 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1217 uint8_t data1
[4] = { 1, 2, 3, 4 };
1218 gfx::Rect
rect(size
);
1219 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1221 ReturnedResourceArray returned_to_child
;
1223 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1225 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1226 resource_ids_to_transfer
.push_back(id1
);
1227 TransferableResourceArray list
;
1228 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1230 ASSERT_EQ(1u, list
.size());
1231 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1232 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1233 list
[0].mailbox_holder
.texture_target
);
1234 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1235 resource_provider_
->ReceiveFromChild(child_id
, list
);
1238 EXPECT_EQ(0u, resource_provider_
->num_resources());
1239 ASSERT_EQ(1u, returned_to_child
.size());
1240 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1241 ResourceProvider::ResourceIdMap resource_map
=
1242 resource_provider_
->GetChildToParentMap(child_id
);
1243 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1244 EXPECT_EQ(0u, mapped_id1
);
1246 resource_provider_
->DestroyChild(child_id
);
1247 EXPECT_EQ(0u, resource_provider_
->num_resources());
1249 ASSERT_EQ(1u, returned_to_child
.size());
1250 EXPECT_FALSE(returned_to_child
[0].lost
);
1253 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1254 if (GetParam() != ResourceProvider::Bitmap
)
1257 gfx::Size
size(1, 1);
1258 ResourceFormat format
= RGBA_8888
;
1259 size_t pixel_size
= TextureSizeBytes(size
, format
);
1260 ASSERT_EQ(4U, pixel_size
);
1262 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1263 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1264 uint8_t data1
[4] = { 1, 2, 3, 4 };
1265 gfx::Rect
rect(size
);
1266 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1268 ReturnedResourceArray returned_to_child
;
1270 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1272 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1273 resource_ids_to_transfer
.push_back(id1
);
1274 TransferableResourceArray list
;
1275 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1277 ASSERT_EQ(1u, list
.size());
1279 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1280 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1281 resource_provider_
->ReceiveFromChild(child_id
, list
);
1284 EXPECT_EQ(1u, resource_provider_
->num_resources());
1285 EXPECT_EQ(0u, returned_to_child
.size());
1287 ResourceProvider::ResourceIdMap resource_map
=
1288 resource_provider_
->GetChildToParentMap(child_id
);
1289 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1290 EXPECT_NE(0u, mapped_id1
);
1292 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1294 EXPECT_FALSE(lock
.valid());
1297 resource_provider_
->DestroyChild(child_id
);
1298 EXPECT_EQ(0u, resource_provider_
->num_resources());
1300 ASSERT_EQ(1u, returned_to_child
.size());
1301 EXPECT_FALSE(returned_to_child
[0].lost
);
1304 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1305 gfx::Size
size(1, 1);
1306 ResourceFormat format
= RGBA_8888
;
1307 size_t pixel_size
= TextureSizeBytes(size
, format
);
1308 ASSERT_EQ(4U, pixel_size
);
1310 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1311 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1312 uint8_t data1
[4] = { 1, 2, 3, 4 };
1313 gfx::Rect
rect(size
);
1314 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1316 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1317 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1318 uint8_t data2
[4] = {5, 5, 5, 5};
1319 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1321 ReturnedResourceArray returned_to_child
;
1323 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1325 // Transfer some resources to the parent.
1326 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1327 resource_ids_to_transfer
.push_back(id1
);
1328 resource_ids_to_transfer
.push_back(id2
);
1329 TransferableResourceArray list
;
1330 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1332 ASSERT_EQ(2u, list
.size());
1333 if (GetParam() == ResourceProvider::GLTexture
) {
1334 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1335 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1337 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1338 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1339 resource_provider_
->ReceiveFromChild(child_id
, list
);
1340 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1341 resource_ids_to_transfer
);
1344 EXPECT_EQ(2u, resource_provider_
->num_resources());
1345 ResourceProvider::ResourceIdMap resource_map
=
1346 resource_provider_
->GetChildToParentMap(child_id
);
1347 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1348 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1349 EXPECT_NE(0u, mapped_id1
);
1350 EXPECT_NE(0u, mapped_id2
);
1351 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1352 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1355 // The parent transfers the resources to the grandparent.
1356 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1357 resource_ids_to_transfer
.push_back(mapped_id1
);
1358 resource_ids_to_transfer
.push_back(mapped_id2
);
1359 TransferableResourceArray list
;
1360 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1362 ASSERT_EQ(2u, list
.size());
1363 if (GetParam() == ResourceProvider::GLTexture
) {
1364 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1365 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1367 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1368 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1370 // Release the resource in the parent. Set no resources as being in use. The
1371 // resources are exported so that can't be transferred back yet.
1372 ResourceProvider::ResourceIdArray no_resources
;
1373 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1375 EXPECT_EQ(0u, returned_to_child
.size());
1376 EXPECT_EQ(2u, resource_provider_
->num_resources());
1378 // Return the resources from the grandparent to the parent. They should be
1379 // returned to the child then.
1380 EXPECT_EQ(2u, list
.size());
1381 EXPECT_EQ(mapped_id1
, list
[0].id
);
1382 EXPECT_EQ(mapped_id2
, list
[1].id
);
1383 ReturnedResourceArray returned
;
1384 TransferableResource::ReturnResources(list
, &returned
);
1385 resource_provider_
->ReceiveReturnsFromParent(returned
);
1387 EXPECT_EQ(0u, resource_provider_
->num_resources());
1388 ASSERT_EQ(2u, returned_to_child
.size());
1389 if (GetParam() == ResourceProvider::GLTexture
) {
1390 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1391 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1393 EXPECT_FALSE(returned_to_child
[0].lost
);
1394 EXPECT_FALSE(returned_to_child
[1].lost
);
1398 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1399 gfx::Size
size(1, 1);
1400 ResourceFormat format
= RGBA_8888
;
1401 size_t pixel_size
= TextureSizeBytes(size
, format
);
1402 ASSERT_EQ(4U, pixel_size
);
1404 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1405 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1406 uint8_t data1
[4] = {1, 2, 3, 4};
1407 gfx::Rect
rect(size
);
1408 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1410 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1411 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1412 uint8_t data2
[4] = {5, 5, 5, 5};
1413 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1415 ReturnedResourceArray returned_to_child
;
1417 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1419 // Transfer some resources to the parent.
1420 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1421 resource_ids_to_transfer
.push_back(id1
);
1422 resource_ids_to_transfer
.push_back(id2
);
1423 TransferableResourceArray list
;
1424 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1426 ASSERT_EQ(2u, list
.size());
1427 if (GetParam() == ResourceProvider::GLTexture
) {
1428 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1429 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1431 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1432 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1433 resource_provider_
->ReceiveFromChild(child_id
, list
);
1434 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1435 resource_ids_to_transfer
);
1438 EXPECT_EQ(2u, resource_provider_
->num_resources());
1439 ResourceProvider::ResourceIdMap resource_map
=
1440 resource_provider_
->GetChildToParentMap(child_id
);
1441 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1442 ResourceProvider::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::GLTexture
) {
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::ResourceIdArray no_resources
;
1467 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1469 // Destroy the child, the resources should not be returned yet.
1470 EXPECT_EQ(0u, returned_to_child
.size());
1471 EXPECT_EQ(2u, resource_provider_
->num_resources());
1473 resource_provider_
->DestroyChild(child_id
);
1475 EXPECT_EQ(2u, resource_provider_
->num_resources());
1476 ASSERT_EQ(0u, returned_to_child
.size());
1478 // Return a resource from the grandparent, it should be returned at this
1480 EXPECT_EQ(2u, list
.size());
1481 EXPECT_EQ(mapped_id1
, list
[0].id
);
1482 EXPECT_EQ(mapped_id2
, list
[1].id
);
1483 TransferableResourceArray return_list
;
1484 return_list
.push_back(list
[1]);
1486 ReturnedResourceArray returned
;
1487 TransferableResource::ReturnResources(return_list
, &returned
);
1488 resource_provider_
->ReceiveReturnsFromParent(returned
);
1490 EXPECT_EQ(1u, resource_provider_
->num_resources());
1491 ASSERT_EQ(1u, returned_to_child
.size());
1492 if (GetParam() == ResourceProvider::GLTexture
) {
1493 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1495 EXPECT_FALSE(returned_to_child
[0].lost
);
1496 returned_to_child
.clear();
1498 // Destroy the parent resource provider. The resource that's left should be
1499 // lost at this point, and returned.
1500 resource_provider_
.reset();
1501 ASSERT_EQ(1u, returned_to_child
.size());
1502 if (GetParam() == ResourceProvider::GLTexture
) {
1503 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1505 EXPECT_TRUE(returned_to_child
[0].lost
);
1509 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1510 gfx::Size
size(1, 1);
1511 ResourceFormat format
= RGBA_8888
;
1512 size_t pixel_size
= TextureSizeBytes(size
, format
);
1513 ASSERT_EQ(4U, pixel_size
);
1515 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1516 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1517 uint8_t data
[4] = { 1, 2, 3, 4 };
1518 gfx::Rect
rect(size
);
1519 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1521 ReturnedResourceArray returned_to_child
;
1523 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1525 // Transfer some resource to the parent.
1526 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1527 resource_ids_to_transfer
.push_back(id
);
1528 TransferableResourceArray list
;
1529 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1531 ASSERT_EQ(1u, list
.size());
1532 if (GetParam() == ResourceProvider::GLTexture
)
1533 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1534 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1535 resource_provider_
->ReceiveFromChild(child_id
, list
);
1536 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1537 resource_ids_to_transfer
);
1540 // Delete textures in the child, while they are transfered.
1541 child_resource_provider_
->DeleteResource(id
);
1542 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1544 EXPECT_EQ(0u, returned_to_child
.size());
1546 // Transfer resources back from the parent to the child. Set no resources as
1548 ResourceProvider::ResourceIdArray no_resources
;
1549 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1551 ASSERT_EQ(1u, returned_to_child
.size());
1552 if (GetParam() == ResourceProvider::GLTexture
)
1553 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1554 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1556 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1559 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1560 gfx::Size
size(1, 1);
1561 ResourceFormat format
= RGBA_8888
;
1562 size_t pixel_size
= TextureSizeBytes(size
, format
);
1563 ASSERT_EQ(4U, pixel_size
);
1565 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1566 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1567 uint8_t data
[4] = {1, 2, 3, 4};
1568 gfx::Rect
rect(size
);
1569 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1571 ReturnedResourceArray returned_to_child
;
1573 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1574 const ResourceProvider::ResourceIdMap
& map
=
1575 resource_provider_
->GetChildToParentMap(child_id
);
1577 // Transfer some resource to the parent.
1578 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1579 resource_ids_to_transfer
.push_back(id
);
1580 TransferableResourceArray list
;
1581 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1583 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1584 resource_provider_
->ReceiveFromChild(child_id
, list
);
1585 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1586 resource_ids_to_transfer
);
1588 TransferableResourceArray sent_to_top_level
;
1590 // Parent transfers to top-level.
1591 ASSERT_TRUE(map
.find(id
) != map
.end());
1592 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1593 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1594 resource_ids_to_transfer
.push_back(parent_id
);
1595 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1596 &sent_to_top_level
);
1597 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1600 // Stop using resource.
1601 ResourceProvider::ResourceIdArray empty
;
1602 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1603 // Resource is not yet returned to the child, since it's in use by the
1605 EXPECT_TRUE(returned_to_child
.empty());
1608 // Send the resource to the parent again.
1609 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1610 resource_ids_to_transfer
.push_back(id
);
1611 TransferableResourceArray list
;
1612 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1614 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1615 resource_provider_
->ReceiveFromChild(child_id
, list
);
1616 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1617 resource_ids_to_transfer
);
1620 // Receive returns back from top-level.
1621 ReturnedResourceArray returned
;
1622 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1623 resource_provider_
->ReceiveReturnsFromParent(returned
);
1624 // Resource is still not yet returned to the child, since it's declared used
1626 EXPECT_TRUE(returned_to_child
.empty());
1627 ASSERT_TRUE(map
.find(id
) != map
.end());
1628 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1629 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1632 sent_to_top_level
.clear();
1633 // Parent transfers again to top-level.
1634 ASSERT_TRUE(map
.find(id
) != map
.end());
1635 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1636 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1637 resource_ids_to_transfer
.push_back(parent_id
);
1638 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1639 &sent_to_top_level
);
1640 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1643 // Receive returns back from top-level.
1644 ReturnedResourceArray returned
;
1645 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1646 resource_provider_
->ReceiveReturnsFromParent(returned
);
1647 // Resource is still not yet returned to the child, since it's still
1648 // declared used in the parent.
1649 EXPECT_TRUE(returned_to_child
.empty());
1650 ASSERT_TRUE(map
.find(id
) != map
.end());
1651 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1652 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1655 // Stop using resource.
1656 ResourceProvider::ResourceIdArray empty
;
1657 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1658 // Resource should have been returned to the child, since it's no longer in
1659 // use by the top-level.
1660 ASSERT_EQ(1u, returned_to_child
.size());
1661 EXPECT_EQ(id
, returned_to_child
[0].id
);
1662 EXPECT_EQ(2, returned_to_child
[0].count
);
1663 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1664 returned_to_child
.clear();
1665 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1669 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1671 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1672 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1673 new TextureStateTrackingContext
);
1674 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1676 FakeOutputSurfaceClient child_output_surface_client
;
1677 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1678 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1679 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1680 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1681 new TestSharedBitmapManager());
1683 scoped_ptr
<ResourceProvider
> child_resource_provider(
1684 ResourceProvider::Create(child_output_surface
.get(),
1685 shared_bitmap_manager
.get(),
1692 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1693 new TextureStateTrackingContext
);
1694 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1696 FakeOutputSurfaceClient parent_output_surface_client
;
1697 scoped_ptr
<OutputSurface
> parent_output_surface(FakeOutputSurface::Create3d(
1698 parent_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1699 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1701 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1702 ResourceProvider::Create(parent_output_surface
.get(),
1703 shared_bitmap_manager
.get(),
1710 gfx::Size
size(1, 1);
1711 ResourceFormat format
= RGBA_8888
;
1712 int child_texture_id
= 1;
1713 int parent_texture_id
= 2;
1715 size_t pixel_size
= TextureSizeBytes(size
, format
);
1716 ASSERT_EQ(4U, pixel_size
);
1718 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1719 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
1721 // The new texture is created with GL_LINEAR.
1722 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1723 .Times(2); // Once to create and once to allocate.
1724 EXPECT_CALL(*child_context
,
1725 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1726 EXPECT_CALL(*child_context
,
1727 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1730 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1733 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1734 EXPECT_CALL(*child_context
,
1735 texParameteri(GL_TEXTURE_2D
,
1736 GL_TEXTURE_POOL_CHROMIUM
,
1737 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1738 child_resource_provider
->AllocateForTesting(id
);
1739 Mock::VerifyAndClearExpectations(child_context
);
1741 uint8_t data
[4] = { 1, 2, 3, 4 };
1742 gfx::Rect
rect(size
);
1744 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1745 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1746 Mock::VerifyAndClearExpectations(child_context
);
1748 // The texture is set to |child_filter| in the child.
1749 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1750 if (child_filter
!= GL_LINEAR
) {
1753 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1756 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1758 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1759 Mock::VerifyAndClearExpectations(child_context
);
1761 ReturnedResourceArray returned_to_child
;
1762 int child_id
= parent_resource_provider
->CreateChild(
1763 GetReturnCallback(&returned_to_child
));
1765 // Transfer some resource to the parent.
1766 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1767 resource_ids_to_transfer
.push_back(id
);
1768 TransferableResourceArray list
;
1770 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1771 EXPECT_CALL(*child_context
,
1772 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1773 EXPECT_CALL(*child_context
, insertSyncPoint());
1774 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1776 Mock::VerifyAndClearExpectations(child_context
);
1778 ASSERT_EQ(1u, list
.size());
1779 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1781 EXPECT_CALL(*parent_context
,
1782 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1783 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1784 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1786 parent_resource_provider
->WaitSyncPointIfNeeded(list
[0].id
);
1787 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1790 Mock::VerifyAndClearExpectations(parent_context
);
1792 parent_resource_provider
->DeclareUsedResourcesFromChild(
1793 child_id
, resource_ids_to_transfer
);
1794 Mock::VerifyAndClearExpectations(parent_context
);
1796 ResourceProvider::ResourceIdMap resource_map
=
1797 parent_resource_provider
->GetChildToParentMap(child_id
);
1798 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1799 EXPECT_NE(0u, mapped_id
);
1801 // The texture is set to |parent_filter| in the parent.
1802 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1805 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1808 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1809 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1810 Mock::VerifyAndClearExpectations(parent_context
);
1812 // The texture should be reset to |child_filter| in the parent when it is
1813 // returned, since that is how it was received.
1814 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1817 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1820 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1823 EXPECT_EQ(0u, returned_to_child
.size());
1825 // Transfer resources back from the parent to the child. Set no resources
1827 ResourceProvider::ResourceIdArray no_resources
;
1828 EXPECT_CALL(*parent_context
, insertSyncPoint());
1829 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1831 Mock::VerifyAndClearExpectations(parent_context
);
1833 ASSERT_EQ(1u, returned_to_child
.size());
1834 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1837 // The child remembers the texture filter is set to |child_filter|.
1838 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1839 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1840 Mock::VerifyAndClearExpectations(child_context
);
1844 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1845 if (GetParam() != ResourceProvider::GLTexture
)
1847 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1850 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1851 if (GetParam() != ResourceProvider::GLTexture
)
1853 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1856 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1857 // Other mailbox transfers tested elsewhere.
1858 if (GetParam() != ResourceProvider::GLTexture
)
1860 unsigned texture
= context()->createTexture();
1861 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1862 uint8_t data
[4] = { 1, 2, 3, 4 };
1863 context()->texImage2D(
1864 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1865 gpu::Mailbox mailbox
;
1866 context()->genMailboxCHROMIUM(mailbox
.name
);
1867 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1868 uint32 sync_point
= context()->insertSyncPoint();
1870 // All the logic below assumes that the sync points are all positive.
1871 EXPECT_LT(0u, sync_point
);
1873 uint32 release_sync_point
= 0;
1874 bool lost_resource
= false;
1875 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
1876 ReleaseCallbackImpl callback
= base::Bind(ReleaseCallback
,
1877 &release_sync_point
,
1879 &main_thread_task_runner
);
1880 ResourceProvider::ResourceId resource
=
1881 resource_provider_
->CreateResourceFromTextureMailbox(
1882 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1883 SingleReleaseCallbackImpl::Create(callback
));
1884 EXPECT_EQ(1u, context()->NumTextures());
1885 EXPECT_EQ(0u, release_sync_point
);
1887 // Transfer the resource, expect the sync points to be consistent.
1888 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1889 resource_ids_to_transfer
.push_back(resource
);
1890 TransferableResourceArray list
;
1891 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1892 ASSERT_EQ(1u, list
.size());
1893 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1895 memcmp(mailbox
.name
,
1896 list
[0].mailbox_holder
.mailbox
.name
,
1897 sizeof(mailbox
.name
)));
1898 EXPECT_EQ(0u, release_sync_point
);
1900 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1901 unsigned other_texture
= context()->createTexture();
1902 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1903 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1904 uint8_t test_data
[4] = { 0 };
1905 context()->GetPixels(
1906 gfx::Size(1, 1), RGBA_8888
, test_data
);
1907 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1908 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1909 context()->deleteTexture(other_texture
);
1910 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1911 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1913 // Receive the resource, then delete it, expect the sync points to be
1915 ReturnedResourceArray returned
;
1916 TransferableResource::ReturnResources(list
, &returned
);
1917 resource_provider_
->ReceiveReturnsFromParent(returned
);
1918 EXPECT_EQ(1u, context()->NumTextures());
1919 EXPECT_EQ(0u, release_sync_point
);
1921 resource_provider_
->DeleteResource(resource
);
1922 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1923 EXPECT_FALSE(lost_resource
);
1924 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1927 // We're going to do the same thing as above, but testing the case where we
1928 // delete the resource before we receive it back.
1929 sync_point
= release_sync_point
;
1930 EXPECT_LT(0u, sync_point
);
1931 release_sync_point
= 0;
1932 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1933 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1934 SingleReleaseCallbackImpl::Create(callback
));
1935 EXPECT_EQ(1u, context()->NumTextures());
1936 EXPECT_EQ(0u, release_sync_point
);
1938 // Transfer the resource, expect the sync points to be consistent.
1939 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1940 resource_ids_to_transfer
.push_back(resource
);
1941 TransferableResourceArray list
;
1942 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1943 ASSERT_EQ(1u, list
.size());
1944 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1946 memcmp(mailbox
.name
,
1947 list
[0].mailbox_holder
.mailbox
.name
,
1948 sizeof(mailbox
.name
)));
1949 EXPECT_EQ(0u, release_sync_point
);
1951 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1952 unsigned other_texture
= context()->createTexture();
1953 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1954 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1955 uint8_t test_data
[4] = { 0 };
1956 context()->GetPixels(
1957 gfx::Size(1, 1), RGBA_8888
, test_data
);
1958 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1959 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1960 context()->deleteTexture(other_texture
);
1961 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1962 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1964 // Delete the resource, which shouldn't do anything.
1965 resource_provider_
->DeleteResource(resource
);
1966 EXPECT_EQ(1u, context()->NumTextures());
1967 EXPECT_EQ(0u, release_sync_point
);
1969 // Then receive the resource which should release the mailbox, expect the
1970 // sync points to be consistent.
1971 ReturnedResourceArray returned
;
1972 TransferableResource::ReturnResources(list
, &returned
);
1973 resource_provider_
->ReceiveReturnsFromParent(returned
);
1974 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1975 EXPECT_FALSE(lost_resource
);
1976 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
1979 context()->waitSyncPoint(release_sync_point
);
1980 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1981 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1982 context()->deleteTexture(texture
);
1985 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1986 gfx::Size
size(1, 1);
1987 ResourceFormat format
= RGBA_8888
;
1988 ResourceProvider::ResourceId resource
=
1989 child_resource_provider_
->CreateResource(
1992 ResourceProvider::TextureHintImmutable
,
1994 child_resource_provider_
->AllocateForTesting(resource
);
1995 // Expect a GL resource to be lost.
1996 bool should_lose_resource
= GetParam() == ResourceProvider::GLTexture
;
1998 ReturnedResourceArray returned_to_child
;
2000 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2002 // Transfer the resource to the parent.
2003 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2004 resource_ids_to_transfer
.push_back(resource
);
2005 TransferableResourceArray list
;
2006 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2008 EXPECT_EQ(1u, list
.size());
2010 resource_provider_
->ReceiveFromChild(child_id
, list
);
2011 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2012 resource_ids_to_transfer
);
2015 // Lose the output surface in the parent.
2016 resource_provider_
->DidLoseOutputSurface();
2019 EXPECT_EQ(0u, returned_to_child
.size());
2021 // Transfer resources back from the parent to the child. Set no resources as
2023 ResourceProvider::ResourceIdArray no_resources
;
2024 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2026 // Expect a GL resource to be lost.
2027 ASSERT_EQ(1u, returned_to_child
.size());
2028 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
2029 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2030 returned_to_child
.clear();
2033 // A GL resource should be lost.
2034 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
2036 // Lost resources stay in use in the parent forever.
2037 EXPECT_EQ(should_lose_resource
,
2038 child_resource_provider_
->InUseByConsumer(resource
));
2041 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
2042 gfx::Size
size(1, 1);
2043 ResourceFormat format
= RGBA_8888
;
2044 ResourceProvider::ResourceId resource
=
2045 child_resource_provider_
->CreateResource(
2048 ResourceProvider::TextureHintImmutable
,
2050 child_resource_provider_
->AllocateForTesting(resource
);
2052 ReturnedResourceArray returned_to_child
;
2054 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2056 // Transfer the resource to the parent.
2057 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2058 resource_ids_to_transfer
.push_back(resource
);
2059 TransferableResourceArray list
;
2060 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2062 EXPECT_EQ(1u, list
.size());
2064 resource_provider_
->ReceiveFromChild(child_id
, list
);
2065 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2066 resource_ids_to_transfer
);
2070 ResourceProvider::ResourceIdMap resource_map
=
2071 resource_provider_
->GetChildToParentMap(child_id
);
2072 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2073 EXPECT_NE(0u, parent_resource
);
2075 // Transfer to a grandparent.
2076 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2077 resource_ids_to_transfer
.push_back(parent_resource
);
2078 TransferableResourceArray list
;
2079 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2081 // Receive back a lost resource from the grandparent.
2082 EXPECT_EQ(1u, list
.size());
2083 EXPECT_EQ(parent_resource
, list
[0].id
);
2084 ReturnedResourceArray returned
;
2085 TransferableResource::ReturnResources(list
, &returned
);
2086 EXPECT_EQ(1u, returned
.size());
2087 EXPECT_EQ(parent_resource
, returned
[0].id
);
2088 returned
[0].lost
= true;
2089 resource_provider_
->ReceiveReturnsFromParent(returned
);
2091 // The resource should be lost.
2092 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
2094 // Lost resources stay in use in the parent forever.
2095 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
2099 EXPECT_EQ(0u, returned_to_child
.size());
2101 // Transfer resources back from the parent to the child. Set no resources as
2103 ResourceProvider::ResourceIdArray no_resources
;
2104 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2106 // Expect the resource to be lost.
2107 ASSERT_EQ(1u, returned_to_child
.size());
2108 EXPECT_TRUE(returned_to_child
[0].lost
);
2109 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2110 returned_to_child
.clear();
2113 // The resource should be lost.
2114 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2116 // Lost resources stay in use in the parent forever.
2117 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2120 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2121 uint32 release_sync_point
= 0;
2122 bool lost_resource
= false;
2123 bool release_called
= false;
2124 uint32 sync_point
= 0;
2125 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2126 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2128 ReturnedResourceArray returned_to_child
;
2130 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2132 // Transfer the resource to the parent.
2133 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2134 resource_ids_to_transfer
.push_back(resource
);
2135 TransferableResourceArray list
;
2136 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2138 EXPECT_EQ(1u, list
.size());
2140 resource_provider_
->ReceiveFromChild(child_id
, list
);
2141 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2142 resource_ids_to_transfer
);
2145 // Lose the output surface in the parent.
2146 resource_provider_
->DidLoseOutputSurface();
2149 EXPECT_EQ(0u, returned_to_child
.size());
2151 // Transfer resources back from the parent to the child. Set no resources as
2153 ResourceProvider::ResourceIdArray no_resources
;
2154 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2156 ASSERT_EQ(1u, returned_to_child
.size());
2157 // Losing an output surface only loses hardware resources.
2158 EXPECT_EQ(returned_to_child
[0].lost
,
2159 GetParam() == ResourceProvider::GLTexture
);
2160 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2161 returned_to_child
.clear();
2164 // Delete the resource in the child. Expect the resource to be lost if it's
2166 child_resource_provider_
->DeleteResource(resource
);
2167 EXPECT_EQ(lost_resource
, GetParam() == ResourceProvider::GLTexture
);
2170 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2171 uint32 release_sync_point
= 0;
2172 bool lost_resource
= false;
2173 bool release_called
= false;
2174 uint32 sync_point
= 0;
2175 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2176 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2178 ReturnedResourceArray returned_to_child
;
2180 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2182 // Transfer the resource to the parent.
2183 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2184 resource_ids_to_transfer
.push_back(resource
);
2185 TransferableResourceArray list
;
2186 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2188 EXPECT_EQ(1u, list
.size());
2190 resource_provider_
->ReceiveFromChild(child_id
, list
);
2191 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2192 resource_ids_to_transfer
);
2196 ResourceProvider::ResourceIdMap resource_map
=
2197 resource_provider_
->GetChildToParentMap(child_id
);
2198 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2199 EXPECT_NE(0u, parent_resource
);
2201 // Transfer to a grandparent.
2202 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2203 resource_ids_to_transfer
.push_back(parent_resource
);
2204 TransferableResourceArray list
;
2205 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2207 // Receive back a lost resource from the grandparent.
2208 EXPECT_EQ(1u, list
.size());
2209 EXPECT_EQ(parent_resource
, list
[0].id
);
2210 ReturnedResourceArray returned
;
2211 TransferableResource::ReturnResources(list
, &returned
);
2212 EXPECT_EQ(1u, returned
.size());
2213 EXPECT_EQ(parent_resource
, returned
[0].id
);
2214 returned
[0].lost
= true;
2215 resource_provider_
->ReceiveReturnsFromParent(returned
);
2219 EXPECT_EQ(0u, returned_to_child
.size());
2221 // Transfer resources back from the parent to the child. Set no resources as
2223 ResourceProvider::ResourceIdArray no_resources
;
2224 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2226 // Expect the resource to be lost.
2227 ASSERT_EQ(1u, returned_to_child
.size());
2228 EXPECT_TRUE(returned_to_child
[0].lost
);
2229 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2230 returned_to_child
.clear();
2233 // Delete the resource in the child. Expect the resource to be lost.
2234 child_resource_provider_
->DeleteResource(resource
);
2235 EXPECT_TRUE(lost_resource
);
2238 TEST_P(ResourceProviderTest
, Shutdown
) {
2239 uint32 release_sync_point
= 0;
2240 bool lost_resource
= false;
2241 bool release_called
= false;
2242 uint32 sync_point
= 0;
2244 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2246 EXPECT_EQ(0u, release_sync_point
);
2247 EXPECT_FALSE(lost_resource
);
2249 child_resource_provider_
.reset();
2251 if (GetParam() == ResourceProvider::GLTexture
) {
2252 EXPECT_LE(sync_point
, release_sync_point
);
2254 EXPECT_TRUE(release_called
);
2255 EXPECT_FALSE(lost_resource
);
2258 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2259 uint32 release_sync_point
= 0;
2260 bool lost_resource
= false;
2261 bool release_called
= false;
2262 uint32 sync_point
= 0;
2263 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2264 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2266 // Transfer the resource, so we can't release it properly on shutdown.
2267 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2268 resource_ids_to_transfer
.push_back(resource
);
2269 TransferableResourceArray list
;
2270 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2273 EXPECT_EQ(0u, release_sync_point
);
2274 EXPECT_FALSE(lost_resource
);
2276 child_resource_provider_
.reset();
2278 // Since the resource is in the parent, the child considers it lost.
2279 EXPECT_EQ(0u, release_sync_point
);
2280 EXPECT_TRUE(lost_resource
);
2283 TEST_P(ResourceProviderTest
, LostContext
) {
2284 // TextureMailbox callbacks only exist for GL textures for now.
2285 if (GetParam() != ResourceProvider::GLTexture
)
2287 unsigned texture
= context()->createTexture();
2288 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2289 gpu::Mailbox mailbox
;
2290 context()->genMailboxCHROMIUM(mailbox
.name
);
2291 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2292 uint32 sync_point
= context()->insertSyncPoint();
2294 EXPECT_LT(0u, sync_point
);
2296 uint32 release_sync_point
= 0;
2297 bool lost_resource
= false;
2298 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2299 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2300 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback
,
2301 &release_sync_point
,
2303 &main_thread_task_runner
));
2304 resource_provider_
->CreateResourceFromTextureMailbox(
2305 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2307 EXPECT_EQ(0u, release_sync_point
);
2308 EXPECT_FALSE(lost_resource
);
2309 EXPECT_EQ(NULL
, main_thread_task_runner
);
2311 resource_provider_
->DidLoseOutputSurface();
2312 resource_provider_
.reset();
2314 EXPECT_LE(sync_point
, release_sync_point
);
2315 EXPECT_TRUE(lost_resource
);
2316 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2319 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2320 // Sampling is only supported for GL textures.
2321 if (GetParam() != ResourceProvider::GLTexture
)
2324 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2325 new TextureStateTrackingContext
);
2326 TextureStateTrackingContext
* context
= context_owned
.get();
2328 FakeOutputSurfaceClient output_surface_client
;
2329 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2330 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2331 CHECK(output_surface
->BindToClient(&output_surface_client
));
2333 scoped_ptr
<ResourceProvider
> resource_provider(
2334 ResourceProvider::Create(output_surface
.get(),
2335 shared_bitmap_manager_
.get(),
2342 gfx::Size
size(1, 1);
2343 ResourceFormat format
= RGBA_8888
;
2346 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2347 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
2349 // Check that the texture gets created with the right sampler settings.
2350 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2351 .Times(2); // Once to create and once to allocate.
2352 EXPECT_CALL(*context
,
2353 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2354 EXPECT_CALL(*context
,
2355 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2358 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2361 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2362 EXPECT_CALL(*context
,
2363 texParameteri(GL_TEXTURE_2D
,
2364 GL_TEXTURE_POOL_CHROMIUM
,
2365 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2367 resource_provider
->AllocateForTesting(id
);
2368 Mock::VerifyAndClearExpectations(context
);
2370 // Creating a sampler with the default filter should not change any texture
2373 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2374 ResourceProvider::ScopedSamplerGL
sampler(
2375 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2376 Mock::VerifyAndClearExpectations(context
);
2379 // Using a different filter should be reflected in the texture parameters.
2381 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2384 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2387 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2388 ResourceProvider::ScopedSamplerGL
sampler(
2389 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2390 Mock::VerifyAndClearExpectations(context
);
2393 // Test resetting to the default filter.
2395 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2396 EXPECT_CALL(*context
,
2397 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2398 EXPECT_CALL(*context
,
2399 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2400 ResourceProvider::ScopedSamplerGL
sampler(
2401 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2402 Mock::VerifyAndClearExpectations(context
);
2406 TEST_P(ResourceProviderTest
, ManagedResource
) {
2407 // Sampling is only supported for GL textures.
2408 if (GetParam() != ResourceProvider::GLTexture
)
2411 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2412 new TextureStateTrackingContext
);
2413 TextureStateTrackingContext
* context
= context_owned
.get();
2415 FakeOutputSurfaceClient output_surface_client
;
2416 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2417 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2418 CHECK(output_surface
->BindToClient(&output_surface_client
));
2420 scoped_ptr
<ResourceProvider
> resource_provider(
2421 ResourceProvider::Create(output_surface
.get(),
2422 shared_bitmap_manager_
.get(),
2429 gfx::Size
size(1, 1);
2430 ResourceFormat format
= RGBA_8888
;
2433 // Check that the texture gets created with the right sampler settings.
2434 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2438 ResourceProvider::TextureHintImmutable
,
2440 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2441 EXPECT_CALL(*context
,
2442 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2443 EXPECT_CALL(*context
,
2444 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2447 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2450 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2451 EXPECT_CALL(*context
,
2452 texParameteri(GL_TEXTURE_2D
,
2453 GL_TEXTURE_POOL_CHROMIUM
,
2454 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2455 resource_provider
->CreateForTesting(id
);
2458 Mock::VerifyAndClearExpectations(context
);
2461 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2462 // Sampling is only supported for GL textures.
2463 if (GetParam() != ResourceProvider::GLTexture
)
2466 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2467 new TextureStateTrackingContext
);
2468 TextureStateTrackingContext
* context
= context_owned
.get();
2470 FakeOutputSurfaceClient output_surface_client
;
2471 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2472 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2473 CHECK(output_surface
->BindToClient(&output_surface_client
));
2475 scoped_ptr
<ResourceProvider
> resource_provider(
2476 ResourceProvider::Create(output_surface
.get(),
2477 shared_bitmap_manager_
.get(),
2484 gfx::Size
size(1, 1);
2485 ResourceFormat format
= RGBA_8888
;
2486 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2488 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2489 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2490 // Check that the texture gets created with the right sampler settings.
2491 ResourceProvider::ResourceId id
= resource_provider
->CreateGLTexture(
2496 ResourceProvider::TextureHintImmutable
,
2498 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2499 EXPECT_CALL(*context
,
2500 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2501 EXPECT_CALL(*context
,
2502 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2503 EXPECT_CALL(*context
,
2504 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2505 EXPECT_CALL(*context
,
2506 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2507 EXPECT_CALL(*context
,
2508 texParameteri(GL_TEXTURE_2D
,
2509 GL_TEXTURE_POOL_CHROMIUM
,
2510 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2511 resource_provider
->CreateForTesting(id
);
2514 Mock::VerifyAndClearExpectations(context
);
2518 TEST_P(ResourceProviderTest
, TextureHint
) {
2519 // Sampling is only supported for GL textures.
2520 if (GetParam() != ResourceProvider::GLTexture
)
2523 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2524 new TextureStateTrackingContext
);
2525 TextureStateTrackingContext
* context
= context_owned
.get();
2526 context
->set_support_texture_storage(true);
2527 context
->set_support_texture_usage(true);
2529 FakeOutputSurfaceClient output_surface_client
;
2530 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2531 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2532 CHECK(output_surface
->BindToClient(&output_surface_client
));
2534 scoped_ptr
<ResourceProvider
> resource_provider(
2535 ResourceProvider::Create(output_surface
.get(),
2536 shared_bitmap_manager_
.get(),
2543 gfx::Size
size(1, 1);
2544 ResourceFormat format
= RGBA_8888
;
2545 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2547 const ResourceProvider::TextureHint hints
[4] = {
2548 ResourceProvider::TextureHintDefault
,
2549 ResourceProvider::TextureHintImmutable
,
2550 ResourceProvider::TextureHintFramebuffer
,
2551 ResourceProvider::TextureHintImmutableFramebuffer
,
2553 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
2554 // Check that the texture gets created with the right sampler settings.
2555 ResourceProvider::ResourceId id
=
2556 resource_provider
->CreateGLTexture(size
,
2560 hints
[texture_id
- 1],
2562 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2563 EXPECT_CALL(*context
,
2564 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2565 EXPECT_CALL(*context
,
2566 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2569 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2572 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2573 EXPECT_CALL(*context
,
2574 texParameteri(GL_TEXTURE_2D
,
2575 GL_TEXTURE_POOL_CHROMIUM
,
2576 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2577 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2578 bool is_framebuffer_hint
=
2579 hints
[texture_id
- 1] & ResourceProvider::TextureHintFramebuffer
;
2580 EXPECT_CALL(*context
,
2581 texParameteri(GL_TEXTURE_2D
,
2582 GL_TEXTURE_USAGE_ANGLE
,
2583 GL_FRAMEBUFFER_ATTACHMENT_ANGLE
))
2584 .Times(is_framebuffer_hint
? 1 : 0);
2585 resource_provider
->CreateForTesting(id
);
2588 Mock::VerifyAndClearExpectations(context
);
2592 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2593 if (GetParam() != ResourceProvider::Bitmap
)
2596 gfx::Size
size(64, 64);
2597 const uint32_t kBadBeef
= 0xbadbeef;
2598 scoped_ptr
<base::SharedMemory
> shared_memory(
2599 CreateAndFillSharedMemory(size
, kBadBeef
));
2601 FakeOutputSurfaceClient output_surface_client
;
2602 scoped_ptr
<OutputSurface
> output_surface(
2603 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2604 new SoftwareOutputDevice
)));
2605 CHECK(output_surface
->BindToClient(&output_surface_client
));
2607 scoped_ptr
<ResourceProvider
> resource_provider(
2608 ResourceProvider::Create(output_surface
.get(),
2609 shared_bitmap_manager_
.get(),
2610 main_thread_task_runner_
.get(),
2616 uint32 release_sync_point
= 0;
2617 bool lost_resource
= false;
2618 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2619 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2620 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2621 &release_sync_point
,
2623 &main_thread_task_runner
));
2624 TextureMailbox
mailbox(shared_memory
.get(), size
);
2626 ResourceProvider::ResourceId id
=
2627 resource_provider
->CreateResourceFromTextureMailbox(
2628 mailbox
, callback
.Pass());
2632 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2633 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2634 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2635 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2636 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2639 resource_provider
->DeleteResource(id
);
2640 EXPECT_EQ(0u, release_sync_point
);
2641 EXPECT_FALSE(lost_resource
);
2642 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2645 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D
) {
2646 // Mailboxing is only supported for GL textures.
2647 if (GetParam() != ResourceProvider::GLTexture
)
2650 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2651 new TextureStateTrackingContext
);
2652 TextureStateTrackingContext
* context
= context_owned
.get();
2654 FakeOutputSurfaceClient output_surface_client
;
2655 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2656 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2657 CHECK(output_surface
->BindToClient(&output_surface_client
));
2659 scoped_ptr
<ResourceProvider
> resource_provider(
2660 ResourceProvider::Create(output_surface
.get(),
2661 shared_bitmap_manager_
.get(),
2662 main_thread_task_runner_
.get(),
2668 unsigned texture_id
= 1;
2669 uint32 sync_point
= 30;
2670 unsigned target
= GL_TEXTURE_2D
;
2672 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2673 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2674 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2675 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2676 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2678 gpu::Mailbox gpu_mailbox
;
2679 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2680 uint32 release_sync_point
= 0;
2681 bool lost_resource
= false;
2682 BlockingTaskRunner
* main_thread_task_runner
= NULL
;
2683 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2684 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback
,
2685 &release_sync_point
,
2687 &main_thread_task_runner
));
2689 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2691 ResourceProvider::ResourceId id
=
2692 resource_provider
->CreateResourceFromTextureMailbox(
2693 mailbox
, callback
.Pass());
2696 Mock::VerifyAndClearExpectations(context
);
2699 // Mailbox sync point WaitSyncPoint before using the texture.
2700 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2701 resource_provider
->WaitSyncPointIfNeeded(id
);
2702 Mock::VerifyAndClearExpectations(context
);
2704 // Using the texture does a consume of the mailbox.
2705 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2706 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2708 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2709 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2711 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2712 Mock::VerifyAndClearExpectations(context
);
2714 // When done with it, a sync point should be inserted, but no produce is
2716 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2717 EXPECT_CALL(*context
, insertSyncPoint());
2718 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2720 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2721 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2724 resource_provider
->DeleteResource(id
);
2725 EXPECT_EQ(0u, release_sync_point
);
2726 EXPECT_FALSE(lost_resource
);
2727 EXPECT_EQ(main_thread_task_runner_
.get(), main_thread_task_runner
);
2730 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2731 // Mailboxing is only supported for GL textures.
2732 if (GetParam() != ResourceProvider::GLTexture
)
2735 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2736 new TextureStateTrackingContext
);
2737 TextureStateTrackingContext
* context
= context_owned
.get();
2739 FakeOutputSurfaceClient output_surface_client
;
2740 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2741 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2742 CHECK(output_surface
->BindToClient(&output_surface_client
));
2744 scoped_ptr
<ResourceProvider
> resource_provider(
2745 ResourceProvider::Create(output_surface
.get(),
2746 shared_bitmap_manager_
.get(),
2753 unsigned texture_id
= 1;
2754 uint32 sync_point
= 30;
2755 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2757 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2758 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2759 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2760 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2761 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2763 gpu::Mailbox gpu_mailbox
;
2764 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2765 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2766 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2768 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2770 ResourceProvider::ResourceId id
=
2771 resource_provider
->CreateResourceFromTextureMailbox(
2772 mailbox
, callback
.Pass());
2775 Mock::VerifyAndClearExpectations(context
);
2778 // Mailbox sync point WaitSyncPoint before using the texture.
2779 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2780 resource_provider
->WaitSyncPointIfNeeded(id
);
2781 Mock::VerifyAndClearExpectations(context
);
2783 // Using the texture does a consume of the mailbox.
2784 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2785 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2787 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2788 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2790 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2791 Mock::VerifyAndClearExpectations(context
);
2793 // When done with it, a sync point should be inserted, but no produce is
2795 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2796 EXPECT_CALL(*context
, insertSyncPoint());
2797 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2799 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2800 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2804 TEST_P(ResourceProviderTest
,
2805 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint
) {
2806 // Mailboxing is only supported for GL textures.
2807 if (GetParam() != ResourceProvider::GLTexture
)
2810 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2811 new TextureStateTrackingContext
);
2812 TextureStateTrackingContext
* context
= context_owned
.get();
2814 FakeOutputSurfaceClient output_surface_client
;
2815 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2816 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2817 CHECK(output_surface
->BindToClient(&output_surface_client
));
2819 scoped_ptr
<ResourceProvider
> resource_provider(
2820 ResourceProvider::Create(output_surface
.get(),
2821 shared_bitmap_manager_
.get(),
2828 uint32 sync_point
= 30;
2829 unsigned target
= GL_TEXTURE_2D
;
2831 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2832 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2833 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2834 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2835 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2837 gpu::Mailbox gpu_mailbox
;
2838 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2839 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2840 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2842 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2844 ResourceProvider::ResourceId id
=
2845 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2849 Mock::VerifyAndClearExpectations(context
);
2852 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2853 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2854 resource_provider
->WaitSyncPointIfNeeded(id
);
2855 Mock::VerifyAndClearExpectations(context
);
2857 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2858 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2859 resource_provider
->WaitSyncPointIfNeeded(id
);
2860 Mock::VerifyAndClearExpectations(context
);
2864 TEST_P(ResourceProviderTest
, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint
) {
2865 // Mailboxing is only supported for GL textures.
2866 if (GetParam() != ResourceProvider::GLTexture
)
2869 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2870 new TextureStateTrackingContext
);
2871 TextureStateTrackingContext
* context
= context_owned
.get();
2873 FakeOutputSurfaceClient output_surface_client
;
2874 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2875 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2876 CHECK(output_surface
->BindToClient(&output_surface_client
));
2878 scoped_ptr
<ResourceProvider
> resource_provider(
2879 ResourceProvider::Create(output_surface
.get(),
2880 shared_bitmap_manager_
.get(),
2887 uint32 sync_point
= 0;
2888 unsigned target
= GL_TEXTURE_2D
;
2890 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2891 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2892 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2893 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2894 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2896 gpu::Mailbox gpu_mailbox
;
2897 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2898 scoped_ptr
<SingleReleaseCallbackImpl
> callback
=
2899 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback
));
2901 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2903 ResourceProvider::ResourceId id
=
2904 resource_provider
->CreateResourceFromTextureMailbox(mailbox
,
2908 Mock::VerifyAndClearExpectations(context
);
2911 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2912 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2913 resource_provider
->WaitSyncPointIfNeeded(id
);
2914 Mock::VerifyAndClearExpectations(context
);
2918 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2920 MOCK_METHOD0(NextTextureId
, GLuint());
2921 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2922 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2923 MOCK_METHOD5(texStorage2DEXT
,
2926 GLuint internalformat
,
2929 MOCK_METHOD9(texImage2D
,
2932 GLenum internalformat
,
2938 const void* pixels
));
2939 MOCK_METHOD9(texSubImage2D
,
2948 const void* pixels
));
2949 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2952 GLenum internalformat
,
2958 const void* pixels
));
2959 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2968 const void* pixels
));
2969 MOCK_METHOD8(compressedTexImage2D
,
2972 GLenum internalformat
,
2978 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
2979 MOCK_METHOD4(createImageCHROMIUM
, GLuint(GLsizei
, GLsizei
, GLenum
, GLenum
));
2980 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
2981 MOCK_METHOD1(mapImageCHROMIUM
, void*(GLuint
));
2982 MOCK_METHOD3(getImageParameterivCHROMIUM
, void(GLuint
, GLenum
, GLint
*));
2983 MOCK_METHOD1(unmapImageCHROMIUM
, void(GLuint
));
2984 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2985 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2987 // We're mocking bindTexture, so we override
2988 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2989 // currently bound texture.
2990 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
2993 TEST_P(ResourceProviderTest
, TextureAllocation
) {
2994 // Only for GL textures.
2995 if (GetParam() != ResourceProvider::GLTexture
)
2997 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2998 new StrictMock
<AllocationTrackingContext3D
>);
2999 AllocationTrackingContext3D
* context
= context_owned
.get();
3001 FakeOutputSurfaceClient output_surface_client
;
3002 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3003 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3004 CHECK(output_surface
->BindToClient(&output_surface_client
));
3006 scoped_ptr
<ResourceProvider
> resource_provider(
3007 ResourceProvider::Create(output_surface
.get(),
3008 shared_bitmap_manager_
.get(),
3015 gfx::Size
size(2, 2);
3016 gfx::Vector2d
offset(0, 0);
3017 gfx::Rect
rect(0, 0, 2, 2);
3018 ResourceFormat format
= RGBA_8888
;
3019 ResourceProvider::ResourceId id
= 0;
3020 uint8_t pixels
[16] = { 0 };
3021 int texture_id
= 123;
3023 // Lazy allocation. Don't allocate when creating the resource.
3024 id
= resource_provider
->CreateResource(
3025 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3027 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3028 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3029 resource_provider
->CreateForTesting(id
);
3031 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3032 resource_provider
->DeleteResource(id
);
3034 Mock::VerifyAndClearExpectations(context
);
3036 // Do allocate when we set the pixels.
3037 id
= resource_provider
->CreateResource(
3038 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3040 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3041 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3042 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
3043 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
3044 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
3046 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3047 resource_provider
->DeleteResource(id
);
3049 Mock::VerifyAndClearExpectations(context
);
3051 // Same for async version.
3052 id
= resource_provider
->CreateResource(
3053 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3054 RasterBuffer
* raster_buffer
= resource_provider
->AcquirePixelRasterBuffer(id
);
3055 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3056 raster_buffer
->ReleaseSkCanvas(canvas
);
3059 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3060 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3061 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3063 resource_provider
->BeginSetPixels(id
);
3064 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3066 resource_provider
->ReleasePixelRasterBuffer(id
);
3068 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3069 resource_provider
->DeleteResource(id
);
3071 Mock::VerifyAndClearExpectations(context
);
3074 TEST_P(ResourceProviderTest
, TextureAllocationHint
) {
3075 // Only for GL textures.
3076 if (GetParam() != ResourceProvider::GLTexture
)
3078 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3079 new StrictMock
<AllocationTrackingContext3D
>);
3080 AllocationTrackingContext3D
* context
= context_owned
.get();
3081 context
->set_support_texture_storage(true);
3082 context
->set_support_texture_usage(true);
3084 FakeOutputSurfaceClient output_surface_client
;
3085 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3086 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3087 CHECK(output_surface
->BindToClient(&output_surface_client
));
3089 scoped_ptr
<ResourceProvider
> resource_provider(
3090 ResourceProvider::Create(output_surface
.get(),
3091 shared_bitmap_manager_
.get(),
3098 gfx::Size
size(2, 2);
3100 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3101 const ResourceProvider::TextureHint hints
[4] = {
3102 ResourceProvider::TextureHintDefault
,
3103 ResourceProvider::TextureHintImmutable
,
3104 ResourceProvider::TextureHintFramebuffer
,
3105 ResourceProvider::TextureHintImmutableFramebuffer
,
3107 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3108 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3109 // Lazy allocation. Don't allocate when creating the resource.
3110 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3111 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3113 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3114 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3115 bool is_immutable_hint
=
3116 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3117 bool support_immutable_texture
=
3118 is_immutable_hint
&& formats
[i
] == RGBA_8888
;
3119 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3120 .Times(support_immutable_texture
? 1 : 0);
3121 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3122 .Times(support_immutable_texture
? 0 : 1);
3123 resource_provider
->AllocateForTesting(id
);
3125 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3126 resource_provider
->DeleteResource(id
);
3128 Mock::VerifyAndClearExpectations(context
);
3133 TEST_P(ResourceProviderTest
, TextureAllocationHint_BGRA
) {
3134 // Only for GL textures.
3135 if (GetParam() != ResourceProvider::GLTexture
)
3137 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3138 new StrictMock
<AllocationTrackingContext3D
>);
3139 AllocationTrackingContext3D
* context
= context_owned
.get();
3140 context
->set_support_texture_format_bgra8888(true);
3141 context
->set_support_texture_storage(true);
3142 context
->set_support_texture_usage(true);
3144 FakeOutputSurfaceClient output_surface_client
;
3145 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3146 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3147 CHECK(output_surface
->BindToClient(&output_surface_client
));
3149 scoped_ptr
<ResourceProvider
> resource_provider(
3150 ResourceProvider::Create(output_surface
.get(),
3151 shared_bitmap_manager_
.get(),
3158 gfx::Size
size(2, 2);
3159 const ResourceFormat formats
[2] = {RGBA_8888
, BGRA_8888
};
3161 const ResourceProvider::TextureHint hints
[4] = {
3162 ResourceProvider::TextureHintDefault
,
3163 ResourceProvider::TextureHintImmutable
,
3164 ResourceProvider::TextureHintFramebuffer
,
3165 ResourceProvider::TextureHintImmutableFramebuffer
,
3167 for (size_t i
= 0; i
< arraysize(formats
); ++i
) {
3168 for (GLuint texture_id
= 1; texture_id
<= arraysize(hints
); ++texture_id
) {
3169 // Lazy allocation. Don't allocate when creating the resource.
3170 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3171 size
, GL_CLAMP_TO_EDGE
, hints
[texture_id
- 1], formats
[i
]);
3173 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3174 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3175 bool is_immutable_hint
=
3176 hints
[texture_id
- 1] & ResourceProvider::TextureHintImmutable
;
3177 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2))
3178 .Times(is_immutable_hint
? 1 : 0);
3179 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3180 .Times(is_immutable_hint
? 0 : 1);
3181 resource_provider
->AllocateForTesting(id
);
3183 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3184 resource_provider
->DeleteResource(id
);
3186 Mock::VerifyAndClearExpectations(context
);
3191 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
3192 if (GetParam() != ResourceProvider::GLTexture
)
3194 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3195 new StrictMock
<AllocationTrackingContext3D
>);
3196 AllocationTrackingContext3D
* context
= context_owned
.get();
3198 FakeOutputSurfaceClient output_surface_client
;
3199 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3200 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3201 CHECK(output_surface
->BindToClient(&output_surface_client
));
3203 gfx::Size
size(2, 2);
3204 ResourceFormat format
= RGBA_8888
;
3205 ResourceProvider::ResourceId id
= 0;
3206 int texture_id
= 123;
3208 scoped_ptr
<ResourceProvider
> resource_provider(
3209 ResourceProvider::Create(output_surface
.get(),
3210 shared_bitmap_manager_
.get(),
3217 id
= resource_provider
->CreateResource(
3218 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3219 RasterBuffer
* raster_buffer
= resource_provider
->AcquirePixelRasterBuffer(id
);
3220 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3221 raster_buffer
->ReleaseSkCanvas(canvas
);
3224 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3225 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3226 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3228 resource_provider
->BeginSetPixels(id
);
3230 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
3232 resource_provider
->ReleasePixelRasterBuffer(id
);
3234 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3235 resource_provider
->DeleteResource(id
);
3237 Mock::VerifyAndClearExpectations(context
);
3240 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
3241 // Only for GL textures.
3242 if (GetParam() != ResourceProvider::GLTexture
)
3244 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3245 new StrictMock
<AllocationTrackingContext3D
>);
3246 AllocationTrackingContext3D
* context
= context_owned
.get();
3248 FakeOutputSurfaceClient output_surface_client
;
3249 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3250 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3251 CHECK(output_surface
->BindToClient(&output_surface_client
));
3253 gfx::Size
size(2, 2);
3254 ResourceFormat format
= RGBA_8888
;
3255 ResourceProvider::ResourceId id
= 0;
3256 int texture_id
= 123;
3258 scoped_ptr
<ResourceProvider
> resource_provider(
3259 ResourceProvider::Create(output_surface
.get(),
3260 shared_bitmap_manager_
.get(),
3267 id
= resource_provider
->CreateResource(
3268 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3269 RasterBuffer
* raster_buffer
= resource_provider
->AcquirePixelRasterBuffer(id
);
3270 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3271 raster_buffer
->ReleaseSkCanvas(canvas
);
3274 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3275 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3276 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
3278 resource_provider
->BeginSetPixels(id
);
3280 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
3281 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
3282 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
3283 resource_provider
->ForceSetPixelsToComplete(id
);
3285 resource_provider
->ReleasePixelRasterBuffer(id
);
3287 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3288 resource_provider
->DeleteResource(id
);
3290 Mock::VerifyAndClearExpectations(context
);
3293 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
3294 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3295 new NiceMock
<AllocationTrackingContext3D
>);
3296 AllocationTrackingContext3D
* context
= context_owned
.get();
3298 FakeOutputSurfaceClient output_surface_client
;
3299 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3300 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3301 CHECK(output_surface
->BindToClient(&output_surface_client
));
3303 gfx::Size
size(2, 2);
3304 ResourceFormat format
= RGBA_8888
;
3305 ResourceProvider::ResourceId id
= 0;
3306 int texture_id
= 123;
3308 scoped_ptr
<ResourceProvider
> resource_provider(
3309 ResourceProvider::Create(output_surface
.get(),
3310 shared_bitmap_manager_
.get(),
3317 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
3319 id
= resource_provider
->CreateResource(
3320 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3321 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
3322 GL_INNOCENT_CONTEXT_RESET_ARB
);
3324 RasterBuffer
* raster_buffer
= resource_provider
->AcquirePixelRasterBuffer(id
);
3325 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3326 EXPECT_TRUE(canvas
.get() == NULL
);
3327 raster_buffer
->ReleaseSkCanvas(canvas
);
3329 resource_provider
->ReleasePixelRasterBuffer(id
);
3330 Mock::VerifyAndClearExpectations(context
);
3333 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
3334 // Only for GL textures.
3335 if (GetParam() != ResourceProvider::GLTexture
)
3337 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3338 new StrictMock
<AllocationTrackingContext3D
>);
3339 AllocationTrackingContext3D
* context
= context_owned
.get();
3341 FakeOutputSurfaceClient output_surface_client
;
3342 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3343 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3344 CHECK(output_surface
->BindToClient(&output_surface_client
));
3346 const int kWidth
= 2;
3347 const int kHeight
= 2;
3348 gfx::Size
size(kWidth
, kHeight
);
3349 ResourceFormat format
= RGBA_8888
;
3350 ResourceProvider::ResourceId id
= 0;
3351 const unsigned kTextureId
= 123u;
3352 const unsigned kImageId
= 234u;
3354 scoped_ptr
<ResourceProvider
> resource_provider(
3355 ResourceProvider::Create(output_surface
.get(),
3356 shared_bitmap_manager_
.get(),
3363 id
= resource_provider
->CreateResource(
3364 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3366 const int kStride
= 4;
3367 void* dummy_mapped_buffer_address
= NULL
;
3370 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
3371 .WillOnce(Return(kImageId
))
3372 .RetiresOnSaturation();
3373 EXPECT_CALL(*context
, getImageParameterivCHROMIUM(kImageId
,
3374 GL_IMAGE_ROWBYTES_CHROMIUM
,
3376 .WillOnce(SetArgPointee
<2>(kStride
))
3377 .RetiresOnSaturation();
3378 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3379 .WillOnce(Return(dummy_mapped_buffer_address
))
3380 .RetiresOnSaturation();
3381 resource_provider
->AcquireImageRasterBuffer(id
);
3382 resource_provider
->ReleaseImageRasterBuffer(id
);
3384 EXPECT_CALL(*context
, NextTextureId())
3385 .WillOnce(Return(kTextureId
))
3386 .RetiresOnSaturation();
3387 // Once in CreateTextureId and once in BindForSampling
3388 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
3389 .RetiresOnSaturation();
3390 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3392 .RetiresOnSaturation();
3394 ResourceProvider::ScopedSamplerGL
lock_gl(
3395 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3396 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3401 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
3402 .WillOnce(SetArgPointee
<2>(kStride
))
3403 .RetiresOnSaturation();
3404 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3405 .WillOnce(Return(dummy_mapped_buffer_address
))
3406 .RetiresOnSaturation();
3407 resource_provider
->AcquireImageRasterBuffer(id
);
3408 resource_provider
->ReleaseImageRasterBuffer(id
);
3410 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
3411 .RetiresOnSaturation();
3412 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3414 .RetiresOnSaturation();
3415 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3417 .RetiresOnSaturation();
3418 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
3420 .RetiresOnSaturation();
3422 ResourceProvider::ScopedSamplerGL
lock_gl(
3423 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
3424 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
3427 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3429 .RetiresOnSaturation();
3432 TEST_P(ResourceProviderTest
, Image_Bitmap
) {
3433 if (GetParam() != ResourceProvider::Bitmap
)
3435 FakeOutputSurfaceClient output_surface_client
;
3436 scoped_ptr
<OutputSurface
> output_surface(
3437 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3438 new SoftwareOutputDevice
)));
3439 CHECK(output_surface
->BindToClient(&output_surface_client
));
3441 gfx::Size
size(1, 1);
3442 ResourceFormat format
= RGBA_8888
;
3443 ResourceProvider::ResourceId id
= 0;
3444 const uint32_t kBadBeef
= 0xbadbeef;
3446 scoped_ptr
<ResourceProvider
> resource_provider(
3447 ResourceProvider::Create(output_surface
.get(),
3448 shared_bitmap_manager_
.get(),
3455 id
= resource_provider
->CreateResource(
3456 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3459 bitmap
.allocN32Pixels(size
.width(), size
.height());
3460 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3461 RasterBuffer
* raster_buffer
= resource_provider
->AcquireImageRasterBuffer(id
);
3462 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3463 ASSERT_TRUE(!!canvas
);
3464 canvas
->writePixels(bitmap
, 0, 0);
3465 raster_buffer
->ReleaseSkCanvas(canvas
);
3467 resource_provider
->ReleaseImageRasterBuffer(id
);
3470 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
3471 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3472 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3473 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3474 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3477 resource_provider
->DeleteResource(id
);
3480 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3481 if (GetParam() != ResourceProvider::GLTexture
)
3483 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3484 new StrictMock
<AllocationTrackingContext3D
>);
3485 AllocationTrackingContext3D
* context
= context_owned
.get();
3486 context_owned
->set_support_sync_query(true);
3488 FakeOutputSurfaceClient output_surface_client
;
3489 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3490 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3491 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3493 const int kWidth
= 2;
3494 const int kHeight
= 2;
3495 gfx::Size
size(kWidth
, kHeight
);
3496 ResourceFormat format
= RGBA_8888
;
3497 ResourceProvider::ResourceId source_id
= 0;
3498 ResourceProvider::ResourceId dest_id
= 0;
3499 const unsigned kSourceTextureId
= 123u;
3500 const unsigned kDestTextureId
= 321u;
3501 const unsigned kImageId
= 234u;
3503 scoped_ptr
<ResourceProvider
> resource_provider(
3504 ResourceProvider::Create(output_surface
.get(),
3505 shared_bitmap_manager_
.get(),
3512 source_id
= resource_provider
->CreateResource(
3513 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3515 const int kStride
= 4;
3516 void* dummy_mapped_buffer_address
= NULL
;
3519 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
3520 .WillOnce(Return(kImageId
))
3521 .RetiresOnSaturation();
3524 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
3525 .WillOnce(SetArgPointee
<2>(kStride
))
3526 .RetiresOnSaturation();
3527 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3528 .WillOnce(Return(dummy_mapped_buffer_address
))
3529 .RetiresOnSaturation();
3530 resource_provider
->AcquireImageRasterBuffer(source_id
);
3531 resource_provider
->ReleaseImageRasterBuffer(source_id
);
3532 Mock::VerifyAndClearExpectations(context
);
3534 dest_id
= resource_provider
->CreateResource(
3535 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3537 EXPECT_CALL(*context
, NextTextureId())
3538 .WillOnce(Return(kDestTextureId
))
3539 .RetiresOnSaturation();
3540 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3542 .RetiresOnSaturation();
3543 EXPECT_CALL(*context
, NextTextureId())
3544 .WillOnce(Return(kSourceTextureId
))
3545 .RetiresOnSaturation();
3546 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3548 .RetiresOnSaturation();
3549 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3551 .RetiresOnSaturation();
3552 resource_provider
->CopyResource(source_id
, dest_id
);
3553 Mock::VerifyAndClearExpectations(context
);
3555 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3557 .RetiresOnSaturation();
3558 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3560 .RetiresOnSaturation();
3561 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3563 .RetiresOnSaturation();
3564 resource_provider
->DeleteResource(source_id
);
3565 resource_provider
->DeleteResource(dest_id
);
3568 TEST_P(ResourceProviderTest
, CopyResource_Bitmap
) {
3569 if (GetParam() != ResourceProvider::Bitmap
)
3571 FakeOutputSurfaceClient output_surface_client
;
3572 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::CreateSoftware(
3573 make_scoped_ptr(new SoftwareOutputDevice
)));
3574 CHECK(output_surface
->BindToClient(&output_surface_client
));
3576 gfx::Size
size(1, 1);
3577 ResourceFormat format
= RGBA_8888
;
3578 ResourceProvider::ResourceId source_id
= 0;
3579 ResourceProvider::ResourceId dest_id
= 0;
3580 const uint32_t kBadBeef
= 0xbadbeef;
3582 scoped_ptr
<ResourceProvider
> resource_provider(
3583 ResourceProvider::Create(output_surface
.get(),
3584 shared_bitmap_manager_
.get(),
3591 source_id
= resource_provider
->CreateResource(
3592 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3595 bitmap
.allocN32Pixels(size
.width(), size
.height());
3596 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3597 RasterBuffer
* raster_buffer
=
3598 resource_provider
->AcquireImageRasterBuffer(source_id
);
3599 skia::RefPtr
<SkCanvas
> canvas
= raster_buffer
->AcquireSkCanvas();
3600 ASSERT_TRUE(!!canvas
);
3601 canvas
->writePixels(bitmap
, 0, 0);
3602 raster_buffer
->ReleaseSkCanvas(canvas
);
3604 resource_provider
->ReleaseImageRasterBuffer(source_id
);
3606 dest_id
= resource_provider
->CreateResource(
3607 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3609 resource_provider
->CopyResource(source_id
, dest_id
);
3612 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(),
3614 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3615 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3616 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3617 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3620 resource_provider
->DeleteResource(source_id
);
3621 resource_provider
->DeleteResource(dest_id
);
3624 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3625 ResourceProvider
* resource_provider
,
3626 FakeOutputSurface
* output_surface
) {
3627 scoped_ptr
<ResourceProviderContext
> context_owned
=
3628 ResourceProviderContext::Create(shared_data
);
3629 ResourceProviderContext
* context
= context_owned
.get();
3631 scoped_refptr
<TestContextProvider
> context_provider
=
3632 TestContextProvider::Create(
3633 context_owned
.PassAs
<TestWebGraphicsContext3D
>());
3634 output_surface
->InitializeAndSetContext3d(context_provider
);
3635 resource_provider
->InitializeGL();
3637 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3640 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3641 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3642 bool delegated_rendering
= false;
3643 scoped_ptr
<FakeOutputSurface
> output_surface(
3644 FakeOutputSurface::CreateDeferredGL(
3645 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3646 delegated_rendering
));
3647 FakeOutputSurfaceClient
client(output_surface
.get());
3648 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3649 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3650 new TestSharedBitmapManager());
3651 scoped_ptr
<ResourceProvider
> resource_provider(
3652 ResourceProvider::Create(output_surface
.get(),
3653 shared_bitmap_manager
.get(),
3660 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3662 InitializeGLAndCheck(shared_data
.get(),
3663 resource_provider
.get(),
3664 output_surface
.get());
3666 resource_provider
->InitializeSoftware();
3667 output_surface
->ReleaseGL();
3668 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3670 InitializeGLAndCheck(shared_data
.get(),
3671 resource_provider
.get(),
3672 output_surface
.get());
3675 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3676 if (GetParam() != ResourceProvider::GLTexture
)
3679 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3680 new AllocationTrackingContext3D
);
3681 AllocationTrackingContext3D
* context
= context_owned
.get();
3682 context_owned
->set_support_compressed_texture_etc1(true);
3684 FakeOutputSurfaceClient output_surface_client
;
3685 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3686 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3687 CHECK(output_surface
->BindToClient(&output_surface_client
));
3689 gfx::Size
size(4, 4);
3690 scoped_ptr
<ResourceProvider
> resource_provider(
3691 ResourceProvider::Create(output_surface
.get(),
3692 shared_bitmap_manager_
.get(),
3698 int texture_id
= 123;
3700 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3701 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3703 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3704 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3705 resource_provider
->AllocateForTesting(id
);
3707 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3708 resource_provider
->DeleteResource(id
);
3711 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3712 if (GetParam() != ResourceProvider::GLTexture
)
3715 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3716 new AllocationTrackingContext3D
);
3717 AllocationTrackingContext3D
* context
= context_owned
.get();
3718 context_owned
->set_support_compressed_texture_etc1(true);
3720 FakeOutputSurfaceClient output_surface_client
;
3721 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3722 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3723 CHECK(output_surface
->BindToClient(&output_surface_client
));
3725 gfx::Size
size(4, 4);
3726 scoped_ptr
<ResourceProvider
> resource_provider(
3727 ResourceProvider::Create(output_surface
.get(),
3728 shared_bitmap_manager_
.get(),
3734 int texture_id
= 123;
3737 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3738 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, ETC1
);
3740 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3741 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3742 EXPECT_CALL(*context
,
3743 compressedTexImage2D(
3744 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3745 resource_provider
->SetPixels(
3746 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3748 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3749 resource_provider
->DeleteResource(id
);
3752 INSTANTIATE_TEST_CASE_P(
3753 ResourceProviderTests
,
3754 ResourceProviderTest
,
3755 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3757 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3759 virtual GLuint
NextTextureId() OVERRIDE
{
3760 base::AutoLock
lock(namespace_
->lock
);
3761 return namespace_
->next_texture_id
++;
3763 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
3764 GLuint
PeekTextureId() {
3765 base::AutoLock
lock(namespace_
->lock
);
3766 return namespace_
->next_texture_id
;
3770 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3771 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3772 new TextureIdAllocationTrackingContext
);
3773 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3775 FakeOutputSurfaceClient output_surface_client
;
3776 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3777 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3778 CHECK(output_surface
->BindToClient(&output_surface_client
));
3779 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3780 new TestSharedBitmapManager());
3782 gfx::Size
size(1, 1);
3783 ResourceFormat format
= RGBA_8888
;
3786 size_t kTextureAllocationChunkSize
= 1;
3787 scoped_ptr
<ResourceProvider
> resource_provider(
3788 ResourceProvider::Create(output_surface
.get(),
3789 shared_bitmap_manager
.get(),
3793 kTextureAllocationChunkSize
,
3796 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3797 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3798 resource_provider
->AllocateForTesting(id
);
3799 Mock::VerifyAndClearExpectations(context
);
3801 DCHECK_EQ(2u, context
->PeekTextureId());
3802 resource_provider
->DeleteResource(id
);
3806 size_t kTextureAllocationChunkSize
= 8;
3807 scoped_ptr
<ResourceProvider
> resource_provider(
3808 ResourceProvider::Create(output_surface
.get(),
3809 shared_bitmap_manager
.get(),
3813 kTextureAllocationChunkSize
,
3816 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3817 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureHintImmutable
, format
);
3818 resource_provider
->AllocateForTesting(id
);
3819 Mock::VerifyAndClearExpectations(context
);
3821 DCHECK_EQ(10u, context
->PeekTextureId());
3822 resource_provider
->DeleteResource(id
);