Home | History | Annotate | Download | only in client
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // A class to emulate GLES2 over command buffers.
      6 
      7 #include "gpu/command_buffer/client/gles2_implementation.h"
      8 
      9 #include <algorithm>
     10 #include <map>
     11 #include <queue>
     12 #include <set>
     13 #include <limits>
     14 #include <stdio.h>
     15 #include <string.h>
     16 #include <GLES2/gl2ext.h>
     17 #include <GLES2/gl2extchromium.h>
     18 #include "gpu/command_buffer/client/buffer_tracker.h"
     19 #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
     20 #include "gpu/command_buffer/client/mapped_memory.h"
     21 #include "gpu/command_buffer/client/program_info_manager.h"
     22 #include "gpu/command_buffer/client/query_tracker.h"
     23 #include "gpu/command_buffer/client/transfer_buffer.h"
     24 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
     25 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
     26 #include "gpu/command_buffer/common/trace_event.h"
     27 #include "ui/gfx/gpu_memory_buffer.h"
     28 
     29 #if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
     30 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
     31 #endif
     32 
     33 #if defined(GPU_CLIENT_DEBUG)
     34 #include "ui/gl/gl_switches.h"
     35 #include "base/command_line.h"
     36 #endif
     37 
     38 namespace gpu {
     39 namespace gles2 {
     40 
     41 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
     42 static GLuint ToGLuint(const void* ptr) {
     43   return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
     44 }
     45 
     46 #if !defined(_MSC_VER)
     47 const size_t GLES2Implementation::kMaxSizeOfSimpleResult;
     48 const unsigned int GLES2Implementation::kStartingOffset;
     49 #endif
     50 
     51 GLES2Implementation::GLStaticState::GLStaticState() {
     52 }
     53 
     54 GLES2Implementation::GLStaticState::~GLStaticState() {
     55 }
     56 
     57 GLES2Implementation::GLStaticState::IntState::IntState()
     58     : max_combined_texture_image_units(0),
     59       max_cube_map_texture_size(0),
     60       max_fragment_uniform_vectors(0),
     61       max_renderbuffer_size(0),
     62       max_texture_image_units(0),
     63       max_texture_size(0),
     64       max_varying_vectors(0),
     65       max_vertex_attribs(0),
     66       max_vertex_texture_image_units(0),
     67       max_vertex_uniform_vectors(0),
     68       num_compressed_texture_formats(0),
     69       num_shader_binary_formats(0) {
     70 }
     71 
     72 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
     73     GLES2Implementation* gles2_implementation)
     74     : gles2_implementation_(gles2_implementation) {
     75   GPU_CHECK_EQ(0, gles2_implementation_->use_count_);
     76   ++gles2_implementation_->use_count_;
     77 }
     78 
     79 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
     80   --gles2_implementation_->use_count_;
     81   GPU_CHECK_EQ(0, gles2_implementation_->use_count_);
     82 }
     83 
     84 GLES2Implementation::GLES2Implementation(
     85       GLES2CmdHelper* helper,
     86       ShareGroup* share_group,
     87       TransferBufferInterface* transfer_buffer,
     88       bool bind_generates_resource,
     89       ImageFactory* image_factory)
     90     : helper_(helper),
     91       transfer_buffer_(transfer_buffer),
     92       angle_pack_reverse_row_order_status_(kUnknownExtensionStatus),
     93       chromium_framebuffer_multisample_(kUnknownExtensionStatus),
     94       pack_alignment_(4),
     95       unpack_alignment_(4),
     96       unpack_flip_y_(false),
     97       unpack_row_length_(0),
     98       unpack_skip_rows_(0),
     99       unpack_skip_pixels_(0),
    100       pack_reverse_row_order_(false),
    101       active_texture_unit_(0),
    102       bound_framebuffer_(0),
    103       bound_read_framebuffer_(0),
    104       bound_renderbuffer_(0),
    105       current_program_(0),
    106       bound_array_buffer_id_(0),
    107       bound_pixel_pack_transfer_buffer_id_(0),
    108       bound_pixel_unpack_transfer_buffer_id_(0),
    109       error_bits_(0),
    110       debug_(false),
    111       use_count_(0),
    112       current_query_(NULL),
    113       error_message_callback_(NULL),
    114       image_factory_(image_factory) {
    115   GPU_DCHECK(helper);
    116   GPU_DCHECK(transfer_buffer);
    117 
    118   char temp[128];
    119   sprintf(temp, "%p", static_cast<void*>(this));
    120   this_in_hex_ = std::string(temp);
    121 
    122   GPU_CLIENT_LOG_CODE_BLOCK({
    123     debug_ = CommandLine::ForCurrentProcess()->HasSwitch(
    124         switches::kEnableGPUClientLogging);
    125   });
    126 
    127   share_group_ =
    128       (share_group ? share_group : new ShareGroup(bind_generates_resource));
    129 
    130   memset(&reserved_ids_, 0, sizeof(reserved_ids_));
    131 }
    132 
    133 bool GLES2Implementation::Initialize(
    134     unsigned int starting_transfer_buffer_size,
    135     unsigned int min_transfer_buffer_size,
    136     unsigned int max_transfer_buffer_size) {
    137   GPU_DCHECK_GE(starting_transfer_buffer_size, min_transfer_buffer_size);
    138   GPU_DCHECK_LE(starting_transfer_buffer_size, max_transfer_buffer_size);
    139   GPU_DCHECK_GE(min_transfer_buffer_size, kStartingOffset);
    140 
    141   if (!transfer_buffer_->Initialize(
    142       starting_transfer_buffer_size,
    143       kStartingOffset,
    144       min_transfer_buffer_size,
    145       max_transfer_buffer_size,
    146       kAlignment,
    147       kSizeToFlush)) {
    148     return false;
    149   }
    150 
    151   mapped_memory_.reset(new MappedMemoryManager(helper_));
    152   SetSharedMemoryChunkSizeMultiple(1024 * 1024 * 2);
    153 
    154   if (!QueryAndCacheStaticState())
    155     return false;
    156 
    157   util_.set_num_compressed_texture_formats(
    158       static_state_.int_state.num_compressed_texture_formats);
    159   util_.set_num_shader_binary_formats(
    160       static_state_.int_state.num_shader_binary_formats);
    161 
    162   texture_units_.reset(
    163       new TextureUnit[
    164           static_state_.int_state.max_combined_texture_image_units]);
    165 
    166   query_tracker_.reset(new QueryTracker(mapped_memory_.get()));
    167   buffer_tracker_.reset(new BufferTracker(mapped_memory_.get()));
    168   gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(image_factory_));
    169 
    170 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
    171   GetIdHandler(id_namespaces::kBuffers)->MakeIds(
    172       this, kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]);
    173 #endif
    174 
    175   vertex_array_object_manager_.reset(new VertexArrayObjectManager(
    176       static_state_.int_state.max_vertex_attribs,
    177       reserved_ids_[0],
    178       reserved_ids_[1]));
    179 
    180   return true;
    181 }
    182 
    183 bool GLES2Implementation::QueryAndCacheStaticState() {
    184   // Setup query for multiple GetIntegerv's
    185   static const GLenum pnames[] = {
    186     GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
    187     GL_MAX_CUBE_MAP_TEXTURE_SIZE,
    188     GL_MAX_FRAGMENT_UNIFORM_VECTORS,
    189     GL_MAX_RENDERBUFFER_SIZE,
    190     GL_MAX_TEXTURE_IMAGE_UNITS,
    191     GL_MAX_TEXTURE_SIZE,
    192     GL_MAX_VARYING_VECTORS,
    193     GL_MAX_VERTEX_ATTRIBS,
    194     GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
    195     GL_MAX_VERTEX_UNIFORM_VECTORS,
    196     GL_NUM_COMPRESSED_TEXTURE_FORMATS,
    197     GL_NUM_SHADER_BINARY_FORMATS,
    198   };
    199 
    200   GetMultipleIntegervState integerv_state(
    201       pnames, arraysize(pnames),
    202       &static_state_.int_state.max_combined_texture_image_units,
    203       sizeof(static_state_.int_state));
    204   if (!GetMultipleIntegervSetup(&integerv_state)) {
    205     return false;
    206   }
    207 
    208   // Setup query for multiple GetShaderPrecisionFormat's
    209   static const GLenum precision_params[][2] = {
    210     { GL_VERTEX_SHADER, GL_LOW_INT },
    211     { GL_VERTEX_SHADER, GL_MEDIUM_INT },
    212     { GL_VERTEX_SHADER, GL_HIGH_INT },
    213     { GL_VERTEX_SHADER, GL_LOW_FLOAT },
    214     { GL_VERTEX_SHADER, GL_MEDIUM_FLOAT },
    215     { GL_VERTEX_SHADER, GL_HIGH_FLOAT },
    216     { GL_FRAGMENT_SHADER, GL_LOW_INT },
    217     { GL_FRAGMENT_SHADER, GL_MEDIUM_INT },
    218     { GL_FRAGMENT_SHADER, GL_HIGH_INT },
    219     { GL_FRAGMENT_SHADER, GL_LOW_FLOAT },
    220     { GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT },
    221     { GL_FRAGMENT_SHADER, GL_HIGH_FLOAT },
    222   };
    223 
    224   GetAllShaderPrecisionFormatsState  precision_state(
    225       precision_params, arraysize(precision_params));
    226   GetAllShaderPrecisionFormatsSetup(&precision_state);
    227 
    228   // Allocate and partition transfer buffer for all requests
    229   void* buffer = transfer_buffer_->Alloc(
    230       integerv_state.transfer_buffer_size_needed +
    231       precision_state.transfer_buffer_size_needed);
    232   if (!buffer) {
    233     SetGLError(GL_OUT_OF_MEMORY, "QueryAndCacheStaticState",
    234                "Transfer buffer allocation failed.");
    235     return false;
    236   }
    237   integerv_state.buffer = buffer;
    238   precision_state.results_buffer =
    239       static_cast<char*>(buffer) + integerv_state.transfer_buffer_size_needed;
    240 
    241   // Make all the requests and wait once for all the results.
    242   GetMultipleIntegervRequest(&integerv_state);
    243   GetAllShaderPrecisionFormatsRequest(&precision_state);
    244   WaitForCmd();
    245   GetMultipleIntegervOnCompleted(&integerv_state);
    246   GetAllShaderPrecisionFormatsOnCompleted(&precision_state);
    247 
    248   // TODO(gman): We should be able to free without a token.
    249   transfer_buffer_->FreePendingToken(buffer, helper_->InsertToken());
    250   CheckGLError();
    251 
    252   return true;
    253 }
    254 
    255 GLES2Implementation::~GLES2Implementation() {
    256   // Make sure the queries are finished otherwise we'll delete the
    257   // shared memory (mapped_memory_) which will free the memory used
    258   // by the queries. The GPU process when validating that memory is still
    259   // shared will fail and abort (ie, it will stop running).
    260   WaitForCmd();
    261   query_tracker_.reset();
    262 
    263 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
    264   DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
    265 #endif
    266   buffer_tracker_.reset();
    267 
    268   // Make sure the commands make it the service.
    269   WaitForCmd();
    270 }
    271 
    272 GLES2CmdHelper* GLES2Implementation::helper() const {
    273   return helper_;
    274 }
    275 
    276 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const {
    277   return share_group_->GetIdHandler(namespace_id);
    278 }
    279 
    280 void* GLES2Implementation::GetResultBuffer() {
    281   return transfer_buffer_->GetResultBuffer();
    282 }
    283 
    284 int32 GLES2Implementation::GetResultShmId() {
    285   return transfer_buffer_->GetShmId();
    286 }
    287 
    288 uint32 GLES2Implementation::GetResultShmOffset() {
    289   return transfer_buffer_->GetResultOffset();
    290 }
    291 
    292 void GLES2Implementation::SetSharedMemoryChunkSizeMultiple(
    293     unsigned int multiple) {
    294   mapped_memory_->set_chunk_size_multiple(multiple);
    295 }
    296 
    297 void GLES2Implementation::FreeUnusedSharedMemory() {
    298   mapped_memory_->FreeUnused();
    299 }
    300 
    301 void GLES2Implementation::FreeEverything() {
    302   WaitForCmd();
    303   query_tracker_->Shrink();
    304   FreeUnusedSharedMemory();
    305   transfer_buffer_->Free();
    306   helper_->FreeRingBuffer();
    307 }
    308 
    309 void GLES2Implementation::WaitForCmd() {
    310   TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
    311   helper_->CommandBufferHelper::Finish();
    312 }
    313 
    314 bool GLES2Implementation::IsExtensionAvailable(const char* ext) {
    315   const char* extensions =
    316       reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS));
    317   if (!extensions)
    318     return false;
    319 
    320   int length = strlen(ext);
    321   while (true) {
    322     int n = strcspn(extensions, " ");
    323     if (n == length && 0 == strncmp(ext, extensions, length)) {
    324       return true;
    325     }
    326     if ('\0' == extensions[n]) {
    327       return false;
    328     }
    329     extensions += n + 1;
    330   }
    331 }
    332 
    333 bool GLES2Implementation::IsExtensionAvailableHelper(
    334     const char* extension, ExtensionStatus* status) {
    335   switch (*status) {
    336     case kAvailableExtensionStatus:
    337       return true;
    338     case kUnavailableExtensionStatus:
    339       return false;
    340     default: {
    341       bool available = IsExtensionAvailable(extension);
    342       *status = available ? kAvailableExtensionStatus :
    343                             kUnavailableExtensionStatus;
    344       return available;
    345     }
    346   }
    347 }
    348 
    349 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
    350   return IsExtensionAvailableHelper(
    351       "GL_ANGLE_pack_reverse_row_order",
    352       &angle_pack_reverse_row_order_status_);
    353 }
    354 
    355 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
    356   return IsExtensionAvailableHelper(
    357       "GL_CHROMIUM_framebuffer_multisample",
    358       &chromium_framebuffer_multisample_);
    359 }
    360 
    361 const std::string& GLES2Implementation::GetLogPrefix() const {
    362   const std::string& prefix(debug_marker_manager_.GetMarker());
    363   return prefix.empty() ? this_in_hex_ : prefix;
    364 }
    365 
    366 GLenum GLES2Implementation::GetError() {
    367   GPU_CLIENT_SINGLE_THREAD_CHECK();
    368   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
    369   GLenum err = GetGLError();
    370   GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err));
    371   return err;
    372 }
    373 
    374 GLenum GLES2Implementation::GetClientSideGLError() {
    375   if (error_bits_ == 0) {
    376     return GL_NO_ERROR;
    377   }
    378 
    379   GLenum error = GL_NO_ERROR;
    380   for (uint32 mask = 1; mask != 0; mask = mask << 1) {
    381     if ((error_bits_ & mask) != 0) {
    382       error = GLES2Util::GLErrorBitToGLError(mask);
    383       break;
    384     }
    385   }
    386   error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
    387   return error;
    388 }
    389 
    390 GLenum GLES2Implementation::GetGLError() {
    391   TRACE_EVENT0("gpu", "GLES2::GetGLError");
    392   // Check the GL error first, then our wrapped error.
    393   typedef cmds::GetError::Result Result;
    394   Result* result = GetResultAs<Result*>();
    395   // If we couldn't allocate a result the context is lost.
    396   if (!result) {
    397     return GL_NO_ERROR;
    398   }
    399   *result = GL_NO_ERROR;
    400   helper_->GetError(GetResultShmId(), GetResultShmOffset());
    401   WaitForCmd();
    402   GLenum error = *result;
    403   if (error == GL_NO_ERROR) {
    404     error = GetClientSideGLError();
    405   } else {
    406     // There was an error, clear the corresponding wrapped error.
    407     error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
    408   }
    409   return error;
    410 }
    411 
    412 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
    413 void GLES2Implementation::FailGLError(GLenum error) {
    414   if (error != GL_NO_ERROR) {
    415     GPU_NOTREACHED() << "Error";
    416   }
    417 }
    418 // NOTE: Calling GetGLError overwrites data in the result buffer.
    419 void GLES2Implementation::CheckGLError() {
    420   FailGLError(GetGLError());
    421 }
    422 #endif  // defined(GPU_CLIENT_FAIL_GL_ERRORS)
    423 
    424 void GLES2Implementation::SetGLError(
    425     GLenum error, const char* function_name, const char* msg) {
    426   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
    427                  << GLES2Util::GetStringError(error) << ": "
    428                  << function_name << ": " << msg);
    429   FailGLError(error);
    430   if (msg) {
    431     last_error_ = msg;
    432   }
    433   if (error_message_callback_) {
    434     std::string temp(GLES2Util::GetStringError(error)  + " : " +
    435                      function_name + ": " + (msg ? msg : ""));
    436     error_message_callback_->OnErrorMessage(temp.c_str(), 0);
    437   }
    438   error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
    439 }
    440 
    441 void GLES2Implementation::SetGLErrorInvalidEnum(
    442     const char* function_name, GLenum value, const char* label) {
    443   SetGLError(GL_INVALID_ENUM, function_name,
    444              (std::string(label) + " was " +
    445               GLES2Util::GetStringEnum(value)).c_str());
    446 }
    447 
    448 bool GLES2Implementation::GetBucketContents(uint32 bucket_id,
    449                                             std::vector<int8>* data) {
    450   TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
    451   GPU_DCHECK(data);
    452   const uint32 kStartSize = 32 * 1024;
    453   ScopedTransferBufferPtr buffer(kStartSize, helper_, transfer_buffer_);
    454   if (!buffer.valid()) {
    455     return false;
    456   }
    457   typedef cmd::GetBucketStart::Result Result;
    458   Result* result = GetResultAs<Result*>();
    459   if (!result) {
    460     return false;
    461   }
    462   *result = 0;
    463   helper_->GetBucketStart(
    464       bucket_id, GetResultShmId(), GetResultShmOffset(),
    465       buffer.size(), buffer.shm_id(), buffer.offset());
    466   WaitForCmd();
    467   uint32 size = *result;
    468   data->resize(size);
    469   if (size > 0u) {
    470     uint32 offset = 0;
    471     while (size) {
    472       if (!buffer.valid()) {
    473         buffer.Reset(size);
    474         if (!buffer.valid()) {
    475           return false;
    476         }
    477         helper_->GetBucketData(
    478             bucket_id, offset, buffer.size(), buffer.shm_id(), buffer.offset());
    479         WaitForCmd();
    480       }
    481       uint32 size_to_copy = std::min(size, buffer.size());
    482       memcpy(&(*data)[offset], buffer.address(), size_to_copy);
    483       offset += size_to_copy;
    484       size -= size_to_copy;
    485       buffer.Release();
    486     };
    487     // Free the bucket. This is not required but it does free up the memory.
    488     // and we don't have to wait for the result so from the client's perspective
    489     // it's cheap.
    490     helper_->SetBucketSize(bucket_id, 0);
    491   }
    492   return true;
    493 }
    494 
    495 void GLES2Implementation::SetBucketContents(
    496     uint32 bucket_id, const void* data, size_t size) {
    497   GPU_DCHECK(data);
    498   helper_->SetBucketSize(bucket_id, size);
    499   if (size > 0u) {
    500     uint32 offset = 0;
    501     while (size) {
    502       ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
    503       if (!buffer.valid()) {
    504         return;
    505       }
    506       memcpy(buffer.address(), static_cast<const int8*>(data) + offset,
    507              buffer.size());
    508       helper_->SetBucketData(
    509           bucket_id, offset, buffer.size(), buffer.shm_id(), buffer.offset());
    510       offset += buffer.size();
    511       size -= buffer.size();
    512     }
    513   }
    514 }
    515 
    516 void GLES2Implementation::SetBucketAsCString(
    517     uint32 bucket_id, const char* str) {
    518   // NOTE: strings are passed NULL terminated. That means the empty
    519   // string will have a size of 1 and no-string will have a size of 0
    520   if (str) {
    521     SetBucketContents(bucket_id, str, strlen(str) + 1);
    522   } else {
    523     helper_->SetBucketSize(bucket_id, 0);
    524   }
    525 }
    526 
    527 bool GLES2Implementation::GetBucketAsString(
    528     uint32 bucket_id, std::string* str) {
    529   GPU_DCHECK(str);
    530   std::vector<int8> data;
    531   // NOTE: strings are passed NULL terminated. That means the empty
    532   // string will have a size of 1 and no-string will have a size of 0
    533   if (!GetBucketContents(bucket_id, &data)) {
    534     return false;
    535   }
    536   if (data.empty()) {
    537     return false;
    538   }
    539   str->assign(&data[0], &data[0] + data.size() - 1);
    540   return true;
    541 }
    542 
    543 void GLES2Implementation::SetBucketAsString(
    544     uint32 bucket_id, const std::string& str) {
    545   // NOTE: strings are passed NULL terminated. That means the empty
    546   // string will have a size of 1 and no-string will have a size of 0
    547   SetBucketContents(bucket_id, str.c_str(), str.size() + 1);
    548 }
    549 
    550 void GLES2Implementation::Disable(GLenum cap) {
    551   GPU_CLIENT_SINGLE_THREAD_CHECK();
    552   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
    553                  << GLES2Util::GetStringCapability(cap) << ")");
    554   bool changed = false;
    555   if (!state_.SetCapabilityState(cap, false, &changed) || changed) {
    556     helper_->Disable(cap);
    557   }
    558   CheckGLError();
    559 }
    560 
    561 void GLES2Implementation::Enable(GLenum cap) {
    562   GPU_CLIENT_SINGLE_THREAD_CHECK();
    563   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
    564                  << GLES2Util::GetStringCapability(cap) << ")");
    565   bool changed = false;
    566   if (!state_.SetCapabilityState(cap, true, &changed) || changed) {
    567     helper_->Enable(cap);
    568   }
    569   CheckGLError();
    570 }
    571 
    572 GLboolean GLES2Implementation::IsEnabled(GLenum cap) {
    573   GPU_CLIENT_SINGLE_THREAD_CHECK();
    574   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
    575                  << GLES2Util::GetStringCapability(cap) << ")");
    576   bool state = false;
    577   if (!state_.GetEnabled(cap, &state)) {
    578     typedef cmds::IsEnabled::Result Result;
    579     Result* result = GetResultAs<Result*>();
    580     if (!result) {
    581       return GL_FALSE;
    582     }
    583     *result = 0;
    584     helper_->IsEnabled(cap, GetResultShmId(), GetResultShmOffset());
    585     WaitForCmd();
    586     state = (*result) != 0;
    587   }
    588 
    589   GPU_CLIENT_LOG("returned " << state);
    590   CheckGLError();
    591   return state;
    592 }
    593 
    594 bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
    595   switch (pname) {
    596     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
    597       *params = static_state_.int_state.max_combined_texture_image_units;
    598       return true;
    599     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    600       *params = static_state_.int_state.max_cube_map_texture_size;
    601       return true;
    602     case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
    603       *params = static_state_.int_state.max_fragment_uniform_vectors;
    604       return true;
    605     case GL_MAX_RENDERBUFFER_SIZE:
    606       *params = static_state_.int_state.max_renderbuffer_size;
    607       return true;
    608     case GL_MAX_TEXTURE_IMAGE_UNITS:
    609       *params = static_state_.int_state.max_texture_image_units;
    610       return true;
    611     case GL_MAX_TEXTURE_SIZE:
    612       *params = static_state_.int_state.max_texture_size;
    613       return true;
    614     case GL_MAX_VARYING_VECTORS:
    615       *params = static_state_.int_state.max_varying_vectors;
    616       return true;
    617     case GL_MAX_VERTEX_ATTRIBS:
    618       *params = static_state_.int_state.max_vertex_attribs;
    619       return true;
    620     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
    621       *params = static_state_.int_state.max_vertex_texture_image_units;
    622       return true;
    623     case GL_MAX_VERTEX_UNIFORM_VECTORS:
    624       *params = static_state_.int_state.max_vertex_uniform_vectors;
    625       return true;
    626     case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
    627       *params = static_state_.int_state.num_compressed_texture_formats;
    628       return true;
    629     case GL_NUM_SHADER_BINARY_FORMATS:
    630       *params = static_state_.int_state.num_shader_binary_formats;
    631       return true;
    632     case GL_ARRAY_BUFFER_BINDING:
    633       if (share_group_->bind_generates_resource()) {
    634         *params = bound_array_buffer_id_;
    635         return true;
    636       }
    637       return false;
    638     case GL_ELEMENT_ARRAY_BUFFER_BINDING:
    639       if (share_group_->bind_generates_resource()) {
    640         *params =
    641             vertex_array_object_manager_->bound_element_array_buffer();
    642         return true;
    643       }
    644       return false;
    645     case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
    646       *params = bound_pixel_pack_transfer_buffer_id_;
    647       return true;
    648     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
    649       *params = bound_pixel_unpack_transfer_buffer_id_;
    650       return true;
    651     case GL_ACTIVE_TEXTURE:
    652       *params = active_texture_unit_ + GL_TEXTURE0;
    653       return true;
    654     case GL_TEXTURE_BINDING_2D:
    655       if (share_group_->bind_generates_resource()) {
    656         *params = texture_units_[active_texture_unit_].bound_texture_2d;
    657         return true;
    658       }
    659       return false;
    660     case GL_TEXTURE_BINDING_CUBE_MAP:
    661       if (share_group_->bind_generates_resource()) {
    662         *params = texture_units_[active_texture_unit_].bound_texture_cube_map;
    663         return true;
    664       }
    665       return false;
    666     case GL_FRAMEBUFFER_BINDING:
    667       if (share_group_->bind_generates_resource()) {
    668         *params = bound_framebuffer_;
    669         return true;
    670       }
    671       return false;
    672     case GL_READ_FRAMEBUFFER_BINDING:
    673       if (IsChromiumFramebufferMultisampleAvailable() &&
    674           share_group_->bind_generates_resource()) {
    675         *params = bound_read_framebuffer_;
    676         return true;
    677       }
    678       return false;
    679     case GL_RENDERBUFFER_BINDING:
    680       if (share_group_->bind_generates_resource()) {
    681         *params = bound_renderbuffer_;
    682         return true;
    683       }
    684       return false;
    685     default:
    686       return false;
    687   }
    688 }
    689 
    690 bool GLES2Implementation::GetBooleanvHelper(GLenum pname, GLboolean* params) {
    691   // TODO(gman): Make this handle pnames that return more than 1 value.
    692   GLint value;
    693   if (!GetHelper(pname, &value)) {
    694     return false;
    695   }
    696   *params = static_cast<GLboolean>(value);
    697   return true;
    698 }
    699 
    700 bool GLES2Implementation::GetFloatvHelper(GLenum pname, GLfloat* params) {
    701   // TODO(gman): Make this handle pnames that return more than 1 value.
    702   GLint value;
    703   if (!GetHelper(pname, &value)) {
    704     return false;
    705   }
    706   *params = static_cast<GLfloat>(value);
    707   return true;
    708 }
    709 
    710 bool GLES2Implementation::GetIntegervHelper(GLenum pname, GLint* params) {
    711   return GetHelper(pname, params);
    712 }
    713 
    714 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
    715     GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
    716   typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result;
    717   Result* result = GetResultAs<Result*>();
    718   if (!result) {
    719     return 0;
    720   }
    721   *result = 0;
    722   helper_->GetMaxValueInBufferCHROMIUM(
    723       buffer_id, count, type, offset, GetResultShmId(), GetResultShmOffset());
    724   WaitForCmd();
    725   return *result;
    726 }
    727 
    728 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUM(
    729     GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
    730   GPU_CLIENT_SINGLE_THREAD_CHECK();
    731   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
    732                  << buffer_id << ", " << count << ", "
    733                  << GLES2Util::GetStringGetMaxIndexType(type)
    734                  << ", " << offset << ")");
    735   GLuint result = GetMaxValueInBufferCHROMIUMHelper(
    736       buffer_id, count, type, offset);
    737   GPU_CLIENT_LOG("returned " << result);
    738   CheckGLError();
    739   return result;
    740 }
    741 
    742 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore) {
    743   if (restore) {
    744     RestoreArrayBuffer(restore);
    745     // Restore the element array binding.
    746     // We only need to restore it if it wasn't a client side array.
    747     if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
    748       helper_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    749     }
    750   }
    751 }
    752 
    753 void GLES2Implementation::RestoreArrayBuffer(bool restore) {
    754   if (restore) {
    755     // Restore the user's current binding.
    756     helper_->BindBuffer(GL_ARRAY_BUFFER, bound_array_buffer_id_);
    757   }
    758 }
    759 
    760 void GLES2Implementation::DrawElements(
    761     GLenum mode, GLsizei count, GLenum type, const void* indices) {
    762   GPU_CLIENT_SINGLE_THREAD_CHECK();
    763   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
    764       << GLES2Util::GetStringDrawMode(mode) << ", "
    765       << count << ", "
    766       << GLES2Util::GetStringIndexType(type) << ", "
    767       << static_cast<const void*>(indices) << ")");
    768   if (count < 0) {
    769     SetGLError(GL_INVALID_VALUE, "glDrawElements", "count less than 0.");
    770     return;
    771   }
    772   if (count == 0) {
    773     return;
    774   }
    775   GLuint offset = 0;
    776   bool simulated = false;
    777   if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
    778       "glDrawElements", this, helper_, count, type, 0, indices,
    779       &offset, &simulated)) {
    780     return;
    781   }
    782   helper_->DrawElements(mode, count, type, offset);
    783   RestoreElementAndArrayBuffers(simulated);
    784   CheckGLError();
    785 }
    786 
    787 void GLES2Implementation::Flush() {
    788   GPU_CLIENT_SINGLE_THREAD_CHECK();
    789   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
    790   // Insert the cmd to call glFlush
    791   helper_->Flush();
    792   // Flush our command buffer
    793   // (tell the service to execute up to the flush cmd.)
    794   helper_->CommandBufferHelper::Flush();
    795 }
    796 
    797 void GLES2Implementation::ShallowFlushCHROMIUM() {
    798   GPU_CLIENT_SINGLE_THREAD_CHECK();
    799   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
    800   // Flush our command buffer
    801   // (tell the service to execute up to the flush cmd.)
    802   helper_->CommandBufferHelper::Flush();
    803 }
    804 
    805 void GLES2Implementation::Finish() {
    806   GPU_CLIENT_SINGLE_THREAD_CHECK();
    807   FinishHelper();
    808 }
    809 
    810 void GLES2Implementation::ShallowFinishCHROMIUM() {
    811   GPU_CLIENT_SINGLE_THREAD_CHECK();
    812   // Flush our command buffer (tell the service to execute up to the flush cmd
    813   // and don't return until it completes).
    814   helper_->CommandBufferHelper::Finish();
    815 }
    816 
    817 bool GLES2Implementation::MustBeContextLost() {
    818   bool context_lost = helper_->IsContextLost();
    819   if (!context_lost) {
    820     WaitForCmd();
    821     context_lost = helper_->IsContextLost();
    822   }
    823   GPU_CHECK(context_lost);
    824   return context_lost;
    825 }
    826 
    827 void GLES2Implementation::FinishHelper() {
    828   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
    829   TRACE_EVENT0("gpu", "GLES2::Finish");
    830   // Insert the cmd to call glFinish
    831   helper_->Finish();
    832   // Finish our command buffer
    833   // (tell the service to execute up to the Finish cmd and wait for it to
    834   // execute.)
    835   helper_->CommandBufferHelper::Finish();
    836 }
    837 
    838 void GLES2Implementation::SwapBuffers() {
    839   GPU_CLIENT_SINGLE_THREAD_CHECK();
    840   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
    841   // TODO(piman): Strictly speaking we'd want to insert the token after the
    842   // swap, but the state update with the updated token might not have happened
    843   // by the time the SwapBuffer callback gets called, forcing us to synchronize
    844   // with the GPU process more than needed. So instead, make it happen before.
    845   // All it means is that we could be slightly looser on the kMaxSwapBuffers
    846   // semantics if the client doesn't use the callback mechanism, and by chance
    847   // the scheduler yields between the InsertToken and the SwapBuffers.
    848   swap_buffers_tokens_.push(helper_->InsertToken());
    849   helper_->SwapBuffers();
    850   helper_->CommandBufferHelper::Flush();
    851   // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
    852   // compensate for TODO above.
    853   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
    854     helper_->WaitForToken(swap_buffers_tokens_.front());
    855     swap_buffers_tokens_.pop();
    856   }
    857 }
    858 
    859 void GLES2Implementation::GenSharedIdsCHROMIUM(
    860   GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
    861   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSharedIdsCHROMIUM("
    862       << namespace_id << ", " << id_offset << ", " << n << ", " <<
    863       static_cast<void*>(ids) << ")");
    864   TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM");
    865   GLsizei num = n;
    866   GLuint* dst = ids;
    867   while (num) {
    868     ScopedTransferBufferArray<GLint> id_buffer(num, helper_, transfer_buffer_);
    869     if (!id_buffer.valid()) {
    870       return;
    871     }
    872     helper_->GenSharedIdsCHROMIUM(
    873         namespace_id, id_offset, id_buffer.num_elements(),
    874         id_buffer.shm_id(), id_buffer.offset());
    875     WaitForCmd();
    876     memcpy(dst, id_buffer.address(), sizeof(*dst) * id_buffer.num_elements());
    877     num -= id_buffer.num_elements();
    878     dst += id_buffer.num_elements();
    879   }
    880   GPU_CLIENT_LOG_CODE_BLOCK({
    881     for (GLsizei i = 0; i < n; ++i) {
    882       GPU_CLIENT_LOG("  " << i << ": " << namespace_id << ", " << ids[i]);
    883     }
    884   });
    885 }
    886 
    887 void GLES2Implementation::DeleteSharedIdsCHROMIUM(
    888     GLuint namespace_id, GLsizei n, const GLuint* ids) {
    889   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedIdsCHROMIUM("
    890       << namespace_id << ", " << n << ", "
    891       << static_cast<const void*>(ids) << ")");
    892   GPU_CLIENT_LOG_CODE_BLOCK({
    893     for (GLsizei i = 0; i < n; ++i) {
    894       GPU_CLIENT_LOG("  " << i << ": " << namespace_id << ", "  << ids[i]);
    895     }
    896   });
    897   TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM");
    898   while (n) {
    899     ScopedTransferBufferArray<GLint> id_buffer(n, helper_, transfer_buffer_);
    900     if (!id_buffer.valid()) {
    901       return;
    902     }
    903     memcpy(id_buffer.address(), ids, sizeof(*ids) * id_buffer.num_elements());
    904     helper_->DeleteSharedIdsCHROMIUM(
    905         namespace_id, id_buffer.num_elements(),
    906         id_buffer.shm_id(), id_buffer.offset());
    907     WaitForCmd();
    908     n -= id_buffer.num_elements();
    909     ids += id_buffer.num_elements();
    910   }
    911 }
    912 
    913 void GLES2Implementation::RegisterSharedIdsCHROMIUM(
    914     GLuint namespace_id, GLsizei n, const GLuint* ids) {
    915   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRegisterSharedIdsCHROMIUM("
    916      << namespace_id << ", " << n << ", "
    917      << static_cast<const void*>(ids) << ")");
    918   GPU_CLIENT_LOG_CODE_BLOCK({
    919     for (GLsizei i = 0; i < n; ++i) {
    920       GPU_CLIENT_LOG("  " << i << ": "  << namespace_id << ", " << ids[i]);
    921     }
    922   });
    923   TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM");
    924   while (n) {
    925     ScopedTransferBufferArray<GLint> id_buffer(n, helper_, transfer_buffer_);
    926     if (!id_buffer.valid()) {
    927       return;
    928     }
    929     memcpy(id_buffer.address(), ids, sizeof(*ids) * id_buffer.num_elements());
    930     helper_->RegisterSharedIdsCHROMIUM(
    931         namespace_id, id_buffer.num_elements(),
    932         id_buffer.shm_id(), id_buffer.offset());
    933     WaitForCmd();
    934     n -= id_buffer.num_elements();
    935     ids += id_buffer.num_elements();
    936   }
    937 }
    938 
    939 void GLES2Implementation::BindAttribLocation(
    940   GLuint program, GLuint index, const char* name) {
    941   GPU_CLIENT_SINGLE_THREAD_CHECK();
    942   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
    943       << program << ", " << index << ", " << name << ")");
    944   SetBucketAsString(kResultBucketId, name);
    945   helper_->BindAttribLocationBucket(program, index, kResultBucketId);
    946   helper_->SetBucketSize(kResultBucketId, 0);
    947   CheckGLError();
    948 }
    949 
    950 void GLES2Implementation::BindUniformLocationCHROMIUM(
    951   GLuint program, GLint location, const char* name) {
    952   GPU_CLIENT_SINGLE_THREAD_CHECK();
    953   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
    954       << program << ", " << location << ", " << name << ")");
    955   SetBucketAsString(kResultBucketId, name);
    956   helper_->BindUniformLocationCHROMIUMBucket(
    957       program, location, kResultBucketId);
    958   helper_->SetBucketSize(kResultBucketId, 0);
    959   CheckGLError();
    960 }
    961 
    962 void GLES2Implementation::GetVertexAttribPointerv(
    963     GLuint index, GLenum pname, void** ptr) {
    964   GPU_CLIENT_SINGLE_THREAD_CHECK();
    965   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
    966       << index << ", " << GLES2Util::GetStringVertexPointer(pname) << ", "
    967       << static_cast<void*>(ptr) << ")");
    968   GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results = 1);
    969   if (!vertex_array_object_manager_->GetAttribPointer(index, pname, ptr)) {
    970     TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
    971     typedef cmds::GetVertexAttribPointerv::Result Result;
    972     Result* result = GetResultAs<Result*>();
    973     if (!result) {
    974       return;
    975     }
    976     result->SetNumResults(0);
    977     helper_->GetVertexAttribPointerv(
    978       index, pname, GetResultShmId(), GetResultShmOffset());
    979     WaitForCmd();
    980     result->CopyResult(ptr);
    981     GPU_CLIENT_LOG_CODE_BLOCK(num_results = result->GetNumResults());
    982   }
    983   GPU_CLIENT_LOG_CODE_BLOCK({
    984     for (int32 i = 0; i < num_results; ++i) {
    985       GPU_CLIENT_LOG("  " << i << ": " << ptr[i]);
    986     }
    987   });
    988   CheckGLError();
    989 }
    990 
    991 bool GLES2Implementation::DeleteProgramHelper(GLuint program) {
    992   if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds(
    993       this, 1, &program, &GLES2Implementation::DeleteProgramStub)) {
    994     SetGLError(
    995         GL_INVALID_VALUE,
    996         "glDeleteProgram", "id not created by this context.");
    997     return false;
    998   }
    999   if (program == current_program_) {
   1000     current_program_ = 0;
   1001   }
   1002   return true;
   1003 }
   1004 
   1005 void GLES2Implementation::DeleteProgramStub(
   1006     GLsizei n, const GLuint* programs) {
   1007   GPU_DCHECK_EQ(1, n);
   1008   share_group_->program_info_manager()->DeleteInfo(programs[0]);
   1009   helper_->DeleteProgram(programs[0]);
   1010 }
   1011 
   1012 bool GLES2Implementation::DeleteShaderHelper(GLuint shader) {
   1013   if (!GetIdHandler(id_namespaces::kProgramsAndShaders)->FreeIds(
   1014       this, 1, &shader, &GLES2Implementation::DeleteShaderStub)) {
   1015     SetGLError(
   1016         GL_INVALID_VALUE,
   1017         "glDeleteShader", "id not created by this context.");
   1018     return false;
   1019   }
   1020   return true;
   1021 }
   1022 
   1023 void GLES2Implementation::DeleteShaderStub(
   1024     GLsizei n, const GLuint* shaders) {
   1025   GPU_DCHECK_EQ(1, n);
   1026   share_group_->program_info_manager()->DeleteInfo(shaders[0]);
   1027   helper_->DeleteShader(shaders[0]);
   1028 }
   1029 
   1030 
   1031 GLint GLES2Implementation::GetAttribLocationHelper(
   1032     GLuint program, const char* name) {
   1033   typedef cmds::GetAttribLocationBucket::Result Result;
   1034   Result* result = GetResultAs<Result*>();
   1035   if (!result) {
   1036     return -1;
   1037   }
   1038   *result = -1;
   1039   SetBucketAsCString(kResultBucketId, name);
   1040   helper_->GetAttribLocationBucket(
   1041       program, kResultBucketId, GetResultShmId(), GetResultShmOffset());
   1042   WaitForCmd();
   1043   helper_->SetBucketSize(kResultBucketId, 0);
   1044   return *result;
   1045 }
   1046 
   1047 GLint GLES2Implementation::GetAttribLocation(
   1048     GLuint program, const char* name) {
   1049   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1050   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
   1051       << ", " << name << ")");
   1052   TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
   1053   GLint loc = share_group_->program_info_manager()->GetAttribLocation(
   1054       this, program, name);
   1055   GPU_CLIENT_LOG("returned " << loc);
   1056   CheckGLError();
   1057   return loc;
   1058 }
   1059 
   1060 GLint GLES2Implementation::GetUniformLocationHelper(
   1061     GLuint program, const char* name) {
   1062   typedef cmds::GetUniformLocationBucket::Result Result;
   1063   Result* result = GetResultAs<Result*>();
   1064   if (!result) {
   1065     return -1;
   1066   }
   1067   *result = -1;
   1068   SetBucketAsCString(kResultBucketId, name);
   1069   helper_->GetUniformLocationBucket(program, kResultBucketId,
   1070                                     GetResultShmId(), GetResultShmOffset());
   1071   WaitForCmd();
   1072   helper_->SetBucketSize(kResultBucketId, 0);
   1073   return *result;
   1074 }
   1075 
   1076 GLint GLES2Implementation::GetUniformLocation(
   1077     GLuint program, const char* name) {
   1078   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1079   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
   1080       << ", " << name << ")");
   1081   TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
   1082   GLint loc = share_group_->program_info_manager()->GetUniformLocation(
   1083       this, program, name);
   1084   GPU_CLIENT_LOG("returned " << loc);
   1085   CheckGLError();
   1086   return loc;
   1087 }
   1088 
   1089 void GLES2Implementation::UseProgram(GLuint program) {
   1090   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1091   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program << ")");
   1092   if (current_program_ != program) {
   1093     current_program_ = program;
   1094     helper_->UseProgram(program);
   1095   }
   1096   CheckGLError();
   1097 }
   1098 
   1099 bool GLES2Implementation::GetProgramivHelper(
   1100     GLuint program, GLenum pname, GLint* params) {
   1101   bool got_value = share_group_->program_info_manager()->GetProgramiv(
   1102       this, program, pname, params);
   1103   GPU_CLIENT_LOG_CODE_BLOCK({
   1104     if (got_value) {
   1105       GPU_CLIENT_LOG("  0: " << *params);
   1106     }
   1107   });
   1108   return got_value;
   1109 }
   1110 
   1111 void GLES2Implementation::LinkProgram(GLuint program) {
   1112   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1113   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")");
   1114   helper_->LinkProgram(program);
   1115   share_group_->program_info_manager()->CreateInfo(program);
   1116   CheckGLError();
   1117 }
   1118 
   1119 void GLES2Implementation::ShaderBinary(
   1120     GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary,
   1121     GLsizei length) {
   1122   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1123   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n << ", "
   1124       << static_cast<const void*>(shaders) << ", "
   1125       << GLES2Util::GetStringEnum(binaryformat) << ", "
   1126       << static_cast<const void*>(binary) << ", "
   1127       << length << ")");
   1128   if (n < 0) {
   1129     SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0.");
   1130     return;
   1131   }
   1132   if (length < 0) {
   1133     SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0.");
   1134     return;
   1135   }
   1136   // TODO(gman): ShaderBinary should use buckets.
   1137   unsigned int shader_id_size = n * sizeof(*shaders);
   1138   ScopedTransferBufferArray<GLint> buffer(
   1139       shader_id_size + length, helper_, transfer_buffer_);
   1140   if (!buffer.valid() || buffer.num_elements() != shader_id_size + length) {
   1141     SetGLError(GL_OUT_OF_MEMORY, "glShaderBinary", "out of memory.");
   1142     return;
   1143   }
   1144   void* shader_ids = buffer.elements();
   1145   void* shader_data = buffer.elements() + shader_id_size;
   1146   memcpy(shader_ids, shaders, shader_id_size);
   1147   memcpy(shader_data, binary, length);
   1148   helper_->ShaderBinary(
   1149       n,
   1150       buffer.shm_id(),
   1151       buffer.offset(),
   1152       binaryformat,
   1153       buffer.shm_id(),
   1154       buffer.offset() + shader_id_size,
   1155       length);
   1156   CheckGLError();
   1157 }
   1158 
   1159 void GLES2Implementation::PixelStorei(GLenum pname, GLint param) {
   1160   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1161   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
   1162       << GLES2Util::GetStringPixelStore(pname) << ", "
   1163       << param << ")");
   1164   switch (pname) {
   1165     case GL_PACK_ALIGNMENT:
   1166         pack_alignment_ = param;
   1167         break;
   1168     case GL_UNPACK_ALIGNMENT:
   1169         unpack_alignment_ = param;
   1170         break;
   1171     case GL_UNPACK_ROW_LENGTH:
   1172         unpack_row_length_ = param;
   1173         return;
   1174     case GL_UNPACK_SKIP_ROWS:
   1175         unpack_skip_rows_ = param;
   1176         return;
   1177     case GL_UNPACK_SKIP_PIXELS:
   1178         unpack_skip_pixels_ = param;
   1179         return;
   1180     case GL_UNPACK_FLIP_Y_CHROMIUM:
   1181         unpack_flip_y_ = (param != 0);
   1182         break;
   1183     case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
   1184         pack_reverse_row_order_ =
   1185             IsAnglePackReverseRowOrderAvailable() ? (param != 0) : false;
   1186         break;
   1187     default:
   1188         break;
   1189   }
   1190   helper_->PixelStorei(pname, param);
   1191   CheckGLError();
   1192 }
   1193 
   1194 
   1195 void GLES2Implementation::VertexAttribPointer(
   1196     GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
   1197     const void* ptr) {
   1198   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1199   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
   1200       << index << ", "
   1201       << size << ", "
   1202       << GLES2Util::GetStringVertexAttribType(type) << ", "
   1203       << GLES2Util::GetStringBool(normalized) << ", "
   1204       << stride << ", "
   1205       << static_cast<const void*>(ptr) << ")");
   1206   // Record the info on the client side.
   1207   if (!vertex_array_object_manager_->SetAttribPointer(
   1208       bound_array_buffer_id_, index, size, type, normalized, stride, ptr)) {
   1209     SetGLError(GL_INVALID_OPERATION, "glVertexAttribPointer",
   1210                "client side arrays are not allowed in vertex array objects.");
   1211     return;
   1212   }
   1213 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
   1214   if (bound_array_buffer_id_ != 0) {
   1215     // Only report NON client side buffers to the service.
   1216     helper_->VertexAttribPointer(index, size, type, normalized, stride,
   1217                                  ToGLuint(ptr));
   1218   }
   1219 #else  // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
   1220   helper_->VertexAttribPointer(index, size, type, normalized, stride,
   1221                                ToGLuint(ptr));
   1222 #endif  // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
   1223   CheckGLError();
   1224 }
   1225 
   1226 void GLES2Implementation::VertexAttribDivisorANGLE(
   1227     GLuint index, GLuint divisor) {
   1228   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1229   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
   1230       << index << ", "
   1231       << divisor << ") ");
   1232   // Record the info on the client side.
   1233   vertex_array_object_manager_->SetAttribDivisor(index, divisor);
   1234   helper_->VertexAttribDivisorANGLE(index, divisor);
   1235   CheckGLError();
   1236 }
   1237 
   1238 void GLES2Implementation::ShaderSource(
   1239     GLuint shader, GLsizei count, const GLchar* const* source, const GLint* length) {
   1240   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1241   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderSource("
   1242       << shader << ", " << count << ", "
   1243       << static_cast<const void*>(source) << ", "
   1244       << static_cast<const void*>(length) << ")");
   1245   GPU_CLIENT_LOG_CODE_BLOCK({
   1246     for (GLsizei ii = 0; ii < count; ++ii) {
   1247       if (source[ii]) {
   1248         if (length && length[ii] >= 0) {
   1249           std::string str(source[ii], length[ii]);
   1250           GPU_CLIENT_LOG("  " << ii << ": ---\n" << str << "\n---");
   1251         } else {
   1252           GPU_CLIENT_LOG("  " << ii << ": ---\n" << source[ii] << "\n---");
   1253         }
   1254       } else {
   1255         GPU_CLIENT_LOG("  " << ii << ": NULL");
   1256       }
   1257     }
   1258   });
   1259   if (count < 0) {
   1260     SetGLError(GL_INVALID_VALUE, "glShaderSource", "count < 0");
   1261     return;
   1262   }
   1263   if (shader == 0) {
   1264     SetGLError(GL_INVALID_VALUE, "glShaderSource", "shader == 0");
   1265     return;
   1266   }
   1267 
   1268   // Compute the total size.
   1269   uint32 total_size = 1;
   1270   for (GLsizei ii = 0; ii < count; ++ii) {
   1271     if (source[ii]) {
   1272       total_size += (length && length[ii] >= 0) ?
   1273           static_cast<size_t>(length[ii]) : strlen(source[ii]);
   1274     }
   1275   }
   1276 
   1277   // Concatenate all the strings in to a bucket on the service.
   1278   helper_->SetBucketSize(kResultBucketId, total_size);
   1279   uint32 offset = 0;
   1280   for (GLsizei ii = 0; ii <= count; ++ii) {
   1281     const char* src = ii < count ? source[ii] : "";
   1282     if (src) {
   1283       uint32 size = ii < count ?
   1284           (length ? static_cast<size_t>(length[ii]) : strlen(src)) : 1;
   1285       while (size) {
   1286         ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
   1287         if (!buffer.valid()) {
   1288           return;
   1289         }
   1290         memcpy(buffer.address(), src, buffer.size());
   1291         helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
   1292                                buffer.shm_id(), buffer.offset());
   1293         offset += buffer.size();
   1294         src += buffer.size();
   1295         size -= buffer.size();
   1296       }
   1297     }
   1298   }
   1299 
   1300   GPU_DCHECK_EQ(total_size, offset);
   1301 
   1302   helper_->ShaderSourceBucket(shader, kResultBucketId);
   1303   helper_->SetBucketSize(kResultBucketId, 0);
   1304   CheckGLError();
   1305 }
   1306 
   1307 void GLES2Implementation::BufferDataHelper(
   1308     GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
   1309   if (size < 0) {
   1310     SetGLError(GL_INVALID_VALUE, "glBufferData", "size < 0");
   1311     return;
   1312   }
   1313 
   1314   GLuint buffer_id;
   1315   if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) {
   1316     if (!buffer_id) {
   1317       return;
   1318     }
   1319 
   1320     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
   1321     if (buffer) {
   1322       // Free buffer memory, pending the passage of a token.
   1323       buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken());
   1324 
   1325       // Remove old buffer.
   1326       buffer_tracker_->RemoveBuffer(buffer_id);
   1327     }
   1328 
   1329     // Create new buffer.
   1330     buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
   1331     GPU_DCHECK(buffer);
   1332     if (buffer->address() && data)
   1333       memcpy(buffer->address(), data, size);
   1334     return;
   1335   }
   1336 
   1337   if (size == 0) {
   1338     return;
   1339   }
   1340 
   1341   // If there is no data just send BufferData
   1342   if (!data) {
   1343     helper_->BufferData(target, size, 0, 0, usage);
   1344     return;
   1345   }
   1346 
   1347   // See if we can send all at once.
   1348   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
   1349   if (!buffer.valid()) {
   1350     return;
   1351   }
   1352 
   1353   if (buffer.size() >= static_cast<unsigned int>(size)) {
   1354     memcpy(buffer.address(), data, size);
   1355     helper_->BufferData(
   1356         target,
   1357         size,
   1358         buffer.shm_id(),
   1359         buffer.offset(),
   1360         usage);
   1361     return;
   1362   }
   1363 
   1364   // Make the buffer with BufferData then send via BufferSubData
   1365   helper_->BufferData(target, size, 0, 0, usage);
   1366   BufferSubDataHelperImpl(target, 0, size, data, &buffer);
   1367   CheckGLError();
   1368 }
   1369 
   1370 void GLES2Implementation::BufferData(
   1371     GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
   1372   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1373   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
   1374       << GLES2Util::GetStringBufferTarget(target) << ", "
   1375       << size << ", "
   1376       << static_cast<const void*>(data) << ", "
   1377       << GLES2Util::GetStringBufferUsage(usage) << ")");
   1378   BufferDataHelper(target, size, data, usage);
   1379   CheckGLError();
   1380 }
   1381 
   1382 void GLES2Implementation::BufferSubDataHelper(
   1383     GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
   1384   if (size == 0) {
   1385     return;
   1386   }
   1387 
   1388   if (size < 0) {
   1389     SetGLError(GL_INVALID_VALUE, "glBufferSubData", "size < 0");
   1390     return;
   1391   }
   1392 
   1393   GLuint buffer_id;
   1394   if (GetBoundPixelTransferBuffer(target, "glBufferSubData", &buffer_id)) {
   1395     if (!buffer_id) {
   1396       return;
   1397     }
   1398     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
   1399     if (!buffer) {
   1400       SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
   1401       return;
   1402     }
   1403 
   1404     int32 end = 0;
   1405     int32 buffer_size = buffer->size();
   1406     if (!SafeAddInt32(offset, size, &end) || end > buffer_size) {
   1407       SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
   1408       return;
   1409     }
   1410 
   1411     if (buffer->address() && data)
   1412       memcpy(static_cast<uint8*>(buffer->address()) + offset, data, size);
   1413     return;
   1414   }
   1415 
   1416   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
   1417   BufferSubDataHelperImpl(target, offset, size, data, &buffer);
   1418 }
   1419 
   1420 void GLES2Implementation::BufferSubDataHelperImpl(
   1421     GLenum target, GLintptr offset, GLsizeiptr size, const void* data,
   1422     ScopedTransferBufferPtr* buffer) {
   1423   GPU_DCHECK(buffer);
   1424   GPU_DCHECK_GT(size, 0);
   1425 
   1426   const int8* source = static_cast<const int8*>(data);
   1427   while (size) {
   1428     if (!buffer->valid() || buffer->size() == 0) {
   1429       buffer->Reset(size);
   1430       if (!buffer->valid()) {
   1431         return;
   1432       }
   1433     }
   1434     memcpy(buffer->address(), source, buffer->size());
   1435     helper_->BufferSubData(
   1436         target, offset, buffer->size(), buffer->shm_id(), buffer->offset());
   1437     offset += buffer->size();
   1438     source += buffer->size();
   1439     size -= buffer->size();
   1440     buffer->Release();
   1441   }
   1442 }
   1443 
   1444 void GLES2Implementation::BufferSubData(
   1445     GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
   1446   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1447   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
   1448       << GLES2Util::GetStringBufferTarget(target) << ", "
   1449       << offset << ", " << size << ", "
   1450       << static_cast<const void*>(data) << ")");
   1451   BufferSubDataHelper(target, offset, size, data);
   1452   CheckGLError();
   1453 }
   1454 
   1455 bool GLES2Implementation::GetBoundPixelTransferBuffer(
   1456     GLenum target,
   1457     const char* function_name,
   1458     GLuint* buffer_id) {
   1459   *buffer_id = 0;
   1460 
   1461   switch (target) {
   1462     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
   1463       *buffer_id = bound_pixel_pack_transfer_buffer_id_;
   1464       break;
   1465     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
   1466       *buffer_id = bound_pixel_unpack_transfer_buffer_id_;
   1467       break;
   1468     default:
   1469       // Unknown target
   1470       return false;
   1471   }
   1472   if (!*buffer_id) {
   1473     SetGLError(GL_INVALID_OPERATION, function_name, "no buffer bound");
   1474   }
   1475   return true;
   1476 }
   1477 
   1478 BufferTracker::Buffer*
   1479 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
   1480     GLuint buffer_id,
   1481     const char* function_name,
   1482     GLuint offset, GLsizei size)
   1483 {
   1484   DCHECK(buffer_id);
   1485   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
   1486   if (!buffer) {
   1487     SetGLError(GL_INVALID_OPERATION, function_name, "invalid buffer");
   1488     return NULL;
   1489   }
   1490   if (buffer->mapped()) {
   1491     SetGLError(GL_INVALID_OPERATION, function_name, "buffer mapped");
   1492     return NULL;
   1493   }
   1494   if ((buffer->size() - offset) < static_cast<GLuint>(size)) {
   1495     SetGLError(GL_INVALID_VALUE, function_name, "unpack size to large");
   1496     return NULL;
   1497   }
   1498   return buffer;
   1499 }
   1500 
   1501 void GLES2Implementation::CompressedTexImage2D(
   1502     GLenum target, GLint level, GLenum internalformat, GLsizei width,
   1503     GLsizei height, GLint border, GLsizei image_size, const void* data) {
   1504   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1505   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
   1506       << GLES2Util::GetStringTextureTarget(target) << ", "
   1507       << level << ", "
   1508       << GLES2Util::GetStringCompressedTextureFormat(internalformat) << ", "
   1509       << width << ", " << height << ", " << border << ", "
   1510       << image_size << ", "
   1511       << static_cast<const void*>(data) << ")");
   1512   if (width < 0 || height < 0 || level < 0) {
   1513     SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "dimension < 0");
   1514     return;
   1515   }
   1516   if (height == 0 || width == 0) {
   1517     return;
   1518   }
   1519   // If there's a pixel unpack buffer bound use it when issuing
   1520   // CompressedTexImage2D.
   1521   if (bound_pixel_unpack_transfer_buffer_id_) {
   1522     GLuint offset = ToGLuint(data);
   1523     BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   1524         bound_pixel_unpack_transfer_buffer_id_,
   1525         "glCompressedTexImage2D", offset, image_size);
   1526     if (buffer && buffer->shm_id() != -1) {
   1527       helper_->CompressedTexImage2D(
   1528           target, level, internalformat, width, height, border, image_size,
   1529           buffer->shm_id(), buffer->shm_offset() + offset);
   1530       buffer->set_transfer_ready_token(helper_->InsertToken());
   1531     }
   1532     return;
   1533   }
   1534   SetBucketContents(kResultBucketId, data, image_size);
   1535   helper_->CompressedTexImage2DBucket(
   1536       target, level, internalformat, width, height, border, kResultBucketId);
   1537   // Free the bucket. This is not required but it does free up the memory.
   1538   // and we don't have to wait for the result so from the client's perspective
   1539   // it's cheap.
   1540   helper_->SetBucketSize(kResultBucketId, 0);
   1541   CheckGLError();
   1542 }
   1543 
   1544 void GLES2Implementation::CompressedTexSubImage2D(
   1545     GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
   1546     GLsizei height, GLenum format, GLsizei image_size, const void* data) {
   1547   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1548   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
   1549       << GLES2Util::GetStringTextureTarget(target) << ", "
   1550       << level << ", "
   1551       << xoffset << ", " << yoffset << ", "
   1552       << width << ", " << height << ", "
   1553       << GLES2Util::GetStringCompressedTextureFormat(format) << ", "
   1554       << image_size << ", "
   1555       << static_cast<const void*>(data) << ")");
   1556   if (width < 0 || height < 0 || level < 0) {
   1557     SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "dimension < 0");
   1558     return;
   1559   }
   1560   // If there's a pixel unpack buffer bound use it when issuing
   1561   // CompressedTexSubImage2D.
   1562   if (bound_pixel_unpack_transfer_buffer_id_) {
   1563     GLuint offset = ToGLuint(data);
   1564     BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   1565         bound_pixel_unpack_transfer_buffer_id_,
   1566         "glCompressedTexSubImage2D", offset, image_size);
   1567     if (buffer && buffer->shm_id() != -1) {
   1568       helper_->CompressedTexSubImage2D(
   1569           target, level, xoffset, yoffset, width, height, format, image_size,
   1570           buffer->shm_id(), buffer->shm_offset() + offset);
   1571       buffer->set_transfer_ready_token(helper_->InsertToken());
   1572       CheckGLError();
   1573     }
   1574     return;
   1575   }
   1576   SetBucketContents(kResultBucketId, data, image_size);
   1577   helper_->CompressedTexSubImage2DBucket(
   1578       target, level, xoffset, yoffset, width, height, format, kResultBucketId);
   1579   // Free the bucket. This is not required but it does free up the memory.
   1580   // and we don't have to wait for the result so from the client's perspective
   1581   // it's cheap.
   1582   helper_->SetBucketSize(kResultBucketId, 0);
   1583   CheckGLError();
   1584 }
   1585 
   1586 namespace {
   1587 
   1588 void CopyRectToBuffer(
   1589     const void* pixels,
   1590     uint32 height,
   1591     uint32 unpadded_row_size,
   1592     uint32 pixels_padded_row_size,
   1593     bool flip_y,
   1594     void* buffer,
   1595     uint32 buffer_padded_row_size) {
   1596   const int8* source = static_cast<const int8*>(pixels);
   1597   int8* dest = static_cast<int8*>(buffer);
   1598   if (flip_y || pixels_padded_row_size != buffer_padded_row_size) {
   1599     if (flip_y) {
   1600       dest += buffer_padded_row_size * (height - 1);
   1601     }
   1602     // the last row is copied unpadded at the end
   1603     for (; height > 1; --height) {
   1604       memcpy(dest, source, buffer_padded_row_size);
   1605       if (flip_y) {
   1606         dest -= buffer_padded_row_size;
   1607       } else {
   1608         dest += buffer_padded_row_size;
   1609       }
   1610       source += pixels_padded_row_size;
   1611     }
   1612     memcpy(dest, source, unpadded_row_size);
   1613   } else {
   1614     uint32 size = (height - 1) * pixels_padded_row_size + unpadded_row_size;
   1615     memcpy(dest, source, size);
   1616   }
   1617 }
   1618 
   1619 }  // anonymous namespace
   1620 
   1621 void GLES2Implementation::TexImage2D(
   1622     GLenum target, GLint level, GLint internalformat, GLsizei width,
   1623     GLsizei height, GLint border, GLenum format, GLenum type,
   1624     const void* pixels) {
   1625   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1626   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
   1627       << GLES2Util::GetStringTextureTarget(target) << ", "
   1628       << level << ", "
   1629       << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
   1630       << width << ", " << height << ", " << border << ", "
   1631       << GLES2Util::GetStringTextureFormat(format) << ", "
   1632       << GLES2Util::GetStringPixelType(type) << ", "
   1633       << static_cast<const void*>(pixels) << ")");
   1634   if (level < 0 || height < 0 || width < 0) {
   1635     SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimension < 0");
   1636     return;
   1637   }
   1638   uint32 size;
   1639   uint32 unpadded_row_size;
   1640   uint32 padded_row_size;
   1641   if (!GLES2Util::ComputeImageDataSizes(
   1642           width, height, format, type, unpack_alignment_, &size,
   1643           &unpadded_row_size, &padded_row_size)) {
   1644     SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large");
   1645     return;
   1646   }
   1647 
   1648   // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
   1649   if (bound_pixel_unpack_transfer_buffer_id_) {
   1650     GLuint offset = ToGLuint(pixels);
   1651     BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   1652         bound_pixel_unpack_transfer_buffer_id_,
   1653         "glTexImage2D", offset, size);
   1654     if (buffer && buffer->shm_id() != -1) {
   1655       helper_->TexImage2D(
   1656           target, level, internalformat, width, height, border, format, type,
   1657           buffer->shm_id(), buffer->shm_offset() + offset);
   1658       buffer->set_transfer_ready_token(helper_->InsertToken());
   1659       CheckGLError();
   1660     }
   1661     return;
   1662   }
   1663 
   1664   // If there's no data just issue TexImage2D
   1665   if (!pixels) {
   1666     helper_->TexImage2D(
   1667        target, level, internalformat, width, height, border, format, type,
   1668        0, 0);
   1669     CheckGLError();
   1670     return;
   1671   }
   1672 
   1673   // compute the advance bytes per row for the src pixels
   1674   uint32 src_padded_row_size;
   1675   if (unpack_row_length_ > 0) {
   1676     if (!GLES2Util::ComputeImagePaddedRowSize(
   1677         unpack_row_length_, format, type, unpack_alignment_,
   1678         &src_padded_row_size)) {
   1679       SetGLError(
   1680           GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large");
   1681       return;
   1682     }
   1683   } else {
   1684     src_padded_row_size = padded_row_size;
   1685   }
   1686 
   1687   // advance pixels pointer past the skip rows and skip pixels
   1688   pixels = reinterpret_cast<const int8*>(pixels) +
   1689       unpack_skip_rows_ * src_padded_row_size;
   1690   if (unpack_skip_pixels_) {
   1691     uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type);
   1692     pixels = reinterpret_cast<const int8*>(pixels) +
   1693         unpack_skip_pixels_ * group_size;
   1694   }
   1695 
   1696   // Check if we can send it all at once.
   1697   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
   1698   if (!buffer.valid()) {
   1699     return;
   1700   }
   1701 
   1702   if (buffer.size() >= size) {
   1703     CopyRectToBuffer(
   1704         pixels, height, unpadded_row_size, src_padded_row_size, unpack_flip_y_,
   1705         buffer.address(), padded_row_size);
   1706     helper_->TexImage2D(
   1707         target, level, internalformat, width, height, border, format, type,
   1708         buffer.shm_id(), buffer.offset());
   1709     CheckGLError();
   1710     return;
   1711   }
   1712 
   1713   // No, so send it using TexSubImage2D.
   1714   helper_->TexImage2D(
   1715      target, level, internalformat, width, height, border, format, type,
   1716      0, 0);
   1717   TexSubImage2DImpl(
   1718       target, level, 0, 0, width, height, format, type, unpadded_row_size,
   1719       pixels, src_padded_row_size, GL_TRUE, &buffer, padded_row_size);
   1720   CheckGLError();
   1721 }
   1722 
   1723 void GLES2Implementation::TexSubImage2D(
   1724     GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
   1725     GLsizei height, GLenum format, GLenum type, const void* pixels) {
   1726   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1727   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
   1728       << GLES2Util::GetStringTextureTarget(target) << ", "
   1729       << level << ", "
   1730       << xoffset << ", " << yoffset << ", "
   1731       << width << ", " << height << ", "
   1732       << GLES2Util::GetStringTextureFormat(format) << ", "
   1733       << GLES2Util::GetStringPixelType(type) << ", "
   1734       << static_cast<const void*>(pixels) << ")");
   1735 
   1736   if (level < 0 || height < 0 || width < 0) {
   1737     SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "dimension < 0");
   1738     return;
   1739   }
   1740   if (height == 0 || width == 0) {
   1741     return;
   1742   }
   1743 
   1744   uint32 temp_size;
   1745   uint32 unpadded_row_size;
   1746   uint32 padded_row_size;
   1747   if (!GLES2Util::ComputeImageDataSizes(
   1748         width, height, format, type, unpack_alignment_, &temp_size,
   1749         &unpadded_row_size, &padded_row_size)) {
   1750     SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "size to large");
   1751     return;
   1752   }
   1753 
   1754   // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
   1755   if (bound_pixel_unpack_transfer_buffer_id_) {
   1756     GLuint offset = ToGLuint(pixels);
   1757     BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   1758         bound_pixel_unpack_transfer_buffer_id_,
   1759         "glTexSubImage2D", offset, temp_size);
   1760     if (buffer && buffer->shm_id() != -1) {
   1761       helper_->TexSubImage2D(
   1762           target, level, xoffset, yoffset, width, height, format, type,
   1763           buffer->shm_id(), buffer->shm_offset() + offset, false);
   1764       buffer->set_transfer_ready_token(helper_->InsertToken());
   1765       CheckGLError();
   1766     }
   1767     return;
   1768   }
   1769 
   1770   // compute the advance bytes per row for the src pixels
   1771   uint32 src_padded_row_size;
   1772   if (unpack_row_length_ > 0) {
   1773     if (!GLES2Util::ComputeImagePaddedRowSize(
   1774         unpack_row_length_, format, type, unpack_alignment_,
   1775         &src_padded_row_size)) {
   1776       SetGLError(
   1777           GL_INVALID_VALUE, "glTexImage2D", "unpack row length too large");
   1778       return;
   1779     }
   1780   } else {
   1781     src_padded_row_size = padded_row_size;
   1782   }
   1783 
   1784   // advance pixels pointer past the skip rows and skip pixels
   1785   pixels = reinterpret_cast<const int8*>(pixels) +
   1786       unpack_skip_rows_ * src_padded_row_size;
   1787   if (unpack_skip_pixels_) {
   1788     uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type);
   1789     pixels = reinterpret_cast<const int8*>(pixels) +
   1790         unpack_skip_pixels_ * group_size;
   1791   }
   1792 
   1793   ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_);
   1794   TexSubImage2DImpl(
   1795       target, level, xoffset, yoffset, width, height, format, type,
   1796       unpadded_row_size, pixels, src_padded_row_size, GL_FALSE, &buffer,
   1797       padded_row_size);
   1798   CheckGLError();
   1799 }
   1800 
   1801 static GLint ComputeNumRowsThatFitInBuffer(
   1802     GLsizeiptr padded_row_size, GLsizeiptr unpadded_row_size,
   1803     unsigned int size) {
   1804   GPU_DCHECK_GE(unpadded_row_size, 0);
   1805   if (padded_row_size == 0) {
   1806     return 1;
   1807   }
   1808   GLint num_rows = size / padded_row_size;
   1809   return num_rows + (size - num_rows * padded_row_size) / unpadded_row_size;
   1810 }
   1811 
   1812 void GLES2Implementation::TexSubImage2DImpl(
   1813     GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
   1814     GLsizei height, GLenum format, GLenum type, uint32 unpadded_row_size,
   1815     const void* pixels, uint32 pixels_padded_row_size, GLboolean internal,
   1816     ScopedTransferBufferPtr* buffer, uint32 buffer_padded_row_size) {
   1817   GPU_DCHECK(buffer);
   1818   GPU_DCHECK_GE(level, 0);
   1819   GPU_DCHECK_GT(height, 0);
   1820   GPU_DCHECK_GT(width, 0);
   1821 
   1822   const int8* source = reinterpret_cast<const int8*>(pixels);
   1823   GLint original_yoffset = yoffset;
   1824   // Transfer by rows.
   1825   while (height) {
   1826     unsigned int desired_size =
   1827         buffer_padded_row_size * (height - 1) + unpadded_row_size;
   1828     if (!buffer->valid() || buffer->size() == 0) {
   1829       buffer->Reset(desired_size);
   1830       if (!buffer->valid()) {
   1831         return;
   1832       }
   1833     }
   1834 
   1835     GLint num_rows = ComputeNumRowsThatFitInBuffer(
   1836         buffer_padded_row_size, unpadded_row_size, buffer->size());
   1837     num_rows = std::min(num_rows, height);
   1838     CopyRectToBuffer(
   1839         source, num_rows, unpadded_row_size, pixels_padded_row_size,
   1840         unpack_flip_y_, buffer->address(), buffer_padded_row_size);
   1841     GLint y = unpack_flip_y_ ? original_yoffset + height - num_rows : yoffset;
   1842     helper_->TexSubImage2D(
   1843         target, level, xoffset, y, width, num_rows, format, type,
   1844         buffer->shm_id(), buffer->offset(), internal);
   1845     buffer->Release();
   1846     yoffset += num_rows;
   1847     source += num_rows * pixels_padded_row_size;
   1848     height -= num_rows;
   1849   }
   1850 }
   1851 
   1852 bool GLES2Implementation::GetActiveAttribHelper(
   1853     GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
   1854     GLenum* type, char* name) {
   1855   // Clear the bucket so if the command fails nothing will be in it.
   1856   helper_->SetBucketSize(kResultBucketId, 0);
   1857   typedef cmds::GetActiveAttrib::Result Result;
   1858   Result* result = GetResultAs<Result*>();
   1859   if (!result) {
   1860     return false;
   1861   }
   1862   // Set as failed so if the command fails we'll recover.
   1863   result->success = false;
   1864   helper_->GetActiveAttrib(program, index, kResultBucketId,
   1865                            GetResultShmId(), GetResultShmOffset());
   1866   WaitForCmd();
   1867   if (result->success) {
   1868     if (size) {
   1869       *size = result->size;
   1870     }
   1871     if (type) {
   1872       *type = result->type;
   1873     }
   1874     if (length || name) {
   1875       std::vector<int8> str;
   1876       GetBucketContents(kResultBucketId, &str);
   1877       GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
   1878                                   std::max(static_cast<size_t>(0),
   1879                                            str.size() - 1));
   1880       if (length) {
   1881         *length = max_size;
   1882       }
   1883       if (name && bufsize > 0) {
   1884         memcpy(name, &str[0], max_size);
   1885         name[max_size] = '\0';
   1886       }
   1887     }
   1888   }
   1889   return result->success != 0;
   1890 }
   1891 
   1892 void GLES2Implementation::GetActiveAttrib(
   1893     GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
   1894     GLenum* type, char* name) {
   1895   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1896   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
   1897       << program << ", " << index << ", " << bufsize << ", "
   1898       << static_cast<const void*>(length) << ", "
   1899       << static_cast<const void*>(size) << ", "
   1900       << static_cast<const void*>(type) << ", "
   1901       << static_cast<const void*>(name) << ", ");
   1902   if (bufsize < 0) {
   1903     SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "bufsize < 0");
   1904     return;
   1905   }
   1906   TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
   1907   bool success = share_group_->program_info_manager()->GetActiveAttrib(
   1908         this, program, index, bufsize, length, size, type, name);
   1909   if (success) {
   1910     if (size) {
   1911       GPU_CLIENT_LOG("  size: " << *size);
   1912     }
   1913     if (type) {
   1914       GPU_CLIENT_LOG("  type: " << GLES2Util::GetStringEnum(*type));
   1915     }
   1916     if (name) {
   1917       GPU_CLIENT_LOG("  name: " << name);
   1918     }
   1919   }
   1920   CheckGLError();
   1921 }
   1922 
   1923 bool GLES2Implementation::GetActiveUniformHelper(
   1924     GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
   1925     GLenum* type, char* name) {
   1926   // Clear the bucket so if the command fails nothing will be in it.
   1927   helper_->SetBucketSize(kResultBucketId, 0);
   1928   typedef cmds::GetActiveUniform::Result Result;
   1929   Result* result = GetResultAs<Result*>();
   1930   if (!result) {
   1931     return false;
   1932   }
   1933   // Set as failed so if the command fails we'll recover.
   1934   result->success = false;
   1935   helper_->GetActiveUniform(program, index, kResultBucketId,
   1936                             GetResultShmId(), GetResultShmOffset());
   1937   WaitForCmd();
   1938   if (result->success) {
   1939     if (size) {
   1940       *size = result->size;
   1941     }
   1942     if (type) {
   1943       *type = result->type;
   1944     }
   1945     if (length || name) {
   1946       std::vector<int8> str;
   1947       GetBucketContents(kResultBucketId, &str);
   1948       GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
   1949                                   std::max(static_cast<size_t>(0),
   1950                                            str.size() - 1));
   1951       if (length) {
   1952         *length = max_size;
   1953       }
   1954       if (name && bufsize > 0) {
   1955         memcpy(name, &str[0], max_size);
   1956         name[max_size] = '\0';
   1957       }
   1958     }
   1959   }
   1960   return result->success != 0;
   1961 }
   1962 
   1963 void GLES2Implementation::GetActiveUniform(
   1964     GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
   1965     GLenum* type, char* name) {
   1966   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1967   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
   1968       << program << ", " << index << ", " << bufsize << ", "
   1969       << static_cast<const void*>(length) << ", "
   1970       << static_cast<const void*>(size) << ", "
   1971       << static_cast<const void*>(type) << ", "
   1972       << static_cast<const void*>(name) << ", ");
   1973   if (bufsize < 0) {
   1974     SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "bufsize < 0");
   1975     return;
   1976   }
   1977   TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
   1978   bool success = share_group_->program_info_manager()->GetActiveUniform(
   1979       this, program, index, bufsize, length, size, type, name);
   1980   if (success) {
   1981     if (size) {
   1982       GPU_CLIENT_LOG("  size: " << *size);
   1983     }
   1984     if (type) {
   1985       GPU_CLIENT_LOG("  type: " << GLES2Util::GetStringEnum(*type));
   1986     }
   1987     if (name) {
   1988       GPU_CLIENT_LOG("  name: " << name);
   1989     }
   1990   }
   1991   CheckGLError();
   1992 }
   1993 
   1994 void GLES2Implementation::GetAttachedShaders(
   1995     GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
   1996   GPU_CLIENT_SINGLE_THREAD_CHECK();
   1997   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
   1998       << program << ", " << maxcount << ", "
   1999       << static_cast<const void*>(count) << ", "
   2000       << static_cast<const void*>(shaders) << ", ");
   2001   if (maxcount < 0) {
   2002     SetGLError(GL_INVALID_VALUE, "glGetAttachedShaders", "maxcount < 0");
   2003     return;
   2004   }
   2005   TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
   2006   typedef cmds::GetAttachedShaders::Result Result;
   2007   uint32 size = Result::ComputeSize(maxcount);
   2008   Result* result = static_cast<Result*>(transfer_buffer_->Alloc(size));
   2009   if (!result) {
   2010     return;
   2011   }
   2012   result->SetNumResults(0);
   2013   helper_->GetAttachedShaders(
   2014     program,
   2015     transfer_buffer_->GetShmId(),
   2016     transfer_buffer_->GetOffset(result),
   2017     size);
   2018   int32 token = helper_->InsertToken();
   2019   WaitForCmd();
   2020   if (count) {
   2021     *count = result->GetNumResults();
   2022   }
   2023   result->CopyResult(shaders);
   2024   GPU_CLIENT_LOG_CODE_BLOCK({
   2025     for (int32 i = 0; i < result->GetNumResults(); ++i) {
   2026       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
   2027     }
   2028   });
   2029   transfer_buffer_->FreePendingToken(result, token);
   2030   CheckGLError();
   2031 }
   2032 
   2033 void GLES2Implementation::GetShaderPrecisionFormat(
   2034     GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
   2035   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2036   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
   2037       << GLES2Util::GetStringShaderType(shadertype) << ", "
   2038       << GLES2Util::GetStringShaderPrecision(precisiontype) << ", "
   2039       << static_cast<const void*>(range) << ", "
   2040       << static_cast<const void*>(precision) << ", ");
   2041   TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
   2042   typedef cmds::GetShaderPrecisionFormat::Result Result;
   2043   Result* result = GetResultAs<Result*>();
   2044   if (!result) {
   2045     return;
   2046   }
   2047 
   2048   GLStaticState::ShaderPrecisionKey key(shadertype, precisiontype);
   2049   GLStaticState::ShaderPrecisionMap::iterator i =
   2050       static_state_.shader_precisions.find(key);
   2051   if (i != static_state_.shader_precisions.end()) {
   2052     *result = i->second;
   2053   } else {
   2054     result->success = false;
   2055     helper_->GetShaderPrecisionFormat(
   2056         shadertype, precisiontype, GetResultShmId(), GetResultShmOffset());
   2057     WaitForCmd();
   2058     if (result->success)
   2059       static_state_.shader_precisions[key] = *result;
   2060   }
   2061 
   2062   if (result->success) {
   2063     if (range) {
   2064       range[0] = result->min_range;
   2065       range[1] = result->max_range;
   2066       GPU_CLIENT_LOG("  min_range: " << range[0]);
   2067       GPU_CLIENT_LOG("  min_range: " << range[1]);
   2068     }
   2069     if (precision) {
   2070       precision[0] = result->precision;
   2071       GPU_CLIENT_LOG("  min_range: " << precision[0]);
   2072     }
   2073   }
   2074   CheckGLError();
   2075 }
   2076 
   2077 const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) {
   2078   const char* result = NULL;
   2079   // Clears the bucket so if the command fails nothing will be in it.
   2080   helper_->SetBucketSize(kResultBucketId, 0);
   2081   helper_->GetString(name, kResultBucketId);
   2082   std::string str;
   2083   if (GetBucketAsString(kResultBucketId, &str)) {
   2084     // Adds extensions implemented on client side only.
   2085     switch (name) {
   2086       case GL_EXTENSIONS:
   2087         str += std::string(str.empty() ? "" : " ") +
   2088             "GL_CHROMIUM_flipy "
   2089             "GL_CHROMIUM_map_sub "
   2090             "GL_CHROMIUM_shallow_flush "
   2091             "GL_EXT_unpack_subimage";
   2092         if (image_factory_ != NULL) {
   2093           // The first space character is intentional.
   2094           str += " GL_CHROMIUM_map_image";
   2095         }
   2096         break;
   2097       default:
   2098         break;
   2099     }
   2100 
   2101     // Because of WebGL the extensions can change. We have to cache each unique
   2102     // result since we don't know when the client will stop referring to a
   2103     // previous one it queries.
   2104     GLStringMap::iterator it = gl_strings_.find(name);
   2105     if (it == gl_strings_.end()) {
   2106       std::set<std::string> strings;
   2107       std::pair<GLStringMap::iterator, bool> insert_result =
   2108           gl_strings_.insert(std::make_pair(name, strings));
   2109       GPU_DCHECK(insert_result.second);
   2110       it = insert_result.first;
   2111     }
   2112     std::set<std::string>& string_set = it->second;
   2113     std::set<std::string>::const_iterator sit = string_set.find(str);
   2114     if (sit != string_set.end()) {
   2115       result = sit->c_str();
   2116     } else {
   2117       std::pair<std::set<std::string>::const_iterator, bool> insert_result =
   2118           string_set.insert(str);
   2119       GPU_DCHECK(insert_result.second);
   2120       result = insert_result.first->c_str();
   2121     }
   2122   }
   2123   return reinterpret_cast<const GLubyte*>(result);
   2124 }
   2125 
   2126 const GLubyte* GLES2Implementation::GetString(GLenum name) {
   2127   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2128   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
   2129       << GLES2Util::GetStringStringType(name) << ")");
   2130   TRACE_EVENT0("gpu", "GLES2::GetString");
   2131   const GLubyte* result = GetStringHelper(name);
   2132   GPU_CLIENT_LOG("  returned " << reinterpret_cast<const char*>(result));
   2133   CheckGLError();
   2134   return result;
   2135 }
   2136 
   2137 void GLES2Implementation::GetUniformfv(
   2138     GLuint program, GLint location, GLfloat* params) {
   2139   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2140   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
   2141       << program << ", " << location << ", "
   2142       << static_cast<const void*>(params) << ")");
   2143   TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
   2144   typedef cmds::GetUniformfv::Result Result;
   2145   Result* result = GetResultAs<Result*>();
   2146   if (!result) {
   2147     return;
   2148   }
   2149   result->SetNumResults(0);
   2150   helper_->GetUniformfv(
   2151       program, location, GetResultShmId(), GetResultShmOffset());
   2152   WaitForCmd();
   2153   result->CopyResult(params);
   2154   GPU_CLIENT_LOG_CODE_BLOCK({
   2155     for (int32 i = 0; i < result->GetNumResults(); ++i) {
   2156       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
   2157     }
   2158   });
   2159   CheckGLError();
   2160 }
   2161 
   2162 void GLES2Implementation::GetUniformiv(
   2163     GLuint program, GLint location, GLint* params) {
   2164   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2165   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
   2166       << program << ", " << location << ", "
   2167       << static_cast<const void*>(params) << ")");
   2168   TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
   2169   typedef cmds::GetUniformiv::Result Result;
   2170   Result* result = GetResultAs<Result*>();
   2171   if (!result) {
   2172     return;
   2173   }
   2174   result->SetNumResults(0);
   2175   helper_->GetUniformiv(
   2176       program, location, GetResultShmId(), GetResultShmOffset());
   2177   WaitForCmd();
   2178   GetResultAs<cmds::GetUniformfv::Result*>()->CopyResult(params);
   2179   GPU_CLIENT_LOG_CODE_BLOCK({
   2180     for (int32 i = 0; i < result->GetNumResults(); ++i) {
   2181       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
   2182     }
   2183   });
   2184   CheckGLError();
   2185 }
   2186 
   2187 void GLES2Implementation::ReadPixels(
   2188     GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
   2189     GLenum type, void* pixels) {
   2190   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2191   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
   2192       << xoffset << ", " << yoffset << ", "
   2193       << width << ", " << height << ", "
   2194       << GLES2Util::GetStringReadPixelFormat(format) << ", "
   2195       << GLES2Util::GetStringPixelType(type) << ", "
   2196       << static_cast<const void*>(pixels) << ")");
   2197   if (width < 0 || height < 0) {
   2198     SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
   2199     return;
   2200   }
   2201   if (width == 0 || height == 0) {
   2202     return;
   2203   }
   2204 
   2205   // glReadPixel pads the size of each row of pixels by an amount specified by
   2206   // glPixelStorei. So, we have to take that into account both in the fact that
   2207   // the pixels returned from the ReadPixel command will include that padding
   2208   // and that when we copy the results to the user's buffer we need to not
   2209   // write those padding bytes but leave them as they are.
   2210 
   2211   TRACE_EVENT0("gpu", "GLES2::ReadPixels");
   2212   typedef cmds::ReadPixels::Result Result;
   2213 
   2214   int8* dest = reinterpret_cast<int8*>(pixels);
   2215   uint32 temp_size;
   2216   uint32 unpadded_row_size;
   2217   uint32 padded_row_size;
   2218   if (!GLES2Util::ComputeImageDataSizes(
   2219       width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size,
   2220       &padded_row_size)) {
   2221     SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large.");
   2222     return;
   2223   }
   2224 
   2225   if (bound_pixel_pack_transfer_buffer_id_) {
   2226     GLuint offset = ToGLuint(pixels);
   2227     BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   2228         bound_pixel_pack_transfer_buffer_id_,
   2229         "glReadPixels", offset, padded_row_size * height);
   2230     if (buffer && buffer->shm_id() != -1) {
   2231       helper_->ReadPixels(xoffset, yoffset, width, height, format, type,
   2232                           buffer->shm_id(), buffer->shm_offset(),
   2233                           0, 0, true);
   2234       CheckGLError();
   2235     }
   2236     return;
   2237   }
   2238 
   2239   if (!pixels) {
   2240     SetGLError(GL_INVALID_OPERATION, "glReadPixels", "pixels = NULL");
   2241     return;
   2242   }
   2243 
   2244   // Transfer by rows.
   2245   // The max rows we can transfer.
   2246   while (height) {
   2247     GLsizei desired_size = padded_row_size * height - 1 + unpadded_row_size;
   2248     ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_);
   2249     if (!buffer.valid()) {
   2250       return;
   2251     }
   2252     GLint num_rows = ComputeNumRowsThatFitInBuffer(
   2253         padded_row_size, unpadded_row_size, buffer.size());
   2254     num_rows = std::min(num_rows, height);
   2255     // NOTE: We must look up the address of the result area AFTER allocation
   2256     // of the transfer buffer since the transfer buffer may be reallocated.
   2257     Result* result = GetResultAs<Result*>();
   2258     if (!result) {
   2259       return;
   2260     }
   2261     *result = 0;  // mark as failed.
   2262     helper_->ReadPixels(
   2263         xoffset, yoffset, width, num_rows, format, type,
   2264         buffer.shm_id(), buffer.offset(),
   2265         GetResultShmId(), GetResultShmOffset(),
   2266         false);
   2267     WaitForCmd();
   2268     if (*result != 0) {
   2269       // when doing a y-flip we have to iterate through top-to-bottom chunks
   2270       // of the dst. The service side handles reversing the rows within a
   2271       // chunk.
   2272       int8* rows_dst;
   2273       if (pack_reverse_row_order_) {
   2274           rows_dst = dest + (height - num_rows) * padded_row_size;
   2275       } else {
   2276           rows_dst = dest;
   2277       }
   2278       // We have to copy 1 row at a time to avoid writing pad bytes.
   2279       const int8* src = static_cast<const int8*>(buffer.address());
   2280       for (GLint yy = 0; yy < num_rows; ++yy) {
   2281         memcpy(rows_dst, src, unpadded_row_size);
   2282         rows_dst += padded_row_size;
   2283         src += padded_row_size;
   2284       }
   2285       if (!pack_reverse_row_order_) {
   2286         dest = rows_dst;
   2287       }
   2288     }
   2289     // If it was not marked as successful exit.
   2290     if (*result == 0) {
   2291       return;
   2292     }
   2293     yoffset += num_rows;
   2294     height -= num_rows;
   2295   }
   2296   CheckGLError();
   2297 }
   2298 
   2299 void GLES2Implementation::ActiveTexture(GLenum texture) {
   2300   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2301   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
   2302       << GLES2Util::GetStringEnum(texture) << ")");
   2303   GLuint texture_index = texture - GL_TEXTURE0;
   2304   if (texture_index >= static_cast<GLuint>(
   2305       static_state_.int_state.max_combined_texture_image_units)) {
   2306     SetGLErrorInvalidEnum(
   2307         "glActiveTexture", texture, "texture");
   2308     return;
   2309   }
   2310 
   2311   active_texture_unit_ = texture_index;
   2312   helper_->ActiveTexture(texture);
   2313   CheckGLError();
   2314 }
   2315 
   2316 void GLES2Implementation::GenBuffersHelper(
   2317     GLsizei /* n */, const GLuint* /* buffers */) {
   2318 }
   2319 
   2320 void GLES2Implementation::GenFramebuffersHelper(
   2321     GLsizei /* n */, const GLuint* /* framebuffers */) {
   2322 }
   2323 
   2324 void GLES2Implementation::GenRenderbuffersHelper(
   2325     GLsizei /* n */, const GLuint* /* renderbuffers */) {
   2326 }
   2327 
   2328 void GLES2Implementation::GenTexturesHelper(
   2329     GLsizei /* n */, const GLuint* /* textures */) {
   2330 }
   2331 
   2332 void GLES2Implementation::GenVertexArraysOESHelper(
   2333     GLsizei n, const GLuint* arrays) {
   2334   vertex_array_object_manager_->GenVertexArrays(n, arrays);
   2335 }
   2336 
   2337 void GLES2Implementation::GenQueriesEXTHelper(
   2338     GLsizei /* n */, const GLuint* /* queries */) {
   2339 }
   2340 
   2341 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
   2342 // generates a new resource. On newer versions of OpenGL they don't. The code
   2343 // related to binding below will need to change if we switch to the new OpenGL
   2344 // model. Specifically it assumes a bind will succeed which is always true in
   2345 // the old model but possibly not true in the new model if another context has
   2346 // deleted the resource.
   2347 
   2348 bool GLES2Implementation::BindBufferHelper(
   2349     GLenum target, GLuint buffer) {
   2350   // TODO(gman): See note #1 above.
   2351   bool changed = false;
   2352   switch (target) {
   2353     case GL_ARRAY_BUFFER:
   2354       if (bound_array_buffer_id_ != buffer) {
   2355         bound_array_buffer_id_ = buffer;
   2356         changed = true;
   2357       }
   2358       break;
   2359     case GL_ELEMENT_ARRAY_BUFFER:
   2360       changed = vertex_array_object_manager_->BindElementArray(buffer);
   2361       break;
   2362     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
   2363       bound_pixel_pack_transfer_buffer_id_ = buffer;
   2364       break;
   2365     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
   2366       bound_pixel_unpack_transfer_buffer_id_ = buffer;
   2367       break;
   2368     default:
   2369       changed = true;
   2370       break;
   2371   }
   2372   // TODO(gman): There's a bug here. If the target is invalid the ID will not be
   2373   // used even though it's marked it as used here.
   2374   GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer);
   2375   return changed;
   2376 }
   2377 
   2378 bool GLES2Implementation::BindFramebufferHelper(
   2379     GLenum target, GLuint framebuffer) {
   2380   // TODO(gman): See note #1 above.
   2381   bool changed = false;
   2382   switch (target) {
   2383     case GL_FRAMEBUFFER:
   2384       if (bound_framebuffer_ != framebuffer ||
   2385           bound_read_framebuffer_ != framebuffer) {
   2386         bound_framebuffer_ = framebuffer;
   2387         bound_read_framebuffer_ = framebuffer;
   2388         changed = true;
   2389       }
   2390       break;
   2391     case GL_READ_FRAMEBUFFER:
   2392       if (!IsChromiumFramebufferMultisampleAvailable()) {
   2393         SetGLErrorInvalidEnum("glBindFramebuffer", target, "target");
   2394         return false;
   2395       }
   2396       if (bound_read_framebuffer_ != framebuffer) {
   2397         bound_read_framebuffer_ = framebuffer;
   2398         changed = true;
   2399       }
   2400       break;
   2401     case GL_DRAW_FRAMEBUFFER:
   2402       if (!IsChromiumFramebufferMultisampleAvailable()) {
   2403         SetGLErrorInvalidEnum("glBindFramebuffer", target, "target");
   2404         return false;
   2405       }
   2406       if (bound_framebuffer_ != framebuffer) {
   2407         bound_framebuffer_ = framebuffer;
   2408         changed = true;
   2409       }
   2410       break;
   2411     default:
   2412       SetGLErrorInvalidEnum("glBindFramebuffer", target, "target");
   2413       return false;
   2414   }
   2415   GetIdHandler(id_namespaces::kFramebuffers)->MarkAsUsedForBind(framebuffer);
   2416   return changed;
   2417 }
   2418 
   2419 bool GLES2Implementation::BindRenderbufferHelper(
   2420     GLenum target, GLuint renderbuffer) {
   2421   // TODO(gman): See note #1 above.
   2422   bool changed = false;
   2423   switch (target) {
   2424     case GL_RENDERBUFFER:
   2425       if (bound_renderbuffer_ != renderbuffer) {
   2426         bound_renderbuffer_ = renderbuffer;
   2427         changed = true;
   2428       }
   2429       break;
   2430     default:
   2431       changed = true;
   2432       break;
   2433   }
   2434   // TODO(gman): There's a bug here. If the target is invalid the ID will not be
   2435   // used even though it's marked it as used here.
   2436   GetIdHandler(id_namespaces::kRenderbuffers)->MarkAsUsedForBind(renderbuffer);
   2437   return changed;
   2438 }
   2439 
   2440 bool GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) {
   2441   // TODO(gman): See note #1 above.
   2442   // TODO(gman): Change this to false once we figure out why it's failing
   2443   //     on daisy.
   2444   bool changed = true;
   2445   TextureUnit& unit = texture_units_[active_texture_unit_];
   2446   switch (target) {
   2447     case GL_TEXTURE_2D:
   2448       if (unit.bound_texture_2d != texture) {
   2449         unit.bound_texture_2d = texture;
   2450         changed = true;
   2451       }
   2452       break;
   2453     case GL_TEXTURE_CUBE_MAP:
   2454       if (unit.bound_texture_cube_map != texture) {
   2455         unit.bound_texture_cube_map = texture;
   2456         changed = true;
   2457       }
   2458       break;
   2459     default:
   2460       changed = true;
   2461       break;
   2462   }
   2463   // TODO(gman): There's a bug here. If the target is invalid the ID will not be
   2464   // used. even though it's marked it as used here.
   2465   GetIdHandler(id_namespaces::kTextures)->MarkAsUsedForBind(texture);
   2466   return changed;
   2467 }
   2468 
   2469 bool GLES2Implementation::BindVertexArrayHelper(GLuint array) {
   2470   // TODO(gman): See note #1 above.
   2471   bool changed = false;
   2472   if (!vertex_array_object_manager_->BindVertexArray(array, &changed)) {
   2473     SetGLError(
   2474         GL_INVALID_OPERATION, "glBindVertexArrayOES",
   2475         "id was not generated with glGenVertexArrayOES");
   2476   }
   2477   // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
   2478   // because unlike other resources VertexArrayObject ids must
   2479   // be generated by GenVertexArrays. A random id to Bind will not
   2480   // generate a new object.
   2481   return changed;
   2482 }
   2483 
   2484 bool GLES2Implementation::IsBufferReservedId(GLuint id) {
   2485   return vertex_array_object_manager_->IsReservedId(id);
   2486 }
   2487 
   2488 void GLES2Implementation::DeleteBuffersHelper(
   2489     GLsizei n, const GLuint* buffers) {
   2490   if (!GetIdHandler(id_namespaces::kBuffers)->FreeIds(
   2491       this, n, buffers, &GLES2Implementation::DeleteBuffersStub)) {
   2492     SetGLError(
   2493         GL_INVALID_VALUE,
   2494         "glDeleteBuffers", "id not created by this context.");
   2495     return;
   2496   }
   2497   for (GLsizei ii = 0; ii < n; ++ii) {
   2498     if (buffers[ii] == bound_array_buffer_id_) {
   2499       bound_array_buffer_id_ = 0;
   2500     }
   2501     vertex_array_object_manager_->UnbindBuffer(buffers[ii]);
   2502     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]);
   2503     if (buffer) {
   2504       // Free buffer memory, pending the passage of a token.
   2505       buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken());
   2506       // Remove buffer.
   2507       buffer_tracker_->RemoveBuffer(buffers[ii]);
   2508     }
   2509     if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
   2510       bound_pixel_unpack_transfer_buffer_id_ = 0;
   2511     }
   2512   }
   2513 }
   2514 
   2515 void GLES2Implementation::DeleteBuffersStub(
   2516     GLsizei n, const GLuint* buffers) {
   2517   helper_->DeleteBuffersImmediate(n, buffers);
   2518 }
   2519 
   2520 
   2521 void GLES2Implementation::DeleteFramebuffersHelper(
   2522     GLsizei n, const GLuint* framebuffers) {
   2523   if (!GetIdHandler(id_namespaces::kFramebuffers)->FreeIds(
   2524       this, n, framebuffers, &GLES2Implementation::DeleteFramebuffersStub)) {
   2525     SetGLError(
   2526         GL_INVALID_VALUE,
   2527         "glDeleteFramebuffers", "id not created by this context.");
   2528     return;
   2529   }
   2530   for (GLsizei ii = 0; ii < n; ++ii) {
   2531     if (framebuffers[ii] == bound_framebuffer_) {
   2532       bound_framebuffer_ = 0;
   2533     }
   2534     if (framebuffers[ii] == bound_read_framebuffer_) {
   2535       bound_read_framebuffer_ = 0;
   2536     }
   2537   }
   2538 }
   2539 
   2540 void GLES2Implementation::DeleteFramebuffersStub(
   2541     GLsizei n, const GLuint* framebuffers) {
   2542   helper_->DeleteFramebuffersImmediate(n, framebuffers);
   2543 }
   2544 
   2545 void GLES2Implementation::DeleteRenderbuffersHelper(
   2546     GLsizei n, const GLuint* renderbuffers) {
   2547   if (!GetIdHandler(id_namespaces::kRenderbuffers)->FreeIds(
   2548       this, n, renderbuffers, &GLES2Implementation::DeleteRenderbuffersStub)) {
   2549     SetGLError(
   2550         GL_INVALID_VALUE,
   2551         "glDeleteRenderbuffers", "id not created by this context.");
   2552     return;
   2553   }
   2554   for (GLsizei ii = 0; ii < n; ++ii) {
   2555     if (renderbuffers[ii] == bound_renderbuffer_) {
   2556       bound_renderbuffer_ = 0;
   2557     }
   2558   }
   2559 }
   2560 
   2561 void GLES2Implementation::DeleteRenderbuffersStub(
   2562     GLsizei n, const GLuint* renderbuffers) {
   2563   helper_->DeleteRenderbuffersImmediate(n, renderbuffers);
   2564 }
   2565 
   2566 void GLES2Implementation::DeleteTexturesHelper(
   2567     GLsizei n, const GLuint* textures) {
   2568   if (!GetIdHandler(id_namespaces::kTextures)->FreeIds(
   2569       this, n, textures, &GLES2Implementation::DeleteTexturesStub)) {
   2570     SetGLError(
   2571         GL_INVALID_VALUE,
   2572         "glDeleteTextures", "id not created by this context.");
   2573     return;
   2574   }
   2575   for (GLsizei ii = 0; ii < n; ++ii) {
   2576     for (GLint tt = 0;
   2577          tt < static_state_.int_state.max_combined_texture_image_units;
   2578          ++tt) {
   2579       TextureUnit& unit = texture_units_[tt];
   2580       if (textures[ii] == unit.bound_texture_2d) {
   2581         unit.bound_texture_2d = 0;
   2582       }
   2583       if (textures[ii] == unit.bound_texture_cube_map) {
   2584         unit.bound_texture_cube_map = 0;
   2585       }
   2586     }
   2587   }
   2588 }
   2589 
   2590 void GLES2Implementation::DeleteVertexArraysOESHelper(
   2591     GLsizei n, const GLuint* arrays) {
   2592   vertex_array_object_manager_->DeleteVertexArrays(n, arrays);
   2593   if (!GetIdHandler(id_namespaces::kVertexArrays)->FreeIds(
   2594       this, n, arrays, &GLES2Implementation::DeleteVertexArraysOESStub)) {
   2595     SetGLError(
   2596         GL_INVALID_VALUE,
   2597         "glDeleteVertexArraysOES", "id not created by this context.");
   2598     return;
   2599   }
   2600 }
   2601 
   2602 void GLES2Implementation::DeleteVertexArraysOESStub(
   2603     GLsizei n, const GLuint* arrays) {
   2604   helper_->DeleteVertexArraysOESImmediate(n, arrays);
   2605 }
   2606 
   2607 void GLES2Implementation::DeleteTexturesStub(
   2608     GLsizei n, const GLuint* textures) {
   2609   helper_->DeleteTexturesImmediate(n, textures);
   2610 }
   2611 
   2612 void GLES2Implementation::DisableVertexAttribArray(GLuint index) {
   2613   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2614   GPU_CLIENT_LOG(
   2615       "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index << ")");
   2616   vertex_array_object_manager_->SetAttribEnable(index, false);
   2617   helper_->DisableVertexAttribArray(index);
   2618   CheckGLError();
   2619 }
   2620 
   2621 void GLES2Implementation::EnableVertexAttribArray(GLuint index) {
   2622   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2623   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
   2624       << index << ")");
   2625   vertex_array_object_manager_->SetAttribEnable(index, true);
   2626   helper_->EnableVertexAttribArray(index);
   2627   CheckGLError();
   2628 }
   2629 
   2630 void GLES2Implementation::DrawArrays(GLenum mode, GLint first, GLsizei count) {
   2631   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2632   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
   2633       << GLES2Util::GetStringDrawMode(mode) << ", "
   2634       << first << ", " << count << ")");
   2635   if (count < 0) {
   2636     SetGLError(GL_INVALID_VALUE, "glDrawArrays", "count < 0");
   2637     return;
   2638   }
   2639   bool simulated = false;
   2640   if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers(
   2641       "glDrawArrays", this, helper_, first + count, 0, &simulated)) {
   2642     return;
   2643   }
   2644   helper_->DrawArrays(mode, first, count);
   2645   RestoreArrayBuffer(simulated);
   2646   CheckGLError();
   2647 }
   2648 
   2649 void GLES2Implementation::GetVertexAttribfv(
   2650     GLuint index, GLenum pname, GLfloat* params) {
   2651   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2652   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
   2653       << index << ", "
   2654       << GLES2Util::GetStringVertexAttribute(pname) << ", "
   2655       << static_cast<const void*>(params) << ")");
   2656   uint32 value = 0;
   2657   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
   2658     *params = static_cast<float>(value);
   2659     return;
   2660   }
   2661   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
   2662   typedef cmds::GetVertexAttribfv::Result Result;
   2663   Result* result = GetResultAs<Result*>();
   2664   if (!result) {
   2665     return;
   2666   }
   2667   result->SetNumResults(0);
   2668   helper_->GetVertexAttribfv(
   2669       index, pname, GetResultShmId(), GetResultShmOffset());
   2670   WaitForCmd();
   2671   result->CopyResult(params);
   2672   GPU_CLIENT_LOG_CODE_BLOCK({
   2673     for (int32 i = 0; i < result->GetNumResults(); ++i) {
   2674       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
   2675     }
   2676   });
   2677   CheckGLError();
   2678 }
   2679 
   2680 void GLES2Implementation::GetVertexAttribiv(
   2681     GLuint index, GLenum pname, GLint* params) {
   2682   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2683   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
   2684       << index << ", "
   2685       << GLES2Util::GetStringVertexAttribute(pname) << ", "
   2686       << static_cast<const void*>(params) << ")");
   2687   uint32 value = 0;
   2688   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
   2689     *params = value;
   2690     return;
   2691   }
   2692   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
   2693   typedef cmds::GetVertexAttribiv::Result Result;
   2694   Result* result = GetResultAs<Result*>();
   2695   if (!result) {
   2696     return;
   2697   }
   2698   result->SetNumResults(0);
   2699   helper_->GetVertexAttribiv(
   2700       index, pname, GetResultShmId(), GetResultShmOffset());
   2701   WaitForCmd();
   2702   result->CopyResult(params);
   2703   GPU_CLIENT_LOG_CODE_BLOCK({
   2704     for (int32 i = 0; i < result->GetNumResults(); ++i) {
   2705       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
   2706     }
   2707   });
   2708   CheckGLError();
   2709 }
   2710 
   2711 GLboolean GLES2Implementation::EnableFeatureCHROMIUM(
   2712     const char* feature) {
   2713   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2714   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
   2715                  << feature << ")");
   2716   TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
   2717   typedef cmds::EnableFeatureCHROMIUM::Result Result;
   2718   Result* result = GetResultAs<Result*>();
   2719   if (!result) {
   2720     return false;
   2721   }
   2722   *result = 0;
   2723   SetBucketAsCString(kResultBucketId, feature);
   2724   helper_->EnableFeatureCHROMIUM(
   2725       kResultBucketId, GetResultShmId(), GetResultShmOffset());
   2726   WaitForCmd();
   2727   helper_->SetBucketSize(kResultBucketId, 0);
   2728   GPU_CLIENT_LOG("   returned " << GLES2Util::GetStringBool(*result));
   2729   return *result;
   2730 }
   2731 
   2732 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
   2733     GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) {
   2734   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2735   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
   2736       << target << ", " << offset << ", " << size << ", "
   2737       << GLES2Util::GetStringEnum(access) << ")");
   2738   // NOTE: target is NOT checked because the service will check it
   2739   // and we don't know what targets are valid.
   2740   if (access != GL_WRITE_ONLY) {
   2741     SetGLErrorInvalidEnum(
   2742         "glMapBufferSubDataCHROMIUM", access, "access");
   2743     return NULL;
   2744   }
   2745   if (offset < 0 || size < 0) {
   2746     SetGLError(GL_INVALID_VALUE, "glMapBufferSubDataCHROMIUM", "bad range");
   2747     return NULL;
   2748   }
   2749   int32 shm_id;
   2750   unsigned int shm_offset;
   2751   void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
   2752   if (!mem) {
   2753     SetGLError(GL_OUT_OF_MEMORY, "glMapBufferSubDataCHROMIUM", "out of memory");
   2754     return NULL;
   2755   }
   2756 
   2757   std::pair<MappedBufferMap::iterator, bool> result =
   2758      mapped_buffers_.insert(std::make_pair(
   2759          mem,
   2760          MappedBuffer(
   2761              access, shm_id, mem, shm_offset, target, offset, size)));
   2762   GPU_DCHECK(result.second);
   2763   GPU_CLIENT_LOG("  returned " << mem);
   2764   return mem;
   2765 }
   2766 
   2767 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem) {
   2768   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2769   GPU_CLIENT_LOG(
   2770       "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem << ")");
   2771   MappedBufferMap::iterator it = mapped_buffers_.find(mem);
   2772   if (it == mapped_buffers_.end()) {
   2773     SetGLError(
   2774         GL_INVALID_VALUE, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
   2775     return;
   2776   }
   2777   const MappedBuffer& mb = it->second;
   2778   helper_->BufferSubData(
   2779       mb.target, mb.offset, mb.size, mb.shm_id, mb.shm_offset);
   2780   mapped_memory_->FreePendingToken(mb.shm_memory, helper_->InsertToken());
   2781   mapped_buffers_.erase(it);
   2782   CheckGLError();
   2783 }
   2784 
   2785 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
   2786      GLenum target,
   2787      GLint level,
   2788      GLint xoffset,
   2789      GLint yoffset,
   2790      GLsizei width,
   2791      GLsizei height,
   2792      GLenum format,
   2793      GLenum type,
   2794      GLenum access) {
   2795   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2796   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
   2797       << target << ", " << level << ", "
   2798       << xoffset << ", " << yoffset << ", "
   2799       << width << ", " << height << ", "
   2800       << GLES2Util::GetStringTextureFormat(format) << ", "
   2801       << GLES2Util::GetStringPixelType(type) << ", "
   2802       << GLES2Util::GetStringEnum(access) << ")");
   2803   if (access != GL_WRITE_ONLY) {
   2804     SetGLErrorInvalidEnum(
   2805         "glMapTexSubImage2DCHROMIUM", access, "access");
   2806     return NULL;
   2807   }
   2808   // NOTE: target is NOT checked because the service will check it
   2809   // and we don't know what targets are valid.
   2810   if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) {
   2811     SetGLError(
   2812         GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
   2813     return NULL;
   2814   }
   2815   uint32 size;
   2816   if (!GLES2Util::ComputeImageDataSizes(
   2817       width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
   2818     SetGLError(
   2819         GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM", "image size too large");
   2820     return NULL;
   2821   }
   2822   int32 shm_id;
   2823   unsigned int shm_offset;
   2824   void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
   2825   if (!mem) {
   2826     SetGLError(GL_OUT_OF_MEMORY, "glMapTexSubImage2DCHROMIUM", "out of memory");
   2827     return NULL;
   2828   }
   2829 
   2830   std::pair<MappedTextureMap::iterator, bool> result =
   2831      mapped_textures_.insert(std::make_pair(
   2832          mem,
   2833          MappedTexture(
   2834              access, shm_id, mem, shm_offset,
   2835              target, level, xoffset, yoffset, width, height, format, type)));
   2836   GPU_DCHECK(result.second);
   2837   GPU_CLIENT_LOG("  returned " << mem);
   2838   return mem;
   2839 }
   2840 
   2841 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem) {
   2842   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2843   GPU_CLIENT_LOG(
   2844       "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem << ")");
   2845   MappedTextureMap::iterator it = mapped_textures_.find(mem);
   2846   if (it == mapped_textures_.end()) {
   2847     SetGLError(
   2848         GL_INVALID_VALUE, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
   2849     return;
   2850   }
   2851   const MappedTexture& mt = it->second;
   2852   helper_->TexSubImage2D(
   2853       mt.target, mt.level, mt.xoffset, mt.yoffset, mt.width, mt.height,
   2854       mt.format, mt.type, mt.shm_id, mt.shm_offset, GL_FALSE);
   2855   mapped_memory_->FreePendingToken(mt.shm_memory, helper_->InsertToken());
   2856   mapped_textures_.erase(it);
   2857   CheckGLError();
   2858 }
   2859 
   2860 void GLES2Implementation::ResizeCHROMIUM(GLuint width, GLuint height,
   2861                                          float scale_factor) {
   2862   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2863   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
   2864                  << width << ", " << height << ", " << scale_factor << ")");
   2865   helper_->ResizeCHROMIUM(width, height, scale_factor);
   2866   CheckGLError();
   2867 }
   2868 
   2869 const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
   2870   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2871   GPU_CLIENT_LOG("[" << GetLogPrefix()
   2872       << "] glGetRequestableExtensionsCHROMIUM()");
   2873   TRACE_EVENT0("gpu",
   2874                "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
   2875   const char* result = NULL;
   2876   // Clear the bucket so if the command fails nothing will be in it.
   2877   helper_->SetBucketSize(kResultBucketId, 0);
   2878   helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId);
   2879   std::string str;
   2880   if (GetBucketAsString(kResultBucketId, &str)) {
   2881     // The set of requestable extensions shrinks as we enable
   2882     // them. Because we don't know when the client will stop referring
   2883     // to a previous one it queries (see GetString) we need to cache
   2884     // the unique results.
   2885     std::set<std::string>::const_iterator sit =
   2886         requestable_extensions_set_.find(str);
   2887     if (sit != requestable_extensions_set_.end()) {
   2888       result = sit->c_str();
   2889     } else {
   2890       std::pair<std::set<std::string>::const_iterator, bool> insert_result =
   2891           requestable_extensions_set_.insert(str);
   2892       GPU_DCHECK(insert_result.second);
   2893       result = insert_result.first->c_str();
   2894     }
   2895   }
   2896   GPU_CLIENT_LOG("  returned " << result);
   2897   return reinterpret_cast<const GLchar*>(result);
   2898 }
   2899 
   2900 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
   2901 // with VirtualGL contexts.
   2902 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) {
   2903   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2904   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
   2905                  << extension << ")");
   2906   SetBucketAsCString(kResultBucketId, extension);
   2907   helper_->RequestExtensionCHROMIUM(kResultBucketId);
   2908   helper_->SetBucketSize(kResultBucketId, 0);
   2909 
   2910   struct ExtensionCheck {
   2911     const char* extension;
   2912     ExtensionStatus* status;
   2913   };
   2914   const ExtensionCheck checks[] = {
   2915     {
   2916       "GL_ANGLE_pack_reverse_row_order",
   2917       &angle_pack_reverse_row_order_status_,
   2918     },
   2919     {
   2920       "GL_CHROMIUM_framebuffer_multisample",
   2921        &chromium_framebuffer_multisample_,
   2922     },
   2923   };
   2924   const size_t kNumChecks = sizeof(checks)/sizeof(checks[0]);
   2925   for (size_t ii = 0; ii < kNumChecks; ++ii) {
   2926     const ExtensionCheck& check = checks[ii];
   2927     if (*check.status == kUnavailableExtensionStatus &&
   2928         !strcmp(extension, check.extension)) {
   2929       *check.status = kUnknownExtensionStatus;
   2930     }
   2931   }
   2932 }
   2933 
   2934 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
   2935   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2936   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
   2937   // Wait if this would add too many rate limit tokens.
   2938   if (rate_limit_tokens_.size() == kMaxSwapBuffers) {
   2939     helper_->WaitForToken(rate_limit_tokens_.front());
   2940     rate_limit_tokens_.pop();
   2941   }
   2942   rate_limit_tokens_.push(helper_->InsertToken());
   2943 }
   2944 
   2945 void GLES2Implementation::GetMultipleIntegervCHROMIUM(
   2946     const GLenum* pnames, GLuint count, GLint* results, GLsizeiptr size) {
   2947   GPU_CLIENT_SINGLE_THREAD_CHECK();
   2948   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMultipleIntegervCHROMIUM("
   2949                  << static_cast<const void*>(pnames) << ", "
   2950                  << count << ", " << results << ", "
   2951                  << size << ")");
   2952   GPU_CLIENT_LOG_CODE_BLOCK({
   2953     for (GLuint i = 0; i < count; ++i) {
   2954       GPU_CLIENT_LOG(
   2955           "  " << i << ": " << GLES2Util::GetStringGLState(pnames[i]));
   2956     }
   2957   });
   2958 
   2959   GetMultipleIntegervState state(pnames, count, results, size);
   2960   if (!GetMultipleIntegervSetup(&state)) {
   2961     return;
   2962   }
   2963   state.buffer = transfer_buffer_->Alloc(state.transfer_buffer_size_needed);
   2964   if (!state.buffer) {
   2965     SetGLError(GL_OUT_OF_MEMORY, "glGetMultipleIntegervCHROMIUM",
   2966                "Transfer buffer allocation failed.");
   2967     return;
   2968   }
   2969   GetMultipleIntegervRequest(&state);
   2970   WaitForCmd();
   2971   GetMultipleIntegervOnCompleted(&state);
   2972 
   2973   GPU_CLIENT_LOG("  returned");
   2974   GPU_CLIENT_LOG_CODE_BLOCK({
   2975     for (int i = 0; i < state.num_results; ++i) {
   2976       GPU_CLIENT_LOG("  " << i << ": " << (results[i]));
   2977     }
   2978   });
   2979 
   2980   // TODO(gman): We should be able to free without a token.
   2981   transfer_buffer_->FreePendingToken(state.buffer, helper_->InsertToken());
   2982   CheckGLError();
   2983 }
   2984 
   2985 bool GLES2Implementation::GetMultipleIntegervSetup(
   2986     GetMultipleIntegervState* state) {
   2987   state->num_results = 0;
   2988   for (GLuint ii = 0; ii < state->pnames_count; ++ii) {
   2989     int num = util_.GLGetNumValuesReturned(state->pnames[ii]);
   2990     if (!num) {
   2991       SetGLErrorInvalidEnum(
   2992           "glGetMultipleIntegervCHROMIUM", state->pnames[ii], "pname");
   2993       return false;
   2994     }
   2995     state->num_results += num;
   2996   }
   2997   if (static_cast<size_t>(state->results_size) !=
   2998       state->num_results * sizeof(GLint)) {
   2999     SetGLError(GL_INVALID_VALUE, "glGetMultipleIntegervCHROMIUM", "bad size");
   3000     return false;
   3001   }
   3002   for (int ii = 0; ii < state->num_results; ++ii) {
   3003     if (state->results[ii] != 0) {
   3004       SetGLError(GL_INVALID_VALUE,
   3005                  "glGetMultipleIntegervCHROMIUM", "results not set to zero.");
   3006       return false;
   3007     }
   3008   }
   3009   state->transfer_buffer_size_needed =
   3010       state->pnames_count * sizeof(state->pnames[0]) +
   3011       state->num_results * sizeof(state->results[0]);
   3012   return true;
   3013 }
   3014 
   3015 void GLES2Implementation::GetMultipleIntegervRequest(
   3016     GetMultipleIntegervState* state) {
   3017   GLenum* pnames_buffer = static_cast<GLenum*>(state->buffer);
   3018   state->results_buffer = pnames_buffer + state->pnames_count;
   3019   memcpy(pnames_buffer, state->pnames, state->pnames_count * sizeof(GLenum));
   3020   memset(state->results_buffer, 0, state->num_results * sizeof(GLint));
   3021   helper_->GetMultipleIntegervCHROMIUM(
   3022       transfer_buffer_->GetShmId(),
   3023       transfer_buffer_->GetOffset(pnames_buffer),
   3024       state->pnames_count,
   3025       transfer_buffer_->GetShmId(),
   3026       transfer_buffer_->GetOffset(state->results_buffer),
   3027       state->results_size);
   3028 }
   3029 
   3030 void GLES2Implementation::GetMultipleIntegervOnCompleted(
   3031     GetMultipleIntegervState* state) {
   3032   memcpy(state->results, state->results_buffer, state->results_size);;
   3033 }
   3034 
   3035 void GLES2Implementation::GetAllShaderPrecisionFormatsSetup(
   3036     GetAllShaderPrecisionFormatsState* state) {
   3037   state->transfer_buffer_size_needed =
   3038       state->precision_params_count *
   3039       sizeof(cmds::GetShaderPrecisionFormat::Result);
   3040 }
   3041 
   3042 void GLES2Implementation::GetAllShaderPrecisionFormatsRequest(
   3043     GetAllShaderPrecisionFormatsState* state) {
   3044   typedef cmds::GetShaderPrecisionFormat::Result Result;
   3045   Result* result = static_cast<Result*>(state->results_buffer);
   3046 
   3047   for (int i = 0; i < state->precision_params_count; i++) {
   3048     result->success = false;
   3049     helper_->GetShaderPrecisionFormat(state->precision_params[i][0],
   3050                                       state->precision_params[i][1],
   3051                                       transfer_buffer_->GetShmId(),
   3052                                       transfer_buffer_->GetOffset(result));
   3053     result++;
   3054   }
   3055 }
   3056 
   3057 void GLES2Implementation::GetAllShaderPrecisionFormatsOnCompleted(
   3058     GetAllShaderPrecisionFormatsState* state) {
   3059   typedef cmds::GetShaderPrecisionFormat::Result Result;
   3060   Result* result = static_cast<Result*>(state->results_buffer);
   3061 
   3062   for (int i = 0; i < state->precision_params_count; i++) {
   3063     if (result->success) {
   3064       const GLStaticState::ShaderPrecisionKey key(
   3065         state->precision_params[i][0], state->precision_params[i][1]);
   3066       static_state_.shader_precisions[key] = *result;
   3067     }
   3068     result++;
   3069   }
   3070 }
   3071 
   3072 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
   3073     GLuint program, std::vector<int8>* result) {
   3074   GPU_DCHECK(result);
   3075   // Clear the bucket so if the command fails nothing will be in it.
   3076   helper_->SetBucketSize(kResultBucketId, 0);
   3077   helper_->GetProgramInfoCHROMIUM(program, kResultBucketId);
   3078   GetBucketContents(kResultBucketId, result);
   3079 }
   3080 
   3081 void GLES2Implementation::GetProgramInfoCHROMIUM(
   3082     GLuint program, GLsizei bufsize, GLsizei* size, void* info) {
   3083   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3084   if (bufsize < 0) {
   3085     SetGLError(
   3086         GL_INVALID_VALUE, "glProgramInfoCHROMIUM", "bufsize less than 0.");
   3087     return;
   3088   }
   3089   if (size == NULL) {
   3090     SetGLError(GL_INVALID_VALUE, "glProgramInfoCHROMIUM", "size is null.");
   3091     return;
   3092   }
   3093   // Make sure they've set size to 0 else the value will be undefined on
   3094   // lost context.
   3095   GPU_DCHECK(*size == 0);
   3096   std::vector<int8> result;
   3097   GetProgramInfoCHROMIUMHelper(program, &result);
   3098   if (result.empty()) {
   3099     return;
   3100   }
   3101   *size = result.size();
   3102   if (!info) {
   3103     return;
   3104   }
   3105   if (static_cast<size_t>(bufsize) < result.size()) {
   3106     SetGLError(GL_INVALID_OPERATION,
   3107                "glProgramInfoCHROMIUM", "bufsize is too small for result.");
   3108     return;
   3109   }
   3110   memcpy(info, &result[0], result.size());
   3111 }
   3112 
   3113 GLuint GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture) {
   3114   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3115   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
   3116       << texture << ")");
   3117   TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
   3118   typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
   3119   Result* result = GetResultAs<Result*>();
   3120   if (!result) {
   3121     return GL_ZERO;
   3122   }
   3123   *result = GL_ZERO;
   3124 
   3125   helper_->CreateStreamTextureCHROMIUM(texture,
   3126                                        GetResultShmId(),
   3127                                        GetResultShmOffset());
   3128   WaitForCmd();
   3129   GLuint result_value = *result;
   3130   CheckGLError();
   3131   return result_value;
   3132 }
   3133 
   3134 void GLES2Implementation::DestroyStreamTextureCHROMIUM(GLuint texture) {
   3135   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3136   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] DestroyStreamTextureCHROMIUM("
   3137       << texture << ")");
   3138   TRACE_EVENT0("gpu", "GLES2::DestroyStreamTextureCHROMIUM");
   3139   helper_->DestroyStreamTextureCHROMIUM(texture);
   3140   CheckGLError();
   3141 }
   3142 
   3143 void GLES2Implementation::PostSubBufferCHROMIUM(
   3144     GLint x, GLint y, GLint width, GLint height) {
   3145   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3146   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
   3147       << x << ", " << y << ", " << width << ", " << height << ")");
   3148   TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
   3149                "width", width, "height", height);
   3150 
   3151   // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
   3152   swap_buffers_tokens_.push(helper_->InsertToken());
   3153   helper_->PostSubBufferCHROMIUM(x, y, width, height);
   3154   helper_->CommandBufferHelper::Flush();
   3155   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
   3156     helper_->WaitForToken(swap_buffers_tokens_.front());
   3157     swap_buffers_tokens_.pop();
   3158   }
   3159 }
   3160 
   3161 void GLES2Implementation::DeleteQueriesEXTHelper(
   3162     GLsizei n, const GLuint* queries) {
   3163   // TODO(gman): Remove this as queries are not shared resources.
   3164   if (!GetIdHandler(id_namespaces::kQueries)->FreeIds(
   3165       this, n, queries, &GLES2Implementation::DeleteQueriesStub)) {
   3166     SetGLError(
   3167         GL_INVALID_VALUE,
   3168         "glDeleteTextures", "id not created by this context.");
   3169     return;
   3170   }
   3171 
   3172   for (GLsizei ii = 0; ii < n; ++ii)
   3173     query_tracker_->RemoveQuery(queries[ii]);
   3174 
   3175   helper_->DeleteQueriesEXTImmediate(n, queries);
   3176 }
   3177 
   3178 // TODO(gman): Remove this. Queries are not shared resources.
   3179 void GLES2Implementation::DeleteQueriesStub(
   3180     GLsizei /* n */, const GLuint* /* queries */) {
   3181 }
   3182 
   3183 GLboolean GLES2Implementation::IsQueryEXT(GLuint id) {
   3184   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3185   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id << ")");
   3186 
   3187   // TODO(gman): To be spec compliant IDs from other contexts sharing
   3188   // resources need to return true here even though you can't share
   3189   // queries across contexts?
   3190   return query_tracker_->GetQuery(id) != NULL;
   3191 }
   3192 
   3193 void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) {
   3194   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3195   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
   3196                  << GLES2Util::GetStringQueryTarget(target)
   3197                  << ", " << id << ")");
   3198 
   3199   // if any outstanding queries INV_OP
   3200   if (current_query_) {
   3201     SetGLError(
   3202         GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
   3203     return;
   3204   }
   3205 
   3206   // id = 0 INV_OP
   3207   if (id == 0) {
   3208     SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
   3209     return;
   3210   }
   3211 
   3212   // TODO(gman) if id not GENned INV_OPERATION
   3213 
   3214   // if id does not have an object
   3215   QueryTracker::Query* query = query_tracker_->GetQuery(id);
   3216   if (!query) {
   3217     query = query_tracker_->CreateQuery(id, target);
   3218     if (!query) {
   3219       MustBeContextLost();
   3220       return;
   3221     }
   3222   } else if (query->target() != target) {
   3223     SetGLError(
   3224         GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
   3225     return;
   3226   }
   3227 
   3228   current_query_ = query;
   3229 
   3230   query->Begin(this);
   3231   CheckGLError();
   3232 }
   3233 
   3234 void GLES2Implementation::EndQueryEXT(GLenum target) {
   3235   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3236   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
   3237                  << GLES2Util::GetStringQueryTarget(target) << ")");
   3238   // Don't do anything if the context is lost.
   3239   if (helper_->IsContextLost()) {
   3240     return;
   3241   }
   3242 
   3243   if (!current_query_) {
   3244     SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "no active query");
   3245     return;
   3246   }
   3247 
   3248   if (current_query_->target() != target) {
   3249     SetGLError(GL_INVALID_OPERATION,
   3250                "glEndQueryEXT", "target does not match active query");
   3251     return;
   3252   }
   3253 
   3254   current_query_->End(this);
   3255   current_query_ = NULL;
   3256   CheckGLError();
   3257 }
   3258 
   3259 void GLES2Implementation::GetQueryivEXT(
   3260     GLenum target, GLenum pname, GLint* params) {
   3261   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3262   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
   3263                  << GLES2Util::GetStringQueryTarget(target) << ", "
   3264                  << GLES2Util::GetStringQueryParameter(pname) << ", "
   3265                  << static_cast<const void*>(params) << ")");
   3266 
   3267   if (pname != GL_CURRENT_QUERY_EXT) {
   3268     SetGLErrorInvalidEnum("glGetQueryivEXT", pname, "pname");
   3269     return;
   3270   }
   3271   *params = (current_query_ && current_query_->target() == target) ?
   3272       current_query_->id() : 0;
   3273   GPU_CLIENT_LOG("  " << *params);
   3274   CheckGLError();
   3275 }
   3276 
   3277 void GLES2Implementation::GetQueryObjectuivEXT(
   3278     GLuint id, GLenum pname, GLuint* params) {
   3279   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3280   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id << ", "
   3281                  << GLES2Util::GetStringQueryObjectParameter(pname) << ", "
   3282                  << static_cast<const void*>(params) << ")");
   3283 
   3284   QueryTracker::Query* query = query_tracker_->GetQuery(id);
   3285   if (!query) {
   3286     SetGLError(GL_INVALID_OPERATION, "glQueryObjectuivEXT", "unknown query id");
   3287     return;
   3288   }
   3289 
   3290   if (query == current_query_) {
   3291     SetGLError(
   3292         GL_INVALID_OPERATION,
   3293         "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
   3294     return;
   3295   }
   3296 
   3297   if (query->NeverUsed()) {
   3298     SetGLError(
   3299         GL_INVALID_OPERATION,
   3300         "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
   3301     return;
   3302   }
   3303 
   3304   switch (pname) {
   3305     case GL_QUERY_RESULT_EXT:
   3306       if (!query->CheckResultsAvailable(helper_)) {
   3307         helper_->WaitForToken(query->token());
   3308         if (!query->CheckResultsAvailable(helper_)) {
   3309           // TODO(gman): Speed this up.
   3310           WaitForCmd();
   3311           GPU_CHECK(query->CheckResultsAvailable(helper_));
   3312         }
   3313       }
   3314       *params = query->GetResult();
   3315       break;
   3316     case GL_QUERY_RESULT_AVAILABLE_EXT:
   3317       *params = query->CheckResultsAvailable(helper_);
   3318       break;
   3319     default:
   3320       SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname, "pname");
   3321       break;
   3322   }
   3323   GPU_CLIENT_LOG("  " << *params);
   3324   CheckGLError();
   3325 }
   3326 
   3327 void GLES2Implementation::DrawArraysInstancedANGLE(
   3328     GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
   3329   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3330   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
   3331       << GLES2Util::GetStringDrawMode(mode) << ", "
   3332       << first << ", " << count << ", " << primcount << ")");
   3333   if (count < 0) {
   3334     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "count < 0");
   3335     return;
   3336   }
   3337   if (primcount < 0) {
   3338     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "primcount < 0");
   3339     return;
   3340   }
   3341   if (primcount == 0) {
   3342     return;
   3343   }
   3344   bool simulated = false;
   3345   if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers(
   3346       "glDrawArraysInstancedANGLE", this, helper_, first + count, primcount,
   3347       &simulated)) {
   3348     return;
   3349   }
   3350   helper_->DrawArraysInstancedANGLE(mode, first, count, primcount);
   3351   RestoreArrayBuffer(simulated);
   3352   CheckGLError();
   3353 }
   3354 
   3355 void GLES2Implementation::DrawElementsInstancedANGLE(
   3356     GLenum mode, GLsizei count, GLenum type, const void* indices,
   3357     GLsizei primcount) {
   3358   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3359   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
   3360       << GLES2Util::GetStringDrawMode(mode) << ", "
   3361       << count << ", "
   3362       << GLES2Util::GetStringIndexType(type) << ", "
   3363       << static_cast<const void*>(indices) << ", "
   3364       << primcount << ")");
   3365   if (count < 0) {
   3366     SetGLError(GL_INVALID_VALUE,
   3367                "glDrawElementsInstancedANGLE", "count less than 0.");
   3368     return;
   3369   }
   3370   if (count == 0) {
   3371     return;
   3372   }
   3373   if (primcount < 0) {
   3374     SetGLError(GL_INVALID_VALUE,
   3375                "glDrawElementsInstancedANGLE", "primcount < 0");
   3376     return;
   3377   }
   3378   if (primcount == 0) {
   3379     return;
   3380   }
   3381   GLuint offset = 0;
   3382   bool simulated = false;
   3383   if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
   3384       "glDrawElementsInstancedANGLE", this, helper_, count, type, primcount,
   3385       indices, &offset, &simulated)) {
   3386     return;
   3387   }
   3388   helper_->DrawElementsInstancedANGLE(mode, count, type, offset, primcount);
   3389   RestoreElementAndArrayBuffers(simulated);
   3390   CheckGLError();
   3391 }
   3392 
   3393 void GLES2Implementation::GenMailboxCHROMIUM(
   3394     GLbyte* mailbox) {
   3395   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3396   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
   3397       << static_cast<const void*>(mailbox) << ")");
   3398   TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
   3399 
   3400   helper_->GenMailboxCHROMIUM(kResultBucketId);
   3401 
   3402   std::vector<GLbyte> result;
   3403   GetBucketContents(kResultBucketId, &result);
   3404 
   3405   std::copy(result.begin(), result.end(), mailbox);
   3406   CheckGLError();
   3407 }
   3408 
   3409 void GLES2Implementation::PushGroupMarkerEXT(
   3410     GLsizei length, const GLchar* marker) {
   3411   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3412   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
   3413       << length << ", " << marker << ")");
   3414   if (!marker) {
   3415     marker = "";
   3416   }
   3417   SetBucketAsString(
   3418       kResultBucketId,
   3419       (length ? std::string(marker, length) : std::string(marker)));
   3420   helper_->PushGroupMarkerEXT(kResultBucketId);
   3421   helper_->SetBucketSize(kResultBucketId, 0);
   3422   debug_marker_manager_.PushGroup(
   3423       length ? std::string(marker, length) : std::string(marker));
   3424 }
   3425 
   3426 void GLES2Implementation::InsertEventMarkerEXT(
   3427     GLsizei length, const GLchar* marker) {
   3428   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3429   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
   3430       << length << ", " << marker << ")");
   3431   if (!marker) {
   3432     marker = "";
   3433   }
   3434   SetBucketAsString(
   3435       kResultBucketId,
   3436       (length ? std::string(marker, length) : std::string(marker)));
   3437   helper_->InsertEventMarkerEXT(kResultBucketId);
   3438   helper_->SetBucketSize(kResultBucketId, 0);
   3439   debug_marker_manager_.SetMarker(
   3440       length ? std::string(marker, length) : std::string(marker));
   3441 }
   3442 
   3443 void GLES2Implementation::PopGroupMarkerEXT() {
   3444   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3445   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
   3446   helper_->PopGroupMarkerEXT();
   3447   debug_marker_manager_.PopGroup();
   3448 }
   3449 
   3450 void GLES2Implementation::TraceBeginCHROMIUM(const char* name) {
   3451   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3452   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
   3453                  << name << ")");
   3454   if (current_trace_name_.get()) {
   3455     SetGLError(GL_INVALID_OPERATION, "glTraceBeginCHROMIUM",
   3456                "trace already running");
   3457     return;
   3458   }
   3459   TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", name, this);
   3460   SetBucketAsCString(kResultBucketId, name);
   3461   helper_->TraceBeginCHROMIUM(kResultBucketId);
   3462   helper_->SetBucketSize(kResultBucketId, 0);
   3463   current_trace_name_.reset(new std::string(name));
   3464 }
   3465 
   3466 void GLES2Implementation::TraceEndCHROMIUM() {
   3467   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3468   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
   3469   if (!current_trace_name_.get()) {
   3470     SetGLError(GL_INVALID_OPERATION, "glTraceEndCHROMIUM",
   3471                "missing begin trace");
   3472     return;
   3473   }
   3474   helper_->TraceEndCHROMIUM();
   3475   TRACE_EVENT_COPY_ASYNC_END0("gpu", current_trace_name_->c_str(), this);
   3476   current_trace_name_.reset();
   3477 }
   3478 
   3479 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
   3480   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3481   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
   3482       << target << ", " << GLES2Util::GetStringEnum(access) << ")");
   3483   switch (target)  {
   3484     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
   3485       if (access != GL_READ_ONLY) {
   3486         SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
   3487         return NULL;
   3488       }
   3489       break;
   3490     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
   3491       if (access != GL_WRITE_ONLY) {
   3492         SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
   3493         return NULL;
   3494       }
   3495       break;
   3496     default:
   3497       SetGLError(
   3498           GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target");
   3499       return NULL;
   3500   }
   3501   GLuint buffer_id;
   3502   GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id);
   3503   if (!buffer_id) {
   3504     return NULL;
   3505   }
   3506   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
   3507   if (!buffer) {
   3508     SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
   3509     return NULL;
   3510   }
   3511   if (buffer->mapped()) {
   3512     SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
   3513     return NULL;
   3514   }
   3515   // Here we wait for previous transfer operations to be finished.
   3516   // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
   3517   // with this method of synchronization. Until this is fixed,
   3518   // MapBufferCHROMIUM will not block even if the transfer is not ready
   3519   // for these calls.
   3520   if (buffer->transfer_ready_token()) {
   3521     helper_->WaitForToken(buffer->transfer_ready_token());
   3522     buffer->set_transfer_ready_token(0);
   3523   }
   3524   buffer->set_mapped(true);
   3525 
   3526   GPU_CLIENT_LOG("  returned " << buffer->address());
   3527   CheckGLError();
   3528   return buffer->address();
   3529 }
   3530 
   3531 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
   3532   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3533   GPU_CLIENT_LOG(
   3534       "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target << ")");
   3535   GLuint buffer_id;
   3536   if (!GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id)) {
   3537     SetGLError(GL_INVALID_ENUM, "glUnmapBufferCHROMIUM", "invalid target");
   3538   }
   3539   if (!buffer_id) {
   3540     return false;
   3541   }
   3542   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
   3543   if (!buffer) {
   3544     SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "invalid buffer");
   3545     return false;
   3546   }
   3547   if (!buffer->mapped()) {
   3548     SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped");
   3549     return false;
   3550   }
   3551   buffer->set_mapped(false);
   3552   CheckGLError();
   3553   return true;
   3554 }
   3555 
   3556 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
   3557     GLenum target, GLint level, GLint internalformat, GLsizei width,
   3558     GLsizei height, GLint border, GLenum format, GLenum type,
   3559     const void* pixels) {
   3560   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3561   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
   3562       << GLES2Util::GetStringTextureTarget(target) << ", "
   3563       << level << ", "
   3564       << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
   3565       << width << ", " << height << ", " << border << ", "
   3566       << GLES2Util::GetStringTextureFormat(format) << ", "
   3567       << GLES2Util::GetStringPixelType(type) << ", "
   3568       << static_cast<const void*>(pixels) << ")");
   3569   if (level < 0 || height < 0 || width < 0) {
   3570     SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimension < 0");
   3571     return;
   3572   }
   3573   uint32 size;
   3574   uint32 unpadded_row_size;
   3575   uint32 padded_row_size;
   3576   if (!GLES2Util::ComputeImageDataSizes(
   3577           width, height, format, type, unpack_alignment_, &size,
   3578           &unpadded_row_size, &padded_row_size)) {
   3579     SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large");
   3580     return;
   3581   }
   3582 
   3583   // If there's no data/buffer just issue the AsyncTexImage2D
   3584   if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) {
   3585     helper_->AsyncTexImage2DCHROMIUM(
   3586        target, level, internalformat, width, height, border, format, type,
   3587        0, 0);
   3588     return;
   3589   }
   3590 
   3591   // Otherwise, async uploads require a transfer buffer to be bound.
   3592   // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
   3593   // the buffer before the transfer is finished. (Currently such
   3594   // synchronization has to be handled manually.)
   3595   GLuint offset = ToGLuint(pixels);
   3596   BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   3597       bound_pixel_unpack_transfer_buffer_id_,
   3598       "glAsyncTexImage2DCHROMIUM", offset, size);
   3599   if (buffer && buffer->shm_id() != -1) {
   3600     helper_->AsyncTexImage2DCHROMIUM(
   3601         target, level, internalformat, width, height, border, format, type,
   3602         buffer->shm_id(), buffer->shm_offset() + offset);
   3603   }
   3604 }
   3605 
   3606 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
   3607     GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
   3608     GLsizei height, GLenum format, GLenum type, const void* pixels) {
   3609   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3610   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
   3611       << GLES2Util::GetStringTextureTarget(target) << ", "
   3612       << level << ", "
   3613       << xoffset << ", " << yoffset << ", "
   3614       << width << ", " << height << ", "
   3615       << GLES2Util::GetStringTextureFormat(format) << ", "
   3616       << GLES2Util::GetStringPixelType(type) << ", "
   3617       << static_cast<const void*>(pixels) << ")");
   3618   if (level < 0 || height < 0 || width < 0) {
   3619     SetGLError(
   3620         GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
   3621     return;
   3622   }
   3623 
   3624   uint32 size;
   3625   uint32 unpadded_row_size;
   3626   uint32 padded_row_size;
   3627   if (!GLES2Util::ComputeImageDataSizes(
   3628         width, height, format, type, unpack_alignment_, &size,
   3629         &unpadded_row_size, &padded_row_size)) {
   3630     SetGLError(
   3631         GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large");
   3632     return;
   3633   }
   3634 
   3635   // Async uploads require a transfer buffer to be bound.
   3636   // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
   3637   // the buffer before the transfer is finished. (Currently such
   3638   // synchronization has to be handled manually.)
   3639   GLuint offset = ToGLuint(pixels);
   3640   BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
   3641       bound_pixel_unpack_transfer_buffer_id_,
   3642       "glAsyncTexSubImage2DCHROMIUM", offset, size);
   3643   if (buffer && buffer->shm_id() != -1) {
   3644     helper_->AsyncTexSubImage2DCHROMIUM(
   3645         target, level, xoffset, yoffset, width, height, format, type,
   3646         buffer->shm_id(), buffer->shm_offset() + offset);
   3647   }
   3648 }
   3649 
   3650 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) {
   3651   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3652   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
   3653       << GLES2Util::GetStringTextureTarget(target) << ")");
   3654   helper_->WaitAsyncTexImage2DCHROMIUM(target);
   3655   CheckGLError();
   3656 }
   3657 
   3658 GLuint GLES2Implementation::InsertSyncPointCHROMIUM() {
   3659   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3660   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
   3661   return helper_->InsertSyncPointCHROMIUM();
   3662 }
   3663 
   3664 GLuint GLES2Implementation::CreateImageCHROMIUMHelper(
   3665     GLsizei width, GLsizei height, GLenum internalformat) {
   3666   if (width <= 0) {
   3667     SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "width <= 0");
   3668     return 0;
   3669   }
   3670 
   3671   if (height <= 0) {
   3672     SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "height <= 0");
   3673     return 0;
   3674   }
   3675   // Flush the command stream to ensure ordering in case the newly
   3676   // returned image_id has recently been in use with a different buffer.
   3677   helper_->CommandBufferHelper::Flush();
   3678 
   3679   // Create new buffer.
   3680   GLuint buffer_id = gpu_memory_buffer_tracker_->CreateBuffer(
   3681       width, height, internalformat);
   3682   if (buffer_id == 0) {
   3683     SetGLError(GL_OUT_OF_MEMORY, "glCreateImageCHROMIUM", "out of GPU memory.");
   3684     return 0;
   3685   }
   3686   return buffer_id;
   3687 }
   3688 
   3689 GLuint GLES2Implementation::CreateImageCHROMIUM(
   3690     GLsizei width, GLsizei height, GLenum internalformat) {
   3691   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3692   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM("
   3693       << width << ", "
   3694       << height << ", "
   3695       << GLES2Util::GetStringTextureInternalFormat(internalformat) << ")");
   3696   GLuint image_id = CreateImageCHROMIUMHelper(width, height, internalformat);
   3697   CheckGLError();
   3698   return image_id;
   3699 }
   3700 
   3701 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id) {
   3702   gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer(
   3703       image_id);
   3704   if (!gpu_buffer) {
   3705     SetGLError(GL_INVALID_OPERATION, "glDestroyImageCHROMIUM", "invalid image");
   3706     return;
   3707   }
   3708 
   3709   // Flush the command stream to make sure all pending commands
   3710   // that may refer to the image_id are executed on the service side.
   3711   helper_->CommandBufferHelper::Flush();
   3712   gpu_memory_buffer_tracker_->RemoveBuffer(image_id);
   3713 }
   3714 
   3715 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id) {
   3716   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3717   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
   3718       << image_id << ")");
   3719   DestroyImageCHROMIUMHelper(image_id);
   3720   CheckGLError();
   3721 }
   3722 
   3723 void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id) {
   3724   gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer(
   3725       image_id);
   3726   if (!gpu_buffer) {
   3727     SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "invalid image");
   3728     return;
   3729   }
   3730 
   3731   if (!gpu_buffer->IsMapped()) {
   3732     SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "not mapped");
   3733     return;
   3734   }
   3735   gpu_buffer->Unmap();
   3736 }
   3737 
   3738 void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id) {
   3739   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3740   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM("
   3741        << image_id << ")");
   3742 
   3743   UnmapImageCHROMIUMHelper(image_id);
   3744   CheckGLError();
   3745 }
   3746 
   3747 void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id,
   3748                                                   GLenum access) {
   3749   gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer(
   3750       image_id);
   3751   if (!gpu_buffer) {
   3752     SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "invalid image");
   3753     return NULL;
   3754   }
   3755   gfx::GpuMemoryBuffer::AccessMode mode;
   3756   switch(access) {
   3757     case GL_WRITE_ONLY:
   3758       mode = gfx::GpuMemoryBuffer::WRITE_ONLY;
   3759       break;
   3760     case GL_READ_ONLY:
   3761       mode = gfx::GpuMemoryBuffer::READ_ONLY;
   3762       break;
   3763     case GL_READ_WRITE:
   3764       mode = gfx::GpuMemoryBuffer::READ_WRITE;
   3765       break;
   3766     default:
   3767       SetGLError(GL_INVALID_ENUM, "glMapImageCHROMIUM",
   3768                  "invalid GPU access mode");
   3769       return NULL;
   3770   }
   3771 
   3772   if (gpu_buffer->IsMapped()) {
   3773     SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "already mapped");
   3774     return NULL;
   3775   }
   3776 
   3777   void* mapped_buffer = NULL;
   3778   gpu_buffer->Map(mode, &mapped_buffer);
   3779   return mapped_buffer;
   3780 }
   3781 
   3782 void* GLES2Implementation::MapImageCHROMIUM(
   3783     GLuint image_id, GLenum access) {
   3784   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3785   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
   3786       << image_id << ", "
   3787       << GLES2Util::GetStringEnum(access) << ")");
   3788 
   3789   void* mapped = MapImageCHROMIUMHelper(image_id, access);
   3790   CheckGLError();
   3791   return mapped;
   3792 }
   3793 
   3794 void GLES2Implementation::GetImageParameterivCHROMIUMHelper(
   3795     GLuint image_id, GLenum pname, GLint* params) {
   3796   if (pname != GL_IMAGE_ROWBYTES_CHROMIUM) {
   3797     SetGLError(GL_INVALID_ENUM, "glGetImageParameterivCHROMIUM",
   3798                "invalid parameter");
   3799     return;
   3800   }
   3801 
   3802   gfx::GpuMemoryBuffer* gpu_buffer = gpu_memory_buffer_tracker_->GetBuffer(
   3803       image_id);
   3804   if (!gpu_buffer) {
   3805     SetGLError(GL_INVALID_OPERATION, "glGetImageParameterivCHROMIUM",
   3806                "invalid image");
   3807     return;
   3808   }
   3809 
   3810   *params = gpu_buffer->GetStride();
   3811 }
   3812 
   3813 void GLES2Implementation::GetImageParameterivCHROMIUM(
   3814     GLuint image_id, GLenum pname, GLint* params) {
   3815   GPU_CLIENT_SINGLE_THREAD_CHECK();
   3816   GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params);
   3817   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glImageParameterivCHROMIUM("
   3818       << image_id << ", "
   3819       << GLES2Util::GetStringBufferParameter(pname) << ", "
   3820       << static_cast<const void*>(params) << ")");
   3821   GetImageParameterivCHROMIUMHelper(image_id, pname, params);
   3822   CheckGLError();
   3823 }
   3824 
   3825 // Include the auto-generated part of this file. We split this because it means
   3826 // we can easily edit the non-auto generated parts right here in this file
   3827 // instead of having to edit some template or the code generator.
   3828 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
   3829 
   3830 }  // namespace gles2
   3831 }  // namespace gpu
   3832