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