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