Home | History | Annotate | Download | only in test
      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