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