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"
10 #include "base/logging.h"
11 #include "cc/base/scoped_ptr_deque.h"
12 #include "cc/base/scoped_ptr_hash_map.h"
13 #include "cc/output/output_surface.h"
14 #include "cc/test/fake_output_surface.h"
15 #include "cc/test/test_web_graphics_context_3d.h"
16 #include "gpu/GLES2/gl2extchromium.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "third_party/khronos/GLES2/gl2ext.h"
22 #include "ui/gfx/rect.h"
25 using testing::NiceMock
;
26 using testing::Return
;
27 using testing::StrictMock
;
29 using WebKit::WGC3Dbyte
;
30 using WebKit::WGC3Denum
;
31 using WebKit::WGC3Dint
;
32 using WebKit::WGC3Dsizei
;
33 using WebKit::WGC3Duint
;
34 using WebKit::WebGLId
;
39 size_t TextureSize(gfx::Size size
, WGC3Denum format
) {
40 unsigned int components_per_pixel
= 4;
41 unsigned int bytes_per_component
= 1;
42 return size
.width() * size
.height() * components_per_pixel
*
47 Texture() : format(0), filter(GL_NEAREST_MIPMAP_LINEAR
) {}
49 void Reallocate(gfx::Size size
, WGC3Denum format
) {
51 this->format
= format
;
52 this->data
.reset(new uint8_t[TextureSize(size
, format
)]);
58 scoped_array
<uint8_t> data
;
61 // Shared data between multiple ResourceProviderContext. This contains mailbox
62 // contents as well as information about sync points.
63 class ContextSharedData
{
65 static scoped_ptr
<ContextSharedData
> Create() {
66 return make_scoped_ptr(new ContextSharedData());
69 unsigned InsertSyncPoint() { return next_sync_point_
++; }
71 void GenMailbox(WGC3Dbyte
* mailbox
) {
72 memset(mailbox
, 0, sizeof(WGC3Dbyte
[64]));
73 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
77 void ProduceTexture(const WGC3Dbyte
* mailbox_name
,
79 scoped_ptr
<Texture
> texture
) {
81 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
82 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
83 textures_
.set(mailbox
, texture
.Pass());
84 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
85 sync_point_for_mailbox_
[mailbox
] = sync_point
;
88 scoped_ptr
<Texture
> ConsumeTexture(const WGC3Dbyte
* mailbox_name
,
89 unsigned sync_point
) {
91 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
92 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
94 // If the latest sync point the context has waited on is before the sync
95 // point for when the mailbox was set, pretend we never saw that
97 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
99 return scoped_ptr
<Texture
>();
101 return textures_
.take(mailbox
);
105 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
107 unsigned next_sync_point_
;
108 unsigned next_mailbox_
;
109 typedef ScopedPtrHashMap
<unsigned, Texture
> TextureMap
;
110 TextureMap textures_
;
111 base::hash_map
<unsigned, unsigned> sync_point_for_mailbox_
;
114 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
116 static scoped_ptr
<ResourceProviderContext
> Create(
117 ContextSharedData
* shared_data
) {
118 return make_scoped_ptr(
119 new ResourceProviderContext(Attributes(), shared_data
));
122 virtual unsigned insertSyncPoint() OVERRIDE
{
123 unsigned sync_point
= shared_data_
->InsertSyncPoint();
124 // Commit the produceTextureCHROMIUM calls at this point, so that
125 // they're associated with the sync point.
126 for (PendingProduceTextureList::iterator it
=
127 pending_produce_textures_
.begin();
128 it
!= pending_produce_textures_
.end();
130 shared_data_
->ProduceTexture(
131 (*it
)->mailbox
, sync_point
, (*it
)->texture
.Pass());
133 pending_produce_textures_
.clear();
137 virtual void waitSyncPoint(unsigned sync_point
) OVERRIDE
{
138 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
141 virtual void bindTexture(WGC3Denum target
, WebGLId texture
) OVERRIDE
{
142 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
143 ASSERT_TRUE(!texture
|| textures_
.find(texture
) != textures_
.end());
144 current_texture_
= texture
;
147 virtual WebGLId
createTexture() OVERRIDE
{
148 WebGLId id
= TestWebGraphicsContext3D::createTexture();
149 textures_
.add(id
, make_scoped_ptr(new Texture
));
153 virtual void deleteTexture(WebGLId id
) OVERRIDE
{
154 TextureMap::iterator it
= textures_
.find(id
);
155 ASSERT_FALSE(it
== textures_
.end());
157 if (current_texture_
== id
)
158 current_texture_
= 0;
161 virtual void texStorage2DEXT(WGC3Denum target
,
163 WGC3Duint internalformat
,
165 WGC3Dint height
) OVERRIDE
{
166 ASSERT_TRUE(current_texture_
);
167 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
168 ASSERT_EQ(1, levels
);
169 WGC3Denum format
= GL_RGBA
;
170 switch (internalformat
) {
174 format
= GL_BGRA_EXT
;
179 AllocateTexture(gfx::Size(width
, height
), format
);
182 virtual void texImage2D(WGC3Denum target
,
184 WGC3Denum internalformat
,
190 const void* pixels
) OVERRIDE
{
191 ASSERT_TRUE(current_texture_
);
192 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
194 ASSERT_EQ(internalformat
, format
);
195 ASSERT_FALSE(border
);
196 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
197 AllocateTexture(gfx::Size(width
, height
), format
);
199 SetPixels(0, 0, width
, height
, pixels
);
202 virtual void texSubImage2D(WGC3Denum target
,
210 const void* pixels
) OVERRIDE
{
211 ASSERT_TRUE(current_texture_
);
212 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
214 ASSERT_TRUE(textures_
.get(current_texture_
));
215 ASSERT_EQ(textures_
.get(current_texture_
)->format
, format
);
216 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
218 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
221 virtual void texParameteri(WGC3Denum target
, WGC3Denum param
, WGC3Dint value
)
223 ASSERT_TRUE(current_texture_
);
224 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
225 Texture
* texture
= textures_
.get(current_texture_
);
226 ASSERT_TRUE(texture
);
227 if (param
!= GL_TEXTURE_MIN_FILTER
)
229 texture
->filter
= value
;
232 virtual void genMailboxCHROMIUM(WGC3Dbyte
* mailbox
) OVERRIDE
{
233 return shared_data_
->GenMailbox(mailbox
);
236 virtual void produceTextureCHROMIUM(WGC3Denum target
,
237 const WGC3Dbyte
* mailbox
) OVERRIDE
{
238 ASSERT_TRUE(current_texture_
);
239 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
241 // Delay moving the texture into the mailbox until the next
242 // InsertSyncPoint, so that it is not visible to other contexts that
243 // haven't waited on that sync point.
244 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
245 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
246 pending
->texture
= textures_
.take(current_texture_
);
247 textures_
.set(current_texture_
, scoped_ptr
<Texture
>());
248 pending_produce_textures_
.push_back(pending
.Pass());
251 virtual void consumeTextureCHROMIUM(WGC3Denum target
,
252 const WGC3Dbyte
* mailbox
) OVERRIDE
{
253 ASSERT_TRUE(current_texture_
);
254 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
257 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
));
260 void GetPixels(gfx::Size size
, WGC3Denum format
, uint8_t* pixels
) {
261 ASSERT_TRUE(current_texture_
);
262 Texture
* texture
= textures_
.get(current_texture_
);
263 ASSERT_TRUE(texture
);
264 ASSERT_EQ(texture
->size
, size
);
265 ASSERT_EQ(texture
->format
, format
);
266 memcpy(pixels
, texture
->data
.get(), TextureSize(size
, format
));
269 WGC3Denum
GetTextureFilter() {
270 DCHECK(current_texture_
);
271 Texture
* texture
= textures_
.get(current_texture_
);
273 return texture
->filter
;
276 int texture_count() { return textures_
.size(); }
279 ResourceProviderContext(const Attributes
& attrs
,
280 ContextSharedData
* shared_data
)
281 : TestWebGraphicsContext3D(attrs
),
282 shared_data_(shared_data
),
284 last_waited_sync_point_(0) {}
287 void AllocateTexture(gfx::Size size
, WGC3Denum format
) {
288 ASSERT_TRUE(current_texture_
);
289 Texture
* texture
= textures_
.get(current_texture_
);
290 ASSERT_TRUE(texture
);
291 texture
->Reallocate(size
, format
);
294 void SetPixels(int xoffset
,
298 const void* pixels
) {
299 ASSERT_TRUE(current_texture_
);
300 Texture
* texture
= textures_
.get(current_texture_
);
301 ASSERT_TRUE(texture
);
302 ASSERT_TRUE(texture
->data
.get());
303 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
304 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
306 size_t in_pitch
= TextureSize(gfx::Size(width
, 1), texture
->format
);
308 TextureSize(gfx::Size(texture
->size
.width(), 1), texture
->format
);
309 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
310 TextureSize(gfx::Size(xoffset
, 1), texture
->format
);
311 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
312 for (int i
= 0; i
< height
; ++i
) {
313 memcpy(dest
, src
, in_pitch
);
319 typedef ScopedPtrHashMap
<WebGLId
, Texture
> TextureMap
;
320 struct PendingProduceTexture
{
321 WGC3Dbyte mailbox
[64];
322 scoped_ptr
<Texture
> texture
;
324 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
325 ContextSharedData
* shared_data_
;
326 WebGLId current_texture_
;
327 TextureMap textures_
;
328 unsigned last_waited_sync_point_
;
329 PendingProduceTextureList pending_produce_textures_
;
332 class ResourceProviderTest
333 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
335 ResourceProviderTest()
336 : shared_data_(ContextSharedData::Create()),
337 output_surface_(FakeOutputSurface::Create3d(
338 ResourceProviderContext::Create(shared_data_
.get())
339 .PassAs
<WebKit::WebGraphicsContext3D
>())),
340 resource_provider_(ResourceProvider::Create(output_surface_
.get(), 0)) {
341 resource_provider_
->set_default_resource_type(GetParam());
344 ResourceProviderContext
* context() {
345 return static_cast<ResourceProviderContext
*>(output_surface_
->context3d());
348 void GetResourcePixels(ResourceProvider::ResourceId id
,
352 if (GetParam() == ResourceProvider::GLTexture
) {
353 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider_
.get(), id
);
354 ASSERT_NE(0U, lock_gl
.texture_id());
355 context()->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
356 context()->GetPixels(size
, format
, pixels
);
357 } else if (GetParam() == ResourceProvider::Bitmap
) {
358 ResourceProvider::ScopedReadLockSoftware
lock_software(
359 resource_provider_
.get(), id
);
361 lock_software
.sk_bitmap()->getPixels(),
362 lock_software
.sk_bitmap()->getSize());
366 void SetResourceFilter(ResourceProvider
* resource_provider
,
367 ResourceProvider::ResourceId id
,
369 ResourceProvider::ScopedSamplerGL
sampler(
370 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
373 WGC3Denum
GetResourceFilter(ResourceProvider
* resource_provider
,
374 ResourceProvider::ResourceId id
) {
375 DCHECK_EQ(GetParam(), ResourceProvider::GLTexture
);
376 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
377 EXPECT_NE(0u, lock_gl
.texture_id());
378 ResourceProviderContext
* context
= static_cast<ResourceProviderContext
*>(
379 resource_provider
->GraphicsContext3D());
380 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
381 return context
->GetTextureFilter();
384 void ExpectNumResources(int count
) {
385 EXPECT_EQ(count
, static_cast<int>(resource_provider_
->num_resources()));
386 if (GetParam() == ResourceProvider::GLTexture
)
387 EXPECT_EQ(count
, context()->texture_count());
391 scoped_ptr
<ContextSharedData
> shared_data_
;
392 scoped_ptr
<OutputSurface
> output_surface_
;
393 scoped_ptr
<ResourceProvider
> resource_provider_
;
396 TEST_P(ResourceProviderTest
, Basic
) {
397 gfx::Size
size(1, 1);
398 WGC3Denum format
= GL_RGBA
;
399 size_t pixel_size
= TextureSize(size
, format
);
400 ASSERT_EQ(4U, pixel_size
);
402 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
403 size
, format
, ResourceProvider::TextureUsageAny
);
404 ExpectNumResources(1);
406 uint8_t data
[4] = { 1, 2, 3, 4 };
407 gfx::Rect
rect(size
);
408 resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
410 uint8_t result
[4] = { 0 };
411 GetResourcePixels(id
, size
, format
, result
);
412 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
414 resource_provider_
->DeleteResource(id
);
415 ExpectNumResources(0);
418 TEST_P(ResourceProviderTest
, Upload
) {
419 gfx::Size
size(2, 2);
420 WGC3Denum format
= GL_RGBA
;
421 size_t pixel_size
= TextureSize(size
, format
);
422 ASSERT_EQ(16U, pixel_size
);
424 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
425 size
, format
, ResourceProvider::TextureUsageAny
);
427 uint8_t image
[16] = { 0 };
428 gfx::Rect
image_rect(size
);
429 resource_provider_
->SetPixels(
430 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
432 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
435 uint8_t result
[16] = { 0 };
437 gfx::Rect
source_rect(0, 0, 1, 1);
438 gfx::Vector2d
dest_offset(0, 0);
439 resource_provider_
->SetPixels(
440 id
, image
, image_rect
, source_rect
, dest_offset
);
442 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
443 GetResourcePixels(id
, size
, format
, result
);
444 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
447 gfx::Rect
source_rect(0, 0, 1, 1);
448 gfx::Vector2d
dest_offset(1, 1);
449 resource_provider_
->SetPixels(
450 id
, image
, image_rect
, source_rect
, dest_offset
);
452 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
453 GetResourcePixels(id
, size
, format
, result
);
454 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
457 gfx::Rect
source_rect(1, 0, 1, 1);
458 gfx::Vector2d
dest_offset(0, 1);
459 resource_provider_
->SetPixels(
460 id
, image
, image_rect
, source_rect
, dest_offset
);
462 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
463 GetResourcePixels(id
, size
, format
, result
);
464 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
467 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
468 gfx::Rect
source_rect(100, 100, 1, 1);
469 gfx::Vector2d
dest_offset(1, 0);
470 resource_provider_
->SetPixels(
471 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
473 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
474 GetResourcePixels(id
, size
, format
, result
);
475 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
478 resource_provider_
->DeleteResource(id
);
481 TEST_P(ResourceProviderTest
, TransferResources
) {
482 // Resource transfer is only supported with GL textures for now.
483 if (GetParam() != ResourceProvider::GLTexture
)
486 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
487 ResourceProviderContext::Create(shared_data_
.get())
488 .PassAs
<WebKit::WebGraphicsContext3D
>()));
489 scoped_ptr
<ResourceProvider
> child_resource_provider(
490 ResourceProvider::Create(child_output_surface
.get(), 0));
492 gfx::Size
size(1, 1);
493 WGC3Denum format
= GL_RGBA
;
494 size_t pixel_size
= TextureSize(size
, format
);
495 ASSERT_EQ(4U, pixel_size
);
497 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
498 size
, format
, ResourceProvider::TextureUsageAny
);
499 uint8_t data1
[4] = { 1, 2, 3, 4 };
500 gfx::Rect
rect(size
);
501 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
503 ResourceProvider::ResourceId id2
= child_resource_provider
->CreateResource(
504 size
, format
, ResourceProvider::TextureUsageAny
);
505 uint8_t data2
[4] = { 5, 5, 5, 5 };
506 child_resource_provider
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
508 int child_id
= resource_provider_
->CreateChild();
510 // Transfer some resources to the parent.
511 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
512 resource_ids_to_transfer
.push_back(id1
);
513 resource_ids_to_transfer
.push_back(id2
);
514 TransferableResourceArray list
;
515 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
517 ASSERT_EQ(2u, list
.size());
518 EXPECT_NE(0u, list
[0].sync_point
);
519 EXPECT_NE(0u, list
[1].sync_point
);
520 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
521 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id2
));
522 resource_provider_
->ReceiveFromChild(child_id
, list
);
525 EXPECT_EQ(2u, resource_provider_
->num_resources());
526 ResourceProvider::ResourceIdMap resource_map
=
527 resource_provider_
->GetChildToParentMap(child_id
);
528 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
529 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
530 EXPECT_NE(0u, mapped_id1
);
531 EXPECT_NE(0u, mapped_id2
);
532 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
533 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
535 uint8_t result
[4] = { 0 };
536 GetResourcePixels(mapped_id1
, size
, format
, result
);
537 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
539 GetResourcePixels(mapped_id2
, size
, format
, result
);
540 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
542 // Check that transfering again the same resource from the child to the
544 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
545 resource_ids_to_transfer
.push_back(id1
);
546 TransferableResourceArray list
;
547 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
549 EXPECT_EQ(0u, list
.size());
552 // Transfer resources back from the parent to the child.
553 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
554 resource_ids_to_transfer
.push_back(mapped_id1
);
555 resource_ids_to_transfer
.push_back(mapped_id2
);
556 TransferableResourceArray list
;
557 resource_provider_
->PrepareSendToChild(
558 child_id
, resource_ids_to_transfer
, &list
);
559 ASSERT_EQ(2u, list
.size());
560 EXPECT_NE(0u, list
[0].sync_point
);
561 EXPECT_NE(0u, list
[1].sync_point
);
562 child_resource_provider
->ReceiveFromParent(list
);
564 EXPECT_FALSE(child_resource_provider
->InUseByConsumer(id1
));
565 EXPECT_FALSE(child_resource_provider
->InUseByConsumer(id2
));
567 ResourceProviderContext
* child_context
=
568 static_cast<ResourceProviderContext
*>(child_output_surface
->context3d());
570 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider
.get(), id1
);
571 ASSERT_NE(0U, lock
.texture_id());
572 child_context
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
573 child_context
->GetPixels(size
, format
, result
);
574 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
577 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider
.get(), id2
);
578 ASSERT_NE(0U, lock
.texture_id());
579 child_context
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
580 child_context
->GetPixels(size
, format
, result
);
581 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
584 // Transfer resources to the parent again.
585 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
586 resource_ids_to_transfer
.push_back(id1
);
587 resource_ids_to_transfer
.push_back(id2
);
588 TransferableResourceArray list
;
589 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
591 ASSERT_EQ(2u, list
.size());
592 EXPECT_NE(0u, list
[0].sync_point
);
593 EXPECT_NE(0u, list
[1].sync_point
);
594 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
595 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id2
));
596 resource_provider_
->ReceiveFromChild(child_id
, list
);
599 EXPECT_EQ(2u, resource_provider_
->num_resources());
600 resource_provider_
->DestroyChild(child_id
);
601 EXPECT_EQ(0u, resource_provider_
->num_resources());
604 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
605 // Resource transfer is only supported with GL textures for now.
606 if (GetParam() != ResourceProvider::GLTexture
)
609 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
610 ResourceProviderContext::Create(shared_data_
.get())
611 .PassAs
<WebKit::WebGraphicsContext3D
>()));
612 scoped_ptr
<ResourceProvider
> child_resource_provider(
613 ResourceProvider::Create(child_output_surface
.get(), 0));
615 gfx::Size
size(1, 1);
616 WGC3Denum format
= GL_RGBA
;
617 size_t pixel_size
= TextureSize(size
, format
);
618 ASSERT_EQ(4U, pixel_size
);
620 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
621 size
, format
, ResourceProvider::TextureUsageAny
);
622 uint8_t data
[4] = { 1, 2, 3, 4 };
623 gfx::Rect
rect(size
);
624 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
626 int child_id
= resource_provider_
->CreateChild();
628 // Transfer some resource to the parent.
629 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
630 resource_ids_to_transfer
.push_back(id
);
631 TransferableResourceArray list
;
632 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
634 ASSERT_EQ(1u, list
.size());
635 EXPECT_NE(0u, list
[0].sync_point
);
636 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id
));
637 resource_provider_
->ReceiveFromChild(child_id
, list
);
640 // Delete textures in the child, while they are transfered.
641 child_resource_provider
->DeleteResource(id
);
642 EXPECT_EQ(1u, child_resource_provider
->num_resources());
644 // Transfer resources back from the parent to the child.
645 ResourceProvider::ResourceIdMap resource_map
=
646 resource_provider_
->GetChildToParentMap(child_id
);
647 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
648 EXPECT_NE(0u, mapped_id
);
649 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
650 resource_ids_to_transfer
.push_back(mapped_id
);
651 TransferableResourceArray list
;
652 resource_provider_
->PrepareSendToChild(
653 child_id
, resource_ids_to_transfer
, &list
);
654 ASSERT_EQ(1u, list
.size());
655 EXPECT_NE(0u, list
[0].sync_point
);
656 child_resource_provider
->ReceiveFromParent(list
);
658 EXPECT_EQ(0u, child_resource_provider
->num_resources());
661 TEST_P(ResourceProviderTest
, TextureFilters
) {
662 // Resource transfer is only supported with GL textures for now.
663 if (GetParam() != ResourceProvider::GLTexture
)
666 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
667 ResourceProviderContext::Create(shared_data_
.get())
668 .PassAs
<WebKit::WebGraphicsContext3D
>()));
669 scoped_ptr
<ResourceProvider
> child_resource_provider(
670 ResourceProvider::Create(child_output_surface
.get(), 0));
672 gfx::Size
size(1, 1);
673 WGC3Denum format
= GL_RGBA
;
674 size_t pixel_size
= TextureSize(size
, format
);
675 ASSERT_EQ(4U, pixel_size
);
677 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
678 size
, format
, ResourceProvider::TextureUsageAny
);
679 uint8_t data
[4] = { 1, 2, 3, 4 };
680 gfx::Rect
rect(size
);
681 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
682 EXPECT_EQ(static_cast<unsigned>(GL_LINEAR
),
683 GetResourceFilter(child_resource_provider
.get(), id
));
684 SetResourceFilter(child_resource_provider
.get(), id
, GL_NEAREST
);
685 EXPECT_EQ(static_cast<unsigned>(GL_NEAREST
),
686 GetResourceFilter(child_resource_provider
.get(), id
));
688 int child_id
= resource_provider_
->CreateChild();
690 // Transfer some resource to the parent.
691 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
692 resource_ids_to_transfer
.push_back(id
);
693 TransferableResourceArray list
;
694 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
696 ASSERT_EQ(1u, list
.size());
697 EXPECT_EQ(static_cast<unsigned>(GL_NEAREST
), list
[0].filter
);
698 resource_provider_
->ReceiveFromChild(child_id
, list
);
700 ResourceProvider::ResourceIdMap resource_map
=
701 resource_provider_
->GetChildToParentMap(child_id
);
702 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
703 EXPECT_NE(0u, mapped_id
);
704 EXPECT_EQ(static_cast<unsigned>(GL_NEAREST
),
705 GetResourceFilter(resource_provider_
.get(), mapped_id
));
706 SetResourceFilter(resource_provider_
.get(), mapped_id
, GL_LINEAR
);
707 EXPECT_EQ(static_cast<unsigned>(GL_LINEAR
),
708 GetResourceFilter(resource_provider_
.get(), mapped_id
));
710 // Transfer resources back from the parent to the child.
711 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
712 resource_ids_to_transfer
.push_back(mapped_id
);
713 TransferableResourceArray list
;
714 resource_provider_
->PrepareSendToChild(
715 child_id
, resource_ids_to_transfer
, &list
);
716 ASSERT_EQ(1u, list
.size());
717 EXPECT_EQ(static_cast<unsigned>(GL_LINEAR
), list
[0].filter
);
718 child_resource_provider
->ReceiveFromParent(list
);
720 EXPECT_EQ(static_cast<unsigned>(GL_LINEAR
),
721 GetResourceFilter(child_resource_provider
.get(), id
));
722 SetResourceFilter(child_resource_provider
.get(), id
, GL_NEAREST
);
723 EXPECT_EQ(static_cast<unsigned>(GL_NEAREST
),
724 GetResourceFilter(child_resource_provider
.get(), id
));
727 void ReleaseTextureMailbox(unsigned* release_sync_point
, unsigned sync_point
) {
728 *release_sync_point
= sync_point
;
731 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
732 // Resource transfer is only supported with GL textures for now.
733 if (GetParam() != ResourceProvider::GLTexture
)
735 unsigned texture
= context()->createTexture();
736 context()->bindTexture(GL_TEXTURE_2D
, texture
);
737 uint8_t data
[4] = { 1, 2, 3, 4 };
738 context()->texImage2D(
739 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
740 gpu::Mailbox mailbox
;
741 context()->genMailboxCHROMIUM(mailbox
.name
);
742 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
743 unsigned sync_point
= context()->insertSyncPoint();
745 // All the logic below assumes that the sync points are all positive.
746 EXPECT_LT(0u, sync_point
);
748 unsigned release_sync_point
= 0;
749 TextureMailbox::ReleaseCallback callback
=
750 base::Bind(ReleaseTextureMailbox
, &release_sync_point
);
751 ResourceProvider::ResourceId resource
=
752 resource_provider_
->CreateResourceFromTextureMailbox(
753 TextureMailbox(mailbox
, callback
, sync_point
));
754 EXPECT_EQ(1, context()->texture_count());
755 EXPECT_EQ(0u, release_sync_point
);
757 // Transfer the resource, expect the sync points to be consistent.
758 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
759 resource_ids_to_transfer
.push_back(resource
);
760 TransferableResourceArray list
;
761 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
762 ASSERT_EQ(1u, list
.size());
763 EXPECT_LE(sync_point
, list
[0].sync_point
);
765 memcmp(mailbox
.name
, list
[0].mailbox
.name
, sizeof(mailbox
.name
)));
766 EXPECT_EQ(0u, release_sync_point
);
768 context()->waitSyncPoint(list
[0].sync_point
);
769 unsigned other_texture
= context()->createTexture();
770 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
771 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
772 uint8_t test_data
[4] = { 0 };
773 context()->GetPixels(gfx::Size(1, 1), GL_RGBA
, test_data
);
774 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
775 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
776 context()->deleteTexture(other_texture
);
777 list
[0].sync_point
= context()->insertSyncPoint();
778 EXPECT_LT(0u, list
[0].sync_point
);
780 // Receive the resource, then delete it, expect the sync points to be
782 resource_provider_
->ReceiveFromParent(list
);
783 EXPECT_EQ(1, context()->texture_count());
784 EXPECT_EQ(0u, release_sync_point
);
786 resource_provider_
->DeleteResource(resource
);
787 EXPECT_LE(list
[0].sync_point
, release_sync_point
);
790 // We're going to do the same thing as above, but testing the case where we
791 // delete the resource before we receive it back.
792 sync_point
= release_sync_point
;
793 EXPECT_LT(0u, sync_point
);
794 release_sync_point
= 0;
795 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
796 TextureMailbox(mailbox
, callback
, sync_point
));
797 EXPECT_EQ(1, context()->texture_count());
798 EXPECT_EQ(0u, release_sync_point
);
800 // Transfer the resource, expect the sync points to be consistent.
801 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
802 resource_ids_to_transfer
.push_back(resource
);
803 TransferableResourceArray list
;
804 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
805 ASSERT_EQ(1u, list
.size());
806 EXPECT_LE(sync_point
, list
[0].sync_point
);
808 memcmp(mailbox
.name
, list
[0].mailbox
.name
, sizeof(mailbox
.name
)));
809 EXPECT_EQ(0u, release_sync_point
);
811 context()->waitSyncPoint(list
[0].sync_point
);
812 unsigned other_texture
= context()->createTexture();
813 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
814 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
815 uint8_t test_data
[4] = { 0 };
816 context()->GetPixels(gfx::Size(1, 1), GL_RGBA
, test_data
);
817 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
818 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
819 context()->deleteTexture(other_texture
);
820 list
[0].sync_point
= context()->insertSyncPoint();
821 EXPECT_LT(0u, list
[0].sync_point
);
823 // Delete the resource, which shouldn't do anything.
824 resource_provider_
->DeleteResource(resource
);
825 EXPECT_EQ(1, context()->texture_count());
826 EXPECT_EQ(0u, release_sync_point
);
828 // Then receive the resource which should release the mailbox, expect the
829 // sync points to be consistent.
830 resource_provider_
->ReceiveFromParent(list
);
831 EXPECT_LE(list
[0].sync_point
, release_sync_point
);
834 context()->waitSyncPoint(release_sync_point
);
835 context()->bindTexture(GL_TEXTURE_2D
, texture
);
836 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
837 context()->deleteTexture(texture
);
840 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
842 MOCK_METHOD2(bindTexture
, void(WGC3Denum target
, WebGLId texture
));
843 MOCK_METHOD3(texParameteri
,
844 void(WGC3Denum target
, WGC3Denum pname
, WGC3Dint param
));
846 // Force all textures to be "1" so we can test for them.
847 virtual WebKit::WebGLId
NextTextureId() OVERRIDE
{ return 1; }
850 TEST_P(ResourceProviderTest
, ScopedSampler
) {
851 // Sampling is only supported for GL textures.
852 if (GetParam() != ResourceProvider::GLTexture
)
855 scoped_ptr
<OutputSurface
> output_surface(
856 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
857 new TextureStateTrackingContext
)));
858 TextureStateTrackingContext
* context
=
859 static_cast<TextureStateTrackingContext
*>(output_surface
->context3d());
860 scoped_ptr
<ResourceProvider
> resource_provider(
861 ResourceProvider::Create(output_surface
.get(), 0));
863 gfx::Size
size(1, 1);
864 WGC3Denum format
= GL_RGBA
;
867 // Check that the texture gets created with the right sampler settings.
868 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
869 .Times(2); // Once to create and once to allocate.
870 EXPECT_CALL(*context
,
871 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
872 EXPECT_CALL(*context
,
873 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
876 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
879 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
880 EXPECT_CALL(*context
,
881 texParameteri(GL_TEXTURE_2D
,
882 GL_TEXTURE_POOL_CHROMIUM
,
883 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
884 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
885 size
, format
, ResourceProvider::TextureUsageAny
);
886 resource_provider
->AllocateForTesting(id
);
888 // Creating a sampler with the default filter should not change any texture
891 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
892 ResourceProvider::ScopedSamplerGL
sampler(
893 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
896 // Using a different filter should be reflected in the texture parameters.
898 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
901 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
904 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
905 ResourceProvider::ScopedSamplerGL
sampler(
906 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
909 // Test resetting to the default filter.
911 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
912 EXPECT_CALL(*context
,
913 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
914 EXPECT_CALL(*context
,
915 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
916 ResourceProvider::ScopedSamplerGL
sampler(
917 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
920 Mock::VerifyAndClearExpectations(context
);
923 TEST_P(ResourceProviderTest
, ManagedResource
) {
924 // Sampling is only supported for GL textures.
925 if (GetParam() != ResourceProvider::GLTexture
)
928 scoped_ptr
<OutputSurface
> output_surface(
929 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
930 new TextureStateTrackingContext
)));
931 TextureStateTrackingContext
* context
=
932 static_cast<TextureStateTrackingContext
*>(output_surface
->context3d());
933 scoped_ptr
<ResourceProvider
> resource_provider(
934 ResourceProvider::Create(output_surface
.get(), 0));
936 gfx::Size
size(1, 1);
937 WGC3Denum format
= GL_RGBA
;
940 // Check that the texture gets created with the right sampler settings.
941 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
942 EXPECT_CALL(*context
,
943 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
944 EXPECT_CALL(*context
,
945 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
948 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
951 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
952 EXPECT_CALL(*context
,
953 texParameteri(GL_TEXTURE_2D
,
954 GL_TEXTURE_POOL_CHROMIUM
,
955 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
956 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
957 size
, format
, ResourceProvider::TextureUsageAny
);
960 Mock::VerifyAndClearExpectations(context
);
963 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
965 MOCK_METHOD0(createTexture
, WebGLId());
966 MOCK_METHOD1(deleteTexture
, void(WebGLId texture_id
));
967 MOCK_METHOD2(bindTexture
, void(WGC3Denum target
, WebGLId texture
));
968 MOCK_METHOD9(texImage2D
,
969 void(WGC3Denum target
,
971 WGC3Denum internalformat
,
977 const void* pixels
));
978 MOCK_METHOD9(texSubImage2D
,
979 void(WGC3Denum target
,
987 const void* pixels
));
988 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
989 void(WGC3Denum target
,
991 WGC3Denum internalformat
,
997 const void* pixels
));
998 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
999 void(WGC3Denum target
,
1007 const void* pixels
));
1008 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(WGC3Denum target
));
1011 TEST_P(ResourceProviderTest
, TextureAllocation
) {
1012 // Only for GL textures.
1013 if (GetParam() != ResourceProvider::GLTexture
)
1015 scoped_ptr
<WebKit::WebGraphicsContext3D
> mock_context(
1016 static_cast<WebKit::WebGraphicsContext3D
*>(
1017 new NiceMock
<AllocationTrackingContext3D
>));
1018 scoped_ptr
<OutputSurface
> output_surface(
1019 FakeOutputSurface::Create3d(mock_context
.Pass()));
1021 gfx::Size
size(2, 2);
1022 gfx::Vector2d
offset(0, 0);
1023 gfx::Rect
rect(0, 0, 2, 2);
1024 WGC3Denum format
= GL_RGBA
;
1025 ResourceProvider::ResourceId id
= 0;
1026 uint8_t pixels
[16] = { 0 };
1027 int texture_id
= 123;
1029 AllocationTrackingContext3D
* context
=
1030 static_cast<AllocationTrackingContext3D
*>(output_surface
->context3d());
1031 scoped_ptr
<ResourceProvider
> resource_provider(
1032 ResourceProvider::Create(output_surface
.get(), 0));
1034 // Lazy allocation. Don't allocate when creating the resource.
1035 EXPECT_CALL(*context
, createTexture()).WillOnce(Return(texture_id
));
1036 EXPECT_CALL(*context
, deleteTexture(texture_id
)).Times(1);
1037 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
1038 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, _
, _
, _
, _
, _
, _
)).Times(0);
1039 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, _
, _
, _
, _
, _
, _
))
1041 id
= resource_provider
->CreateResource(
1042 size
, format
, ResourceProvider::TextureUsageAny
);
1043 resource_provider
->DeleteResource(id
);
1044 Mock::VerifyAndClearExpectations(context
);
1046 // Do allocate when we set the pixels.
1047 EXPECT_CALL(*context
, createTexture()).WillOnce(Return(texture_id
));
1048 EXPECT_CALL(*context
, deleteTexture(texture_id
)).Times(1);
1049 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
1050 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
1051 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
1052 id
= resource_provider
->CreateResource(
1053 size
, format
, ResourceProvider::TextureUsageAny
);
1054 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
1055 resource_provider
->DeleteResource(id
);
1056 Mock::VerifyAndClearExpectations(context
);
1058 // Same for SetPixelsFromBuffer
1059 EXPECT_CALL(*context
, createTexture()).WillOnce(Return(texture_id
));
1060 EXPECT_CALL(*context
, deleteTexture(texture_id
)).Times(1);
1061 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
1062 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
1063 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
1064 id
= resource_provider
->CreateResource(
1065 size
, format
, ResourceProvider::TextureUsageAny
);
1066 resource_provider
->AcquirePixelBuffer(id
);
1067 resource_provider
->SetPixelsFromBuffer(id
);
1068 resource_provider
->ReleasePixelBuffer(id
);
1069 resource_provider
->DeleteResource(id
);
1070 Mock::VerifyAndClearExpectations(context
);
1072 // Same for async version.
1073 EXPECT_CALL(*context
, createTexture()).WillOnce(Return(texture_id
));
1074 EXPECT_CALL(*context
, deleteTexture(texture_id
)).Times(1);
1075 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
1076 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
1078 id
= resource_provider
->CreateResource(
1079 size
, format
, ResourceProvider::TextureUsageAny
);
1080 resource_provider
->AcquirePixelBuffer(id
);
1081 resource_provider
->BeginSetPixels(id
);
1082 resource_provider
->ReleasePixelBuffer(id
);
1083 resource_provider
->DeleteResource(id
);
1084 Mock::VerifyAndClearExpectations(context
);
1087 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
1088 // Only for GL textures.
1089 if (GetParam() != ResourceProvider::GLTexture
)
1091 scoped_ptr
<WebKit::WebGraphicsContext3D
> mock_context(
1092 static_cast<WebKit::WebGraphicsContext3D
*>(
1093 new NiceMock
<AllocationTrackingContext3D
>));
1094 scoped_ptr
<OutputSurface
> output_surface(
1095 FakeOutputSurface::Create3d(mock_context
.Pass()));
1097 gfx::Size
size(2, 2);
1098 WGC3Denum format
= GL_RGBA
;
1099 ResourceProvider::ResourceId id
= 0;
1100 int texture_id
= 123;
1102 AllocationTrackingContext3D
* context
=
1103 static_cast<AllocationTrackingContext3D
*>(output_surface
->context3d());
1104 scoped_ptr
<ResourceProvider
> resource_provider(
1105 ResourceProvider::Create(output_surface
.get(), 0));
1107 EXPECT_CALL(*context
, createTexture()).WillOnce(Return(texture_id
));
1108 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
1109 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
1111 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
1112 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
1113 id
= resource_provider
->CreateResource(
1114 size
, format
, ResourceProvider::TextureUsageAny
);
1115 resource_provider
->AcquirePixelBuffer(id
);
1116 resource_provider
->BeginSetPixels(id
);
1117 resource_provider
->ForceSetPixelsToComplete(id
);
1118 resource_provider
->ReleasePixelBuffer(id
);
1119 Mock::VerifyAndClearExpectations(context
);
1122 TEST_P(ResourceProviderTest
, AbortForcedAsyncUpload
) {
1123 // Only for GL textures.
1124 if (GetParam() != ResourceProvider::GLTexture
)
1126 scoped_ptr
<WebKit::WebGraphicsContext3D
> mock_context(
1127 static_cast<WebKit::WebGraphicsContext3D
*>(
1128 new NiceMock
<AllocationTrackingContext3D
>));
1129 scoped_ptr
<OutputSurface
> output_surface(
1130 FakeOutputSurface::Create3d(mock_context
.Pass()));
1132 gfx::Size
size(2, 2);
1133 WGC3Denum format
= GL_RGBA
;
1134 ResourceProvider::ResourceId id
= 0;
1135 int texture_id
= 123;
1137 AllocationTrackingContext3D
* context
=
1138 static_cast<AllocationTrackingContext3D
*>(output_surface
->context3d());
1139 scoped_ptr
<ResourceProvider
> resource_provider(
1140 ResourceProvider::Create(output_surface
.get(), 0));
1142 EXPECT_CALL(*context
, createTexture()).WillRepeatedly(Return(texture_id
));
1143 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(4);
1144 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
1146 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
1147 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
1148 EXPECT_CALL(*context
, deleteTexture(_
)).Times(1);
1149 id
= resource_provider
->CreateResource(
1150 size
, format
, ResourceProvider::TextureUsageAny
);
1151 resource_provider
->AcquirePixelBuffer(id
);
1152 resource_provider
->BeginSetPixels(id
);
1153 resource_provider
->ForceSetPixelsToComplete(id
);
1154 resource_provider
->AbortSetPixels(id
);
1155 resource_provider
->ReleasePixelBuffer(id
);
1156 Mock::VerifyAndClearExpectations(context
);
1159 INSTANTIATE_TEST_CASE_P(
1160 ResourceProviderTests
,
1161 ResourceProviderTest
,
1162 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));