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