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