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