| 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 |