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/resources/resource_provider.h" 6 7#include <algorithm> 8#include <map> 9 10#include "base/bind.h" 11#include "base/containers/hash_tables.h" 12#include "base/logging.h" 13#include "base/memory/ref_counted.h" 14#include "cc/base/scoped_ptr_deque.h" 15#include "cc/output/output_surface.h" 16#include "cc/resources/returned_resource.h" 17#include "cc/resources/shared_bitmap_manager.h" 18#include "cc/resources/single_release_callback.h" 19#include "cc/test/fake_output_surface.h" 20#include "cc/test/fake_output_surface_client.h" 21#include "cc/test/test_texture.h" 22#include "cc/test/test_web_graphics_context_3d.h" 23#include "gpu/GLES2/gl2extchromium.h" 24#include "testing/gmock/include/gmock/gmock.h" 25#include "testing/gtest/include/gtest/gtest.h" 26#include "third_party/khronos/GLES2/gl2.h" 27#include "third_party/khronos/GLES2/gl2ext.h" 28#include "ui/gfx/rect.h" 29 30using testing::Mock; 31using testing::NiceMock; 32using testing::Return; 33using testing::SetArgPointee; 34using testing::StrictMock; 35using testing::_; 36 37namespace cc { 38namespace { 39 40static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {} 41 42static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory, 43 unsigned sync_point, 44 bool lost_resource) {} 45 46static void ReleaseTextureMailbox(unsigned* release_sync_point, 47 bool* release_lost_resource, 48 unsigned sync_point, 49 bool lost_resource) { 50 *release_sync_point = sync_point; 51 *release_lost_resource = lost_resource; 52} 53 54static void ReleaseSharedMemoryCallback( 55 scoped_ptr<base::SharedMemory> shared_memory, 56 bool* release_called, 57 unsigned* release_sync_point, 58 bool* lost_resource_result, 59 unsigned sync_point, 60 bool lost_resource) { 61 *release_called = true; 62 *release_sync_point = sync_point; 63 *lost_resource_result = lost_resource; 64} 65 66static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory( 67 gfx::Size size, 68 uint32_t value) { 69 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); 70 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea())); 71 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory()); 72 CHECK(pixels); 73 std::fill_n(pixels, size.GetArea(), value); 74 return shared_memory.Pass(); 75} 76 77class TextureStateTrackingContext : public TestWebGraphicsContext3D { 78 public: 79 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); 80 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param)); 81 MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point)); 82 MOCK_METHOD0(insertSyncPoint, unsigned(void)); 83 MOCK_METHOD2(produceTextureCHROMIUM, 84 void(GLenum target, const GLbyte* mailbox)); 85 MOCK_METHOD2(consumeTextureCHROMIUM, 86 void(GLenum target, const GLbyte* mailbox)); 87 88 // Force all textures to be consecutive numbers starting at "1", 89 // so we easily can test for them. 90 virtual GLuint NextTextureId() OVERRIDE { 91 base::AutoLock lock(namespace_->lock); 92 return namespace_->next_texture_id++; 93 } 94 virtual void RetireTextureId(GLuint) OVERRIDE {} 95}; 96 97// Shared data between multiple ResourceProviderContext. This contains mailbox 98// contents as well as information about sync points. 99class ContextSharedData { 100 public: 101 static scoped_ptr<ContextSharedData> Create() { 102 return make_scoped_ptr(new ContextSharedData()); 103 } 104 105 unsigned InsertSyncPoint() { return next_sync_point_++; } 106 107 void GenMailbox(GLbyte* mailbox) { 108 memset(mailbox, 0, sizeof(GLbyte[64])); 109 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_)); 110 ++next_mailbox_; 111 } 112 113 void ProduceTexture(const GLbyte* mailbox_name, 114 unsigned sync_point, 115 scoped_refptr<TestTexture> texture) { 116 unsigned mailbox = 0; 117 memcpy(&mailbox, mailbox_name, sizeof(mailbox)); 118 ASSERT_TRUE(mailbox && mailbox < next_mailbox_); 119 textures_[mailbox] = texture; 120 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point); 121 sync_point_for_mailbox_[mailbox] = sync_point; 122 } 123 124 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name, 125 unsigned sync_point) { 126 unsigned mailbox = 0; 127 memcpy(&mailbox, mailbox_name, sizeof(mailbox)); 128 DCHECK(mailbox && mailbox < next_mailbox_); 129 130 // If the latest sync point the context has waited on is before the sync 131 // point for when the mailbox was set, pretend we never saw that 132 // ProduceTexture. 133 if (sync_point_for_mailbox_[mailbox] > sync_point) { 134 NOTREACHED(); 135 return scoped_refptr<TestTexture>(); 136 } 137 return textures_[mailbox]; 138 } 139 140 private: 141 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {} 142 143 unsigned next_sync_point_; 144 unsigned next_mailbox_; 145 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap; 146 TextureMap textures_; 147 base::hash_map<unsigned, unsigned> sync_point_for_mailbox_; 148}; 149 150class ResourceProviderContext : public TestWebGraphicsContext3D { 151 public: 152 static scoped_ptr<ResourceProviderContext> Create( 153 ContextSharedData* shared_data) { 154 return make_scoped_ptr(new ResourceProviderContext(shared_data)); 155 } 156 157 virtual unsigned insertSyncPoint() OVERRIDE { 158 unsigned sync_point = shared_data_->InsertSyncPoint(); 159 // Commit the produceTextureCHROMIUM calls at this point, so that 160 // they're associated with the sync point. 161 for (PendingProduceTextureList::iterator it = 162 pending_produce_textures_.begin(); 163 it != pending_produce_textures_.end(); 164 ++it) { 165 shared_data_->ProduceTexture( 166 (*it)->mailbox, sync_point, (*it)->texture); 167 } 168 pending_produce_textures_.clear(); 169 return sync_point; 170 } 171 172 virtual void waitSyncPoint(unsigned sync_point) OVERRIDE { 173 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_); 174 } 175 176 virtual void texStorage2DEXT(GLenum target, 177 GLint levels, 178 GLuint internalformat, 179 GLint width, 180 GLint height) OVERRIDE { 181 CheckTextureIsBound(target); 182 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); 183 ASSERT_EQ(1, levels); 184 GLenum format = GL_RGBA; 185 switch (internalformat) { 186 case GL_RGBA8_OES: 187 break; 188 case GL_BGRA8_EXT: 189 format = GL_BGRA_EXT; 190 break; 191 default: 192 NOTREACHED(); 193 } 194 AllocateTexture(gfx::Size(width, height), format); 195 } 196 197 virtual void texImage2D(GLenum target, 198 GLint level, 199 GLenum internalformat, 200 GLsizei width, 201 GLsizei height, 202 GLint border, 203 GLenum format, 204 GLenum type, 205 const void* pixels) OVERRIDE { 206 CheckTextureIsBound(target); 207 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); 208 ASSERT_FALSE(level); 209 ASSERT_EQ(internalformat, format); 210 ASSERT_FALSE(border); 211 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); 212 AllocateTexture(gfx::Size(width, height), format); 213 if (pixels) 214 SetPixels(0, 0, width, height, pixels); 215 } 216 217 virtual void texSubImage2D(GLenum target, 218 GLint level, 219 GLint xoffset, 220 GLint yoffset, 221 GLsizei width, 222 GLsizei height, 223 GLenum format, 224 GLenum type, 225 const void* pixels) OVERRIDE { 226 CheckTextureIsBound(target); 227 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target); 228 ASSERT_FALSE(level); 229 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type); 230 { 231 base::AutoLock lock_for_texture_access(namespace_->lock); 232 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format); 233 } 234 ASSERT_TRUE(pixels); 235 SetPixels(xoffset, yoffset, width, height, pixels); 236 } 237 238 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE { 239 return shared_data_->GenMailbox(mailbox); 240 } 241 242 virtual void produceTextureCHROMIUM(GLenum target, 243 const GLbyte* mailbox) OVERRIDE { 244 CheckTextureIsBound(target); 245 246 // Delay moving the texture into the mailbox until the next 247 // InsertSyncPoint, so that it is not visible to other contexts that 248 // haven't waited on that sync point. 249 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture); 250 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox)); 251 base::AutoLock lock_for_texture_access(namespace_->lock); 252 pending->texture = BoundTexture(target); 253 pending_produce_textures_.push_back(pending.Pass()); 254 } 255 256 virtual void consumeTextureCHROMIUM(GLenum target, 257 const GLbyte* mailbox) OVERRIDE { 258 CheckTextureIsBound(target); 259 base::AutoLock lock_for_texture_access(namespace_->lock); 260 scoped_refptr<TestTexture> texture = 261 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_); 262 namespace_->textures.Replace(BoundTextureId(target), texture); 263 } 264 265 void GetPixels(gfx::Size size, ResourceFormat format, uint8_t* pixels) { 266 CheckTextureIsBound(GL_TEXTURE_2D); 267 base::AutoLock lock_for_texture_access(namespace_->lock); 268 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); 269 ASSERT_EQ(texture->size, size); 270 ASSERT_EQ(texture->format, format); 271 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format)); 272 } 273 274 protected: 275 explicit ResourceProviderContext(ContextSharedData* shared_data) 276 : shared_data_(shared_data), 277 last_waited_sync_point_(0) {} 278 279 private: 280 void AllocateTexture(gfx::Size size, GLenum format) { 281 CheckTextureIsBound(GL_TEXTURE_2D); 282 ResourceFormat texture_format = RGBA_8888; 283 switch (format) { 284 case GL_RGBA: 285 texture_format = RGBA_8888; 286 break; 287 case GL_BGRA_EXT: 288 texture_format = BGRA_8888; 289 break; 290 } 291 base::AutoLock lock_for_texture_access(namespace_->lock); 292 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format); 293 } 294 295 void SetPixels(int xoffset, 296 int yoffset, 297 int width, 298 int height, 299 const void* pixels) { 300 CheckTextureIsBound(GL_TEXTURE_2D); 301 base::AutoLock lock_for_texture_access(namespace_->lock); 302 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D); 303 ASSERT_TRUE(texture->data.get()); 304 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width()); 305 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height()); 306 ASSERT_TRUE(pixels); 307 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format); 308 size_t out_pitch = 309 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format); 310 uint8_t* dest = texture->data.get() + yoffset * out_pitch + 311 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format); 312 const uint8_t* src = static_cast<const uint8_t*>(pixels); 313 for (int i = 0; i < height; ++i) { 314 memcpy(dest, src, in_pitch); 315 dest += out_pitch; 316 src += in_pitch; 317 } 318 } 319 320 struct PendingProduceTexture { 321 GLbyte mailbox[64]; 322 scoped_refptr<TestTexture> texture; 323 }; 324 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList; 325 ContextSharedData* shared_data_; 326 unsigned last_waited_sync_point_; 327 PendingProduceTextureList pending_produce_textures_; 328}; 329 330void FreeSharedBitmap(SharedBitmap* shared_bitmap) { 331 delete shared_bitmap->memory(); 332} 333 334void IgnoreSharedBitmap(SharedBitmap* shared_bitmap) {} 335 336class TestSharedBitmapManager : public SharedBitmapManager { 337 public: 338 TestSharedBitmapManager() : count_(0) {} 339 virtual ~TestSharedBitmapManager() {} 340 341 virtual scoped_ptr<SharedBitmap> AllocateSharedBitmap(gfx::Size size) 342 OVERRIDE { 343 scoped_ptr<base::SharedMemory> memory(new base::SharedMemory); 344 memory->CreateAndMapAnonymous(size.GetArea() * 4); 345 int8 name[64] = { 0 }; 346 name[0] = count_++; 347 SharedBitmapId id; 348 id.SetName(name); 349 bitmap_map_[id] = memory.get(); 350 return scoped_ptr<SharedBitmap>( 351 new SharedBitmap(memory.release(), id, base::Bind(&FreeSharedBitmap))); 352 } 353 354 virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId( 355 gfx::Size, 356 const SharedBitmapId& id) OVERRIDE { 357 if (bitmap_map_.find(id) == bitmap_map_.end()) 358 return scoped_ptr<SharedBitmap>(); 359 return scoped_ptr<SharedBitmap>( 360 new SharedBitmap(bitmap_map_[id], id, base::Bind(&IgnoreSharedBitmap))); 361 } 362 363 virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory( 364 base::SharedMemory* memory) OVERRIDE { 365 int8 name[64] = { 0 }; 366 name[0] = count_++; 367 SharedBitmapId id; 368 id.SetName(name); 369 bitmap_map_[id] = memory; 370 return scoped_ptr<SharedBitmap>( 371 new SharedBitmap(memory, id, base::Bind(&IgnoreSharedBitmap))); 372 } 373 374 private: 375 int count_; 376 std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_; 377}; 378 379void GetResourcePixels(ResourceProvider* resource_provider, 380 ResourceProviderContext* context, 381 ResourceProvider::ResourceId id, 382 gfx::Size size, 383 ResourceFormat format, 384 uint8_t* pixels) { 385 switch (resource_provider->default_resource_type()) { 386 case ResourceProvider::GLTexture: { 387 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id); 388 ASSERT_NE(0U, lock_gl.texture_id()); 389 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id()); 390 context->GetPixels(size, format, pixels); 391 break; 392 } 393 case ResourceProvider::Bitmap: { 394 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider, 395 id); 396 memcpy(pixels, 397 lock_software.sk_bitmap()->getPixels(), 398 lock_software.sk_bitmap()->getSize()); 399 break; 400 } 401 case ResourceProvider::InvalidType: 402 NOTREACHED(); 403 break; 404 } 405} 406 407class ResourceProviderTest 408 : public testing::TestWithParam<ResourceProvider::ResourceType> { 409 public: 410 ResourceProviderTest() 411 : shared_data_(ContextSharedData::Create()), 412 context3d_(NULL), 413 child_context_(NULL) { 414 switch (GetParam()) { 415 case ResourceProvider::GLTexture: { 416 scoped_ptr<ResourceProviderContext> context3d( 417 ResourceProviderContext::Create(shared_data_.get())); 418 context3d_ = context3d.get(); 419 420 scoped_refptr<TestContextProvider> context_provider = 421 TestContextProvider::Create( 422 context3d.PassAs<TestWebGraphicsContext3D>()); 423 424 output_surface_ = FakeOutputSurface::Create3d(context_provider); 425 426 scoped_ptr<ResourceProviderContext> child_context_owned = 427 ResourceProviderContext::Create(shared_data_.get()); 428 child_context_ = child_context_owned.get(); 429 child_output_surface_ = FakeOutputSurface::Create3d( 430 child_context_owned.PassAs<TestWebGraphicsContext3D>()); 431 break; 432 } 433 case ResourceProvider::Bitmap: 434 output_surface_ = FakeOutputSurface::CreateSoftware( 435 make_scoped_ptr(new SoftwareOutputDevice)); 436 child_output_surface_ = FakeOutputSurface::CreateSoftware( 437 make_scoped_ptr(new SoftwareOutputDevice)); 438 break; 439 case ResourceProvider::InvalidType: 440 NOTREACHED(); 441 break; 442 } 443 CHECK(output_surface_->BindToClient(&output_surface_client_)); 444 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_)); 445 446 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); 447 448 resource_provider_ = ResourceProvider::Create( 449 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1); 450 child_resource_provider_ = ResourceProvider::Create( 451 child_output_surface_.get(), 452 shared_bitmap_manager_.get(), 453 0, 454 false, 455 1); 456 } 457 458 static void CollectResources(ReturnedResourceArray* array, 459 const ReturnedResourceArray& returned) { 460 array->insert(array->end(), returned.begin(), returned.end()); 461 } 462 463 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) { 464 return base::Bind(&ResourceProviderTest::CollectResources, array); 465 } 466 467 static void SetResourceFilter(ResourceProvider* resource_provider, 468 ResourceProvider::ResourceId id, 469 GLenum filter) { 470 ResourceProvider::ScopedSamplerGL sampler( 471 resource_provider, id, GL_TEXTURE_2D, filter); 472 } 473 474 ResourceProviderContext* context() { return context3d_; } 475 476 ResourceProvider::ResourceId CreateChildMailbox(unsigned* release_sync_point, 477 bool* lost_resource, 478 bool* release_called, 479 unsigned* sync_point) { 480 if (GetParam() == ResourceProvider::GLTexture) { 481 unsigned texture = child_context_->createTexture(); 482 gpu::Mailbox gpu_mailbox; 483 child_context_->bindTexture(GL_TEXTURE_2D, texture); 484 child_context_->genMailboxCHROMIUM(gpu_mailbox.name); 485 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name); 486 *sync_point = child_context_->insertSyncPoint(); 487 EXPECT_LT(0u, *sync_point); 488 489 scoped_ptr<base::SharedMemory> shared_memory; 490 scoped_ptr<SingleReleaseCallback> callback = 491 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback, 492 base::Passed(&shared_memory), 493 release_called, 494 release_sync_point, 495 lost_resource)); 496 return child_resource_provider_->CreateResourceFromTextureMailbox( 497 TextureMailbox(gpu_mailbox, *sync_point), callback.Pass()); 498 } else { 499 gfx::Size size(64, 64); 500 scoped_ptr<base::SharedMemory> shared_memory( 501 CreateAndFillSharedMemory(size, 0)); 502 503 base::SharedMemory* shared_memory_ptr = shared_memory.get(); 504 scoped_ptr<SingleReleaseCallback> callback = 505 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback, 506 base::Passed(&shared_memory), 507 release_called, 508 release_sync_point, 509 lost_resource)); 510 return child_resource_provider_->CreateResourceFromTextureMailbox( 511 TextureMailbox(shared_memory_ptr, size), callback.Pass()); 512 } 513 } 514 515 protected: 516 scoped_ptr<ContextSharedData> shared_data_; 517 ResourceProviderContext* context3d_; 518 ResourceProviderContext* child_context_; 519 FakeOutputSurfaceClient output_surface_client_; 520 FakeOutputSurfaceClient child_output_surface_client_; 521 scoped_ptr<OutputSurface> output_surface_; 522 scoped_ptr<OutputSurface> child_output_surface_; 523 scoped_ptr<ResourceProvider> resource_provider_; 524 scoped_ptr<ResourceProvider> child_resource_provider_; 525 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_; 526}; 527 528void CheckCreateResource(ResourceProvider::ResourceType expected_default_type, 529 ResourceProvider* resource_provider, 530 ResourceProviderContext* context) { 531 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type()); 532 533 gfx::Size size(1, 1); 534 ResourceFormat format = RGBA_8888; 535 size_t pixel_size = TextureSizeBytes(size, format); 536 ASSERT_EQ(4U, pixel_size); 537 538 ResourceProvider::ResourceId id = resource_provider->CreateResource( 539 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 540 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources())); 541 if (expected_default_type == ResourceProvider::GLTexture) 542 EXPECT_EQ(0u, context->NumTextures()); 543 544 uint8_t data[4] = { 1, 2, 3, 4 }; 545 gfx::Rect rect(size); 546 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d()); 547 if (expected_default_type == ResourceProvider::GLTexture) 548 EXPECT_EQ(1u, context->NumTextures()); 549 550 uint8_t result[4] = { 0 }; 551 GetResourcePixels(resource_provider, context, id, size, format, result); 552 EXPECT_EQ(0, memcmp(data, result, pixel_size)); 553 554 resource_provider->DeleteResource(id); 555 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources())); 556 if (expected_default_type == ResourceProvider::GLTexture) 557 EXPECT_EQ(0u, context->NumTextures()); 558} 559 560TEST_P(ResourceProviderTest, Basic) { 561 CheckCreateResource(GetParam(), resource_provider_.get(), context()); 562} 563 564TEST_P(ResourceProviderTest, Upload) { 565 gfx::Size size(2, 2); 566 ResourceFormat format = RGBA_8888; 567 size_t pixel_size = TextureSizeBytes(size, format); 568 ASSERT_EQ(16U, pixel_size); 569 570 ResourceProvider::ResourceId id = resource_provider_->CreateResource( 571 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 572 573 uint8_t image[16] = { 0 }; 574 gfx::Rect image_rect(size); 575 resource_provider_->SetPixels( 576 id, image, image_rect, image_rect, gfx::Vector2d()); 577 578 for (uint8_t i = 0; i < pixel_size; ++i) 579 image[i] = i; 580 581 uint8_t result[16] = { 0 }; 582 { 583 gfx::Rect source_rect(0, 0, 1, 1); 584 gfx::Vector2d dest_offset(0, 0); 585 resource_provider_->SetPixels( 586 id, image, image_rect, source_rect, dest_offset); 587 588 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 589 GetResourcePixels( 590 resource_provider_.get(), context(), id, size, format, result); 591 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); 592 } 593 { 594 gfx::Rect source_rect(0, 0, 1, 1); 595 gfx::Vector2d dest_offset(1, 1); 596 resource_provider_->SetPixels( 597 id, image, image_rect, source_rect, dest_offset); 598 599 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 }; 600 GetResourcePixels( 601 resource_provider_.get(), context(), id, size, format, result); 602 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); 603 } 604 { 605 gfx::Rect source_rect(1, 0, 1, 1); 606 gfx::Vector2d dest_offset(0, 1); 607 resource_provider_->SetPixels( 608 id, image, image_rect, source_rect, dest_offset); 609 610 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 }; 611 GetResourcePixels( 612 resource_provider_.get(), context(), id, size, format, result); 613 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); 614 } 615 { 616 gfx::Rect offset_image_rect(gfx::Point(100, 100), size); 617 gfx::Rect source_rect(100, 100, 1, 1); 618 gfx::Vector2d dest_offset(1, 0); 619 resource_provider_->SetPixels( 620 id, image, offset_image_rect, source_rect, dest_offset); 621 622 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 }; 623 GetResourcePixels( 624 resource_provider_.get(), context(), id, size, format, result); 625 EXPECT_EQ(0, memcmp(expected, result, pixel_size)); 626 } 627 628 resource_provider_->DeleteResource(id); 629} 630 631TEST_P(ResourceProviderTest, TransferGLResources) { 632 if (GetParam() != ResourceProvider::GLTexture) 633 return; 634 gfx::Size size(1, 1); 635 ResourceFormat format = RGBA_8888; 636 size_t pixel_size = TextureSizeBytes(size, format); 637 ASSERT_EQ(4U, pixel_size); 638 639 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( 640 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 641 uint8_t data1[4] = { 1, 2, 3, 4 }; 642 gfx::Rect rect(size); 643 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 644 645 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( 646 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 647 uint8_t data2[4] = { 5, 5, 5, 5 }; 648 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); 649 650 GLuint external_texture_id = child_context_->createExternalTexture(); 651 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id); 652 653 gpu::Mailbox external_mailbox; 654 child_context_->genMailboxCHROMIUM(external_mailbox.name); 655 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES, 656 external_mailbox.name); 657 const unsigned external_sync_point = child_context_->insertSyncPoint(); 658 ResourceProvider::ResourceId id3 = 659 child_resource_provider_->CreateResourceFromTextureMailbox( 660 TextureMailbox( 661 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point), 662 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback))); 663 664 ReturnedResourceArray returned_to_child; 665 int child_id = 666 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 667 { 668 // Transfer some resources to the parent. 669 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 670 resource_ids_to_transfer.push_back(id1); 671 resource_ids_to_transfer.push_back(id2); 672 resource_ids_to_transfer.push_back(id3); 673 TransferableResourceArray list; 674 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 675 &list); 676 ASSERT_EQ(3u, list.size()); 677 EXPECT_NE(0u, list[0].sync_point); 678 EXPECT_NE(0u, list[1].sync_point); 679 EXPECT_EQ(external_sync_point, list[2].sync_point); 680 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); 681 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target); 682 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target); 683 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 684 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 685 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); 686 resource_provider_->ReceiveFromChild(child_id, list); 687 resource_provider_->DeclareUsedResourcesFromChild(child_id, 688 resource_ids_to_transfer); 689 } 690 691 EXPECT_EQ(3u, resource_provider_->num_resources()); 692 ResourceProvider::ResourceIdMap resource_map = 693 resource_provider_->GetChildToParentMap(child_id); 694 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 695 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; 696 ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; 697 EXPECT_NE(0u, mapped_id1); 698 EXPECT_NE(0u, mapped_id2); 699 EXPECT_NE(0u, mapped_id3); 700 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); 701 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); 702 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3)); 703 704 uint8_t result[4] = { 0 }; 705 GetResourcePixels( 706 resource_provider_.get(), context(), mapped_id1, size, format, result); 707 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); 708 709 GetResourcePixels( 710 resource_provider_.get(), context(), mapped_id2, size, format, result); 711 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); 712 713 { 714 // Check that transfering again the same resource from the child to the 715 // parent works. 716 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 717 resource_ids_to_transfer.push_back(id1); 718 TransferableResourceArray list; 719 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 720 &list); 721 EXPECT_EQ(1u, list.size()); 722 EXPECT_EQ(id1, list[0].id); 723 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); 724 ReturnedResourceArray returned; 725 TransferableResource::ReturnResources(list, &returned); 726 child_resource_provider_->ReceiveReturnsFromParent(returned); 727 // id1 was exported twice, we returned it only once, it should still be 728 // in-use. 729 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 730 } 731 { 732 EXPECT_EQ(0u, returned_to_child.size()); 733 734 // Transfer resources back from the parent to the child. Set no resources as 735 // being in use. 736 ResourceProvider::ResourceIdArray no_resources; 737 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 738 739 ASSERT_EQ(3u, returned_to_child.size()); 740 EXPECT_NE(0u, returned_to_child[0].sync_point); 741 EXPECT_NE(0u, returned_to_child[1].sync_point); 742 EXPECT_NE(0u, returned_to_child[2].sync_point); 743 EXPECT_FALSE(returned_to_child[0].lost); 744 EXPECT_FALSE(returned_to_child[1].lost); 745 EXPECT_FALSE(returned_to_child[2].lost); 746 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 747 returned_to_child.clear(); 748 } 749 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); 750 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); 751 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); 752 753 { 754 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), 755 id1); 756 ASSERT_NE(0U, lock.texture_id()); 757 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); 758 child_context_->GetPixels(size, format, result); 759 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); 760 } 761 { 762 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(), 763 id2); 764 ASSERT_NE(0U, lock.texture_id()); 765 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id()); 766 child_context_->GetPixels(size, format, result); 767 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); 768 } 769 { 770 // Transfer resources to the parent again. 771 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 772 resource_ids_to_transfer.push_back(id1); 773 resource_ids_to_transfer.push_back(id2); 774 resource_ids_to_transfer.push_back(id3); 775 TransferableResourceArray list; 776 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 777 &list); 778 ASSERT_EQ(3u, list.size()); 779 EXPECT_EQ(id1, list[0].id); 780 EXPECT_EQ(id2, list[1].id); 781 EXPECT_EQ(id3, list[2].id); 782 EXPECT_NE(0u, list[0].sync_point); 783 EXPECT_NE(0u, list[1].sync_point); 784 EXPECT_NE(0u, list[2].sync_point); 785 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); 786 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[1].target); 787 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), list[2].target); 788 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 789 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 790 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); 791 resource_provider_->ReceiveFromChild(child_id, list); 792 resource_provider_->DeclareUsedResourcesFromChild(child_id, 793 resource_ids_to_transfer); 794 } 795 796 EXPECT_EQ(0u, returned_to_child.size()); 797 798 EXPECT_EQ(3u, resource_provider_->num_resources()); 799 resource_provider_->DestroyChild(child_id); 800 EXPECT_EQ(0u, resource_provider_->num_resources()); 801 802 ASSERT_EQ(3u, returned_to_child.size()); 803 EXPECT_NE(0u, returned_to_child[0].sync_point); 804 EXPECT_NE(0u, returned_to_child[1].sync_point); 805 EXPECT_NE(0u, returned_to_child[2].sync_point); 806 EXPECT_FALSE(returned_to_child[0].lost); 807 EXPECT_FALSE(returned_to_child[1].lost); 808 EXPECT_FALSE(returned_to_child[2].lost); 809} 810 811TEST_P(ResourceProviderTest, TransferSoftwareResources) { 812 if (GetParam() != ResourceProvider::Bitmap) 813 return; 814 815 gfx::Size size(1, 1); 816 ResourceFormat format = RGBA_8888; 817 size_t pixel_size = TextureSizeBytes(size, format); 818 ASSERT_EQ(4U, pixel_size); 819 820 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( 821 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 822 uint8_t data1[4] = { 1, 2, 3, 4 }; 823 gfx::Rect rect(size); 824 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 825 826 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( 827 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 828 uint8_t data2[4] = { 5, 5, 5, 5 }; 829 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); 830 831 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); 832 shared_memory->CreateAndMapAnonymous(1); 833 base::SharedMemory* shared_memory_ptr = shared_memory.get(); 834 ResourceProvider::ResourceId id3 = 835 child_resource_provider_->CreateResourceFromTextureMailbox( 836 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)), 837 SingleReleaseCallback::Create(base::Bind( 838 &SharedMemoryReleaseCallback, base::Passed(&shared_memory)))); 839 840 ReturnedResourceArray returned_to_child; 841 int child_id = 842 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 843 { 844 // Transfer some resources to the parent. 845 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 846 resource_ids_to_transfer.push_back(id1); 847 resource_ids_to_transfer.push_back(id2); 848 resource_ids_to_transfer.push_back(id3); 849 TransferableResourceArray list; 850 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 851 &list); 852 ASSERT_EQ(3u, list.size()); 853 EXPECT_EQ(0u, list[0].sync_point); 854 EXPECT_EQ(0u, list[1].sync_point); 855 EXPECT_EQ(0u, list[2].sync_point); 856 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 857 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 858 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); 859 resource_provider_->ReceiveFromChild(child_id, list); 860 resource_provider_->DeclareUsedResourcesFromChild(child_id, 861 resource_ids_to_transfer); 862 } 863 864 EXPECT_EQ(3u, resource_provider_->num_resources()); 865 ResourceProvider::ResourceIdMap resource_map = 866 resource_provider_->GetChildToParentMap(child_id); 867 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 868 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; 869 ResourceProvider::ResourceId mapped_id3 = resource_map[id3]; 870 EXPECT_NE(0u, mapped_id1); 871 EXPECT_NE(0u, mapped_id2); 872 EXPECT_NE(0u, mapped_id3); 873 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); 874 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); 875 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3)); 876 877 uint8_t result[4] = { 0 }; 878 GetResourcePixels( 879 resource_provider_.get(), context(), mapped_id1, size, format, result); 880 EXPECT_EQ(0, memcmp(data1, result, pixel_size)); 881 882 GetResourcePixels( 883 resource_provider_.get(), context(), mapped_id2, size, format, result); 884 EXPECT_EQ(0, memcmp(data2, result, pixel_size)); 885 886 { 887 // Check that transfering again the same resource from the child to the 888 // parent works. 889 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 890 resource_ids_to_transfer.push_back(id1); 891 TransferableResourceArray list; 892 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 893 &list); 894 EXPECT_EQ(1u, list.size()); 895 EXPECT_EQ(id1, list[0].id); 896 ReturnedResourceArray returned; 897 TransferableResource::ReturnResources(list, &returned); 898 child_resource_provider_->ReceiveReturnsFromParent(returned); 899 // id1 was exported twice, we returned it only once, it should still be 900 // in-use. 901 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 902 } 903 { 904 EXPECT_EQ(0u, returned_to_child.size()); 905 906 // Transfer resources back from the parent to the child. Set no resources as 907 // being in use. 908 ResourceProvider::ResourceIdArray no_resources; 909 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 910 911 ASSERT_EQ(3u, returned_to_child.size()); 912 EXPECT_EQ(0u, returned_to_child[0].sync_point); 913 EXPECT_EQ(0u, returned_to_child[1].sync_point); 914 EXPECT_EQ(0u, returned_to_child[2].sync_point); 915 EXPECT_EQ(id1, returned_to_child[0].id); 916 EXPECT_EQ(id2, returned_to_child[1].id); 917 EXPECT_EQ(id3, returned_to_child[2].id); 918 EXPECT_FALSE(returned_to_child[0].lost); 919 EXPECT_FALSE(returned_to_child[1].lost); 920 EXPECT_FALSE(returned_to_child[2].lost); 921 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 922 returned_to_child.clear(); 923 } 924 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1)); 925 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2)); 926 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3)); 927 928 { 929 ResourceProvider::ScopedReadLockSoftware lock( 930 child_resource_provider_.get(), id1); 931 const SkBitmap* sk_bitmap = lock.sk_bitmap(); 932 EXPECT_EQ(sk_bitmap->width(), size.width()); 933 EXPECT_EQ(sk_bitmap->height(), size.height()); 934 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size)); 935 } 936 { 937 ResourceProvider::ScopedReadLockSoftware lock( 938 child_resource_provider_.get(), id2); 939 const SkBitmap* sk_bitmap = lock.sk_bitmap(); 940 EXPECT_EQ(sk_bitmap->width(), size.width()); 941 EXPECT_EQ(sk_bitmap->height(), size.height()); 942 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size)); 943 } 944 { 945 // Transfer resources to the parent again. 946 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 947 resource_ids_to_transfer.push_back(id1); 948 resource_ids_to_transfer.push_back(id2); 949 resource_ids_to_transfer.push_back(id3); 950 TransferableResourceArray list; 951 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 952 &list); 953 ASSERT_EQ(3u, list.size()); 954 EXPECT_EQ(id1, list[0].id); 955 EXPECT_EQ(id2, list[1].id); 956 EXPECT_EQ(id3, list[2].id); 957 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 958 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 959 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3)); 960 resource_provider_->ReceiveFromChild(child_id, list); 961 resource_provider_->DeclareUsedResourcesFromChild(child_id, 962 resource_ids_to_transfer); 963 } 964 965 EXPECT_EQ(0u, returned_to_child.size()); 966 967 EXPECT_EQ(3u, resource_provider_->num_resources()); 968 resource_provider_->DestroyChild(child_id); 969 EXPECT_EQ(0u, resource_provider_->num_resources()); 970 971 ASSERT_EQ(3u, returned_to_child.size()); 972 EXPECT_EQ(0u, returned_to_child[0].sync_point); 973 EXPECT_EQ(0u, returned_to_child[1].sync_point); 974 EXPECT_EQ(0u, returned_to_child[2].sync_point); 975 EXPECT_EQ(id1, returned_to_child[0].id); 976 EXPECT_EQ(id2, returned_to_child[1].id); 977 EXPECT_EQ(id3, returned_to_child[2].id); 978 EXPECT_FALSE(returned_to_child[0].lost); 979 EXPECT_FALSE(returned_to_child[1].lost); 980 EXPECT_FALSE(returned_to_child[2].lost); 981} 982 983TEST_P(ResourceProviderTest, TransferSoftwareToNonUber) { 984 // TODO(jbauman): Remove test when shared bitmap manager available 985 // everywhere. 986 if (GetParam() != ResourceProvider::Bitmap) 987 return; 988 989 scoped_ptr<FakeOutputSurface> parent_output_surface = 990 FakeOutputSurface::CreateSoftware( 991 make_scoped_ptr(new SoftwareOutputDevice)); 992 FakeOutputSurfaceClient parent_output_surface_client; 993 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client)); 994 995 scoped_ptr<ResourceProvider> parent_resource_provider( 996 ResourceProvider::Create(parent_output_surface.get(), 997 NULL, 998 0, 999 false, 1000 1)); 1001 1002 gfx::Size size(1, 1); 1003 ResourceFormat format = RGBA_8888; 1004 size_t pixel_size = TextureSizeBytes(size, format); 1005 ASSERT_EQ(4U, pixel_size); 1006 1007 ResourceProvider::ResourceId id1 = resource_provider_->CreateResource( 1008 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1009 uint8_t data1[4] = { 1, 2, 3, 4 }; 1010 gfx::Rect rect(size); 1011 resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 1012 1013 ReturnedResourceArray returned_to_child; 1014 int child_id = parent_resource_provider->CreateChild( 1015 GetReturnCallback(&returned_to_child)); 1016 { 1017 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1018 resource_ids_to_transfer.push_back(id1); 1019 TransferableResourceArray list; 1020 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1021 ASSERT_EQ(1u, list.size()); 1022 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); 1023 parent_resource_provider->ReceiveFromChild(child_id, list); 1024 } 1025 1026 EXPECT_EQ(0u, parent_resource_provider->num_resources()); 1027 ASSERT_EQ(1u, returned_to_child.size()); 1028 EXPECT_EQ(returned_to_child[0].id, id1); 1029 ResourceProvider::ResourceIdMap resource_map = 1030 parent_resource_provider->GetChildToParentMap(child_id); 1031 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 1032 EXPECT_EQ(0u, mapped_id1); 1033 1034 parent_resource_provider->DestroyChild(child_id); 1035 EXPECT_EQ(0u, parent_resource_provider->num_resources()); 1036 1037 ASSERT_EQ(1u, returned_to_child.size()); 1038 EXPECT_FALSE(returned_to_child[0].lost); 1039} 1040 1041TEST_P(ResourceProviderTest, TransferGLToSoftware) { 1042 if (GetParam() != ResourceProvider::Bitmap) 1043 return; 1044 1045 scoped_ptr<ResourceProviderContext> child_context_owned( 1046 ResourceProviderContext::Create(shared_data_.get())); 1047 1048 FakeOutputSurfaceClient child_output_surface_client; 1049 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( 1050 child_context_owned.PassAs<TestWebGraphicsContext3D>())); 1051 CHECK(child_output_surface->BindToClient(&child_output_surface_client)); 1052 1053 scoped_ptr<ResourceProvider> child_resource_provider( 1054 ResourceProvider::Create(child_output_surface.get(), 1055 NULL, 1056 0, 1057 false, 1058 1)); 1059 1060 gfx::Size size(1, 1); 1061 ResourceFormat format = RGBA_8888; 1062 size_t pixel_size = TextureSizeBytes(size, format); 1063 ASSERT_EQ(4U, pixel_size); 1064 1065 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource( 1066 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1067 uint8_t data1[4] = { 1, 2, 3, 4 }; 1068 gfx::Rect rect(size); 1069 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 1070 1071 ReturnedResourceArray returned_to_child; 1072 int child_id = 1073 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1074 { 1075 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1076 resource_ids_to_transfer.push_back(id1); 1077 TransferableResourceArray list; 1078 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, 1079 &list); 1080 ASSERT_EQ(1u, list.size()); 1081 EXPECT_NE(0u, list[0].sync_point); 1082 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D), list[0].target); 1083 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1)); 1084 resource_provider_->ReceiveFromChild(child_id, list); 1085 } 1086 1087 EXPECT_EQ(0u, resource_provider_->num_resources()); 1088 ASSERT_EQ(1u, returned_to_child.size()); 1089 EXPECT_EQ(returned_to_child[0].id, id1); 1090 ResourceProvider::ResourceIdMap resource_map = 1091 resource_provider_->GetChildToParentMap(child_id); 1092 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 1093 EXPECT_EQ(0u, mapped_id1); 1094 1095 resource_provider_->DestroyChild(child_id); 1096 EXPECT_EQ(0u, resource_provider_->num_resources()); 1097 1098 ASSERT_EQ(1u, returned_to_child.size()); 1099 EXPECT_FALSE(returned_to_child[0].lost); 1100} 1101 1102TEST_P(ResourceProviderTest, TransferInvalidSoftware) { 1103 if (GetParam() != ResourceProvider::Bitmap) 1104 return; 1105 1106 gfx::Size size(1, 1); 1107 ResourceFormat format = RGBA_8888; 1108 size_t pixel_size = TextureSizeBytes(size, format); 1109 ASSERT_EQ(4U, pixel_size); 1110 1111 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( 1112 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1113 uint8_t data1[4] = { 1, 2, 3, 4 }; 1114 gfx::Rect rect(size); 1115 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 1116 1117 ReturnedResourceArray returned_to_child; 1118 int child_id = 1119 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1120 { 1121 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1122 resource_ids_to_transfer.push_back(id1); 1123 TransferableResourceArray list; 1124 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1125 &list); 1126 ASSERT_EQ(1u, list.size()); 1127 // Make invalid. 1128 list[0].mailbox.name[1] = 5; 1129 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 1130 resource_provider_->ReceiveFromChild(child_id, list); 1131 } 1132 1133 EXPECT_EQ(0u, resource_provider_->num_resources()); 1134 ASSERT_EQ(1u, returned_to_child.size()); 1135 EXPECT_EQ(returned_to_child[0].id, id1); 1136 ResourceProvider::ResourceIdMap resource_map = 1137 resource_provider_->GetChildToParentMap(child_id); 1138 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 1139 EXPECT_EQ(0u, mapped_id1); 1140 1141 resource_provider_->DestroyChild(child_id); 1142 EXPECT_EQ(0u, resource_provider_->num_resources()); 1143 1144 ASSERT_EQ(1u, returned_to_child.size()); 1145 EXPECT_FALSE(returned_to_child[0].lost); 1146} 1147 1148TEST_P(ResourceProviderTest, DeleteExportedResources) { 1149 gfx::Size size(1, 1); 1150 ResourceFormat format = RGBA_8888; 1151 size_t pixel_size = TextureSizeBytes(size, format); 1152 ASSERT_EQ(4U, pixel_size); 1153 1154 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( 1155 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1156 uint8_t data1[4] = { 1, 2, 3, 4 }; 1157 gfx::Rect rect(size); 1158 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 1159 1160 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( 1161 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1162 uint8_t data2[4] = {5, 5, 5, 5}; 1163 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); 1164 1165 ReturnedResourceArray returned_to_child; 1166 int child_id = 1167 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1168 { 1169 // Transfer some resources to the parent. 1170 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1171 resource_ids_to_transfer.push_back(id1); 1172 resource_ids_to_transfer.push_back(id2); 1173 TransferableResourceArray list; 1174 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1175 &list); 1176 ASSERT_EQ(2u, list.size()); 1177 if (GetParam() == ResourceProvider::GLTexture) { 1178 EXPECT_NE(0u, list[0].sync_point); 1179 EXPECT_NE(0u, list[1].sync_point); 1180 } 1181 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 1182 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 1183 resource_provider_->ReceiveFromChild(child_id, list); 1184 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1185 resource_ids_to_transfer); 1186 } 1187 1188 EXPECT_EQ(2u, resource_provider_->num_resources()); 1189 ResourceProvider::ResourceIdMap resource_map = 1190 resource_provider_->GetChildToParentMap(child_id); 1191 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 1192 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; 1193 EXPECT_NE(0u, mapped_id1); 1194 EXPECT_NE(0u, mapped_id2); 1195 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); 1196 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); 1197 1198 { 1199 // The parent transfers the resources to the grandparent. 1200 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1201 resource_ids_to_transfer.push_back(mapped_id1); 1202 resource_ids_to_transfer.push_back(mapped_id2); 1203 TransferableResourceArray list; 1204 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1205 1206 ASSERT_EQ(2u, list.size()); 1207 if (GetParam() == ResourceProvider::GLTexture) { 1208 EXPECT_NE(0u, list[0].sync_point); 1209 EXPECT_NE(0u, list[1].sync_point); 1210 } 1211 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); 1212 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); 1213 1214 // Release the resource in the parent. Set no resources as being in use. The 1215 // resources are exported so that can't be transferred back yet. 1216 ResourceProvider::ResourceIdArray no_resources; 1217 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1218 1219 EXPECT_EQ(0u, returned_to_child.size()); 1220 EXPECT_EQ(2u, resource_provider_->num_resources()); 1221 1222 // Return the resources from the grandparent to the parent. They should be 1223 // returned to the child then. 1224 EXPECT_EQ(2u, list.size()); 1225 EXPECT_EQ(mapped_id1, list[0].id); 1226 EXPECT_EQ(mapped_id2, list[1].id); 1227 ReturnedResourceArray returned; 1228 TransferableResource::ReturnResources(list, &returned); 1229 resource_provider_->ReceiveReturnsFromParent(returned); 1230 1231 EXPECT_EQ(0u, resource_provider_->num_resources()); 1232 ASSERT_EQ(2u, returned_to_child.size()); 1233 if (GetParam() == ResourceProvider::GLTexture) { 1234 EXPECT_NE(0u, returned_to_child[0].sync_point); 1235 EXPECT_NE(0u, returned_to_child[1].sync_point); 1236 } 1237 EXPECT_FALSE(returned_to_child[0].lost); 1238 EXPECT_FALSE(returned_to_child[1].lost); 1239 } 1240} 1241 1242TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) { 1243 gfx::Size size(1, 1); 1244 ResourceFormat format = RGBA_8888; 1245 size_t pixel_size = TextureSizeBytes(size, format); 1246 ASSERT_EQ(4U, pixel_size); 1247 1248 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource( 1249 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1250 uint8_t data1[4] = {1, 2, 3, 4}; 1251 gfx::Rect rect(size); 1252 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d()); 1253 1254 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource( 1255 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1256 uint8_t data2[4] = {5, 5, 5, 5}; 1257 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); 1258 1259 ReturnedResourceArray returned_to_child; 1260 int child_id = 1261 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1262 { 1263 // Transfer some resources to the parent. 1264 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1265 resource_ids_to_transfer.push_back(id1); 1266 resource_ids_to_transfer.push_back(id2); 1267 TransferableResourceArray list; 1268 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1269 &list); 1270 ASSERT_EQ(2u, list.size()); 1271 if (GetParam() == ResourceProvider::GLTexture) { 1272 EXPECT_NE(0u, list[0].sync_point); 1273 EXPECT_NE(0u, list[1].sync_point); 1274 } 1275 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1)); 1276 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2)); 1277 resource_provider_->ReceiveFromChild(child_id, list); 1278 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1279 resource_ids_to_transfer); 1280 } 1281 1282 EXPECT_EQ(2u, resource_provider_->num_resources()); 1283 ResourceProvider::ResourceIdMap resource_map = 1284 resource_provider_->GetChildToParentMap(child_id); 1285 ResourceProvider::ResourceId mapped_id1 = resource_map[id1]; 1286 ResourceProvider::ResourceId mapped_id2 = resource_map[id2]; 1287 EXPECT_NE(0u, mapped_id1); 1288 EXPECT_NE(0u, mapped_id2); 1289 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1)); 1290 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2)); 1291 1292 { 1293 // The parent transfers the resources to the grandparent. 1294 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1295 resource_ids_to_transfer.push_back(mapped_id1); 1296 resource_ids_to_transfer.push_back(mapped_id2); 1297 TransferableResourceArray list; 1298 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1299 1300 ASSERT_EQ(2u, list.size()); 1301 if (GetParam() == ResourceProvider::GLTexture) { 1302 EXPECT_NE(0u, list[0].sync_point); 1303 EXPECT_NE(0u, list[1].sync_point); 1304 } 1305 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1)); 1306 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2)); 1307 1308 // Release the resource in the parent. Set no resources as being in use. The 1309 // resources are exported so that can't be transferred back yet. 1310 ResourceProvider::ResourceIdArray no_resources; 1311 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1312 1313 // Destroy the child, the resources should not be returned yet. 1314 EXPECT_EQ(0u, returned_to_child.size()); 1315 EXPECT_EQ(2u, resource_provider_->num_resources()); 1316 1317 resource_provider_->DestroyChild(child_id); 1318 1319 EXPECT_EQ(2u, resource_provider_->num_resources()); 1320 ASSERT_EQ(0u, returned_to_child.size()); 1321 1322 // Return a resource from the grandparent, it should be returned at this 1323 // point. 1324 EXPECT_EQ(2u, list.size()); 1325 EXPECT_EQ(mapped_id1, list[0].id); 1326 EXPECT_EQ(mapped_id2, list[1].id); 1327 TransferableResourceArray return_list; 1328 return_list.push_back(list[1]); 1329 list.pop_back(); 1330 ReturnedResourceArray returned; 1331 TransferableResource::ReturnResources(return_list, &returned); 1332 resource_provider_->ReceiveReturnsFromParent(returned); 1333 1334 EXPECT_EQ(1u, resource_provider_->num_resources()); 1335 ASSERT_EQ(1u, returned_to_child.size()); 1336 if (GetParam() == ResourceProvider::GLTexture) { 1337 EXPECT_NE(0u, returned_to_child[0].sync_point); 1338 } 1339 EXPECT_FALSE(returned_to_child[0].lost); 1340 returned_to_child.clear(); 1341 1342 // Destroy the parent resource provider. The resource that's left should be 1343 // lost at this point, and returned. 1344 resource_provider_.reset(); 1345 ASSERT_EQ(1u, returned_to_child.size()); 1346 if (GetParam() == ResourceProvider::GLTexture) { 1347 EXPECT_NE(0u, returned_to_child[0].sync_point); 1348 } 1349 EXPECT_TRUE(returned_to_child[0].lost); 1350 } 1351} 1352 1353TEST_P(ResourceProviderTest, DeleteTransferredResources) { 1354 gfx::Size size(1, 1); 1355 ResourceFormat format = RGBA_8888; 1356 size_t pixel_size = TextureSizeBytes(size, format); 1357 ASSERT_EQ(4U, pixel_size); 1358 1359 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource( 1360 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1361 uint8_t data[4] = { 1, 2, 3, 4 }; 1362 gfx::Rect rect(size); 1363 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d()); 1364 1365 ReturnedResourceArray returned_to_child; 1366 int child_id = 1367 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1368 { 1369 // Transfer some resource to the parent. 1370 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1371 resource_ids_to_transfer.push_back(id); 1372 TransferableResourceArray list; 1373 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1374 &list); 1375 ASSERT_EQ(1u, list.size()); 1376 if (GetParam() == ResourceProvider::GLTexture) 1377 EXPECT_NE(0u, list[0].sync_point); 1378 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id)); 1379 resource_provider_->ReceiveFromChild(child_id, list); 1380 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1381 resource_ids_to_transfer); 1382 } 1383 1384 // Delete textures in the child, while they are transfered. 1385 child_resource_provider_->DeleteResource(id); 1386 EXPECT_EQ(1u, child_resource_provider_->num_resources()); 1387 { 1388 EXPECT_EQ(0u, returned_to_child.size()); 1389 1390 // Transfer resources back from the parent to the child. Set no resources as 1391 // being in use. 1392 ResourceProvider::ResourceIdArray no_resources; 1393 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1394 1395 ASSERT_EQ(1u, returned_to_child.size()); 1396 if (GetParam() == ResourceProvider::GLTexture) 1397 EXPECT_NE(0u, returned_to_child[0].sync_point); 1398 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 1399 } 1400 EXPECT_EQ(0u, child_resource_provider_->num_resources()); 1401} 1402 1403class ResourceProviderTestTextureFilters : public ResourceProviderTest { 1404 public: 1405 static void RunTest(GLenum child_filter, GLenum parent_filter) { 1406 scoped_ptr<TextureStateTrackingContext> child_context_owned( 1407 new TextureStateTrackingContext); 1408 TextureStateTrackingContext* child_context = child_context_owned.get(); 1409 1410 FakeOutputSurfaceClient child_output_surface_client; 1411 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d( 1412 child_context_owned.PassAs<TestWebGraphicsContext3D>())); 1413 CHECK(child_output_surface->BindToClient(&child_output_surface_client)); 1414 1415 scoped_ptr<ResourceProvider> child_resource_provider( 1416 ResourceProvider::Create(child_output_surface.get(), 1417 NULL, 1418 0, 1419 false, 1420 1)); 1421 1422 scoped_ptr<TextureStateTrackingContext> parent_context_owned( 1423 new TextureStateTrackingContext); 1424 TextureStateTrackingContext* parent_context = parent_context_owned.get(); 1425 1426 FakeOutputSurfaceClient parent_output_surface_client; 1427 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d( 1428 parent_context_owned.PassAs<TestWebGraphicsContext3D>())); 1429 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client)); 1430 1431 scoped_ptr<ResourceProvider> parent_resource_provider( 1432 ResourceProvider::Create(parent_output_surface.get(), 1433 NULL, 1434 0, 1435 false, 1436 1)); 1437 1438 gfx::Size size(1, 1); 1439 ResourceFormat format = RGBA_8888; 1440 int child_texture_id = 1; 1441 int parent_texture_id = 2; 1442 1443 size_t pixel_size = TextureSizeBytes(size, format); 1444 ASSERT_EQ(4U, pixel_size); 1445 1446 ResourceProvider::ResourceId id = child_resource_provider->CreateResource( 1447 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1448 1449 // The new texture is created with GL_LINEAR. 1450 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)) 1451 .Times(2); // Once to create and once to allocate. 1452 EXPECT_CALL(*child_context, 1453 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 1454 EXPECT_CALL(*child_context, 1455 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 1456 EXPECT_CALL( 1457 *child_context, 1458 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 1459 EXPECT_CALL( 1460 *child_context, 1461 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 1462 EXPECT_CALL(*child_context, 1463 texParameteri(GL_TEXTURE_2D, 1464 GL_TEXTURE_POOL_CHROMIUM, 1465 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); 1466 child_resource_provider->AllocateForTesting(id); 1467 Mock::VerifyAndClearExpectations(child_context); 1468 1469 uint8_t data[4] = { 1, 2, 3, 4 }; 1470 gfx::Rect rect(size); 1471 1472 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); 1473 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d()); 1474 Mock::VerifyAndClearExpectations(child_context); 1475 1476 // The texture is set to |child_filter| in the child. 1477 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); 1478 if (child_filter != GL_LINEAR) { 1479 EXPECT_CALL( 1480 *child_context, 1481 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter)); 1482 EXPECT_CALL( 1483 *child_context, 1484 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter)); 1485 } 1486 SetResourceFilter(child_resource_provider.get(), id, child_filter); 1487 Mock::VerifyAndClearExpectations(child_context); 1488 1489 ReturnedResourceArray returned_to_child; 1490 int child_id = parent_resource_provider->CreateChild( 1491 GetReturnCallback(&returned_to_child)); 1492 { 1493 // Transfer some resource to the parent. 1494 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1495 resource_ids_to_transfer.push_back(id); 1496 TransferableResourceArray list; 1497 1498 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); 1499 EXPECT_CALL(*child_context, 1500 produceTextureCHROMIUM(GL_TEXTURE_2D, _)); 1501 EXPECT_CALL(*child_context, insertSyncPoint()); 1502 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, 1503 &list); 1504 Mock::VerifyAndClearExpectations(child_context); 1505 1506 ASSERT_EQ(1u, list.size()); 1507 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter); 1508 1509 EXPECT_CALL(*parent_context, 1510 bindTexture(GL_TEXTURE_2D, parent_texture_id)); 1511 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _)); 1512 parent_resource_provider->ReceiveFromChild(child_id, list); 1513 Mock::VerifyAndClearExpectations(parent_context); 1514 1515 parent_resource_provider->DeclareUsedResourcesFromChild( 1516 child_id, resource_ids_to_transfer); 1517 Mock::VerifyAndClearExpectations(parent_context); 1518 } 1519 ResourceProvider::ResourceIdMap resource_map = 1520 parent_resource_provider->GetChildToParentMap(child_id); 1521 ResourceProvider::ResourceId mapped_id = resource_map[id]; 1522 EXPECT_NE(0u, mapped_id); 1523 1524 // The texture is set to |parent_filter| in the parent. 1525 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); 1526 EXPECT_CALL( 1527 *parent_context, 1528 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter)); 1529 EXPECT_CALL( 1530 *parent_context, 1531 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter)); 1532 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter); 1533 Mock::VerifyAndClearExpectations(parent_context); 1534 1535 // The texture should be reset to |child_filter| in the parent when it is 1536 // returned, since that is how it was received. 1537 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id)); 1538 EXPECT_CALL( 1539 *parent_context, 1540 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter)); 1541 EXPECT_CALL( 1542 *parent_context, 1543 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter)); 1544 1545 { 1546 EXPECT_EQ(0u, returned_to_child.size()); 1547 1548 // Transfer resources back from the parent to the child. Set no resources 1549 // as being in use. 1550 ResourceProvider::ResourceIdArray no_resources; 1551 EXPECT_CALL(*parent_context, insertSyncPoint()); 1552 parent_resource_provider->DeclareUsedResourcesFromChild(child_id, 1553 no_resources); 1554 Mock::VerifyAndClearExpectations(parent_context); 1555 1556 ASSERT_EQ(1u, returned_to_child.size()); 1557 child_resource_provider->ReceiveReturnsFromParent(returned_to_child); 1558 } 1559 1560 // The child remembers the texture filter is set to |child_filter|. 1561 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id)); 1562 SetResourceFilter(child_resource_provider.get(), id, child_filter); 1563 Mock::VerifyAndClearExpectations(child_context); 1564 } 1565}; 1566 1567TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) { 1568 if (GetParam() != ResourceProvider::GLTexture) 1569 return; 1570 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR); 1571} 1572 1573TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) { 1574 if (GetParam() != ResourceProvider::GLTexture) 1575 return; 1576 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST); 1577} 1578 1579TEST_P(ResourceProviderTest, TransferMailboxResources) { 1580 // Other mailbox transfers tested elsewhere. 1581 if (GetParam() != ResourceProvider::GLTexture) 1582 return; 1583 unsigned texture = context()->createTexture(); 1584 context()->bindTexture(GL_TEXTURE_2D, texture); 1585 uint8_t data[4] = { 1, 2, 3, 4 }; 1586 context()->texImage2D( 1587 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); 1588 gpu::Mailbox mailbox; 1589 context()->genMailboxCHROMIUM(mailbox.name); 1590 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1591 unsigned sync_point = context()->insertSyncPoint(); 1592 1593 // All the logic below assumes that the sync points are all positive. 1594 EXPECT_LT(0u, sync_point); 1595 1596 unsigned release_sync_point = 0; 1597 bool lost_resource = false; 1598 ReleaseCallback callback = 1599 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource); 1600 ResourceProvider::ResourceId resource = 1601 resource_provider_->CreateResourceFromTextureMailbox( 1602 TextureMailbox(mailbox, sync_point), 1603 SingleReleaseCallback::Create(callback)); 1604 EXPECT_EQ(1u, context()->NumTextures()); 1605 EXPECT_EQ(0u, release_sync_point); 1606 { 1607 // Transfer the resource, expect the sync points to be consistent. 1608 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1609 resource_ids_to_transfer.push_back(resource); 1610 TransferableResourceArray list; 1611 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1612 ASSERT_EQ(1u, list.size()); 1613 EXPECT_LE(sync_point, list[0].sync_point); 1614 EXPECT_EQ(0, 1615 memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name))); 1616 EXPECT_EQ(0u, release_sync_point); 1617 1618 context()->waitSyncPoint(list[0].sync_point); 1619 unsigned other_texture = context()->createTexture(); 1620 context()->bindTexture(GL_TEXTURE_2D, other_texture); 1621 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1622 uint8_t test_data[4] = { 0 }; 1623 context()->GetPixels( 1624 gfx::Size(1, 1), RGBA_8888, test_data); 1625 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); 1626 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1627 context()->deleteTexture(other_texture); 1628 list[0].sync_point = context()->insertSyncPoint(); 1629 EXPECT_LT(0u, list[0].sync_point); 1630 1631 // Receive the resource, then delete it, expect the sync points to be 1632 // consistent. 1633 ReturnedResourceArray returned; 1634 TransferableResource::ReturnResources(list, &returned); 1635 resource_provider_->ReceiveReturnsFromParent(returned); 1636 EXPECT_EQ(1u, context()->NumTextures()); 1637 EXPECT_EQ(0u, release_sync_point); 1638 1639 resource_provider_->DeleteResource(resource); 1640 EXPECT_LE(list[0].sync_point, release_sync_point); 1641 EXPECT_FALSE(lost_resource); 1642 } 1643 1644 // We're going to do the same thing as above, but testing the case where we 1645 // delete the resource before we receive it back. 1646 sync_point = release_sync_point; 1647 EXPECT_LT(0u, sync_point); 1648 release_sync_point = 0; 1649 resource = resource_provider_->CreateResourceFromTextureMailbox( 1650 TextureMailbox(mailbox, sync_point), 1651 SingleReleaseCallback::Create(callback)); 1652 EXPECT_EQ(1u, context()->NumTextures()); 1653 EXPECT_EQ(0u, release_sync_point); 1654 { 1655 // Transfer the resource, expect the sync points to be consistent. 1656 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1657 resource_ids_to_transfer.push_back(resource); 1658 TransferableResourceArray list; 1659 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1660 ASSERT_EQ(1u, list.size()); 1661 EXPECT_LE(sync_point, list[0].sync_point); 1662 EXPECT_EQ(0, 1663 memcmp(mailbox.name, list[0].mailbox.name, sizeof(mailbox.name))); 1664 EXPECT_EQ(0u, release_sync_point); 1665 1666 context()->waitSyncPoint(list[0].sync_point); 1667 unsigned other_texture = context()->createTexture(); 1668 context()->bindTexture(GL_TEXTURE_2D, other_texture); 1669 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1670 uint8_t test_data[4] = { 0 }; 1671 context()->GetPixels( 1672 gfx::Size(1, 1), RGBA_8888, test_data); 1673 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data))); 1674 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1675 context()->deleteTexture(other_texture); 1676 list[0].sync_point = context()->insertSyncPoint(); 1677 EXPECT_LT(0u, list[0].sync_point); 1678 1679 // Delete the resource, which shouldn't do anything. 1680 resource_provider_->DeleteResource(resource); 1681 EXPECT_EQ(1u, context()->NumTextures()); 1682 EXPECT_EQ(0u, release_sync_point); 1683 1684 // Then receive the resource which should release the mailbox, expect the 1685 // sync points to be consistent. 1686 ReturnedResourceArray returned; 1687 TransferableResource::ReturnResources(list, &returned); 1688 resource_provider_->ReceiveReturnsFromParent(returned); 1689 EXPECT_LE(list[0].sync_point, release_sync_point); 1690 EXPECT_FALSE(lost_resource); 1691 } 1692 1693 context()->waitSyncPoint(release_sync_point); 1694 context()->bindTexture(GL_TEXTURE_2D, texture); 1695 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 1696 context()->deleteTexture(texture); 1697} 1698 1699TEST_P(ResourceProviderTest, LostResourceInParent) { 1700 gfx::Size size(1, 1); 1701 ResourceFormat format = RGBA_8888; 1702 ResourceProvider::ResourceId resource = 1703 child_resource_provider_->CreateResource( 1704 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1705 child_resource_provider_->AllocateForTesting(resource); 1706 // Expect a GL resource to be lost. 1707 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture; 1708 1709 ReturnedResourceArray returned_to_child; 1710 int child_id = 1711 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1712 { 1713 // Transfer the resource to the parent. 1714 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1715 resource_ids_to_transfer.push_back(resource); 1716 TransferableResourceArray list; 1717 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1718 &list); 1719 EXPECT_EQ(1u, list.size()); 1720 1721 resource_provider_->ReceiveFromChild(child_id, list); 1722 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1723 resource_ids_to_transfer); 1724 } 1725 1726 // Lose the output surface in the parent. 1727 resource_provider_->DidLoseOutputSurface(); 1728 1729 { 1730 EXPECT_EQ(0u, returned_to_child.size()); 1731 1732 // Transfer resources back from the parent to the child. Set no resources as 1733 // being in use. 1734 ResourceProvider::ResourceIdArray no_resources; 1735 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1736 1737 // Expect a GL resource to be lost. 1738 ASSERT_EQ(1u, returned_to_child.size()); 1739 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost); 1740 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 1741 returned_to_child.clear(); 1742 } 1743 1744 // A GL resource should be lost. 1745 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource)); 1746 1747 // Lost resources stay in use in the parent forever. 1748 EXPECT_EQ(should_lose_resource, 1749 child_resource_provider_->InUseByConsumer(resource)); 1750} 1751 1752TEST_P(ResourceProviderTest, LostResourceInGrandParent) { 1753 gfx::Size size(1, 1); 1754 ResourceFormat format = RGBA_8888; 1755 ResourceProvider::ResourceId resource = 1756 child_resource_provider_->CreateResource( 1757 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 1758 child_resource_provider_->AllocateForTesting(resource); 1759 1760 ReturnedResourceArray returned_to_child; 1761 int child_id = 1762 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1763 { 1764 // Transfer the resource to the parent. 1765 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1766 resource_ids_to_transfer.push_back(resource); 1767 TransferableResourceArray list; 1768 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1769 &list); 1770 EXPECT_EQ(1u, list.size()); 1771 1772 resource_provider_->ReceiveFromChild(child_id, list); 1773 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1774 resource_ids_to_transfer); 1775 } 1776 1777 { 1778 ResourceProvider::ResourceIdMap resource_map = 1779 resource_provider_->GetChildToParentMap(child_id); 1780 ResourceProvider::ResourceId parent_resource = resource_map[resource]; 1781 EXPECT_NE(0u, parent_resource); 1782 1783 // Transfer to a grandparent. 1784 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1785 resource_ids_to_transfer.push_back(parent_resource); 1786 TransferableResourceArray list; 1787 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1788 1789 // Receive back a lost resource from the grandparent. 1790 EXPECT_EQ(1u, list.size()); 1791 EXPECT_EQ(parent_resource, list[0].id); 1792 ReturnedResourceArray returned; 1793 TransferableResource::ReturnResources(list, &returned); 1794 EXPECT_EQ(1u, returned.size()); 1795 EXPECT_EQ(parent_resource, returned[0].id); 1796 returned[0].lost = true; 1797 resource_provider_->ReceiveReturnsFromParent(returned); 1798 1799 // The resource should be lost. 1800 EXPECT_TRUE(resource_provider_->IsLost(parent_resource)); 1801 1802 // Lost resources stay in use in the parent forever. 1803 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource)); 1804 } 1805 1806 { 1807 EXPECT_EQ(0u, returned_to_child.size()); 1808 1809 // Transfer resources back from the parent to the child. Set no resources as 1810 // being in use. 1811 ResourceProvider::ResourceIdArray no_resources; 1812 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1813 1814 // Expect the resource to be lost. 1815 ASSERT_EQ(1u, returned_to_child.size()); 1816 EXPECT_TRUE(returned_to_child[0].lost); 1817 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 1818 returned_to_child.clear(); 1819 } 1820 1821 // The resource should be lost. 1822 EXPECT_TRUE(child_resource_provider_->IsLost(resource)); 1823 1824 // Lost resources stay in use in the parent forever. 1825 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource)); 1826} 1827 1828TEST_P(ResourceProviderTest, LostMailboxInParent) { 1829 unsigned release_sync_point = 0; 1830 bool lost_resource = false; 1831 bool release_called = false; 1832 unsigned sync_point = 0; 1833 ResourceProvider::ResourceId resource = CreateChildMailbox( 1834 &release_sync_point, &lost_resource, &release_called, &sync_point); 1835 1836 ReturnedResourceArray returned_to_child; 1837 int child_id = 1838 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1839 { 1840 // Transfer the resource to the parent. 1841 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1842 resource_ids_to_transfer.push_back(resource); 1843 TransferableResourceArray list; 1844 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1845 &list); 1846 EXPECT_EQ(1u, list.size()); 1847 1848 resource_provider_->ReceiveFromChild(child_id, list); 1849 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1850 resource_ids_to_transfer); 1851 } 1852 1853 // Lose the output surface in the parent. 1854 resource_provider_->DidLoseOutputSurface(); 1855 1856 { 1857 EXPECT_EQ(0u, returned_to_child.size()); 1858 1859 // Transfer resources back from the parent to the child. Set no resources as 1860 // being in use. 1861 ResourceProvider::ResourceIdArray no_resources; 1862 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1863 1864 ASSERT_EQ(1u, returned_to_child.size()); 1865 // Losing an output surface only loses hardware resources. 1866 EXPECT_EQ(returned_to_child[0].lost, 1867 GetParam() == ResourceProvider::GLTexture); 1868 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 1869 returned_to_child.clear(); 1870 } 1871 1872 // Delete the resource in the child. Expect the resource to be lost if it's 1873 // a GL texture. 1874 child_resource_provider_->DeleteResource(resource); 1875 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture); 1876} 1877 1878TEST_P(ResourceProviderTest, LostMailboxInGrandParent) { 1879 unsigned release_sync_point = 0; 1880 bool lost_resource = false; 1881 bool release_called = false; 1882 unsigned sync_point = 0; 1883 ResourceProvider::ResourceId resource = CreateChildMailbox( 1884 &release_sync_point, &lost_resource, &release_called, &sync_point); 1885 1886 ReturnedResourceArray returned_to_child; 1887 int child_id = 1888 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child)); 1889 { 1890 // Transfer the resource to the parent. 1891 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1892 resource_ids_to_transfer.push_back(resource); 1893 TransferableResourceArray list; 1894 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1895 &list); 1896 EXPECT_EQ(1u, list.size()); 1897 1898 resource_provider_->ReceiveFromChild(child_id, list); 1899 resource_provider_->DeclareUsedResourcesFromChild(child_id, 1900 resource_ids_to_transfer); 1901 } 1902 1903 { 1904 ResourceProvider::ResourceIdMap resource_map = 1905 resource_provider_->GetChildToParentMap(child_id); 1906 ResourceProvider::ResourceId parent_resource = resource_map[resource]; 1907 EXPECT_NE(0u, parent_resource); 1908 1909 // Transfer to a grandparent. 1910 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1911 resource_ids_to_transfer.push_back(parent_resource); 1912 TransferableResourceArray list; 1913 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list); 1914 1915 // Receive back a lost resource from the grandparent. 1916 EXPECT_EQ(1u, list.size()); 1917 EXPECT_EQ(parent_resource, list[0].id); 1918 ReturnedResourceArray returned; 1919 TransferableResource::ReturnResources(list, &returned); 1920 EXPECT_EQ(1u, returned.size()); 1921 EXPECT_EQ(parent_resource, returned[0].id); 1922 returned[0].lost = true; 1923 resource_provider_->ReceiveReturnsFromParent(returned); 1924 } 1925 1926 { 1927 EXPECT_EQ(0u, returned_to_child.size()); 1928 1929 // Transfer resources back from the parent to the child. Set no resources as 1930 // being in use. 1931 ResourceProvider::ResourceIdArray no_resources; 1932 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources); 1933 1934 // Expect the resource to be lost. 1935 ASSERT_EQ(1u, returned_to_child.size()); 1936 EXPECT_TRUE(returned_to_child[0].lost); 1937 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child); 1938 returned_to_child.clear(); 1939 } 1940 1941 // Delete the resource in the child. Expect the resource to be lost. 1942 child_resource_provider_->DeleteResource(resource); 1943 EXPECT_TRUE(lost_resource); 1944} 1945 1946TEST_P(ResourceProviderTest, Shutdown) { 1947 unsigned release_sync_point = 0; 1948 bool lost_resource = false; 1949 bool release_called = false; 1950 unsigned sync_point = 0; 1951 CreateChildMailbox( 1952 &release_sync_point, &lost_resource, &release_called, &sync_point); 1953 1954 EXPECT_EQ(0u, release_sync_point); 1955 EXPECT_FALSE(lost_resource); 1956 1957 child_resource_provider_.reset(); 1958 1959 if (GetParam() == ResourceProvider::GLTexture) { 1960 EXPECT_LE(sync_point, release_sync_point); 1961 } 1962 EXPECT_TRUE(release_called); 1963 EXPECT_FALSE(lost_resource); 1964} 1965 1966TEST_P(ResourceProviderTest, ShutdownWithExportedResource) { 1967 unsigned release_sync_point = 0; 1968 bool lost_resource = false; 1969 bool release_called = false; 1970 unsigned sync_point = 0; 1971 ResourceProvider::ResourceId resource = CreateChildMailbox( 1972 &release_sync_point, &lost_resource, &release_called, &sync_point); 1973 1974 // Transfer the resource, so we can't release it properly on shutdown. 1975 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1976 resource_ids_to_transfer.push_back(resource); 1977 TransferableResourceArray list; 1978 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, 1979 &list); 1980 1981 EXPECT_EQ(0u, release_sync_point); 1982 EXPECT_FALSE(lost_resource); 1983 1984 child_resource_provider_.reset(); 1985 1986 // Since the resource is in the parent, the child considers it lost. 1987 EXPECT_EQ(0u, release_sync_point); 1988 EXPECT_TRUE(lost_resource); 1989} 1990 1991TEST_P(ResourceProviderTest, LostContext) { 1992 // TextureMailbox callbacks only exist for GL textures for now. 1993 if (GetParam() != ResourceProvider::GLTexture) 1994 return; 1995 unsigned texture = context()->createTexture(); 1996 context()->bindTexture(GL_TEXTURE_2D, texture); 1997 gpu::Mailbox mailbox; 1998 context()->genMailboxCHROMIUM(mailbox.name); 1999 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 2000 unsigned sync_point = context()->insertSyncPoint(); 2001 2002 EXPECT_LT(0u, sync_point); 2003 2004 unsigned release_sync_point = 0; 2005 bool lost_resource = false; 2006 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 2007 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource)); 2008 resource_provider_->CreateResourceFromTextureMailbox( 2009 TextureMailbox(mailbox, sync_point), 2010 callback.Pass()); 2011 2012 EXPECT_EQ(0u, release_sync_point); 2013 EXPECT_FALSE(lost_resource); 2014 2015 resource_provider_->DidLoseOutputSurface(); 2016 resource_provider_.reset(); 2017 2018 EXPECT_LE(sync_point, release_sync_point); 2019 EXPECT_TRUE(lost_resource); 2020} 2021 2022TEST_P(ResourceProviderTest, ScopedSampler) { 2023 // Sampling is only supported for GL textures. 2024 if (GetParam() != ResourceProvider::GLTexture) 2025 return; 2026 2027 scoped_ptr<TextureStateTrackingContext> context_owned( 2028 new TextureStateTrackingContext); 2029 TextureStateTrackingContext* context = context_owned.get(); 2030 2031 FakeOutputSurfaceClient output_surface_client; 2032 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2033 context_owned.PassAs<TestWebGraphicsContext3D>())); 2034 CHECK(output_surface->BindToClient(&output_surface_client)); 2035 2036 scoped_ptr<ResourceProvider> resource_provider( 2037 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2038 2039 gfx::Size size(1, 1); 2040 ResourceFormat format = RGBA_8888; 2041 int texture_id = 1; 2042 2043 ResourceProvider::ResourceId id = resource_provider->CreateResource( 2044 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2045 2046 // Check that the texture gets created with the right sampler settings. 2047 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)) 2048 .Times(2); // Once to create and once to allocate. 2049 EXPECT_CALL(*context, 2050 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2051 EXPECT_CALL(*context, 2052 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2053 EXPECT_CALL( 2054 *context, 2055 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2056 EXPECT_CALL( 2057 *context, 2058 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2059 EXPECT_CALL(*context, 2060 texParameteri(GL_TEXTURE_2D, 2061 GL_TEXTURE_POOL_CHROMIUM, 2062 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); 2063 2064 resource_provider->AllocateForTesting(id); 2065 Mock::VerifyAndClearExpectations(context); 2066 2067 // Creating a sampler with the default filter should not change any texture 2068 // parameters. 2069 { 2070 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); 2071 ResourceProvider::ScopedSamplerGL sampler( 2072 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); 2073 Mock::VerifyAndClearExpectations(context); 2074 } 2075 2076 // Using a different filter should be reflected in the texture parameters. 2077 { 2078 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); 2079 EXPECT_CALL( 2080 *context, 2081 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); 2082 EXPECT_CALL( 2083 *context, 2084 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 2085 ResourceProvider::ScopedSamplerGL sampler( 2086 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST); 2087 Mock::VerifyAndClearExpectations(context); 2088 } 2089 2090 // Test resetting to the default filter. 2091 { 2092 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); 2093 EXPECT_CALL(*context, 2094 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2095 EXPECT_CALL(*context, 2096 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2097 ResourceProvider::ScopedSamplerGL sampler( 2098 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); 2099 Mock::VerifyAndClearExpectations(context); 2100 } 2101} 2102 2103TEST_P(ResourceProviderTest, ManagedResource) { 2104 // Sampling is only supported for GL textures. 2105 if (GetParam() != ResourceProvider::GLTexture) 2106 return; 2107 2108 scoped_ptr<TextureStateTrackingContext> context_owned( 2109 new TextureStateTrackingContext); 2110 TextureStateTrackingContext* context = context_owned.get(); 2111 2112 FakeOutputSurfaceClient output_surface_client; 2113 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2114 context_owned.PassAs<TestWebGraphicsContext3D>())); 2115 CHECK(output_surface->BindToClient(&output_surface_client)); 2116 2117 scoped_ptr<ResourceProvider> resource_provider( 2118 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2119 2120 gfx::Size size(1, 1); 2121 ResourceFormat format = RGBA_8888; 2122 int texture_id = 1; 2123 2124 // Check that the texture gets created with the right sampler settings. 2125 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource( 2126 size, 2127 GL_TEXTURE_2D, 2128 GL_CLAMP_TO_EDGE, 2129 ResourceProvider::TextureUsageAny, 2130 format); 2131 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); 2132 EXPECT_CALL(*context, 2133 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2134 EXPECT_CALL(*context, 2135 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2136 EXPECT_CALL( 2137 *context, 2138 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2139 EXPECT_CALL( 2140 *context, 2141 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2142 EXPECT_CALL(*context, 2143 texParameteri(GL_TEXTURE_2D, 2144 GL_TEXTURE_POOL_CHROMIUM, 2145 GL_TEXTURE_POOL_MANAGED_CHROMIUM)); 2146 resource_provider->CreateForTesting(id); 2147 EXPECT_NE(0u, id); 2148 2149 Mock::VerifyAndClearExpectations(context); 2150} 2151 2152TEST_P(ResourceProviderTest, TextureWrapMode) { 2153 // Sampling is only supported for GL textures. 2154 if (GetParam() != ResourceProvider::GLTexture) 2155 return; 2156 2157 scoped_ptr<TextureStateTrackingContext> context_owned( 2158 new TextureStateTrackingContext); 2159 TextureStateTrackingContext* context = context_owned.get(); 2160 2161 FakeOutputSurfaceClient output_surface_client; 2162 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2163 context_owned.PassAs<TestWebGraphicsContext3D>())); 2164 CHECK(output_surface->BindToClient(&output_surface_client)); 2165 2166 scoped_ptr<ResourceProvider> resource_provider( 2167 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2168 2169 gfx::Size size(1, 1); 2170 ResourceFormat format = RGBA_8888; 2171 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM; 2172 2173 for (int texture_id = 1; texture_id <= 2; ++texture_id) { 2174 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT; 2175 // Check that the texture gets created with the right sampler settings. 2176 ResourceProvider::ResourceId id = 2177 resource_provider->CreateGLTexture(size, 2178 GL_TEXTURE_2D, 2179 texture_pool, 2180 wrap_mode, 2181 ResourceProvider::TextureUsageAny, 2182 format); 2183 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)); 2184 EXPECT_CALL(*context, 2185 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2186 EXPECT_CALL(*context, 2187 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2188 EXPECT_CALL( 2189 *context, 2190 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode)); 2191 EXPECT_CALL( 2192 *context, 2193 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode)); 2194 EXPECT_CALL(*context, 2195 texParameteri(GL_TEXTURE_2D, 2196 GL_TEXTURE_POOL_CHROMIUM, 2197 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM)); 2198 resource_provider->CreateForTesting(id); 2199 EXPECT_NE(0u, id); 2200 2201 Mock::VerifyAndClearExpectations(context); 2202 } 2203} 2204 2205TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { 2206 if (GetParam() != ResourceProvider::Bitmap) 2207 return; 2208 2209 gfx::Size size(64, 64); 2210 const uint32_t kBadBeef = 0xbadbeef; 2211 scoped_ptr<base::SharedMemory> shared_memory( 2212 CreateAndFillSharedMemory(size, kBadBeef)); 2213 2214 FakeOutputSurfaceClient output_surface_client; 2215 scoped_ptr<OutputSurface> output_surface( 2216 FakeOutputSurface::CreateSoftware(make_scoped_ptr( 2217 new SoftwareOutputDevice))); 2218 CHECK(output_surface->BindToClient(&output_surface_client)); 2219 2220 scoped_ptr<ResourceProvider> resource_provider( 2221 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2222 2223 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 2224 base::Bind(&EmptyReleaseCallback)); 2225 TextureMailbox mailbox(shared_memory.get(), size); 2226 2227 ResourceProvider::ResourceId id = 2228 resource_provider->CreateResourceFromTextureMailbox( 2229 mailbox, callback.Pass()); 2230 EXPECT_NE(0u, id); 2231 2232 { 2233 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id); 2234 const SkBitmap* sk_bitmap = lock.sk_bitmap(); 2235 EXPECT_EQ(sk_bitmap->width(), size.width()); 2236 EXPECT_EQ(sk_bitmap->height(), size.height()); 2237 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef); 2238 } 2239} 2240 2241TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) { 2242 // Mailboxing is only supported for GL textures. 2243 if (GetParam() != ResourceProvider::GLTexture) 2244 return; 2245 2246 scoped_ptr<TextureStateTrackingContext> context_owned( 2247 new TextureStateTrackingContext); 2248 TextureStateTrackingContext* context = context_owned.get(); 2249 2250 FakeOutputSurfaceClient output_surface_client; 2251 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2252 context_owned.PassAs<TestWebGraphicsContext3D>())); 2253 CHECK(output_surface->BindToClient(&output_surface_client)); 2254 2255 scoped_ptr<ResourceProvider> resource_provider( 2256 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2257 2258 unsigned texture_id = 1; 2259 unsigned sync_point = 30; 2260 unsigned target = GL_TEXTURE_2D; 2261 2262 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); 2263 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); 2264 EXPECT_CALL(*context, insertSyncPoint()).Times(0); 2265 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2266 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0); 2267 2268 gpu::Mailbox gpu_mailbox; 2269 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); 2270 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 2271 base::Bind(&EmptyReleaseCallback)); 2272 2273 TextureMailbox mailbox(gpu_mailbox, sync_point); 2274 2275 ResourceProvider::ResourceId id = 2276 resource_provider->CreateResourceFromTextureMailbox( 2277 mailbox, callback.Pass()); 2278 EXPECT_NE(0u, id); 2279 2280 Mock::VerifyAndClearExpectations(context); 2281 2282 { 2283 // Using the texture does a consume of the mailbox. 2284 EXPECT_CALL(*context, bindTexture(target, texture_id)); 2285 EXPECT_CALL(*context, waitSyncPoint(sync_point)); 2286 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _)); 2287 2288 EXPECT_CALL(*context, insertSyncPoint()).Times(0); 2289 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2290 2291 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id); 2292 Mock::VerifyAndClearExpectations(context); 2293 2294 // When done with it, a sync point should be inserted, but no produce is 2295 // necessary. 2296 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); 2297 EXPECT_CALL(*context, insertSyncPoint()); 2298 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2299 2300 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); 2301 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0); 2302 } 2303} 2304 2305TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { 2306 // Mailboxing is only supported for GL textures. 2307 if (GetParam() != ResourceProvider::GLTexture) 2308 return; 2309 2310 scoped_ptr<TextureStateTrackingContext> context_owned( 2311 new TextureStateTrackingContext); 2312 TextureStateTrackingContext* context = context_owned.get(); 2313 2314 FakeOutputSurfaceClient output_surface_client; 2315 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2316 context_owned.PassAs<TestWebGraphicsContext3D>())); 2317 CHECK(output_surface->BindToClient(&output_surface_client)); 2318 2319 scoped_ptr<ResourceProvider> resource_provider( 2320 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2321 2322 unsigned texture_id = 1; 2323 unsigned sync_point = 30; 2324 unsigned target = GL_TEXTURE_EXTERNAL_OES; 2325 2326 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); 2327 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); 2328 EXPECT_CALL(*context, insertSyncPoint()).Times(0); 2329 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2330 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0); 2331 2332 gpu::Mailbox gpu_mailbox; 2333 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1); 2334 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 2335 base::Bind(&EmptyReleaseCallback)); 2336 2337 TextureMailbox mailbox(gpu_mailbox, target, sync_point); 2338 2339 ResourceProvider::ResourceId id = 2340 resource_provider->CreateResourceFromTextureMailbox( 2341 mailbox, callback.Pass()); 2342 EXPECT_NE(0u, id); 2343 2344 Mock::VerifyAndClearExpectations(context); 2345 2346 { 2347 // Using the texture does a consume of the mailbox. 2348 EXPECT_CALL(*context, bindTexture(target, texture_id)); 2349 EXPECT_CALL(*context, waitSyncPoint(sync_point)); 2350 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _)); 2351 2352 EXPECT_CALL(*context, insertSyncPoint()).Times(0); 2353 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2354 2355 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id); 2356 Mock::VerifyAndClearExpectations(context); 2357 2358 // When done with it, a sync point should be inserted, but no produce is 2359 // necessary. 2360 EXPECT_CALL(*context, bindTexture(_, _)).Times(0); 2361 EXPECT_CALL(*context, insertSyncPoint()); 2362 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0); 2363 2364 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0); 2365 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0); 2366 } 2367} 2368 2369class AllocationTrackingContext3D : public TestWebGraphicsContext3D { 2370 public: 2371 MOCK_METHOD0(NextTextureId, GLuint()); 2372 MOCK_METHOD1(RetireTextureId, void(GLuint id)); 2373 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); 2374 MOCK_METHOD5(texStorage2DEXT, 2375 void(GLenum target, 2376 GLint levels, 2377 GLuint internalformat, 2378 GLint width, 2379 GLint height)); 2380 MOCK_METHOD9(texImage2D, 2381 void(GLenum target, 2382 GLint level, 2383 GLenum internalformat, 2384 GLsizei width, 2385 GLsizei height, 2386 GLint border, 2387 GLenum format, 2388 GLenum type, 2389 const void* pixels)); 2390 MOCK_METHOD9(texSubImage2D, 2391 void(GLenum target, 2392 GLint level, 2393 GLint xoffset, 2394 GLint yoffset, 2395 GLsizei width, 2396 GLsizei height, 2397 GLenum format, 2398 GLenum type, 2399 const void* pixels)); 2400 MOCK_METHOD9(asyncTexImage2DCHROMIUM, 2401 void(GLenum target, 2402 GLint level, 2403 GLenum internalformat, 2404 GLsizei width, 2405 GLsizei height, 2406 GLint border, 2407 GLenum format, 2408 GLenum type, 2409 const void* pixels)); 2410 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM, 2411 void(GLenum target, 2412 GLint level, 2413 GLint xoffset, 2414 GLint yoffset, 2415 GLsizei width, 2416 GLsizei height, 2417 GLenum format, 2418 GLenum type, 2419 const void* pixels)); 2420 MOCK_METHOD8(compressedTexImage2D, 2421 void(GLenum target, 2422 GLint level, 2423 GLenum internalformat, 2424 GLsizei width, 2425 GLsizei height, 2426 GLint border, 2427 GLsizei image_size, 2428 const void* data)); 2429 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum)); 2430 MOCK_METHOD3(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum)); 2431 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint)); 2432 MOCK_METHOD2(mapImageCHROMIUM, void*(GLuint, GLenum)); 2433 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*)); 2434 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint)); 2435 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint)); 2436 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint)); 2437 2438 // We're mocking bindTexture, so we override 2439 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the 2440 // currently bound texture. 2441 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {} 2442}; 2443 2444TEST_P(ResourceProviderTest, TextureAllocation) { 2445 // Only for GL textures. 2446 if (GetParam() != ResourceProvider::GLTexture) 2447 return; 2448 scoped_ptr<AllocationTrackingContext3D> context_owned( 2449 new StrictMock<AllocationTrackingContext3D>); 2450 AllocationTrackingContext3D* context = context_owned.get(); 2451 2452 FakeOutputSurfaceClient output_surface_client; 2453 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2454 context_owned.PassAs<TestWebGraphicsContext3D>())); 2455 CHECK(output_surface->BindToClient(&output_surface_client)); 2456 2457 scoped_ptr<ResourceProvider> resource_provider( 2458 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2459 2460 gfx::Size size(2, 2); 2461 gfx::Vector2d offset(0, 0); 2462 gfx::Rect rect(0, 0, 2, 2); 2463 ResourceFormat format = RGBA_8888; 2464 ResourceProvider::ResourceId id = 0; 2465 uint8_t pixels[16] = { 0 }; 2466 int texture_id = 123; 2467 2468 // Lazy allocation. Don't allocate when creating the resource. 2469 id = resource_provider->CreateResource( 2470 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2471 2472 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2473 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); 2474 resource_provider->CreateForTesting(id); 2475 2476 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2477 resource_provider->DeleteResource(id); 2478 2479 Mock::VerifyAndClearExpectations(context); 2480 2481 // Do allocate when we set the pixels. 2482 id = resource_provider->CreateResource( 2483 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2484 2485 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2486 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); 2487 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1); 2488 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1); 2489 resource_provider->SetPixels(id, pixels, rect, rect, offset); 2490 2491 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2492 resource_provider->DeleteResource(id); 2493 2494 Mock::VerifyAndClearExpectations(context); 2495 2496 // Same for async version. 2497 id = resource_provider->CreateResource( 2498 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2499 resource_provider->AcquirePixelBuffer(id); 2500 2501 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2502 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2503 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) 2504 .Times(1); 2505 resource_provider->BeginSetPixels(id); 2506 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id)); 2507 2508 resource_provider->ReleasePixelBuffer(id); 2509 2510 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2511 resource_provider->DeleteResource(id); 2512 2513 Mock::VerifyAndClearExpectations(context); 2514} 2515 2516TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) { 2517 // Only for GL textures. 2518 if (GetParam() != ResourceProvider::GLTexture) 2519 return; 2520 scoped_ptr<AllocationTrackingContext3D> context_owned( 2521 new StrictMock<AllocationTrackingContext3D>); 2522 AllocationTrackingContext3D* context = context_owned.get(); 2523 context->set_support_texture_storage(true); 2524 2525 FakeOutputSurfaceClient output_surface_client; 2526 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2527 context_owned.PassAs<TestWebGraphicsContext3D>())); 2528 CHECK(output_surface->BindToClient(&output_surface_client)); 2529 2530 scoped_ptr<ResourceProvider> resource_provider( 2531 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2532 2533 gfx::Size size(2, 2); 2534 ResourceFormat format = RGBA_8888; 2535 ResourceProvider::ResourceId id = 0; 2536 int texture_id = 123; 2537 2538 // Lazy allocation. Don't allocate when creating the resource. 2539 id = resource_provider->CreateResource( 2540 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2541 2542 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2543 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2544 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1); 2545 resource_provider->AllocateForTesting(id); 2546 2547 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2548 resource_provider->DeleteResource(id); 2549 2550 Mock::VerifyAndClearExpectations(context); 2551} 2552 2553TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) { 2554 // Only for GL textures. 2555 if (GetParam() != ResourceProvider::GLTexture) 2556 return; 2557 scoped_ptr<AllocationTrackingContext3D> context_owned( 2558 new StrictMock<AllocationTrackingContext3D>); 2559 AllocationTrackingContext3D* context = context_owned.get(); 2560 context->set_support_texture_storage(true); 2561 2562 FakeOutputSurfaceClient output_surface_client; 2563 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2564 context_owned.PassAs<TestWebGraphicsContext3D>())); 2565 CHECK(output_surface->BindToClient(&output_surface_client)); 2566 2567 scoped_ptr<ResourceProvider> resource_provider( 2568 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2569 2570 gfx::Size size(2, 2); 2571 ResourceFormat format = RGBA_8888; 2572 ResourceProvider::ResourceId id = 0; 2573 int texture_id = 123; 2574 2575 // Lazy allocation. Don't allocate when creating the resource. 2576 id = resource_provider->CreateResource( 2577 size, 2578 GL_CLAMP_TO_EDGE, 2579 ResourceProvider::TextureUsageFramebuffer, 2580 format); 2581 2582 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2583 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2584 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1); 2585 resource_provider->AllocateForTesting(id); 2586 2587 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2588 resource_provider->DeleteResource(id); 2589 2590 Mock::VerifyAndClearExpectations(context); 2591} 2592 2593TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { 2594 if (GetParam() != ResourceProvider::GLTexture) 2595 return; 2596 scoped_ptr<AllocationTrackingContext3D> context_owned( 2597 new StrictMock<AllocationTrackingContext3D>); 2598 AllocationTrackingContext3D* context = context_owned.get(); 2599 2600 FakeOutputSurfaceClient output_surface_client; 2601 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2602 context_owned.PassAs<TestWebGraphicsContext3D>())); 2603 CHECK(output_surface->BindToClient(&output_surface_client)); 2604 2605 gfx::Size size(2, 2); 2606 ResourceFormat format = RGBA_8888; 2607 ResourceProvider::ResourceId id = 0; 2608 int texture_id = 123; 2609 2610 scoped_ptr<ResourceProvider> resource_provider( 2611 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2612 2613 id = resource_provider->CreateResource( 2614 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2615 resource_provider->AcquirePixelBuffer(id); 2616 2617 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2618 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2619 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) 2620 .Times(1); 2621 resource_provider->BeginSetPixels(id); 2622 2623 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id)); 2624 2625 resource_provider->ReleasePixelBuffer(id); 2626 2627 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2628 resource_provider->DeleteResource(id); 2629 2630 Mock::VerifyAndClearExpectations(context); 2631} 2632 2633TEST_P(ResourceProviderTest, PixelBuffer_Bitmap) { 2634 if (GetParam() != ResourceProvider::Bitmap) 2635 return; 2636 FakeOutputSurfaceClient output_surface_client; 2637 scoped_ptr<OutputSurface> output_surface( 2638 FakeOutputSurface::CreateSoftware(make_scoped_ptr( 2639 new SoftwareOutputDevice))); 2640 CHECK(output_surface->BindToClient(&output_surface_client)); 2641 2642 gfx::Size size(1, 1); 2643 ResourceFormat format = RGBA_8888; 2644 ResourceProvider::ResourceId id = 0; 2645 const uint32_t kBadBeef = 0xbadbeef; 2646 2647 scoped_ptr<ResourceProvider> resource_provider( 2648 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2649 2650 id = resource_provider->CreateResource( 2651 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2652 resource_provider->AcquirePixelBuffer(id); 2653 2654 void* data = resource_provider->MapPixelBuffer(id); 2655 ASSERT_TRUE(!!data); 2656 memcpy(data, &kBadBeef, sizeof(kBadBeef)); 2657 resource_provider->UnmapPixelBuffer(id); 2658 2659 resource_provider->BeginSetPixels(id); 2660 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id)); 2661 2662 resource_provider->ReleasePixelBuffer(id); 2663 2664 { 2665 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id); 2666 const SkBitmap* sk_bitmap = lock.sk_bitmap(); 2667 EXPECT_EQ(sk_bitmap->width(), size.width()); 2668 EXPECT_EQ(sk_bitmap->height(), size.height()); 2669 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef); 2670 } 2671 2672 resource_provider->DeleteResource(id); 2673} 2674 2675TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { 2676 // Only for GL textures. 2677 if (GetParam() != ResourceProvider::GLTexture) 2678 return; 2679 scoped_ptr<AllocationTrackingContext3D> context_owned( 2680 new StrictMock<AllocationTrackingContext3D>); 2681 AllocationTrackingContext3D* context = context_owned.get(); 2682 2683 FakeOutputSurfaceClient output_surface_client; 2684 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2685 context_owned.PassAs<TestWebGraphicsContext3D>())); 2686 CHECK(output_surface->BindToClient(&output_surface_client)); 2687 2688 gfx::Size size(2, 2); 2689 ResourceFormat format = RGBA_8888; 2690 ResourceProvider::ResourceId id = 0; 2691 int texture_id = 123; 2692 2693 scoped_ptr<ResourceProvider> resource_provider( 2694 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2695 2696 id = resource_provider->CreateResource( 2697 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2698 resource_provider->AcquirePixelBuffer(id); 2699 2700 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2701 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2702 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _)) 2703 .Times(1); 2704 resource_provider->BeginSetPixels(id); 2705 2706 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); 2707 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1); 2708 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1); 2709 resource_provider->ForceSetPixelsToComplete(id); 2710 2711 resource_provider->ReleasePixelBuffer(id); 2712 2713 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2714 resource_provider->DeleteResource(id); 2715 2716 Mock::VerifyAndClearExpectations(context); 2717} 2718 2719TEST_P(ResourceProviderTest, PixelBufferLostContext) { 2720 scoped_ptr<AllocationTrackingContext3D> context_owned( 2721 new NiceMock<AllocationTrackingContext3D>); 2722 AllocationTrackingContext3D* context = context_owned.get(); 2723 2724 FakeOutputSurfaceClient output_surface_client; 2725 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2726 context_owned.PassAs<TestWebGraphicsContext3D>())); 2727 CHECK(output_surface->BindToClient(&output_surface_client)); 2728 2729 gfx::Size size(2, 2); 2730 ResourceFormat format = RGBA_8888; 2731 ResourceProvider::ResourceId id = 0; 2732 int texture_id = 123; 2733 2734 scoped_ptr<ResourceProvider> resource_provider( 2735 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2736 2737 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id)); 2738 2739 id = resource_provider->CreateResource( 2740 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2741 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 2742 GL_INNOCENT_CONTEXT_RESET_ARB); 2743 resource_provider->AcquirePixelBuffer(id); 2744 uint8_t* buffer = resource_provider->MapPixelBuffer(id); 2745 EXPECT_TRUE(buffer == NULL); 2746 resource_provider->UnmapPixelBuffer(id); 2747 resource_provider->ReleasePixelBuffer(id); 2748 Mock::VerifyAndClearExpectations(context); 2749} 2750 2751TEST_P(ResourceProviderTest, Image_GLTexture) { 2752 // Only for GL textures. 2753 if (GetParam() != ResourceProvider::GLTexture) 2754 return; 2755 scoped_ptr<AllocationTrackingContext3D> context_owned( 2756 new StrictMock<AllocationTrackingContext3D>); 2757 AllocationTrackingContext3D* context = context_owned.get(); 2758 2759 FakeOutputSurfaceClient output_surface_client; 2760 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2761 context_owned.PassAs<TestWebGraphicsContext3D>())); 2762 CHECK(output_surface->BindToClient(&output_surface_client)); 2763 2764 const int kWidth = 2; 2765 const int kHeight = 2; 2766 gfx::Size size(kWidth, kHeight); 2767 ResourceFormat format = RGBA_8888; 2768 ResourceProvider::ResourceId id = 0; 2769 const unsigned kTextureId = 123u; 2770 const unsigned kImageId = 234u; 2771 2772 scoped_ptr<ResourceProvider> resource_provider( 2773 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2774 2775 id = resource_provider->CreateResource( 2776 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2777 EXPECT_CALL(*context, createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES)) 2778 .WillOnce(Return(kImageId)) 2779 .RetiresOnSaturation(); 2780 resource_provider->AcquireImage(id); 2781 2782 void* dummy_mapped_buffer_address = NULL; 2783 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE)) 2784 .WillOnce(Return(dummy_mapped_buffer_address)) 2785 .RetiresOnSaturation(); 2786 resource_provider->MapImage(id); 2787 2788 const int kStride = 4; 2789 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId, 2790 GL_IMAGE_ROWBYTES_CHROMIUM, 2791 _)) 2792 .WillOnce(SetArgPointee<2>(kStride)) 2793 .RetiresOnSaturation(); 2794 int stride = resource_provider->GetImageStride(id); 2795 EXPECT_EQ(kStride, stride); 2796 2797 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId)) 2798 .Times(1) 2799 .RetiresOnSaturation(); 2800 resource_provider->UnmapImage(id); 2801 2802 EXPECT_CALL(*context, NextTextureId()) 2803 .WillOnce(Return(kTextureId)) 2804 .RetiresOnSaturation(); 2805 // Once in CreateTextureId and once in BindForSampling 2806 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2) 2807 .RetiresOnSaturation(); 2808 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) 2809 .Times(1) 2810 .RetiresOnSaturation(); 2811 { 2812 ResourceProvider::ScopedSamplerGL lock_gl( 2813 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); 2814 EXPECT_EQ(kTextureId, lock_gl.texture_id()); 2815 } 2816 2817 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE)) 2818 .WillOnce(Return(dummy_mapped_buffer_address)) 2819 .RetiresOnSaturation(); 2820 resource_provider->MapImage(id); 2821 2822 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId)) 2823 .Times(1) 2824 .RetiresOnSaturation(); 2825 resource_provider->UnmapImage(id); 2826 2827 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1) 2828 .RetiresOnSaturation(); 2829 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) 2830 .Times(1) 2831 .RetiresOnSaturation(); 2832 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) 2833 .Times(1) 2834 .RetiresOnSaturation(); 2835 EXPECT_CALL(*context, RetireTextureId(kTextureId)) 2836 .Times(1) 2837 .RetiresOnSaturation(); 2838 { 2839 ResourceProvider::ScopedSamplerGL lock_gl( 2840 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); 2841 EXPECT_EQ(kTextureId, lock_gl.texture_id()); 2842 } 2843 2844 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) 2845 .Times(1) 2846 .RetiresOnSaturation(); 2847 resource_provider->ReleaseImage(id); 2848} 2849 2850TEST_P(ResourceProviderTest, Image_Bitmap) { 2851 if (GetParam() != ResourceProvider::Bitmap) 2852 return; 2853 FakeOutputSurfaceClient output_surface_client; 2854 scoped_ptr<OutputSurface> output_surface( 2855 FakeOutputSurface::CreateSoftware(make_scoped_ptr( 2856 new SoftwareOutputDevice))); 2857 CHECK(output_surface->BindToClient(&output_surface_client)); 2858 2859 gfx::Size size(1, 1); 2860 ResourceFormat format = RGBA_8888; 2861 ResourceProvider::ResourceId id = 0; 2862 const uint32_t kBadBeef = 0xbadbeef; 2863 2864 scoped_ptr<ResourceProvider> resource_provider( 2865 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2866 2867 id = resource_provider->CreateResource( 2868 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 2869 resource_provider->AcquireImage(id); 2870 2871 const int kStride = 0; 2872 int stride = resource_provider->GetImageStride(id); 2873 EXPECT_EQ(kStride, stride); 2874 2875 void* data = resource_provider->MapImage(id); 2876 ASSERT_TRUE(!!data); 2877 memcpy(data, &kBadBeef, sizeof(kBadBeef)); 2878 resource_provider->UnmapImage(id); 2879 2880 { 2881 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id); 2882 const SkBitmap* sk_bitmap = lock.sk_bitmap(); 2883 EXPECT_EQ(sk_bitmap->width(), size.width()); 2884 EXPECT_EQ(sk_bitmap->height(), size.height()); 2885 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef); 2886 } 2887 2888 resource_provider->ReleaseImage(id); 2889 resource_provider->DeleteResource(id); 2890} 2891 2892void InitializeGLAndCheck(ContextSharedData* shared_data, 2893 ResourceProvider* resource_provider, 2894 FakeOutputSurface* output_surface) { 2895 scoped_ptr<ResourceProviderContext> context_owned = 2896 ResourceProviderContext::Create(shared_data); 2897 ResourceProviderContext* context = context_owned.get(); 2898 2899 scoped_refptr<TestContextProvider> context_provider = 2900 TestContextProvider::Create( 2901 context_owned.PassAs<TestWebGraphicsContext3D>()); 2902 output_surface->InitializeAndSetContext3d(context_provider, NULL); 2903 EXPECT_TRUE(resource_provider->InitializeGL()); 2904 2905 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context); 2906} 2907 2908TEST(ResourceProviderTest, BasicInitializeGLSoftware) { 2909 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create(); 2910 FakeOutputSurfaceClient client; 2911 scoped_ptr<FakeOutputSurface> output_surface( 2912 FakeOutputSurface::CreateDeferredGL( 2913 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice))); 2914 EXPECT_TRUE(output_surface->BindToClient(&client)); 2915 scoped_ptr<ResourceProvider> resource_provider( 2916 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1)); 2917 2918 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL); 2919 2920 InitializeGLAndCheck(shared_data.get(), 2921 resource_provider.get(), 2922 output_surface.get()); 2923 2924 resource_provider->InitializeSoftware(); 2925 output_surface->ReleaseGL(); 2926 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL); 2927 2928 InitializeGLAndCheck(shared_data.get(), 2929 resource_provider.get(), 2930 output_surface.get()); 2931} 2932 2933TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { 2934 if (GetParam() != ResourceProvider::GLTexture) 2935 return; 2936 2937 scoped_ptr<AllocationTrackingContext3D> context_owned( 2938 new AllocationTrackingContext3D); 2939 AllocationTrackingContext3D* context = context_owned.get(); 2940 context_owned->set_support_compressed_texture_etc1(true); 2941 2942 FakeOutputSurfaceClient output_surface_client; 2943 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2944 context_owned.PassAs<TestWebGraphicsContext3D>())); 2945 CHECK(output_surface->BindToClient(&output_surface_client)); 2946 2947 gfx::Size size(4, 4); 2948 scoped_ptr<ResourceProvider> resource_provider( 2949 ResourceProvider::Create(output_surface.get(), 2950 shared_bitmap_manager_.get(), 2951 0, 2952 false, 2953 1)); 2954 int texture_id = 123; 2955 2956 ResourceProvider::ResourceId id = resource_provider->CreateResource( 2957 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1); 2958 EXPECT_NE(0u, id); 2959 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2960 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); 2961 resource_provider->AllocateForTesting(id); 2962 2963 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 2964 resource_provider->DeleteResource(id); 2965} 2966 2967TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) { 2968 if (GetParam() != ResourceProvider::GLTexture) 2969 return; 2970 2971 scoped_ptr<AllocationTrackingContext3D> context_owned( 2972 new AllocationTrackingContext3D); 2973 AllocationTrackingContext3D* context = context_owned.get(); 2974 context_owned->set_support_compressed_texture_etc1(true); 2975 2976 FakeOutputSurfaceClient output_surface_client; 2977 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 2978 context_owned.PassAs<TestWebGraphicsContext3D>())); 2979 CHECK(output_surface->BindToClient(&output_surface_client)); 2980 2981 gfx::Size size(4, 4); 2982 scoped_ptr<ResourceProvider> resource_provider( 2983 ResourceProvider::Create(output_surface.get(), 2984 shared_bitmap_manager_.get(), 2985 0, 2986 false, 2987 1)); 2988 int texture_id = 123; 2989 uint8_t pixels[8]; 2990 2991 ResourceProvider::ResourceId id = resource_provider->CreateResource( 2992 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1); 2993 EXPECT_NE(0u, id); 2994 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); 2995 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); 2996 EXPECT_CALL(*context, 2997 compressedTexImage2D( 2998 _, 0, _, size.width(), size.height(), _, _, _)).Times(1); 2999 resource_provider->SetPixels( 3000 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0)); 3001 3002 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); 3003 resource_provider->DeleteResource(id); 3004} 3005 3006INSTANTIATE_TEST_CASE_P( 3007 ResourceProviderTests, 3008 ResourceProviderTest, 3009 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap)); 3010 3011class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D { 3012 public: 3013 virtual GLuint NextTextureId() OVERRIDE { 3014 base::AutoLock lock(namespace_->lock); 3015 return namespace_->next_texture_id++; 3016 } 3017 virtual void RetireTextureId(GLuint) OVERRIDE {} 3018 GLuint PeekTextureId() { 3019 base::AutoLock lock(namespace_->lock); 3020 return namespace_->next_texture_id; 3021 } 3022}; 3023 3024TEST(ResourceProviderTest, TextureAllocationChunkSize) { 3025 scoped_ptr<TextureIdAllocationTrackingContext> context_owned( 3026 new TextureIdAllocationTrackingContext); 3027 TextureIdAllocationTrackingContext* context = context_owned.get(); 3028 3029 FakeOutputSurfaceClient output_surface_client; 3030 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d( 3031 context_owned.PassAs<TestWebGraphicsContext3D>())); 3032 CHECK(output_surface->BindToClient(&output_surface_client)); 3033 3034 gfx::Size size(1, 1); 3035 ResourceFormat format = RGBA_8888; 3036 3037 { 3038 size_t kTextureAllocationChunkSize = 1; 3039 scoped_ptr<ResourceProvider> resource_provider( 3040 ResourceProvider::Create(output_surface.get(), 3041 NULL, 3042 0, 3043 false, 3044 kTextureAllocationChunkSize)); 3045 3046 ResourceProvider::ResourceId id = resource_provider->CreateResource( 3047 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 3048 resource_provider->AllocateForTesting(id); 3049 Mock::VerifyAndClearExpectations(context); 3050 3051 DCHECK_EQ(2u, context->PeekTextureId()); 3052 resource_provider->DeleteResource(id); 3053 } 3054 3055 { 3056 size_t kTextureAllocationChunkSize = 8; 3057 scoped_ptr<ResourceProvider> resource_provider( 3058 ResourceProvider::Create(output_surface.get(), 3059 NULL, 3060 0, 3061 false, 3062 kTextureAllocationChunkSize)); 3063 3064 ResourceProvider::ResourceId id = resource_provider->CreateResource( 3065 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format); 3066 resource_provider->AllocateForTesting(id); 3067 Mock::VerifyAndClearExpectations(context); 3068 3069 DCHECK_EQ(10u, context->PeekTextureId()); 3070 resource_provider->DeleteResource(id); 3071 } 3072} 3073 3074} // namespace 3075} // namespace cc 3076