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