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