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