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/resource_provider.h"
7 #include "base/logging.h"
8 #include "cc/graphics_context.h"
9 #include "cc/scoped_ptr_deque.h"
10 #include "cc/scoped_ptr_hash_map.h"
11 #include "cc/test/compositor_fake_web_graphics_context_3d.h"
12 #include "cc/test/fake_web_compositor_output_surface.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/khronos/GLES2/gl2.h"
16 #include "third_party/khronos/GLES2/gl2ext.h"
17 #include "ui/gfx/rect.h"
18 #include <public/WebGraphicsContext3D.h>
20 using namespace WebKit
;
27 size_t textureSize(const gfx::Size
& size
, WGC3Denum format
)
29 unsigned int componentsPerPixel
= 4;
30 unsigned int bytesPerComponent
= 1;
31 return size
.width() * size
.height() * componentsPerPixel
* bytesPerComponent
;
35 Texture(const gfx::Size
& size
, WGC3Denum format
)
38 , data(new uint8_t[textureSize(size
, format
)])
44 scoped_array
<uint8_t> data
;
47 // Shared data between multiple ResourceProviderContext. This contains mailbox
48 // contents as well as information about sync points.
49 class ContextSharedData
{
51 static scoped_ptr
<ContextSharedData
> create() { return make_scoped_ptr(new ContextSharedData()); }
53 unsigned insertSyncPoint() { return m_nextSyncPoint
++; }
55 void genMailbox(WGC3Dbyte
* mailbox
)
57 memset(mailbox
, 0, sizeof(WGC3Dbyte
[64]));
58 memcpy(mailbox
, &m_nextMailBox
, sizeof(m_nextMailBox
));
62 void produceTexture(const WGC3Dbyte
* mailboxName
, unsigned syncPoint
, scoped_ptr
<Texture
> texture
)
65 memcpy(&mailbox
, mailboxName
, sizeof(mailbox
));
66 ASSERT_TRUE(mailbox
&& mailbox
< m_nextMailBox
);
67 m_textures
.set(mailbox
, texture
.Pass());
68 ASSERT_LT(m_syncPointForMailbox
[mailbox
], syncPoint
);
69 m_syncPointForMailbox
[mailbox
] = syncPoint
;
72 scoped_ptr
<Texture
> consumeTexture(const WGC3Dbyte
* mailboxName
, unsigned syncPoint
)
75 memcpy(&mailbox
, mailboxName
, sizeof(mailbox
));
76 DCHECK(mailbox
&& mailbox
< m_nextMailBox
);
78 // If the latest sync point the context has waited on is before the sync
79 // point for when the mailbox was set, pretend we never saw that
81 if (m_syncPointForMailbox
[mailbox
] < syncPoint
)
82 return scoped_ptr
<Texture
>();
83 return m_textures
.take(mailbox
);
92 unsigned m_nextSyncPoint
;
93 unsigned m_nextMailBox
;
94 typedef ScopedPtrHashMap
<unsigned, Texture
> TextureMap
;
95 TextureMap m_textures
;
96 base::hash_map
<unsigned, unsigned> m_syncPointForMailbox
;
99 class ResourceProviderContext
: public CompositorFakeWebGraphicsContext3D
{
101 static scoped_ptr
<ResourceProviderContext
> create(ContextSharedData
* sharedData
) { return make_scoped_ptr(new ResourceProviderContext(Attributes(), sharedData
)); }
103 virtual unsigned insertSyncPoint()
105 unsigned syncPoint
= m_sharedData
->insertSyncPoint();
106 // Commit the produceTextureCHROMIUM calls at this point, so that
107 // they're associated with the sync point.
108 for (PendingProduceTextureList::iterator it
= m_pendingProduceTextures
.begin(); it
!= m_pendingProduceTextures
.end(); ++it
)
109 m_sharedData
->produceTexture((*it
)->mailbox
, syncPoint
, (*it
)->texture
.Pass());
110 m_pendingProduceTextures
.clear();
114 virtual void waitSyncPoint(unsigned syncPoint
)
116 m_lastWaitedSyncPoint
= std::max(syncPoint
, m_lastWaitedSyncPoint
);
119 virtual void bindTexture(WGC3Denum target
, WebGLId texture
)
121 ASSERT_EQ(target
, GL_TEXTURE_2D
);
122 ASSERT_TRUE(!texture
|| m_textures
.find(texture
) != m_textures
.end());
123 m_currentTexture
= texture
;
126 virtual WebGLId
createTexture()
128 WebGLId id
= CompositorFakeWebGraphicsContext3D::createTexture();
129 m_textures
.add(id
, scoped_ptr
<Texture
>());
133 virtual void deleteTexture(WebGLId id
)
135 TextureMap::iterator it
= m_textures
.find(id
);
136 ASSERT_FALSE(it
== m_textures
.end());
137 m_textures
.erase(it
);
138 if (m_currentTexture
== id
)
139 m_currentTexture
= 0;
142 virtual void texStorage2DEXT(WGC3Denum target
, WGC3Dint levels
, WGC3Duint internalformat
,
143 WGC3Dint width
, WGC3Dint height
)
145 ASSERT_TRUE(m_currentTexture
);
146 ASSERT_EQ(target
, GL_TEXTURE_2D
);
147 ASSERT_EQ(levels
, 1);
148 WGC3Denum format
= GL_RGBA
;
149 switch (internalformat
) {
153 format
= GL_BGRA_EXT
;
158 allocateTexture(gfx::Size(width
, height
), format
);
161 virtual void texImage2D(WGC3Denum target
, WGC3Dint level
, WGC3Denum internalformat
, WGC3Dsizei width
, WGC3Dsizei height
, WGC3Dint border
, WGC3Denum format
, WGC3Denum type
, const void* pixels
)
163 ASSERT_TRUE(m_currentTexture
);
164 ASSERT_EQ(target
, GL_TEXTURE_2D
);
166 ASSERT_EQ(internalformat
, format
);
167 ASSERT_FALSE(border
);
168 ASSERT_EQ(type
, GL_UNSIGNED_BYTE
);
169 allocateTexture(gfx::Size(width
, height
), format
);
171 setPixels(0, 0, width
, height
, pixels
);
174 virtual void texSubImage2D(WGC3Denum target
, WGC3Dint level
, WGC3Dint xoffset
, WGC3Dint yoffset
, WGC3Dsizei width
, WGC3Dsizei height
, WGC3Denum format
, WGC3Denum type
, const void* pixels
)
176 ASSERT_TRUE(m_currentTexture
);
177 ASSERT_EQ(target
, GL_TEXTURE_2D
);
179 ASSERT_TRUE(m_textures
.get(m_currentTexture
));
180 ASSERT_EQ(m_textures
.get(m_currentTexture
)->format
, format
);
181 ASSERT_EQ(type
, GL_UNSIGNED_BYTE
);
183 setPixels(xoffset
, yoffset
, width
, height
, pixels
);
186 virtual void genMailboxCHROMIUM(WGC3Dbyte
* mailbox
) { return m_sharedData
->genMailbox(mailbox
); }
187 virtual void produceTextureCHROMIUM(WGC3Denum target
, const WGC3Dbyte
* mailbox
)
189 ASSERT_TRUE(m_currentTexture
);
190 ASSERT_EQ(target
, GL_TEXTURE_2D
);
192 // Delay moving the texture into the mailbox until the next
193 // insertSyncPoint, so that it is not visible to other contexts that
194 // haven't waited on that sync point.
195 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
196 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
197 pending
->texture
= m_textures
.take(m_currentTexture
);
198 m_textures
.set(m_currentTexture
, scoped_ptr
<Texture
>());
199 m_pendingProduceTextures
.append(pending
.Pass());
202 virtual void consumeTextureCHROMIUM(WGC3Denum target
, const WGC3Dbyte
* mailbox
)
204 ASSERT_TRUE(m_currentTexture
);
205 ASSERT_EQ(target
, GL_TEXTURE_2D
);
206 m_textures
.set(m_currentTexture
, m_sharedData
->consumeTexture(mailbox
, m_lastWaitedSyncPoint
));
209 void getPixels(const gfx::Size
& size
, WGC3Denum format
, uint8_t* pixels
)
211 ASSERT_TRUE(m_currentTexture
);
212 Texture
* texture
= m_textures
.get(m_currentTexture
);
213 ASSERT_TRUE(texture
);
214 ASSERT_EQ(texture
->size
, size
);
215 ASSERT_EQ(texture
->format
, format
);
216 memcpy(pixels
, texture
->data
.get(), textureSize(size
, format
));
221 return m_textures
.size();
225 ResourceProviderContext(const Attributes
& attrs
, ContextSharedData
* sharedData
)
226 : CompositorFakeWebGraphicsContext3D(attrs
)
227 , m_sharedData(sharedData
)
228 , m_currentTexture(0)
229 , m_lastWaitedSyncPoint(0)
233 void allocateTexture(const gfx::Size
& size
, WGC3Denum format
)
235 ASSERT_TRUE(m_currentTexture
);
236 m_textures
.set(m_currentTexture
, make_scoped_ptr(new Texture(size
, format
)));
239 void setPixels(int xoffset
, int yoffset
, int width
, int height
, const void* pixels
)
241 ASSERT_TRUE(m_currentTexture
);
242 Texture
* texture
= m_textures
.get(m_currentTexture
);
243 ASSERT_TRUE(texture
);
244 ASSERT_TRUE(xoffset
>= 0 && xoffset
+width
<= texture
->size
.width());
245 ASSERT_TRUE(yoffset
>= 0 && yoffset
+height
<= texture
->size
.height());
247 size_t inPitch
= textureSize(gfx::Size(width
, 1), texture
->format
);
248 size_t outPitch
= textureSize(gfx::Size(texture
->size
.width(), 1), texture
->format
);
249 uint8_t* dest
= texture
->data
.get() + yoffset
* outPitch
+ textureSize(gfx::Size(xoffset
, 1), texture
->format
);
250 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
251 for (int i
= 0; i
< height
; ++i
) {
252 memcpy(dest
, src
, inPitch
);
258 typedef ScopedPtrHashMap
<WebGLId
, Texture
> TextureMap
;
259 struct PendingProduceTexture
{
260 WGC3Dbyte mailbox
[64];
261 scoped_ptr
<Texture
> texture
;
263 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
264 ContextSharedData
* m_sharedData
;
265 WebGLId m_currentTexture
;
266 TextureMap m_textures
;
267 unsigned m_lastWaitedSyncPoint
;
268 PendingProduceTextureList m_pendingProduceTextures
;
271 class ResourceProviderTest
: public testing::TestWithParam
<ResourceProvider::ResourceType
> {
273 ResourceProviderTest()
274 : m_sharedData(ContextSharedData::create())
275 , m_context(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData
.get()).PassAs
<WebKit::WebGraphicsContext3D
>().PassAs
<WebKit::WebGraphicsContext3D
>()))
276 , m_resourceProvider(ResourceProvider::create(m_context
.get()))
278 m_resourceProvider
->setDefaultResourceType(GetParam());
281 ResourceProviderContext
* context() { return static_cast<ResourceProviderContext
*>(m_context
->context3D()); }
283 void getResourcePixels(ResourceProvider::ResourceId id
, const gfx::Size
& size
, WGC3Denum format
, uint8_t* pixels
)
285 if (GetParam() == ResourceProvider::GLTexture
) {
286 ResourceProvider::ScopedReadLockGL
lockGL(m_resourceProvider
.get(), id
);
287 ASSERT_NE(0U, lockGL
.textureId());
288 context()->bindTexture(GL_TEXTURE_2D
, lockGL
.textureId());
289 context()->getPixels(size
, format
, pixels
);
290 } else if (GetParam() == ResourceProvider::Bitmap
) {
291 ResourceProvider::ScopedReadLockSoftware
lockSoftware(m_resourceProvider
.get(), id
);
292 memcpy(pixels
, lockSoftware
.skBitmap()->getPixels(), lockSoftware
.skBitmap()->getSize());
296 void expectNumResources(int count
)
298 EXPECT_EQ(count
, static_cast<int>(m_resourceProvider
->numResources()));
299 if (GetParam() == ResourceProvider::GLTexture
)
300 EXPECT_EQ(count
, context()->textureCount());
304 scoped_ptr
<ContextSharedData
> m_sharedData
;
305 scoped_ptr
<GraphicsContext
> m_context
;
306 scoped_ptr
<ResourceProvider
> m_resourceProvider
;
309 TEST_P(ResourceProviderTest
, Basic
)
311 gfx::Size
size(1, 1);
312 WGC3Denum format
= GL_RGBA
;
314 size_t pixelSize
= textureSize(size
, format
);
315 ASSERT_EQ(4U, pixelSize
);
317 ResourceProvider::ResourceId id
= m_resourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
318 expectNumResources(1);
320 uint8_t data
[4] = {1, 2, 3, 4};
321 gfx::Rect
rect(gfx::Point(), size
);
322 m_resourceProvider
->setPixels(id
, data
, rect
, rect
, gfx::Vector2d());
324 uint8_t result
[4] = {0};
325 getResourcePixels(id
, size
, format
, result
);
326 EXPECT_EQ(0, memcmp(data
, result
, pixelSize
));
328 m_resourceProvider
->deleteResource(id
);
329 expectNumResources(0);
332 TEST_P(ResourceProviderTest
, DeleteOwnedResources
)
334 gfx::Size
size(1, 1);
335 WGC3Denum format
= GL_RGBA
;
339 for (int i
= 0; i
< count
; ++i
)
340 m_resourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
341 expectNumResources(3);
343 m_resourceProvider
->deleteOwnedResources(pool
+1);
344 expectNumResources(3);
346 m_resourceProvider
->deleteOwnedResources(pool
);
347 expectNumResources(0);
350 TEST_P(ResourceProviderTest
, Upload
)
352 gfx::Size
size(2, 2);
353 WGC3Denum format
= GL_RGBA
;
355 size_t pixelSize
= textureSize(size
, format
);
356 ASSERT_EQ(16U, pixelSize
);
358 ResourceProvider::ResourceId id
= m_resourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
360 uint8_t image
[16] = {0};
361 gfx::Rect
imageRect(gfx::Point(), size
);
362 m_resourceProvider
->setPixels(id
, image
, imageRect
, imageRect
, gfx::Vector2d());
364 for (uint8_t i
= 0 ; i
< pixelSize
; ++i
)
367 uint8_t result
[16] = {0};
369 gfx::Rect
sourceRect(0, 0, 1, 1);
370 gfx::Vector2d
destOffset(0, 0);
371 m_resourceProvider
->setPixels(id
, image
, imageRect
, sourceRect
, destOffset
);
373 uint8_t expected
[16] = {0, 1, 2, 3, 0, 0, 0, 0,
374 0, 0, 0, 0, 0, 0, 0, 0};
375 getResourcePixels(id
, size
, format
, result
);
376 EXPECT_EQ(0, memcmp(expected
, result
, pixelSize
));
379 gfx::Rect
sourceRect(0, 0, 1, 1);
380 gfx::Vector2d
destOffset(1, 1);
381 m_resourceProvider
->setPixels(id
, image
, imageRect
, sourceRect
, destOffset
);
383 uint8_t expected
[16] = {0, 1, 2, 3, 0, 0, 0, 0,
384 0, 0, 0, 0, 0, 1, 2, 3};
385 getResourcePixels(id
, size
, format
, result
);
386 EXPECT_EQ(0, memcmp(expected
, result
, pixelSize
));
389 gfx::Rect
sourceRect(1, 0, 1, 1);
390 gfx::Vector2d
destOffset(0, 1);
391 m_resourceProvider
->setPixels(id
, image
, imageRect
, sourceRect
, destOffset
);
393 uint8_t expected
[16] = {0, 1, 2, 3, 0, 0, 0, 0,
394 4, 5, 6, 7, 0, 1, 2, 3};
395 getResourcePixels(id
, size
, format
, result
);
396 EXPECT_EQ(0, memcmp(expected
, result
, pixelSize
));
399 gfx::Rect
offsetImageRect(gfx::Point(100, 100), size
);
400 gfx::Rect
sourceRect(100, 100, 1, 1);
401 gfx::Vector2d
destOffset(1, 0);
402 m_resourceProvider
->setPixels(id
, image
, offsetImageRect
, sourceRect
, destOffset
);
404 uint8_t expected
[16] = {0, 1, 2, 3, 0, 1, 2, 3,
405 4, 5, 6, 7, 0, 1, 2, 3};
406 getResourcePixels(id
, size
, format
, result
);
407 EXPECT_EQ(0, memcmp(expected
, result
, pixelSize
));
411 m_resourceProvider
->deleteResource(id
);
414 TEST_P(ResourceProviderTest
, TransferResources
)
416 // Resource transfer is only supported with GL textures for now.
417 if (GetParam() != ResourceProvider::GLTexture
)
420 scoped_ptr
<GraphicsContext
> childContext(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData
.get()).PassAs
<WebKit::WebGraphicsContext3D
>()));
421 scoped_ptr
<ResourceProvider
> childResourceProvider(ResourceProvider::create(childContext
.get()));
423 gfx::Size
size(1, 1);
424 WGC3Denum format
= GL_RGBA
;
426 size_t pixelSize
= textureSize(size
, format
);
427 ASSERT_EQ(4U, pixelSize
);
429 ResourceProvider::ResourceId id1
= childResourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
430 uint8_t data1
[4] = {1, 2, 3, 4};
431 gfx::Rect
rect(gfx::Point(), size
);
432 childResourceProvider
->setPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
434 ResourceProvider::ResourceId id2
= childResourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
435 uint8_t data2
[4] = {5, 5, 5, 5};
436 childResourceProvider
->setPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
439 int childId
= m_resourceProvider
->createChild(childPool
);
442 // Transfer some resources to the parent.
443 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
444 resourceIdsToTransfer
.push_back(id1
);
445 resourceIdsToTransfer
.push_back(id2
);
446 TransferableResourceList list
;
447 childResourceProvider
->prepareSendToParent(resourceIdsToTransfer
, &list
);
448 EXPECT_NE(0u, list
.sync_point
);
449 EXPECT_EQ(2u, list
.resources
.size());
450 EXPECT_TRUE(childResourceProvider
->inUseByConsumer(id1
));
451 EXPECT_TRUE(childResourceProvider
->inUseByConsumer(id2
));
452 m_resourceProvider
->receiveFromChild(childId
, list
);
455 EXPECT_EQ(2u, m_resourceProvider
->numResources());
456 ResourceProvider::ResourceIdMap resourceMap
= m_resourceProvider
->getChildToParentMap(childId
);
457 ResourceProvider::ResourceId mappedId1
= resourceMap
[id1
];
458 ResourceProvider::ResourceId mappedId2
= resourceMap
[id2
];
459 EXPECT_NE(0u, mappedId1
);
460 EXPECT_NE(0u, mappedId2
);
461 EXPECT_FALSE(m_resourceProvider
->inUseByConsumer(id1
));
462 EXPECT_FALSE(m_resourceProvider
->inUseByConsumer(id2
));
464 uint8_t result
[4] = {0};
465 getResourcePixels(mappedId1
, size
, format
, result
);
466 EXPECT_EQ(0, memcmp(data1
, result
, pixelSize
));
468 getResourcePixels(mappedId2
, size
, format
, result
);
469 EXPECT_EQ(0, memcmp(data2
, result
, pixelSize
));
472 // Check that transfering again the same resource from the child to the
474 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
475 resourceIdsToTransfer
.push_back(id1
);
476 TransferableResourceList list
;
477 childResourceProvider
->prepareSendToParent(resourceIdsToTransfer
, &list
);
478 EXPECT_EQ(0u, list
.sync_point
);
479 EXPECT_EQ(0u, list
.resources
.size());
483 // Transfer resources back from the parent to the child.
484 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
485 resourceIdsToTransfer
.push_back(mappedId1
);
486 resourceIdsToTransfer
.push_back(mappedId2
);
487 TransferableResourceList list
;
488 m_resourceProvider
->prepareSendToChild(childId
, resourceIdsToTransfer
, &list
);
489 EXPECT_NE(0u, list
.sync_point
);
490 EXPECT_EQ(2u, list
.resources
.size());
491 childResourceProvider
->receiveFromParent(list
);
493 EXPECT_FALSE(childResourceProvider
->inUseByConsumer(id1
));
494 EXPECT_FALSE(childResourceProvider
->inUseByConsumer(id2
));
496 ResourceProviderContext
* childContext3D
= static_cast<ResourceProviderContext
*>(childContext
->context3D());
498 ResourceProvider::ScopedReadLockGL
lock(childResourceProvider
.get(), id1
);
499 ASSERT_NE(0U, lock
.textureId());
500 childContext3D
->bindTexture(GL_TEXTURE_2D
, lock
.textureId());
501 childContext3D
->getPixels(size
, format
, result
);
502 EXPECT_EQ(0, memcmp(data1
, result
, pixelSize
));
505 ResourceProvider::ScopedReadLockGL
lock(childResourceProvider
.get(), id2
);
506 ASSERT_NE(0U, lock
.textureId());
507 childContext3D
->bindTexture(GL_TEXTURE_2D
, lock
.textureId());
508 childContext3D
->getPixels(size
, format
, result
);
509 EXPECT_EQ(0, memcmp(data2
, result
, pixelSize
));
513 // Transfer resources to the parent again.
514 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
515 resourceIdsToTransfer
.push_back(id1
);
516 resourceIdsToTransfer
.push_back(id2
);
517 TransferableResourceList list
;
518 childResourceProvider
->prepareSendToParent(resourceIdsToTransfer
, &list
);
519 EXPECT_NE(0u, list
.sync_point
);
520 EXPECT_EQ(2u, list
.resources
.size());
521 EXPECT_TRUE(childResourceProvider
->inUseByConsumer(id1
));
522 EXPECT_TRUE(childResourceProvider
->inUseByConsumer(id2
));
523 m_resourceProvider
->receiveFromChild(childId
, list
);
526 EXPECT_EQ(2u, m_resourceProvider
->numResources());
527 m_resourceProvider
->destroyChild(childId
);
528 EXPECT_EQ(0u, m_resourceProvider
->numResources());
531 TEST_P(ResourceProviderTest
, DeleteTransferredResources
)
533 // Resource transfer is only supported with GL textures for now.
534 if (GetParam() != ResourceProvider::GLTexture
)
537 scoped_ptr
<GraphicsContext
> childContext(FakeWebCompositorOutputSurface::create(ResourceProviderContext::create(m_sharedData
.get()).PassAs
<WebKit::WebGraphicsContext3D
>()));
538 scoped_ptr
<ResourceProvider
> childResourceProvider(ResourceProvider::create(childContext
.get()));
540 gfx::Size
size(1, 1);
541 WGC3Denum format
= GL_RGBA
;
543 size_t pixelSize
= textureSize(size
, format
);
544 ASSERT_EQ(4U, pixelSize
);
546 ResourceProvider::ResourceId id
= childResourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
547 uint8_t data
[4] = {1, 2, 3, 4};
548 gfx::Rect
rect(gfx::Point(), size
);
549 childResourceProvider
->setPixels(id
, data
, rect
, rect
, gfx::Vector2d());
552 int childId
= m_resourceProvider
->createChild(childPool
);
555 // Transfer some resource to the parent.
556 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
557 resourceIdsToTransfer
.push_back(id
);
558 TransferableResourceList list
;
559 childResourceProvider
->prepareSendToParent(resourceIdsToTransfer
, &list
);
560 EXPECT_NE(0u, list
.sync_point
);
561 EXPECT_EQ(1u, list
.resources
.size());
562 EXPECT_TRUE(childResourceProvider
->inUseByConsumer(id
));
563 m_resourceProvider
->receiveFromChild(childId
, list
);
566 // Delete textures in the child, while they are transfered.
567 childResourceProvider
->deleteResource(id
);
568 EXPECT_EQ(1u, childResourceProvider
->numResources());
571 // Transfer resources back from the parent to the child.
572 ResourceProvider::ResourceIdMap resourceMap
= m_resourceProvider
->getChildToParentMap(childId
);
573 ResourceProvider::ResourceId mappedId
= resourceMap
[id
];
574 EXPECT_NE(0u, mappedId
);
575 ResourceProvider::ResourceIdArray resourceIdsToTransfer
;
576 resourceIdsToTransfer
.push_back(mappedId
);
577 TransferableResourceList list
;
578 m_resourceProvider
->prepareSendToChild(childId
, resourceIdsToTransfer
, &list
);
579 EXPECT_NE(0u, list
.sync_point
);
580 EXPECT_EQ(1u, list
.resources
.size());
581 childResourceProvider
->receiveFromParent(list
);
583 EXPECT_EQ(0u, childResourceProvider
->numResources());
586 class TextureStateTrackingContext
: public FakeWebGraphicsContext3D
{
588 MOCK_METHOD2(bindTexture
, void(WGC3Denum target
, WebGLId texture
));
589 MOCK_METHOD3(texParameteri
, void(WGC3Denum target
, WGC3Denum pname
, WGC3Dint param
));
592 TEST_P(ResourceProviderTest
, ScopedSampler
)
594 // Sampling is only supported for GL textures.
595 if (GetParam() != ResourceProvider::GLTexture
)
598 scoped_ptr
<GraphicsContext
> outputSurface(FakeWebCompositorOutputSurface::create(scoped_ptr
<WebKit::WebGraphicsContext3D
>(new TextureStateTrackingContext
)));
599 TextureStateTrackingContext
* context
= static_cast<TextureStateTrackingContext
*>(outputSurface
->context3D());
600 scoped_ptr
<ResourceProvider
> resourceProvider(ResourceProvider::create(outputSurface
.get()));
602 gfx::Size
size(1, 1);
603 WGC3Denum format
= GL_RGBA
;
607 // Check that the texture gets created with the right sampler settings.
608 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, textureId
));
609 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
610 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
611 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
612 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
613 ResourceProvider::ResourceId id
= resourceProvider
->createResource(pool
, size
, format
, ResourceProvider::TextureUsageAny
);
615 // Creating a sampler with the default filter should not change any texture
618 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, textureId
));
619 ResourceProvider::ScopedSamplerGL
sampler(resourceProvider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
622 // Using a different filter should be reflected in the texture parameters.
624 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, textureId
));
625 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
626 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
627 ResourceProvider::ScopedSamplerGL
sampler(resourceProvider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
630 // Test resetting to the default filter.
632 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, textureId
));
633 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
634 EXPECT_CALL(*context
, texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
635 ResourceProvider::ScopedSamplerGL
sampler(resourceProvider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
638 Mock::VerifyAndClearExpectations(context
);
641 INSTANTIATE_TEST_CASE_P(ResourceProviderTests
,
642 ResourceProviderTest
,
643 ::testing::Values(ResourceProvider::GLTexture
,
644 ResourceProvider::Bitmap
));