OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "cc/resource_provider.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "cc/base/scoped_ptr_deque.h" | |
10 #include "cc/base/scoped_ptr_hash_map.h" | |
11 #include "cc/output/output_surface.h" | |
12 #include "cc/test/fake_output_surface.h" | |
13 #include "cc/test/test_web_graphics_context_3d.h" | |
14 #include "gpu/GLES2/gl2extchromium.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3
D.h" | |
18 #include "third_party/khronos/GLES2/gl2.h" | |
19 #include "third_party/khronos/GLES2/gl2ext.h" | |
20 #include "ui/gfx/rect.h" | |
21 | |
22 using namespace WebKit; | |
23 | |
24 using testing::Mock; | |
25 using testing::NiceMock; | |
26 using testing::Return; | |
27 using testing::StrictMock; | |
28 using testing::_; | |
29 | |
30 namespace cc { | |
31 namespace { | |
32 | |
33 size_t textureSize(const gfx::Size& size, WGC3Denum format) | |
34 { | |
35 unsigned int componentsPerPixel = 4; | |
36 unsigned int bytesPerComponent = 1; | |
37 return size.width() * size.height() * componentsPerPixel * bytesPerComponent
; | |
38 } | |
39 | |
40 struct Texture { | |
41 Texture() | |
42 : format(0) | |
43 , filter(GL_NEAREST_MIPMAP_LINEAR) | |
44 { | |
45 } | |
46 | |
47 void reallocate(const gfx::Size& size, WGC3Denum format) | |
48 { | |
49 this->size = size; | |
50 this->format = format; | |
51 this->data.reset(new uint8_t[textureSize(size, format)]); | |
52 } | |
53 | |
54 gfx::Size size; | |
55 WGC3Denum format; | |
56 WGC3Denum filter; | |
57 scoped_array<uint8_t> data; | |
58 }; | |
59 | |
60 // Shared data between multiple ResourceProviderContext. This contains mailbox | |
61 // contents as well as information about sync points. | |
62 class ContextSharedData { | |
63 public: | |
64 static scoped_ptr<ContextSharedData> Create() { return make_scoped_ptr(new C
ontextSharedData()); } | |
65 | |
66 unsigned insertSyncPoint() { return m_nextSyncPoint++; } | |
67 | |
68 void genMailbox(WGC3Dbyte* mailbox) | |
69 { | |
70 memset(mailbox, 0, sizeof(WGC3Dbyte[64])); | |
71 memcpy(mailbox, &m_nextMailBox, sizeof(m_nextMailBox)); | |
72 ++m_nextMailBox; | |
73 } | |
74 | |
75 void produceTexture(const WGC3Dbyte* mailboxName, unsigned syncPoint, scoped
_ptr<Texture> texture) | |
76 { | |
77 unsigned mailbox = 0; | |
78 memcpy(&mailbox, mailboxName, sizeof(mailbox)); | |
79 ASSERT_TRUE(mailbox && mailbox < m_nextMailBox); | |
80 m_textures.set(mailbox, texture.Pass()); | |
81 ASSERT_LT(m_syncPointForMailbox[mailbox], syncPoint); | |
82 m_syncPointForMailbox[mailbox] = syncPoint; | |
83 } | |
84 | |
85 scoped_ptr<Texture> consumeTexture(const WGC3Dbyte* mailboxName, unsigned sy
ncPoint) | |
86 { | |
87 unsigned mailbox = 0; | |
88 memcpy(&mailbox, mailboxName, sizeof(mailbox)); | |
89 DCHECK(mailbox && mailbox < m_nextMailBox); | |
90 | |
91 // If the latest sync point the context has waited on is before the sync | |
92 // point for when the mailbox was set, pretend we never saw that | |
93 // produceTexture. | |
94 if (m_syncPointForMailbox[mailbox] > syncPoint) { | |
95 NOTREACHED(); | |
96 return scoped_ptr<Texture>(); | |
97 } | |
98 return m_textures.take(mailbox); | |
99 } | |
100 | |
101 private: | |
102 ContextSharedData() | |
103 : m_nextSyncPoint(1) | |
104 , m_nextMailBox(1) | |
105 { } | |
106 | |
107 unsigned m_nextSyncPoint; | |
108 unsigned m_nextMailBox; | |
109 typedef ScopedPtrHashMap<unsigned, Texture> TextureMap; | |
110 TextureMap m_textures; | |
111 base::hash_map<unsigned, unsigned> m_syncPointForMailbox; | |
112 }; | |
113 | |
114 class ResourceProviderContext : public TestWebGraphicsContext3D { | |
115 public: | |
116 static scoped_ptr<ResourceProviderContext> Create(ContextSharedData* sharedD
ata) { return make_scoped_ptr(new ResourceProviderContext(Attributes(), sharedDa
ta)); } | |
117 | |
118 virtual unsigned insertSyncPoint() | |
119 { | |
120 unsigned syncPoint = m_sharedData->insertSyncPoint(); | |
121 // Commit the produceTextureCHROMIUM calls at this point, so that | |
122 // they're associated with the sync point. | |
123 for (PendingProduceTextureList::iterator it = m_pendingProduceTextures.b
egin(); it != m_pendingProduceTextures.end(); ++it) | |
124 m_sharedData->produceTexture((*it)->mailbox, syncPoint, (*it)->textu
re.Pass()); | |
125 m_pendingProduceTextures.clear(); | |
126 return syncPoint; | |
127 } | |
128 | |
129 virtual void waitSyncPoint(unsigned syncPoint) | |
130 { | |
131 m_lastWaitedSyncPoint = std::max(syncPoint, m_lastWaitedSyncPoint); | |
132 } | |
133 | |
134 virtual void bindTexture(WGC3Denum target, WebGLId texture) | |
135 { | |
136 ASSERT_EQ(target, GL_TEXTURE_2D); | |
137 ASSERT_TRUE(!texture || m_textures.find(texture) != m_textures.end()); | |
138 m_currentTexture = texture; | |
139 } | |
140 | |
141 virtual WebGLId createTexture() | |
142 { | |
143 WebGLId id = TestWebGraphicsContext3D::createTexture(); | |
144 m_textures.add(id, make_scoped_ptr(new Texture)); | |
145 return id; | |
146 } | |
147 | |
148 virtual void deleteTexture(WebGLId id) | |
149 { | |
150 TextureMap::iterator it = m_textures.find(id); | |
151 ASSERT_FALSE(it == m_textures.end()); | |
152 m_textures.erase(it); | |
153 if (m_currentTexture == id) | |
154 m_currentTexture = 0; | |
155 } | |
156 | |
157 virtual void texStorage2DEXT(WGC3Denum target, WGC3Dint levels, WGC3Duint in
ternalformat, | |
158 WGC3Dint width, WGC3Dint height) | |
159 { | |
160 ASSERT_TRUE(m_currentTexture); | |
161 ASSERT_EQ(target, GL_TEXTURE_2D); | |
162 ASSERT_EQ(levels, 1); | |
163 WGC3Denum format = GL_RGBA; | |
164 switch (internalformat) { | |
165 case GL_RGBA8_OES: | |
166 break; | |
167 case GL_BGRA8_EXT: | |
168 format = GL_BGRA_EXT; | |
169 break; | |
170 default: | |
171 NOTREACHED(); | |
172 } | |
173 allocateTexture(gfx::Size(width, height), format); | |
174 } | |
175 | |
176 virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internal
format, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format,
WGC3Denum type, const void* pixels) | |
177 { | |
178 ASSERT_TRUE(m_currentTexture); | |
179 ASSERT_EQ(target, GL_TEXTURE_2D); | |
180 ASSERT_FALSE(level); | |
181 ASSERT_EQ(internalformat, format); | |
182 ASSERT_FALSE(border); | |
183 ASSERT_EQ(type, GL_UNSIGNED_BYTE); | |
184 allocateTexture(gfx::Size(width, height), format); | |
185 if (pixels) | |
186 setPixels(0, 0, width, height, pixels); | |
187 } | |
188 | |
189 virtual void texSubImage2D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffse
t, WGC3Dint yoffset, WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3
Denum type, const void* pixels) | |
190 { | |
191 ASSERT_TRUE(m_currentTexture); | |
192 ASSERT_EQ(target, GL_TEXTURE_2D); | |
193 ASSERT_FALSE(level); | |
194 ASSERT_TRUE(m_textures.get(m_currentTexture)); | |
195 ASSERT_EQ(m_textures.get(m_currentTexture)->format, format); | |
196 ASSERT_EQ(type, GL_UNSIGNED_BYTE); | |
197 ASSERT_TRUE(pixels); | |
198 setPixels(xoffset, yoffset, width, height, pixels); | |
199 } | |
200 | |
201 virtual void texParameteri(WGC3Denum target, WGC3Denum param, WGC3Dint value
) | |
202 { | |
203 ASSERT_TRUE(m_currentTexture); | |
204 ASSERT_EQ(target, GL_TEXTURE_2D); | |
205 Texture* texture = m_textures.get(m_currentTexture); | |
206 ASSERT_TRUE(texture); | |
207 if (param != GL_TEXTURE_MIN_FILTER) | |
208 return; | |
209 texture->filter = value; | |
210 } | |
211 | |
212 virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox) { return m_sharedData->g
enMailbox(mailbox); } | |
213 virtual void produceTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailb
ox) | |
214 { | |
215 ASSERT_TRUE(m_currentTexture); | |
216 ASSERT_EQ(target, GL_TEXTURE_2D); | |
217 | |
218 // Delay moving the texture into the mailbox until the next | |
219 // insertSyncPoint, so that it is not visible to other contexts that | |
220 // haven't waited on that sync point. | |
221 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture); | |
222 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); | |
223 pending->texture = m_textures.take(m_currentTexture); | |
224 m_textures.set(m_currentTexture, scoped_ptr<Texture>()); | |
225 m_pendingProduceTextures.push_back(pending.Pass()); | |
226 } | |
227 | |
228 virtual void consumeTextureCHROMIUM(WGC3Denum target, const WGC3Dbyte* mailb
ox) | |
229 { | |
230 ASSERT_TRUE(m_currentTexture); | |
231 ASSERT_EQ(target, GL_TEXTURE_2D); | |
232 m_textures.set(m_currentTexture, m_sharedData->consumeTexture(mailbox, m
_lastWaitedSyncPoint)); | |
233 } | |
234 | |
235 void getPixels(const gfx::Size& size, WGC3Denum format, uint8_t* pixels) | |
236 { | |
237 ASSERT_TRUE(m_currentTexture); | |
238 Texture* texture = m_textures.get(m_currentTexture); | |
239 ASSERT_TRUE(texture); | |
240 ASSERT_EQ(texture->size, size); | |
241 ASSERT_EQ(texture->format, format); | |
242 memcpy(pixels, texture->data.get(), textureSize(size, format)); | |
243 } | |
244 | |
245 WGC3Denum getTextureFilter() | |
246 { | |
247 DCHECK(m_currentTexture); | |
248 Texture* texture = m_textures.get(m_currentTexture); | |
249 DCHECK(texture); | |
250 return texture->filter; | |
251 } | |
252 | |
253 int textureCount() | |
254 { | |
255 return m_textures.size(); | |
256 } | |
257 | |
258 protected: | |
259 ResourceProviderContext(const Attributes& attrs, ContextSharedData* sharedDa
ta) | |
260 : TestWebGraphicsContext3D(attrs) | |
261 , m_sharedData(sharedData) | |
262 , m_currentTexture(0) | |
263 , m_lastWaitedSyncPoint(0) | |
264 { } | |
265 | |
266 private: | |
267 void allocateTexture(const gfx::Size& size, WGC3Denum format) | |
268 { | |
269 ASSERT_TRUE(m_currentTexture); | |
270 Texture* texture = m_textures.get(m_currentTexture); | |
271 ASSERT_TRUE(texture); | |
272 texture->reallocate(size, format); | |
273 } | |
274 | |
275 void setPixels(int xoffset, int yoffset, int width, int height, const void*
pixels) | |
276 { | |
277 ASSERT_TRUE(m_currentTexture); | |
278 Texture* texture = m_textures.get(m_currentTexture); | |
279 ASSERT_TRUE(texture); | |
280 ASSERT_TRUE(texture->data.get()); | |
281 ASSERT_TRUE(xoffset >= 0 && xoffset+width <= texture->size.width()); | |
282 ASSERT_TRUE(yoffset >= 0 && yoffset+height <= texture->size.height()); | |
283 ASSERT_TRUE(pixels); | |
284 size_t inPitch = textureSize(gfx::Size(width, 1), texture->format); | |
285 size_t outPitch = textureSize(gfx::Size(texture->size.width(), 1), textu
re->format); | |
286 uint8_t* dest = texture->data.get() + yoffset * outPitch + textureSize(g
fx::Size(xoffset, 1), texture->format); | |
287 const uint8_t* src = static_cast<const uint8_t*>(pixels); | |
288 for (int i = 0; i < height; ++i) { | |
289 memcpy(dest, src, inPitch); | |
290 dest += outPitch; | |
291 src += inPitch; | |
292 } | |
293 } | |
294 | |
295 typedef ScopedPtrHashMap<WebGLId, Texture> TextureMap; | |
296 struct PendingProduceTexture { | |
297 WGC3Dbyte mailbox[64]; | |
298 scoped_ptr<Texture> texture; | |
299 }; | |
300 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList; | |
301 ContextSharedData* m_sharedData; | |
302 WebGLId m_currentTexture; | |
303 TextureMap m_textures; | |
304 unsigned m_lastWaitedSyncPoint; | |
305 PendingProduceTextureList m_pendingProduceTextures; | |
306 }; | |
307 | |
308 class ResourceProviderTest : public testing::TestWithParam<ResourceProvider::Res
ourceType> { | |
309 public: | |
310 ResourceProviderTest() | |
311 : m_sharedData(ContextSharedData::Create()) | |
312 , m_outputSurface(FakeOutputSurface::Create3d(ResourceProviderContext::C
reate(m_sharedData.get()).PassAs<WebKit::WebGraphicsContext3D>().PassAs<WebKit::
WebGraphicsContext3D>())) | |
313 , m_resourceProvider(ResourceProvider::Create(m_outputSurface.get())) | |
314 { | |
315 m_resourceProvider->set_default_resource_type(GetParam()); | |
316 } | |
317 | |
318 ResourceProviderContext* context() { return static_cast<ResourceProviderCont
ext*>(m_outputSurface->context3d()); } | |
319 | |
320 void getResourcePixels(ResourceProvider::ResourceId id, const gfx::Size& siz
e, WGC3Denum format, uint8_t* pixels) | |
321 { | |
322 if (GetParam() == ResourceProvider::GLTexture) { | |
323 ResourceProvider::ScopedReadLockGL lockGL(m_resourceProvider.get(),
id); | |
324 ASSERT_NE(0U, lockGL.texture_id()); | |
325 context()->bindTexture(GL_TEXTURE_2D, lockGL.texture_id()); | |
326 context()->getPixels(size, format, pixels); | |
327 } else if (GetParam() == ResourceProvider::Bitmap) { | |
328 ResourceProvider::ScopedReadLockSoftware lockSoftware(m_resourceProv
ider.get(), id); | |
329 memcpy(pixels, lockSoftware.sk_bitmap()->getPixels(), lockSoftware.s
k_bitmap()->getSize()); | |
330 } | |
331 } | |
332 | |
333 void setResourceFilter(ResourceProvider* resourceProvider, ResourceProvider:
:ResourceId id, WGC3Denum filter) | |
334 { | |
335 ResourceProvider::ScopedSamplerGL sampler(resourceProvider, id, GL_TEXTU
RE_2D, filter); | |
336 } | |
337 | |
338 WGC3Denum getResourceFilter(ResourceProvider* resourceProvider, ResourceProv
ider::ResourceId id) | |
339 { | |
340 DCHECK_EQ(GetParam(), ResourceProvider::GLTexture); | |
341 ResourceProvider::ScopedReadLockGL lockGL(resourceProvider, id); | |
342 EXPECT_NE(0u, lockGL.texture_id()); | |
343 ResourceProviderContext* context = static_cast<ResourceProviderContext*>
(resourceProvider->GraphicsContext3D()); | |
344 context->bindTexture(GL_TEXTURE_2D, lockGL.texture_id()); | |
345 return context->getTextureFilter(); | |
346 } | |
347 | |
348 void expectNumResources(int count) | |
349 { | |
350 EXPECT_EQ(count, static_cast<int>(m_resourceProvider->num_resources())); | |
351 if (GetParam() == ResourceProvider::GLTexture) | |
352 EXPECT_EQ(count, context()->textureCount()); | |
353 } | |
354 | |
355 protected: | |
356 scoped_ptr<ContextSharedData> m_sharedData; | |
357 scoped_ptr<OutputSurface> m_outputSurface; | |
358 scoped_ptr<ResourceProvider> m_resourceProvider; | |
359 }; | |
360 | |
361 TEST_P(ResourceProviderTest, Basic) | |
362 { | |
363 gfx::Size size(1, 1); | |
364 WGC3Denum format = GL_RGBA; | |
365 size_t pixelSize = textureSize(size, format); | |
366 ASSERT_EQ(4U, pixelSize); | |
367 | |
368 ResourceProvider::ResourceId id = m_resourceProvider->CreateResource(size, f
ormat, ResourceProvider::TextureUsageAny); | |
369 expectNumResources(1); | |
370 | |
371 uint8_t data[4] = {1, 2, 3, 4}; | |
372 gfx::Rect rect(gfx::Point(), size); | |
373 m_resourceProvider->SetPixels(id, data, rect, rect, gfx::Vector2d()); | |
374 | |
375 uint8_t result[4] = {0}; | |
376 getResourcePixels(id, size, format, result); | |
377 EXPECT_EQ(0, memcmp(data, result, pixelSize)); | |
378 | |
379 m_resourceProvider->DeleteResource(id); | |
380 expectNumResources(0); | |
381 } | |
382 | |
383 TEST_P(ResourceProviderTest, Upload) | |
384 { | |
385 gfx::Size size(2, 2); | |
386 WGC3Denum format = GL_RGBA; | |
387 size_t pixelSize = textureSize(size, format); | |
388 ASSERT_EQ(16U, pixelSize); | |
389 | |
390 ResourceProvider::ResourceId id = m_resourceProvider->CreateResource(size, f
ormat, ResourceProvider::TextureUsageAny); | |
391 | |
392 uint8_t image[16] = {0}; | |
393 gfx::Rect imageRect(gfx::Point(), size); | |
394 m_resourceProvider->SetPixels(id, image, imageRect, imageRect, gfx::Vector2d
()); | |
395 | |
396 for (uint8_t i = 0 ; i < pixelSize; ++i) | |
397 image[i] = i; | |
398 | |
399 uint8_t result[16] = {0}; | |
400 { | |
401 gfx::Rect sourceRect(0, 0, 1, 1); | |
402 gfx::Vector2d destOffset(0, 0); | |
403 m_resourceProvider->SetPixels(id, image, imageRect, sourceRect, destOffs
et); | |
404 | |
405 uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0, | |
406 0, 0, 0, 0, 0, 0, 0, 0}; | |
407 getResourcePixels(id, size, format, result); | |
408 EXPECT_EQ(0, memcmp(expected, result, pixelSize)); | |
409 } | |
410 { | |
411 gfx::Rect sourceRect(0, 0, 1, 1); | |
412 gfx::Vector2d destOffset(1, 1); | |
413 m_resourceProvider->SetPixels(id, image, imageRect, sourceRect, destOffs
et); | |
414 | |
415 uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0, | |
416 0, 0, 0, 0, 0, 1, 2, 3}; | |
417 getResourcePixels(id, size, format, result); | |
418 EXPECT_EQ(0, memcmp(expected, result, pixelSize)); | |
419 } | |
420 { | |
421 gfx::Rect sourceRect(1, 0, 1, 1); | |
422 gfx::Vector2d destOffset(0, 1); | |
423 m_resourceProvider->SetPixels(id, image, imageRect, sourceRect, destOffs
et); | |
424 | |
425 uint8_t expected[16] = {0, 1, 2, 3, 0, 0, 0, 0, | |
426 4, 5, 6, 7, 0, 1, 2, 3}; | |
427 getResourcePixels(id, size, format, result); | |
428 EXPECT_EQ(0, memcmp(expected, result, pixelSize)); | |
429 } | |
430 { | |
431 gfx::Rect offsetImageRect(gfx::Point(100, 100), size); | |
432 gfx::Rect sourceRect(100, 100, 1, 1); | |
433 gfx::Vector2d destOffset(1, 0); | |
434 m_resourceProvider->SetPixels(id, image, offsetImageRect, sourceRect, de
stOffset); | |
435 | |
436 uint8_t expected[16] = {0, 1, 2, 3, 0, 1, 2, 3, | |
437 4, 5, 6, 7, 0, 1, 2, 3}; | |
438 getResourcePixels(id, size, format, result); | |
439 EXPECT_EQ(0, memcmp(expected, result, pixelSize)); | |
440 } | |
441 | |
442 | |
443 m_resourceProvider->DeleteResource(id); | |
444 } | |
445 | |
446 TEST_P(ResourceProviderTest, TransferResources) | |
447 { | |
448 // Resource transfer is only supported with GL textures for now. | |
449 if (GetParam() != ResourceProvider::GLTexture) | |
450 return; | |
451 | |
452 scoped_ptr<OutputSurface> childOutputSurface(FakeOutputSurface::Create3d(Res
ourceProviderContext::Create(m_sharedData.get()).PassAs<WebKit::WebGraphicsConte
xt3D>())); | |
453 scoped_ptr<ResourceProvider> childResourceProvider(ResourceProvider::Create(
childOutputSurface.get())); | |
454 | |
455 gfx::Size size(1, 1); | |
456 WGC3Denum format = GL_RGBA; | |
457 size_t pixelSize = textureSize(size, format); | |
458 ASSERT_EQ(4U, pixelSize); | |
459 | |
460 ResourceProvider::ResourceId id1 = childResourceProvider->CreateResource(siz
e, format, ResourceProvider::TextureUsageAny); | |
461 uint8_t data1[4] = {1, 2, 3, 4}; | |
462 gfx::Rect rect(gfx::Point(), size); | |
463 childResourceProvider->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); | |
464 | |
465 ResourceProvider::ResourceId id2 = childResourceProvider->CreateResource(siz
e, format, ResourceProvider::TextureUsageAny); | |
466 uint8_t data2[4] = {5, 5, 5, 5}; | |
467 childResourceProvider->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); | |
468 | |
469 int childId = m_resourceProvider->CreateChild(); | |
470 | |
471 { | |
472 // Transfer some resources to the parent. | |
473 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
474 resourceIdsToTransfer.push_back(id1); | |
475 resourceIdsToTransfer.push_back(id2); | |
476 TransferableResourceArray list; | |
477 childResourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list)
; | |
478 ASSERT_EQ(2u, list.size()); | |
479 EXPECT_NE(0u, list[0].sync_point); | |
480 EXPECT_NE(0u, list[1].sync_point); | |
481 EXPECT_TRUE(childResourceProvider->InUseByConsumer(id1)); | |
482 EXPECT_TRUE(childResourceProvider->InUseByConsumer(id2)); | |
483 m_resourceProvider->ReceiveFromChild(childId, list); | |
484 } | |
485 | |
486 EXPECT_EQ(2u, m_resourceProvider->num_resources()); | |
487 ResourceProvider::ResourceIdMap resourceMap = m_resourceProvider->GetChildTo
ParentMap(childId); | |
488 ResourceProvider::ResourceId mappedId1 = resourceMap[id1]; | |
489 ResourceProvider::ResourceId mappedId2 = resourceMap[id2]; | |
490 EXPECT_NE(0u, mappedId1); | |
491 EXPECT_NE(0u, mappedId2); | |
492 EXPECT_FALSE(m_resourceProvider->InUseByConsumer(id1)); | |
493 EXPECT_FALSE(m_resourceProvider->InUseByConsumer(id2)); | |
494 | |
495 uint8_t result[4] = {0}; | |
496 getResourcePixels(mappedId1, size, format, result); | |
497 EXPECT_EQ(0, memcmp(data1, result, pixelSize)); | |
498 | |
499 getResourcePixels(mappedId2, size, format, result); | |
500 EXPECT_EQ(0, memcmp(data2, result, pixelSize)); | |
501 | |
502 { | |
503 // Check that transfering again the same resource from the child to the | |
504 // parent is a noop. | |
505 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
506 resourceIdsToTransfer.push_back(id1); | |
507 TransferableResourceArray list; | |
508 childResourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list)
; | |
509 EXPECT_EQ(0u, list.size()); | |
510 } | |
511 | |
512 { | |
513 // Transfer resources back from the parent to the child. | |
514 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
515 resourceIdsToTransfer.push_back(mappedId1); | |
516 resourceIdsToTransfer.push_back(mappedId2); | |
517 TransferableResourceArray list; | |
518 m_resourceProvider->PrepareSendToChild(childId, resourceIdsToTransfer, &
list); | |
519 ASSERT_EQ(2u, list.size()); | |
520 EXPECT_NE(0u, list[0].sync_point); | |
521 EXPECT_NE(0u, list[1].sync_point); | |
522 childResourceProvider->ReceiveFromParent(list); | |
523 } | |
524 EXPECT_FALSE(childResourceProvider->InUseByConsumer(id1)); | |
525 EXPECT_FALSE(childResourceProvider->InUseByConsumer(id2)); | |
526 | |
527 ResourceProviderContext* childContext3D = static_cast<ResourceProviderContex
t*>(childOutputSurface->context3d()); | |
528 { | |
529 ResourceProvider::ScopedReadLockGL lock(childResourceProvider.get(), id1
); | |
530 ASSERT_NE(0U, lock.texture_id()); | |
531 childContext3D->bindTexture(GL_TEXTURE_2D, lock.texture_id()); | |
532 childContext3D->getPixels(size, format, result); | |
533 EXPECT_EQ(0, memcmp(data1, result, pixelSize)); | |
534 } | |
535 { | |
536 ResourceProvider::ScopedReadLockGL lock(childResourceProvider.get(), id2
); | |
537 ASSERT_NE(0U, lock.texture_id()); | |
538 childContext3D->bindTexture(GL_TEXTURE_2D, lock.texture_id()); | |
539 childContext3D->getPixels(size, format, result); | |
540 EXPECT_EQ(0, memcmp(data2, result, pixelSize)); | |
541 } | |
542 | |
543 { | |
544 // Transfer resources to the parent again. | |
545 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
546 resourceIdsToTransfer.push_back(id1); | |
547 resourceIdsToTransfer.push_back(id2); | |
548 TransferableResourceArray list; | |
549 childResourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list)
; | |
550 ASSERT_EQ(2u, list.size()); | |
551 EXPECT_NE(0u, list[0].sync_point); | |
552 EXPECT_NE(0u, list[1].sync_point); | |
553 EXPECT_TRUE(childResourceProvider->InUseByConsumer(id1)); | |
554 EXPECT_TRUE(childResourceProvider->InUseByConsumer(id2)); | |
555 m_resourceProvider->ReceiveFromChild(childId, list); | |
556 } | |
557 | |
558 EXPECT_EQ(2u, m_resourceProvider->num_resources()); | |
559 m_resourceProvider->DestroyChild(childId); | |
560 EXPECT_EQ(0u, m_resourceProvider->num_resources()); | |
561 } | |
562 | |
563 TEST_P(ResourceProviderTest, DeleteTransferredResources) | |
564 { | |
565 // Resource transfer is only supported with GL textures for now. | |
566 if (GetParam() != ResourceProvider::GLTexture) | |
567 return; | |
568 | |
569 scoped_ptr<OutputSurface> childOutputSurface(FakeOutputSurface::Create3d(Res
ourceProviderContext::Create(m_sharedData.get()).PassAs<WebKit::WebGraphicsConte
xt3D>())); | |
570 scoped_ptr<ResourceProvider> childResourceProvider(ResourceProvider::Create(
childOutputSurface.get())); | |
571 | |
572 gfx::Size size(1, 1); | |
573 WGC3Denum format = GL_RGBA; | |
574 size_t pixelSize = textureSize(size, format); | |
575 ASSERT_EQ(4U, pixelSize); | |
576 | |
577 ResourceProvider::ResourceId id = childResourceProvider->CreateResource(size
, format, ResourceProvider::TextureUsageAny); | |
578 uint8_t data[4] = {1, 2, 3, 4}; | |
579 gfx::Rect rect(gfx::Point(), size); | |
580 childResourceProvider->SetPixels(id, data, rect, rect, gfx::Vector2d()); | |
581 | |
582 int childId = m_resourceProvider->CreateChild(); | |
583 | |
584 { | |
585 // Transfer some resource to the parent. | |
586 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
587 resourceIdsToTransfer.push_back(id); | |
588 TransferableResourceArray list; | |
589 childResourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list)
; | |
590 ASSERT_EQ(1u, list.size()); | |
591 EXPECT_NE(0u, list[0].sync_point); | |
592 EXPECT_TRUE(childResourceProvider->InUseByConsumer(id)); | |
593 m_resourceProvider->ReceiveFromChild(childId, list); | |
594 } | |
595 | |
596 // Delete textures in the child, while they are transfered. | |
597 childResourceProvider->DeleteResource(id); | |
598 EXPECT_EQ(1u, childResourceProvider->num_resources()); | |
599 | |
600 { | |
601 // Transfer resources back from the parent to the child. | |
602 ResourceProvider::ResourceIdMap resourceMap = m_resourceProvider->GetChi
ldToParentMap(childId); | |
603 ResourceProvider::ResourceId mappedId = resourceMap[id]; | |
604 EXPECT_NE(0u, mappedId); | |
605 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
606 resourceIdsToTransfer.push_back(mappedId); | |
607 TransferableResourceArray list; | |
608 m_resourceProvider->PrepareSendToChild(childId, resourceIdsToTransfer, &
list); | |
609 ASSERT_EQ(1u, list.size()); | |
610 EXPECT_NE(0u, list[0].sync_point); | |
611 childResourceProvider->ReceiveFromParent(list); | |
612 } | |
613 EXPECT_EQ(0u, childResourceProvider->num_resources()); | |
614 } | |
615 | |
616 TEST_P(ResourceProviderTest, TextureFilters) | |
617 { | |
618 // Resource transfer is only supported with GL textures for now. | |
619 if (GetParam() != ResourceProvider::GLTexture) | |
620 return; | |
621 | |
622 scoped_ptr<OutputSurface> childOutputSurface(FakeOutputSurface::Create3d(Res
ourceProviderContext::Create(m_sharedData.get()).PassAs<WebKit::WebGraphicsConte
xt3D>())); | |
623 scoped_ptr<ResourceProvider> childResourceProvider(ResourceProvider::Create(
childOutputSurface.get())); | |
624 | |
625 gfx::Size size(1, 1); | |
626 WGC3Denum format = GL_RGBA; | |
627 size_t pixelSize = textureSize(size, format); | |
628 ASSERT_EQ(4U, pixelSize); | |
629 | |
630 ResourceProvider::ResourceId id = childResourceProvider->CreateResource(size
, format, ResourceProvider::TextureUsageAny); | |
631 uint8_t data[4] = {1, 2, 3, 4}; | |
632 gfx::Rect rect(gfx::Point(), size); | |
633 childResourceProvider->SetPixels(id, data, rect, rect, gfx::Vector2d()); | |
634 EXPECT_EQ(GL_LINEAR, getResourceFilter(childResourceProvider.get(), id)); | |
635 setResourceFilter(childResourceProvider.get(), id, GL_NEAREST); | |
636 EXPECT_EQ(GL_NEAREST, getResourceFilter(childResourceProvider.get(), id)); | |
637 | |
638 int childId = m_resourceProvider->CreateChild(); | |
639 | |
640 { | |
641 // Transfer some resource to the parent. | |
642 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
643 resourceIdsToTransfer.push_back(id); | |
644 TransferableResourceArray list; | |
645 childResourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list)
; | |
646 ASSERT_EQ(1u, list.size()); | |
647 EXPECT_EQ(GL_NEAREST, list[0].filter); | |
648 m_resourceProvider->ReceiveFromChild(childId, list); | |
649 } | |
650 ResourceProvider::ResourceIdMap resourceMap = m_resourceProvider->GetChildTo
ParentMap(childId); | |
651 ResourceProvider::ResourceId mappedId = resourceMap[id]; | |
652 EXPECT_NE(0u, mappedId); | |
653 EXPECT_EQ(GL_NEAREST, getResourceFilter(m_resourceProvider.get(), mappedId))
; | |
654 setResourceFilter(m_resourceProvider.get(), mappedId, GL_LINEAR); | |
655 EXPECT_EQ(GL_LINEAR, getResourceFilter(m_resourceProvider.get(), mappedId)); | |
656 { | |
657 // Transfer resources back from the parent to the child. | |
658 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
659 resourceIdsToTransfer.push_back(mappedId); | |
660 TransferableResourceArray list; | |
661 m_resourceProvider->PrepareSendToChild(childId, resourceIdsToTransfer, &
list); | |
662 ASSERT_EQ(1u, list.size()); | |
663 EXPECT_EQ(GL_LINEAR, list[0].filter); | |
664 childResourceProvider->ReceiveFromParent(list); | |
665 } | |
666 EXPECT_EQ(GL_LINEAR, getResourceFilter(childResourceProvider.get(), id)); | |
667 setResourceFilter(childResourceProvider.get(), id, GL_NEAREST); | |
668 EXPECT_EQ(GL_NEAREST, getResourceFilter(childResourceProvider.get(), id)); | |
669 } | |
670 | |
671 void ReleaseTextureMailbox(unsigned* releaseSyncPoint, unsigned syncPoint) { | |
672 *releaseSyncPoint = syncPoint; | |
673 } | |
674 | |
675 TEST_P(ResourceProviderTest, TransferMailboxResources) | |
676 { | |
677 // Resource transfer is only supported with GL textures for now. | |
678 if (GetParam() != ResourceProvider::GLTexture) | |
679 return; | |
680 unsigned texture = context()->createTexture(); | |
681 context()->bindTexture(GL_TEXTURE_2D, texture); | |
682 uint8_t data[4] = {1, 2, 3, 4}; | |
683 context()->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGN
ED_BYTE, &data); | |
684 gpu::Mailbox mailbox; | |
685 context()->genMailboxCHROMIUM(mailbox.name); | |
686 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
687 unsigned syncPoint = context()->insertSyncPoint(); | |
688 | |
689 // All the logic below assumes that the sync points are all positive. | |
690 EXPECT_LT(0u, syncPoint); | |
691 | |
692 unsigned releaseSyncPoint = 0; | |
693 TextureMailbox::ReleaseCallback callback = base::Bind(ReleaseTextureMailbox,
&releaseSyncPoint); | |
694 ResourceProvider::ResourceId resource = m_resourceProvider->CreateResourceFr
omTextureMailbox(TextureMailbox(mailbox, callback, syncPoint)); | |
695 EXPECT_EQ(1u, context()->textureCount()); | |
696 EXPECT_EQ(0u, releaseSyncPoint); | |
697 | |
698 { | |
699 // Transfer the resource, expect the sync points to be consistent. | |
700 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
701 resourceIdsToTransfer.push_back(resource); | |
702 TransferableResourceArray list; | |
703 m_resourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list); | |
704 ASSERT_EQ(1u, list.size()); | |
705 EXPECT_LE(syncPoint, list[0].sync_point); | |
706 EXPECT_EQ(0u, memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.
name))); | |
707 EXPECT_EQ(0u, releaseSyncPoint); | |
708 | |
709 context()->waitSyncPoint(list[0].sync_point); | |
710 unsigned otherTexture = context()->createTexture(); | |
711 context()->bindTexture(GL_TEXTURE_2D, otherTexture); | |
712 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
713 uint8_t testData[4] = {0}; | |
714 context()->getPixels(gfx::Size(1, 1), GL_RGBA, testData); | |
715 EXPECT_EQ(0u, memcmp(data, testData, sizeof(data))); | |
716 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
717 context()->deleteTexture(otherTexture); | |
718 list[0].sync_point = context()->insertSyncPoint(); | |
719 EXPECT_LT(0u, list[0].sync_point); | |
720 | |
721 // Receive the resource, then delete it, expect the sync points to be co
nsistent. | |
722 m_resourceProvider->ReceiveFromParent(list); | |
723 EXPECT_EQ(1u, context()->textureCount()); | |
724 EXPECT_EQ(0u, releaseSyncPoint); | |
725 | |
726 m_resourceProvider->DeleteResource(resource); | |
727 EXPECT_LE(list[0].sync_point, releaseSyncPoint); | |
728 } | |
729 | |
730 | |
731 // We're going to do the same thing as above, but testing the case where we | |
732 // delete the resource before we receive it back. | |
733 syncPoint = releaseSyncPoint; | |
734 EXPECT_LT(0u, syncPoint); | |
735 releaseSyncPoint = 0; | |
736 resource = m_resourceProvider->CreateResourceFromTextureMailbox(TextureMailb
ox(mailbox, callback, syncPoint)); | |
737 EXPECT_EQ(1u, context()->textureCount()); | |
738 EXPECT_EQ(0u, releaseSyncPoint); | |
739 | |
740 { | |
741 // Transfer the resource, expect the sync points to be consistent. | |
742 ResourceProvider::ResourceIdArray resourceIdsToTransfer; | |
743 resourceIdsToTransfer.push_back(resource); | |
744 TransferableResourceArray list; | |
745 m_resourceProvider->PrepareSendToParent(resourceIdsToTransfer, &list); | |
746 ASSERT_EQ(1u, list.size()); | |
747 EXPECT_LE(syncPoint, list[0].sync_point); | |
748 EXPECT_EQ(0u, memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.
name))); | |
749 EXPECT_EQ(0u, releaseSyncPoint); | |
750 | |
751 context()->waitSyncPoint(list[0].sync_point); | |
752 unsigned otherTexture = context()->createTexture(); | |
753 context()->bindTexture(GL_TEXTURE_2D, otherTexture); | |
754 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
755 uint8_t testData[4] = {0}; | |
756 context()->getPixels(gfx::Size(1, 1), GL_RGBA, testData); | |
757 EXPECT_EQ(0u, memcmp(data, testData, sizeof(data))); | |
758 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
759 context()->deleteTexture(otherTexture); | |
760 list[0].sync_point = context()->insertSyncPoint(); | |
761 EXPECT_LT(0u, list[0].sync_point); | |
762 | |
763 // Delete the resource, which shouldn't do anything. | |
764 m_resourceProvider->DeleteResource(resource); | |
765 EXPECT_EQ(1u, context()->textureCount()); | |
766 EXPECT_EQ(0u, releaseSyncPoint); | |
767 | |
768 // Then receive the resource which should release the mailbox, expect th
e sync points to be consistent. | |
769 m_resourceProvider->ReceiveFromParent(list); | |
770 EXPECT_LE(list[0].sync_point, releaseSyncPoint); | |
771 } | |
772 | |
773 context()->waitSyncPoint(releaseSyncPoint); | |
774 context()->bindTexture(GL_TEXTURE_2D, texture); | |
775 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
776 context()->deleteTexture(texture); | |
777 } | |
778 | |
779 class TextureStateTrackingContext : public TestWebGraphicsContext3D { | |
780 public: | |
781 MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture)); | |
782 MOCK_METHOD3(texParameteri, void(WGC3Denum target, WGC3Denum pname, WGC3Dint
param)); | |
783 | |
784 // Force all textures to be "1" so we can test for them. | |
785 virtual WebKit::WebGLId NextTextureId() { return 1; } | |
786 }; | |
787 | |
788 TEST_P(ResourceProviderTest, ScopedSampler) | |
789 { | |
790 // Sampling is only supported for GL textures. | |
791 if (GetParam() != ResourceProvider::GLTexture) | |
792 return; | |
793 | |
794 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p
tr<WebKit::WebGraphicsContext3D>(new TextureStateTrackingContext))); | |
795 TextureStateTrackingContext* context = static_cast<TextureStateTrackingConte
xt*>(outputSurface->context3d()); | |
796 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu
tSurface.get())); | |
797 | |
798 gfx::Size size(1, 1); | |
799 WGC3Denum format = GL_RGBA; | |
800 int textureId = 1; | |
801 | |
802 // Check that the texture gets created with the right sampler settings. | |
803 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)) | |
804 .Times(2); // Once to create and once to allocate. | |
805 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL
_LINEAR)); | |
806 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL
_LINEAR)); | |
807 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLA
MP_TO_EDGE)); | |
808 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLA
MP_TO_EDGE)); | |
809 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_POOL_CHROMIUM,
GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); | |
810 ResourceProvider::ResourceId id = resourceProvider->CreateResource(size, for
mat, ResourceProvider::TextureUsageAny); | |
811 resourceProvider->AllocateForTesting(id); | |
812 | |
813 // Creating a sampler with the default filter should not change any texture | |
814 // parameters. | |
815 { | |
816 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)); | |
817 ResourceProvider::ScopedSamplerGL sampler(resourceProvider.get(), id, GL
_TEXTURE_2D, GL_LINEAR); | |
818 } | |
819 | |
820 // Using a different filter should be reflected in the texture parameters. | |
821 { | |
822 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)); | |
823 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_NEAREST)); | |
824 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_NEAREST)); | |
825 ResourceProvider::ScopedSamplerGL sampler(resourceProvider.get(), id, GL
_TEXTURE_2D, GL_NEAREST); | |
826 } | |
827 | |
828 // Test resetting to the default filter. | |
829 { | |
830 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)); | |
831 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_LINEAR)); | |
832 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_LINEAR)); | |
833 ResourceProvider::ScopedSamplerGL sampler(resourceProvider.get(), id, GL
_TEXTURE_2D, GL_LINEAR); | |
834 } | |
835 | |
836 Mock::VerifyAndClearExpectations(context); | |
837 } | |
838 | |
839 TEST_P(ResourceProviderTest, ManagedResource) | |
840 { | |
841 // Sampling is only supported for GL textures. | |
842 if (GetParam() != ResourceProvider::GLTexture) | |
843 return; | |
844 | |
845 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p
tr<WebKit::WebGraphicsContext3D>(new TextureStateTrackingContext))); | |
846 TextureStateTrackingContext* context = static_cast<TextureStateTrackingConte
xt*>(outputSurface->context3d()); | |
847 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu
tSurface.get())); | |
848 | |
849 gfx::Size size(1, 1); | |
850 WGC3Denum format = GL_RGBA; | |
851 int textureId = 1; | |
852 | |
853 // Check that the texture gets created with the right sampler settings. | |
854 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)); | |
855 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL
_LINEAR)); | |
856 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL
_LINEAR)); | |
857 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLA
MP_TO_EDGE)); | |
858 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLA
MP_TO_EDGE)); | |
859 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_POOL_CHROMIUM,
GL_TEXTURE_POOL_MANAGED_CHROMIUM)); | |
860 ResourceProvider::ResourceId id = resourceProvider->CreateManagedResource(si
ze, format, ResourceProvider::TextureUsageAny); | |
861 | |
862 Mock::VerifyAndClearExpectations(context); | |
863 } | |
864 | |
865 class AllocationTrackingContext3D : public TestWebGraphicsContext3D { | |
866 public: | |
867 MOCK_METHOD0(createTexture, WebGLId()); | |
868 MOCK_METHOD1(deleteTexture, void(WebGLId texture_id)); | |
869 MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture)); | |
870 MOCK_METHOD9(texImage2D, void(WGC3Denum target, WGC3Dint level, WGC3Denum in
ternalformat, | |
871 WGC3Dsizei width, WGC3Dsizei height, WGC3Dint
border, WGC3Denum format, | |
872 WGC3Denum type, const void* pixels)); | |
873 MOCK_METHOD9(texSubImage2D, void(WGC3Denum target, WGC3Dint level, WGC3Dint
xoffset, WGC3Dint yoffset, | |
874 WGC3Dsizei width, WGC3Dsizei height, WGC3De
num format, | |
875 WGC3Denum type, const void* pixels)); | |
876 MOCK_METHOD9(asyncTexImage2DCHROMIUM, void(WGC3Denum target, WGC3Dint level,
WGC3Denum internalformat, | |
877 WGC3Dsizei width, WGC3Dsizei heigh
t, WGC3Dint border, WGC3Denum format, | |
878 WGC3Denum type, const void* pixels
)); | |
879 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM, void(WGC3Denum target, WGC3Dint lev
el, WGC3Dint xoffset, WGC3Dint yoffset, | |
880 WGC3Dsizei width, WGC3Dsizei h
eight, WGC3Denum format, | |
881 WGC3Denum type, const void* pi
xels)); | |
882 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(WGC3Denum target)); | |
883 }; | |
884 | |
885 TEST_P(ResourceProviderTest, TextureAllocation) | |
886 { | |
887 // Only for GL textures. | |
888 if (GetParam() != ResourceProvider::GLTexture) | |
889 return; | |
890 scoped_ptr<WebKit::WebGraphicsContext3D> mock_context( | |
891 static_cast<WebKit::WebGraphicsContext3D*>(new NiceMock<AllocationTracki
ngContext3D>)); | |
892 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(mock_con
text.Pass())); | |
893 | |
894 gfx::Size size(2, 2); | |
895 gfx::Vector2d offset(0, 0); | |
896 gfx::Rect rect(0, 0, 2, 2); | |
897 WGC3Denum format = GL_RGBA; | |
898 ResourceProvider::ResourceId id = 0; | |
899 uint8_t pixels[16] = {0}; | |
900 int textureId = 123; | |
901 | |
902 AllocationTrackingContext3D* context = static_cast<AllocationTrackingContext
3D*>(outputSurface->context3d()); | |
903 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu
tSurface.get())); | |
904 | |
905 // Lazy allocation. Don't allocate when creating the resource. | |
906 EXPECT_CALL(*context, createTexture()).WillOnce(Return(textureId)); | |
907 EXPECT_CALL(*context, deleteTexture(textureId)).Times(1); | |
908 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(1); | |
909 EXPECT_CALL(*context, texImage2D(_,_,_,_,_,_,_,_,_)).Times(0); | |
910 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,_,_,_,_,_,_)).Times(0); | |
911 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
912 resourceProvider->DeleteResource(id); | |
913 Mock::VerifyAndClearExpectations(context); | |
914 | |
915 // Do allocate when we set the pixels. | |
916 EXPECT_CALL(*context, createTexture()).WillOnce(Return(textureId)); | |
917 EXPECT_CALL(*context, deleteTexture(textureId)).Times(1); | |
918 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(3); | |
919 EXPECT_CALL(*context, texImage2D(_,_,_,2,2,_,_,_,_)).Times(1); | |
920 EXPECT_CALL(*context, texSubImage2D(_,_,_,_,2,2,_,_,_)).Times(1); | |
921 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
922 resourceProvider->SetPixels(id, pixels, rect, rect, offset); | |
923 resourceProvider->DeleteResource(id); | |
924 Mock::VerifyAndClearExpectations(context); | |
925 | |
926 // Same for setPixelsFromBuffer | |
927 EXPECT_CALL(*context, createTexture()).WillOnce(Return(textureId)); | |
928 EXPECT_CALL(*context, deleteTexture(textureId)).Times(1); | |
929 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(3); | |
930 EXPECT_CALL(*context, texImage2D(_,_,_,2,2,_,_,_,_)).Times(1); | |
931 EXPECT_CALL(*context, texSubImage2D(_,_,_,_,2,2,_,_,_)).Times(1); | |
932 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
933 resourceProvider->AcquirePixelBuffer(id); | |
934 resourceProvider->SetPixelsFromBuffer(id); | |
935 resourceProvider->ReleasePixelBuffer(id); | |
936 resourceProvider->DeleteResource(id); | |
937 Mock::VerifyAndClearExpectations(context); | |
938 | |
939 // Same for async version. | |
940 EXPECT_CALL(*context, createTexture()).WillOnce(Return(textureId)); | |
941 EXPECT_CALL(*context, deleteTexture(textureId)).Times(1); | |
942 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(2); | |
943 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,2,2,_,_,_,_)).Times(1); | |
944 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
945 resourceProvider->AcquirePixelBuffer(id); | |
946 resourceProvider->BeginSetPixels(id); | |
947 resourceProvider->ReleasePixelBuffer(id); | |
948 resourceProvider->DeleteResource(id); | |
949 Mock::VerifyAndClearExpectations(context); | |
950 } | |
951 | |
952 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) | |
953 { | |
954 // Only for GL textures. | |
955 if (GetParam() != ResourceProvider::GLTexture) | |
956 return; | |
957 scoped_ptr<WebKit::WebGraphicsContext3D> mock_context( | |
958 static_cast<WebKit::WebGraphicsContext3D*>(new NiceMock<AllocationTracki
ngContext3D>)); | |
959 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(mock_con
text.Pass())); | |
960 | |
961 gfx::Size size(2, 2); | |
962 WGC3Denum format = GL_RGBA; | |
963 ResourceProvider::ResourceId id = 0; | |
964 int textureId = 123; | |
965 | |
966 AllocationTrackingContext3D* context = static_cast<AllocationTrackingContext
3D*>(outputSurface->context3d()); | |
967 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu
tSurface.get())); | |
968 | |
969 EXPECT_CALL(*context, createTexture()).WillOnce(Return(textureId)); | |
970 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(3); | |
971 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,2,2,_,_,_,_)).Times(1); | |
972 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1); | |
973 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1); | |
974 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
975 resourceProvider->AcquirePixelBuffer(id); | |
976 resourceProvider->BeginSetPixels(id); | |
977 resourceProvider->ForceSetPixelsToComplete(id); | |
978 resourceProvider->ReleasePixelBuffer(id); | |
979 Mock::VerifyAndClearExpectations(context); | |
980 } | |
981 | |
982 TEST_P(ResourceProviderTest, AbortForcedAsyncUpload) | |
983 { | |
984 // Only for GL textures. | |
985 if (GetParam() != ResourceProvider::GLTexture) | |
986 return; | |
987 scoped_ptr<WebKit::WebGraphicsContext3D> mock_context( | |
988 static_cast<WebKit::WebGraphicsContext3D*>(new NiceMock<AllocationTracki
ngContext3D>)); | |
989 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(mock_con
text.Pass())); | |
990 | |
991 gfx::Size size(2, 2); | |
992 WGC3Denum format = GL_RGBA; | |
993 ResourceProvider::ResourceId id = 0; | |
994 int textureId = 123; | |
995 | |
996 AllocationTrackingContext3D* context = static_cast<AllocationTrackingContext
3D*>(outputSurface->context3d()); | |
997 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu
tSurface.get())); | |
998 | |
999 EXPECT_CALL(*context, createTexture()).WillRepeatedly(Return(textureId)); | |
1000 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, textureId)).Times(4); | |
1001 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,2,2,_,_,_,_)).Times(1); | |
1002 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1); | |
1003 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1); | |
1004 EXPECT_CALL(*context, deleteTexture(_)).Times(1); | |
1005 id = resourceProvider->CreateResource(size, format, ResourceProvider::Textur
eUsageAny); | |
1006 resourceProvider->AcquirePixelBuffer(id); | |
1007 resourceProvider->BeginSetPixels(id); | |
1008 resourceProvider->ForceSetPixelsToComplete(id); | |
1009 resourceProvider->AbortSetPixels(id); | |
1010 resourceProvider->ReleasePixelBuffer(id); | |
1011 Mock::VerifyAndClearExpectations(context); | |
1012 } | |
1013 | |
1014 INSTANTIATE_TEST_CASE_P(ResourceProviderTests, | |
1015 ResourceProviderTest, | |
1016 ::testing::Values(ResourceProvider::GLTexture, | |
1017 ResourceProvider::Bitmap)); | |
1018 | |
1019 } // namespace | |
1020 } // namespace cc | |
OLD | NEW |