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