1 // Copyright 2011 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/test/test_web_graphics_context_3d.h" 6 7 #include <algorithm> 8 #include <string> 9 10 #include "base/bind.h" 11 #include "base/lazy_instance.h" 12 #include "base/logging.h" 13 #include "base/message_loop/message_loop.h" 14 #include "gpu/GLES2/gl2extchromium.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "third_party/khronos/GLES2/gl2ext.h" 17 18 using WebKit::WGC3Dboolean; 19 using WebKit::WGC3Dchar; 20 using WebKit::WGC3Denum; 21 using WebKit::WGC3Dint; 22 using WebKit::WGC3Dsizei; 23 using WebKit::WGC3Dsizeiptr; 24 using WebKit::WGC3Duint; 25 using WebKit::WebGLId; 26 using WebKit::WebGraphicsContext3D; 27 28 namespace cc { 29 30 static const WebGLId kFramebufferId = 1; 31 static const WebGLId kProgramId = 2; 32 static const WebGLId kRenderbufferId = 3; 33 static const WebGLId kShaderId = 4; 34 35 static unsigned s_context_id = 1; 36 37 const WebGLId TestWebGraphicsContext3D::kExternalTextureId = 1337; 38 39 static base::LazyInstance<base::Lock>::Leaky 40 g_shared_namespace_lock = LAZY_INSTANCE_INITIALIZER; 41 42 TestWebGraphicsContext3D::Namespace* 43 TestWebGraphicsContext3D::shared_namespace_ = NULL; 44 45 TestWebGraphicsContext3D::Namespace::Namespace() 46 : next_buffer_id(1), 47 next_image_id(1), 48 next_texture_id(1) { 49 } 50 51 TestWebGraphicsContext3D::Namespace::~Namespace() { 52 g_shared_namespace_lock.Get().AssertAcquired(); 53 if (shared_namespace_ == this) 54 shared_namespace_ = NULL; 55 } 56 57 TestWebGraphicsContext3D::TestWebGraphicsContext3D() 58 : FakeWebGraphicsContext3D(), 59 context_id_(s_context_id++), 60 support_swapbuffers_complete_callback_(true), 61 have_extension_io_surface_(false), 62 have_extension_egl_image_(false), 63 times_make_current_succeeds_(-1), 64 times_bind_texture_succeeds_(-1), 65 times_end_query_succeeds_(-1), 66 times_gen_mailbox_succeeds_(-1), 67 context_lost_(false), 68 times_map_image_chromium_succeeds_(-1), 69 times_map_buffer_chromium_succeeds_(-1), 70 context_lost_callback_(NULL), 71 swap_buffers_callback_(NULL), 72 memory_allocation_changed_callback_(NULL), 73 max_texture_size_(1024), 74 width_(0), 75 height_(0), 76 bound_buffer_(0), 77 weak_ptr_factory_(this) { 78 CreateNamespace(); 79 } 80 81 TestWebGraphicsContext3D::TestWebGraphicsContext3D( 82 const WebGraphicsContext3D::Attributes& attributes) 83 : FakeWebGraphicsContext3D(), 84 context_id_(s_context_id++), 85 attributes_(attributes), 86 support_swapbuffers_complete_callback_(true), 87 have_extension_io_surface_(false), 88 have_extension_egl_image_(false), 89 times_make_current_succeeds_(-1), 90 times_bind_texture_succeeds_(-1), 91 times_end_query_succeeds_(-1), 92 times_gen_mailbox_succeeds_(-1), 93 context_lost_(false), 94 times_map_image_chromium_succeeds_(-1), 95 times_map_buffer_chromium_succeeds_(-1), 96 context_lost_callback_(NULL), 97 swap_buffers_callback_(NULL), 98 memory_allocation_changed_callback_(NULL), 99 max_texture_size_(1024), 100 width_(0), 101 height_(0), 102 bound_buffer_(0), 103 weak_ptr_factory_(this) { 104 CreateNamespace(); 105 } 106 107 void TestWebGraphicsContext3D::CreateNamespace() { 108 if (attributes_.shareResources) { 109 base::AutoLock lock(g_shared_namespace_lock.Get()); 110 if (shared_namespace_) { 111 namespace_ = shared_namespace_; 112 } else { 113 namespace_ = new Namespace; 114 shared_namespace_ = namespace_.get(); 115 } 116 } else { 117 namespace_ = new Namespace; 118 } 119 } 120 121 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() { 122 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) { 123 if (sync_point_callbacks_[i] != NULL) 124 delete sync_point_callbacks_[i]; 125 } 126 base::AutoLock lock(g_shared_namespace_lock.Get()); 127 namespace_ = NULL; 128 } 129 130 bool TestWebGraphicsContext3D::makeContextCurrent() { 131 if (times_make_current_succeeds_ >= 0) { 132 if (!times_make_current_succeeds_) { 133 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 134 GL_INNOCENT_CONTEXT_RESET_ARB); 135 } 136 --times_make_current_succeeds_; 137 } 138 return !context_lost_; 139 } 140 141 int TestWebGraphicsContext3D::width() { 142 return width_; 143 } 144 145 int TestWebGraphicsContext3D::height() { 146 return height_; 147 } 148 149 void TestWebGraphicsContext3D::reshapeWithScaleFactor( 150 int width, int height, float scale_factor) { 151 width_ = width; 152 height_ = height; 153 } 154 155 bool TestWebGraphicsContext3D::isContextLost() { 156 return context_lost_; 157 } 158 159 WGC3Denum TestWebGraphicsContext3D::getGraphicsResetStatusARB() { 160 return context_lost_ ? GL_UNKNOWN_CONTEXT_RESET_ARB : GL_NO_ERROR; 161 } 162 163 WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus( 164 WGC3Denum target) { 165 if (context_lost_) 166 return GL_FRAMEBUFFER_UNDEFINED_OES; 167 return GL_FRAMEBUFFER_COMPLETE; 168 } 169 170 WebGraphicsContext3D::Attributes 171 TestWebGraphicsContext3D::getContextAttributes() { 172 return attributes_; 173 } 174 175 WebKit::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) { 176 std::string string; 177 178 if (support_swapbuffers_complete_callback_) 179 string += "GL_CHROMIUM_swapbuffers_complete_callback"; 180 181 if (name == GL_EXTENSIONS) { 182 if (have_extension_io_surface_) 183 string += " GL_CHROMIUM_iosurface GL_ARB_texture_rectangle"; 184 if (have_extension_egl_image_) 185 string += " GL_OES_EGL_image_external"; 186 } 187 188 return WebKit::WebString::fromUTF8(string.c_str()); 189 } 190 191 WGC3Dint TestWebGraphicsContext3D::getUniformLocation( 192 WebGLId program, 193 const WGC3Dchar* name) { 194 return 0; 195 } 196 197 WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset( 198 WGC3Duint index, 199 WGC3Denum pname) { 200 return 0; 201 } 202 203 WGC3Dboolean TestWebGraphicsContext3D::isBuffer( 204 WebGLId buffer) { 205 return false; 206 } 207 208 WGC3Dboolean TestWebGraphicsContext3D::isEnabled( 209 WGC3Denum cap) { 210 return false; 211 } 212 213 WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer( 214 WebGLId framebuffer) { 215 return false; 216 } 217 218 WGC3Dboolean TestWebGraphicsContext3D::isProgram( 219 WebGLId program) { 220 return false; 221 } 222 223 WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer( 224 WebGLId renderbuffer) { 225 return false; 226 } 227 228 WGC3Dboolean TestWebGraphicsContext3D::isShader( 229 WebGLId shader) { 230 return false; 231 } 232 233 WGC3Dboolean TestWebGraphicsContext3D::isTexture( 234 WebGLId texture) { 235 return false; 236 } 237 238 WebGLId TestWebGraphicsContext3D::createBuffer() { 239 return NextBufferId(); 240 } 241 242 void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) { 243 base::AutoLock lock(namespace_->lock); 244 unsigned context_id = id >> 17; 245 unsigned buffer_id = id & 0x1ffff; 246 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id); 247 DCHECK_EQ(context_id, context_id_); 248 } 249 250 WebGLId TestWebGraphicsContext3D::createFramebuffer() { 251 return kFramebufferId | context_id_ << 16; 252 } 253 254 void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) { 255 EXPECT_EQ(kFramebufferId | context_id_ << 16, id); 256 } 257 258 WebGLId TestWebGraphicsContext3D::createProgram() { 259 return kProgramId | context_id_ << 16; 260 } 261 262 void TestWebGraphicsContext3D::deleteProgram(WebGLId id) { 263 EXPECT_EQ(kProgramId | context_id_ << 16, id); 264 } 265 266 WebGLId TestWebGraphicsContext3D::createRenderbuffer() { 267 return kRenderbufferId | context_id_ << 16; 268 } 269 270 void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) { 271 EXPECT_EQ(kRenderbufferId | context_id_ << 16, id); 272 } 273 274 WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) { 275 return kShaderId | context_id_ << 16; 276 } 277 278 void TestWebGraphicsContext3D::deleteShader(WebGLId id) { 279 EXPECT_EQ(kShaderId | context_id_ << 16, id); 280 } 281 282 WebGLId TestWebGraphicsContext3D::createTexture() { 283 WebGLId texture_id = NextTextureId(); 284 DCHECK_NE(texture_id, kExternalTextureId); 285 base::AutoLock lock(namespace_->lock); 286 namespace_->textures.push_back(texture_id); 287 return texture_id; 288 } 289 290 void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id) { 291 base::AutoLock lock(namespace_->lock); 292 std::vector<WebKit::WebGLId>& textures = namespace_->textures; 293 DCHECK(std::find(textures.begin(), textures.end(), texture_id) != 294 textures.end()); 295 textures.erase(std::find(textures.begin(), textures.end(), texture_id)); 296 } 297 298 void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) { 299 EXPECT_EQ(kProgramId | context_id_ << 16, program); 300 EXPECT_EQ(kShaderId | context_id_ << 16, shader); 301 } 302 303 void TestWebGraphicsContext3D::useProgram(WebGLId program) { 304 if (!program) 305 return; 306 EXPECT_EQ(kProgramId | context_id_ << 16, program); 307 } 308 309 void TestWebGraphicsContext3D::bindFramebuffer( 310 WGC3Denum target, WebGLId framebuffer) { 311 if (!framebuffer) 312 return; 313 EXPECT_EQ(kFramebufferId | context_id_ << 16, framebuffer); 314 } 315 316 void TestWebGraphicsContext3D::bindRenderbuffer( 317 WGC3Denum target, WebGLId renderbuffer) { 318 if (!renderbuffer) 319 return; 320 EXPECT_EQ(kRenderbufferId | context_id_ << 16, renderbuffer); 321 } 322 323 void TestWebGraphicsContext3D::bindTexture( 324 WGC3Denum target, WebGLId texture_id) { 325 if (times_bind_texture_succeeds_ >= 0) { 326 if (!times_bind_texture_succeeds_) { 327 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 328 GL_INNOCENT_CONTEXT_RESET_ARB); 329 } 330 --times_bind_texture_succeeds_; 331 } 332 333 if (!texture_id) 334 return; 335 if (texture_id == kExternalTextureId) 336 return; 337 base::AutoLock lock(namespace_->lock); 338 std::vector<WebKit::WebGLId>& textures = namespace_->textures; 339 DCHECK(std::find(textures.begin(), textures.end(), texture_id) != 340 textures.end()); 341 used_textures_.insert(texture_id); 342 } 343 344 void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target) { 345 if (times_end_query_succeeds_ >= 0) { 346 if (!times_end_query_succeeds_) { 347 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 348 GL_INNOCENT_CONTEXT_RESET_ARB); 349 } 350 --times_end_query_succeeds_; 351 } 352 } 353 354 void TestWebGraphicsContext3D::getQueryObjectuivEXT( 355 WebGLId query, 356 WGC3Denum pname, 357 WGC3Duint* params) { 358 // If the context is lost, behave as if result is available. 359 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) 360 *params = 1; 361 } 362 363 void TestWebGraphicsContext3D::getIntegerv( 364 WGC3Denum pname, 365 WebKit::WGC3Dint* value) { 366 if (pname == GL_MAX_TEXTURE_SIZE) 367 *value = max_texture_size_; 368 else if (pname == GL_ACTIVE_TEXTURE) 369 *value = GL_TEXTURE0; 370 } 371 372 void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox) { 373 if (times_gen_mailbox_succeeds_ >= 0) { 374 if (!times_gen_mailbox_succeeds_) { 375 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 376 GL_INNOCENT_CONTEXT_RESET_ARB); 377 } 378 --times_gen_mailbox_succeeds_; 379 } 380 if (context_lost_) { 381 memset(mailbox, 0, 64); 382 return; 383 } 384 385 static char mailbox_name1 = '1'; 386 static char mailbox_name2 = '1'; 387 mailbox[0] = mailbox_name1; 388 mailbox[1] = mailbox_name2; 389 mailbox[2] = '\0'; 390 if (++mailbox_name1 == 0) { 391 mailbox_name1 = '1'; 392 ++mailbox_name2; 393 } 394 } 395 396 void TestWebGraphicsContext3D::setContextLostCallback( 397 WebGraphicsContextLostCallback* callback) { 398 context_lost_callback_ = callback; 399 } 400 401 void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current, 402 WGC3Denum other) { 403 if (context_lost_) 404 return; 405 context_lost_ = true; 406 if (context_lost_callback_) 407 context_lost_callback_->onContextLost(); 408 409 for (size_t i = 0; i < shared_contexts_.size(); ++i) 410 shared_contexts_[i]->loseContextCHROMIUM(current, other); 411 shared_contexts_.clear(); 412 } 413 414 void TestWebGraphicsContext3D::signalSyncPoint( 415 unsigned sync_point, 416 WebGraphicsSyncPointCallback* callback) { 417 sync_point_callbacks_.push_back(callback); 418 } 419 420 void TestWebGraphicsContext3D::signalQuery( 421 WebKit::WebGLId query, 422 WebGraphicsSyncPointCallback* callback) { 423 sync_point_callbacks_.push_back(callback); 424 } 425 426 void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM( 427 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) { 428 if (support_swapbuffers_complete_callback_) 429 swap_buffers_callback_ = callback; 430 } 431 432 void TestWebGraphicsContext3D::setMemoryAllocationChangedCallbackCHROMIUM( 433 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { 434 memory_allocation_changed_callback_ = callback; 435 } 436 437 void TestWebGraphicsContext3D::prepareTexture() { 438 if (swap_buffers_callback_) { 439 base::MessageLoop::current()->PostTask( 440 FROM_HERE, base::Bind(&TestWebGraphicsContext3D::SwapBuffersComplete, 441 weak_ptr_factory_.GetWeakPtr())); 442 } 443 CallAllSyncPointCallbacks(); 444 } 445 446 void TestWebGraphicsContext3D::finish() { 447 CallAllSyncPointCallbacks(); 448 } 449 450 void TestWebGraphicsContext3D::flush() { 451 CallAllSyncPointCallbacks(); 452 } 453 454 static void CallAndDestroy( 455 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback* callback) { 456 if (!callback) 457 return; 458 callback->onSyncPointReached(); 459 delete callback; 460 } 461 462 void TestWebGraphicsContext3D::CallAllSyncPointCallbacks() { 463 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) { 464 base::MessageLoop::current()->PostTask( 465 FROM_HERE, 466 base::Bind(&CallAndDestroy, 467 sync_point_callbacks_[i])); 468 } 469 sync_point_callbacks_.clear(); 470 } 471 472 void TestWebGraphicsContext3D::SwapBuffersComplete() { 473 if (swap_buffers_callback_) 474 swap_buffers_callback_->onSwapBuffersComplete(); 475 } 476 477 void TestWebGraphicsContext3D::bindBuffer(WebKit::WGC3Denum target, 478 WebKit::WebGLId buffer) { 479 bound_buffer_ = buffer; 480 if (!bound_buffer_) 481 return; 482 unsigned context_id = buffer >> 17; 483 unsigned buffer_id = buffer & 0x1ffff; 484 base::AutoLock lock(namespace_->lock); 485 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id); 486 DCHECK_EQ(context_id, context_id_); 487 488 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers; 489 if (buffers.count(bound_buffer_) == 0) 490 buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass()); 491 492 buffers.get(bound_buffer_)->target = target; 493 } 494 495 void TestWebGraphicsContext3D::bufferData(WebKit::WGC3Denum target, 496 WebKit::WGC3Dsizeiptr size, 497 const void* data, 498 WebKit::WGC3Denum usage) { 499 base::AutoLock lock(namespace_->lock); 500 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers; 501 DCHECK_GT(buffers.count(bound_buffer_), 0u); 502 DCHECK_EQ(target, buffers.get(bound_buffer_)->target); 503 if (context_lost_) { 504 buffers.get(bound_buffer_)->pixels.reset(); 505 return; 506 } 507 buffers.get(bound_buffer_)->pixels.reset(new uint8[size]); 508 if (data != NULL) 509 memcpy(buffers.get(bound_buffer_)->pixels.get(), data, size); 510 } 511 512 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(WebKit::WGC3Denum target, 513 WebKit::WGC3Denum access) { 514 base::AutoLock lock(namespace_->lock); 515 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers; 516 DCHECK_GT(buffers.count(bound_buffer_), 0u); 517 DCHECK_EQ(target, buffers.get(bound_buffer_)->target); 518 if (times_map_buffer_chromium_succeeds_ >= 0) { 519 if (!times_map_buffer_chromium_succeeds_) { 520 return NULL; 521 } 522 --times_map_buffer_chromium_succeeds_; 523 } 524 return buffers.get(bound_buffer_)->pixels.get(); 525 } 526 527 WebKit::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM( 528 WebKit::WGC3Denum target) { 529 base::AutoLock lock(namespace_->lock); 530 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers; 531 DCHECK_GT(buffers.count(bound_buffer_), 0u); 532 DCHECK_EQ(target, buffers.get(bound_buffer_)->target); 533 buffers.get(bound_buffer_)->pixels.reset(); 534 return true; 535 } 536 537 void TestWebGraphicsContext3D::bindTexImage2DCHROMIUM( 538 WebKit::WGC3Denum target, 539 WebKit::WGC3Dint image_id) { 540 base::AutoLock lock(namespace_->lock); 541 DCHECK_GT(namespace_->images.count(image_id), 0u); 542 } 543 544 WebKit::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM( 545 WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height, 546 WebKit::WGC3Denum internalformat) { 547 DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat)); 548 WebKit::WGC3Duint image_id = NextImageId(); 549 base::AutoLock lock(namespace_->lock); 550 ScopedPtrHashMap<unsigned, Image>& images = namespace_->images; 551 images.set(image_id, make_scoped_ptr(new Image).Pass()); 552 images.get(image_id)->pixels.reset(new uint8[width * height * 4]); 553 return image_id; 554 } 555 556 void TestWebGraphicsContext3D::destroyImageCHROMIUM( 557 WebKit::WGC3Duint id) { 558 base::AutoLock lock(namespace_->lock); 559 unsigned context_id = id >> 17; 560 unsigned image_id = id & 0x1ffff; 561 DCHECK(image_id && image_id < namespace_->next_image_id); 562 DCHECK_EQ(context_id, context_id_); 563 } 564 565 void TestWebGraphicsContext3D::getImageParameterivCHROMIUM( 566 WebKit::WGC3Duint image_id, 567 WebKit::WGC3Denum pname, 568 WebKit::WGC3Dint* params) { 569 base::AutoLock lock(namespace_->lock); 570 DCHECK_GT(namespace_->images.count(image_id), 0u); 571 DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname)); 572 *params = 0; 573 } 574 575 void* TestWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id, 576 WebKit::WGC3Denum access) { 577 base::AutoLock lock(namespace_->lock); 578 ScopedPtrHashMap<unsigned, Image>& images = namespace_->images; 579 DCHECK_GT(images.count(image_id), 0u); 580 if (times_map_image_chromium_succeeds_ >= 0) { 581 if (!times_map_image_chromium_succeeds_) { 582 return NULL; 583 } 584 --times_map_image_chromium_succeeds_; 585 } 586 return images.get(image_id)->pixels.get(); 587 } 588 589 void TestWebGraphicsContext3D::unmapImageCHROMIUM( 590 WebKit::WGC3Duint image_id) { 591 base::AutoLock lock(namespace_->lock); 592 DCHECK_GT(namespace_->images.count(image_id), 0u); 593 } 594 595 size_t TestWebGraphicsContext3D::NumTextures() const { 596 base::AutoLock lock(namespace_->lock); 597 return namespace_->textures.size(); 598 } 599 600 WebKit::WebGLId TestWebGraphicsContext3D::TextureAt(int i) const { 601 base::AutoLock lock(namespace_->lock); 602 return namespace_->textures[i]; 603 } 604 605 WebGLId TestWebGraphicsContext3D::NextTextureId() { 606 base::AutoLock lock(namespace_->lock); 607 WebGLId texture_id = namespace_->next_texture_id++; 608 DCHECK(texture_id < (1 << 16)); 609 texture_id |= context_id_ << 16; 610 return texture_id; 611 } 612 613 WebGLId TestWebGraphicsContext3D::NextBufferId() { 614 base::AutoLock lock(namespace_->lock); 615 WebGLId buffer_id = namespace_->next_buffer_id++; 616 DCHECK(buffer_id < (1 << 17)); 617 buffer_id |= context_id_ << 17; 618 return buffer_id; 619 } 620 621 WebKit::WGC3Duint TestWebGraphicsContext3D::NextImageId() { 622 base::AutoLock lock(namespace_->lock); 623 WGC3Duint image_id = namespace_->next_image_id++; 624 DCHECK(image_id < (1 << 17)); 625 image_id |= context_id_ << 17; 626 return image_id; 627 } 628 629 void TestWebGraphicsContext3D::SetMemoryAllocation( 630 WebKit::WebGraphicsMemoryAllocation allocation) { 631 if (!memory_allocation_changed_callback_) 632 return; 633 memory_allocation_changed_callback_->onMemoryAllocationChanged(allocation); 634 } 635 636 TestWebGraphicsContext3D::Buffer::Buffer() : target(0) {} 637 638 TestWebGraphicsContext3D::Buffer::~Buffer() {} 639 640 TestWebGraphicsContext3D::Image::Image() {} 641 642 TestWebGraphicsContext3D::Image::~Image() {} 643 644 } // namespace cc 645