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