Home | History | Annotate | Download | only in test
      1 // Copyright 2013 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 "cc/test/test_context_support.h"
     15 #include "gpu/GLES2/gl2extchromium.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "third_party/khronos/GLES2/gl2ext.h"
     18 
     19 using blink::WGC3Dboolean;
     20 using blink::WGC3Dchar;
     21 using blink::WGC3Denum;
     22 using blink::WGC3Dint;
     23 using blink::WGC3Dsizei;
     24 using blink::WGC3Dsizeiptr;
     25 using blink::WGC3Duint;
     26 using blink::WebGLId;
     27 using blink::WebGraphicsContext3D;
     28 
     29 namespace cc {
     30 
     31 static const WebGLId kFramebufferId = 1;
     32 static const WebGLId kRenderbufferId = 2;
     33 
     34 static unsigned s_context_id = 1;
     35 
     36 const WebGLId TestWebGraphicsContext3D::kExternalTextureId = 1337;
     37 
     38 static base::LazyInstance<base::Lock>::Leaky
     39     g_shared_namespace_lock = LAZY_INSTANCE_INITIALIZER;
     40 
     41 TestWebGraphicsContext3D::Namespace*
     42     TestWebGraphicsContext3D::shared_namespace_ = NULL;
     43 
     44 TestWebGraphicsContext3D::Namespace::Namespace()
     45     : next_buffer_id(1),
     46       next_image_id(1),
     47       next_texture_id(1) {
     48 }
     49 
     50 TestWebGraphicsContext3D::Namespace::~Namespace() {
     51   g_shared_namespace_lock.Get().AssertAcquired();
     52   if (shared_namespace_ == this)
     53     shared_namespace_ = NULL;
     54 }
     55 
     56 // static
     57 scoped_ptr<TestWebGraphicsContext3D> TestWebGraphicsContext3D::Create() {
     58   return make_scoped_ptr(new TestWebGraphicsContext3D());
     59 }
     60 
     61 TestWebGraphicsContext3D::TestWebGraphicsContext3D()
     62     : FakeWebGraphicsContext3D(),
     63       context_id_(s_context_id++),
     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       next_program_id_(1000),
     72       next_shader_id_(2000),
     73       max_texture_size_(2048),
     74       reshape_called_(false),
     75       width_(0),
     76       height_(0),
     77       scale_factor_(-1.f),
     78       test_support_(NULL),
     79       last_update_type_(NoUpdate),
     80       next_insert_sync_point_(1),
     81       last_waited_sync_point_(0),
     82       bound_buffer_(0),
     83       peak_transfer_buffer_memory_used_bytes_(0),
     84       weak_ptr_factory_(this) {
     85   CreateNamespace();
     86 }
     87 
     88 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
     89   base::AutoLock lock(g_shared_namespace_lock.Get());
     90   namespace_ = NULL;
     91 }
     92 
     93 void TestWebGraphicsContext3D::CreateNamespace() {
     94   if (attributes_.shareResources) {
     95     base::AutoLock lock(g_shared_namespace_lock.Get());
     96     if (shared_namespace_) {
     97       namespace_ = shared_namespace_;
     98     } else {
     99       namespace_ = new Namespace;
    100       shared_namespace_ = namespace_.get();
    101     }
    102   } else {
    103     namespace_ = new Namespace;
    104   }
    105 }
    106 
    107 void TestWebGraphicsContext3D::reshapeWithScaleFactor(
    108     int width, int height, float scale_factor) {
    109   reshape_called_ = true;
    110   width_ = width;
    111   height_ = height;
    112   scale_factor_ = scale_factor;
    113 }
    114 
    115 bool TestWebGraphicsContext3D::isContextLost() {
    116   return context_lost_;
    117 }
    118 
    119 WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus(
    120     WGC3Denum target) {
    121   if (context_lost_)
    122     return GL_FRAMEBUFFER_UNDEFINED_OES;
    123   return GL_FRAMEBUFFER_COMPLETE;
    124 }
    125 
    126 WebGraphicsContext3D::Attributes
    127     TestWebGraphicsContext3D::getContextAttributes() {
    128   return attributes_;
    129 }
    130 
    131 blink::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) {
    132   return blink::WebString();
    133 }
    134 
    135 WGC3Dint TestWebGraphicsContext3D::getUniformLocation(
    136     WebGLId program,
    137     const WGC3Dchar* name) {
    138   return 0;
    139 }
    140 
    141 WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset(
    142     WGC3Duint index,
    143     WGC3Denum pname) {
    144   return 0;
    145 }
    146 
    147 WGC3Dboolean TestWebGraphicsContext3D::isBuffer(
    148     WebGLId buffer) {
    149   return false;
    150 }
    151 
    152 WGC3Dboolean TestWebGraphicsContext3D::isEnabled(
    153     WGC3Denum cap) {
    154   return false;
    155 }
    156 
    157 WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer(
    158     WebGLId framebuffer) {
    159   return false;
    160 }
    161 
    162 WGC3Dboolean TestWebGraphicsContext3D::isProgram(
    163     WebGLId program) {
    164   return false;
    165 }
    166 
    167 WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer(
    168     WebGLId renderbuffer) {
    169   return false;
    170 }
    171 
    172 WGC3Dboolean TestWebGraphicsContext3D::isShader(
    173     WebGLId shader) {
    174   return false;
    175 }
    176 
    177 WGC3Dboolean TestWebGraphicsContext3D::isTexture(
    178     WebGLId texture) {
    179   return false;
    180 }
    181 
    182 void TestWebGraphicsContext3D::genBuffers(WGC3Dsizei count, WebGLId* ids) {
    183   for (int i = 0; i < count; ++i)
    184     ids[i] = NextBufferId();
    185 }
    186 
    187 void TestWebGraphicsContext3D::genFramebuffers(
    188     WGC3Dsizei count, WebGLId* ids) {
    189   for (int i = 0; i < count; ++i)
    190     ids[i] = kFramebufferId | context_id_ << 16;
    191 }
    192 
    193 void TestWebGraphicsContext3D::genRenderbuffers(
    194     WGC3Dsizei count, WebGLId* ids) {
    195   for (int i = 0; i < count; ++i)
    196     ids[i] = kRenderbufferId | context_id_ << 16;
    197 }
    198 
    199 void TestWebGraphicsContext3D::genTextures(WGC3Dsizei count, WebGLId* ids) {
    200   for (int i = 0; i < count; ++i) {
    201     ids[i] = NextTextureId();
    202     DCHECK_NE(ids[i], kExternalTextureId);
    203   }
    204   base::AutoLock lock(namespace_->lock);
    205   for (int i = 0; i < count; ++i)
    206     namespace_->textures.Append(ids[i], new TestTexture());
    207 }
    208 
    209 void TestWebGraphicsContext3D::deleteBuffers(WGC3Dsizei count, WebGLId* ids) {
    210   for (int i = 0; i < count; ++i)
    211     RetireBufferId(ids[i]);
    212 }
    213 
    214 void TestWebGraphicsContext3D::deleteFramebuffers(
    215     WGC3Dsizei count, WebGLId* ids) {
    216   for (int i = 0; i < count; ++i)
    217     DCHECK_EQ(kFramebufferId | context_id_ << 16, ids[i]);
    218 }
    219 
    220 void TestWebGraphicsContext3D::deleteRenderbuffers(
    221     WGC3Dsizei count, WebGLId* ids) {
    222   for (int i = 0; i < count; ++i)
    223     DCHECK_EQ(kRenderbufferId | context_id_ << 16, ids[i]);
    224 }
    225 
    226 void TestWebGraphicsContext3D::deleteTextures(WGC3Dsizei count, WebGLId* ids) {
    227   for (int i = 0; i < count; ++i)
    228     RetireTextureId(ids[i]);
    229   base::AutoLock lock(namespace_->lock);
    230   for (int i = 0; i < count; ++i) {
    231     namespace_->textures.Remove(ids[i]);
    232     texture_targets_.UnbindTexture(ids[i]);
    233   }
    234 }
    235 
    236 WebGLId TestWebGraphicsContext3D::createBuffer() {
    237   WebGLId id;
    238   genBuffers(1, &id);
    239   return id;
    240 }
    241 
    242 WebGLId TestWebGraphicsContext3D::createFramebuffer() {
    243   WebGLId id;
    244   genFramebuffers(1, &id);
    245   return id;
    246 }
    247 
    248 WebGLId TestWebGraphicsContext3D::createRenderbuffer() {
    249   WebGLId id;
    250   genRenderbuffers(1, &id);
    251   return id;
    252 }
    253 
    254 WebGLId TestWebGraphicsContext3D::createTexture() {
    255   WebGLId id;
    256   genTextures(1, &id);
    257   return id;
    258 }
    259 
    260 void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) {
    261   deleteBuffers(1, &id);
    262 }
    263 
    264 void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) {
    265   deleteFramebuffers(1, &id);
    266 }
    267 
    268 void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) {
    269   deleteRenderbuffers(1, &id);
    270 }
    271 
    272 void TestWebGraphicsContext3D::deleteTexture(WebGLId id) {
    273   deleteTextures(1, &id);
    274 }
    275 
    276 unsigned TestWebGraphicsContext3D::createProgram() {
    277   unsigned program = next_program_id_++ | context_id_ << 16;
    278   program_set_.insert(program);
    279   return program;
    280 }
    281 
    282 WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) {
    283   unsigned shader = next_shader_id_++ | context_id_ << 16;
    284   shader_set_.insert(shader);
    285   return shader;
    286 }
    287 
    288 WebGLId TestWebGraphicsContext3D::createExternalTexture() {
    289   base::AutoLock lock(namespace_->lock);
    290   namespace_->textures.Append(kExternalTextureId, new TestTexture());
    291   return kExternalTextureId;
    292 }
    293 
    294 void TestWebGraphicsContext3D::deleteProgram(WebGLId id) {
    295   if (!program_set_.count(id))
    296     ADD_FAILURE() << "deleteProgram called on unknown program " << id;
    297   program_set_.erase(id);
    298 }
    299 
    300 void TestWebGraphicsContext3D::deleteShader(WebGLId id) {
    301   if (!shader_set_.count(id))
    302     ADD_FAILURE() << "deleteShader called on unknown shader " << id;
    303   shader_set_.erase(id);
    304 }
    305 
    306 void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) {
    307   if (!program_set_.count(program))
    308     ADD_FAILURE() << "attachShader called with unknown program " << program;
    309   if (!shader_set_.count(shader))
    310     ADD_FAILURE() << "attachShader called with unknown shader " << shader;
    311 }
    312 
    313 void TestWebGraphicsContext3D::useProgram(WebGLId program) {
    314   if (!program)
    315     return;
    316   if (!program_set_.count(program))
    317     ADD_FAILURE() << "useProgram called on unknown program " << program;
    318 }
    319 
    320 void TestWebGraphicsContext3D::bindFramebuffer(
    321     WGC3Denum target, WebGLId framebuffer) {
    322   if (!framebuffer)
    323     return;
    324   DCHECK_EQ(kFramebufferId | context_id_ << 16, framebuffer);
    325 }
    326 
    327 void TestWebGraphicsContext3D::bindRenderbuffer(
    328       WGC3Denum target, WebGLId renderbuffer) {
    329   if (!renderbuffer)
    330     return;
    331   DCHECK_EQ(kRenderbufferId | context_id_ << 16, renderbuffer);
    332 }
    333 
    334 void TestWebGraphicsContext3D::bindTexture(
    335     WGC3Denum target, WebGLId texture_id) {
    336   if (times_bind_texture_succeeds_ >= 0) {
    337     if (!times_bind_texture_succeeds_) {
    338       loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
    339                           GL_INNOCENT_CONTEXT_RESET_ARB);
    340     }
    341     --times_bind_texture_succeeds_;
    342   }
    343 
    344   if (!texture_id)
    345     return;
    346   base::AutoLock lock(namespace_->lock);
    347   DCHECK(namespace_->textures.ContainsId(texture_id));
    348   texture_targets_.BindTexture(target, texture_id);
    349   used_textures_.insert(texture_id);
    350 }
    351 
    352 blink::WebGLId TestWebGraphicsContext3D::BoundTextureId(
    353     blink::WGC3Denum target) {
    354   return texture_targets_.BoundTexture(target);
    355 }
    356 
    357 scoped_refptr<TestTexture> TestWebGraphicsContext3D::BoundTexture(
    358     WGC3Denum target) {
    359   // The caller is expected to lock the namespace for texture access.
    360   namespace_->lock.AssertAcquired();
    361   return namespace_->textures.TextureForId(BoundTextureId(target));
    362 }
    363 
    364 void TestWebGraphicsContext3D::CheckTextureIsBound(WGC3Denum target) {
    365   DCHECK(BoundTextureId(target));
    366 }
    367 
    368 void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target) {
    369   if (times_end_query_succeeds_ >= 0) {
    370     if (!times_end_query_succeeds_) {
    371       loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
    372                           GL_INNOCENT_CONTEXT_RESET_ARB);
    373     }
    374     --times_end_query_succeeds_;
    375   }
    376 }
    377 
    378 void TestWebGraphicsContext3D::getQueryObjectuivEXT(
    379     WebGLId query,
    380     WGC3Denum pname,
    381     WGC3Duint* params) {
    382   // If the context is lost, behave as if result is available.
    383   if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
    384     *params = 1;
    385 }
    386 
    387 void TestWebGraphicsContext3D::getIntegerv(
    388     WGC3Denum pname,
    389     blink::WGC3Dint* value) {
    390   if (pname == GL_MAX_TEXTURE_SIZE)
    391     *value = max_texture_size_;
    392   else if (pname == GL_ACTIVE_TEXTURE)
    393     *value = GL_TEXTURE0;
    394 }
    395 
    396 void TestWebGraphicsContext3D::genMailboxCHROMIUM(blink::WGC3Dbyte* mailbox) {
    397   if (times_gen_mailbox_succeeds_ >= 0) {
    398     if (!times_gen_mailbox_succeeds_) {
    399       loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
    400                           GL_INNOCENT_CONTEXT_RESET_ARB);
    401     }
    402     --times_gen_mailbox_succeeds_;
    403   }
    404   if (context_lost_) {
    405     memset(mailbox, 0, 64);
    406     return;
    407   }
    408 
    409   static char mailbox_name1 = '1';
    410   static char mailbox_name2 = '1';
    411   mailbox[0] = mailbox_name1;
    412   mailbox[1] = mailbox_name2;
    413   mailbox[2] = '\0';
    414   if (++mailbox_name1 == 0) {
    415     mailbox_name1 = '1';
    416     ++mailbox_name2;
    417   }
    418 }
    419 
    420 void TestWebGraphicsContext3D::setContextLostCallback(
    421     WebGraphicsContextLostCallback* callback) {
    422   context_lost_callback_ = callback;
    423 }
    424 
    425 void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
    426                                                    WGC3Denum other) {
    427   if (context_lost_)
    428     return;
    429   context_lost_ = true;
    430   if (context_lost_callback_)
    431     context_lost_callback_->onContextLost();
    432 
    433   for (size_t i = 0; i < shared_contexts_.size(); ++i)
    434     shared_contexts_[i]->loseContextCHROMIUM(current, other);
    435   shared_contexts_.clear();
    436 }
    437 
    438 void TestWebGraphicsContext3D::finish() {
    439   test_support_->CallAllSyncPointCallbacks();
    440 }
    441 
    442 void TestWebGraphicsContext3D::flush() {
    443   test_support_->CallAllSyncPointCallbacks();
    444 }
    445 
    446 void TestWebGraphicsContext3D::bindBuffer(blink::WGC3Denum target,
    447                                           blink::WebGLId buffer) {
    448   bound_buffer_ = buffer;
    449   if (!bound_buffer_)
    450     return;
    451   unsigned context_id = buffer >> 16;
    452   unsigned buffer_id = buffer & 0xffff;
    453   base::AutoLock lock(namespace_->lock);
    454   DCHECK(buffer_id);
    455   DCHECK_LT(buffer_id, namespace_->next_buffer_id);
    456   DCHECK_EQ(context_id, context_id_);
    457 
    458   base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
    459   if (buffers.count(bound_buffer_) == 0)
    460     buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass());
    461 
    462   buffers.get(bound_buffer_)->target = target;
    463 }
    464 
    465 void TestWebGraphicsContext3D::bufferData(blink::WGC3Denum target,
    466                                           blink::WGC3Dsizeiptr size,
    467                                           const void* data,
    468                                           blink::WGC3Denum usage) {
    469   base::AutoLock lock(namespace_->lock);
    470   base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
    471   DCHECK_GT(buffers.count(bound_buffer_), 0u);
    472   DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
    473   Buffer* buffer = buffers.get(bound_buffer_);
    474   if (context_lost_) {
    475     buffer->pixels.reset();
    476     return;
    477   }
    478 
    479   buffer->pixels.reset(new uint8[size]);
    480   buffer->size = size;
    481   if (data != NULL)
    482     memcpy(buffer->pixels.get(), data, size);
    483 
    484   peak_transfer_buffer_memory_used_bytes_ =
    485       std::max(peak_transfer_buffer_memory_used_bytes_,
    486                GetTransferBufferMemoryUsedBytes());
    487 }
    488 
    489 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(blink::WGC3Denum target,
    490                                                   blink::WGC3Denum access) {
    491   base::AutoLock lock(namespace_->lock);
    492   base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
    493   DCHECK_GT(buffers.count(bound_buffer_), 0u);
    494   DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
    495   if (times_map_buffer_chromium_succeeds_ >= 0) {
    496     if (!times_map_buffer_chromium_succeeds_) {
    497       return NULL;
    498     }
    499     --times_map_buffer_chromium_succeeds_;
    500   }
    501 
    502   peak_transfer_buffer_memory_used_bytes_ =
    503       std::max(peak_transfer_buffer_memory_used_bytes_,
    504                GetTransferBufferMemoryUsedBytes());
    505 
    506   return buffers.get(bound_buffer_)->pixels.get();
    507 }
    508 
    509 blink::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM(
    510     blink::WGC3Denum target) {
    511   base::AutoLock lock(namespace_->lock);
    512   base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
    513   DCHECK_GT(buffers.count(bound_buffer_), 0u);
    514   DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
    515   buffers.get(bound_buffer_)->pixels.reset();
    516   return true;
    517 }
    518 
    519 blink::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM(
    520       blink::WGC3Dsizei width, blink::WGC3Dsizei height,
    521       blink::WGC3Denum internalformat) {
    522   DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat));
    523   blink::WGC3Duint image_id = NextImageId();
    524   base::AutoLock lock(namespace_->lock);
    525   base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
    526   images.set(image_id, make_scoped_ptr(new Image).Pass());
    527   images.get(image_id)->pixels.reset(new uint8[width * height * 4]);
    528   return image_id;
    529 }
    530 
    531 void TestWebGraphicsContext3D::destroyImageCHROMIUM(
    532     blink::WGC3Duint id) {
    533   RetireImageId(id);
    534 }
    535 
    536 void TestWebGraphicsContext3D::getImageParameterivCHROMIUM(
    537     blink::WGC3Duint image_id,
    538     blink::WGC3Denum pname,
    539     blink::WGC3Dint* params) {
    540   base::AutoLock lock(namespace_->lock);
    541   DCHECK_GT(namespace_->images.count(image_id), 0u);
    542   DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname));
    543   *params = 0;
    544 }
    545 
    546 void* TestWebGraphicsContext3D::mapImageCHROMIUM(blink::WGC3Duint image_id,
    547                                                  blink::WGC3Denum access) {
    548   base::AutoLock lock(namespace_->lock);
    549   base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
    550   DCHECK_GT(images.count(image_id), 0u);
    551   if (times_map_image_chromium_succeeds_ >= 0) {
    552     if (!times_map_image_chromium_succeeds_) {
    553       return NULL;
    554     }
    555     --times_map_image_chromium_succeeds_;
    556   }
    557   return images.get(image_id)->pixels.get();
    558 }
    559 
    560 void TestWebGraphicsContext3D::unmapImageCHROMIUM(
    561     blink::WGC3Duint image_id) {
    562   base::AutoLock lock(namespace_->lock);
    563   DCHECK_GT(namespace_->images.count(image_id), 0u);
    564 }
    565 
    566 unsigned TestWebGraphicsContext3D::insertSyncPoint() {
    567   return next_insert_sync_point_++;
    568 }
    569 
    570 void TestWebGraphicsContext3D::waitSyncPoint(unsigned sync_point) {
    571   if (sync_point)
    572     last_waited_sync_point_ = sync_point;
    573 }
    574 
    575 size_t TestWebGraphicsContext3D::NumTextures() const {
    576   base::AutoLock lock(namespace_->lock);
    577   return namespace_->textures.Size();
    578 }
    579 
    580 blink::WebGLId TestWebGraphicsContext3D::TextureAt(int i) const {
    581   base::AutoLock lock(namespace_->lock);
    582   return namespace_->textures.IdAt(i);
    583 }
    584 
    585 WebGLId TestWebGraphicsContext3D::NextTextureId() {
    586   base::AutoLock lock(namespace_->lock);
    587   WebGLId texture_id = namespace_->next_texture_id++;
    588   DCHECK(texture_id < (1 << 16));
    589   texture_id |= context_id_ << 16;
    590   return texture_id;
    591 }
    592 
    593 void TestWebGraphicsContext3D::RetireTextureId(WebGLId id) {
    594   base::AutoLock lock(namespace_->lock);
    595   unsigned context_id = id >> 16;
    596   unsigned texture_id = id & 0xffff;
    597   DCHECK(texture_id);
    598   DCHECK_LT(texture_id, namespace_->next_texture_id);
    599   DCHECK_EQ(context_id, context_id_);
    600 }
    601 
    602 WebGLId TestWebGraphicsContext3D::NextBufferId() {
    603   base::AutoLock lock(namespace_->lock);
    604   WebGLId buffer_id = namespace_->next_buffer_id++;
    605   DCHECK(buffer_id < (1 << 16));
    606   buffer_id |= context_id_ << 16;
    607   return buffer_id;
    608 }
    609 
    610 void TestWebGraphicsContext3D::RetireBufferId(WebGLId id) {
    611   base::AutoLock lock(namespace_->lock);
    612   unsigned context_id = id >> 16;
    613   unsigned buffer_id = id & 0xffff;
    614   DCHECK(buffer_id);
    615   DCHECK_LT(buffer_id, namespace_->next_buffer_id);
    616   DCHECK_EQ(context_id, context_id_);
    617 }
    618 
    619 blink::WGC3Duint TestWebGraphicsContext3D::NextImageId() {
    620   base::AutoLock lock(namespace_->lock);
    621   WGC3Duint image_id = namespace_->next_image_id++;
    622   DCHECK(image_id < (1 << 16));
    623   image_id |= context_id_ << 16;
    624   return image_id;
    625 }
    626 
    627 void TestWebGraphicsContext3D::RetireImageId(WebGLId id) {
    628   base::AutoLock lock(namespace_->lock);
    629   unsigned context_id = id >> 16;
    630   unsigned image_id = id & 0xffff;
    631   DCHECK(image_id);
    632   DCHECK_LT(image_id, namespace_->next_image_id);
    633   DCHECK_EQ(context_id, context_id_);
    634 }
    635 
    636 size_t TestWebGraphicsContext3D::GetTransferBufferMemoryUsedBytes() const {
    637   size_t total_bytes = 0;
    638   base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
    639   base::ScopedPtrHashMap<unsigned, Buffer>::iterator it = buffers.begin();
    640   for (; it != buffers.end(); ++it) {
    641     Buffer* buffer = it->second;
    642     if (buffer->target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM)
    643       total_bytes += buffer->size;
    644   }
    645   return total_bytes;
    646 }
    647 
    648 void TestWebGraphicsContext3D::SetMaxTransferBufferUsageBytes(
    649     size_t max_transfer_buffer_usage_bytes) {
    650   test_capabilities_.max_transfer_buffer_usage_bytes =
    651       max_transfer_buffer_usage_bytes;
    652 }
    653 
    654 TestWebGraphicsContext3D::TextureTargets::TextureTargets() {
    655   // Initialize default bindings.
    656   bound_textures_[GL_TEXTURE_2D] = 0;
    657   bound_textures_[GL_TEXTURE_EXTERNAL_OES] = 0;
    658   bound_textures_[GL_TEXTURE_RECTANGLE_ARB] = 0;
    659 }
    660 
    661 TestWebGraphicsContext3D::TextureTargets::~TextureTargets() {}
    662 
    663 void TestWebGraphicsContext3D::TextureTargets::BindTexture(
    664     blink::WGC3Denum target,
    665     blink::WebGLId id) {
    666   // Make sure this is a supported target by seeing if it was bound to before.
    667   DCHECK(bound_textures_.find(target) != bound_textures_.end());
    668   bound_textures_[target] = id;
    669 }
    670 
    671 void TestWebGraphicsContext3D::texParameteri(blink::WGC3Denum target,
    672                                              blink::WGC3Denum pname,
    673                                              blink::WGC3Dint param) {
    674   CheckTextureIsBound(target);
    675   base::AutoLock lock_for_texture_access(namespace_->lock);
    676   scoped_refptr<TestTexture> texture = BoundTexture(target);
    677   DCHECK(texture->IsValidParameter(pname));
    678   texture->params[pname] = param;
    679 }
    680 
    681 void TestWebGraphicsContext3D::getTexParameteriv(blink::WGC3Denum target,
    682                                                  blink::WGC3Denum pname,
    683                                                  blink::WGC3Dint* value) {
    684   CheckTextureIsBound(target);
    685   base::AutoLock lock_for_texture_access(namespace_->lock);
    686   scoped_refptr<TestTexture> texture = BoundTexture(target);
    687   DCHECK(texture->IsValidParameter(pname));
    688   TestTexture::TextureParametersMap::iterator it = texture->params.find(pname);
    689   if (it != texture->params.end())
    690     *value = it->second;
    691 }
    692 
    693 void TestWebGraphicsContext3D::TextureTargets::UnbindTexture(
    694     blink::WebGLId id) {
    695   // Bind zero to any targets that the id is bound to.
    696   for (TargetTextureMap::iterator it = bound_textures_.begin();
    697        it != bound_textures_.end();
    698        it++) {
    699     if (it->second == id)
    700       it->second = 0;
    701   }
    702 }
    703 
    704 blink::WebGLId TestWebGraphicsContext3D::TextureTargets::BoundTexture(
    705     blink::WGC3Denum target) {
    706   DCHECK(bound_textures_.find(target) != bound_textures_.end());
    707   return bound_textures_[target];
    708 }
    709 
    710 TestWebGraphicsContext3D::Buffer::Buffer() : target(0), size(0) {}
    711 
    712 TestWebGraphicsContext3D::Buffer::~Buffer() {}
    713 
    714 TestWebGraphicsContext3D::Image::Image() {}
    715 
    716 TestWebGraphicsContext3D::Image::~Image() {}
    717 
    718 }  // namespace cc
    719