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/gl2.h>
10 #include <GLES2/gl2ext.h>
11 #include <GLES2/gl2extchromium.h>
12 #include <GLES3/gl3.h>
13 #include <GLES3/gl31.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <algorithm>
18 #include <map>
19 #include <set>
20 #include <sstream>
21 #include <string>
22 
23 #include "base/atomic_sequence_num.h"
24 #include "base/bind.h"
25 #include "base/bits.h"
26 #include "base/compiler_specific.h"
27 #include "base/containers/span.h"
28 #include "base/numerics/safe_math.h"
29 #include "base/stl_util.h"
30 #include "base/strings/string_split.h"
31 #include "base/strings/stringprintf.h"
32 #include "base/system/sys_info.h"
33 #include "base/threading/thread_task_runner_handle.h"
34 #include "base/trace_event/memory_allocator_dump.h"
35 #include "base/trace_event/memory_dump_manager.h"
36 #include "base/trace_event/process_memory_dump.h"
37 #include "base/trace_event/trace_event.h"
38 #include "build/build_config.h"
39 #include "gpu/command_buffer/client/buffer_tracker.h"
40 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
41 #include "gpu/command_buffer/client/gpu_control.h"
42 #include "gpu/command_buffer/client/program_info_manager.h"
43 #include "gpu/command_buffer/client/query_tracker.h"
44 #include "gpu/command_buffer/client/readback_buffer_shadow_tracker.h"
45 #include "gpu/command_buffer/client/shared_memory_limits.h"
46 #include "gpu/command_buffer/client/transfer_buffer.h"
47 #include "gpu/command_buffer/client/transfer_buffer_cmd_copy_helpers.h"
48 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
49 #include "gpu/command_buffer/common/context_creation_attribs.h"
50 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
51 #include "gpu/command_buffer/common/id_allocator.h"
52 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
53 #include "gpu/command_buffer/common/sync_token.h"
54 #include "ui/gfx/geometry/rect.h"
55 #include "ui/gfx/geometry/rect_f.h"
56 #include "ui/gl/gpu_preference.h"
57 
58 #if !defined(__native_client__)
59 #include "ui/gfx/color_space.h"
60 #include "ui/gfx/ipc/color/gfx_param_traits.h"
61 #endif
62 
63 #if defined(GPU_CLIENT_DEBUG)
64 #define GPU_CLIENT_SINGLE_THREAD_CHECK() \
65   DeferErrorCallbacks deferrer(this);    \
66   SingleThreadChecker checker(this);
67 #else  // !defined(GPU_CLIENT_DEBUG)
68 #define GPU_CLIENT_SINGLE_THREAD_CHECK() DeferErrorCallbacks deferrer(this);
69 #endif  // defined(GPU_CLIENT_DEBUG)
70 
71 // Check that destination pointers point to initialized memory.
72 // When the context is lost, calling GL function has no effect so if destination
73 // pointers point to initialized memory it can often lead to crash bugs. eg.
74 //
75 // GLsizei len;
76 // glGetShaderSource(shader, max_size, &len, buffer);
77 // std::string src(buffer, buffer + len);  // len can be uninitialized here!!!
78 //
79 // Because this check is not official GL this check happens only on Chrome code,
80 // not Pepper.
81 //
82 // If it was up to us we'd just always write to the destination but the OpenGL
83 // spec defines the behavior of OpenGL functions, not us. :-(
84 #if defined(__native_client__) || defined(GLES2_CONFORMANCE_TESTS)
85 #define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v)
86 #define GPU_CLIENT_DCHECK(v)
87 #elif defined(GPU_DCHECK)
88 #define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) GPU_DCHECK(v)
89 #define GPU_CLIENT_DCHECK(v) GPU_DCHECK(v)
90 #elif defined(DCHECK)
91 #define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) DCHECK(v)
92 #define GPU_CLIENT_DCHECK(v) DCHECK(v)
93 #else
94 #define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(v) ASSERT(v)
95 #define GPU_CLIENT_DCHECK(v) ASSERT(v)
96 #endif
97 
98 #define GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(type, ptr) \
99   GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(          \
100       ptr &&                                                     \
101       (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1)));
102 
103 #define GPU_CLIENT_VALIDATE_DESTINATION_OPTIONAL_INITALIZATION(type, ptr) \
104   GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION_ASSERT(                   \
105       !ptr ||                                                             \
106       (ptr[0] == static_cast<type>(0) || ptr[0] == static_cast<type>(-1)));
107 
108 namespace gpu {
109 namespace gles2 {
110 
111 namespace {
112 
CopyRectToBuffer(const void * pixels,uint32_t height,uint32_t unpadded_row_size,uint32_t pixels_padded_row_size,void * buffer,uint32_t buffer_padded_row_size)113 void CopyRectToBuffer(const void* pixels,
114                       uint32_t height,
115                       uint32_t unpadded_row_size,
116                       uint32_t pixels_padded_row_size,
117                       void* buffer,
118                       uint32_t buffer_padded_row_size) {
119   if (height == 0)
120     return;
121   const int8_t* source = static_cast<const int8_t*>(pixels);
122   int8_t* dest = static_cast<int8_t*>(buffer);
123   if (pixels_padded_row_size != buffer_padded_row_size) {
124     for (uint32_t ii = 0; ii < height; ++ii) {
125       memcpy(dest, source, unpadded_row_size);
126       dest += buffer_padded_row_size;
127       source += pixels_padded_row_size;
128     }
129   } else {
130     uint32_t size = (height - 1) * pixels_padded_row_size + unpadded_row_size;
131     memcpy(dest, source, size);
132   }
133 }
134 
135 static base::AtomicSequenceNumber g_flush_id;
136 
GenerateNextFlushId()137 uint32_t GenerateNextFlushId() {
138   return static_cast<uint32_t>(g_flush_id.GetNext());
139 }
140 
IsReadbackUsage(GLenum usage)141 bool IsReadbackUsage(GLenum usage) {
142   return usage == GL_STREAM_READ || usage == GL_DYNAMIC_READ ||
143          usage == GL_STATIC_READ;
144 }
145 
146 }  // anonymous namespace
147 
148 GLES2Implementation::GLStaticState::GLStaticState() = default;
149 
150 GLES2Implementation::GLStaticState::~GLStaticState() = default;
151 
DeferErrorCallbacks(GLES2Implementation * gles2_implementation)152 GLES2Implementation::DeferErrorCallbacks::DeferErrorCallbacks(
153     GLES2Implementation* gles2_implementation)
154     : gles2_implementation_(gles2_implementation) {
155   DCHECK_EQ(false, gles2_implementation_->deferring_error_callbacks_);
156   gles2_implementation_->deferring_error_callbacks_ = true;
157 }
158 
~DeferErrorCallbacks()159 GLES2Implementation::DeferErrorCallbacks::~DeferErrorCallbacks() {
160   DCHECK_EQ(true, gles2_implementation_->deferring_error_callbacks_);
161   gles2_implementation_->deferring_error_callbacks_ = false;
162   gles2_implementation_->CallDeferredErrorCallbacks();
163 }
164 
DeferredErrorCallback(std::string message,int32_t id)165 GLES2Implementation::DeferredErrorCallback::DeferredErrorCallback(
166     std::string message,
167     int32_t id)
168     : message(std::move(message)), id(id) {}
169 
SingleThreadChecker(GLES2Implementation * gles2_implementation)170 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
171     GLES2Implementation* gles2_implementation)
172     : gles2_implementation_(gles2_implementation) {
173   CHECK_EQ(0, gles2_implementation_->use_count_);
174   ++gles2_implementation_->use_count_;
175 }
176 
~SingleThreadChecker()177 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
178   --gles2_implementation_->use_count_;
179   CHECK_EQ(0, gles2_implementation_->use_count_);
180 }
181 
GLES2Implementation(GLES2CmdHelper * helper,scoped_refptr<ShareGroup> share_group,TransferBufferInterface * transfer_buffer,bool bind_generates_resource,bool lose_context_when_out_of_memory,bool support_client_side_arrays,GpuControl * gpu_control)182 GLES2Implementation::GLES2Implementation(
183     GLES2CmdHelper* helper,
184     scoped_refptr<ShareGroup> share_group,
185     TransferBufferInterface* transfer_buffer,
186     bool bind_generates_resource,
187     bool lose_context_when_out_of_memory,
188     bool support_client_side_arrays,
189     GpuControl* gpu_control)
190     : ImplementationBase(helper, transfer_buffer, gpu_control),
191       helper_(helper),
192       chromium_framebuffer_multisample_(kUnknownExtensionStatus),
193       pack_alignment_(4),
194       pack_row_length_(0),
195       pack_skip_pixels_(0),
196       pack_skip_rows_(0),
197       unpack_alignment_(4),
198       unpack_row_length_(0),
199       unpack_image_height_(0),
200       unpack_skip_rows_(0),
201       unpack_skip_pixels_(0),
202       unpack_skip_images_(0),
203       active_texture_unit_(0),
204       bound_framebuffer_(0),
205       bound_read_framebuffer_(0),
206       bound_renderbuffer_(0),
207       current_program_(0),
208       bound_array_buffer_(0),
209       bound_atomic_counter_buffer_(0),
210       bound_copy_read_buffer_(0),
211       bound_copy_write_buffer_(0),
212       bound_dispatch_indirect_buffer_(0),
213       bound_draw_indirect_buffer_(0),
214       bound_pixel_pack_buffer_(0),
215       bound_pixel_unpack_buffer_(0),
216       bound_shader_storage_buffer_(0),
217       bound_transform_feedback_buffer_(0),
218       bound_uniform_buffer_(0),
219       bound_pixel_pack_transfer_buffer_id_(0),
220       bound_pixel_unpack_transfer_buffer_id_(0),
221       error_bits_(0),
222       lose_context_when_out_of_memory_(lose_context_when_out_of_memory),
223       support_client_side_arrays_(support_client_side_arrays),
224       use_count_(0),
225       flush_id_(0),
226       max_extra_transfer_buffer_size_(0),
227       current_trace_stack_(0),
228       aggressively_free_resources_(false),
229       cached_extension_string_(nullptr) {
230   DCHECK(helper);
231 
232   std::stringstream ss;
233   ss << std::hex << this;
234   this_in_hex_ = ss.str();
235 
236   share_group_ =
237       (share_group ? std::move(share_group)
238                    : new ShareGroup(
239                          bind_generates_resource,
240                          gpu_control_->GetCommandBufferID().GetUnsafeValue()));
241   DCHECK(share_group_->bind_generates_resource() == bind_generates_resource);
242 
243   memset(&reserved_ids_, 0, sizeof(reserved_ids_));
244 }
245 
Initialize(const SharedMemoryLimits & limits)246 gpu::ContextResult GLES2Implementation::Initialize(
247     const SharedMemoryLimits& limits) {
248   TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
249   auto result = ImplementationBase::Initialize(limits);
250   if (result != gpu::ContextResult::kSuccess) {
251     return result;
252   }
253 
254   max_extra_transfer_buffer_size_ = limits.max_mapped_memory_for_texture_upload;
255 
256   GLStaticState::ShaderPrecisionMap* shader_precisions =
257       &static_state_.shader_precisions;
258   capabilities_.VisitPrecisions(
259       [shader_precisions](GLenum shader, GLenum type,
260                           Capabilities::ShaderPrecision* result) {
261         const GLStaticState::ShaderPrecisionKey key(shader, type);
262         cmds::GetShaderPrecisionFormat::Result cached_result = {
263             true, result->min_range, result->max_range, result->precision};
264         shader_precisions->insert(std::make_pair(key, cached_result));
265       });
266 
267   util_.set_num_compressed_texture_formats(
268       capabilities_.num_compressed_texture_formats);
269   util_.set_num_shader_binary_formats(capabilities_.num_shader_binary_formats);
270 
271   texture_units_ = std::make_unique<TextureUnit[]>(
272       capabilities_.max_combined_texture_image_units);
273 
274   buffer_tracker_ = std::make_unique<BufferTracker>(mapped_memory_.get());
275   readback_buffer_shadow_tracker_ =
276       std::make_unique<ReadbackBufferShadowTracker>(mapped_memory_.get(),
277                                                     helper_);
278 
279   for (int i = 0; i < static_cast<int>(IdNamespaces::kNumIdNamespaces); ++i)
280     id_allocators_[i].reset(new IdAllocator());
281 
282   if (support_client_side_arrays_) {
283     GetIdHandler(SharedIdNamespaces::kBuffers)
284         ->MakeIds(this, kClientSideArrayId, base::size(reserved_ids_),
285                   &reserved_ids_[0]);
286   }
287 
288   vertex_array_object_manager_.reset(new VertexArrayObjectManager(
289       capabilities_.max_vertex_attribs, reserved_ids_[0], reserved_ids_[1],
290       support_client_side_arrays_));
291 
292   // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
293   // on Client & Service.
294   if (capabilities_.bind_generates_resource_chromium !=
295       (share_group_->bind_generates_resource() ? 1 : 0)) {
296     SetGLError(GL_INVALID_OPERATION, "Initialize",
297                "Service bind_generates_resource mismatch.");
298     LOG(ERROR) << "ContextResult::kFatalFailure: "
299                << "bind_generates_resource mismatch";
300     return gpu::ContextResult::kFatalFailure;
301   }
302 
303   return gpu::ContextResult::kSuccess;
304 }
305 
~GLES2Implementation()306 GLES2Implementation::~GLES2Implementation() {
307   // Make sure the queries are finished otherwise we'll delete the
308   // shared memory (mapped_memory_) which will free the memory used
309   // by the queries. The GPU process when validating that memory is still
310   // shared will fail and abort (ie, it will stop running).
311   WaitForCmd();
312 
313   query_tracker_.reset();
314 
315   // GLES2Implementation::Initialize() could fail before allocating
316   // reserved_ids_, so we need delete them carefully.
317   if (support_client_side_arrays_ && reserved_ids_[0]) {
318     DeleteBuffers(base::size(reserved_ids_), &reserved_ids_[0]);
319   }
320 
321   // Release remaining BufferRange mem; This is when a MapBufferRange() is
322   // called but not the UnmapBuffer() pair.
323   ClearMappedBufferRangeMap();
324 
325   // Release any per-context data in share group.
326   share_group_->FreeContext(this);
327 
328   buffer_tracker_.reset();
329   readback_buffer_shadow_tracker_.reset();
330 
331   // Make sure the commands make it the service.
332   WaitForCmd();
333 }
334 
helper() const335 GLES2CmdHelper* GLES2Implementation::helper() const {
336   return helper_;
337 }
338 
GetIdHandler(SharedIdNamespaces namespace_id) const339 IdHandlerInterface* GLES2Implementation::GetIdHandler(
340     SharedIdNamespaces namespace_id) const {
341   return share_group_->GetIdHandler(namespace_id);
342 }
343 
GetRangeIdHandler(int namespace_id) const344 RangeIdHandlerInterface* GLES2Implementation::GetRangeIdHandler(
345     int namespace_id) const {
346   return share_group_->GetRangeIdHandler(namespace_id);
347 }
348 
GetIdAllocator(IdNamespaces namespace_id) const349 IdAllocator* GLES2Implementation::GetIdAllocator(
350     IdNamespaces namespace_id) const {
351   return id_allocators_[static_cast<int>(namespace_id)].get();
352 }
353 
OnGpuControlLostContext()354 void GLES2Implementation::OnGpuControlLostContext() {
355   // This should never occur more than once.
356   DCHECK(!lost_context_callback_run_);
357   lost_context_callback_run_ = true;
358   share_group_->Lose();
359   if (!lost_context_callback_.is_null()) {
360     std::move(lost_context_callback_).Run();
361   }
362 }
363 
OnGpuControlLostContextMaybeReentrant()364 void GLES2Implementation::OnGpuControlLostContextMaybeReentrant() {
365   // Queries for lost context state should immediately reflect reality,
366   // but don't call out to clients yet to avoid them re-entering this
367   // class.
368   share_group_->Lose();
369 }
370 
OnGpuControlErrorMessage(const char * message,int32_t id)371 void GLES2Implementation::OnGpuControlErrorMessage(const char* message,
372                                                    int32_t id) {
373   SendErrorMessage(message, id);
374 }
375 
OnGpuControlSwapBuffersCompleted(const SwapBuffersCompleteParams & params)376 void GLES2Implementation::OnGpuControlSwapBuffersCompleted(
377     const SwapBuffersCompleteParams& params) {
378   auto found = pending_swap_callbacks_.find(params.swap_response.swap_id);
379   if (found == pending_swap_callbacks_.end())
380     return;
381 
382   // Erase the entry before running the callback to guard against the callback
383   // mutating the |pending_swap_callbacks_|.
384   auto callback = std::move(found->second);
385   pending_swap_callbacks_.erase(found);
386 
387   std::move(callback).Run(params);
388 }
389 
OnGpuSwitched(gl::GpuPreference active_gpu_heuristic)390 void GLES2Implementation::OnGpuSwitched(
391     gl::GpuPreference active_gpu_heuristic) {
392   gpu_switched_ = true;
393   active_gpu_heuristic_ = active_gpu_heuristic;
394 }
395 
DidGpuSwitch(gl::GpuPreference * active_gpu)396 GLboolean GLES2Implementation::DidGpuSwitch(gl::GpuPreference* active_gpu) {
397   if (gpu_switched_) {
398     *active_gpu = active_gpu_heuristic_;
399   }
400   GLboolean result = gpu_switched_ ? GL_TRUE : GL_FALSE;
401   gpu_switched_ = false;
402   return result;
403 }
404 
SendErrorMessage(std::string message,int32_t id)405 void GLES2Implementation::SendErrorMessage(std::string message, int32_t id) {
406   if (error_message_callback_.is_null())
407     return;
408 
409   if (deferring_error_callbacks_) {
410     deferred_error_callbacks_.emplace_back(std::move(message), id);
411     return;
412   }
413 
414   error_message_callback_.Run(message.c_str(), id);
415 }
416 
CallDeferredErrorCallbacks()417 void GLES2Implementation::CallDeferredErrorCallbacks() {
418   if (deferred_error_callbacks_.empty())
419     return;
420 
421   if (error_message_callback_.is_null()) {
422     // User probably cleared this out.
423     deferred_error_callbacks_.clear();
424     return;
425   }
426 
427   std::deque<DeferredErrorCallback> local_callbacks;
428   std::swap(deferred_error_callbacks_, local_callbacks);
429   for (auto c : local_callbacks) {
430     error_message_callback_.Run(c.message.c_str(), c.id);
431   }
432 }
433 
OnSwapBufferPresented(uint64_t swap_id,const gfx::PresentationFeedback & feedback)434 void GLES2Implementation::OnSwapBufferPresented(
435     uint64_t swap_id,
436     const gfx::PresentationFeedback& feedback) {
437   auto found = pending_presentation_callbacks_.find(swap_id);
438   if (found == pending_presentation_callbacks_.end())
439     return;
440 
441   // Erase the entry before running the callback to guard against the callback
442   // mutating the |pending_presentation_callbacks_|.
443   auto callback = std::move(found->second);
444   pending_presentation_callbacks_.erase(found);
445 
446   std::move(callback).Run(feedback);
447 }
448 
OnGpuControlReturnData(base::span<const uint8_t> data)449 void GLES2Implementation::OnGpuControlReturnData(
450     base::span<const uint8_t> data) {
451   NOTIMPLEMENTED();
452 }
453 
FreeSharedMemory(void * mem)454 void GLES2Implementation::FreeSharedMemory(void* mem) {
455   mapped_memory_->FreePendingToken(mem, helper_->InsertToken());
456 }
457 
CreateGpuFenceCHROMIUM()458 GLuint GLES2Implementation::CreateGpuFenceCHROMIUM() {
459   GLuint client_id = GetIdAllocator(IdNamespaces::kGpuFences)
460                          ->AllocateIDAtOrAbove(last_gpu_fence_id_ + 1);
461   // Out of paranoia, don't allow IDs to wrap around to avoid potential
462   // collisions on reuse. The space of 2^32 IDs is enough for over a year of
463   // allocating two per frame at 60fps. TODO(crbug.com/790550): Revisit if this
464   // is an issue, for example by deferring ID release if they would be reissued
465   // too soon.
466   CHECK(client_id > last_gpu_fence_id_) << "ID wrap prevented";
467   last_gpu_fence_id_ = client_id;
468   helper_->CreateGpuFenceINTERNAL(client_id);
469   GPU_CLIENT_LOG("returned " << client_id);
470   CheckGLError();
471   return client_id;
472 }
473 
CreateClientGpuFenceCHROMIUM(ClientGpuFence source)474 GLuint GLES2Implementation::CreateClientGpuFenceCHROMIUM(
475     ClientGpuFence source) {
476   GLuint client_id = GetIdAllocator(IdNamespaces::kGpuFences)
477                          ->AllocateIDAtOrAbove(last_gpu_fence_id_ + 1);
478   // See CreateGpuFenceCHROMIUM comment re wraparound.
479   CHECK(client_id > last_gpu_fence_id_) << "ID wrap prevented";
480   last_gpu_fence_id_ = client_id;
481 
482   // Create the service-side GpuFenceEntry via gpu_control. This is guaranteed
483   // to arrive before any future GL helper_ commands on this stream, so it's
484   // safe to use the client_id generated here in following commands such as
485   // WaitGpuFenceCHROMIUM without explicit flushing.
486   gpu_control_->CreateGpuFence(client_id, source);
487 
488   GPU_CLIENT_LOG("returned " << client_id);
489   CheckGLError();
490   return client_id;
491 }
492 
DestroyGpuFenceCHROMIUMHelper(GLuint client_id)493 void GLES2Implementation::DestroyGpuFenceCHROMIUMHelper(GLuint client_id) {
494   if (GetIdAllocator(IdNamespaces::kGpuFences)->InUse(client_id)) {
495     GetIdAllocator(IdNamespaces::kGpuFences)->FreeID(client_id);
496     helper_->DestroyGpuFenceCHROMIUM(client_id);
497   } else {
498     SetGLError(GL_INVALID_VALUE, "glDestroyGpuFenceCHROMIUM",
499                "id not created by this context.");
500   }
501 }
502 
SetAggressivelyFreeResources(bool aggressively_free_resources)503 void GLES2Implementation::SetAggressivelyFreeResources(
504     bool aggressively_free_resources) {
505   TRACE_EVENT1("gpu", "GLES2Implementation::SetAggressivelyFreeResources",
506                "aggressively_free_resources", aggressively_free_resources);
507   aggressively_free_resources_ = aggressively_free_resources;
508 
509   if (aggressively_free_resources_ && helper_->HaveRingBuffer()) {
510     // Ensure that we clean up as much cache memory as possible and fully flush.
511     FlushDriverCachesCHROMIUM();
512 
513     // Flush will delete transfer buffer resources if
514     // |aggressively_free_resources_| is true.
515     Flush();
516   } else {
517     ShallowFlushCHROMIUM();
518   }
519 }
520 
IsExtensionAvailable(const char * ext)521 bool GLES2Implementation::IsExtensionAvailable(const char* ext) {
522   const char* extensions =
523       reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS));
524   if (!extensions)
525     return false;
526 
527   int length = strlen(ext);
528   while (true) {
529     int n = strcspn(extensions, " ");
530     if (n == length && 0 == strncmp(ext, extensions, length)) {
531       return true;
532     }
533     if ('\0' == extensions[n]) {
534       return false;
535     }
536     extensions += n + 1;
537   }
538 }
539 
IsExtensionAvailableHelper(const char * extension,ExtensionStatus * status)540 bool GLES2Implementation::IsExtensionAvailableHelper(const char* extension,
541                                                      ExtensionStatus* status) {
542   switch (*status) {
543     case kAvailableExtensionStatus:
544       return true;
545     case kUnavailableExtensionStatus:
546       return false;
547     default: {
548       bool available = IsExtensionAvailable(extension);
549       *status =
550           available ? kAvailableExtensionStatus : kUnavailableExtensionStatus;
551       return available;
552     }
553   }
554 }
555 
IsChromiumFramebufferMultisampleAvailable()556 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
557   return IsExtensionAvailableHelper("GL_CHROMIUM_framebuffer_multisample",
558                                     &chromium_framebuffer_multisample_);
559 }
560 
GetLogPrefix() const561 const std::string& GLES2Implementation::GetLogPrefix() const {
562   const std::string& prefix(debug_marker_manager_.GetMarker());
563   return prefix.empty() ? this_in_hex_ : prefix;
564 }
565 
GetError()566 GLenum GLES2Implementation::GetError() {
567   GPU_CLIENT_SINGLE_THREAD_CHECK();
568   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
569   GLenum err = GetGLError();
570   GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err));
571   return err;
572 }
573 
GetGLError()574 GLenum GLES2Implementation::GetGLError() {
575   TRACE_EVENT0("gpu", "GLES2::GetGLError");
576   // Check the GL error first, then our wrapped error.
577   typedef cmds::GetError::Result Result;
578   auto result = GetResultAs<Result>();
579   // If we couldn't allocate a result the context is lost.
580   if (!result) {
581     return GL_NO_ERROR;
582   }
583   *result = GL_NO_ERROR;
584   helper_->GetError(GetResultShmId(), result.offset());
585   WaitForCmd();
586   GLenum error = *result;
587   if (error == GL_NO_ERROR) {
588     error = GetClientSideGLError();
589   } else {
590     // There was an error, clear the corresponding wrapped error.
591     error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
592   }
593   return error;
594 }
595 
596 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
FailGLError(GLenum error)597 void GLES2Implementation::FailGLError(GLenum error) {
598   if (error != GL_NO_ERROR) {
599     NOTREACHED() << "Error";
600   }
601 }
602 // NOTE: Calling GetGLError overwrites data in the result buffer.
CheckGLError()603 void GLES2Implementation::CheckGLError() {
604   FailGLError(GetGLError());
605 }
606 #endif  // defined(GPU_CLIENT_FAIL_GL_ERRORS)
607 
SetGLError(GLenum error,const char * function_name,const char * msg)608 void GLES2Implementation::SetGLError(GLenum error,
609                                      const char* function_name,
610                                      const char* msg) {
611   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
612                      << GLES2Util::GetStringError(error) << ": "
613                      << function_name << ": " << msg);
614   FailGLError(error);
615   if (msg) {
616     last_error_ = msg;
617   }
618   if (!error_message_callback_.is_null()) {
619     std::string temp(GLES2Util::GetStringError(error) + " : " + function_name +
620                      ": " + (msg ? msg : ""));
621     SendErrorMessage(temp.c_str(), 0);
622   }
623   error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
624 
625   if (error == GL_OUT_OF_MEMORY && lose_context_when_out_of_memory_) {
626     helper_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
627                                  GL_UNKNOWN_CONTEXT_RESET_ARB);
628   }
629 }
630 
SetGLErrorInvalidEnum(const char * function_name,GLenum value,const char * label)631 void GLES2Implementation::SetGLErrorInvalidEnum(const char* function_name,
632                                                 GLenum value,
633                                                 const char* label) {
634   SetGLError(
635       GL_INVALID_ENUM, function_name,
636       (std::string(label) + " was " + GLES2Util::GetStringEnum(value)).c_str());
637 }
638 
Disable(GLenum cap)639 void GLES2Implementation::Disable(GLenum cap) {
640   GPU_CLIENT_SINGLE_THREAD_CHECK();
641   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
642                      << GLES2Util::GetStringCapability(cap) << ")");
643   bool changed = false;
644   if (!state_.SetCapabilityState(cap, false, &changed) || changed) {
645     helper_->Disable(cap);
646   }
647   CheckGLError();
648 }
649 
Enable(GLenum cap)650 void GLES2Implementation::Enable(GLenum cap) {
651   GPU_CLIENT_SINGLE_THREAD_CHECK();
652   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
653                      << GLES2Util::GetStringCapability(cap) << ")");
654   bool changed = false;
655   if (!state_.SetCapabilityState(cap, true, &changed) || changed) {
656     helper_->Enable(cap);
657   }
658   CheckGLError();
659 }
660 
IsEnabled(GLenum cap)661 GLboolean GLES2Implementation::IsEnabled(GLenum cap) {
662   GPU_CLIENT_SINGLE_THREAD_CHECK();
663   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
664                      << GLES2Util::GetStringCapability(cap) << ")");
665   bool state = false;
666   if (!state_.GetEnabled(cap, &state)) {
667     typedef cmds::IsEnabled::Result Result;
668     auto result = GetResultAs<Result>();
669     if (!result) {
670       return GL_FALSE;
671     }
672     *result = 0;
673     helper_->IsEnabled(cap, GetResultShmId(), result.offset());
674     WaitForCmd();
675     state = (*result) != 0;
676   }
677 
678   GPU_CLIENT_LOG("returned " << state);
679   CheckGLError();
680   return state;
681 }
682 
GetHelper(GLenum pname,GLint * params)683 bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
684   // TODO(zmo): For all the BINDING points, there is a possibility where
685   // resources are shared among multiple contexts, that the cached points
686   // are invalid. It is not a problem for now, but once we allow resource
687   // sharing in WebGL, we need to implement a mechanism to allow correct
688   // client side binding points tracking.  crbug.com/465562.
689 
690   // ES2 parameters.
691   switch (pname) {
692     case GL_ACTIVE_TEXTURE:
693       *params = active_texture_unit_ + GL_TEXTURE0;
694       return true;
695     case GL_ARRAY_BUFFER_BINDING:
696       *params = bound_array_buffer_;
697       return true;
698     case GL_ELEMENT_ARRAY_BUFFER_BINDING:
699       *params = vertex_array_object_manager_->bound_element_array_buffer();
700       return true;
701     case GL_FRAMEBUFFER_BINDING:
702       *params = bound_framebuffer_;
703       return true;
704     case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
705       *params = capabilities_.max_combined_texture_image_units;
706       return true;
707     case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
708       *params = capabilities_.max_cube_map_texture_size;
709       return true;
710     case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
711       *params = capabilities_.max_fragment_uniform_vectors;
712       return true;
713     case GL_MAX_RENDERBUFFER_SIZE:
714       *params = capabilities_.max_renderbuffer_size;
715       return true;
716     case GL_MAX_TEXTURE_IMAGE_UNITS:
717       *params = capabilities_.max_texture_image_units;
718       return true;
719     case GL_MAX_TEXTURE_SIZE:
720       *params = capabilities_.max_texture_size;
721       return true;
722     case GL_MAX_VARYING_VECTORS:
723       *params = capabilities_.max_varying_vectors;
724       return true;
725     case GL_MAX_VERTEX_ATTRIBS:
726       *params = capabilities_.max_vertex_attribs;
727       return true;
728     case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
729       *params = capabilities_.max_vertex_texture_image_units;
730       return true;
731     case GL_MAX_VERTEX_UNIFORM_VECTORS:
732       *params = capabilities_.max_vertex_uniform_vectors;
733       return true;
734     case GL_MAX_VIEWPORT_DIMS:
735       if (capabilities_.max_viewport_width > 0 &&
736           capabilities_.max_viewport_height > 0) {
737         params[0] = capabilities_.max_viewport_width;
738         params[1] = capabilities_.max_viewport_height;
739         return true;
740       }
741       // If they are not cached on the client side yet, query the service side.
742       return false;
743     case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
744       *params = capabilities_.num_compressed_texture_formats;
745       return true;
746     case GL_NUM_SHADER_BINARY_FORMATS:
747       *params = capabilities_.num_shader_binary_formats;
748       return true;
749     case GL_RENDERBUFFER_BINDING:
750       *params = bound_renderbuffer_;
751       return true;
752     case GL_TEXTURE_BINDING_2D:
753       *params = texture_units_[active_texture_unit_].bound_texture_2d;
754       return true;
755     case GL_TEXTURE_BINDING_CUBE_MAP:
756       *params = texture_units_[active_texture_unit_].bound_texture_cube_map;
757       return true;
758 
759     // Non-standard parameters.
760     case GL_TEXTURE_BINDING_EXTERNAL_OES:
761       *params = texture_units_[active_texture_unit_].bound_texture_external_oes;
762       return true;
763     case GL_TEXTURE_BINDING_RECTANGLE_ARB:
764       *params =
765           texture_units_[active_texture_unit_].bound_texture_rectangle_arb;
766       return true;
767     case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
768       *params = bound_pixel_pack_transfer_buffer_id_;
769       return true;
770     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
771       *params = bound_pixel_unpack_transfer_buffer_id_;
772       return true;
773     case GL_READ_FRAMEBUFFER_BINDING:
774       if (capabilities_.major_version >= 3 ||
775           IsChromiumFramebufferMultisampleAvailable()) {
776         *params = bound_read_framebuffer_;
777         return true;
778       }
779       break;
780     case GL_TIMESTAMP_EXT:
781       // We convert all GPU timestamps to CPU time.
782       *params = base::saturated_cast<GLint>(
783           (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds() *
784           base::Time::kNanosecondsPerMicrosecond);
785       return true;
786     case GL_GPU_DISJOINT_EXT:
787       *params = static_cast<GLint>(query_tracker_->CheckAndResetDisjoint());
788       return true;
789 
790     case GL_VIEWPORT:
791       if (state_.viewport_width > 0 && state_.viewport_height > 0 &&
792           capabilities_.max_viewport_width > 0 &&
793           capabilities_.max_viewport_height > 0) {
794         params[0] = state_.viewport_x;
795         params[1] = state_.viewport_y;
796         params[2] =
797             std::min(state_.viewport_width, capabilities_.max_viewport_width);
798         params[3] =
799             std::min(state_.viewport_height, capabilities_.max_viewport_height);
800         return true;
801       }
802       // If they haven't been cached on the client side, go to service side
803       // to query the underlying driver.
804       return false;
805 
806     // Non-cached parameters.
807     case GL_ALIASED_LINE_WIDTH_RANGE:
808     case GL_ALIASED_POINT_SIZE_RANGE:
809     case GL_ALPHA_BITS:
810     case GL_BLEND:
811     case GL_BLEND_COLOR:
812     case GL_BLEND_DST_ALPHA:
813     case GL_BLEND_DST_RGB:
814     case GL_BLEND_EQUATION_ALPHA:
815     case GL_BLEND_EQUATION_RGB:
816     case GL_BLEND_SRC_ALPHA:
817     case GL_BLEND_SRC_RGB:
818     case GL_BLUE_BITS:
819     case GL_COLOR_CLEAR_VALUE:
820     case GL_COLOR_WRITEMASK:
821     case GL_COMPRESSED_TEXTURE_FORMATS:
822     case GL_CULL_FACE:
823     case GL_CULL_FACE_MODE:
824     case GL_CURRENT_PROGRAM:
825     case GL_DEPTH_BITS:
826     case GL_DEPTH_CLEAR_VALUE:
827     case GL_DEPTH_FUNC:
828     case GL_DEPTH_RANGE:
829     case GL_DEPTH_TEST:
830     case GL_DEPTH_WRITEMASK:
831     case GL_DITHER:
832     case GL_FRONT_FACE:
833     case GL_GENERATE_MIPMAP_HINT:
834     case GL_GREEN_BITS:
835     case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
836     case GL_IMPLEMENTATION_COLOR_READ_TYPE:
837     case GL_LINE_WIDTH:
838     case GL_PACK_ALIGNMENT:
839     case GL_POLYGON_OFFSET_FACTOR:
840     case GL_POLYGON_OFFSET_FILL:
841     case GL_POLYGON_OFFSET_UNITS:
842     case GL_RED_BITS:
843     case GL_SAMPLE_ALPHA_TO_COVERAGE:
844     case GL_SAMPLE_BUFFERS:
845     case GL_SAMPLE_COVERAGE:
846     case GL_SAMPLE_COVERAGE_INVERT:
847     case GL_SAMPLE_COVERAGE_VALUE:
848     case GL_SAMPLES:
849     case GL_SCISSOR_BOX:
850     case GL_SCISSOR_TEST:
851     case GL_SHADER_BINARY_FORMATS:
852     case GL_SHADER_COMPILER:
853     case GL_STENCIL_BACK_FAIL:
854     case GL_STENCIL_BACK_FUNC:
855     case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
856     case GL_STENCIL_BACK_PASS_DEPTH_PASS:
857     case GL_STENCIL_BACK_REF:
858     case GL_STENCIL_BACK_VALUE_MASK:
859     case GL_STENCIL_BACK_WRITEMASK:
860     case GL_STENCIL_BITS:
861     case GL_STENCIL_CLEAR_VALUE:
862     case GL_STENCIL_FAIL:
863     case GL_STENCIL_FUNC:
864     case GL_STENCIL_PASS_DEPTH_FAIL:
865     case GL_STENCIL_PASS_DEPTH_PASS:
866     case GL_STENCIL_REF:
867     case GL_STENCIL_TEST:
868     case GL_STENCIL_VALUE_MASK:
869     case GL_STENCIL_WRITEMASK:
870     case GL_SUBPIXEL_BITS:
871     case GL_UNPACK_ALIGNMENT:
872       return false;
873     default:
874       break;
875   }
876 
877   if (capabilities_.major_version < 3) {
878     return false;
879   }
880 
881   // ES3 parameters.
882   switch (pname) {
883     case GL_COPY_READ_BUFFER_BINDING:
884       *params = bound_copy_read_buffer_;
885       return true;
886     case GL_COPY_WRITE_BUFFER_BINDING:
887       *params = bound_copy_write_buffer_;
888       return true;
889     case GL_MAJOR_VERSION:
890       *params = capabilities_.major_version;
891       return true;
892     case GL_MAX_3D_TEXTURE_SIZE:
893       *params = capabilities_.max_3d_texture_size;
894       return true;
895     case GL_MAX_ARRAY_TEXTURE_LAYERS:
896       *params = capabilities_.max_array_texture_layers;
897       return true;
898     case GL_MAX_COLOR_ATTACHMENTS:
899       *params = capabilities_.max_color_attachments;
900       return true;
901     case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
902       *params = static_cast<GLint>(
903           capabilities_.max_combined_fragment_uniform_components);
904       return true;
905     case GL_MAX_COMBINED_UNIFORM_BLOCKS:
906       *params = capabilities_.max_combined_uniform_blocks;
907       return true;
908     case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
909       *params = static_cast<GLint>(
910           capabilities_.max_combined_vertex_uniform_components);
911       return true;
912     case GL_MAX_DRAW_BUFFERS:
913       *params = capabilities_.max_draw_buffers;
914       return true;
915     case GL_MAX_ELEMENT_INDEX:
916       *params = static_cast<GLint>(capabilities_.max_element_index);
917       return true;
918     case GL_MAX_ELEMENTS_INDICES:
919       *params = capabilities_.max_elements_indices;
920       return true;
921     case GL_MAX_ELEMENTS_VERTICES:
922       *params = capabilities_.max_elements_vertices;
923       return true;
924     case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
925       *params = capabilities_.max_fragment_input_components;
926       return true;
927     case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
928       *params = capabilities_.max_fragment_uniform_blocks;
929       return true;
930     case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
931       *params = capabilities_.max_fragment_uniform_components;
932       return true;
933     case GL_MAX_PROGRAM_TEXEL_OFFSET:
934       *params = capabilities_.max_program_texel_offset;
935       return true;
936     case GL_MAX_SAMPLES:
937       *params = capabilities_.max_samples;
938       return true;
939     case GL_MAX_SERVER_WAIT_TIMEOUT:
940       *params = static_cast<GLint>(capabilities_.max_server_wait_timeout);
941       return true;
942     case GL_MAX_TEXTURE_LOD_BIAS:
943       *params = static_cast<GLint>(capabilities_.max_texture_lod_bias);
944       return true;
945     case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
946       *params = capabilities_.max_transform_feedback_interleaved_components;
947       return true;
948     case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
949       *params = capabilities_.max_transform_feedback_separate_attribs;
950       return true;
951     case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
952       *params = capabilities_.max_transform_feedback_separate_components;
953       return true;
954     case GL_MAX_UNIFORM_BLOCK_SIZE:
955       *params = static_cast<GLint>(capabilities_.max_uniform_block_size);
956       return true;
957     case GL_MAX_UNIFORM_BUFFER_BINDINGS:
958       *params = capabilities_.max_uniform_buffer_bindings;
959       return true;
960     case GL_MAX_VARYING_COMPONENTS:
961       *params = capabilities_.max_varying_components;
962       return true;
963     case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
964       *params = capabilities_.max_vertex_output_components;
965       return true;
966     case GL_MAX_VERTEX_UNIFORM_BLOCKS:
967       *params = capabilities_.max_vertex_uniform_blocks;
968       return true;
969     case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
970       *params = capabilities_.max_vertex_uniform_components;
971       return true;
972     case GL_MIN_PROGRAM_TEXEL_OFFSET:
973       *params = capabilities_.min_program_texel_offset;
974       return true;
975     case GL_MINOR_VERSION:
976       *params = capabilities_.minor_version;
977       return true;
978     case GL_NUM_EXTENSIONS:
979       UpdateCachedExtensionsIfNeeded();
980       *params = cached_extensions_.size();
981       return true;
982     case GL_NUM_PROGRAM_BINARY_FORMATS:
983       *params = capabilities_.num_program_binary_formats;
984       return true;
985     case GL_PACK_SKIP_PIXELS:
986       *params = pack_skip_pixels_;
987       return true;
988     case GL_PACK_SKIP_ROWS:
989       *params = pack_skip_rows_;
990       return true;
991     case GL_PIXEL_PACK_BUFFER_BINDING:
992       *params = bound_pixel_pack_buffer_;
993       return true;
994     case GL_PIXEL_UNPACK_BUFFER_BINDING:
995       *params = bound_pixel_unpack_buffer_;
996       return true;
997     case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
998       *params = bound_transform_feedback_buffer_;
999       return true;
1000     case GL_UNIFORM_BUFFER_BINDING:
1001       *params = bound_uniform_buffer_;
1002       return true;
1003     case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
1004       *params = capabilities_.uniform_buffer_offset_alignment;
1005       return true;
1006     case GL_UNPACK_SKIP_IMAGES:
1007       *params = unpack_skip_images_;
1008       return true;
1009     case GL_UNPACK_SKIP_PIXELS:
1010       *params = unpack_skip_pixels_;
1011       return true;
1012     case GL_UNPACK_SKIP_ROWS:
1013       *params = unpack_skip_rows_;
1014       return true;
1015 
1016     // Non-cached ES3 parameters.
1017     case GL_DRAW_BUFFER0:
1018     case GL_DRAW_BUFFER1:
1019     case GL_DRAW_BUFFER2:
1020     case GL_DRAW_BUFFER3:
1021     case GL_DRAW_BUFFER4:
1022     case GL_DRAW_BUFFER5:
1023     case GL_DRAW_BUFFER6:
1024     case GL_DRAW_BUFFER7:
1025     case GL_DRAW_BUFFER8:
1026     case GL_DRAW_BUFFER9:
1027     case GL_DRAW_BUFFER10:
1028     case GL_DRAW_BUFFER11:
1029     case GL_DRAW_BUFFER12:
1030     case GL_DRAW_BUFFER13:
1031     case GL_DRAW_BUFFER14:
1032     case GL_DRAW_BUFFER15:
1033     case GL_DRAW_FRAMEBUFFER_BINDING:
1034     case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
1035     case GL_PACK_ROW_LENGTH:
1036     case GL_PRIMITIVE_RESTART_FIXED_INDEX:
1037     case GL_PROGRAM_BINARY_FORMATS:
1038     case GL_RASTERIZER_DISCARD:
1039     case GL_READ_BUFFER:
1040     case GL_READ_FRAMEBUFFER_BINDING:
1041     case GL_SAMPLER_BINDING:
1042     case GL_TEXTURE_BINDING_2D_ARRAY:
1043     case GL_TEXTURE_BINDING_3D:
1044     case GL_TRANSFORM_FEEDBACK_BINDING:
1045     case GL_TRANSFORM_FEEDBACK_ACTIVE:
1046     case GL_TRANSFORM_FEEDBACK_PAUSED:
1047     case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1048     case GL_TRANSFORM_FEEDBACK_BUFFER_START:
1049     case GL_UNIFORM_BUFFER_SIZE:
1050     case GL_UNIFORM_BUFFER_START:
1051     case GL_UNPACK_IMAGE_HEIGHT:
1052     case GL_UNPACK_ROW_LENGTH:
1053     case GL_VERTEX_ARRAY_BINDING:
1054       return false;
1055     default:
1056       break;
1057   }
1058 
1059   if (capabilities_.minor_version < 1) {
1060     return false;
1061   }
1062 
1063   // ES31 parameters.
1064   switch (pname) {
1065     case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
1066       *params = capabilities_.max_atomic_counter_buffer_bindings;
1067       return true;
1068     case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
1069       *params = capabilities_.max_shader_storage_buffer_bindings;
1070       return true;
1071     case GL_ATOMIC_COUNTER_BUFFER_BINDING:
1072       *params = bound_atomic_counter_buffer_;
1073       return true;
1074     case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
1075       *params = bound_dispatch_indirect_buffer_;
1076       return true;
1077     case GL_DRAW_INDIRECT_BUFFER_BINDING:
1078       *params = bound_draw_indirect_buffer_;
1079       return true;
1080     case GL_SHADER_STORAGE_BUFFER_BINDING:
1081       *params = bound_shader_storage_buffer_;
1082       return true;
1083     case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
1084       *params = capabilities_.shader_storage_buffer_offset_alignment;
1085       return true;
1086 
1087     // Non-cached ES31 parameters.
1088     case GL_ATOMIC_COUNTER_BUFFER_SIZE:
1089     case GL_ATOMIC_COUNTER_BUFFER_START:
1090     case GL_SHADER_STORAGE_BUFFER_SIZE:
1091     case GL_SHADER_STORAGE_BUFFER_START:
1092       return false;
1093     default:
1094       return false;
1095   }
1096 }
1097 
GetBooleanvHelper(GLenum pname,GLboolean * params)1098 bool GLES2Implementation::GetBooleanvHelper(GLenum pname, GLboolean* params) {
1099   // TODO(gman): Make this handle pnames that return more than 1 value.
1100   GLint value;
1101   if (!GetHelper(pname, &value)) {
1102     return false;
1103   }
1104   *params = static_cast<GLboolean>(value);
1105   return true;
1106 }
1107 
GetFloatvHelper(GLenum pname,GLfloat * params)1108 bool GLES2Implementation::GetFloatvHelper(GLenum pname, GLfloat* params) {
1109   // TODO(gman): Make this handle pnames that return more than 1 value.
1110   switch (pname) {
1111     case GL_MAX_TEXTURE_LOD_BIAS:
1112       *params = capabilities_.max_texture_lod_bias;
1113       return true;
1114     default:
1115       break;
1116   }
1117   GLint value;
1118   if (!GetHelper(pname, &value)) {
1119     return false;
1120   }
1121   *params = static_cast<GLfloat>(value);
1122   return true;
1123 }
1124 
GetInteger64vHelper(GLenum pname,GLint64 * params)1125 bool GLES2Implementation::GetInteger64vHelper(GLenum pname, GLint64* params) {
1126   switch (pname) {
1127     case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
1128       *params = capabilities_.max_combined_fragment_uniform_components;
1129       return true;
1130     case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
1131       *params = capabilities_.max_combined_vertex_uniform_components;
1132       return true;
1133     case GL_MAX_ELEMENT_INDEX:
1134       *params = capabilities_.max_element_index;
1135       return true;
1136     case GL_MAX_SERVER_WAIT_TIMEOUT:
1137       *params = capabilities_.max_server_wait_timeout;
1138       return true;
1139     case GL_MAX_UNIFORM_BLOCK_SIZE:
1140       *params = capabilities_.max_uniform_block_size;
1141       return true;
1142     case GL_TIMESTAMP_EXT:
1143       // We convert all GPU timestamps to CPU time.
1144       *params = (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds() *
1145                 base::Time::kNanosecondsPerMicrosecond;
1146       return true;
1147     default:
1148       break;
1149   }
1150   GLint value;
1151   if (!GetHelper(pname, &value)) {
1152     return false;
1153   }
1154   *params = static_cast<GLint64>(value);
1155   return true;
1156 }
1157 
GetIntegervHelper(GLenum pname,GLint * params)1158 bool GLES2Implementation::GetIntegervHelper(GLenum pname, GLint* params) {
1159   return GetHelper(pname, params);
1160 }
1161 
GetIntegeri_vHelper(GLenum pname,GLuint index,GLint * data)1162 bool GLES2Implementation::GetIntegeri_vHelper(GLenum pname,
1163                                               GLuint index,
1164                                               GLint* data) {
1165   // TODO(zmo): Implement client side caching.
1166   return false;
1167 }
1168 
GetInteger64i_vHelper(GLenum pname,GLuint index,GLint64 * data)1169 bool GLES2Implementation::GetInteger64i_vHelper(GLenum pname,
1170                                                 GLuint index,
1171                                                 GLint64* data) {
1172   // TODO(zmo): Implement client side caching.
1173   return false;
1174 }
1175 
GetInternalformativHelper(GLenum target,GLenum format,GLenum pname,GLsizei bufSize,GLint * params)1176 bool GLES2Implementation::GetInternalformativHelper(GLenum target,
1177                                                     GLenum format,
1178                                                     GLenum pname,
1179                                                     GLsizei bufSize,
1180                                                     GLint* params) {
1181   // TODO(zmo): Implement the client side caching.
1182   return false;
1183 }
1184 
GetSyncivHelper(GLsync sync,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * values)1185 bool GLES2Implementation::GetSyncivHelper(GLsync sync,
1186                                           GLenum pname,
1187                                           GLsizei bufsize,
1188                                           GLsizei* length,
1189                                           GLint* values) {
1190   GLint value = 0;
1191   switch (pname) {
1192     case GL_OBJECT_TYPE:
1193       value = GL_SYNC_FENCE;
1194       break;
1195     case GL_SYNC_CONDITION:
1196       value = GL_SYNC_GPU_COMMANDS_COMPLETE;
1197       break;
1198     case GL_SYNC_FLAGS:
1199       value = 0;
1200       break;
1201     default:
1202       return false;
1203   }
1204   if (bufsize > 0) {
1205     DCHECK(values);
1206     *values = value;
1207   }
1208   if (length) {
1209     *length = 1;
1210   }
1211   return true;
1212 }
1213 
GetQueryObjectValueHelper(const char * function_name,GLuint id,GLenum pname,GLuint64 * params)1214 bool GLES2Implementation::GetQueryObjectValueHelper(const char* function_name,
1215                                                     GLuint id,
1216                                                     GLenum pname,
1217                                                     GLuint64* params) {
1218   GPU_CLIENT_SINGLE_THREAD_CHECK();
1219   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper(" << id
1220                      << ", " << GLES2Util::GetStringQueryObjectParameter(pname)
1221                      << ", " << static_cast<const void*>(params) << ")");
1222 
1223   QueryTracker::Query* query = query_tracker_->GetQuery(id);
1224   if (!query) {
1225     SetGLError(GL_INVALID_OPERATION, function_name, "unknown query id");
1226     return false;
1227   }
1228 
1229   if (query->Active()) {
1230     SetGLError(GL_INVALID_OPERATION, function_name,
1231                "query active. Did you call glEndQueryEXT?");
1232     return false;
1233   }
1234 
1235   if (query->NeverUsed()) {
1236     SetGLError(GL_INVALID_OPERATION, function_name,
1237                "Never used. Did you call glBeginQueryEXT?");
1238     return false;
1239   }
1240 
1241   bool valid_value = false;
1242   const bool flush_if_pending =
1243       pname != GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT;
1244   switch (pname) {
1245     case GL_QUERY_RESULT_EXT:
1246       if (!query->CheckResultsAvailable(helper_, flush_if_pending)) {
1247         helper_->WaitForToken(query->token());
1248         if (!query->CheckResultsAvailable(helper_, flush_if_pending)) {
1249           FinishHelper();
1250           CHECK(query->CheckResultsAvailable(helper_, flush_if_pending));
1251         }
1252       }
1253       *params = query->GetResult();
1254       valid_value = true;
1255       break;
1256     case GL_QUERY_RESULT_AVAILABLE_EXT:
1257       *params = query->CheckResultsAvailable(helper_, flush_if_pending);
1258       valid_value = true;
1259       break;
1260     case GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT:
1261       *params = query->CheckResultsAvailable(helper_, flush_if_pending);
1262       valid_value = true;
1263       break;
1264     default:
1265       SetGLErrorInvalidEnum(function_name, pname, "pname");
1266       break;
1267   }
1268   GPU_CLIENT_LOG("  " << *params);
1269   CheckGLError();
1270   return valid_value;
1271 }
1272 
GetMaxValueInBufferCHROMIUMHelper(GLuint buffer_id,GLsizei count,GLenum type,GLuint offset)1273 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(GLuint buffer_id,
1274                                                               GLsizei count,
1275                                                               GLenum type,
1276                                                               GLuint offset) {
1277   typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result;
1278   auto result = GetResultAs<Result>();
1279   if (!result) {
1280     return 0;
1281   }
1282   *result = 0;
1283   helper_->GetMaxValueInBufferCHROMIUM(buffer_id, count, type, offset,
1284                                        GetResultShmId(), result.offset());
1285   WaitForCmd();
1286   return *result;
1287 }
1288 
GetMaxValueInBufferCHROMIUM(GLuint buffer_id,GLsizei count,GLenum type,GLuint offset)1289 GLuint GLES2Implementation::GetMaxValueInBufferCHROMIUM(GLuint buffer_id,
1290                                                         GLsizei count,
1291                                                         GLenum type,
1292                                                         GLuint offset) {
1293   GPU_CLIENT_SINGLE_THREAD_CHECK();
1294   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1295                      << buffer_id << ", " << count << ", "
1296                      << GLES2Util::GetStringGetMaxIndexType(type) << ", "
1297                      << offset << ")");
1298   GLuint result =
1299       GetMaxValueInBufferCHROMIUMHelper(buffer_id, count, type, offset);
1300   GPU_CLIENT_LOG("returned " << result);
1301   CheckGLError();
1302   return result;
1303 }
1304 
RestoreElementAndArrayBuffers(bool restore)1305 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore) {
1306   if (restore) {
1307     RestoreArrayBuffer(restore);
1308     // Restore the element array binding.
1309     // We only need to restore it if it wasn't a client side array.
1310     if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
1311       helper_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1312     }
1313   }
1314 }
1315 
RestoreArrayBuffer(bool restore)1316 void GLES2Implementation::RestoreArrayBuffer(bool restore) {
1317   if (restore) {
1318     // Restore the user's current binding.
1319     helper_->BindBuffer(GL_ARRAY_BUFFER, bound_array_buffer_);
1320   }
1321 }
1322 
DrawElements(GLenum mode,GLsizei count,GLenum type,const void * indices)1323 void GLES2Implementation::DrawElements(GLenum mode,
1324                                        GLsizei count,
1325                                        GLenum type,
1326                                        const void* indices) {
1327   GPU_CLIENT_SINGLE_THREAD_CHECK();
1328   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1329                      << GLES2Util::GetStringDrawMode(mode) << ", " << count
1330                      << ", " << GLES2Util::GetStringIndexType(type) << ", "
1331                      << static_cast<const void*>(indices) << ")");
1332   DrawElementsImpl(mode, count, type, indices, "glDrawElements");
1333 }
1334 
DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const void * indices)1335 void GLES2Implementation::DrawRangeElements(GLenum mode,
1336                                             GLuint start,
1337                                             GLuint end,
1338                                             GLsizei count,
1339                                             GLenum type,
1340                                             const void* indices) {
1341   GPU_CLIENT_SINGLE_THREAD_CHECK();
1342   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1343                      << GLES2Util::GetStringDrawMode(mode) << ", " << start
1344                      << ", " << end << ", " << count << ", "
1345                      << GLES2Util::GetStringIndexType(type) << ", "
1346                      << static_cast<const void*>(indices) << ")");
1347   if (end < start) {
1348     SetGLError(GL_INVALID_VALUE, "glDrawRangeElements", "end < start");
1349     return;
1350   }
1351   DrawElementsImpl(mode, count, type, indices, "glDrawRangeElements");
1352 }
1353 
DrawElementsImpl(GLenum mode,GLsizei count,GLenum type,const void * indices,const char * func_name)1354 void GLES2Implementation::DrawElementsImpl(GLenum mode,
1355                                            GLsizei count,
1356                                            GLenum type,
1357                                            const void* indices,
1358                                            const char* func_name) {
1359   if (count < 0) {
1360     SetGLError(GL_INVALID_VALUE, func_name, "count < 0");
1361     return;
1362   }
1363   bool simulated = false;
1364   GLuint offset = ToGLuint(indices);
1365   if (count > 0) {
1366     if (vertex_array_object_manager_->bound_element_array_buffer() != 0 &&
1367         !ValidateOffset(func_name, reinterpret_cast<GLintptr>(indices))) {
1368       return;
1369     }
1370     if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
1371             func_name, this, helper_, count, type, 0, indices, &offset,
1372             &simulated)) {
1373       return;
1374     }
1375   }
1376   helper_->DrawElements(mode, count, type, offset);
1377   RestoreElementAndArrayBuffers(simulated);
1378   CheckGLError();
1379 }
1380 
DrawElementsIndirect(GLenum mode,GLenum type,const void * offset)1381 void GLES2Implementation::DrawElementsIndirect(GLenum mode,
1382                                                GLenum type,
1383                                                const void* offset) {
1384   GPU_CLIENT_SINGLE_THREAD_CHECK();
1385   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsIndirect("
1386                      << GLES2Util::GetStringDrawMode(mode) << ", "
1387                      << GLES2Util::GetStringIndexType(type) << ", " << offset
1388                      << ")");
1389   if (!ValidateOffset("glDrawElementsIndirect",
1390                       reinterpret_cast<GLintptr>(offset))) {
1391     return;
1392   }
1393   // This is for WebGL 2.0 Compute which doesn't support client side arrays
1394   if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
1395     SetGLError(GL_INVALID_OPERATION, "glDrawElementsIndirect",
1396                "No element array buffer");
1397     return;
1398   }
1399   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
1400     SetGLError(GL_INVALID_OPERATION, "glDrawElementsIndirect",
1401                "Missing array buffer for vertex attribute");
1402     return;
1403   }
1404   helper_->DrawElementsIndirect(mode, type, ToGLuint(offset));
1405   CheckGLError();
1406 }
1407 
Flush()1408 void GLES2Implementation::Flush() {
1409   GPU_CLIENT_SINGLE_THREAD_CHECK();
1410   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1411   flush_id_ = GenerateNextFlushId();
1412   // Insert the cmd to call glFlush
1413   helper_->Flush();
1414   FlushHelper();
1415 }
1416 
1417 // InterfaceBase implementation.
GenSyncTokenCHROMIUM(GLbyte * sync_token)1418 void GLES2Implementation::GenSyncTokenCHROMIUM(GLbyte* sync_token) {
1419   ImplementationBase::GenSyncToken(sync_token);
1420 }
GenUnverifiedSyncTokenCHROMIUM(GLbyte * sync_token)1421 void GLES2Implementation::GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) {
1422   ImplementationBase::GenUnverifiedSyncToken(sync_token);
1423 }
VerifySyncTokensCHROMIUM(GLbyte ** sync_tokens,GLsizei count)1424 void GLES2Implementation::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
1425                                                    GLsizei count) {
1426   ImplementationBase::VerifySyncTokens(sync_tokens, count);
1427 }
WaitSyncTokenCHROMIUM(const GLbyte * sync_token)1428 void GLES2Implementation::WaitSyncTokenCHROMIUM(const GLbyte* sync_token) {
1429   ImplementationBase::WaitSyncToken(sync_token);
1430 }
1431 
1432 // ImplementationBase implementation.
IssueShallowFlush()1433 void GLES2Implementation::IssueShallowFlush() {
1434   GPU_CLIENT_SINGLE_THREAD_CHECK();
1435   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1436   flush_id_ = GenerateNextFlushId();
1437   FlushHelper();
1438 }
1439 
ShallowFlushCHROMIUM()1440 void GLES2Implementation::ShallowFlushCHROMIUM() {
1441   IssueShallowFlush();
1442 }
1443 
FlushHelper()1444 void GLES2Implementation::FlushHelper() {
1445   // Flush our command buffer
1446   // (tell the service to execute up to the flush cmd.)
1447   helper_->CommandBufferHelper::Flush();
1448 
1449   if (aggressively_free_resources_)
1450     FreeEverything();
1451 }
1452 
OrderingBarrierCHROMIUM()1453 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1454   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1455   // Flush command buffer at the GPU channel level.  May be implemented as
1456   // Flush().
1457   helper_->CommandBufferHelper::OrderingBarrier();
1458 }
1459 
Finish()1460 void GLES2Implementation::Finish() {
1461   GPU_CLIENT_SINGLE_THREAD_CHECK();
1462   flush_id_ = GenerateNextFlushId();
1463   FinishHelper();
1464 }
1465 
ShallowFinishCHROMIUM()1466 void GLES2Implementation::ShallowFinishCHROMIUM() {
1467   GPU_CLIENT_SINGLE_THREAD_CHECK();
1468   TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1469   flush_id_ = GenerateNextFlushId();
1470   // Flush our command buffer (tell the service to execute up to the flush cmd
1471   // and don't return until it completes).
1472   helper_->CommandBufferHelper::Finish();
1473 
1474   if (aggressively_free_resources_)
1475     FreeEverything();
1476 }
1477 
FinishHelper()1478 void GLES2Implementation::FinishHelper() {
1479   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1480   TRACE_EVENT0("gpu", "GLES2::Finish");
1481   // Insert the cmd to call glFinish
1482   helper_->Finish();
1483   // Finish our command buffer
1484   // (tell the service to execute up to the Finish cmd and wait for it to
1485   // execute.)
1486   helper_->CommandBufferHelper::Finish();
1487 
1488   if (aggressively_free_resources_)
1489     FreeEverything();
1490 }
1491 
GetLastFlushIdCHROMIUM()1492 GLuint GLES2Implementation::GetLastFlushIdCHROMIUM() {
1493   GPU_CLIENT_SINGLE_THREAD_CHECK();
1494   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetLastFlushIdCHROMIUM()");
1495   return flush_id_;
1496 }
1497 
SwapBuffers(uint64_t swap_id,GLbitfield flags)1498 void GLES2Implementation::SwapBuffers(uint64_t swap_id, GLbitfield flags) {
1499   GPU_CLIENT_SINGLE_THREAD_CHECK();
1500   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1501   // TODO(piman): Strictly speaking we'd want to insert the token after the
1502   // swap, but the state update with the updated token might not have happened
1503   // by the time the SwapBuffer callback gets called, forcing us to synchronize
1504   // with the GPU process more than needed. So instead, make it happen before.
1505   // All it means is that we could be slightly looser on the kMaxSwapBuffers
1506   // semantics if the client doesn't use the callback mechanism, and by chance
1507   // the scheduler yields between the InsertToken and the SwapBuffers.
1508   swap_buffers_tokens_.push(helper_->InsertToken());
1509   helper_->SwapBuffers(swap_id, flags);
1510   helper_->CommandBufferHelper::Flush();
1511   // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1512   // compensate for TODO above.
1513   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
1514     helper_->WaitForToken(swap_buffers_tokens_.front());
1515     swap_buffers_tokens_.pop();
1516   }
1517 }
1518 
SwapBuffersWithBoundsCHROMIUM(uint64_t swap_id,GLsizei count,const GLint * rects,GLbitfield flags)1519 void GLES2Implementation::SwapBuffersWithBoundsCHROMIUM(uint64_t swap_id,
1520                                                         GLsizei count,
1521                                                         const GLint* rects,
1522                                                         GLbitfield flags) {
1523   GPU_CLIENT_SINGLE_THREAD_CHECK();
1524   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffersWithBoundsCHROMIUM("
1525                      << count << ", " << static_cast<const void*>(rects)
1526                      << ")");
1527   GPU_CLIENT_LOG_CODE_BLOCK({
1528     for (GLsizei i = 0; i < count; ++i) {
1529       GPU_CLIENT_LOG("  " << i << ": " << rects[0 + i * 4] << ", "
1530                           << rects[1 + i * 4] << ", " << rects[2 + i * 4]
1531                           << ", " << rects[3 + i * 4]);
1532     }
1533   });
1534   if (count < 0) {
1535     SetGLError(GL_INVALID_VALUE, "glSwapBuffersWithBoundsCHROMIUM",
1536                "count < 0");
1537     return;
1538   }
1539 
1540   // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
1541   swap_buffers_tokens_.push(helper_->InsertToken());
1542   helper_->SwapBuffersWithBoundsCHROMIUMImmediate(swap_id, count, rects, flags);
1543   helper_->CommandBufferHelper::Flush();
1544   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
1545     helper_->WaitForToken(swap_buffers_tokens_.front());
1546     swap_buffers_tokens_.pop();
1547   }
1548 }
1549 
BindAttribLocation(GLuint program,GLuint index,const char * name)1550 void GLES2Implementation::BindAttribLocation(GLuint program,
1551                                              GLuint index,
1552                                              const char* name) {
1553   GPU_CLIENT_SINGLE_THREAD_CHECK();
1554   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation(" << program
1555                      << ", " << index << ", " << name << ")");
1556   SetBucketAsString(kResultBucketId, name);
1557   helper_->BindAttribLocationBucket(program, index, kResultBucketId);
1558   helper_->SetBucketSize(kResultBucketId, 0);
1559   CheckGLError();
1560 }
1561 
BindFragDataLocationEXT(GLuint program,GLuint colorName,const char * name)1562 void GLES2Implementation::BindFragDataLocationEXT(GLuint program,
1563                                                   GLuint colorName,
1564                                                   const char* name) {
1565   GPU_CLIENT_SINGLE_THREAD_CHECK();
1566   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindFragDataLocationEXT("
1567                      << program << ", " << colorName << ", " << name << ")");
1568   SetBucketAsString(kResultBucketId, name);
1569   helper_->BindFragDataLocationEXTBucket(program, colorName, kResultBucketId);
1570   helper_->SetBucketSize(kResultBucketId, 0);
1571   CheckGLError();
1572 }
1573 
BindFragDataLocationIndexedEXT(GLuint program,GLuint colorName,GLuint index,const char * name)1574 void GLES2Implementation::BindFragDataLocationIndexedEXT(GLuint program,
1575                                                          GLuint colorName,
1576                                                          GLuint index,
1577                                                          const char* name) {
1578   GPU_CLIENT_SINGLE_THREAD_CHECK();
1579   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindFragDataLocationEXT("
1580                      << program << ", " << colorName << ", " << index << ", "
1581                      << name << ")");
1582   SetBucketAsString(kResultBucketId, name);
1583   helper_->BindFragDataLocationIndexedEXTBucket(program, colorName, index,
1584                                                 kResultBucketId);
1585   helper_->SetBucketSize(kResultBucketId, 0);
1586   CheckGLError();
1587 }
1588 
BindUniformLocationCHROMIUM(GLuint program,GLint location,const char * name)1589 void GLES2Implementation::BindUniformLocationCHROMIUM(GLuint program,
1590                                                       GLint location,
1591                                                       const char* name) {
1592   GPU_CLIENT_SINGLE_THREAD_CHECK();
1593   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1594                      << program << ", " << location << ", " << name << ")");
1595   SetBucketAsString(kResultBucketId, name);
1596   helper_->BindUniformLocationCHROMIUMBucket(program, location,
1597                                              kResultBucketId);
1598   helper_->SetBucketSize(kResultBucketId, 0);
1599   CheckGLError();
1600 }
1601 
GetVertexAttribPointerv(GLuint index,GLenum pname,void ** ptr)1602 void GLES2Implementation::GetVertexAttribPointerv(GLuint index,
1603                                                   GLenum pname,
1604                                                   void** ptr) {
1605   GPU_CLIENT_SINGLE_THREAD_CHECK();
1606   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer(" << index
1607                      << ", " << GLES2Util::GetStringVertexPointer(pname) << ", "
1608                      << static_cast<void*>(ptr) << ")");
1609   GPU_CLIENT_LOG_CODE_BLOCK(int32_t num_results = 1);
1610   if (!vertex_array_object_manager_->GetAttribPointer(index, pname, ptr)) {
1611     TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1612     typedef cmds::GetVertexAttribPointerv::Result Result;
1613     auto result = GetResultAs<Result>();
1614     if (!result) {
1615       return;
1616     }
1617     result->SetNumResults(0);
1618     helper_->GetVertexAttribPointerv(index, pname, GetResultShmId(),
1619                                      result.offset());
1620     WaitForCmd();
1621     result->CopyResult(ptr);
1622     GPU_CLIENT_LOG_CODE_BLOCK(num_results = result->GetNumResults());
1623   }
1624   GPU_CLIENT_LOG_CODE_BLOCK({
1625     for (int32_t i = 0; i < num_results; ++i) {
1626       GPU_CLIENT_LOG("  " << i << ": " << ptr[i]);
1627     }
1628   });
1629   CheckGLError();
1630 }
1631 
DeleteProgramHelper(GLuint program)1632 bool GLES2Implementation::DeleteProgramHelper(GLuint program) {
1633   if (!GetIdHandler(SharedIdNamespaces::kProgramsAndShaders)
1634            ->FreeIds(this, 1, &program,
1635                      &GLES2Implementation::DeleteProgramStub)) {
1636     SetGLError(GL_INVALID_VALUE, "glDeleteProgram",
1637                "id not created by this context.");
1638     return false;
1639   }
1640   if (program == current_program_) {
1641     current_program_ = 0;
1642   }
1643   return true;
1644 }
1645 
DeleteProgramStub(GLsizei n,const GLuint * programs)1646 void GLES2Implementation::DeleteProgramStub(GLsizei n, const GLuint* programs) {
1647   DCHECK_EQ(1, n);
1648   share_group_->program_info_manager()->DeleteInfo(programs[0]);
1649   helper_->DeleteProgram(programs[0]);
1650 }
1651 
DeleteShaderHelper(GLuint shader)1652 bool GLES2Implementation::DeleteShaderHelper(GLuint shader) {
1653   if (!GetIdHandler(SharedIdNamespaces::kProgramsAndShaders)
1654            ->FreeIds(this, 1, &shader,
1655                      &GLES2Implementation::DeleteShaderStub)) {
1656     SetGLError(GL_INVALID_VALUE, "glDeleteShader",
1657                "id not created by this context.");
1658     return false;
1659   }
1660   return true;
1661 }
1662 
DeleteShaderStub(GLsizei n,const GLuint * shaders)1663 void GLES2Implementation::DeleteShaderStub(GLsizei n, const GLuint* shaders) {
1664   DCHECK_EQ(1, n);
1665   share_group_->program_info_manager()->DeleteInfo(shaders[0]);
1666   helper_->DeleteShader(shaders[0]);
1667 }
1668 
DeleteSyncHelper(GLsync sync)1669 void GLES2Implementation::DeleteSyncHelper(GLsync sync) {
1670   GLuint sync_uint = ToGLuint(sync);
1671   if (!GetIdHandler(SharedIdNamespaces::kSyncs)
1672            ->FreeIds(this, 1, &sync_uint,
1673                      &GLES2Implementation::DeleteSyncStub)) {
1674     SetGLError(GL_INVALID_VALUE, "glDeleteSync",
1675                "id not created by this context.");
1676   }
1677 }
1678 
DeleteSyncStub(GLsizei n,const GLuint * syncs)1679 void GLES2Implementation::DeleteSyncStub(GLsizei n, const GLuint* syncs) {
1680   DCHECK_EQ(1, n);
1681   helper_->DeleteSync(syncs[0]);
1682 }
1683 
GetAttribLocationHelper(GLuint program,const char * name)1684 GLint GLES2Implementation::GetAttribLocationHelper(GLuint program,
1685                                                    const char* name) {
1686   typedef cmds::GetAttribLocation::Result Result;
1687   SetBucketAsCString(kResultBucketId, name);
1688   auto result = GetResultAs<Result>();
1689   if (!result) {
1690     return -1;
1691   }
1692   *result = -1;
1693   helper_->GetAttribLocation(program, kResultBucketId, GetResultShmId(),
1694                              result.offset());
1695   WaitForCmd();
1696   helper_->SetBucketSize(kResultBucketId, 0);
1697   return *result;
1698 }
1699 
GetAttribLocation(GLuint program,const char * name)1700 GLint GLES2Implementation::GetAttribLocation(GLuint program, const char* name) {
1701   GPU_CLIENT_SINGLE_THREAD_CHECK();
1702   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1703                      << ", " << name << ")");
1704   TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1705   GLint loc = share_group_->program_info_manager()->GetAttribLocation(
1706       this, program, name);
1707   GPU_CLIENT_LOG("returned " << loc);
1708   CheckGLError();
1709   return loc;
1710 }
1711 
GetUniformLocationHelper(GLuint program,const char * name)1712 GLint GLES2Implementation::GetUniformLocationHelper(GLuint program,
1713                                                     const char* name) {
1714   typedef cmds::GetUniformLocation::Result Result;
1715   SetBucketAsCString(kResultBucketId, name);
1716   auto result = GetResultAs<Result>();
1717   if (!result) {
1718     return -1;
1719   }
1720   *result = -1;
1721   helper_->GetUniformLocation(program, kResultBucketId, GetResultShmId(),
1722                               result.offset());
1723   WaitForCmd();
1724   helper_->SetBucketSize(kResultBucketId, 0);
1725   return *result;
1726 }
1727 
GetUniformLocation(GLuint program,const char * name)1728 GLint GLES2Implementation::GetUniformLocation(GLuint program,
1729                                               const char* name) {
1730   GPU_CLIENT_SINGLE_THREAD_CHECK();
1731   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1732                      << ", " << name << ")");
1733   TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1734   GLint loc = share_group_->program_info_manager()->GetUniformLocation(
1735       this, program, name);
1736   GPU_CLIENT_LOG("returned " << loc);
1737   CheckGLError();
1738   return loc;
1739 }
1740 
GetUniformIndicesHelper(GLuint program,GLsizei count,const char * const * names,GLuint * indices)1741 bool GLES2Implementation::GetUniformIndicesHelper(GLuint program,
1742                                                   GLsizei count,
1743                                                   const char* const* names,
1744                                                   GLuint* indices) {
1745   if (!PackStringsToBucket(count, names, nullptr, "glGetUniformIndices")) {
1746     return false;
1747   }
1748   typedef cmds::GetUniformIndices::Result Result;
1749   auto result = GetResultAs<Result>();
1750   if (!result) {
1751     return false;
1752   }
1753   result->SetNumResults(0);
1754   helper_->GetUniformIndices(program, kResultBucketId, GetResultShmId(),
1755                              result.offset());
1756   WaitForCmd();
1757   if (result->GetNumResults() != count) {
1758     return false;
1759   }
1760   result->CopyResult(indices);
1761   return true;
1762 }
1763 
GetUniformIndices(GLuint program,GLsizei count,const char * const * names,GLuint * indices)1764 void GLES2Implementation::GetUniformIndices(GLuint program,
1765                                             GLsizei count,
1766                                             const char* const* names,
1767                                             GLuint* indices) {
1768   GPU_CLIENT_SINGLE_THREAD_CHECK();
1769   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1770                      << ", " << count << ", " << names << ", " << indices
1771                      << ")");
1772   TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1773   if (count < 0) {
1774     SetGLError(GL_INVALID_VALUE, "glGetUniformIndices", "count < 0");
1775     return;
1776   }
1777   if (count == 0) {
1778     return;
1779   }
1780   bool success = share_group_->program_info_manager()->GetUniformIndices(
1781       this, program, count, names, indices);
1782   if (success) {
1783     GPU_CLIENT_LOG_CODE_BLOCK({
1784       for (GLsizei ii = 0; ii < count; ++ii) {
1785         GPU_CLIENT_LOG("  " << ii << ": " << indices[ii]);
1786       }
1787     });
1788   }
1789   CheckGLError();
1790 }
1791 
GetProgramivHelper(GLuint program,GLenum pname,GLint * params)1792 bool GLES2Implementation::GetProgramivHelper(GLuint program,
1793                                              GLenum pname,
1794                                              GLint* params) {
1795   bool got_value = share_group_->program_info_manager()->GetProgramiv(
1796       this, program, pname, params);
1797   GPU_CLIENT_LOG_CODE_BLOCK({
1798     if (got_value) {
1799       GPU_CLIENT_LOG("  0: " << *params);
1800     }
1801   });
1802   return got_value;
1803 }
1804 
GetFragDataIndexEXTHelper(GLuint program,const char * name)1805 GLint GLES2Implementation::GetFragDataIndexEXTHelper(GLuint program,
1806                                                      const char* name) {
1807   typedef cmds::GetFragDataIndexEXT::Result Result;
1808   SetBucketAsCString(kResultBucketId, name);
1809   auto result = GetResultAs<Result>();
1810   if (!result) {
1811     return -1;
1812   }
1813   *result = -1;
1814   helper_->GetFragDataIndexEXT(program, kResultBucketId, GetResultShmId(),
1815                                result.offset());
1816   WaitForCmd();
1817   helper_->SetBucketSize(kResultBucketId, 0);
1818   return *result;
1819 }
1820 
GetFragDataIndexEXT(GLuint program,const char * name)1821 GLint GLES2Implementation::GetFragDataIndexEXT(GLuint program,
1822                                                const char* name) {
1823   GPU_CLIENT_SINGLE_THREAD_CHECK();
1824   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataIndexEXT(" << program
1825                      << ", " << name << ")");
1826   TRACE_EVENT0("gpu", "GLES2::GetFragDataIndexEXT");
1827   GLint loc = share_group_->program_info_manager()->GetFragDataIndex(
1828       this, program, name);
1829   GPU_CLIENT_LOG("returned " << loc);
1830   CheckGLError();
1831   return loc;
1832 }
1833 
GetFragDataLocationHelper(GLuint program,const char * name)1834 GLint GLES2Implementation::GetFragDataLocationHelper(GLuint program,
1835                                                      const char* name) {
1836   typedef cmds::GetFragDataLocation::Result Result;
1837   SetBucketAsCString(kResultBucketId, name);
1838   auto result = GetResultAs<Result>();
1839   if (!result) {
1840     return -1;
1841   }
1842   *result = -1;
1843   helper_->GetFragDataLocation(program, kResultBucketId, GetResultShmId(),
1844                                result.offset());
1845   WaitForCmd();
1846   helper_->SetBucketSize(kResultBucketId, 0);
1847   return *result;
1848 }
1849 
GetFragDataLocation(GLuint program,const char * name)1850 GLint GLES2Implementation::GetFragDataLocation(GLuint program,
1851                                                const char* name) {
1852   GPU_CLIENT_SINGLE_THREAD_CHECK();
1853   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation(" << program
1854                      << ", " << name << ")");
1855   TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1856   GLint loc = share_group_->program_info_manager()->GetFragDataLocation(
1857       this, program, name);
1858   GPU_CLIENT_LOG("returned " << loc);
1859   CheckGLError();
1860   return loc;
1861 }
1862 
GetUniformBlockIndexHelper(GLuint program,const char * name)1863 GLuint GLES2Implementation::GetUniformBlockIndexHelper(GLuint program,
1864                                                        const char* name) {
1865   typedef cmds::GetUniformBlockIndex::Result Result;
1866   SetBucketAsCString(kResultBucketId, name);
1867   auto result = GetResultAs<Result>();
1868   if (!result) {
1869     return GL_INVALID_INDEX;
1870   }
1871   *result = GL_INVALID_INDEX;
1872   helper_->GetUniformBlockIndex(program, kResultBucketId, GetResultShmId(),
1873                                 result.offset());
1874   WaitForCmd();
1875   helper_->SetBucketSize(kResultBucketId, 0);
1876   return *result;
1877 }
1878 
GetUniformBlockIndex(GLuint program,const char * name)1879 GLuint GLES2Implementation::GetUniformBlockIndex(GLuint program,
1880                                                  const char* name) {
1881   GPU_CLIENT_SINGLE_THREAD_CHECK();
1882   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex(" << program
1883                      << ", " << name << ")");
1884   TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1885   GLuint index = share_group_->program_info_manager()->GetUniformBlockIndex(
1886       this, program, name);
1887   GPU_CLIENT_LOG("returned " << index);
1888   CheckGLError();
1889   return index;
1890 }
1891 
GetProgramInterfaceivHelper(GLuint program,GLenum program_interface,GLenum pname,GLint * params)1892 bool GLES2Implementation::GetProgramInterfaceivHelper(GLuint program,
1893                                                       GLenum program_interface,
1894                                                       GLenum pname,
1895                                                       GLint* params) {
1896   bool success = share_group_->program_info_manager()->GetProgramInterfaceiv(
1897       this, program, program_interface, pname, params);
1898   GPU_CLIENT_LOG_CODE_BLOCK({
1899     if (success) {
1900       GPU_CLIENT_LOG("  0: " << *params);
1901     }
1902   });
1903   return success;
1904 }
1905 
GetProgramResourceIndexHelper(GLuint program,GLenum program_interface,const char * name)1906 GLuint GLES2Implementation::GetProgramResourceIndexHelper(
1907     GLuint program,
1908     GLenum program_interface,
1909     const char* name) {
1910   typedef cmds::GetProgramResourceIndex::Result Result;
1911   SetBucketAsCString(kResultBucketId, name);
1912   auto result = GetResultAs<Result>();
1913   if (!result) {
1914     return GL_INVALID_INDEX;
1915   }
1916   *result = GL_INVALID_INDEX;
1917   helper_->GetProgramResourceIndex(program, program_interface, kResultBucketId,
1918                                    GetResultShmId(), result.offset());
1919   WaitForCmd();
1920   helper_->SetBucketSize(kResultBucketId, 0);
1921   return *result;
1922 }
1923 
GetProgramResourceIndex(GLuint program,GLenum program_interface,const char * name)1924 GLuint GLES2Implementation::GetProgramResourceIndex(
1925     GLuint program,
1926     GLenum program_interface,
1927     const char* name) {
1928   GPU_CLIENT_SINGLE_THREAD_CHECK();
1929   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetProgramResourceIndex("
1930                      << program << ", " << program_interface << ", " << name
1931                      << ")");
1932   TRACE_EVENT0("gpu", "GLES2::GetProgramResourceIndex");
1933   GLuint index = share_group_->program_info_manager()->GetProgramResourceIndex(
1934       this, program, program_interface, name);
1935   GPU_CLIENT_LOG("returned " << index);
1936   CheckGLError();
1937   return index;
1938 }
1939 
GetProgramResourceNameHelper(GLuint program,GLenum program_interface,GLuint index,GLsizei bufsize,GLsizei * length,char * name)1940 bool GLES2Implementation::GetProgramResourceNameHelper(GLuint program,
1941                                                        GLenum program_interface,
1942                                                        GLuint index,
1943                                                        GLsizei bufsize,
1944                                                        GLsizei* length,
1945                                                        char* name) {
1946   DCHECK_LE(0, bufsize);
1947   // Clear the bucket so if the command fails nothing will be in it.
1948   helper_->SetBucketSize(kResultBucketId, 0);
1949   bool success = false;
1950   {
1951     // The Result pointer must be scoped to this block because it can be
1952     // invalidated below if getting result name causes the transfer buffer to be
1953     // reallocated.
1954     typedef cmds::GetProgramResourceName::Result Result;
1955     auto result = GetResultAs<Result>();
1956     if (!result) {
1957       return false;
1958     }
1959     // Set as failed so if the command fails we'll recover.
1960     *result = 0;
1961     helper_->GetProgramResourceName(program, program_interface, index,
1962                                     kResultBucketId, GetResultShmId(),
1963                                     result.offset());
1964     WaitForCmd();
1965     success = !!*result;
1966   }
1967   if (success) {
1968     GetResultNameHelper(bufsize, length, name);
1969   }
1970   return success;
1971 }
1972 
GetProgramResourceName(GLuint program,GLenum program_interface,GLuint index,GLsizei bufsize,GLsizei * length,char * name)1973 void GLES2Implementation::GetProgramResourceName(GLuint program,
1974                                                  GLenum program_interface,
1975                                                  GLuint index,
1976                                                  GLsizei bufsize,
1977                                                  GLsizei* length,
1978                                                  char* name) {
1979   GPU_CLIENT_SINGLE_THREAD_CHECK();
1980   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetProgramResourceName("
1981                      << program << ", " << program_interface << ", " << index
1982                      << ", " << bufsize << ", " << static_cast<void*>(length)
1983                      << ", " << static_cast<void*>(name) << ")");
1984   if (bufsize < 0) {
1985     SetGLError(GL_INVALID_VALUE, "glGetProgramResourceName", "bufsize < 0");
1986     return;
1987   }
1988   TRACE_EVENT0("gpu", "GLES2::GetProgramResourceName");
1989   bool success = share_group_->program_info_manager()->GetProgramResourceName(
1990       this, program, program_interface, index, bufsize, length, name);
1991   if (success && name) {
1992     GPU_CLIENT_LOG("  name: " << name);
1993   }
1994   CheckGLError();
1995 }
1996 
GetProgramResourceivHelper(GLuint program,GLenum program_interface,GLuint index,GLsizei prop_count,const GLenum * props,GLsizei bufsize,GLsizei * length,GLint * params)1997 bool GLES2Implementation::GetProgramResourceivHelper(GLuint program,
1998                                                      GLenum program_interface,
1999                                                      GLuint index,
2000                                                      GLsizei prop_count,
2001                                                      const GLenum* props,
2002                                                      GLsizei bufsize,
2003                                                      GLsizei* length,
2004                                                      GLint* params) {
2005   DCHECK_LE(0, prop_count);
2006   DCHECK_LE(0, bufsize);
2007   base::CheckedNumeric<uint32_t> bytes = prop_count;
2008   bytes *= sizeof(GLenum);
2009   if (!bytes.IsValid()) {
2010     SetGLError(GL_INVALID_VALUE, "glGetProgramResourceiv", "count overflow");
2011     return false;
2012   }
2013   SetBucketContents(kResultBucketId, props, bytes.ValueOrDefault(0));
2014   typedef cmds::GetProgramResourceiv::Result Result;
2015   auto result = GetResultAs<Result>();
2016   if (!result) {
2017     return false;
2018   }
2019   result->SetNumResults(0);
2020   helper_->GetProgramResourceiv(program, program_interface, index,
2021                                 kResultBucketId, GetResultShmId(),
2022                                 result.offset());
2023   WaitForCmd();
2024   if (length) {
2025     *length = result->GetNumResults();
2026   }
2027   if (result->GetNumResults() > 0) {
2028     if (params) {
2029       result->CopyResult(params);
2030     }
2031     GPU_CLIENT_LOG_CODE_BLOCK({
2032       for (int32_t i = 0; i < result->GetNumResults(); ++i) {
2033         GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
2034       }
2035     });
2036     return true;
2037   }
2038   return false;
2039 }
2040 
GetProgramResourceiv(GLuint program,GLenum program_interface,GLuint index,GLsizei prop_count,const GLenum * props,GLsizei bufsize,GLsizei * length,GLint * params)2041 void GLES2Implementation::GetProgramResourceiv(GLuint program,
2042                                                GLenum program_interface,
2043                                                GLuint index,
2044                                                GLsizei prop_count,
2045                                                const GLenum* props,
2046                                                GLsizei bufsize,
2047                                                GLsizei* length,
2048                                                GLint* params) {
2049   GPU_CLIENT_SINGLE_THREAD_CHECK();
2050   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetProgramResourceiv(" << program
2051                      << ", " << program_interface << ", " << index << ", "
2052                      << prop_count << ", " << static_cast<const void*>(props)
2053                      << ", " << bufsize << ", " << static_cast<void*>(length)
2054                      << ", " << static_cast<void*>(params) << ")");
2055   if (prop_count < 0) {
2056     SetGLError(GL_INVALID_VALUE, "glGetProgramResourceiv", "prop_count < 0");
2057     return;
2058   }
2059   if (bufsize < 0) {
2060     SetGLError(GL_INVALID_VALUE, "glGetProgramResourceiv", "bufsize < 0");
2061     return;
2062   }
2063   TRACE_EVENT0("gpu", "GLES2::GetProgramResourceiv");
2064   GLsizei param_count = 0;
2065   bool success = share_group_->program_info_manager()->GetProgramResourceiv(
2066       this, program, program_interface, index, prop_count, props, bufsize,
2067       &param_count, params);
2068   if (length) {
2069     *length = param_count;
2070   }
2071   if (success && params) {
2072     GPU_CLIENT_LOG_CODE_BLOCK({
2073       for (GLsizei ii = 0; ii < param_count; ++ii) {
2074         GPU_CLIENT_LOG("  " << ii << ": " << params[ii]);
2075       }
2076     });
2077   }
2078   CheckGLError();
2079 }
2080 
GetProgramResourceLocationHelper(GLuint program,GLenum program_interface,const char * name)2081 GLint GLES2Implementation::GetProgramResourceLocationHelper(
2082     GLuint program,
2083     GLenum program_interface,
2084     const char* name) {
2085   typedef cmds::GetProgramResourceLocation::Result Result;
2086   SetBucketAsCString(kResultBucketId, name);
2087   auto result = GetResultAs<Result>();
2088   if (!result) {
2089     return -1;
2090   }
2091   *result = -1;
2092   helper_->GetProgramResourceLocation(program, program_interface,
2093                                       kResultBucketId, GetResultShmId(),
2094                                       result.offset());
2095   WaitForCmd();
2096   helper_->SetBucketSize(kResultBucketId, 0);
2097   return *result;
2098 }
2099 
GetProgramResourceLocation(GLuint program,GLenum program_interface,const char * name)2100 GLint GLES2Implementation::GetProgramResourceLocation(
2101     GLuint program,
2102     GLenum program_interface,
2103     const char* name) {
2104   GPU_CLIENT_SINGLE_THREAD_CHECK();
2105   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetProgramResourceLocation("
2106                      << program << ", " << program_interface << ", " << name
2107                      << ")");
2108   TRACE_EVENT0("gpu", "GLES2::GetProgramResourceLocation");
2109   GLint location =
2110       share_group_->program_info_manager()->GetProgramResourceLocation(
2111           this, program, program_interface, name);
2112   GPU_CLIENT_LOG("returned " << location);
2113   CheckGLError();
2114   return location;
2115 }
2116 
LinkProgram(GLuint program)2117 void GLES2Implementation::LinkProgram(GLuint program) {
2118   GPU_CLIENT_SINGLE_THREAD_CHECK();
2119   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")");
2120   helper_->LinkProgram(program);
2121   share_group_->program_info_manager()->CreateInfo(program);
2122   CheckGLError();
2123 }
2124 
ShaderBinary(GLsizei n,const GLuint * shaders,GLenum binaryformat,const void * binary,GLsizei length)2125 void GLES2Implementation::ShaderBinary(GLsizei n,
2126                                        const GLuint* shaders,
2127                                        GLenum binaryformat,
2128                                        const void* binary,
2129                                        GLsizei length) {
2130   GPU_CLIENT_SINGLE_THREAD_CHECK();
2131   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n << ", "
2132                      << static_cast<const void*>(shaders) << ", "
2133                      << GLES2Util::GetStringEnum(binaryformat) << ", "
2134                      << static_cast<const void*>(binary) << ", " << length
2135                      << ")");
2136   if (n < 0) {
2137     SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0.");
2138     return;
2139   }
2140   if (length < 0) {
2141     SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0.");
2142     return;
2143   }
2144   // TODO(gman): ShaderBinary should use buckets.
2145   unsigned int shader_id_size = n * sizeof(*shaders);
2146   ScopedTransferBufferArray<GLint> buffer(shader_id_size + length, helper_,
2147                                           transfer_buffer_);
2148   if (!buffer.valid() || buffer.num_elements() != shader_id_size + length) {
2149     SetGLError(GL_OUT_OF_MEMORY, "glShaderBinary", "out of memory.");
2150     return;
2151   }
2152   void* shader_ids = buffer.elements();
2153   void* shader_data = buffer.elements() + shader_id_size;
2154   memcpy(shader_ids, shaders, shader_id_size);
2155   memcpy(shader_data, binary, length);
2156   helper_->ShaderBinary(n, buffer.shm_id(), buffer.offset(), binaryformat,
2157                         buffer.shm_id(), buffer.offset() + shader_id_size,
2158                         length);
2159   CheckGLError();
2160 }
2161 
PixelStorei(GLenum pname,GLint param)2162 void GLES2Implementation::PixelStorei(GLenum pname, GLint param) {
2163   GPU_CLIENT_SINGLE_THREAD_CHECK();
2164   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
2165                      << GLES2Util::GetStringPixelStore(pname) << ", " << param
2166                      << ")");
2167   // We have to validate before caching these parameters because we use them
2168   // to compute image sizes on the client side.
2169   switch (pname) {
2170     case GL_PACK_ALIGNMENT:
2171     case GL_UNPACK_ALIGNMENT:
2172       if (param != 1 && param != 2 && param != 4 && param != 8) {
2173         SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param");
2174         return;
2175       }
2176       break;
2177     case GL_PACK_ROW_LENGTH:
2178     case GL_PACK_SKIP_PIXELS:
2179     case GL_PACK_SKIP_ROWS:
2180     case GL_UNPACK_IMAGE_HEIGHT:
2181     case GL_UNPACK_SKIP_IMAGES:
2182       if (capabilities_.major_version < 3) {
2183         SetGLError(GL_INVALID_ENUM, "glPixelStorei", "invalid pname");
2184         return;
2185       }
2186       if (param < 0) {
2187         SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param");
2188         return;
2189       }
2190       break;
2191     case GL_UNPACK_ROW_LENGTH:
2192     case GL_UNPACK_SKIP_ROWS:
2193     case GL_UNPACK_SKIP_PIXELS:
2194       // These parameters are always enabled in ES2 by EXT_unpack_subimage.
2195       if (param < 0) {
2196         SetGLError(GL_INVALID_VALUE, "glPixelStorei", "invalid param");
2197         return;
2198       }
2199       break;
2200     default:
2201       SetGLError(GL_INVALID_ENUM, "glPixelStorei", "invalid pname");
2202       return;
2203   }
2204   // Do not send SKIP parameters to the service side.
2205   // Handle them on the client side.
2206   switch (pname) {
2207     case GL_PACK_ALIGNMENT:
2208       pack_alignment_ = param;
2209       break;
2210     case GL_PACK_ROW_LENGTH:
2211       pack_row_length_ = param;
2212       break;
2213     case GL_PACK_SKIP_PIXELS:
2214       pack_skip_pixels_ = param;
2215       return;
2216     case GL_PACK_SKIP_ROWS:
2217       pack_skip_rows_ = param;
2218       return;
2219     case GL_UNPACK_ALIGNMENT:
2220       unpack_alignment_ = param;
2221       break;
2222     case GL_UNPACK_ROW_LENGTH:
2223       unpack_row_length_ = param;
2224       if (capabilities_.major_version < 3) {
2225         // In ES2 with EXT_unpack_subimage, it's handled on the client side
2226         // and there is no need to send it to the service side.
2227         return;
2228       }
2229       break;
2230     case GL_UNPACK_IMAGE_HEIGHT:
2231       unpack_image_height_ = param;
2232       break;
2233     case GL_UNPACK_SKIP_ROWS:
2234       unpack_skip_rows_ = param;
2235       return;
2236     case GL_UNPACK_SKIP_PIXELS:
2237       unpack_skip_pixels_ = param;
2238       return;
2239     case GL_UNPACK_SKIP_IMAGES:
2240       unpack_skip_images_ = param;
2241       return;
2242     default:
2243       NOTREACHED();
2244       break;
2245   }
2246   helper_->PixelStorei(pname, param);
2247   CheckGLError();
2248 }
2249 
VertexAttribIPointer(GLuint index,GLint size,GLenum type,GLsizei stride,const void * ptr)2250 void GLES2Implementation::VertexAttribIPointer(GLuint index,
2251                                                GLint size,
2252                                                GLenum type,
2253                                                GLsizei stride,
2254                                                const void* ptr) {
2255   GPU_CLIENT_SINGLE_THREAD_CHECK();
2256   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer(" << index
2257                      << ", " << size << ", "
2258                      << GLES2Util::GetStringVertexAttribIType(type) << ", "
2259                      << stride << ", " << ptr << ")");
2260   // Record the info on the client side.
2261   if (!vertex_array_object_manager_->SetAttribPointer(
2262           bound_array_buffer_, index, size, type, GL_FALSE, stride, ptr,
2263           GL_TRUE)) {
2264     SetGLError(GL_INVALID_OPERATION, "glVertexAttribIPointer",
2265                "client side arrays are not allowed in vertex array objects.");
2266     return;
2267   }
2268   if (!support_client_side_arrays_ || bound_array_buffer_ != 0) {
2269     // Only report NON client side buffers to the service.
2270     if (!ValidateOffset("glVertexAttribIPointer",
2271                         reinterpret_cast<GLintptr>(ptr))) {
2272       return;
2273     }
2274     helper_->VertexAttribIPointer(index, size, type, stride, ToGLuint(ptr));
2275   }
2276   CheckGLError();
2277 }
2278 
VertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const void * ptr)2279 void GLES2Implementation::VertexAttribPointer(GLuint index,
2280                                               GLint size,
2281                                               GLenum type,
2282                                               GLboolean normalized,
2283                                               GLsizei stride,
2284                                               const void* ptr) {
2285   GPU_CLIENT_SINGLE_THREAD_CHECK();
2286   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer(" << index
2287                      << ", " << size << ", "
2288                      << GLES2Util::GetStringVertexAttribType(type) << ", "
2289                      << GLES2Util::GetStringBool(normalized) << ", " << stride
2290                      << ", " << ptr << ")");
2291   // Record the info on the client side.
2292   if (!vertex_array_object_manager_->SetAttribPointer(
2293           bound_array_buffer_, index, size, type, normalized, stride, ptr,
2294           GL_FALSE)) {
2295     SetGLError(GL_INVALID_OPERATION, "glVertexAttribPointer",
2296                "client side arrays are not allowed in vertex array objects.");
2297     return;
2298   }
2299   if (!support_client_side_arrays_ || bound_array_buffer_ != 0) {
2300     // Only report NON client side buffers to the service.
2301     if (!ValidateOffset("glVertexAttribPointer",
2302                         reinterpret_cast<GLintptr>(ptr))) {
2303       return;
2304     }
2305     helper_->VertexAttribPointer(index, size, type, normalized, stride,
2306                                  ToGLuint(ptr));
2307   }
2308   CheckGLError();
2309 }
2310 
VertexAttribDivisorANGLE(GLuint index,GLuint divisor)2311 void GLES2Implementation::VertexAttribDivisorANGLE(GLuint index,
2312                                                    GLuint divisor) {
2313   GPU_CLIENT_SINGLE_THREAD_CHECK();
2314   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
2315                      << index << ", " << divisor << ") ");
2316   // Record the info on the client side.
2317   vertex_array_object_manager_->SetAttribDivisor(index, divisor);
2318   helper_->VertexAttribDivisorANGLE(index, divisor);
2319   CheckGLError();
2320 }
2321 
BufferDataHelper(GLenum target,GLsizeiptr size,const void * data,GLenum usage)2322 void GLES2Implementation::BufferDataHelper(GLenum target,
2323                                            GLsizeiptr size,
2324                                            const void* data,
2325                                            GLenum usage) {
2326   if (!ValidateSize("glBufferData", size))
2327     return;
2328 
2329 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
2330   // Do not upload uninitialized data. Even if it's not a bug, it can cause a
2331   // bogus MSan report during a readback later. This is because MSan doesn't
2332   // understand shared memory and would assume we were reading back the same
2333   // unintialized data.
2334   if (data)
2335     __msan_check_mem_is_initialized(data, size);
2336 #endif
2337 
2338   GLuint buffer_id;
2339   if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) {
2340     if (!buffer_id) {
2341       return;
2342     }
2343 
2344     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
2345     if (buffer)
2346       RemoveTransferBuffer(buffer);
2347 
2348     // Create new buffer.
2349     buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
2350     DCHECK(buffer);
2351     if (buffer->address() && data)
2352       memcpy(buffer->address(), data, size);
2353     return;
2354   }
2355 
2356   if (IsReadbackUsage(usage)) {
2357     GLuint id = GetBoundBufferHelper(target);
2358     readback_buffer_shadow_tracker_->GetOrCreateBuffer(id, size);
2359   }
2360 
2361   RemoveMappedBufferRangeByTarget(target);
2362 
2363   // If there is no data just send BufferData
2364   if (size == 0 || !data) {
2365     helper_->BufferData(target, size, 0, 0, usage);
2366     return;
2367   }
2368 
2369   // See if we can send all at once.
2370   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
2371   if (!buffer.valid()) {
2372     return;
2373   }
2374 
2375   if (buffer.size() >= static_cast<unsigned int>(size)) {
2376     memcpy(buffer.address(), data, size);
2377     helper_->BufferData(target, size, buffer.shm_id(), buffer.offset(), usage);
2378     return;
2379   }
2380 
2381   // Make the buffer with BufferData then send via BufferSubData
2382   helper_->BufferData(target, size, 0, 0, usage);
2383   BufferSubDataHelperImpl(target, 0, size, data, &buffer);
2384   CheckGLError();
2385 }
2386 
BufferData(GLenum target,GLsizeiptr size,const void * data,GLenum usage)2387 void GLES2Implementation::BufferData(GLenum target,
2388                                      GLsizeiptr size,
2389                                      const void* data,
2390                                      GLenum usage) {
2391   GPU_CLIENT_SINGLE_THREAD_CHECK();
2392   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
2393                      << GLES2Util::GetStringBufferTarget(target) << ", " << size
2394                      << ", " << static_cast<const void*>(data) << ", "
2395                      << GLES2Util::GetStringBufferUsage(usage) << ")");
2396   BufferDataHelper(target, size, data, usage);
2397   CheckGLError();
2398 }
2399 
BufferSubDataHelper(GLenum target,GLintptr offset,GLsizeiptr size,const void * data)2400 void GLES2Implementation::BufferSubDataHelper(GLenum target,
2401                                               GLintptr offset,
2402                                               GLsizeiptr size,
2403                                               const void* data) {
2404   if (size == 0) {
2405     return;
2406   }
2407 
2408   if (!ValidateSize("glBufferSubData", size) ||
2409       !ValidateOffset("glBufferSubData", offset)) {
2410     return;
2411   }
2412 
2413   GLuint buffer_id;
2414   if (GetBoundPixelTransferBuffer(target, "glBufferSubData", &buffer_id)) {
2415     if (!buffer_id) {
2416       return;
2417     }
2418     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
2419     if (!buffer) {
2420       SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
2421       return;
2422     }
2423 
2424     int32_t end = 0;
2425     int32_t buffer_size = buffer->size();
2426     if (!base::CheckAdd(offset, size).AssignIfValid(&end) ||
2427         end > buffer_size) {
2428       SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
2429       return;
2430     }
2431 
2432     if (buffer->address() && data)
2433       memcpy(static_cast<uint8_t*>(buffer->address()) + offset, data, size);
2434     return;
2435   }
2436 
2437   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
2438   BufferSubDataHelperImpl(target, offset, size, data, &buffer);
2439 }
2440 
BufferSubDataHelperImpl(GLenum target,GLintptr offset,GLsizeiptr size,const void * data,ScopedTransferBufferPtr * buffer)2441 void GLES2Implementation::BufferSubDataHelperImpl(
2442     GLenum target,
2443     GLintptr offset,
2444     GLsizeiptr size,
2445     const void* data,
2446     ScopedTransferBufferPtr* buffer) {
2447   DCHECK(buffer);
2448   DCHECK_GT(size, 0);
2449 
2450   auto DoBufferSubData = [&](const std::array<uint32_t, 1>&,
2451                              uint32_t copy_offset, uint32_t) {
2452     helper_->BufferSubData(target, offset + copy_offset, buffer->size(),
2453                            buffer->shm_id(), buffer->offset());
2454     InvalidateReadbackBufferShadowDataCHROMIUM(GetBoundBufferHelper(target));
2455   };
2456 
2457   if (!TransferArraysAndExecute(size, buffer, DoBufferSubData,
2458                                 static_cast<const int8_t*>(data))) {
2459     SetGLError(GL_OUT_OF_MEMORY, "glBufferSubData", "out of memory");
2460   }
2461 }
2462 
BufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const void * data)2463 void GLES2Implementation::BufferSubData(GLenum target,
2464                                         GLintptr offset,
2465                                         GLsizeiptr size,
2466                                         const void* data) {
2467   GPU_CLIENT_SINGLE_THREAD_CHECK();
2468   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
2469                      << GLES2Util::GetStringBufferTarget(target) << ", "
2470                      << offset << ", " << size << ", "
2471                      << static_cast<const void*>(data) << ")");
2472   BufferSubDataHelper(target, offset, size, data);
2473   CheckGLError();
2474 }
2475 
MultiDrawArraysWEBGLHelper(GLenum mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)2476 void GLES2Implementation::MultiDrawArraysWEBGLHelper(GLenum mode,
2477                                                      const GLint* firsts,
2478                                                      const GLsizei* counts,
2479                                                      GLsizei drawcount) {
2480   DCHECK_GT(drawcount, 0);
2481 
2482   uint32_t buffer_size = ComputeCombinedCopySize(drawcount, firsts, counts);
2483   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2484 
2485   helper_->MultiDrawBeginCHROMIUM(drawcount);
2486   auto DoMultiDraw = [&](const std::array<uint32_t, 2>& offsets, uint32_t,
2487                          uint32_t copy_count) {
2488     helper_->MultiDrawArraysCHROMIUM(
2489         mode, buffer.shm_id(), buffer.offset() + offsets[0], buffer.shm_id(),
2490         buffer.offset() + offsets[1], copy_count);
2491   };
2492   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, firsts,
2493                                 counts)) {
2494     SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawArraysWEBGL", "out of memory");
2495   }
2496   helper_->MultiDrawEndCHROMIUM();
2497 }
2498 
MultiDrawArraysInstancedWEBGLHelper(GLenum mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instance_counts,GLsizei drawcount)2499 void GLES2Implementation::MultiDrawArraysInstancedWEBGLHelper(
2500     GLenum mode,
2501     const GLint* firsts,
2502     const GLsizei* counts,
2503     const GLsizei* instance_counts,
2504     GLsizei drawcount) {
2505   DCHECK_GT(drawcount, 0);
2506 
2507   uint32_t buffer_size =
2508       ComputeCombinedCopySize(drawcount, firsts, counts, instance_counts);
2509   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2510 
2511   helper_->MultiDrawBeginCHROMIUM(drawcount);
2512   auto DoMultiDraw = [&](const std::array<uint32_t, 3>& offsets, uint32_t,
2513                          uint32_t copy_count) {
2514     helper_->MultiDrawArraysInstancedCHROMIUM(
2515         mode, buffer.shm_id(), buffer.offset() + offsets[0], buffer.shm_id(),
2516         buffer.offset() + offsets[1], buffer.shm_id(),
2517         buffer.offset() + offsets[2], copy_count);
2518   };
2519   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, firsts, counts,
2520                                 instance_counts)) {
2521     SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawArraysInstancedWEBGL",
2522                "out of memory");
2523   }
2524   helper_->MultiDrawEndCHROMIUM();
2525 }
2526 
MultiDrawArraysInstancedBaseInstanceWEBGLHelper(GLenum mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instance_counts,const GLuint * baseinstances,GLsizei drawcount)2527 void GLES2Implementation::MultiDrawArraysInstancedBaseInstanceWEBGLHelper(
2528     GLenum mode,
2529     const GLint* firsts,
2530     const GLsizei* counts,
2531     const GLsizei* instance_counts,
2532     const GLuint* baseinstances,
2533     GLsizei drawcount) {
2534   DCHECK_GT(drawcount, 0);
2535 
2536   uint32_t buffer_size = ComputeCombinedCopySize(
2537       drawcount, firsts, counts, instance_counts, baseinstances);
2538   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2539 
2540   helper_->MultiDrawBeginCHROMIUM(drawcount);
2541   auto DoMultiDraw = [&](const std::array<uint32_t, 4>& offsets, uint32_t,
2542                          uint32_t copy_count) {
2543     helper_->MultiDrawArraysInstancedBaseInstanceCHROMIUM(
2544         mode, buffer.shm_id(), buffer.offset() + offsets[0], buffer.shm_id(),
2545         buffer.offset() + offsets[1], buffer.shm_id(),
2546         buffer.offset() + offsets[2], buffer.shm_id(),
2547         buffer.offset() + offsets[3], copy_count);
2548   };
2549   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, firsts, counts,
2550                                 instance_counts, baseinstances)) {
2551     SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawArraysInstancedBaseInstanceWEBGL",
2552                "out of memory");
2553   }
2554   helper_->MultiDrawEndCHROMIUM();
2555 }
2556 
MultiDrawElementsWEBGLHelper(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,GLsizei drawcount)2557 void GLES2Implementation::MultiDrawElementsWEBGLHelper(GLenum mode,
2558                                                        const GLsizei* counts,
2559                                                        GLenum type,
2560                                                        const GLsizei* offsets,
2561                                                        GLsizei drawcount) {
2562   DCHECK_GT(drawcount, 0);
2563 
2564   uint32_t buffer_size = ComputeCombinedCopySize(drawcount, counts, offsets);
2565   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2566 
2567   helper_->MultiDrawBeginCHROMIUM(drawcount);
2568   auto DoMultiDraw = [&](const std::array<uint32_t, 2>& offsets, uint32_t,
2569                          uint32_t copy_count) {
2570     helper_->MultiDrawElementsCHROMIUM(
2571         mode, buffer.shm_id(), buffer.offset() + offsets[0], type,
2572         buffer.shm_id(), buffer.offset() + offsets[1], copy_count);
2573   };
2574   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, counts,
2575                                 offsets)) {
2576     SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawElementsWEBGL", "out of memory");
2577   }
2578   helper_->MultiDrawEndCHROMIUM();
2579 }
2580 
MultiDrawElementsInstancedWEBGLHelper(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,const GLsizei * instance_counts,GLsizei drawcount)2581 void GLES2Implementation::MultiDrawElementsInstancedWEBGLHelper(
2582     GLenum mode,
2583     const GLsizei* counts,
2584     GLenum type,
2585     const GLsizei* offsets,
2586     const GLsizei* instance_counts,
2587     GLsizei drawcount) {
2588   DCHECK_GT(drawcount, 0);
2589 
2590   uint32_t buffer_size =
2591       ComputeCombinedCopySize(drawcount, counts, offsets, instance_counts);
2592   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2593 
2594   helper_->MultiDrawBeginCHROMIUM(drawcount);
2595   auto DoMultiDraw = [&](const std::array<uint32_t, 3>& offsets, uint32_t,
2596                          uint32_t copy_count) {
2597     helper_->MultiDrawElementsInstancedCHROMIUM(
2598         mode, buffer.shm_id(), buffer.offset() + offsets[0], type,
2599         buffer.shm_id(), buffer.offset() + offsets[1], buffer.shm_id(),
2600         buffer.offset() + offsets[2], copy_count);
2601   };
2602   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, counts,
2603                                 offsets, instance_counts)) {
2604     SetGLError(GL_OUT_OF_MEMORY, "glMultiDrawElementsInstancedWEBGL",
2605                "out of memory");
2606   }
2607   helper_->MultiDrawEndCHROMIUM();
2608 }
2609 
2610 void GLES2Implementation::
MultiDrawElementsInstancedBaseVertexBaseInstanceWEBGLHelper(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,const GLsizei * instance_counts,const GLint * basevertices,const GLuint * baseinstances,GLsizei drawcount)2611     MultiDrawElementsInstancedBaseVertexBaseInstanceWEBGLHelper(
2612         GLenum mode,
2613         const GLsizei* counts,
2614         GLenum type,
2615         const GLsizei* offsets,
2616         const GLsizei* instance_counts,
2617         const GLint* basevertices,
2618         const GLuint* baseinstances,
2619         GLsizei drawcount) {
2620   DCHECK_GT(drawcount, 0);
2621 
2622   uint32_t buffer_size = ComputeCombinedCopySize(
2623       drawcount, counts, offsets, instance_counts, basevertices, baseinstances);
2624   ScopedTransferBufferPtr buffer(buffer_size, helper_, transfer_buffer_);
2625 
2626   helper_->MultiDrawBeginCHROMIUM(drawcount);
2627   auto DoMultiDraw = [&](const std::array<uint32_t, 5>& offsets, uint32_t,
2628                          uint32_t copy_count) {
2629     helper_->MultiDrawElementsInstancedBaseVertexBaseInstanceCHROMIUM(
2630         mode, buffer.shm_id(), buffer.offset() + offsets[0], type,
2631         buffer.shm_id(), buffer.offset() + offsets[1], buffer.shm_id(),
2632         buffer.offset() + offsets[2], buffer.shm_id(),
2633         buffer.offset() + offsets[3], buffer.shm_id(),
2634         buffer.offset() + offsets[4], copy_count);
2635   };
2636   if (!TransferArraysAndExecute(drawcount, &buffer, DoMultiDraw, counts,
2637                                 offsets, instance_counts, basevertices,
2638                                 baseinstances)) {
2639     SetGLError(GL_OUT_OF_MEMORY,
2640                "glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL",
2641                "out of memory");
2642   }
2643   helper_->MultiDrawEndCHROMIUM();
2644 }
2645 
MultiDrawArraysWEBGL(GLenum mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)2646 void GLES2Implementation::MultiDrawArraysWEBGL(GLenum mode,
2647                                                const GLint* firsts,
2648                                                const GLsizei* counts,
2649                                                GLsizei drawcount) {
2650   GPU_CLIENT_SINGLE_THREAD_CHECK();
2651   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMultiDrawArraysWEBGL("
2652                      << GLES2Util::GetStringDrawMode(mode) << ", " << firsts
2653                      << ", " << counts << ", " << drawcount << ")");
2654   if (drawcount < 0) {
2655     SetGLError(GL_INVALID_VALUE, "glMultiDrawArraysWEBGL", "drawcount < 0");
2656     return;
2657   }
2658   if (drawcount == 0) {
2659     return;
2660   }
2661   // This is for an extension for WebGL which doesn't support client side arrays
2662   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2663     SetGLError(GL_INVALID_OPERATION, "glMultiDrawArraysWEBGL",
2664                "Missing array buffer for vertex attribute");
2665     return;
2666   }
2667   MultiDrawArraysWEBGLHelper(mode, firsts, counts, drawcount);
2668   CheckGLError();
2669 }
2670 
MultiDrawArraysInstancedWEBGL(GLenum mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instance_counts,GLsizei drawcount)2671 void GLES2Implementation::MultiDrawArraysInstancedWEBGL(
2672     GLenum mode,
2673     const GLint* firsts,
2674     const GLsizei* counts,
2675     const GLsizei* instance_counts,
2676     GLsizei drawcount) {
2677   GPU_CLIENT_SINGLE_THREAD_CHECK();
2678   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMultiDrawArraysInstancedWEBGL("
2679                      << GLES2Util::GetStringDrawMode(mode) << ", " << firsts
2680                      << ", " << counts << ", " << instance_counts << ", "
2681                      << drawcount << ")");
2682   if (drawcount < 0) {
2683     SetGLError(GL_INVALID_VALUE, "glMultiDrawArraysWEBGLInstanced",
2684                "drawcount < 0");
2685     return;
2686   }
2687   if (drawcount == 0) {
2688     return;
2689   }
2690   // This is for an extension for WebGL which doesn't support client side arrays
2691   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2692     SetGLError(GL_INVALID_OPERATION, "glMultiDrawArraysWEBGLInstanced",
2693                "Missing array buffer for vertex attribute");
2694     return;
2695   }
2696   MultiDrawArraysInstancedWEBGLHelper(mode, firsts, counts, instance_counts,
2697                                       drawcount);
2698   CheckGLError();
2699 }
2700 
MultiDrawArraysInstancedBaseInstanceWEBGL(GLenum mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instance_counts,const GLuint * baseinstances,GLsizei drawcount)2701 void GLES2Implementation::MultiDrawArraysInstancedBaseInstanceWEBGL(
2702     GLenum mode,
2703     const GLint* firsts,
2704     const GLsizei* counts,
2705     const GLsizei* instance_counts,
2706     const GLuint* baseinstances,
2707     GLsizei drawcount) {
2708   GPU_CLIENT_SINGLE_THREAD_CHECK();
2709   GPU_CLIENT_LOG("[" << GetLogPrefix()
2710                      << "] glMultiDrawArraysInstancedBaseInstanceWEBGL("
2711                      << GLES2Util::GetStringDrawMode(mode) << ", " << firsts
2712                      << ", " << counts << ", " << instance_counts << ", "
2713                      << baseinstances << ", " << drawcount << ")");
2714   if (drawcount < 0) {
2715     SetGLError(GL_INVALID_VALUE, "glMultiDrawArraysInstancedBaseInstanceWEBGL",
2716                "drawcount < 0");
2717     return;
2718   }
2719   if (drawcount == 0) {
2720     return;
2721   }
2722   // This is for an extension for WebGL which doesn't support client side arrays
2723   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2724     SetGLError(GL_INVALID_OPERATION,
2725                "glMultiDrawArraysInstancedBaseInstanceWEBGL",
2726                "Missing array buffer for vertex attribute");
2727     return;
2728   }
2729   MultiDrawArraysInstancedBaseInstanceWEBGLHelper(
2730       mode, firsts, counts, instance_counts, baseinstances, drawcount);
2731   CheckGLError();
2732 }
2733 
MultiDrawElementsWEBGL(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,GLsizei drawcount)2734 void GLES2Implementation::MultiDrawElementsWEBGL(GLenum mode,
2735                                                  const GLsizei* counts,
2736                                                  GLenum type,
2737                                                  const GLsizei* offsets,
2738                                                  GLsizei drawcount) {
2739   GPU_CLIENT_SINGLE_THREAD_CHECK();
2740   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMultiDrawElementsWEBGL("
2741                      << GLES2Util::GetStringDrawMode(mode) << ", " << counts
2742                      << ", " << GLES2Util::GetStringIndexType(type) << ", "
2743                      << offsets << ", " << drawcount << ")");
2744   if (drawcount < 0) {
2745     SetGLError(GL_INVALID_VALUE, "glMultiDrawElementsWEBGL", "drawcount < 0");
2746     return;
2747   }
2748   if (drawcount == 0) {
2749     return;
2750   }
2751   // This is for an extension for WebGL which doesn't support client side arrays
2752   if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
2753     SetGLError(GL_INVALID_OPERATION, "glMultiDrawElementsWEBGL",
2754                "No element array buffer");
2755     return;
2756   }
2757   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2758     SetGLError(GL_INVALID_OPERATION, "glMultiDrawElementsWEBGL",
2759                "Missing array buffer for vertex attribute");
2760     return;
2761   }
2762   MultiDrawElementsWEBGLHelper(mode, counts, type, offsets, drawcount);
2763   CheckGLError();
2764 }
2765 
MultiDrawElementsInstancedWEBGL(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,const GLsizei * instance_counts,GLsizei drawcount)2766 void GLES2Implementation::MultiDrawElementsInstancedWEBGL(
2767     GLenum mode,
2768     const GLsizei* counts,
2769     GLenum type,
2770     const GLsizei* offsets,
2771     const GLsizei* instance_counts,
2772     GLsizei drawcount) {
2773   GPU_CLIENT_SINGLE_THREAD_CHECK();
2774   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMultiDrawElementsInstancedWEBGL("
2775                      << GLES2Util::GetStringDrawMode(mode) << ", " << counts
2776                      << ", " << GLES2Util::GetStringIndexType(type) << ", "
2777                      << offsets << ", " << instance_counts << ", " << drawcount
2778                      << ")");
2779   if (drawcount < 0) {
2780     SetGLError(GL_INVALID_VALUE, "glMultiDrawElementsInstancedWEBGL",
2781                "drawcount < 0");
2782     return;
2783   }
2784   if (drawcount == 0) {
2785     return;
2786   }
2787   // This is for an extension for WebGL which doesn't support client side arrays
2788   if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
2789     SetGLError(GL_INVALID_OPERATION, "glMultiDrawElementsInstancedWEBGL",
2790                "No element array buffer");
2791     return;
2792   }
2793   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2794     SetGLError(GL_INVALID_OPERATION, "glMultiDrawElementsInstancedWEBGL",
2795                "Missing array buffer for vertex attribute");
2796     return;
2797   }
2798   MultiDrawElementsInstancedWEBGLHelper(mode, counts, type, offsets,
2799                                         instance_counts, drawcount);
2800   CheckGLError();
2801 }
2802 
MultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(GLenum mode,const GLsizei * counts,GLenum type,const GLsizei * offsets,const GLsizei * instance_counts,const GLint * basevertices,const GLuint * baseinstances,GLsizei drawcount)2803 void GLES2Implementation::MultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(
2804     GLenum mode,
2805     const GLsizei* counts,
2806     GLenum type,
2807     const GLsizei* offsets,
2808     const GLsizei* instance_counts,
2809     const GLint* basevertices,
2810     const GLuint* baseinstances,
2811     GLsizei drawcount) {
2812   GPU_CLIENT_SINGLE_THREAD_CHECK();
2813   GPU_CLIENT_LOG(
2814       "[" << GetLogPrefix()
2815           << "] glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL("
2816           << GLES2Util::GetStringDrawMode(mode) << ", " << counts << ", "
2817           << GLES2Util::GetStringIndexType(type) << ", " << offsets << ", "
2818           << instance_counts << ", " << basevertices << ", " << baseinstances
2819           << drawcount << ")");
2820   if (drawcount < 0) {
2821     SetGLError(GL_INVALID_VALUE, "glMultiDrawElementsInstancedWEBGL",
2822                "drawcount < 0");
2823     return;
2824   }
2825   if (drawcount == 0) {
2826     return;
2827   }
2828   // This is for an extension for WebGL which doesn't support client side arrays
2829   if (vertex_array_object_manager_->bound_element_array_buffer() == 0) {
2830     SetGLError(GL_INVALID_OPERATION,
2831                "glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL",
2832                "No element array buffer");
2833     return;
2834   }
2835   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
2836     SetGLError(GL_INVALID_OPERATION,
2837                "glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL",
2838                "Missing array buffer for vertex attribute");
2839     return;
2840   }
2841   MultiDrawElementsInstancedBaseVertexBaseInstanceWEBGLHelper(
2842       mode, counts, type, offsets, instance_counts, basevertices, baseinstances,
2843       drawcount);
2844   CheckGLError();
2845 }
2846 
RemoveTransferBuffer(BufferTracker::Buffer * buffer)2847 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer* buffer) {
2848   int32_t token = buffer->last_usage_token();
2849 
2850   if (token) {
2851     if (helper_->HasTokenPassed(token))
2852       buffer_tracker_->Free(buffer);
2853     else
2854       buffer_tracker_->FreePendingToken(buffer, token);
2855   } else {
2856     buffer_tracker_->Free(buffer);
2857   }
2858 
2859   buffer_tracker_->RemoveBuffer(buffer->id());
2860 }
2861 
GetBoundPixelTransferBuffer(GLenum target,const char * function_name,GLuint * buffer_id)2862 bool GLES2Implementation::GetBoundPixelTransferBuffer(GLenum target,
2863                                                       const char* function_name,
2864                                                       GLuint* buffer_id) {
2865   *buffer_id = 0;
2866 
2867   switch (target) {
2868     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
2869       *buffer_id = bound_pixel_pack_transfer_buffer_id_;
2870       break;
2871     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
2872       *buffer_id = bound_pixel_unpack_transfer_buffer_id_;
2873       break;
2874     default:
2875       // Unknown target
2876       return false;
2877   }
2878   if (!*buffer_id) {
2879     SetGLError(GL_INVALID_OPERATION, function_name, "no buffer bound");
2880   }
2881   return true;
2882 }
2883 
GetBoundPixelTransferBufferIfValid(GLuint buffer_id,const char * function_name,GLuint offset,GLsizei size)2884 BufferTracker::Buffer* GLES2Implementation::GetBoundPixelTransferBufferIfValid(
2885     GLuint buffer_id,
2886     const char* function_name,
2887     GLuint offset,
2888     GLsizei size) {
2889   DCHECK(buffer_id);
2890   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
2891   if (!buffer) {
2892     SetGLError(GL_INVALID_OPERATION, function_name, "invalid buffer");
2893     return nullptr;
2894   }
2895   if (buffer->mapped()) {
2896     SetGLError(GL_INVALID_OPERATION, function_name, "buffer mapped");
2897     return nullptr;
2898   }
2899   base::CheckedNumeric<uint32_t> buffer_offset = buffer->shm_offset();
2900   buffer_offset += offset;
2901   if (!buffer_offset.IsValid()) {
2902     SetGLError(GL_INVALID_VALUE, function_name, "offset to large");
2903     return nullptr;
2904   }
2905   base::CheckedNumeric<uint32_t> required_size = offset;
2906   required_size += size;
2907   if (!required_size.IsValid() ||
2908       buffer->size() < required_size.ValueOrDefault(0)) {
2909     SetGLError(GL_INVALID_VALUE, function_name, "unpack size to large");
2910     return nullptr;
2911   }
2912   return buffer;
2913 }
2914 
InvalidateReadbackBufferShadowDataCHROMIUM(GLuint buffer_id)2915 void GLES2Implementation::InvalidateReadbackBufferShadowDataCHROMIUM(
2916     GLuint buffer_id) {
2917   readback_buffer_shadow_tracker_->OnBufferWrite(buffer_id);
2918 }
2919 
CompressedTexImage2D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei image_size,const void * data)2920 void GLES2Implementation::CompressedTexImage2D(GLenum target,
2921                                                GLint level,
2922                                                GLenum internalformat,
2923                                                GLsizei width,
2924                                                GLsizei height,
2925                                                GLint border,
2926                                                GLsizei image_size,
2927                                                const void* data) {
2928   GPU_CLIENT_SINGLE_THREAD_CHECK();
2929   GPU_CLIENT_LOG(
2930       "[" << GetLogPrefix() << "] glCompressedTexImage2D("
2931           << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", "
2932           << GLES2Util::GetStringCompressedTextureFormat(internalformat) << ", "
2933           << width << ", " << height << ", " << border << ", " << image_size
2934           << ", " << static_cast<const void*>(data) << ")");
2935   if (width < 0 || height < 0 || level < 0) {
2936     SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "dimension < 0");
2937     return;
2938   }
2939   if (border != 0) {
2940     SetGLError(GL_INVALID_VALUE, "glCompressedTexImage2D", "border != 0");
2941     return;
2942   }
2943   // If there's a pixel unpack buffer bound use it when issuing
2944   // CompressedTexImage2D.
2945   if (bound_pixel_unpack_transfer_buffer_id_) {
2946     GLuint offset = ToGLuint(data);
2947     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
2948         bound_pixel_unpack_transfer_buffer_id_, "glCompressedTexImage2D",
2949         offset, image_size);
2950     if (buffer && buffer->shm_id() != -1) {
2951       helper_->CompressedTexImage2D(target, level, internalformat, width,
2952                                     height, image_size, buffer->shm_id(),
2953                                     buffer->shm_offset() + offset);
2954       buffer->set_last_usage_token(helper_->InsertToken());
2955     }
2956     return;
2957   }
2958   if (bound_pixel_unpack_buffer_) {
2959     helper_->CompressedTexImage2D(target, level, internalformat, width, height,
2960                                   image_size, 0, ToGLuint(data));
2961   } else if (data) {
2962     SetBucketContents(kResultBucketId, data, image_size);
2963     helper_->CompressedTexImage2DBucket(target, level, internalformat, width,
2964                                         height, kResultBucketId);
2965     // Free the bucket. This is not required but it does free up the memory.
2966     // and we don't have to wait for the result so from the client's perspective
2967     // it's cheap.
2968     helper_->SetBucketSize(kResultBucketId, 0);
2969   } else {
2970     helper_->CompressedTexImage2D(target, level, internalformat, width, height,
2971                                   image_size, 0, 0);
2972   }
2973   CheckGLError();
2974 }
2975 
CompressedTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei image_size,const void * data)2976 void GLES2Implementation::CompressedTexSubImage2D(GLenum target,
2977                                                   GLint level,
2978                                                   GLint xoffset,
2979                                                   GLint yoffset,
2980                                                   GLsizei width,
2981                                                   GLsizei height,
2982                                                   GLenum format,
2983                                                   GLsizei image_size,
2984                                                   const void* data) {
2985   GPU_CLIENT_SINGLE_THREAD_CHECK();
2986   GPU_CLIENT_LOG(
2987       "[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
2988           << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", "
2989           << xoffset << ", " << yoffset << ", " << width << ", " << height
2990           << ", " << GLES2Util::GetStringCompressedTextureFormat(format) << ", "
2991           << image_size << ", " << static_cast<const void*>(data) << ")");
2992   if (width < 0 || height < 0 || level < 0) {
2993     SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "dimension < 0");
2994     return;
2995   }
2996   // If there's a pixel unpack buffer bound use it when issuing
2997   // CompressedTexSubImage2D.
2998   if (bound_pixel_unpack_transfer_buffer_id_) {
2999     GLuint offset = ToGLuint(data);
3000     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3001         bound_pixel_unpack_transfer_buffer_id_, "glCompressedTexSubImage2D",
3002         offset, image_size);
3003     if (buffer && buffer->shm_id() != -1) {
3004       helper_->CompressedTexSubImage2D(
3005           target, level, xoffset, yoffset, width, height, format, image_size,
3006           buffer->shm_id(), buffer->shm_offset() + offset);
3007       buffer->set_last_usage_token(helper_->InsertToken());
3008       CheckGLError();
3009     }
3010     return;
3011   }
3012   if (bound_pixel_unpack_buffer_) {
3013     helper_->CompressedTexSubImage2D(target, level, xoffset, yoffset, width,
3014                                      height, format, image_size, 0,
3015                                      ToGLuint(data));
3016   } else if (data) {
3017     SetBucketContents(kResultBucketId, data, image_size);
3018     helper_->CompressedTexSubImage2DBucket(target, level, xoffset, yoffset,
3019                                            width, height, format,
3020                                            kResultBucketId);
3021     // Free the bucket. This is not required but it does free up the memory.
3022     // and we don't have to wait for the result so from the client's perspective
3023     // it's cheap.
3024     helper_->SetBucketSize(kResultBucketId, 0);
3025   } else {
3026     helper_->CompressedTexSubImage2D(target, level, xoffset, yoffset, width,
3027                                      height, format, image_size, 0, 0);
3028   }
3029   CheckGLError();
3030 }
3031 
CompressedTexImage3D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei image_size,const void * data)3032 void GLES2Implementation::CompressedTexImage3D(GLenum target,
3033                                                GLint level,
3034                                                GLenum internalformat,
3035                                                GLsizei width,
3036                                                GLsizei height,
3037                                                GLsizei depth,
3038                                                GLint border,
3039                                                GLsizei image_size,
3040                                                const void* data) {
3041   GPU_CLIENT_SINGLE_THREAD_CHECK();
3042   GPU_CLIENT_LOG(
3043       "[" << GetLogPrefix() << "] glCompressedTexImage3D("
3044           << GLES2Util::GetStringTexture3DTarget(target) << ", " << level
3045           << ", " << GLES2Util::GetStringCompressedTextureFormat(internalformat)
3046           << ", " << width << ", " << height << ", " << depth << ", " << border
3047           << ", " << image_size << ", " << static_cast<const void*>(data)
3048           << ")");
3049   if (width < 0 || height < 0 || depth < 0 || level < 0) {
3050     SetGLError(GL_INVALID_VALUE, "glCompressedTexImage3D", "dimension < 0");
3051     return;
3052   }
3053   if (border != 0) {
3054     SetGLError(GL_INVALID_VALUE, "glCompressedTexImage3D", "border != 0");
3055     return;
3056   }
3057   // If there's a pixel unpack buffer bound use it when issuing
3058   // CompressedTexImage3D.
3059   if (bound_pixel_unpack_transfer_buffer_id_) {
3060     GLuint offset = ToGLuint(data);
3061     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3062         bound_pixel_unpack_transfer_buffer_id_, "glCompressedTexImage3D",
3063         offset, image_size);
3064     if (buffer && buffer->shm_id() != -1) {
3065       helper_->CompressedTexImage3D(target, level, internalformat, width,
3066                                     height, depth, image_size, buffer->shm_id(),
3067                                     buffer->shm_offset() + offset);
3068       buffer->set_last_usage_token(helper_->InsertToken());
3069     }
3070     return;
3071   }
3072   if (bound_pixel_unpack_buffer_) {
3073     helper_->CompressedTexImage3D(target, level, internalformat, width, height,
3074                                   depth, image_size, 0, ToGLuint(data));
3075   } else if (data) {
3076     SetBucketContents(kResultBucketId, data, image_size);
3077     helper_->CompressedTexImage3DBucket(target, level, internalformat, width,
3078                                         height, depth, kResultBucketId);
3079     // Free the bucket. This is not required but it does free up the memory.
3080     // and we don't have to wait for the result so from the client's perspective
3081     // it's cheap.
3082     helper_->SetBucketSize(kResultBucketId, 0);
3083   } else {
3084     helper_->CompressedTexImage3D(target, level, internalformat, width, height,
3085                                   depth, image_size, 0, 0);
3086   }
3087   CheckGLError();
3088 }
3089 
CompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei image_size,const void * data)3090 void GLES2Implementation::CompressedTexSubImage3D(GLenum target,
3091                                                   GLint level,
3092                                                   GLint xoffset,
3093                                                   GLint yoffset,
3094                                                   GLint zoffset,
3095                                                   GLsizei width,
3096                                                   GLsizei height,
3097                                                   GLsizei depth,
3098                                                   GLenum format,
3099                                                   GLsizei image_size,
3100                                                   const void* data) {
3101   GPU_CLIENT_SINGLE_THREAD_CHECK();
3102   GPU_CLIENT_LOG(
3103       "[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
3104           << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", "
3105           << xoffset << ", " << yoffset << ", " << zoffset << ", " << width
3106           << ", " << height << ", " << depth << ", "
3107           << GLES2Util::GetStringCompressedTextureFormat(format) << ", "
3108           << image_size << ", " << static_cast<const void*>(data) << ")");
3109   if (width < 0 || height < 0 || depth < 0 || level < 0) {
3110     SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage3D", "dimension < 0");
3111     return;
3112   }
3113   // If there's a pixel unpack buffer bound use it when issuing
3114   // CompressedTexSubImage3D.
3115   if (bound_pixel_unpack_transfer_buffer_id_) {
3116     GLuint offset = ToGLuint(data);
3117     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3118         bound_pixel_unpack_transfer_buffer_id_, "glCompressedTexSubImage3D",
3119         offset, image_size);
3120     if (buffer && buffer->shm_id() != -1) {
3121       helper_->CompressedTexSubImage3D(
3122           target, level, xoffset, yoffset, zoffset, width, height, depth,
3123           format, image_size, buffer->shm_id(), buffer->shm_offset() + offset);
3124       buffer->set_last_usage_token(helper_->InsertToken());
3125       CheckGLError();
3126     }
3127     return;
3128   }
3129   if (bound_pixel_unpack_buffer_) {
3130     helper_->CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
3131                                      width, height, depth, format, image_size,
3132                                      0, ToGLuint(data));
3133   } else if (data) {
3134     SetBucketContents(kResultBucketId, data, image_size);
3135     helper_->CompressedTexSubImage3DBucket(target, level, xoffset, yoffset,
3136                                            zoffset, width, height, depth,
3137                                            format, kResultBucketId);
3138     // Free the bucket. This is not required but it does free up the memory.
3139     // and we don't have to wait for the result so from the client's perspective
3140     // it's cheap.
3141     helper_->SetBucketSize(kResultBucketId, 0);
3142   } else {
3143     helper_->CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
3144                                      width, height, depth, format, image_size,
3145                                      0, 0);
3146   }
3147   CheckGLError();
3148 }
3149 
GetUnpackParameters(Dimension dimension)3150 PixelStoreParams GLES2Implementation::GetUnpackParameters(Dimension dimension) {
3151   PixelStoreParams params;
3152   params.alignment = unpack_alignment_;
3153   params.row_length = unpack_row_length_;
3154   params.skip_pixels = unpack_skip_pixels_;
3155   params.skip_rows = unpack_skip_rows_;
3156   if (dimension == k3D) {
3157     params.image_height = unpack_image_height_;
3158     params.skip_images = unpack_skip_images_;
3159   }
3160   return params;
3161 }
3162 
PrepareNextSwapId(SwapCompletedCallback completion_callback,PresentationCallback presentation_callback)3163 uint64_t GLES2Implementation::PrepareNextSwapId(
3164     SwapCompletedCallback completion_callback,
3165     PresentationCallback presentation_callback) {
3166   uint64_t swap_id = swap_id_++;
3167   pending_swap_callbacks_.emplace(swap_id, std::move(completion_callback));
3168   if (!presentation_callback.is_null()) {
3169     pending_presentation_callbacks_.emplace(swap_id,
3170                                             std::move(presentation_callback));
3171   }
3172   return swap_id;
3173 }
3174 
TexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)3175 void GLES2Implementation::TexImage2D(GLenum target,
3176                                      GLint level,
3177                                      GLint internalformat,
3178                                      GLsizei width,
3179                                      GLsizei height,
3180                                      GLint border,
3181                                      GLenum format,
3182                                      GLenum type,
3183                                      const void* pixels) {
3184   const char* func_name = "glTexImage2D";
3185   GPU_CLIENT_SINGLE_THREAD_CHECK();
3186   GPU_CLIENT_LOG(
3187       "[" << GetLogPrefix() << "] glTexImage2D("
3188           << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", "
3189           << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
3190           << width << ", " << height << ", " << border << ", "
3191           << GLES2Util::GetStringTextureFormat(format) << ", "
3192           << GLES2Util::GetStringPixelType(type) << ", "
3193           << static_cast<const void*>(pixels) << ")");
3194   if (level < 0 || height < 0 || width < 0) {
3195     SetGLError(GL_INVALID_VALUE, func_name, "dimension < 0");
3196     return;
3197   }
3198   if (border != 0) {
3199     SetGLError(GL_INVALID_VALUE, func_name, "border != 0");
3200     return;
3201   }
3202   if ((bound_pixel_unpack_buffer_ || pixels) &&
3203       (unpack_skip_pixels_ + width >
3204        (unpack_row_length_ ? unpack_row_length_ : width))) {
3205     // This is WebGL 2 specific constraints, but we do it for all ES3 contexts.
3206     SetGLError(GL_INVALID_OPERATION, func_name,
3207                "invalid unpack params combination");
3208     return;
3209   }
3210 
3211   uint32_t size;
3212   uint32_t unpadded_row_size;
3213   uint32_t padded_row_size;
3214   uint32_t skip_size;
3215   PixelStoreParams params = GetUnpackParameters(k2D);
3216 
3217   if (!GLES2Util::ComputeImageDataSizesES3(
3218           width, height, 1, format, type, params, &size, &unpadded_row_size,
3219           &padded_row_size, &skip_size, nullptr)) {
3220     SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3221     return;
3222   }
3223 
3224   if (bound_pixel_unpack_buffer_) {
3225     base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels);
3226     offset += skip_size;
3227     if (!offset.IsValid()) {
3228       SetGLError(GL_INVALID_VALUE, func_name, "skip size too large");
3229       return;
3230     }
3231     helper_->TexImage2D(target, level, internalformat, width, height, format,
3232                         type, 0, offset.ValueOrDefault(0));
3233     CheckGLError();
3234     return;
3235   }
3236 
3237   // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
3238   if (bound_pixel_unpack_transfer_buffer_id_) {
3239     if (unpack_row_length_ > 0 || unpack_image_height_ > 0 ||
3240         unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 ||
3241         unpack_skip_images_ > 0) {
3242       SetGLError(GL_INVALID_OPERATION, func_name,
3243                  "No ES3 pack parameters with pixel unpack transfer buffer.");
3244       return;
3245     }
3246     DCHECK_EQ(0u, skip_size);
3247     GLuint offset = ToGLuint(pixels);
3248     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3249         bound_pixel_unpack_transfer_buffer_id_, func_name, offset, size);
3250     if (buffer && buffer->shm_id() != -1) {
3251       helper_->TexImage2D(target, level, internalformat, width, height, format,
3252                           type, buffer->shm_id(),
3253                           buffer->shm_offset() + offset);
3254       buffer->set_last_usage_token(helper_->InsertToken());
3255       CheckGLError();
3256     }
3257     return;
3258   }
3259 
3260   // If there's no data just issue TexImage2D
3261   if (!pixels || width == 0 || height == 0) {
3262     helper_->TexImage2D(target, level, internalformat, width, height, format,
3263                         type, 0, 0);
3264     CheckGLError();
3265     return;
3266   }
3267 
3268   // Compute the advance bytes per row on the service side.
3269   // Note |size| is recomputed here if needed.
3270   uint32_t service_padded_row_size;
3271   if (unpack_row_length_ > 0 && unpack_row_length_ != width) {
3272     // All parameters have been applied to the data that are sent to the
3273     // service side except UNPACK_ALIGNMENT.
3274     PixelStoreParams service_params;
3275     service_params.alignment = unpack_alignment_;
3276     if (!GLES2Util::ComputeImageDataSizesES3(
3277             width, height, 1, format, type, service_params, &size, nullptr,
3278             &service_padded_row_size, nullptr, nullptr)) {
3279       SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3280       return;
3281     }
3282   } else {
3283     service_padded_row_size = padded_row_size;
3284   }
3285 
3286   // advance pixels pointer past the skip rows and skip pixels
3287   pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size;
3288 
3289   // Check if we can send it all at once.
3290   int32_t shm_id = 0;
3291   uint32_t shm_offset = 0;
3292   void* buffer_pointer = nullptr;
3293 
3294   ScopedTransferBufferPtr transfer_alloc(size, helper_, transfer_buffer_);
3295   ScopedMappedMemoryPtr mapped_alloc(0, helper_, mapped_memory_.get());
3296 
3297   if (transfer_alloc.valid() && transfer_alloc.size() >= size) {
3298     shm_id = transfer_alloc.shm_id();
3299     shm_offset = transfer_alloc.offset();
3300     buffer_pointer = transfer_alloc.address();
3301   } else if (size < max_extra_transfer_buffer_size_) {
3302     mapped_alloc.Reset(size);
3303     if (mapped_alloc.valid()) {
3304       transfer_alloc.Discard();
3305 
3306       mapped_alloc.SetFlushAfterRelease(true);
3307       shm_id = mapped_alloc.shm_id();
3308       shm_offset = mapped_alloc.offset();
3309       buffer_pointer = mapped_alloc.address();
3310     }
3311   }
3312 
3313   if (buffer_pointer) {
3314     CopyRectToBuffer(pixels, height, unpadded_row_size, padded_row_size,
3315                      buffer_pointer, service_padded_row_size);
3316     helper_->TexImage2D(target, level, internalformat, width, height, format,
3317                         type, shm_id, shm_offset);
3318     CheckGLError();
3319     return;
3320   }
3321 
3322   // No, so send it using TexSubImage2D.
3323   helper_->TexImage2D(target, level, internalformat, width, height, format,
3324                       type, 0, 0);
3325   TexSubImage2DImpl(target, level, 0, 0, width, height, format, type,
3326                     unpadded_row_size, pixels, padded_row_size, GL_TRUE,
3327                     &transfer_alloc, service_padded_row_size);
3328   CheckGLError();
3329 }
3330 
TexImage3D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)3331 void GLES2Implementation::TexImage3D(GLenum target,
3332                                      GLint level,
3333                                      GLint internalformat,
3334                                      GLsizei width,
3335                                      GLsizei height,
3336                                      GLsizei depth,
3337                                      GLint border,
3338                                      GLenum format,
3339                                      GLenum type,
3340                                      const void* pixels) {
3341   const char* func_name = "glTexImage3D";
3342   GPU_CLIENT_SINGLE_THREAD_CHECK();
3343   GPU_CLIENT_LOG(
3344       "[" << GetLogPrefix() << "] glTexImage3D("
3345           << GLES2Util::GetStringTextureTarget(target) << ", " << level << ", "
3346           << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
3347           << width << ", " << height << ", " << depth << ", " << border << ", "
3348           << GLES2Util::GetStringTextureFormat(format) << ", "
3349           << GLES2Util::GetStringPixelType(type) << ", "
3350           << static_cast<const void*>(pixels) << ")");
3351   if (level < 0 || height < 0 || width < 0 || depth < 0) {
3352     SetGLError(GL_INVALID_VALUE, func_name, "dimension < 0");
3353     return;
3354   }
3355   if (border != 0) {
3356     SetGLError(GL_INVALID_VALUE, func_name, "border != 0");
3357     return;
3358   }
3359   if ((bound_pixel_unpack_buffer_ || pixels) &&
3360       ((unpack_skip_pixels_ + width >
3361         (unpack_row_length_ ? unpack_row_length_ : width)) ||
3362        (unpack_skip_rows_ + height >
3363         (unpack_image_height_ ? unpack_image_height_ : height)))) {
3364     // This is WebGL 2 specific constraints, but we do it for all ES3 contexts.
3365     SetGLError(GL_INVALID_OPERATION, func_name,
3366                "invalid unpack params combination");
3367     return;
3368   }
3369 
3370   uint32_t size;
3371   uint32_t unpadded_row_size;
3372   uint32_t padded_row_size;
3373   uint32_t skip_size;
3374   PixelStoreParams params = GetUnpackParameters(k3D);
3375   if (!GLES2Util::ComputeImageDataSizesES3(
3376           width, height, depth, format, type, params, &size, &unpadded_row_size,
3377           &padded_row_size, &skip_size, nullptr)) {
3378     SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3379     return;
3380   }
3381 
3382   if (bound_pixel_unpack_buffer_) {
3383     base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels);
3384     offset += skip_size;
3385     if (!offset.IsValid()) {
3386       SetGLError(GL_INVALID_VALUE, func_name, "skip size too large");
3387       return;
3388     }
3389     helper_->TexImage3D(target, level, internalformat, width, height, depth,
3390                         format, type, 0, offset.ValueOrDefault(0));
3391     CheckGLError();
3392     return;
3393   }
3394 
3395   // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
3396   if (bound_pixel_unpack_transfer_buffer_id_) {
3397     if (unpack_row_length_ > 0 || unpack_image_height_ > 0 ||
3398         unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 ||
3399         unpack_skip_images_ > 0) {
3400       SetGLError(GL_INVALID_OPERATION, func_name,
3401                  "No ES3 pack parameters with pixel unpack transfer buffer.");
3402       return;
3403     }
3404     DCHECK_EQ(0u, skip_size);
3405     GLuint offset = ToGLuint(pixels);
3406     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3407         bound_pixel_unpack_transfer_buffer_id_, func_name, offset, size);
3408     if (buffer && buffer->shm_id() != -1) {
3409       helper_->TexImage3D(target, level, internalformat, width, height, depth,
3410                           format, type, buffer->shm_id(),
3411                           buffer->shm_offset() + offset);
3412       buffer->set_last_usage_token(helper_->InsertToken());
3413       CheckGLError();
3414     }
3415     return;
3416   }
3417 
3418   // If there's no data just issue TexImage3D
3419   if (!pixels || width == 0 || height == 0 || depth == 0) {
3420     helper_->TexImage3D(target, level, internalformat, width, height, depth,
3421                         format, type, 0, 0);
3422     CheckGLError();
3423     return;
3424   }
3425 
3426   // Compute the advance bytes per row on the service side.
3427   // Note |size| is recomputed here if needed.
3428   uint32_t service_padded_row_size;
3429   if ((unpack_row_length_ > 0 && unpack_row_length_ != width) ||
3430       (unpack_image_height_ > 0 && unpack_image_height_ != height)) {
3431     // All parameters have been applied to the data that are sent to the
3432     // service side except UNPACK_ALIGNMENT.
3433     PixelStoreParams service_params;
3434     service_params.alignment = unpack_alignment_;
3435     if (!GLES2Util::ComputeImageDataSizesES3(
3436             width, height, depth, format, type, service_params, &size, nullptr,
3437             &service_padded_row_size, nullptr, nullptr)) {
3438       SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3439       return;
3440     }
3441   } else {
3442     service_padded_row_size = padded_row_size;
3443   }
3444   uint32_t src_height =
3445       unpack_image_height_ > 0 ? unpack_image_height_ : height;
3446 
3447   // advance pixels pointer past the skip images/rows/pixels
3448   pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size;
3449 
3450   // Check if we can send it all at once.
3451   int32_t shm_id = 0;
3452   uint32_t shm_offset = 0;
3453   void* buffer_pointer = nullptr;
3454 
3455   ScopedTransferBufferPtr transfer_alloc(size, helper_, transfer_buffer_);
3456   ScopedMappedMemoryPtr mapped_alloc(0, helper_, mapped_memory_.get());
3457 
3458   if (transfer_alloc.valid() && transfer_alloc.size() >= size) {
3459     shm_id = transfer_alloc.shm_id();
3460     shm_offset = transfer_alloc.offset();
3461     buffer_pointer = transfer_alloc.address();
3462   } else if (size < max_extra_transfer_buffer_size_) {
3463     mapped_alloc.Reset(size);
3464     if (mapped_alloc.valid()) {
3465       transfer_alloc.Discard();
3466 
3467       mapped_alloc.SetFlushAfterRelease(true);
3468       shm_id = mapped_alloc.shm_id();
3469       shm_offset = mapped_alloc.offset();
3470       buffer_pointer = mapped_alloc.address();
3471     }
3472   }
3473 
3474   if (buffer_pointer) {
3475     for (GLsizei z = 0; z < depth; ++z) {
3476       CopyRectToBuffer(pixels, height, unpadded_row_size, padded_row_size,
3477                        buffer_pointer, service_padded_row_size);
3478       pixels = reinterpret_cast<const int8_t*>(pixels) +
3479                padded_row_size * src_height;
3480       buffer_pointer = reinterpret_cast<int8_t*>(buffer_pointer) +
3481                        service_padded_row_size * height;
3482     }
3483     helper_->TexImage3D(target, level, internalformat, width, height, depth,
3484                         format, type, shm_id, shm_offset);
3485     CheckGLError();
3486     return;
3487   }
3488 
3489   // No, so send it using TexSubImage3D.
3490   helper_->TexImage3D(target, level, internalformat, width, height, depth,
3491                       format, type, 0, 0);
3492   TexSubImage3DImpl(target, level, 0, 0, 0, width, height, depth, format, type,
3493                     unpadded_row_size, pixels, padded_row_size, GL_TRUE,
3494                     &transfer_alloc, service_padded_row_size);
3495   CheckGLError();
3496 }
3497 
TexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)3498 void GLES2Implementation::TexSubImage2D(GLenum target,
3499                                         GLint level,
3500                                         GLint xoffset,
3501                                         GLint yoffset,
3502                                         GLsizei width,
3503                                         GLsizei height,
3504                                         GLenum format,
3505                                         GLenum type,
3506                                         const void* pixels) {
3507   const char* func_name = "glTexSubImage2D";
3508   GPU_CLIENT_SINGLE_THREAD_CHECK();
3509   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
3510                      << GLES2Util::GetStringTextureTarget(target) << ", "
3511                      << level << ", " << xoffset << ", " << yoffset << ", "
3512                      << width << ", " << height << ", "
3513                      << GLES2Util::GetStringTextureFormat(format) << ", "
3514                      << GLES2Util::GetStringPixelType(type) << ", "
3515                      << static_cast<const void*>(pixels) << ")");
3516 
3517   if (level < 0 || height < 0 || width < 0 || xoffset < 0 || yoffset < 0) {
3518     SetGLError(GL_INVALID_VALUE, func_name, "dimension < 0");
3519     return;
3520   }
3521   if (unpack_skip_pixels_ + width >
3522       (unpack_row_length_ ? unpack_row_length_ : width)) {
3523     // This is WebGL 2 specific constraints, but we do it for all ES3 contexts.
3524     SetGLError(GL_INVALID_OPERATION, func_name,
3525                "invalid unpack params combination");
3526     return;
3527   }
3528 
3529   uint32_t size;
3530   uint32_t unpadded_row_size;
3531   uint32_t padded_row_size;
3532   uint32_t skip_size;
3533   PixelStoreParams params = GetUnpackParameters(k2D);
3534   if (!GLES2Util::ComputeImageDataSizesES3(
3535           width, height, 1, format, type, params, &size, &unpadded_row_size,
3536           &padded_row_size, &skip_size, nullptr)) {
3537     SetGLError(GL_INVALID_VALUE, func_name, "image size to large");
3538     return;
3539   }
3540 
3541   if (bound_pixel_unpack_buffer_) {
3542     base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels);
3543     offset += skip_size;
3544     if (!offset.IsValid()) {
3545       SetGLError(GL_INVALID_VALUE, func_name, "skip size too large");
3546       return;
3547     }
3548     helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height,
3549                            format, type, 0, offset.ValueOrDefault(0), false);
3550     CheckGLError();
3551     return;
3552   }
3553 
3554   // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
3555   if (bound_pixel_unpack_transfer_buffer_id_) {
3556     if (unpack_row_length_ > 0 || unpack_image_height_ > 0 ||
3557         unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 ||
3558         unpack_skip_images_ > 0) {
3559       SetGLError(GL_INVALID_OPERATION, func_name,
3560                  "No ES3 pack parameters with pixel unpack transfer buffer.");
3561       return;
3562     }
3563     DCHECK_EQ(0u, skip_size);
3564     GLuint offset = ToGLuint(pixels);
3565     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3566         bound_pixel_unpack_transfer_buffer_id_, func_name, offset, size);
3567     if (buffer && buffer->shm_id() != -1) {
3568       helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height,
3569                              format, type, buffer->shm_id(),
3570                              buffer->shm_offset() + offset, false);
3571       buffer->set_last_usage_token(helper_->InsertToken());
3572       CheckGLError();
3573     }
3574     return;
3575   }
3576 
3577   if (width == 0 || height == 0) {
3578     // No need to worry about pixel data.
3579     helper_->TexSubImage2D(target, level, xoffset, yoffset, width, height,
3580                            format, type, 0, 0, false);
3581     CheckGLError();
3582     return;
3583   }
3584 
3585   // Compute the advance bytes per row on the service side.
3586   // Note |size| is recomputed here if needed.
3587   uint32_t service_padded_row_size;
3588   if (unpack_row_length_ > 0 && unpack_row_length_ != width) {
3589     // All parameters have been applied to the data that are sent to the
3590     // service side except UNPACK_ALIGNMENT.
3591     PixelStoreParams service_params;
3592     service_params.alignment = unpack_alignment_;
3593     if (!GLES2Util::ComputeImageDataSizesES3(
3594             width, height, 1, format, type, service_params, &size, nullptr,
3595             &service_padded_row_size, nullptr, nullptr)) {
3596       SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3597       return;
3598     }
3599   } else {
3600     service_padded_row_size = padded_row_size;
3601   }
3602 
3603   // advance pixels pointer past the skip rows and skip pixels
3604   pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size;
3605 
3606   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
3607   base::CheckedNumeric<GLint> checked_xoffset = xoffset;
3608   checked_xoffset += width;
3609   if (!checked_xoffset.IsValid()) {
3610     SetGLError(GL_INVALID_VALUE, "TexSubImage2D", "xoffset + width overflows");
3611     return;
3612   }
3613   base::CheckedNumeric<GLint> checked_yoffset = yoffset;
3614   checked_yoffset += height;
3615   if (!checked_yoffset.IsValid()) {
3616     SetGLError(GL_INVALID_VALUE, "TexSubImage2D", "yoffset + height overflows");
3617     return;
3618   }
3619   TexSubImage2DImpl(target, level, xoffset, yoffset, width, height, format,
3620                     type, unpadded_row_size, pixels, padded_row_size, GL_FALSE,
3621                     &buffer, service_padded_row_size);
3622   CheckGLError();
3623 }
3624 
TexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)3625 void GLES2Implementation::TexSubImage3D(GLenum target,
3626                                         GLint level,
3627                                         GLint xoffset,
3628                                         GLint yoffset,
3629                                         GLint zoffset,
3630                                         GLsizei width,
3631                                         GLsizei height,
3632                                         GLsizei depth,
3633                                         GLenum format,
3634                                         GLenum type,
3635                                         const void* pixels) {
3636   const char* func_name = "glTexSubImage3D";
3637   GPU_CLIENT_SINGLE_THREAD_CHECK();
3638   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
3639                      << GLES2Util::GetStringTextureTarget(target) << ", "
3640                      << level << ", " << xoffset << ", " << yoffset << ", "
3641                      << zoffset << ", " << width << ", " << height << ", "
3642                      << depth << ", "
3643                      << GLES2Util::GetStringTextureFormat(format) << ", "
3644                      << GLES2Util::GetStringPixelType(type) << ", "
3645                      << static_cast<const void*>(pixels) << ")");
3646 
3647   if (level < 0 || height < 0 || width < 0 || depth < 0 || xoffset < 0 ||
3648       yoffset < 0 || zoffset < 0) {
3649     SetGLError(GL_INVALID_VALUE, func_name, "dimension < 0");
3650     return;
3651   }
3652   if ((unpack_skip_pixels_ + width >
3653        (unpack_row_length_ ? unpack_row_length_ : width)) ||
3654       (unpack_skip_rows_ + height >
3655        (unpack_image_height_ ? unpack_image_height_ : height))) {
3656     // This is WebGL 2 specific constraints, but we do it for all ES3 contexts.
3657     SetGLError(GL_INVALID_OPERATION, func_name,
3658                "invalid unpack params combination");
3659     return;
3660   }
3661 
3662   uint32_t size;
3663   uint32_t unpadded_row_size;
3664   uint32_t padded_row_size;
3665   uint32_t skip_size;
3666   PixelStoreParams params = GetUnpackParameters(k3D);
3667   if (!GLES2Util::ComputeImageDataSizesES3(
3668           width, height, depth, format, type, params, &size, &unpadded_row_size,
3669           &padded_row_size, &skip_size, nullptr)) {
3670     SetGLError(GL_INVALID_VALUE, func_name, "image size to large");
3671     return;
3672   }
3673 
3674   if (bound_pixel_unpack_buffer_) {
3675     base::CheckedNumeric<uint32_t> offset = ToGLuint(pixels);
3676     offset += skip_size;
3677     if (!offset.IsValid()) {
3678       SetGLError(GL_INVALID_VALUE, func_name, "skip size too large");
3679       return;
3680     }
3681     helper_->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
3682                            height, depth, format, type, 0,
3683                            offset.ValueOrDefault(0), false);
3684     CheckGLError();
3685     return;
3686   }
3687 
3688   // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
3689   if (bound_pixel_unpack_transfer_buffer_id_) {
3690     if (unpack_row_length_ > 0 || unpack_image_height_ > 0 ||
3691         unpack_skip_pixels_ > 0 || unpack_skip_rows_ > 0 ||
3692         unpack_skip_images_ > 0) {
3693       SetGLError(GL_INVALID_OPERATION, func_name,
3694                  "No ES3 pack parameters with pixel unpack transfer buffer.");
3695       return;
3696     }
3697     DCHECK_EQ(0u, skip_size);
3698     GLuint offset = ToGLuint(pixels);
3699     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
3700         bound_pixel_unpack_transfer_buffer_id_, func_name, offset, size);
3701     if (buffer && buffer->shm_id() != -1) {
3702       helper_->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
3703                              height, depth, format, type, buffer->shm_id(),
3704                              buffer->shm_offset() + offset, false);
3705       buffer->set_last_usage_token(helper_->InsertToken());
3706       CheckGLError();
3707     }
3708     return;
3709   }
3710 
3711   if (width == 0 || height == 0 || depth == 0) {
3712     // No need to worry about pixel data.
3713     helper_->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
3714                            height, depth, format, type, 0, 0, false);
3715     CheckGLError();
3716     return;
3717   }
3718 
3719   // Compute the advance bytes per row on the service side
3720   // Note |size| is recomputed here if needed.
3721   uint32_t service_padded_row_size;
3722   if ((unpack_row_length_ > 0 && unpack_row_length_ != width) ||
3723       (unpack_image_height_ > 0 && unpack_image_height_ != height)) {
3724     PixelStoreParams service_params;
3725     service_params.alignment = unpack_alignment_;
3726     if (!GLES2Util::ComputeImageDataSizesES3(
3727             width, height, depth, format, type, service_params, &size, nullptr,
3728             &service_padded_row_size, nullptr, nullptr)) {
3729       SetGLError(GL_INVALID_VALUE, func_name, "image size too large");
3730       return;
3731     }
3732   } else {
3733     service_padded_row_size = padded_row_size;
3734   }
3735 
3736   // advance pixels pointer past the skip images/rows/pixels
3737   pixels = reinterpret_cast<const int8_t*>(pixels) + skip_size;
3738 
3739   ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
3740   base::CheckedNumeric<GLint> checked_xoffset = xoffset;
3741   checked_xoffset += width;
3742   if (!checked_xoffset.IsValid()) {
3743     SetGLError(GL_INVALID_VALUE, "TexSubImage3D", "xoffset + width overflows");
3744     return;
3745   }
3746   base::CheckedNumeric<GLint> checked_yoffset = yoffset;
3747   checked_yoffset += height;
3748   if (!checked_yoffset.IsValid()) {
3749     SetGLError(GL_INVALID_VALUE, "TexSubImage3D", "yoffset + height overflows");
3750     return;
3751   }
3752   base::CheckedNumeric<GLint> checked_zoffset = zoffset;
3753   checked_zoffset += depth;
3754   if (!checked_zoffset.IsValid()) {
3755     SetGLError(GL_INVALID_VALUE, "TexSubImage3D", "zoffset + depth overflows");
3756     return;
3757   }
3758   TexSubImage3DImpl(target, level, xoffset, yoffset, zoffset, width, height,
3759                     depth, format, type, unpadded_row_size, pixels,
3760                     padded_row_size, GL_FALSE, &buffer,
3761                     service_padded_row_size);
3762   CheckGLError();
3763 }
3764 
ComputeNumRowsThatFitInBuffer(uint32_t padded_row_size,uint32_t unpadded_row_size,unsigned int size,GLsizei remaining_rows)3765 static GLint ComputeNumRowsThatFitInBuffer(uint32_t padded_row_size,
3766                                            uint32_t unpadded_row_size,
3767                                            unsigned int size,
3768                                            GLsizei remaining_rows) {
3769   DCHECK_GE(unpadded_row_size, 0u);
3770   if (padded_row_size == 0) {
3771     return 1;
3772   }
3773   GLint num_rows = size / padded_row_size;
3774   if (num_rows + 1 == remaining_rows &&
3775       size - num_rows * padded_row_size >= unpadded_row_size) {
3776     num_rows++;
3777   }
3778   return num_rows;
3779 }
3780 
TexSubImage2DImpl(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,uint32_t unpadded_row_size,const void * pixels,uint32_t pixels_padded_row_size,GLboolean internal,ScopedTransferBufferPtr * buffer,uint32_t buffer_padded_row_size)3781 void GLES2Implementation::TexSubImage2DImpl(GLenum target,
3782                                             GLint level,
3783                                             GLint xoffset,
3784                                             GLint yoffset,
3785                                             GLsizei width,
3786                                             GLsizei height,
3787                                             GLenum format,
3788                                             GLenum type,
3789                                             uint32_t unpadded_row_size,
3790                                             const void* pixels,
3791                                             uint32_t pixels_padded_row_size,
3792                                             GLboolean internal,
3793                                             ScopedTransferBufferPtr* buffer,
3794                                             uint32_t buffer_padded_row_size) {
3795   DCHECK(buffer);
3796   DCHECK_GE(level, 0);
3797   DCHECK_GT(height, 0);
3798   DCHECK_GT(width, 0);
3799   DCHECK_GE(xoffset, 0);
3800   DCHECK_GE(yoffset, 0);
3801 
3802   const int8_t* source = reinterpret_cast<const int8_t*>(pixels);
3803   // Transfer by rows.
3804   while (height) {
3805     unsigned int desired_size =
3806         buffer_padded_row_size * (height - 1) + unpadded_row_size;
3807     if (!buffer->valid() || buffer->size() == 0) {
3808       buffer->Reset(desired_size);
3809       if (!buffer->valid()) {
3810         return;
3811       }
3812     }
3813 
3814     GLint num_rows = ComputeNumRowsThatFitInBuffer(
3815         buffer_padded_row_size, unpadded_row_size, buffer->size(), height);
3816     num_rows = std::min(num_rows, height);
3817     CopyRectToBuffer(source, num_rows, unpadded_row_size,
3818                      pixels_padded_row_size, buffer->address(),
3819                      buffer_padded_row_size);
3820     helper_->TexSubImage2D(target, level, xoffset, yoffset, width, num_rows,
3821                            format, type, buffer->shm_id(), buffer->offset(),
3822                            internal);
3823     buffer->Release();
3824     yoffset += num_rows;
3825     source += num_rows * pixels_padded_row_size;
3826     height -= num_rows;
3827   }
3828 }
3829 
TexSubImage3DImpl(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,uint32_t unpadded_row_size,const void * pixels,uint32_t pixels_padded_row_size,GLboolean internal,ScopedTransferBufferPtr * buffer,uint32_t buffer_padded_row_size)3830 void GLES2Implementation::TexSubImage3DImpl(GLenum target,
3831                                             GLint level,
3832                                             GLint xoffset,
3833                                             GLint yoffset,
3834                                             GLsizei zoffset,
3835                                             GLsizei width,
3836                                             GLsizei height,
3837                                             GLsizei depth,
3838                                             GLenum format,
3839                                             GLenum type,
3840                                             uint32_t unpadded_row_size,
3841                                             const void* pixels,
3842                                             uint32_t pixels_padded_row_size,
3843                                             GLboolean internal,
3844                                             ScopedTransferBufferPtr* buffer,
3845                                             uint32_t buffer_padded_row_size) {
3846   DCHECK(buffer);
3847   DCHECK_GE(level, 0);
3848   DCHECK_GT(width, 0);
3849   DCHECK_GT(height, 0);
3850   DCHECK_GT(depth, 0);
3851   DCHECK_GE(xoffset, 0);
3852   DCHECK_GE(yoffset, 0);
3853   DCHECK_GE(zoffset, 0);
3854   const int8_t* source = reinterpret_cast<const int8_t*>(pixels);
3855   GLsizei total_rows = height * depth;
3856   GLint row_index = 0, depth_index = 0;
3857   while (total_rows) {
3858     // Each time, we either copy one or more images, or copy one or more rows
3859     // within a single image, depending on the buffer size limit.
3860     GLsizei max_rows;
3861     unsigned int desired_size;
3862     if (row_index > 0) {
3863       // We are in the middle of an image. Send the remaining of the image.
3864       max_rows = height - row_index;
3865       if (total_rows <= height) {
3866         // Last image, so last row is unpadded.
3867         desired_size =
3868             buffer_padded_row_size * (max_rows - 1) + unpadded_row_size;
3869       } else {
3870         desired_size = buffer_padded_row_size * max_rows;
3871       }
3872     } else {
3873       // Send all the remaining data if possible.
3874       max_rows = total_rows;
3875       desired_size =
3876           buffer_padded_row_size * (max_rows - 1) + unpadded_row_size;
3877     }
3878     if (!buffer->valid() || buffer->size() == 0) {
3879       buffer->Reset(desired_size);
3880       if (!buffer->valid()) {
3881         return;
3882       }
3883     }
3884     GLint num_rows = ComputeNumRowsThatFitInBuffer(
3885         buffer_padded_row_size, unpadded_row_size, buffer->size(), total_rows);
3886     num_rows = std::min(num_rows, max_rows);
3887     GLint num_images = num_rows / height;
3888     GLsizei my_height, my_depth;
3889     if (num_images > 0) {
3890       num_rows = num_images * height;
3891       my_height = height;
3892       my_depth = num_images;
3893     } else {
3894       my_height = num_rows;
3895       my_depth = 1;
3896     }
3897 
3898     if (num_images > 0) {
3899       int8_t* buffer_pointer = reinterpret_cast<int8_t*>(buffer->address());
3900       uint32_t src_height =
3901           unpack_image_height_ > 0 ? unpack_image_height_ : height;
3902       uint32_t image_size_dst = buffer_padded_row_size * height;
3903       uint32_t image_size_src = pixels_padded_row_size * src_height;
3904       for (GLint ii = 0; ii < num_images; ++ii) {
3905         CopyRectToBuffer(source + ii * image_size_src, my_height,
3906                          unpadded_row_size, pixels_padded_row_size,
3907                          buffer_pointer + ii * image_size_dst,
3908                          buffer_padded_row_size);
3909       }
3910     } else {
3911       CopyRectToBuffer(source, my_height, unpadded_row_size,
3912                        pixels_padded_row_size, buffer->address(),
3913                        buffer_padded_row_size);
3914     }
3915     helper_->TexSubImage3D(target, level, xoffset, yoffset + row_index,
3916                            zoffset + depth_index, width, my_height, my_depth,
3917                            format, type, buffer->shm_id(), buffer->offset(),
3918                            internal);
3919     buffer->Release();
3920 
3921     total_rows -= num_rows;
3922     if (total_rows > 0) {
3923       GLint num_image_paddings;
3924       if (num_images > 0) {
3925         DCHECK_EQ(row_index, 0);
3926         depth_index += num_images;
3927         num_image_paddings = num_images;
3928       } else {
3929         row_index = (row_index + my_height) % height;
3930         num_image_paddings = 0;
3931         if (my_height > 0 && row_index == 0) {
3932           depth_index++;
3933           num_image_paddings++;
3934         }
3935       }
3936       source += num_rows * pixels_padded_row_size;
3937       if (unpack_image_height_ > height && num_image_paddings > 0) {
3938         source += num_image_paddings * (unpack_image_height_ - height) *
3939                   pixels_padded_row_size;
3940       }
3941     }
3942   }
3943 }
3944 
GetResultNameHelper(GLsizei bufsize,GLsizei * length,char * name)3945 void GLES2Implementation::GetResultNameHelper(GLsizei bufsize,
3946                                               GLsizei* length,
3947                                               char* name) {
3948   // Length of string (without final \0) that we will write to the buffer.
3949   GLsizei max_length = 0;
3950   if (name && (bufsize > 0)) {
3951     std::vector<int8_t> str;
3952     GetBucketContents(kResultBucketId, &str);
3953     if (!str.empty()) {
3954       DCHECK_LE(str.size(), static_cast<size_t>(INT_MAX));
3955       // Note: both bufsize and str.size() count/include the terminating \0.
3956       max_length = std::min(bufsize, static_cast<GLsizei>(str.size())) - 1;
3957     }
3958     memcpy(name, str.data(), max_length);
3959     name[max_length] = '\0';
3960   }
3961   if (length) {
3962     *length = max_length;
3963   }
3964 }
3965 
GetActiveAttribHelper(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)3966 bool GLES2Implementation::GetActiveAttribHelper(GLuint program,
3967                                                 GLuint index,
3968                                                 GLsizei bufsize,
3969                                                 GLsizei* length,
3970                                                 GLint* size,
3971                                                 GLenum* type,
3972                                                 char* name) {
3973   // Clear the bucket so if the command fails nothing will be in it.
3974   helper_->SetBucketSize(kResultBucketId, 0);
3975   typedef cmds::GetActiveAttrib::Result Result;
3976   auto result = GetResultAs<Result>();
3977   if (!result) {
3978     return false;
3979   }
3980   // Set as failed so if the command fails we'll recover.
3981   result->success = false;
3982   helper_->GetActiveAttrib(program, index, kResultBucketId, GetResultShmId(),
3983                            result.offset());
3984   WaitForCmd();
3985   bool success = !!result->success;
3986   if (success) {
3987     if (size) {
3988       *size = result->size;
3989     }
3990     if (type) {
3991       *type = result->type;
3992     }
3993     // Note: this can invalidate |result|.
3994     GetResultNameHelper(bufsize, length, name);
3995   }
3996   return success;
3997 }
3998 
GetActiveAttrib(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)3999 void GLES2Implementation::GetActiveAttrib(GLuint program,
4000                                           GLuint index,
4001                                           GLsizei bufsize,
4002                                           GLsizei* length,
4003                                           GLint* size,
4004                                           GLenum* type,
4005                                           char* name) {
4006   GPU_CLIENT_SINGLE_THREAD_CHECK();
4007   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib(" << program
4008                      << ", " << index << ", " << bufsize << ", "
4009                      << static_cast<const void*>(length) << ", "
4010                      << static_cast<const void*>(size) << ", "
4011                      << static_cast<const void*>(type) << ", "
4012                      << static_cast<const void*>(name) << ", ");
4013   if (bufsize < 0) {
4014     SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "bufsize < 0");
4015     return;
4016   }
4017   TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
4018   bool success = share_group_->program_info_manager()->GetActiveAttrib(
4019       this, program, index, bufsize, length, size, type, name);
4020   if (success) {
4021     if (size) {
4022       GPU_CLIENT_LOG("  size: " << *size);
4023     }
4024     if (type) {
4025       GPU_CLIENT_LOG("  type: " << GLES2Util::GetStringEnum(*type));
4026     }
4027     if (name) {
4028       GPU_CLIENT_LOG("  name: " << name);
4029     }
4030   }
4031   CheckGLError();
4032 }
4033 
GetActiveUniformHelper(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)4034 bool GLES2Implementation::GetActiveUniformHelper(GLuint program,
4035                                                  GLuint index,
4036                                                  GLsizei bufsize,
4037                                                  GLsizei* length,
4038                                                  GLint* size,
4039                                                  GLenum* type,
4040                                                  char* name) {
4041   // Clear the bucket so if the command fails nothing will be in it.
4042   helper_->SetBucketSize(kResultBucketId, 0);
4043   typedef cmds::GetActiveUniform::Result Result;
4044   auto result = GetResultAs<Result>();
4045   if (!result) {
4046     return false;
4047   }
4048   // Set as failed so if the command fails we'll recover.
4049   result->success = false;
4050   helper_->GetActiveUniform(program, index, kResultBucketId, GetResultShmId(),
4051                             result.offset());
4052   WaitForCmd();
4053   bool success = !!result->success;
4054   if (success) {
4055     if (size) {
4056       *size = result->size;
4057     }
4058     if (type) {
4059       *type = result->type;
4060     }
4061     // Note: this can invalidate |result|.
4062     GetResultNameHelper(bufsize, length, name);
4063   }
4064   return success;
4065 }
4066 
GetActiveUniform(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)4067 void GLES2Implementation::GetActiveUniform(GLuint program,
4068                                            GLuint index,
4069                                            GLsizei bufsize,
4070                                            GLsizei* length,
4071                                            GLint* size,
4072                                            GLenum* type,
4073                                            char* name) {
4074   GPU_CLIENT_SINGLE_THREAD_CHECK();
4075   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform(" << program
4076                      << ", " << index << ", " << bufsize << ", "
4077                      << static_cast<const void*>(length) << ", "
4078                      << static_cast<const void*>(size) << ", "
4079                      << static_cast<const void*>(type) << ", "
4080                      << static_cast<const void*>(name) << ", ");
4081   if (bufsize < 0) {
4082     SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "bufsize < 0");
4083     return;
4084   }
4085   TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
4086   bool success = share_group_->program_info_manager()->GetActiveUniform(
4087       this, program, index, bufsize, length, size, type, name);
4088   if (success) {
4089     if (size) {
4090       GPU_CLIENT_LOG("  size: " << *size);
4091     }
4092     if (type) {
4093       GPU_CLIENT_LOG("  type: " << GLES2Util::GetStringEnum(*type));
4094     }
4095     if (name) {
4096       GPU_CLIENT_LOG("  name: " << name);
4097     }
4098   }
4099   CheckGLError();
4100 }
4101 
GetActiveUniformBlockNameHelper(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,char * name)4102 bool GLES2Implementation::GetActiveUniformBlockNameHelper(GLuint program,
4103                                                           GLuint index,
4104                                                           GLsizei bufsize,
4105                                                           GLsizei* length,
4106                                                           char* name) {
4107   DCHECK_LE(0, bufsize);
4108   // Clear the bucket so if the command fails nothing will be in it.
4109   helper_->SetBucketSize(kResultBucketId, 0);
4110   typedef cmds::GetActiveUniformBlockName::Result Result;
4111   auto result = GetResultAs<Result>();
4112   if (!result) {
4113     return false;
4114   }
4115   // Set as failed so if the command fails we'll recover.
4116   *result = 0;
4117   helper_->GetActiveUniformBlockName(program, index, kResultBucketId,
4118                                      GetResultShmId(), result.offset());
4119   WaitForCmd();
4120   bool success = !!result;
4121   if (success) {
4122     // Note: this can invalidate |result|.
4123     GetResultNameHelper(bufsize, length, name);
4124   }
4125   return success;
4126 }
4127 
GetActiveUniformBlockName(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,char * name)4128 void GLES2Implementation::GetActiveUniformBlockName(GLuint program,
4129                                                     GLuint index,
4130                                                     GLsizei bufsize,
4131                                                     GLsizei* length,
4132                                                     char* name) {
4133   GPU_CLIENT_SINGLE_THREAD_CHECK();
4134   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
4135                      << program << ", " << index << ", " << bufsize << ", "
4136                      << static_cast<const void*>(length) << ", "
4137                      << static_cast<const void*>(name) << ")");
4138   if (bufsize < 0) {
4139     SetGLError(GL_INVALID_VALUE, "glGetActiveUniformBlockName", "bufsize < 0");
4140     return;
4141   }
4142   TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
4143   bool success =
4144       share_group_->program_info_manager()->GetActiveUniformBlockName(
4145           this, program, index, bufsize, length, name);
4146   if (success) {
4147     if (name) {
4148       GPU_CLIENT_LOG("  name: " << name);
4149     }
4150   }
4151   CheckGLError();
4152 }
4153 
GetActiveUniformBlockivHelper(GLuint program,GLuint index,GLenum pname,GLint * params)4154 bool GLES2Implementation::GetActiveUniformBlockivHelper(GLuint program,
4155                                                         GLuint index,
4156                                                         GLenum pname,
4157                                                         GLint* params) {
4158   typedef cmds::GetActiveUniformBlockiv::Result Result;
4159   auto result = GetResultAs<Result>();
4160   if (!result) {
4161     return false;
4162   }
4163   result->SetNumResults(0);
4164   helper_->GetActiveUniformBlockiv(program, index, pname, GetResultShmId(),
4165                                    result.offset());
4166   WaitForCmd();
4167   if (result->GetNumResults() > 0) {
4168     if (params) {
4169       result->CopyResult(params);
4170     }
4171     GPU_CLIENT_LOG_CODE_BLOCK({
4172       for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4173         GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4174       }
4175     });
4176     return true;
4177   }
4178   return false;
4179 }
4180 
GetActiveUniformBlockiv(GLuint program,GLuint index,GLenum pname,GLint * params)4181 void GLES2Implementation::GetActiveUniformBlockiv(GLuint program,
4182                                                   GLuint index,
4183                                                   GLenum pname,
4184                                                   GLint* params) {
4185   GPU_CLIENT_SINGLE_THREAD_CHECK();
4186   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
4187                      << program << ", " << index << ", "
4188                      << GLES2Util::GetStringUniformBlockParameter(pname) << ", "
4189                      << static_cast<const void*>(params) << ")");
4190   TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
4191   bool success = share_group_->program_info_manager()->GetActiveUniformBlockiv(
4192       this, program, index, pname, params);
4193   if (success) {
4194     if (params) {
4195       // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
4196       // be more than one value returned in params.
4197       GPU_CLIENT_LOG("  params: " << params[0]);
4198     }
4199   }
4200   CheckGLError();
4201 }
4202 
GetActiveUniformsivHelper(GLuint program,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)4203 bool GLES2Implementation::GetActiveUniformsivHelper(GLuint program,
4204                                                     GLsizei count,
4205                                                     const GLuint* indices,
4206                                                     GLenum pname,
4207                                                     GLint* params) {
4208   base::CheckedNumeric<uint32_t> bytes = count;
4209   bytes *= sizeof(GLuint);
4210   if (!bytes.IsValid()) {
4211     SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count overflow");
4212     return false;
4213   }
4214   SetBucketContents(kResultBucketId, indices, bytes.ValueOrDefault(0));
4215   typedef cmds::GetActiveUniformsiv::Result Result;
4216   auto result = GetResultAs<Result>();
4217   if (!result) {
4218     return false;
4219   }
4220   result->SetNumResults(0);
4221   helper_->GetActiveUniformsiv(program, kResultBucketId, pname,
4222                                GetResultShmId(), result.offset());
4223   WaitForCmd();
4224   bool success = result->GetNumResults() == count;
4225   if (success) {
4226     if (params) {
4227       result->CopyResult(params);
4228     }
4229     GPU_CLIENT_LOG_CODE_BLOCK({
4230       for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4231         GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4232       }
4233     });
4234   }
4235   helper_->SetBucketSize(kResultBucketId, 0);
4236   return success;
4237 }
4238 
GetActiveUniformsiv(GLuint program,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)4239 void GLES2Implementation::GetActiveUniformsiv(GLuint program,
4240                                               GLsizei count,
4241                                               const GLuint* indices,
4242                                               GLenum pname,
4243                                               GLint* params) {
4244   GPU_CLIENT_SINGLE_THREAD_CHECK();
4245   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv(" << program
4246                      << ", " << count << ", "
4247                      << static_cast<const void*>(indices) << ", "
4248                      << GLES2Util::GetStringUniformParameter(pname) << ", "
4249                      << static_cast<const void*>(params) << ")");
4250   TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
4251   if (count < 0) {
4252     SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count < 0");
4253     return;
4254   }
4255   bool success = share_group_->program_info_manager()->GetActiveUniformsiv(
4256       this, program, count, indices, pname, params);
4257   if (success) {
4258     if (params) {
4259       GPU_CLIENT_LOG_CODE_BLOCK({
4260         for (GLsizei ii = 0; ii < count; ++ii) {
4261           GPU_CLIENT_LOG("  " << ii << ": " << params[ii]);
4262         }
4263       });
4264     }
4265   }
4266   CheckGLError();
4267 }
4268 
GetAttachedShaders(GLuint program,GLsizei maxcount,GLsizei * count,GLuint * shaders)4269 void GLES2Implementation::GetAttachedShaders(GLuint program,
4270                                              GLsizei maxcount,
4271                                              GLsizei* count,
4272                                              GLuint* shaders) {
4273   GPU_CLIENT_SINGLE_THREAD_CHECK();
4274   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders(" << program
4275                      << ", " << maxcount << ", "
4276                      << static_cast<const void*>(count) << ", "
4277                      << static_cast<const void*>(shaders) << ", ");
4278   if (maxcount < 0) {
4279     SetGLError(GL_INVALID_VALUE, "glGetAttachedShaders", "maxcount < 0");
4280     return;
4281   }
4282   TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
4283   typedef cmds::GetAttachedShaders::Result Result;
4284   uint32_t checked_size = 0;
4285   if (!Result::ComputeSize(maxcount).AssignIfValid(&checked_size)) {
4286     SetGLError(GL_OUT_OF_MEMORY, "glGetAttachedShaders",
4287                "allocation too large");
4288     return;
4289   }
4290   Result* result = static_cast<Result*>(transfer_buffer_->Alloc(checked_size));
4291   if (!result) {
4292     return;
4293   }
4294   result->SetNumResults(0);
4295   helper_->GetAttachedShaders(program, transfer_buffer_->GetShmId(),
4296                               transfer_buffer_->GetOffset(result),
4297                               checked_size);
4298   int32_t token = helper_->InsertToken();
4299   WaitForCmd();
4300   if (count) {
4301     *count = result->GetNumResults();
4302   }
4303   result->CopyResult(shaders);
4304   GPU_CLIENT_LOG_CODE_BLOCK({
4305     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4306       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4307     }
4308   });
4309   transfer_buffer_->FreePendingToken(result, token);
4310   CheckGLError();
4311 }
4312 
GetShaderPrecisionFormat(GLenum shadertype,GLenum precisiontype,GLint * range,GLint * precision)4313 void GLES2Implementation::GetShaderPrecisionFormat(GLenum shadertype,
4314                                                    GLenum precisiontype,
4315                                                    GLint* range,
4316                                                    GLint* precision) {
4317   GPU_CLIENT_SINGLE_THREAD_CHECK();
4318   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
4319                      << GLES2Util::GetStringShaderType(shadertype) << ", "
4320                      << GLES2Util::GetStringShaderPrecision(precisiontype)
4321                      << ", " << static_cast<const void*>(range) << ", "
4322                      << static_cast<const void*>(precision) << ", ");
4323   TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
4324   typedef cmds::GetShaderPrecisionFormat::Result Result;
4325   auto result = GetResultAs<Result>();
4326   if (!result) {
4327     return;
4328   }
4329 
4330   GLStaticState::ShaderPrecisionKey key(shadertype, precisiontype);
4331   GLStaticState::ShaderPrecisionMap::iterator i =
4332       static_state_.shader_precisions.find(key);
4333   if (i != static_state_.shader_precisions.end()) {
4334     *result = i->second;
4335   } else {
4336     result->success = false;
4337     helper_->GetShaderPrecisionFormat(shadertype, precisiontype,
4338                                       GetResultShmId(), result.offset());
4339     WaitForCmd();
4340     if (result->success)
4341       static_state_.shader_precisions[key] = *result;
4342   }
4343 
4344   if (result->success) {
4345     if (range) {
4346       range[0] = result->min_range;
4347       range[1] = result->max_range;
4348       GPU_CLIENT_LOG("  min_range: " << range[0]);
4349       GPU_CLIENT_LOG("  min_range: " << range[1]);
4350     }
4351     if (precision) {
4352       precision[0] = result->precision;
4353       GPU_CLIENT_LOG("  min_range: " << precision[0]);
4354     }
4355   }
4356   CheckGLError();
4357 }
4358 
GetStringHelper(GLenum name)4359 const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) {
4360   if (name == GL_EXTENSIONS && cached_extension_string_) {
4361     return reinterpret_cast<const GLubyte*>(cached_extension_string_);
4362   }
4363   const char* result = nullptr;
4364   // Clears the bucket so if the command fails nothing will be in it.
4365   helper_->SetBucketSize(kResultBucketId, 0);
4366   helper_->GetString(name, kResultBucketId);
4367   std::string str;
4368   if (GetBucketAsString(kResultBucketId, &str)) {
4369     // Adds extensions implemented on client side only.
4370     if (name == GL_EXTENSIONS) {
4371       str += std::string(str.empty() ? "" : " ") +
4372              "GL_CHROMIUM_image "
4373              "GL_CHROMIUM_map_sub "
4374              "GL_CHROMIUM_ordering_barrier "
4375              "GL_CHROMIUM_sync_point "
4376              "GL_EXT_unpack_subimage";
4377     }
4378 
4379     // Because of WebGL the extensions can change. We have to cache each unique
4380     // result since we don't know when the client will stop referring to a
4381     // previous one it queries.
4382     // TODO: Here we could save memory by defining RequestExtensions
4383     // invalidating the GL_EXTENSIONS string. http://crbug.com/586414
4384     const std::string& cache = *gl_strings_.insert(str).first;
4385     result = cache.c_str();
4386 
4387     if (name == GL_EXTENSIONS) {
4388       cached_extension_string_ = result;
4389       std::vector<std::string> extensions =
4390           base::SplitString(cache, base::kWhitespaceASCII,
4391                             base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
4392       for (const std::string& extension : extensions) {
4393         cached_extensions_.push_back(
4394             gl_strings_.insert(extension).first->c_str());
4395       }
4396     }
4397   }
4398   return reinterpret_cast<const GLubyte*>(result);
4399 }
4400 
GetString(GLenum name)4401 const GLubyte* GLES2Implementation::GetString(GLenum name) {
4402   GPU_CLIENT_SINGLE_THREAD_CHECK();
4403   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
4404                      << GLES2Util::GetStringStringType(name) << ")");
4405   TRACE_EVENT0("gpu", "GLES2::GetString");
4406   const GLubyte* result = GetStringHelper(name);
4407   GPU_CLIENT_LOG("  returned " << reinterpret_cast<const char*>(result));
4408   CheckGLError();
4409   return result;
4410 }
4411 
GetStringi(GLenum name,GLuint index)4412 const GLubyte* GLES2Implementation::GetStringi(GLenum name, GLuint index) {
4413   GPU_CLIENT_SINGLE_THREAD_CHECK();
4414   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetStringi("
4415                      << GLES2Util::GetStringStringType(name) << "," << index
4416                      << ")");
4417   TRACE_EVENT0("gpu", "GLES2::GetStringi");
4418   UpdateCachedExtensionsIfNeeded();
4419   if (name != GL_EXTENSIONS) {
4420     SetGLError(GL_INVALID_ENUM, "glGetStringi", "name");
4421     return nullptr;
4422   }
4423   if (index >= cached_extensions_.size()) {
4424     SetGLError(GL_INVALID_VALUE, "glGetStringi", "index too large");
4425     return nullptr;
4426   }
4427 
4428   const char* result = cached_extensions_[index];
4429   GPU_CLIENT_LOG("  returned " << result);
4430   CheckGLError();
4431   return reinterpret_cast<const GLubyte*>(result);
4432 }
4433 
GetTransformFeedbackVaryingHelper(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)4434 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(GLuint program,
4435                                                             GLuint index,
4436                                                             GLsizei bufsize,
4437                                                             GLsizei* length,
4438                                                             GLint* size,
4439                                                             GLenum* type,
4440                                                             char* name) {
4441   // Clear the bucket so if the command fails nothing will be in it.
4442   helper_->SetBucketSize(kResultBucketId, 0);
4443   typedef cmds::GetTransformFeedbackVarying::Result Result;
4444   auto result = GetResultAs<Result>();
4445   if (!result) {
4446     return false;
4447   }
4448   // Set as failed so if the command fails we'll recover.
4449   result->success = false;
4450   helper_->GetTransformFeedbackVarying(program, index, kResultBucketId,
4451                                        GetResultShmId(), result.offset());
4452   WaitForCmd();
4453   if (result->success) {
4454     if (size) {
4455       *size = result->size;
4456     }
4457     if (type) {
4458       *type = result->type;
4459     }
4460     // Note: this can invalidate |result|.
4461     GetResultNameHelper(bufsize, length, name);
4462   }
4463   return result->success != 0;
4464 }
4465 
GetTransformFeedbackVarying(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,char * name)4466 void GLES2Implementation::GetTransformFeedbackVarying(GLuint program,
4467                                                       GLuint index,
4468                                                       GLsizei bufsize,
4469                                                       GLsizei* length,
4470                                                       GLint* size,
4471                                                       GLenum* type,
4472                                                       char* name) {
4473   GPU_CLIENT_SINGLE_THREAD_CHECK();
4474   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
4475                      << program << ", " << index << ", " << bufsize << ", "
4476                      << static_cast<const void*>(length) << ", "
4477                      << static_cast<const void*>(size) << ", "
4478                      << static_cast<const void*>(type) << ", "
4479                      << static_cast<const void*>(name) << ", ");
4480   if (bufsize < 0) {
4481     SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVarying",
4482                "bufsize < 0");
4483     return;
4484   }
4485   TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
4486   bool success =
4487       share_group_->program_info_manager()->GetTransformFeedbackVarying(
4488           this, program, index, bufsize, length, size, type, name);
4489   if (success) {
4490     if (size) {
4491       GPU_CLIENT_LOG("  size: " << *size);
4492     }
4493     if (type) {
4494       GPU_CLIENT_LOG("  type: " << GLES2Util::GetStringEnum(*type));
4495     }
4496     if (name) {
4497       GPU_CLIENT_LOG("  name: " << name);
4498     }
4499   }
4500   CheckGLError();
4501 }
4502 
GetUniformfv(GLuint program,GLint location,GLfloat * params)4503 void GLES2Implementation::GetUniformfv(GLuint program,
4504                                        GLint location,
4505                                        GLfloat* params) {
4506   GPU_CLIENT_SINGLE_THREAD_CHECK();
4507   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv(" << program << ", "
4508                      << location << ", " << static_cast<const void*>(params)
4509                      << ")");
4510   TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
4511   typedef cmds::GetUniformfv::Result Result;
4512   auto result = GetResultAs<Result>();
4513   if (!result) {
4514     return;
4515   }
4516   result->SetNumResults(0);
4517   helper_->GetUniformfv(program, location, GetResultShmId(), result.offset());
4518   WaitForCmd();
4519   result->CopyResult(params);
4520   GPU_CLIENT_LOG_CODE_BLOCK({
4521     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4522       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4523     }
4524   });
4525   CheckGLError();
4526 }
4527 
GetUniformiv(GLuint program,GLint location,GLint * params)4528 void GLES2Implementation::GetUniformiv(GLuint program,
4529                                        GLint location,
4530                                        GLint* params) {
4531   GPU_CLIENT_SINGLE_THREAD_CHECK();
4532   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv(" << program << ", "
4533                      << location << ", " << static_cast<const void*>(params)
4534                      << ")");
4535   TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
4536   typedef cmds::GetUniformiv::Result Result;
4537   auto result = GetResultAs<Result>();
4538   if (!result) {
4539     return;
4540   }
4541   result->SetNumResults(0);
4542   helper_->GetUniformiv(program, location, GetResultShmId(), result.offset());
4543   WaitForCmd();
4544   result->CopyResult(params);
4545   GPU_CLIENT_LOG_CODE_BLOCK({
4546     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4547       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4548     }
4549   });
4550   CheckGLError();
4551 }
4552 
GetUniformuiv(GLuint program,GLint location,GLuint * params)4553 void GLES2Implementation::GetUniformuiv(GLuint program,
4554                                         GLint location,
4555                                         GLuint* params) {
4556   GPU_CLIENT_SINGLE_THREAD_CHECK();
4557   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv(" << program
4558                      << ", " << location << ", "
4559                      << static_cast<const void*>(params) << ")");
4560   TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
4561   typedef cmds::GetUniformuiv::Result Result;
4562   auto result = GetResultAs<Result>();
4563   if (!result) {
4564     return;
4565   }
4566   result->SetNumResults(0);
4567   helper_->GetUniformuiv(program, location, GetResultShmId(), result.offset());
4568   WaitForCmd();
4569   result->CopyResult(params);
4570   GPU_CLIENT_LOG_CODE_BLOCK({
4571     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
4572       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
4573     }
4574   });
4575   CheckGLError();
4576 }
4577 
ReadPixels(GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,void * pixels)4578 void GLES2Implementation::ReadPixels(GLint xoffset,
4579                                      GLint yoffset,
4580                                      GLsizei width,
4581                                      GLsizei height,
4582                                      GLenum format,
4583                                      GLenum type,
4584                                      void* pixels) {
4585   const char* func_name = "glReadPixels";
4586   GPU_CLIENT_SINGLE_THREAD_CHECK();
4587   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels(" << xoffset << ", "
4588                      << yoffset << ", " << width << ", " << height << ", "
4589                      << GLES2Util::GetStringReadPixelFormat(format) << ", "
4590                      << GLES2Util::GetStringPixelType(type) << ", "
4591                      << static_cast<const void*>(pixels) << ")");
4592   if (width < 0 || height < 0) {
4593     SetGLError(GL_INVALID_VALUE, func_name, "dimensions < 0");
4594     return;
4595   }
4596 
4597   if (pack_skip_pixels_ + width >
4598       (pack_row_length_ ? pack_row_length_ : width)) {
4599     // This is WebGL 2 specific constraints, but we do it for all ES3 contexts.
4600     SetGLError(GL_INVALID_OPERATION, func_name,
4601                "invalid pack params combination");
4602     return;
4603   }
4604 
4605   // glReadPixel pads the size of each row of pixels by an amount specified by
4606   // glPixelStorei. So, we have to take that into account both in the fact that
4607   // the pixels returned from the ReadPixel command will include that padding
4608   // and that when we copy the results to the user's buffer we need to not
4609   // write those padding bytes but leave them as they are.
4610 
4611   TRACE_EVENT0("gpu", "GLES2::ReadPixels");
4612   typedef cmds::ReadPixels::Result Result;
4613 
4614   uint32_t size;
4615   uint32_t unpadded_row_size;
4616   uint32_t padded_row_size;
4617   uint32_t skip_size;
4618   PixelStoreParams params;
4619   params.alignment = pack_alignment_;
4620   params.row_length = pack_row_length_;
4621   params.skip_pixels = pack_skip_pixels_;
4622   params.skip_rows = pack_skip_rows_;
4623   if (!GLES2Util::ComputeImageDataSizesES3(
4624           width, height, 1, format, type, params, &size, &unpadded_row_size,
4625           &padded_row_size, &skip_size, nullptr)) {
4626     SetGLError(GL_INVALID_VALUE, func_name, "size too large.");
4627     return;
4628   }
4629 
4630   if (bound_pixel_pack_buffer_) {
4631     base::CheckedNumeric<GLuint> offset = ToGLuint(pixels);
4632     offset += skip_size;
4633     if (!offset.IsValid()) {
4634       SetGLError(GL_INVALID_VALUE, func_name, "skip size too large.");
4635       return;
4636     }
4637     helper_->ReadPixels(xoffset, yoffset, width, height, format, type, 0,
4638                         offset.ValueOrDefault(0), 0, 0, false);
4639     InvalidateReadbackBufferShadowDataCHROMIUM(bound_pixel_pack_buffer_);
4640 
4641     CheckGLError();
4642     return;
4643   }
4644 
4645   uint32_t service_padded_row_size = 0;
4646   if (pack_row_length_ > 0 && pack_row_length_ != width) {
4647     if (!GLES2Util::ComputeImagePaddedRowSize(
4648             width, format, type, pack_alignment_, &service_padded_row_size)) {
4649       SetGLError(GL_INVALID_VALUE, func_name, "size too large.");
4650       return;
4651     }
4652   } else {
4653     service_padded_row_size = padded_row_size;
4654   }
4655 
4656   if (bound_pixel_pack_transfer_buffer_id_) {
4657     if (pack_row_length_ > 0 || pack_skip_pixels_ > 0 || pack_skip_rows_ > 0) {
4658       SetGLError(GL_INVALID_OPERATION, func_name,
4659                  "No ES3 pack parameters with pixel pack transfer buffer.");
4660       return;
4661     }
4662     DCHECK_EQ(0u, skip_size);
4663     GLuint offset = ToGLuint(pixels);
4664     BufferTracker::Buffer* buffer = GetBoundPixelTransferBufferIfValid(
4665         bound_pixel_pack_transfer_buffer_id_, func_name, offset, size);
4666     if (buffer && buffer->shm_id() != -1) {
4667       helper_->ReadPixels(xoffset, yoffset, width, height, format, type,
4668                           buffer->shm_id(), buffer->shm_offset() + offset, 0, 0,
4669                           true);
4670       CheckGLError();
4671     }
4672     return;
4673   }
4674 
4675   if (!pixels) {
4676     SetGLError(GL_INVALID_OPERATION, func_name, "pixels = NULL");
4677     return;
4678   }
4679 
4680   int8_t* dest = reinterpret_cast<int8_t*>(pixels);
4681   // Advance pixels pointer past the skip rows and skip pixels
4682   dest += skip_size;
4683 
4684   // Transfer by rows.
4685   // The max rows we can transfer.
4686   GLsizei remaining_rows = height;
4687   GLint y_index = yoffset;
4688   uint32_t group_size = GLES2Util::ComputeImageGroupSize(format, type);
4689   uint32_t skip_row_bytes = 0;
4690   if (xoffset < 0) {
4691     skip_row_bytes = static_cast<uint32_t>(-xoffset) * group_size;
4692   }
4693   do {
4694     // Even if height == 0, we still need to trigger the service side handling
4695     // in case invalid args are passed in and a GL errro needs to be generated.
4696     GLsizei desired_size =
4697         remaining_rows == 0 ? 0
4698                             : service_padded_row_size * (remaining_rows - 1) +
4699                                   unpadded_row_size;
4700     ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_);
4701     if (!buffer.valid()) {
4702       break;
4703     }
4704     GLint num_rows = ComputeNumRowsThatFitInBuffer(
4705         service_padded_row_size, unpadded_row_size, buffer.size(),
4706         remaining_rows);
4707     // NOTE: We must look up the address of the result area AFTER allocation
4708     // of the transfer buffer since the transfer buffer may be reallocated.
4709     auto result = GetResultAs<Result>();
4710     if (!result) {
4711       break;
4712     }
4713     result->success = 0;  // mark as failed.
4714     result->row_length = 0;
4715     result->num_rows = 0;
4716     helper_->ReadPixels(xoffset, y_index, width, num_rows, format, type,
4717                         buffer.shm_id(), buffer.offset(), GetResultShmId(),
4718                         result.offset(), false);
4719     WaitForCmd();
4720     // If it was not marked as successful exit.
4721     if (!result->success) {
4722       break;
4723     }
4724     if (remaining_rows == 0) {
4725       break;
4726     }
4727     const uint8_t* src = static_cast<const uint8_t*>(buffer.address());
4728     if (padded_row_size == unpadded_row_size &&
4729         (pack_row_length_ == 0 || pack_row_length_ == width) &&
4730         result->row_length == width && result->num_rows == num_rows) {
4731       // The pixels are tightly packed.
4732       uint32_t copy_size = unpadded_row_size * num_rows;
4733       memcpy(dest, src, copy_size);
4734       dest += copy_size;
4735     } else if (result->row_length > 0 && result->num_rows > 0) {
4736       uint32_t copy_row_size = result->row_length * group_size;
4737       uint32_t copy_last_row_size = copy_row_size;
4738       if (copy_row_size + skip_row_bytes > padded_row_size) {
4739         // We need to avoid writing into next row in case the leading pixels
4740         // are out-of-bounds and they need to be left untouched.
4741         copy_row_size = padded_row_size - skip_row_bytes;
4742       }
4743       // We have to copy 1 row at a time to avoid writing padding bytes.
4744       GLint copied_rows = 0;
4745       for (GLint yy = 0; yy < num_rows; ++yy) {
4746         if (y_index + yy >= 0 && copied_rows < result->num_rows) {
4747           if (yy + 1 == num_rows && remaining_rows == num_rows) {
4748             memcpy(dest + skip_row_bytes, src + skip_row_bytes,
4749                    copy_last_row_size);
4750           } else {
4751             memcpy(dest + skip_row_bytes, src + skip_row_bytes, copy_row_size);
4752           }
4753           ++copied_rows;
4754         }
4755         dest += padded_row_size;
4756         src += service_padded_row_size;
4757       }
4758       DCHECK_EQ(result->num_rows, copied_rows);
4759     }
4760     y_index += num_rows;
4761     remaining_rows -= num_rows;
4762   } while (remaining_rows);
4763   CheckGLError();
4764 }
4765 
ActiveTexture(GLenum texture)4766 void GLES2Implementation::ActiveTexture(GLenum texture) {
4767   GPU_CLIENT_SINGLE_THREAD_CHECK();
4768   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
4769                      << GLES2Util::GetStringEnum(texture) << ")");
4770   GLuint texture_index = texture - GL_TEXTURE0;
4771   if (texture_index >=
4772       static_cast<GLuint>(capabilities_.max_combined_texture_image_units)) {
4773     SetGLErrorInvalidEnum("glActiveTexture", texture, "texture");
4774     return;
4775   }
4776 
4777   active_texture_unit_ = texture_index;
4778   helper_->ActiveTexture(texture);
4779   CheckGLError();
4780 }
4781 
GenBuffersHelper(GLsizei,const GLuint *)4782 void GLES2Implementation::GenBuffersHelper(GLsizei /* n */,
4783                                            const GLuint* /* buffers */) {}
4784 
GenFramebuffersHelper(GLsizei,const GLuint *)4785 void GLES2Implementation::GenFramebuffersHelper(
4786     GLsizei /* n */,
4787     const GLuint* /* framebuffers */) {}
4788 
GenRenderbuffersHelper(GLsizei,const GLuint *)4789 void GLES2Implementation::GenRenderbuffersHelper(
4790     GLsizei /* n */,
4791     const GLuint* /* renderbuffers */) {}
4792 
GenTexturesHelper(GLsizei,const GLuint *)4793 void GLES2Implementation::GenTexturesHelper(GLsizei /* n */,
4794                                             const GLuint* /* textures */) {}
4795 
GenVertexArraysOESHelper(GLsizei n,const GLuint * arrays)4796 void GLES2Implementation::GenVertexArraysOESHelper(GLsizei n,
4797                                                    const GLuint* arrays) {
4798   vertex_array_object_manager_->GenVertexArrays(n, arrays);
4799 }
4800 
GenQueriesEXTHelper(GLsizei,const GLuint *)4801 void GLES2Implementation::GenQueriesEXTHelper(GLsizei /* n */,
4802                                               const GLuint* /* queries */) {}
4803 
GenSamplersHelper(GLsizei,const GLuint *)4804 void GLES2Implementation::GenSamplersHelper(GLsizei /* n */,
4805                                             const GLuint* /* samplers */) {}
4806 
GenTransformFeedbacksHelper(GLsizei,const GLuint *)4807 void GLES2Implementation::GenTransformFeedbacksHelper(
4808     GLsizei /* n */,
4809     const GLuint* /* transformfeedbacks */) {}
4810 
4811 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
4812 // generates a new resource. On newer versions of OpenGL they don't. The code
4813 // related to binding below will need to change if we switch to the new OpenGL
4814 // model. Specifically it assumes a bind will succeed which is always true in
4815 // the old model but possibly not true in the new model if another context has
4816 // deleted the resource.
4817 
4818 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
4819 // used even when Bind has failed. However, the bug is minor compared to the
4820 // overhead & duplicated checking in client side.
4821 
BindBufferHelper(GLenum target,GLuint buffer_id)4822 void GLES2Implementation::BindBufferHelper(GLenum target, GLuint buffer_id) {
4823   // TODO(gman): See note #1 above.
4824   bool changed = false;
4825   switch (target) {
4826     case GL_ARRAY_BUFFER:
4827       if (bound_array_buffer_ != buffer_id) {
4828         bound_array_buffer_ = buffer_id;
4829         changed = true;
4830       }
4831       break;
4832     case GL_ATOMIC_COUNTER_BUFFER:
4833       if (bound_atomic_counter_buffer_ != buffer_id) {
4834         bound_atomic_counter_buffer_ = buffer_id;
4835         changed = true;
4836       }
4837       break;
4838     case GL_COPY_READ_BUFFER:
4839       if (bound_copy_read_buffer_ != buffer_id) {
4840         bound_copy_read_buffer_ = buffer_id;
4841         changed = true;
4842       }
4843       break;
4844     case GL_COPY_WRITE_BUFFER:
4845       if (bound_copy_write_buffer_ != buffer_id) {
4846         bound_copy_write_buffer_ = buffer_id;
4847         changed = true;
4848       }
4849       break;
4850     case GL_DISPATCH_INDIRECT_BUFFER:
4851       if (bound_dispatch_indirect_buffer_ != buffer_id) {
4852         bound_dispatch_indirect_buffer_ = buffer_id;
4853         changed = true;
4854       }
4855       break;
4856     case GL_DRAW_INDIRECT_BUFFER:
4857       if (bound_draw_indirect_buffer_ != buffer_id) {
4858         bound_draw_indirect_buffer_ = buffer_id;
4859         changed = true;
4860       }
4861       break;
4862     case GL_ELEMENT_ARRAY_BUFFER:
4863       changed = vertex_array_object_manager_->BindElementArray(buffer_id);
4864       break;
4865     case GL_PIXEL_PACK_BUFFER:
4866       if (bound_pixel_pack_buffer_ != buffer_id) {
4867         bound_pixel_pack_buffer_ = buffer_id;
4868         changed = true;
4869       }
4870       break;
4871     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
4872       bound_pixel_pack_transfer_buffer_id_ = buffer_id;
4873       break;
4874     case GL_PIXEL_UNPACK_BUFFER:
4875       if (bound_pixel_unpack_buffer_ != buffer_id) {
4876         bound_pixel_unpack_buffer_ = buffer_id;
4877         changed = true;
4878       }
4879       break;
4880     case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
4881       bound_pixel_unpack_transfer_buffer_id_ = buffer_id;
4882       break;
4883     case GL_SHADER_STORAGE_BUFFER:
4884       if (bound_shader_storage_buffer_ != buffer_id) {
4885         bound_shader_storage_buffer_ = buffer_id;
4886         changed = true;
4887       }
4888       break;
4889     case GL_TRANSFORM_FEEDBACK_BUFFER:
4890       if (bound_transform_feedback_buffer_ != buffer_id) {
4891         bound_transform_feedback_buffer_ = buffer_id;
4892         changed = true;
4893       }
4894       break;
4895     case GL_UNIFORM_BUFFER:
4896       if (bound_uniform_buffer_ != buffer_id) {
4897         bound_uniform_buffer_ = buffer_id;
4898         changed = true;
4899       }
4900       break;
4901     default:
4902       changed = true;
4903       break;
4904   }
4905   // TODO(gman): See note #2 above.
4906   if (changed) {
4907     GetIdHandler(SharedIdNamespaces::kBuffers)
4908         ->MarkAsUsedForBind(this, target, buffer_id,
4909                             &GLES2Implementation::BindBufferStub);
4910   }
4911 }
4912 
BindBufferStub(GLenum target,GLuint buffer)4913 void GLES2Implementation::BindBufferStub(GLenum target, GLuint buffer) {
4914   helper_->BindBuffer(target, buffer);
4915   if (share_group_->bind_generates_resource())
4916     helper_->CommandBufferHelper::OrderingBarrier();
4917 }
4918 
UpdateIndexedBufferState(GLenum target,GLuint index,GLuint buffer_id,const char * function_name)4919 bool GLES2Implementation::UpdateIndexedBufferState(GLenum target,
4920                                                    GLuint index,
4921                                                    GLuint buffer_id,
4922                                                    const char* function_name) {
4923   switch (target) {
4924     case GL_ATOMIC_COUNTER_BUFFER:
4925       if (index >= static_cast<GLuint>(
4926                        capabilities_.max_atomic_counter_buffer_bindings)) {
4927         SetGLError(GL_INVALID_VALUE, function_name, "index out of range");
4928         return false;
4929       }
4930       bound_atomic_counter_buffer_ = buffer_id;
4931       break;
4932     case GL_TRANSFORM_FEEDBACK_BUFFER:
4933       if (index >= static_cast<GLuint>(
4934                        capabilities_.max_transform_feedback_separate_attribs)) {
4935         SetGLError(GL_INVALID_VALUE, function_name, "index out of range");
4936         return false;
4937       }
4938       bound_transform_feedback_buffer_ = buffer_id;
4939       break;
4940     case GL_SHADER_STORAGE_BUFFER:
4941       if (index >= static_cast<GLuint>(
4942                        capabilities_.max_shader_storage_buffer_bindings)) {
4943         SetGLError(GL_INVALID_VALUE, function_name, "index out of range");
4944         return false;
4945       }
4946       bound_shader_storage_buffer_ = buffer_id;
4947       break;
4948     case GL_UNIFORM_BUFFER:
4949       if (index >=
4950           static_cast<GLuint>(capabilities_.max_uniform_buffer_bindings)) {
4951         SetGLError(GL_INVALID_VALUE, function_name, "index out of range");
4952         return false;
4953       }
4954       bound_uniform_buffer_ = buffer_id;
4955       break;
4956     default:
4957       SetGLError(GL_INVALID_ENUM, function_name, "invalid target");
4958       return false;
4959   }
4960   return true;
4961 }
4962 
BindBufferBaseHelper(GLenum target,GLuint index,GLuint buffer_id)4963 void GLES2Implementation::BindBufferBaseHelper(GLenum target,
4964                                                GLuint index,
4965                                                GLuint buffer_id) {
4966   // TODO(zmo): See note #1 above.
4967   // TODO(zmo): See note #2 above.
4968   if (UpdateIndexedBufferState(target, index, buffer_id, "glBindBufferBase")) {
4969     GetIdHandler(SharedIdNamespaces::kBuffers)
4970         ->MarkAsUsedForBind(this, target, index, buffer_id,
4971                             &GLES2Implementation::BindBufferBaseStub);
4972   }
4973 }
4974 
BindBufferBaseStub(GLenum target,GLuint index,GLuint buffer)4975 void GLES2Implementation::BindBufferBaseStub(GLenum target,
4976                                              GLuint index,
4977                                              GLuint buffer) {
4978   helper_->BindBufferBase(target, index, buffer);
4979   if (share_group_->bind_generates_resource())
4980     helper_->CommandBufferHelper::Flush();
4981 }
4982 
BindBufferRangeHelper(GLenum target,GLuint index,GLuint buffer_id,GLintptr offset,GLsizeiptr size)4983 void GLES2Implementation::BindBufferRangeHelper(GLenum target,
4984                                                 GLuint index,
4985                                                 GLuint buffer_id,
4986                                                 GLintptr offset,
4987                                                 GLsizeiptr size) {
4988   // TODO(zmo): See note #1 above.
4989   // TODO(zmo): See note #2 above.
4990   if (UpdateIndexedBufferState(target, index, buffer_id, "glBindBufferRange")) {
4991     GetIdHandler(SharedIdNamespaces::kBuffers)
4992         ->MarkAsUsedForBind(this, target, index, buffer_id, offset, size,
4993                             &GLES2Implementation::BindBufferRangeStub);
4994   }
4995 }
4996 
BindBufferRangeStub(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)4997 void GLES2Implementation::BindBufferRangeStub(GLenum target,
4998                                               GLuint index,
4999                                               GLuint buffer,
5000                                               GLintptr offset,
5001                                               GLsizeiptr size) {
5002   helper_->BindBufferRange(target, index, buffer, offset, size);
5003   if (share_group_->bind_generates_resource())
5004     helper_->CommandBufferHelper::Flush();
5005 }
5006 
BindFramebufferHelper(GLenum target,GLuint framebuffer)5007 void GLES2Implementation::BindFramebufferHelper(GLenum target,
5008                                                 GLuint framebuffer) {
5009   // TODO(gman): See note #1 above.
5010   bool changed = false;
5011   switch (target) {
5012     case GL_FRAMEBUFFER:
5013       if (bound_framebuffer_ != framebuffer ||
5014           bound_read_framebuffer_ != framebuffer) {
5015         bound_framebuffer_ = framebuffer;
5016         bound_read_framebuffer_ = framebuffer;
5017         changed = true;
5018       }
5019       break;
5020     case GL_READ_FRAMEBUFFER:
5021       DCHECK(capabilities_.major_version >= 3 ||
5022              IsChromiumFramebufferMultisampleAvailable());
5023       if (bound_read_framebuffer_ != framebuffer) {
5024         bound_read_framebuffer_ = framebuffer;
5025         changed = true;
5026       }
5027       break;
5028     case GL_DRAW_FRAMEBUFFER:
5029       DCHECK(capabilities_.major_version >= 3 ||
5030              IsChromiumFramebufferMultisampleAvailable());
5031       if (bound_framebuffer_ != framebuffer) {
5032         bound_framebuffer_ = framebuffer;
5033         changed = true;
5034       }
5035       break;
5036     default:
5037       SetGLErrorInvalidEnum("glBindFramebuffer", target, "target");
5038       return;
5039   }
5040 
5041   if (changed) {
5042     if (framebuffer != 0)
5043       GetIdAllocator(IdNamespaces::kFramebuffers)->MarkAsUsed(framebuffer);
5044     helper_->BindFramebuffer(target, framebuffer);
5045   }
5046 }
5047 
BindRenderbufferHelper(GLenum target,GLuint renderbuffer)5048 void GLES2Implementation::BindRenderbufferHelper(GLenum target,
5049                                                  GLuint renderbuffer) {
5050   // TODO(gman): See note #1 above.
5051   bool changed = false;
5052   switch (target) {
5053     case GL_RENDERBUFFER:
5054       if (bound_renderbuffer_ != renderbuffer) {
5055         bound_renderbuffer_ = renderbuffer;
5056         changed = true;
5057       }
5058       break;
5059     default:
5060       changed = true;
5061       break;
5062   }
5063   // TODO(zmo): See note #2 above.
5064   if (changed) {
5065     GetIdHandler(SharedIdNamespaces::kRenderbuffers)
5066         ->MarkAsUsedForBind(this, target, renderbuffer,
5067                             &GLES2Implementation::BindRenderbufferStub);
5068   }
5069 }
5070 
BindRenderbufferStub(GLenum target,GLuint renderbuffer)5071 void GLES2Implementation::BindRenderbufferStub(GLenum target,
5072                                                GLuint renderbuffer) {
5073   helper_->BindRenderbuffer(target, renderbuffer);
5074   if (share_group_->bind_generates_resource())
5075     helper_->CommandBufferHelper::OrderingBarrier();
5076 }
5077 
BindSamplerHelper(GLuint unit,GLuint sampler)5078 void GLES2Implementation::BindSamplerHelper(GLuint unit, GLuint sampler) {
5079   helper_->BindSampler(unit, sampler);
5080 }
5081 
BindTextureHelper(GLenum target,GLuint texture)5082 void GLES2Implementation::BindTextureHelper(GLenum target, GLuint texture) {
5083   // TODO(gman): See note #1 above.
5084   bool changed = false;
5085   TextureUnit& unit = texture_units_[active_texture_unit_];
5086   switch (target) {
5087     case GL_TEXTURE_2D:
5088       if (unit.bound_texture_2d != texture) {
5089         unit.bound_texture_2d = texture;
5090         changed = true;
5091       }
5092       break;
5093     case GL_TEXTURE_CUBE_MAP:
5094       if (unit.bound_texture_cube_map != texture) {
5095         unit.bound_texture_cube_map = texture;
5096         changed = true;
5097       }
5098       break;
5099     case GL_TEXTURE_EXTERNAL_OES:
5100       if (unit.bound_texture_external_oes != texture) {
5101         unit.bound_texture_external_oes = texture;
5102         changed = true;
5103       }
5104       break;
5105     case GL_TEXTURE_RECTANGLE_ARB:
5106       if (unit.bound_texture_rectangle_arb != texture) {
5107         unit.bound_texture_rectangle_arb = texture;
5108         changed = true;
5109       }
5110       break;
5111     default:
5112       changed = true;
5113       break;
5114   }
5115   // TODO(gman): See note #2 above.
5116   if (changed) {
5117     GetIdHandler(SharedIdNamespaces::kTextures)
5118         ->MarkAsUsedForBind(this, target, texture,
5119                             &GLES2Implementation::BindTextureStub);
5120   }
5121 }
5122 
BindTextureStub(GLenum target,GLuint texture)5123 void GLES2Implementation::BindTextureStub(GLenum target, GLuint texture) {
5124   helper_->BindTexture(target, texture);
5125   if (share_group_->bind_generates_resource())
5126     helper_->CommandBufferHelper::OrderingBarrier();
5127 }
5128 
BindTransformFeedbackHelper(GLenum target,GLuint transformfeedback)5129 void GLES2Implementation::BindTransformFeedbackHelper(
5130     GLenum target,
5131     GLuint transformfeedback) {
5132   helper_->BindTransformFeedback(target, transformfeedback);
5133 }
5134 
BindVertexArrayOESHelper(GLuint array)5135 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array) {
5136   bool changed = false;
5137   if (vertex_array_object_manager_->BindVertexArray(array, &changed)) {
5138     if (changed) {
5139       // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
5140       // because unlike other resources VertexArrayObject ids must
5141       // be generated by GenVertexArrays. A random id to Bind will not
5142       // generate a new object.
5143       helper_->BindVertexArrayOES(array);
5144     }
5145   } else {
5146     SetGLError(GL_INVALID_OPERATION, "glBindVertexArrayOES",
5147                "id was not generated with glGenVertexArrayOES");
5148   }
5149 }
5150 
UseProgramHelper(GLuint program)5151 void GLES2Implementation::UseProgramHelper(GLuint program) {
5152   if (current_program_ != program) {
5153     current_program_ = program;
5154     helper_->UseProgram(program);
5155   }
5156 }
5157 
IsBufferReservedId(GLuint id)5158 bool GLES2Implementation::IsBufferReservedId(GLuint id) {
5159   return vertex_array_object_manager_->IsReservedId(id);
5160 }
5161 
DeleteBuffersHelper(GLsizei n,const GLuint * buffers)5162 void GLES2Implementation::DeleteBuffersHelper(GLsizei n,
5163                                               const GLuint* buffers) {
5164   if (!GetIdHandler(SharedIdNamespaces::kBuffers)
5165            ->FreeIds(this, n, buffers,
5166                      &GLES2Implementation::DeleteBuffersStub)) {
5167     SetGLError(GL_INVALID_VALUE, "glDeleteBuffers",
5168                "id not created by this context.");
5169     return;
5170   }
5171   for (GLsizei ii = 0; ii < n; ++ii) {
5172     if (buffers[ii] == bound_array_buffer_) {
5173       bound_array_buffer_ = 0;
5174     }
5175     if (buffers[ii] == bound_atomic_counter_buffer_) {
5176       bound_atomic_counter_buffer_ = 0;
5177     }
5178     if (buffers[ii] == bound_copy_read_buffer_) {
5179       bound_copy_read_buffer_ = 0;
5180     }
5181     if (buffers[ii] == bound_copy_write_buffer_) {
5182       bound_copy_write_buffer_ = 0;
5183     }
5184     if (buffers[ii] == bound_dispatch_indirect_buffer_) {
5185       bound_dispatch_indirect_buffer_ = 0;
5186     }
5187     if (buffers[ii] == bound_draw_indirect_buffer_) {
5188       bound_draw_indirect_buffer_ = 0;
5189     }
5190     if (buffers[ii] == bound_pixel_pack_buffer_) {
5191       bound_pixel_pack_buffer_ = 0;
5192     }
5193     if (buffers[ii] == bound_pixel_unpack_buffer_) {
5194       bound_pixel_unpack_buffer_ = 0;
5195     }
5196     if (buffers[ii] == bound_shader_storage_buffer_) {
5197       bound_shader_storage_buffer_ = 0;
5198     }
5199     if (buffers[ii] == bound_transform_feedback_buffer_) {
5200       bound_transform_feedback_buffer_ = 0;
5201     }
5202     if (buffers[ii] == bound_uniform_buffer_) {
5203       bound_uniform_buffer_ = 0;
5204     }
5205     vertex_array_object_manager_->UnbindBuffer(buffers[ii]);
5206 
5207     BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]);
5208     if (buffer)
5209       RemoveTransferBuffer(buffer);
5210 
5211     readback_buffer_shadow_tracker_->RemoveBuffer(buffers[ii]);
5212 
5213     if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
5214       bound_pixel_unpack_transfer_buffer_id_ = 0;
5215     }
5216 
5217     RemoveMappedBufferRangeById(buffers[ii]);
5218   }
5219 }
5220 
DeleteBuffersStub(GLsizei n,const GLuint * buffers)5221 void GLES2Implementation::DeleteBuffersStub(GLsizei n, const GLuint* buffers) {
5222   helper_->DeleteBuffersImmediate(n, buffers);
5223 }
5224 
DeleteFramebuffersHelper(GLsizei n,const GLuint * framebuffers)5225 void GLES2Implementation::DeleteFramebuffersHelper(GLsizei n,
5226                                                    const GLuint* framebuffers) {
5227   helper_->DeleteFramebuffersImmediate(n, framebuffers);
5228   IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::kFramebuffers);
5229   for (GLsizei ii = 0; ii < n; ++ii) {
5230     id_allocator->FreeID(framebuffers[ii]);
5231     if (framebuffers[ii] == bound_framebuffer_) {
5232       bound_framebuffer_ = 0;
5233     }
5234     if (framebuffers[ii] == bound_read_framebuffer_) {
5235       bound_read_framebuffer_ = 0;
5236     }
5237   }
5238 }
5239 
DeleteRenderbuffersHelper(GLsizei n,const GLuint * renderbuffers)5240 void GLES2Implementation::DeleteRenderbuffersHelper(
5241     GLsizei n,
5242     const GLuint* renderbuffers) {
5243   if (!GetIdHandler(SharedIdNamespaces::kRenderbuffers)
5244            ->FreeIds(this, n, renderbuffers,
5245                      &GLES2Implementation::DeleteRenderbuffersStub)) {
5246     SetGLError(GL_INVALID_VALUE, "glDeleteRenderbuffers",
5247                "id not created by this context.");
5248     return;
5249   }
5250   for (GLsizei ii = 0; ii < n; ++ii) {
5251     if (renderbuffers[ii] == bound_renderbuffer_) {
5252       bound_renderbuffer_ = 0;
5253     }
5254   }
5255 }
5256 
DeleteRenderbuffersStub(GLsizei n,const GLuint * renderbuffers)5257 void GLES2Implementation::DeleteRenderbuffersStub(GLsizei n,
5258                                                   const GLuint* renderbuffers) {
5259   helper_->DeleteRenderbuffersImmediate(n, renderbuffers);
5260 }
5261 
DeleteTexturesHelper(GLsizei n,const GLuint * textures)5262 void GLES2Implementation::DeleteTexturesHelper(GLsizei n,
5263                                                const GLuint* textures) {
5264   if (!GetIdHandler(SharedIdNamespaces::kTextures)
5265            ->FreeIds(this, n, textures,
5266                      &GLES2Implementation::DeleteTexturesStub)) {
5267     SetGLError(GL_INVALID_VALUE, "glDeleteTextures",
5268                "id not created by this context.");
5269     return;
5270   }
5271   for (GLsizei ii = 0; ii < n; ++ii) {
5272     share_group_->discardable_texture_manager()->FreeTexture(textures[ii]);
5273   }
5274   UnbindTexturesHelper(n, textures);
5275 }
5276 
UnbindTexturesHelper(GLsizei n,const GLuint * textures)5277 void GLES2Implementation::UnbindTexturesHelper(GLsizei n,
5278                                                const GLuint* textures) {
5279   for (GLsizei ii = 0; ii < n; ++ii) {
5280     for (GLint tt = 0; tt < capabilities_.max_combined_texture_image_units;
5281          ++tt) {
5282       TextureUnit& unit = texture_units_[tt];
5283       if (textures[ii] == unit.bound_texture_2d) {
5284         unit.bound_texture_2d = 0;
5285       }
5286       if (textures[ii] == unit.bound_texture_cube_map) {
5287         unit.bound_texture_cube_map = 0;
5288       }
5289       if (textures[ii] == unit.bound_texture_external_oes) {
5290         unit.bound_texture_external_oes = 0;
5291       }
5292       if (textures[ii] == unit.bound_texture_rectangle_arb) {
5293         unit.bound_texture_rectangle_arb = 0;
5294       }
5295     }
5296   }
5297 }
5298 
DeleteTexturesStub(GLsizei n,const GLuint * textures)5299 void GLES2Implementation::DeleteTexturesStub(GLsizei n,
5300                                              const GLuint* textures) {
5301   helper_->DeleteTexturesImmediate(n, textures);
5302 }
5303 
DeleteVertexArraysOESHelper(GLsizei n,const GLuint * arrays)5304 void GLES2Implementation::DeleteVertexArraysOESHelper(GLsizei n,
5305                                                       const GLuint* arrays) {
5306   vertex_array_object_manager_->DeleteVertexArrays(n, arrays);
5307   helper_->DeleteVertexArraysOESImmediate(n, arrays);
5308   IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::kVertexArrays);
5309   for (GLsizei ii = 0; ii < n; ++ii)
5310     id_allocator->FreeID(arrays[ii]);
5311 }
5312 
DeleteSamplersStub(GLsizei n,const GLuint * samplers)5313 void GLES2Implementation::DeleteSamplersStub(GLsizei n,
5314                                              const GLuint* samplers) {
5315   helper_->DeleteSamplersImmediate(n, samplers);
5316 }
5317 
DeleteSamplersHelper(GLsizei n,const GLuint * samplers)5318 void GLES2Implementation::DeleteSamplersHelper(GLsizei n,
5319                                                const GLuint* samplers) {
5320   if (!GetIdHandler(SharedIdNamespaces::kSamplers)
5321            ->FreeIds(this, n, samplers,
5322                      &GLES2Implementation::DeleteSamplersStub)) {
5323     SetGLError(GL_INVALID_VALUE, "glDeleteSamplers",
5324                "id not created by this context.");
5325     return;
5326   }
5327 }
5328 
DeleteTransformFeedbacksHelper(GLsizei n,const GLuint * transformfeedbacks)5329 void GLES2Implementation::DeleteTransformFeedbacksHelper(
5330     GLsizei n,
5331     const GLuint* transformfeedbacks) {
5332   helper_->DeleteTransformFeedbacksImmediate(n, transformfeedbacks);
5333   IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::kTransformFeedbacks);
5334   for (GLsizei ii = 0; ii < n; ++ii)
5335     id_allocator->FreeID(transformfeedbacks[ii]);
5336 }
5337 
DisableVertexAttribArray(GLuint index)5338 void GLES2Implementation::DisableVertexAttribArray(GLuint index) {
5339   GPU_CLIENT_SINGLE_THREAD_CHECK();
5340   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisableVertexAttribArray("
5341                      << index << ")");
5342   vertex_array_object_manager_->SetAttribEnable(index, false);
5343   helper_->DisableVertexAttribArray(index);
5344   CheckGLError();
5345 }
5346 
EnableVertexAttribArray(GLuint index)5347 void GLES2Implementation::EnableVertexAttribArray(GLuint index) {
5348   GPU_CLIENT_SINGLE_THREAD_CHECK();
5349   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
5350                      << index << ")");
5351   vertex_array_object_manager_->SetAttribEnable(index, true);
5352   helper_->EnableVertexAttribArray(index);
5353   CheckGLError();
5354 }
5355 
DrawArrays(GLenum mode,GLint first,GLsizei count)5356 void GLES2Implementation::DrawArrays(GLenum mode, GLint first, GLsizei count) {
5357   GPU_CLIENT_SINGLE_THREAD_CHECK();
5358   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
5359                      << GLES2Util::GetStringDrawMode(mode) << ", " << first
5360                      << ", " << count << ")");
5361   if (count < 0) {
5362     SetGLError(GL_INVALID_VALUE, "glDrawArrays", "count < 0");
5363     return;
5364   }
5365   bool simulated = false;
5366   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
5367     GLsizei num_elements;
5368     if (!base::CheckAdd(first, count).AssignIfValid(&num_elements)) {
5369       SetGLError(GL_INVALID_VALUE, "glDrawArrays", "first+count overflow");
5370       return;
5371     }
5372     if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers(
5373             "glDrawArrays", this, helper_, num_elements, 0, &simulated)) {
5374       return;
5375     }
5376   }
5377   helper_->DrawArrays(mode, first, count);
5378   RestoreArrayBuffer(simulated);
5379   CheckGLError();
5380 }
5381 
DrawArraysIndirect(GLenum mode,const void * offset)5382 void GLES2Implementation::DrawArraysIndirect(GLenum mode, const void* offset) {
5383   GPU_CLIENT_SINGLE_THREAD_CHECK();
5384   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysIndirect("
5385                      << GLES2Util::GetStringDrawMode(mode) << ", " << offset
5386                      << ")");
5387   if (!ValidateOffset("glDrawArraysIndirect",
5388                       reinterpret_cast<GLintptr>(offset))) {
5389     return;
5390   }
5391   // This is for WebGL 2.0 Compute which doesn't support client side arrays
5392   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
5393     SetGLError(GL_INVALID_OPERATION, "glDrawArraysIndirect",
5394                "Missing array buffer for vertex attribute");
5395     return;
5396   }
5397   helper_->DrawArraysIndirect(mode, ToGLuint(offset));
5398   CheckGLError();
5399 }
5400 
GetVertexAttribfv(GLuint index,GLenum pname,GLfloat * params)5401 void GLES2Implementation::GetVertexAttribfv(GLuint index,
5402                                             GLenum pname,
5403                                             GLfloat* params) {
5404   GPU_CLIENT_SINGLE_THREAD_CHECK();
5405   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv(" << index
5406                      << ", " << GLES2Util::GetStringVertexAttribute(pname)
5407                      << ", " << static_cast<const void*>(params) << ")");
5408   uint32_t value = 0;
5409   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
5410     *params = static_cast<GLfloat>(value);
5411     return;
5412   }
5413   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
5414   typedef cmds::GetVertexAttribfv::Result Result;
5415   auto result = GetResultAs<Result>();
5416   if (!result) {
5417     return;
5418   }
5419   result->SetNumResults(0);
5420   helper_->GetVertexAttribfv(index, pname, GetResultShmId(), result.offset());
5421   WaitForCmd();
5422   result->CopyResult(params);
5423   GPU_CLIENT_LOG_CODE_BLOCK({
5424     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
5425       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
5426     }
5427   });
5428   CheckGLError();
5429 }
5430 
GetVertexAttribiv(GLuint index,GLenum pname,GLint * params)5431 void GLES2Implementation::GetVertexAttribiv(GLuint index,
5432                                             GLenum pname,
5433                                             GLint* params) {
5434   GPU_CLIENT_SINGLE_THREAD_CHECK();
5435   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv(" << index
5436                      << ", " << GLES2Util::GetStringVertexAttribute(pname)
5437                      << ", " << static_cast<const void*>(params) << ")");
5438   uint32_t value = 0;
5439   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
5440     *params = static_cast<GLint>(value);
5441     return;
5442   }
5443   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
5444   typedef cmds::GetVertexAttribiv::Result Result;
5445   auto result = GetResultAs<Result>();
5446   if (!result) {
5447     return;
5448   }
5449   result->SetNumResults(0);
5450   helper_->GetVertexAttribiv(index, pname, GetResultShmId(), result.offset());
5451   WaitForCmd();
5452   result->CopyResult(params);
5453   GPU_CLIENT_LOG_CODE_BLOCK({
5454     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
5455       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
5456     }
5457   });
5458   CheckGLError();
5459 }
5460 
GetVertexAttribIiv(GLuint index,GLenum pname,GLint * params)5461 void GLES2Implementation::GetVertexAttribIiv(GLuint index,
5462                                              GLenum pname,
5463                                              GLint* params) {
5464   GPU_CLIENT_SINGLE_THREAD_CHECK();
5465   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv(" << index
5466                      << ", " << GLES2Util::GetStringVertexAttribute(pname)
5467                      << ", " << static_cast<const void*>(params) << ")");
5468   uint32_t value = 0;
5469   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
5470     *params = static_cast<GLint>(value);
5471     return;
5472   }
5473   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
5474   typedef cmds::GetVertexAttribiv::Result Result;
5475   auto result = GetResultAs<Result>();
5476   if (!result) {
5477     return;
5478   }
5479   result->SetNumResults(0);
5480   helper_->GetVertexAttribIiv(index, pname, GetResultShmId(), result.offset());
5481   WaitForCmd();
5482   result->CopyResult(params);
5483   GPU_CLIENT_LOG_CODE_BLOCK({
5484     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
5485       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
5486     }
5487   });
5488   CheckGLError();
5489 }
5490 
GetVertexAttribIuiv(GLuint index,GLenum pname,GLuint * params)5491 void GLES2Implementation::GetVertexAttribIuiv(GLuint index,
5492                                               GLenum pname,
5493                                               GLuint* params) {
5494   GPU_CLIENT_SINGLE_THREAD_CHECK();
5495   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv(" << index
5496                      << ", " << GLES2Util::GetStringVertexAttribute(pname)
5497                      << ", " << static_cast<const void*>(params) << ")");
5498   uint32_t value = 0;
5499   if (vertex_array_object_manager_->GetVertexAttrib(index, pname, &value)) {
5500     *params = static_cast<GLuint>(value);
5501     return;
5502   }
5503   TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
5504   typedef cmds::GetVertexAttribiv::Result Result;
5505   auto result = GetResultAs<Result>();
5506   if (!result) {
5507     return;
5508   }
5509   result->SetNumResults(0);
5510   helper_->GetVertexAttribIuiv(index, pname, GetResultShmId(), result.offset());
5511   WaitForCmd();
5512   result->CopyResult(params);
5513   GPU_CLIENT_LOG_CODE_BLOCK({
5514     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
5515       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
5516     }
5517   });
5518   CheckGLError();
5519 }
5520 
GetGraphicsResetStatusKHR()5521 GLenum GLES2Implementation::GetGraphicsResetStatusKHR() {
5522   GPU_CLIENT_SINGLE_THREAD_CHECK();
5523   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");
5524   // If any context (including ourselves) has seen itself become lost,
5525   // then it will have told the ShareGroup, so just report its status.
5526   if (share_group_->IsLost())
5527     return GL_UNKNOWN_CONTEXT_RESET_KHR;
5528   return GL_NO_ERROR;
5529 }
5530 
Swap(uint32_t flags,SwapCompletedCallback complete_callback,PresentationCallback presentation_callback)5531 void GLES2Implementation::Swap(uint32_t flags,
5532                                SwapCompletedCallback complete_callback,
5533                                PresentationCallback presentation_callback) {
5534   SwapBuffers(PrepareNextSwapId(std::move(complete_callback),
5535                                 std::move(presentation_callback)),
5536               flags);
5537 }
5538 
SwapWithBounds(const std::vector<gfx::Rect> & rects,uint32_t flags,SwapCompletedCallback swap_completed,PresentationCallback presentation_callback)5539 void GLES2Implementation::SwapWithBounds(
5540     const std::vector<gfx::Rect>& rects,
5541     uint32_t flags,
5542     SwapCompletedCallback swap_completed,
5543     PresentationCallback presentation_callback) {
5544   std::vector<int> rects_data(rects.size() * 4);
5545   for (size_t i = 0; i < rects.size(); ++i) {
5546     rects_data[i * 4 + 0] = rects[i].x();
5547     rects_data[i * 4 + 1] = rects[i].y();
5548     rects_data[i * 4 + 2] = rects[i].width();
5549     rects_data[i * 4 + 3] = rects[i].height();
5550   }
5551   SwapBuffersWithBoundsCHROMIUM(
5552       PrepareNextSwapId(std::move(swap_completed),
5553                         std::move(presentation_callback)),
5554       rects.size(), rects_data.data(), flags);
5555 }
5556 
PartialSwapBuffers(const gfx::Rect & sub_buffer,uint32_t flags,SwapCompletedCallback swap_completed,PresentationCallback presentation_callback)5557 void GLES2Implementation::PartialSwapBuffers(
5558     const gfx::Rect& sub_buffer,
5559     uint32_t flags,
5560     SwapCompletedCallback swap_completed,
5561     PresentationCallback presentation_callback) {
5562   PostSubBufferCHROMIUM(PrepareNextSwapId(std::move(swap_completed),
5563                                           std::move(presentation_callback)),
5564                         sub_buffer.x(), sub_buffer.y(), sub_buffer.width(),
5565                         sub_buffer.height(), flags);
5566 }
5567 
CommitOverlayPlanes(uint32_t flags,SwapCompletedCallback swap_completed,PresentationCallback presentation_callback)5568 void GLES2Implementation::CommitOverlayPlanes(
5569     uint32_t flags,
5570     SwapCompletedCallback swap_completed,
5571     PresentationCallback presentation_callback) {
5572   CommitOverlayPlanesCHROMIUM(
5573       PrepareNextSwapId(std::move(swap_completed),
5574                         std::move(presentation_callback)),
5575       flags);
5576 }
5577 
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform)5578 static GLenum GetGLESOverlayTransform(gfx::OverlayTransform plane_transform) {
5579   switch (plane_transform) {
5580     case gfx::OVERLAY_TRANSFORM_INVALID:
5581       break;
5582     case gfx::OVERLAY_TRANSFORM_NONE:
5583       return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM;
5584     case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
5585       return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM;
5586     case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
5587       return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM;
5588     case gfx::OVERLAY_TRANSFORM_ROTATE_90:
5589       return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM;
5590     case gfx::OVERLAY_TRANSFORM_ROTATE_180:
5591       return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM;
5592     case gfx::OVERLAY_TRANSFORM_ROTATE_270:
5593       return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM;
5594   }
5595   NOTREACHED();
5596   return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM;
5597 }
5598 
ScheduleOverlayPlane(int plane_z_order,gfx::OverlayTransform plane_transform,unsigned overlay_texture_id,const gfx::Rect & display_bounds,const gfx::RectF & uv_rect,bool enable_blend,unsigned gpu_fence_id)5599 void GLES2Implementation::ScheduleOverlayPlane(
5600     int plane_z_order,
5601     gfx::OverlayTransform plane_transform,
5602     unsigned overlay_texture_id,
5603     const gfx::Rect& display_bounds,
5604     const gfx::RectF& uv_rect,
5605     bool enable_blend,
5606     unsigned gpu_fence_id) {
5607   ScheduleOverlayPlaneCHROMIUM(
5608       plane_z_order, GetGLESOverlayTransform(plane_transform),
5609       overlay_texture_id, display_bounds.x(), display_bounds.y(),
5610       display_bounds.width(), display_bounds.height(), uv_rect.x(), uv_rect.y(),
5611       uv_rect.width(), uv_rect.height(), enable_blend, gpu_fence_id);
5612 }
5613 
ScheduleCALayerSharedStateCHROMIUM(GLfloat opacity,GLboolean is_clipped,const GLfloat * clip_rect,const GLfloat * rounded_corner_bounds,GLint sorting_context_id,const GLfloat * transform)5614 void GLES2Implementation::ScheduleCALayerSharedStateCHROMIUM(
5615     GLfloat opacity,
5616     GLboolean is_clipped,
5617     const GLfloat* clip_rect,
5618     const GLfloat* rounded_corner_bounds,
5619     GLint sorting_context_id,
5620     const GLfloat* transform) {
5621   // 4 for clip_rect, 5 for rounded_corner_rect, 16 for transform.
5622   uint32_t shm_size = 25 * sizeof(GLfloat);
5623   ScopedTransferBufferPtr buffer(shm_size, helper_, transfer_buffer_);
5624   if (!buffer.valid() || buffer.size() < shm_size) {
5625     SetGLError(GL_OUT_OF_MEMORY, "GLES2::ScheduleCALayerSharedStateCHROMIUM",
5626                "out of memory");
5627     return;
5628   }
5629   GLfloat* mem = static_cast<GLfloat*>(buffer.address());
5630   memcpy(mem + 0, clip_rect, 4 * sizeof(GLfloat));
5631   memcpy(mem + 4, rounded_corner_bounds, 5 * sizeof(GLfloat));
5632   memcpy(mem + 9, transform, 16 * sizeof(GLfloat));
5633   helper_->ScheduleCALayerSharedStateCHROMIUM(opacity, is_clipped,
5634                                               sorting_context_id,
5635                                               buffer.shm_id(), buffer.offset());
5636 }
5637 
ScheduleCALayerCHROMIUM(GLuint contents_texture_id,const GLfloat * contents_rect,GLuint background_color,GLuint edge_aa_mask,const GLfloat * bounds_rect,GLuint filter)5638 void GLES2Implementation::ScheduleCALayerCHROMIUM(GLuint contents_texture_id,
5639                                                   const GLfloat* contents_rect,
5640                                                   GLuint background_color,
5641                                                   GLuint edge_aa_mask,
5642                                                   const GLfloat* bounds_rect,
5643                                                   GLuint filter) {
5644   uint32_t shm_size = 8 * sizeof(GLfloat);
5645   ScopedTransferBufferPtr buffer(shm_size, helper_, transfer_buffer_);
5646   if (!buffer.valid() || buffer.size() < shm_size) {
5647     SetGLError(GL_OUT_OF_MEMORY, "GLES2::ScheduleCALayerCHROMIUM",
5648                "out of memory");
5649     return;
5650   }
5651   GLfloat* mem = static_cast<GLfloat*>(buffer.address());
5652   memcpy(mem + 0, contents_rect, 4 * sizeof(GLfloat));
5653   memcpy(mem + 4, bounds_rect, 4 * sizeof(GLfloat));
5654   helper_->ScheduleCALayerCHROMIUM(contents_texture_id, background_color,
5655                                    edge_aa_mask, filter, buffer.shm_id(),
5656                                    buffer.offset());
5657 }
5658 
SetColorSpaceMetadataCHROMIUM(GLuint texture_id,GLcolorSpace color_space)5659 void GLES2Implementation::SetColorSpaceMetadataCHROMIUM(
5660     GLuint texture_id,
5661     GLcolorSpace color_space) {
5662 #if defined(__native_client__)
5663   // Including gfx::ColorSpace would bring Skia and a lot of other code into
5664   // NaCl's IRT.
5665   SetGLError(GL_INVALID_VALUE, "GLES2::SetColorSpaceMetadataCHROMIUM",
5666              "not supported");
5667 #else
5668   gfx::ColorSpace gfx_color_space;
5669   if (color_space)
5670     gfx_color_space = *reinterpret_cast<const gfx::ColorSpace*>(color_space);
5671   base::Pickle color_space_data;
5672   IPC::ParamTraits<gfx::ColorSpace>::Write(&color_space_data, gfx_color_space);
5673   ScopedTransferBufferPtr buffer(color_space_data.size(), helper_,
5674                                  transfer_buffer_);
5675   if (!buffer.valid() || buffer.size() < color_space_data.size()) {
5676     SetGLError(GL_OUT_OF_MEMORY, "GLES2::SetColorSpaceMetadataCHROMIUM",
5677                "out of memory");
5678     return;
5679   }
5680   memcpy(buffer.address(), color_space_data.data(), color_space_data.size());
5681   helper_->SetColorSpaceMetadataCHROMIUM(
5682       texture_id, buffer.shm_id(), buffer.offset(), color_space_data.size());
5683 #endif
5684 }
5685 
CommitOverlayPlanesCHROMIUM(uint64_t swap_id,uint32_t flags)5686 void GLES2Implementation::CommitOverlayPlanesCHROMIUM(uint64_t swap_id,
5687                                                       uint32_t flags) {
5688   GPU_CLIENT_SINGLE_THREAD_CHECK();
5689   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CommitOverlayPlanesCHROMIUM()");
5690   TRACE_EVENT0("gpu", "GLES2::CommitOverlayPlanesCHROMIUM");
5691 
5692   // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
5693   swap_buffers_tokens_.push(helper_->InsertToken());
5694   helper_->CommitOverlayPlanesCHROMIUM(swap_id, flags);
5695   helper_->CommandBufferHelper::Flush();
5696   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
5697     helper_->WaitForToken(swap_buffers_tokens_.front());
5698     swap_buffers_tokens_.pop();
5699   }
5700 }
5701 
EnableFeatureCHROMIUM(const char * feature)5702 GLboolean GLES2Implementation::EnableFeatureCHROMIUM(const char* feature) {
5703   GPU_CLIENT_SINGLE_THREAD_CHECK();
5704   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
5705                      << feature << ")");
5706   TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
5707   typedef cmds::EnableFeatureCHROMIUM::Result Result;
5708   SetBucketAsCString(kResultBucketId, feature);
5709   auto result = GetResultAs<Result>();
5710   if (!result) {
5711     return false;
5712   }
5713   *result = 0;
5714   helper_->EnableFeatureCHROMIUM(kResultBucketId, GetResultShmId(),
5715                                  result.offset());
5716   WaitForCmd();
5717   helper_->SetBucketSize(kResultBucketId, 0);
5718   GPU_CLIENT_LOG("   returned " << GLES2Util::GetStringBool(*result));
5719   return *result != 0;
5720 }
5721 
MapBufferSubDataCHROMIUM(GLuint target,GLintptr offset,GLsizeiptr size,GLenum access)5722 void* GLES2Implementation::MapBufferSubDataCHROMIUM(GLuint target,
5723                                                     GLintptr offset,
5724                                                     GLsizeiptr size,
5725                                                     GLenum access) {
5726   GPU_CLIENT_SINGLE_THREAD_CHECK();
5727   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
5728                      << target << ", " << offset << ", " << size << ", "
5729                      << GLES2Util::GetStringEnum(access) << ")");
5730   // NOTE: target is NOT checked because the service will check it
5731   // and we don't know what targets are valid.
5732   if (access != GL_WRITE_ONLY) {
5733     SetGLErrorInvalidEnum("glMapBufferSubDataCHROMIUM", access, "access");
5734     return nullptr;
5735   }
5736   if (!ValidateSize("glMapBufferSubDataCHROMIUM", size) ||
5737       !ValidateOffset("glMapBufferSubDataCHROMIUM", offset)) {
5738     return nullptr;
5739   }
5740 
5741   int32_t shm_id;
5742   unsigned int shm_offset;
5743   void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
5744   if (!mem) {
5745     SetGLError(GL_OUT_OF_MEMORY, "glMapBufferSubDataCHROMIUM", "out of memory");
5746     return nullptr;
5747   }
5748 
5749   std::pair<MappedBufferMap::iterator, bool> result = mapped_buffers_.insert(
5750       std::make_pair(mem, MappedBuffer(access, shm_id, mem, shm_offset, target,
5751                                        offset, size)));
5752   DCHECK(result.second);
5753   GPU_CLIENT_LOG("  returned " << mem);
5754   return mem;
5755 }
5756 
UnmapBufferSubDataCHROMIUM(const void * mem)5757 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem) {
5758   GPU_CLIENT_SINGLE_THREAD_CHECK();
5759   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM("
5760                      << mem << ")");
5761   MappedBufferMap::iterator it = mapped_buffers_.find(mem);
5762   if (it == mapped_buffers_.end()) {
5763     SetGLError(GL_INVALID_VALUE, "UnmapBufferSubDataCHROMIUM",
5764                "buffer not mapped");
5765     return;
5766   }
5767   const MappedBuffer& mb = it->second;
5768   helper_->BufferSubData(mb.target, mb.offset, mb.size, mb.shm_id,
5769                          mb.shm_offset);
5770   InvalidateReadbackBufferShadowDataCHROMIUM(GetBoundBufferHelper(mb.target));
5771   mapped_memory_->FreePendingToken(mb.shm_memory, helper_->InsertToken());
5772   mapped_buffers_.erase(it);
5773   CheckGLError();
5774 }
5775 
GetBoundBufferHelper(GLenum target)5776 GLuint GLES2Implementation::GetBoundBufferHelper(GLenum target) {
5777   GLenum binding = GLES2Util::MapBufferTargetToBindingEnum(target);
5778   GLint id = 0;
5779   bool cached = GetHelper(binding, &id);
5780   DCHECK(cached);
5781   return static_cast<GLuint>(id);
5782 }
5783 
RemoveMappedBufferRangeByTarget(GLenum target)5784 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target) {
5785   GLuint buffer = GetBoundBufferHelper(target);
5786   RemoveMappedBufferRangeById(buffer);
5787 }
5788 
RemoveMappedBufferRangeById(GLuint buffer)5789 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer) {
5790   if (buffer > 0) {
5791     auto iter = mapped_buffer_range_map_.find(buffer);
5792     if (iter != mapped_buffer_range_map_.end() && iter->second.shm_memory) {
5793       mapped_memory_->FreePendingToken(iter->second.shm_memory,
5794                                        helper_->InsertToken());
5795       mapped_buffer_range_map_.erase(iter);
5796     }
5797   }
5798 }
5799 
ClearMappedBufferRangeMap()5800 void GLES2Implementation::ClearMappedBufferRangeMap() {
5801   for (auto& buffer_range : mapped_buffer_range_map_) {
5802     if (buffer_range.second.shm_memory) {
5803       mapped_memory_->FreePendingToken(buffer_range.second.shm_memory,
5804                                        helper_->InsertToken());
5805     }
5806   }
5807   mapped_buffer_range_map_.clear();
5808 }
5809 
MapBufferRange(GLenum target,GLintptr offset,GLsizeiptr size,GLbitfield access)5810 void* GLES2Implementation::MapBufferRange(GLenum target,
5811                                           GLintptr offset,
5812                                           GLsizeiptr size,
5813                                           GLbitfield access) {
5814   GPU_CLIENT_SINGLE_THREAD_CHECK();
5815   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
5816                      << GLES2Util::GetStringEnum(target) << ", " << offset
5817                      << ", " << size << ", " << access << ")");
5818   if (!ValidateSize("glMapBufferRange", size) ||
5819       !ValidateOffset("glMapBufferRange", offset)) {
5820     return nullptr;
5821   }
5822 
5823   GLuint buffer = GetBoundBufferHelper(target);
5824 
5825   void* mem = nullptr;
5826 
5827   // Early return if we have a valid shadow copy for readback
5828   if (access == GL_MAP_READ_BIT) {
5829     // This will return an incorrect result if the client does the following:
5830     // * Writes into a buffer
5831     // * Issues query (GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM)
5832     // * Writes into the buffer using transform feedback (but doesn't issue
5833     //   InvalidateReadbackBufferShadowDataCHROMIUM correctly)
5834     // * Waits on the query
5835     // * Reads from the buffer (may return results from before the transfom
5836     //   feedback operation).
5837     // Therefore, if (and only if) a client uses the
5838     // GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM query, it must also correctly
5839     // use InvalidateReadbackBufferShadowDataCHROMIUM. WebGL (at the time of
5840     // this writing) is expected to be the only client which uses
5841     // GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM.
5842     if (auto* buffer_object =
5843             readback_buffer_shadow_tracker_->GetBuffer(buffer)) {
5844       mem = buffer_object->MapReadbackShm(offset, size);
5845       if (!mem) {
5846         // (If there's no valid shadow copy, warn and fall back to usual logic.)
5847         SendErrorMessage(
5848             "performance warning: READ-usage buffer was read back without "
5849             "waiting on a fence. This caused a graphics pipeline stall.",
5850             0);
5851       }
5852     }
5853   }
5854 
5855   // Usual, round-trip path if we're not doing a shadow-copy readback
5856   int32_t shm_id = 0;
5857   unsigned int shm_offset = 0;
5858   if (!mem) {
5859     mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
5860     if (!mem) {
5861       SetGLError(GL_OUT_OF_MEMORY, "glMapBufferRange", "out of memory");
5862       return nullptr;
5863     }
5864 
5865     typedef cmds::MapBufferRange::Result Result;
5866     auto result = GetResultAs<Result>();
5867     *result = 0;
5868     helper_->MapBufferRange(target, offset, size, access, shm_id, shm_offset,
5869                             GetResultShmId(), result.offset());
5870     // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
5871     // consider an early return without WaitForCmd(). crbug.com/465804.
5872     WaitForCmd();
5873     if (*result) {
5874       const GLbitfield kInvalidateBits =
5875           GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
5876       if ((access & kInvalidateBits) != 0) {
5877         // We do not read back from the buffer, therefore, we set the client
5878         // side memory to zero to avoid uninitialized data.
5879         memset(mem, 0, size);
5880       }
5881     } else {
5882       mapped_memory_->Free(mem);
5883       mem = nullptr;
5884     }
5885   }
5886 
5887   // Track this mapping regardless of which path was taken above.
5888   if (mem) {
5889     DCHECK_NE(0u, buffer);
5890     // glMapBufferRange fails on an already mapped buffer.
5891     DCHECK(mapped_buffer_range_map_.find(buffer) ==
5892            mapped_buffer_range_map_.end());
5893     auto iter = mapped_buffer_range_map_.insert(std::make_pair(
5894         buffer,
5895         MappedBuffer(access, shm_id, mem, shm_offset, target, offset, size)));
5896     DCHECK(iter.second);
5897   }
5898 
5899   GPU_CLIENT_LOG("  returned " << mem);
5900   CheckGLError();
5901   return mem;
5902 }
5903 
UnmapBuffer(GLenum target)5904 GLboolean GLES2Implementation::UnmapBuffer(GLenum target) {
5905   GPU_CLIENT_SINGLE_THREAD_CHECK();
5906   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
5907                      << GLES2Util::GetStringEnum(target) << ")");
5908   switch (target) {
5909     case GL_ARRAY_BUFFER:
5910     case GL_ATOMIC_COUNTER_BUFFER:
5911     case GL_ELEMENT_ARRAY_BUFFER:
5912     case GL_COPY_READ_BUFFER:
5913     case GL_COPY_WRITE_BUFFER:
5914     case GL_DISPATCH_INDIRECT_BUFFER:
5915     case GL_DRAW_INDIRECT_BUFFER:
5916     case GL_PIXEL_PACK_BUFFER:
5917     case GL_PIXEL_UNPACK_BUFFER:
5918     case GL_SHADER_STORAGE_BUFFER:
5919     case GL_TRANSFORM_FEEDBACK_BUFFER:
5920     case GL_UNIFORM_BUFFER:
5921       break;
5922     default:
5923       SetGLError(GL_INVALID_ENUM, "glUnmapBuffer", "invalid target");
5924       return GL_FALSE;
5925   }
5926   GLuint buffer = GetBoundBufferHelper(target);
5927   if (buffer == 0) {
5928     SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "no buffer bound");
5929     return GL_FALSE;
5930   }
5931   auto iter = mapped_buffer_range_map_.find(buffer);
5932   if (iter == mapped_buffer_range_map_.end()) {
5933     SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "buffer is unmapped");
5934     return GL_FALSE;
5935   }
5936 
5937   bool was_mapped_by_readback_tracker = false;
5938   if (auto* buffer_object =
5939           readback_buffer_shadow_tracker_->GetBuffer(buffer)) {
5940     was_mapped_by_readback_tracker = buffer_object->UnmapReadbackShm();
5941   }
5942   if (!was_mapped_by_readback_tracker) {
5943     helper_->UnmapBuffer(target);
5944     InvalidateReadbackBufferShadowDataCHROMIUM(GetBoundBufferHelper(target));
5945   }
5946   RemoveMappedBufferRangeById(buffer);
5947 
5948   // TODO(zmo): There is a rare situation that data might be corrupted and
5949   // GL_FALSE should be returned. We lose context on that sitatuon, so we
5950   // don't have to WaitForCmd().
5951   GPU_CLIENT_LOG("  returned " << GL_TRUE);
5952   CheckGLError();
5953   return GL_TRUE;
5954 }
5955 
MapTexSubImage2DCHROMIUM(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLenum access)5956 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(GLenum target,
5957                                                     GLint level,
5958                                                     GLint xoffset,
5959                                                     GLint yoffset,
5960                                                     GLsizei width,
5961                                                     GLsizei height,
5962                                                     GLenum format,
5963                                                     GLenum type,
5964                                                     GLenum access) {
5965   GPU_CLIENT_SINGLE_THREAD_CHECK();
5966   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
5967                      << target << ", " << level << ", " << xoffset << ", "
5968                      << yoffset << ", " << width << ", " << height << ", "
5969                      << GLES2Util::GetStringTextureFormat(format) << ", "
5970                      << GLES2Util::GetStringPixelType(type) << ", "
5971                      << GLES2Util::GetStringEnum(access) << ")");
5972   if (access != GL_WRITE_ONLY) {
5973     SetGLErrorInvalidEnum("glMapTexSubImage2DCHROMIUM", access, "access");
5974     return nullptr;
5975   }
5976   // NOTE: target is NOT checked because the service will check it
5977   // and we don't know what targets are valid.
5978   if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) {
5979     SetGLError(GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM",
5980                "bad dimensions");
5981     return nullptr;
5982   }
5983   uint32_t size;
5984   if (!GLES2Util::ComputeImageDataSizes(width, height, 1, format, type,
5985                                         unpack_alignment_, &size, nullptr,
5986                                         nullptr)) {
5987     SetGLError(GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM",
5988                "image size too large");
5989     return nullptr;
5990   }
5991   int32_t shm_id;
5992   unsigned int shm_offset;
5993   void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset);
5994   if (!mem) {
5995     SetGLError(GL_OUT_OF_MEMORY, "glMapTexSubImage2DCHROMIUM", "out of memory");
5996     return nullptr;
5997   }
5998 
5999   std::pair<MappedTextureMap::iterator, bool> result =
6000       mapped_textures_.insert(std::make_pair(
6001           mem, MappedTexture(access, shm_id, mem, shm_offset, target, level,
6002                              xoffset, yoffset, width, height, format, type)));
6003   DCHECK(result.second);
6004   GPU_CLIENT_LOG("  returned " << mem);
6005   return mem;
6006 }
6007 
UnmapTexSubImage2DCHROMIUM(const void * mem)6008 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem) {
6009   GPU_CLIENT_SINGLE_THREAD_CHECK();
6010   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM("
6011                      << mem << ")");
6012   MappedTextureMap::iterator it = mapped_textures_.find(mem);
6013   if (it == mapped_textures_.end()) {
6014     SetGLError(GL_INVALID_VALUE, "UnmapTexSubImage2DCHROMIUM",
6015                "texture not mapped");
6016     return;
6017   }
6018   const MappedTexture& mt = it->second;
6019   helper_->TexSubImage2D(mt.target, mt.level, mt.xoffset, mt.yoffset, mt.width,
6020                          mt.height, mt.format, mt.type, mt.shm_id,
6021                          mt.shm_offset, GL_FALSE);
6022   mapped_memory_->FreePendingToken(mt.shm_memory, helper_->InsertToken());
6023   mapped_textures_.erase(it);
6024   CheckGLError();
6025 }
6026 
ResizeCHROMIUM(GLuint width,GLuint height,float scale_factor,GLcolorSpace gl_color_space,GLboolean alpha)6027 void GLES2Implementation::ResizeCHROMIUM(GLuint width,
6028                                          GLuint height,
6029                                          float scale_factor,
6030                                          GLcolorSpace gl_color_space,
6031                                          GLboolean alpha) {
6032   GPU_CLIENT_SINGLE_THREAD_CHECK();
6033   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM(" << width << ", "
6034                      << height << ", " << scale_factor << ", " << alpha << ")");
6035   // Including gfx::ColorSpace would bring Skia and a lot of other code into
6036   // NaCl's IRT, so just leave the color space unspecified.
6037 #if !defined(__native_client__)
6038   if (gl_color_space) {
6039     gfx::ColorSpace gfx_color_space =
6040         *reinterpret_cast<const gfx::ColorSpace*>(gl_color_space);
6041     base::Pickle color_space_data;
6042     IPC::ParamTraits<gfx::ColorSpace>::Write(&color_space_data,
6043                                              gfx_color_space);
6044     ScopedTransferBufferPtr buffer(color_space_data.size(), helper_,
6045                                    transfer_buffer_);
6046     if (!buffer.valid() || buffer.size() < color_space_data.size()) {
6047       SetGLError(GL_OUT_OF_MEMORY, "GLES2::SetColorSpaceMetadataCHROMIUM",
6048                  "out of memory");
6049       return;
6050     }
6051     memcpy(buffer.address(), color_space_data.data(), color_space_data.size());
6052     helper_->ResizeCHROMIUM(width, height, scale_factor, alpha, buffer.shm_id(),
6053                             buffer.offset(), color_space_data.size());
6054     CheckGLError();
6055     return;
6056   }
6057 #endif
6058   helper_->ResizeCHROMIUM(width, height, scale_factor, alpha, 0, 0, 0);
6059   CheckGLError();
6060 }
6061 
GetRequestableExtensionsCHROMIUM()6062 const GLchar* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
6063   GPU_CLIENT_SINGLE_THREAD_CHECK();
6064   GPU_CLIENT_LOG("[" << GetLogPrefix()
6065                      << "] glGetRequestableExtensionsCHROMIUM()");
6066   TRACE_EVENT0("gpu",
6067                "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
6068   const char* result = nullptr;
6069   // Clear the bucket so if the command fails nothing will be in it.
6070   helper_->SetBucketSize(kResultBucketId, 0);
6071   helper_->GetRequestableExtensionsCHROMIUM(kResultBucketId);
6072   std::string str;
6073   if (GetBucketAsString(kResultBucketId, &str)) {
6074     // The set of requestable extensions shrinks as we enable
6075     // them. Because we don't know when the client will stop referring
6076     // to a previous one it queries (see GetString) we need to cache
6077     // the unique results.
6078     // TODO: Here we could save memory by defining RequestExtensions
6079     // invalidating the GL_EXTENSIONS string. http://crbug.com/586414
6080     result = gl_strings_.insert(str).first->c_str();
6081   }
6082   GPU_CLIENT_LOG("  returned " << result);
6083   return reinterpret_cast<const GLchar*>(result);
6084 }
6085 
6086 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
6087 // with VirtualGL contexts.
RequestExtensionCHROMIUM(const char * extension)6088 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension) {
6089   GPU_CLIENT_SINGLE_THREAD_CHECK();
6090   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
6091                      << extension << ")");
6092   InvalidateCachedExtensions();
6093   SetBucketAsCString(kResultBucketId, extension);
6094   helper_->RequestExtensionCHROMIUM(kResultBucketId);
6095   helper_->SetBucketSize(kResultBucketId, 0);
6096 
6097   struct ExtensionCheck {
6098     const char* extension;
6099     ExtensionStatus* status;
6100   };
6101   const ExtensionCheck checks[] = {
6102       {
6103           "GL_CHROMIUM_framebuffer_multisample",
6104           &chromium_framebuffer_multisample_,
6105       },
6106   };
6107   const size_t kNumChecks = sizeof(checks) / sizeof(checks[0]);
6108   for (size_t ii = 0; ii < kNumChecks; ++ii) {
6109     const ExtensionCheck& check = checks[ii];
6110     if (*check.status == kUnavailableExtensionStatus &&
6111         !strcmp(extension, check.extension)) {
6112       *check.status = kUnknownExtensionStatus;
6113     }
6114   }
6115 }
6116 
GetProgramInfoCHROMIUMHelper(GLuint program,std::vector<int8_t> * result)6117 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
6118     GLuint program,
6119     std::vector<int8_t>* result) {
6120   DCHECK(result);
6121   // Clear the bucket so if the command fails nothing will be in it.
6122   helper_->SetBucketSize(kResultBucketId, 0);
6123   helper_->GetProgramInfoCHROMIUM(program, kResultBucketId);
6124   GetBucketContents(kResultBucketId, result);
6125 }
6126 
GetProgramInfoCHROMIUM(GLuint program,GLsizei bufsize,GLsizei * size,void * info)6127 void GLES2Implementation::GetProgramInfoCHROMIUM(GLuint program,
6128                                                  GLsizei bufsize,
6129                                                  GLsizei* size,
6130                                                  void* info) {
6131   GPU_CLIENT_SINGLE_THREAD_CHECK();
6132   if (bufsize < 0) {
6133     SetGLError(GL_INVALID_VALUE, "glProgramInfoCHROMIUM",
6134                "bufsize less than 0.");
6135     return;
6136   }
6137   if (size == nullptr) {
6138     SetGLError(GL_INVALID_VALUE, "glProgramInfoCHROMIUM", "size is null.");
6139     return;
6140   }
6141   // Make sure they've set size to 0 else the value will be undefined on
6142   // lost context.
6143   DCHECK_EQ(0, *size);
6144   std::vector<int8_t> result;
6145   GetProgramInfoCHROMIUMHelper(program, &result);
6146   if (result.empty()) {
6147     return;
6148   }
6149   *size = result.size();
6150   if (!info) {
6151     return;
6152   }
6153   if (static_cast<size_t>(bufsize) < result.size()) {
6154     SetGLError(GL_INVALID_OPERATION, "glProgramInfoCHROMIUM",
6155                "bufsize is too small for result.");
6156     return;
6157   }
6158   memcpy(info, &result[0], result.size());
6159 }
6160 
GetUniformBlocksCHROMIUMHelper(GLuint program,std::vector<int8_t> * result)6161 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
6162     GLuint program,
6163     std::vector<int8_t>* result) {
6164   DCHECK(result);
6165   // Clear the bucket so if the command fails nothing will be in it.
6166   helper_->SetBucketSize(kResultBucketId, 0);
6167   helper_->GetUniformBlocksCHROMIUM(program, kResultBucketId);
6168   GetBucketContents(kResultBucketId, result);
6169 }
6170 
GetUniformBlocksCHROMIUM(GLuint program,GLsizei bufsize,GLsizei * size,void * info)6171 void GLES2Implementation::GetUniformBlocksCHROMIUM(GLuint program,
6172                                                    GLsizei bufsize,
6173                                                    GLsizei* size,
6174                                                    void* info) {
6175   GPU_CLIENT_SINGLE_THREAD_CHECK();
6176   if (bufsize < 0) {
6177     SetGLError(GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM",
6178                "bufsize less than 0.");
6179     return;
6180   }
6181   if (size == nullptr) {
6182     SetGLError(GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM", "size is null.");
6183     return;
6184   }
6185   // Make sure they've set size to 0 else the value will be undefined on
6186   // lost context.
6187   DCHECK_EQ(0, *size);
6188   std::vector<int8_t> result;
6189   GetUniformBlocksCHROMIUMHelper(program, &result);
6190   if (result.empty()) {
6191     return;
6192   }
6193   *size = result.size();
6194   if (!info) {
6195     return;
6196   }
6197   if (static_cast<size_t>(bufsize) < result.size()) {
6198     SetGLError(GL_INVALID_OPERATION, "glGetUniformBlocksCHROMIUM",
6199                "bufsize is too small for result.");
6200     return;
6201   }
6202   memcpy(info, &result[0], result.size());
6203 }
6204 
GetUniformsES3CHROMIUMHelper(GLuint program,std::vector<int8_t> * result)6205 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
6206     GLuint program,
6207     std::vector<int8_t>* result) {
6208   DCHECK(result);
6209   // Clear the bucket so if the command fails nothing will be in it.
6210   helper_->SetBucketSize(kResultBucketId, 0);
6211   helper_->GetUniformsES3CHROMIUM(program, kResultBucketId);
6212   GetBucketContents(kResultBucketId, result);
6213 }
6214 
GetUniformsES3CHROMIUM(GLuint program,GLsizei bufsize,GLsizei * size,void * info)6215 void GLES2Implementation::GetUniformsES3CHROMIUM(GLuint program,
6216                                                  GLsizei bufsize,
6217                                                  GLsizei* size,
6218                                                  void* info) {
6219   GPU_CLIENT_SINGLE_THREAD_CHECK();
6220   if (bufsize < 0) {
6221     SetGLError(GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM",
6222                "bufsize less than 0.");
6223     return;
6224   }
6225   if (size == nullptr) {
6226     SetGLError(GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM", "size is null.");
6227     return;
6228   }
6229   // Make sure they've set size to 0 else the value will be undefined on
6230   // lost context.
6231   DCHECK_EQ(0, *size);
6232   std::vector<int8_t> result;
6233   GetUniformsES3CHROMIUMHelper(program, &result);
6234   if (result.empty()) {
6235     return;
6236   }
6237   *size = result.size();
6238   if (!info) {
6239     return;
6240   }
6241   if (static_cast<size_t>(bufsize) < result.size()) {
6242     SetGLError(GL_INVALID_OPERATION, "glGetUniformsES3CHROMIUM",
6243                "bufsize is too small for result.");
6244     return;
6245   }
6246   memcpy(info, &result[0], result.size());
6247 }
6248 
GetTransformFeedbackVaryingsCHROMIUMHelper(GLuint program,std::vector<int8_t> * result)6249 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
6250     GLuint program,
6251     std::vector<int8_t>* result) {
6252   DCHECK(result);
6253   // Clear the bucket so if the command fails nothing will be in it.
6254   helper_->SetBucketSize(kResultBucketId, 0);
6255   helper_->GetTransformFeedbackVaryingsCHROMIUM(program, kResultBucketId);
6256   GetBucketContents(kResultBucketId, result);
6257 }
6258 
GetTransformFeedbackVaryingsCHROMIUM(GLuint program,GLsizei bufsize,GLsizei * size,void * info)6259 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
6260                                                                GLsizei bufsize,
6261                                                                GLsizei* size,
6262                                                                void* info) {
6263   GPU_CLIENT_SINGLE_THREAD_CHECK();
6264   if (bufsize < 0) {
6265     SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM",
6266                "bufsize less than 0.");
6267     return;
6268   }
6269   if (size == nullptr) {
6270     SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM",
6271                "size is null.");
6272     return;
6273   }
6274   // Make sure they've set size to 0 else the value will be undefined on
6275   // lost context.
6276   DCHECK_EQ(0, *size);
6277   std::vector<int8_t> result;
6278   GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result);
6279   if (result.empty()) {
6280     return;
6281   }
6282   *size = result.size();
6283   if (!info) {
6284     return;
6285   }
6286   if (static_cast<size_t>(bufsize) < result.size()) {
6287     SetGLError(GL_INVALID_OPERATION, "glGetTransformFeedbackVaryingsCHROMIUM",
6288                "bufsize is too small for result.");
6289     return;
6290   }
6291   memcpy(info, &result[0], result.size());
6292 }
6293 
PostSubBufferCHROMIUM(uint64_t swap_id,GLint x,GLint y,GLint width,GLint height,GLbitfield flags)6294 void GLES2Implementation::PostSubBufferCHROMIUM(uint64_t swap_id,
6295                                                 GLint x,
6296                                                 GLint y,
6297                                                 GLint width,
6298                                                 GLint height,
6299                                                 GLbitfield flags) {
6300   GPU_CLIENT_SINGLE_THREAD_CHECK();
6301   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM(" << x
6302                      << ", " << y << ", " << width << ", " << height << ")");
6303   TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM", "width", width, "height",
6304                height);
6305 
6306   // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
6307   swap_buffers_tokens_.push(helper_->InsertToken());
6308   helper_->PostSubBufferCHROMIUM(swap_id, x, y, width, height, flags);
6309   helper_->CommandBufferHelper::Flush();
6310   if (swap_buffers_tokens_.size() > kMaxSwapBuffers + 1) {
6311     helper_->WaitForToken(swap_buffers_tokens_.front());
6312     swap_buffers_tokens_.pop();
6313   }
6314 }
6315 
DeleteQueriesEXTHelper(GLsizei n,const GLuint * queries)6316 void GLES2Implementation::DeleteQueriesEXTHelper(GLsizei n,
6317                                                  const GLuint* queries) {
6318   IdAllocator* id_allocator = GetIdAllocator(IdNamespaces::kQueries);
6319   for (GLsizei ii = 0; ii < n; ++ii) {
6320     query_tracker_->RemoveQuery(queries[ii]);
6321     id_allocator->FreeID(queries[ii]);
6322   }
6323 
6324   helper_->DeleteQueriesEXTImmediate(n, queries);
6325 }
6326 
IsQueryEXT(GLuint id)6327 GLboolean GLES2Implementation::IsQueryEXT(GLuint id) {
6328   GPU_CLIENT_SINGLE_THREAD_CHECK();
6329   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id << ")");
6330 
6331   // TODO(gman): To be spec compliant IDs from other contexts sharing
6332   // resources need to return true here even though you can't share
6333   // queries across contexts?
6334   return query_tracker_->GetQuery(id) != nullptr;
6335 }
6336 
BeginQueryEXT(GLenum target,GLuint id)6337 void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) {
6338   GPU_CLIENT_SINGLE_THREAD_CHECK();
6339   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
6340                      << GLES2Util::GetStringQueryTarget(target) << ", " << id
6341                      << ")");
6342 
6343   switch (target) {
6344     case GL_COMMANDS_ISSUED_CHROMIUM:
6345     case GL_LATENCY_QUERY_CHROMIUM:
6346     case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
6347     case GL_GET_ERROR_QUERY_CHROMIUM:
6348     case GL_PROGRAM_COMPLETION_QUERY_CHROMIUM:
6349       break;
6350     case GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM:
6351     case GL_COMMANDS_COMPLETED_CHROMIUM:
6352       if (!capabilities_.sync_query) {
6353         SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
6354                    "not enabled for commands completed queries");
6355         return;
6356       }
6357       break;
6358     case GL_SAMPLES_PASSED_ARB:
6359       if (!capabilities_.occlusion_query) {
6360         SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
6361                    "not enabled for occlusion queries");
6362         return;
6363       }
6364       break;
6365     case GL_ANY_SAMPLES_PASSED:
6366     case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
6367       if (!capabilities_.occlusion_query_boolean) {
6368         SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
6369                    "not enabled for boolean occlusion queries");
6370         return;
6371       }
6372       break;
6373     case GL_TIME_ELAPSED_EXT:
6374       if (!capabilities_.timer_queries) {
6375         SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
6376                    "not enabled for timing queries");
6377         return;
6378       }
6379       break;
6380     case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
6381       if (capabilities_.major_version >= 3)
6382         break;
6383       FALLTHROUGH;
6384     default:
6385       SetGLError(GL_INVALID_ENUM, "glBeginQueryEXT", "unknown query target");
6386       return;
6387   }
6388 
6389   // if any outstanding queries INV_OP
6390   if (query_tracker_->GetCurrentQuery(target)) {
6391     SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT",
6392                "query already in progress");
6393     return;
6394   }
6395 
6396   if (id == 0) {
6397     SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
6398     return;
6399   }
6400 
6401   if (!GetIdAllocator(IdNamespaces::kQueries)->InUse(id)) {
6402     SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "invalid id");
6403     return;
6404   }
6405 
6406   // Extra setups some targets might need.
6407   switch (target) {
6408     case GL_TIME_ELAPSED_EXT:
6409       if (!query_tracker_->SetDisjointSync(this)) {
6410         SetGLError(GL_OUT_OF_MEMORY, "glBeginQueryEXT",
6411                    "buffer allocation failed");
6412         return;
6413       }
6414       break;
6415     default:
6416       break;
6417   }
6418 
6419   if (query_tracker_->BeginQuery(id, target, this))
6420     CheckGLError();
6421 
6422   if (target == GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM) {
6423     AllocateShadowCopiesForReadback();
6424   }
6425 }
6426 
AllocateShadowCopiesForReadback()6427 void GLES2Implementation::AllocateShadowCopiesForReadback() {
6428   for (auto buffer : readback_buffer_shadow_tracker_->GetUnfencedBufferList()) {
6429     if (!buffer) {
6430       continue;
6431     }
6432     int32_t shm_id = 0;
6433     uint32_t shm_offset = 0;
6434     bool already_allocated = false;
6435     uint32_t size = buffer->Alloc(&shm_id, &shm_offset, &already_allocated);
6436     if (already_allocated) {
6437       SendErrorMessage(
6438           "performance warning: READ-usage buffer was written, then "
6439           "fenced, but written again before being read back. This discarded "
6440           "the shadow copy that was created to accelerate readback.",
6441           0);
6442     }
6443     helper_->SetReadbackBufferShadowAllocationINTERNAL(buffer->id(), shm_id,
6444                                                        shm_offset, size);
6445   }
6446 }
6447 
BufferShadowWrittenCallback(const ReadbackBufferShadowTracker::BufferList & buffers,uint64_t serial)6448 void GLES2Implementation::BufferShadowWrittenCallback(
6449     const ReadbackBufferShadowTracker::BufferList& buffers,
6450     uint64_t serial) {
6451   for (const auto& buffer : buffers) {
6452     if (buffer) {
6453       buffer->UpdateSerialTo(serial);
6454     }
6455   }
6456 }
6457 
EndQueryEXT(GLenum target)6458 void GLES2Implementation::EndQueryEXT(GLenum target) {
6459   QueryTracker::Query* query = nullptr;
6460   {
6461     GPU_CLIENT_SINGLE_THREAD_CHECK();
6462     GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
6463                        << GLES2Util::GetStringQueryTarget(target) << ")");
6464     query = query_tracker_->GetCurrentQuery(target);
6465     if (!query_tracker_->EndQuery(target, this)) {
6466       return;
6467     }
6468     CheckGLError();
6469   }  // GPU_CLIENT_SINGLE_THREAD_CHECK ends here
6470 
6471   if (target == GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM) {
6472     DCHECK(capabilities_.chromium_nonblocking_readback);
6473     DCHECK(query);
6474     auto serial = readback_buffer_shadow_tracker_->buffer_shadow_serial();
6475     readback_buffer_shadow_tracker_->IncrementSerial();
6476     auto buffers = readback_buffer_shadow_tracker_->TakeUnfencedBufferList();
6477     query->SetCompletedCallback(
6478         base::BindOnce(&GLES2Implementation::BufferShadowWrittenCallback,
6479                        std::move(buffers), serial));
6480   }
6481 }
6482 
QueryCounterEXT(GLuint id,GLenum target)6483 void GLES2Implementation::QueryCounterEXT(GLuint id, GLenum target) {
6484   GPU_CLIENT_SINGLE_THREAD_CHECK();
6485   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] QueryCounterEXT(" << id << ", "
6486                      << GLES2Util::GetStringQueryTarget(target) << ")");
6487 
6488   switch (target) {
6489     case GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM:
6490       break;
6491     case GL_TIMESTAMP_EXT:
6492       if (!capabilities_.timer_queries) {
6493         SetGLError(GL_INVALID_OPERATION, "glQueryCounterEXT",
6494                    "not enabled for timing queries");
6495         return;
6496       }
6497       break;
6498     default:
6499       SetGLError(GL_INVALID_ENUM, "glQueryCounterEXT", "unknown query target");
6500       return;
6501   }
6502 
6503   if (id == 0) {
6504     SetGLError(GL_INVALID_OPERATION, "glQueryCounterEXT", "id is 0");
6505     return;
6506   }
6507 
6508   if (!GetIdAllocator(IdNamespaces::kQueries)->InUse(id)) {
6509     SetGLError(GL_INVALID_OPERATION, "glQueryCounterEXT", "invalid id");
6510     return;
6511   }
6512 
6513   // Extra setups some targets might need.
6514   switch (target) {
6515     case GL_TIMESTAMP_EXT:
6516       if (!query_tracker_->SetDisjointSync(this)) {
6517         SetGLError(GL_OUT_OF_MEMORY, "glQueryCounterEXT",
6518                    "buffer allocation failed");
6519         return;
6520       }
6521       break;
6522     default:
6523       break;
6524   }
6525 
6526   if (query_tracker_->QueryCounter(id, target, this))
6527     CheckGLError();
6528 }
6529 
GetQueryivEXT(GLenum target,GLenum pname,GLint * params)6530 void GLES2Implementation::GetQueryivEXT(GLenum target,
6531                                         GLenum pname,
6532                                         GLint* params) {
6533   GPU_CLIENT_SINGLE_THREAD_CHECK();
6534   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
6535                      << GLES2Util::GetStringQueryTarget(target) << ", "
6536                      << GLES2Util::GetStringQueryParameter(pname) << ", "
6537                      << static_cast<const void*>(params) << ")");
6538   if (pname == GL_QUERY_COUNTER_BITS_EXT) {
6539     switch (target) {
6540       case GL_TIMESTAMP_EXT:
6541         // Overall reliable driver support for timestamps is limited, so we
6542         // disable the timestamp portion of this extension to encourage use of
6543         // the better supported time elapsed queries.
6544         *params = 0;
6545         break;
6546       case GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM:
6547       case GL_TIME_ELAPSED_EXT:
6548         // We convert all queries to CPU time so we support 64 bits.
6549         *params = 64;
6550         break;
6551       default:
6552         SetGLErrorInvalidEnum("glGetQueryivEXT", target, "target");
6553         break;
6554     }
6555     return;
6556   } else if (pname != GL_CURRENT_QUERY_EXT) {
6557     SetGLErrorInvalidEnum("glGetQueryivEXT", pname, "pname");
6558     return;
6559   }
6560   QueryTracker::Query* query = query_tracker_->GetCurrentQuery(target);
6561   *params = query ? query->id() : 0;
6562   GPU_CLIENT_LOG("  " << *params);
6563   CheckGLError();
6564 }
6565 
GetQueryObjectivEXT(GLuint id,GLenum pname,GLint * params)6566 void GLES2Implementation::GetQueryObjectivEXT(GLuint id,
6567                                               GLenum pname,
6568                                               GLint* params) {
6569   GLuint64 result = 0;
6570   if (GetQueryObjectValueHelper("glGetQueryObjectivEXT", id, pname, &result))
6571     *params = base::saturated_cast<GLint>(result);
6572 }
6573 
GetQueryObjectuivEXT(GLuint id,GLenum pname,GLuint * params)6574 void GLES2Implementation::GetQueryObjectuivEXT(GLuint id,
6575                                                GLenum pname,
6576                                                GLuint* params) {
6577   GLuint64 result = 0;
6578   if (GetQueryObjectValueHelper("glGetQueryObjectuivEXT", id, pname, &result))
6579     *params = base::saturated_cast<GLuint>(result);
6580 }
6581 
GetQueryObjecti64vEXT(GLuint id,GLenum pname,GLint64 * params)6582 void GLES2Implementation::GetQueryObjecti64vEXT(GLuint id,
6583                                                 GLenum pname,
6584                                                 GLint64* params) {
6585   GLuint64 result = 0;
6586   if (GetQueryObjectValueHelper("glGetQueryObjectiv64vEXT", id, pname, &result))
6587     *params = base::saturated_cast<GLint64>(result);
6588 }
6589 
GetQueryObjectui64vEXT(GLuint id,GLenum pname,GLuint64 * params)6590 void GLES2Implementation::GetQueryObjectui64vEXT(GLuint id,
6591                                                  GLenum pname,
6592                                                  GLuint64* params) {
6593   GLuint64 result = 0;
6594   if (GetQueryObjectValueHelper("glGetQueryObjectui64vEXT", id, pname, &result))
6595     *params = result;
6596 }
6597 
SetDisjointValueSyncCHROMIUM()6598 void GLES2Implementation::SetDisjointValueSyncCHROMIUM() {
6599   query_tracker_->SetDisjointSync(this);
6600 }
6601 
DrawArraysInstancedANGLE(GLenum mode,GLint first,GLsizei count,GLsizei primcount)6602 void GLES2Implementation::DrawArraysInstancedANGLE(GLenum mode,
6603                                                    GLint first,
6604                                                    GLsizei count,
6605                                                    GLsizei primcount) {
6606   GPU_CLIENT_SINGLE_THREAD_CHECK();
6607   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
6608                      << GLES2Util::GetStringDrawMode(mode) << ", " << first
6609                      << ", " << count << ", " << primcount << ")");
6610   if (count < 0) {
6611     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "count < 0");
6612     return;
6613   }
6614   if (primcount < 0) {
6615     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE", "primcount < 0");
6616     return;
6617   }
6618   if (primcount == 0) {
6619     return;
6620   }
6621   bool simulated = false;
6622   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
6623     GLsizei num_elements;
6624     if (!base::CheckAdd(first, count).AssignIfValid(&num_elements)) {
6625       SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedANGLE",
6626                  "first+count overflow");
6627       return;
6628     }
6629     if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers(
6630             "glDrawArraysInstancedANGLE", this, helper_, num_elements,
6631             primcount, &simulated)) {
6632       return;
6633     }
6634   }
6635   helper_->DrawArraysInstancedANGLE(mode, first, count, primcount);
6636   RestoreArrayBuffer(simulated);
6637   CheckGLError();
6638 }
6639 
DrawArraysInstancedBaseInstanceANGLE(GLenum mode,GLint first,GLsizei count,GLsizei primcount,GLuint baseinstance)6640 void GLES2Implementation::DrawArraysInstancedBaseInstanceANGLE(
6641     GLenum mode,
6642     GLint first,
6643     GLsizei count,
6644     GLsizei primcount,
6645     GLuint baseinstance) {
6646   GPU_CLIENT_SINGLE_THREAD_CHECK();
6647   GPU_CLIENT_LOG(
6648       "[" << GetLogPrefix() << "] glDrawArraysInstancedBaseInstanceANGLE("
6649           << GLES2Util::GetStringDrawMode(mode) << ", " << first << ", "
6650           << count << ", " << primcount << ", " << baseinstance << ")");
6651   if (count < 0) {
6652     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedBaseInstanceANGLE",
6653                "count < 0");
6654     return;
6655   }
6656   if (primcount < 0) {
6657     SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedBaseInstanceANGLE",
6658                "primcount < 0");
6659     return;
6660   }
6661   if (primcount == 0) {
6662     return;
6663   }
6664   bool simulated = false;
6665   if (vertex_array_object_manager_->SupportsClientSideBuffers()) {
6666     GLsizei num_elements;
6667     if (!base::CheckAdd(first, count).AssignIfValid(&num_elements)) {
6668       SetGLError(GL_INVALID_VALUE, "glDrawArraysInstancedBaseInstanceANGLE",
6669                  "first+count overflow");
6670       return;
6671     }
6672     // Client side buffer is not used by WebGL so leave it as is.
6673     if (!vertex_array_object_manager_->SetupSimulatedClientSideBuffers(
6674             "glDrawArraysInstancedBaseInstanceANGLE", this, helper_,
6675             num_elements, primcount, &simulated)) {
6676       return;
6677     }
6678   }
6679   helper_->DrawArraysInstancedBaseInstanceANGLE(mode, first, count, primcount,
6680                                                 baseinstance);
6681   RestoreArrayBuffer(simulated);
6682   CheckGLError();
6683 }
6684 
DrawElementsInstancedANGLE(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount)6685 void GLES2Implementation::DrawElementsInstancedANGLE(GLenum mode,
6686                                                      GLsizei count,
6687                                                      GLenum type,
6688                                                      const void* indices,
6689                                                      GLsizei primcount) {
6690   GPU_CLIENT_SINGLE_THREAD_CHECK();
6691   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
6692                      << GLES2Util::GetStringDrawMode(mode) << ", " << count
6693                      << ", " << GLES2Util::GetStringIndexType(type) << ", "
6694                      << static_cast<const void*>(indices) << ", " << primcount
6695                      << ")");
6696   if (count < 0) {
6697     SetGLError(GL_INVALID_VALUE, "glDrawElementsInstancedANGLE",
6698                "count less than 0.");
6699     return;
6700   }
6701   if (primcount < 0) {
6702     SetGLError(GL_INVALID_VALUE, "glDrawElementsInstancedANGLE",
6703                "primcount < 0");
6704     return;
6705   }
6706   GLuint offset = 0;
6707   bool simulated = false;
6708   if (count > 0 && primcount > 0) {
6709     if (vertex_array_object_manager_->bound_element_array_buffer() != 0 &&
6710         !ValidateOffset("glDrawElementsInstancedANGLE",
6711                         reinterpret_cast<GLintptr>(indices))) {
6712       return;
6713     }
6714     if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
6715             "glDrawElementsInstancedANGLE", this, helper_, count, type,
6716             primcount, indices, &offset, &simulated)) {
6717       return;
6718     }
6719   }
6720   helper_->DrawElementsInstancedANGLE(mode, count, type, offset, primcount);
6721   RestoreElementAndArrayBuffers(simulated);
6722   CheckGLError();
6723 }
6724 
DrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount,GLint basevertex,GLuint baseinstance)6725 void GLES2Implementation::DrawElementsInstancedBaseVertexBaseInstanceANGLE(
6726     GLenum mode,
6727     GLsizei count,
6728     GLenum type,
6729     const void* indices,
6730     GLsizei primcount,
6731     GLint basevertex,
6732     GLuint baseinstance) {
6733   GPU_CLIENT_SINGLE_THREAD_CHECK();
6734   GPU_CLIENT_LOG("[" << GetLogPrefix()
6735                      << "] glDrawElementsInstancedBaseVertexBaseInstanceANGLE("
6736                      << GLES2Util::GetStringDrawMode(mode) << ", " << count
6737                      << ", " << GLES2Util::GetStringIndexType(type) << ", "
6738                      << static_cast<const void*>(indices) << ", " << primcount
6739                      << ", " << basevertex << ", " << baseinstance << ")");
6740   if (count < 0) {
6741     SetGLError(GL_INVALID_VALUE,
6742                "glDrawElementsInstancedBaseVertexBaseInstanceANGLE",
6743                "count less than 0.");
6744     return;
6745   }
6746   if (primcount < 0) {
6747     SetGLError(GL_INVALID_VALUE,
6748                "glDrawElementsInstancedBaseVertexBaseInstanceANGLE",
6749                "primcount < 0");
6750     return;
6751   }
6752   GLuint offset = 0;
6753   bool simulated = false;
6754   if (count > 0 && primcount > 0) {
6755     if (vertex_array_object_manager_->bound_element_array_buffer() != 0 &&
6756         !ValidateOffset("glDrawElementsInstancedBaseVertexBaseInstanceANGLE",
6757                         reinterpret_cast<GLintptr>(indices))) {
6758       return;
6759     }
6760     // Client side buffer is not used by WebGL so leave it as is.
6761     if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers(
6762             "glDrawElementsInstancedBaseVertexBaseInstanceANGLE", this, helper_,
6763             count, type, primcount, indices, &offset, &simulated)) {
6764       return;
6765     }
6766   }
6767   helper_->DrawElementsInstancedBaseVertexBaseInstanceANGLE(
6768       mode, count, type, offset, primcount, basevertex, baseinstance);
6769   RestoreElementAndArrayBuffers(simulated);
6770   CheckGLError();
6771 }
6772 
ProduceTextureDirectCHROMIUM(GLuint texture,GLbyte * data)6773 void GLES2Implementation::ProduceTextureDirectCHROMIUM(GLuint texture,
6774                                                        GLbyte* data) {
6775   GPU_CLIENT_SINGLE_THREAD_CHECK();
6776   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
6777                      << static_cast<const void*>(data) << ")");
6778   static_assert(std::is_trivially_copyable<Mailbox>::value,
6779                 "gpu::Mailbox is not trivially copyable");
6780   Mailbox result = Mailbox::Generate();
6781   memcpy(data, result.name, sizeof(result.name));
6782   helper_->ProduceTextureDirectCHROMIUMImmediate(texture, data);
6783   CheckGLError();
6784 }
6785 
CreateAndConsumeTextureCHROMIUM(const GLbyte * data)6786 GLuint GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
6787     const GLbyte* data) {
6788   GPU_CLIENT_SINGLE_THREAD_CHECK();
6789   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
6790                      << static_cast<const void*>(data) << ")");
6791   const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
6792   DCHECK(mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
6793                               "mailbox that was not generated by "
6794                               "ProduceTextureDirectCHROMIUM.";
6795   GLuint client_id;
6796   GetIdHandler(SharedIdNamespaces::kTextures)->MakeIds(this, 0, 1, &client_id);
6797   helper_->CreateAndConsumeTextureINTERNALImmediate(client_id, data);
6798   if (share_group_->bind_generates_resource())
6799     helper_->CommandBufferHelper::OrderingBarrier();
6800   CheckGLError();
6801   return client_id;
6802 }
6803 
CreateAndTexStorage2DSharedImageCHROMIUM(const GLbyte * mailbox_data)6804 GLuint GLES2Implementation::CreateAndTexStorage2DSharedImageCHROMIUM(
6805     const GLbyte* mailbox_data) {
6806   GPU_CLIENT_SINGLE_THREAD_CHECK();
6807   GPU_CLIENT_LOG("[" << GetLogPrefix()
6808                      << "] CreateAndTexStorage2DSharedImageCHROMIUM("
6809                      << static_cast<const void*>(mailbox_data) << ")");
6810   const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(mailbox_data);
6811   DCHECK(mailbox.Verify()) << "CreateAndTexStorage2DSharedImageCHROMIUM was "
6812                               "passed an invalid mailbox.";
6813   DCHECK(mailbox.IsSharedImage());
6814   GLuint client_id;
6815   GetIdHandler(SharedIdNamespaces::kTextures)->MakeIds(this, 0, 1, &client_id);
6816   helper_->CreateAndTexStorage2DSharedImageINTERNALImmediate(client_id, GL_NONE,
6817                                                              mailbox_data);
6818   if (share_group_->bind_generates_resource())
6819     helper_->CommandBufferHelper::OrderingBarrier();
6820   CheckGLError();
6821   return client_id;
6822 }
6823 
6824 GLuint
CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM(const GLbyte * mailbox_data,GLenum internalformat)6825 GLES2Implementation::CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM(
6826     const GLbyte* mailbox_data,
6827     GLenum internalformat) {
6828   GPU_CLIENT_SINGLE_THREAD_CHECK();
6829   GPU_CLIENT_LOG(
6830       "[" << GetLogPrefix()
6831           << "] CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM("
6832           << static_cast<const void*>(mailbox_data) << ", " << internalformat
6833           << ")");
6834   const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(mailbox_data);
6835   DCHECK(mailbox.Verify())
6836       << "CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM was "
6837          "passed an invalid mailbox.";
6838   DCHECK(mailbox.IsSharedImage());
6839   GLuint client_id;
6840   GetIdHandler(SharedIdNamespaces::kTextures)->MakeIds(this, 0, 1, &client_id);
6841   helper_->CreateAndTexStorage2DSharedImageINTERNALImmediate(
6842       client_id, internalformat, mailbox_data);
6843   if (share_group_->bind_generates_resource())
6844     helper_->CommandBufferHelper::OrderingBarrier();
6845   CheckGLError();
6846   return client_id;
6847 }
6848 
PushGroupMarkerEXT(GLsizei length,const GLchar * marker)6849 void GLES2Implementation::PushGroupMarkerEXT(GLsizei length,
6850                                              const GLchar* marker) {
6851   GPU_CLIENT_SINGLE_THREAD_CHECK();
6852   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT(" << length
6853                      << ", " << marker << ")");
6854   if (!marker) {
6855     marker = "";
6856   }
6857   SetBucketAsString(kResultBucketId, (length ? std::string(marker, length)
6858                                              : std::string(marker)));
6859   helper_->PushGroupMarkerEXT(kResultBucketId);
6860   helper_->SetBucketSize(kResultBucketId, 0);
6861   debug_marker_manager_.PushGroup(length ? std::string(marker, length)
6862                                          : std::string(marker));
6863 }
6864 
InsertEventMarkerEXT(GLsizei length,const GLchar * marker)6865 void GLES2Implementation::InsertEventMarkerEXT(GLsizei length,
6866                                                const GLchar* marker) {
6867   GPU_CLIENT_SINGLE_THREAD_CHECK();
6868   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT(" << length
6869                      << ", " << marker << ")");
6870   if (!marker) {
6871     marker = "";
6872   }
6873   SetBucketAsString(kResultBucketId, (length ? std::string(marker, length)
6874                                              : std::string(marker)));
6875   helper_->InsertEventMarkerEXT(kResultBucketId);
6876   helper_->SetBucketSize(kResultBucketId, 0);
6877   debug_marker_manager_.SetMarker(length ? std::string(marker, length)
6878                                          : std::string(marker));
6879 }
6880 
PopGroupMarkerEXT()6881 void GLES2Implementation::PopGroupMarkerEXT() {
6882   GPU_CLIENT_SINGLE_THREAD_CHECK();
6883   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
6884   helper_->PopGroupMarkerEXT();
6885   debug_marker_manager_.PopGroup();
6886 }
6887 
TraceBeginCHROMIUM(const char * category_name,const char * trace_name)6888 void GLES2Implementation::TraceBeginCHROMIUM(const char* category_name,
6889                                              const char* trace_name) {
6890   GPU_CLIENT_SINGLE_THREAD_CHECK();
6891   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
6892                      << category_name << ", " << trace_name << ")");
6893   static constexpr size_t kMaxStrLen = 256;
6894   DCHECK_LE(strlen(category_name), kMaxStrLen);
6895   DCHECK_LE(strlen(trace_name), kMaxStrLen);
6896   SetBucketAsCString(kResultBucketId, category_name);
6897   SetBucketAsCString(kResultBucketId + 1, trace_name);
6898   helper_->TraceBeginCHROMIUM(kResultBucketId, kResultBucketId + 1);
6899   helper_->SetBucketSize(kResultBucketId, 0);
6900   helper_->SetBucketSize(kResultBucketId + 1, 0);
6901   current_trace_stack_++;
6902 }
6903 
TraceEndCHROMIUM()6904 void GLES2Implementation::TraceEndCHROMIUM() {
6905   GPU_CLIENT_SINGLE_THREAD_CHECK();
6906   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM("
6907                      << ")");
6908   if (current_trace_stack_ == 0) {
6909     SetGLError(GL_INVALID_OPERATION, "glTraceEndCHROMIUM",
6910                "missing begin trace");
6911     return;
6912   }
6913   helper_->TraceEndCHROMIUM();
6914   current_trace_stack_--;
6915 }
6916 
MapBufferCHROMIUM(GLuint target,GLenum access)6917 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
6918   GPU_CLIENT_SINGLE_THREAD_CHECK();
6919   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM(" << target
6920                      << ", " << GLES2Util::GetStringEnum(access) << ")");
6921   switch (target) {
6922     case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
6923       if (access != GL_READ_ONLY) {
6924         SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
6925         return nullptr;
6926       }
6927       break;
6928     default:
6929       SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target");
6930       return nullptr;
6931   }
6932   GLuint buffer_id;
6933   GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id);
6934   if (!buffer_id) {
6935     return nullptr;
6936   }
6937   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
6938   if (!buffer) {
6939     SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
6940     return nullptr;
6941   }
6942   if (buffer->mapped()) {
6943     SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
6944     return nullptr;
6945   }
6946   // Here we wait for previous transfer operations to be finished.
6947   if (buffer->last_usage_token()) {
6948     helper_->WaitForToken(buffer->last_usage_token());
6949     buffer->set_last_usage_token(0);
6950   }
6951   buffer->set_mapped(true);
6952 
6953   GPU_CLIENT_LOG("  returned " << buffer->address());
6954   CheckGLError();
6955   return buffer->address();
6956 }
6957 
UnmapBufferCHROMIUM(GLuint target)6958 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
6959   GPU_CLIENT_SINGLE_THREAD_CHECK();
6960   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
6961                      << ")");
6962   GLuint buffer_id;
6963   if (!GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id)) {
6964     SetGLError(GL_INVALID_ENUM, "glUnmapBufferCHROMIUM", "invalid target");
6965   }
6966   if (!buffer_id) {
6967     return false;
6968   }
6969   BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
6970   if (!buffer) {
6971     SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "invalid buffer");
6972     return false;
6973   }
6974   if (!buffer->mapped()) {
6975     SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped");
6976     return false;
6977   }
6978   buffer->set_mapped(false);
6979   CheckGLError();
6980   return true;
6981 }
6982 
ShareGroupTracingGUID() const6983 uint64_t GLES2Implementation::ShareGroupTracingGUID() const {
6984   return share_group_->TracingGUID();
6985 }
6986 
SetErrorMessageCallback(base::RepeatingCallback<void (const char *,int32_t)> callback)6987 void GLES2Implementation::SetErrorMessageCallback(
6988     base::RepeatingCallback<void(const char*, int32_t)> callback) {
6989   error_message_callback_ = std::move(callback);
6990 }
6991 
ThreadSafeShallowLockDiscardableTexture(uint32_t texture_id)6992 bool GLES2Implementation::ThreadSafeShallowLockDiscardableTexture(
6993     uint32_t texture_id) {
6994   ClientDiscardableTextureManager* manager =
6995       share_group()->discardable_texture_manager();
6996   return manager->TextureIsValid(texture_id) &&
6997          manager->LockTexture(texture_id);
6998 }
6999 
CompleteLockDiscardableTexureOnContextThread(uint32_t texture_id)7000 void GLES2Implementation::CompleteLockDiscardableTexureOnContextThread(
7001     uint32_t texture_id) {
7002   helper_->LockDiscardableTextureCHROMIUM(texture_id);
7003 }
7004 
ThreadsafeDiscardableTextureIsDeletedForTracing(uint32_t texture_id)7005 bool GLES2Implementation::ThreadsafeDiscardableTextureIsDeletedForTracing(
7006     uint32_t texture_id) {
7007   ClientDiscardableTextureManager* manager =
7008       share_group()->discardable_texture_manager();
7009   return manager->TextureIsDeletedForTracing(texture_id);
7010 }
7011 
MapTransferCacheEntry(uint32_t serialized_size)7012 void* GLES2Implementation::MapTransferCacheEntry(uint32_t serialized_size) {
7013   NOTREACHED();
7014   return nullptr;
7015 }
7016 
UnmapAndCreateTransferCacheEntry(uint32_t type,uint32_t id)7017 void GLES2Implementation::UnmapAndCreateTransferCacheEntry(uint32_t type,
7018                                                            uint32_t id) {
7019   NOTREACHED();
7020 }
7021 
ThreadsafeLockTransferCacheEntry(uint32_t type,uint32_t id)7022 bool GLES2Implementation::ThreadsafeLockTransferCacheEntry(uint32_t type,
7023                                                            uint32_t id) {
7024   NOTREACHED();
7025   return false;
7026 }
7027 
UnlockTransferCacheEntries(const std::vector<std::pair<uint32_t,uint32_t>> & entries)7028 void GLES2Implementation::UnlockTransferCacheEntries(
7029     const std::vector<std::pair<uint32_t, uint32_t>>& entries) {
7030   NOTREACHED();
7031 }
7032 
DeleteTransferCacheEntry(uint32_t type,uint32_t id)7033 void GLES2Implementation::DeleteTransferCacheEntry(uint32_t type, uint32_t id) {
7034   NOTREACHED();
7035 }
7036 
GetTransferBufferFreeSize() const7037 unsigned int GLES2Implementation::GetTransferBufferFreeSize() const {
7038   NOTREACHED();
7039   return 0;
7040 }
7041 
IsJpegDecodeAccelerationSupported() const7042 bool GLES2Implementation::IsJpegDecodeAccelerationSupported() const {
7043   NOTREACHED();
7044   return false;
7045 }
7046 
IsWebPDecodeAccelerationSupported() const7047 bool GLES2Implementation::IsWebPDecodeAccelerationSupported() const {
7048   NOTREACHED();
7049   return false;
7050 }
7051 
CanDecodeWithHardwareAcceleration(const cc::ImageHeaderMetadata * image_metadata) const7052 bool GLES2Implementation::CanDecodeWithHardwareAcceleration(
7053     const cc::ImageHeaderMetadata* image_metadata) const {
7054   NOTREACHED();
7055   return false;
7056 }
7057 
7058 namespace {
7059 
CreateImageValidInternalFormat(GLenum internalformat,const Capabilities & capabilities)7060 bool CreateImageValidInternalFormat(GLenum internalformat,
7061                                     const Capabilities& capabilities) {
7062   switch (internalformat) {
7063     case GL_R16_EXT:
7064       return capabilities.texture_norm16;
7065     case GL_RGB10_A2_EXT:
7066       return capabilities.image_ar30 || capabilities.image_ab30;
7067     case GL_RGB_YCBCR_P010_CHROMIUM:
7068       return capabilities.image_ycbcr_p010;
7069     case GL_RED:
7070     case GL_RG_EXT:
7071     case GL_RGB:
7072     case GL_RGBA:
7073     case GL_RGB_YCBCR_422_CHROMIUM:
7074     case GL_RGB_YCBCR_420V_CHROMIUM:
7075     case GL_RGB_YCRCB_420_CHROMIUM:
7076     case GL_BGRA_EXT:
7077       return true;
7078     default:
7079       return false;
7080   }
7081 }
7082 
7083 }  // namespace
7084 
CreateImageCHROMIUMHelper(ClientBuffer buffer,GLsizei width,GLsizei height,GLenum internalformat)7085 GLuint GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer,
7086                                                       GLsizei width,
7087                                                       GLsizei height,
7088                                                       GLenum internalformat) {
7089   if (width <= 0) {
7090     SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "width <= 0");
7091     return 0;
7092   }
7093 
7094   if (height <= 0) {
7095     SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "height <= 0");
7096     return 0;
7097   }
7098 
7099   if (!CreateImageValidInternalFormat(internalformat, capabilities_)) {
7100     SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "invalid format");
7101     return 0;
7102   }
7103 
7104   // CreateImage creates a fence sync so we must flush first to ensure all
7105   // previously created fence syncs are flushed first.
7106   FlushHelper();
7107 
7108   int32_t image_id = gpu_control_->CreateImage(buffer, width, height);
7109   if (image_id < 0) {
7110     SetGLError(GL_OUT_OF_MEMORY, "glCreateImageCHROMIUM", "image_id < 0");
7111     return 0;
7112   }
7113   return image_id;
7114 }
7115 
CreateImageCHROMIUM(ClientBuffer buffer,GLsizei width,GLsizei height,GLenum internalformat)7116 GLuint GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer,
7117                                                 GLsizei width,
7118                                                 GLsizei height,
7119                                                 GLenum internalformat) {
7120   GPU_CLIENT_SINGLE_THREAD_CHECK();
7121   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
7122                      << ", " << height << ", "
7123                      << GLES2Util::GetStringImageInternalFormat(internalformat)
7124                      << ")");
7125   GLuint image_id =
7126       CreateImageCHROMIUMHelper(buffer, width, height, internalformat);
7127   CheckGLError();
7128   return image_id;
7129 }
7130 
DestroyImageCHROMIUMHelper(GLuint image_id)7131 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id) {
7132   // Flush the command stream to make sure all pending commands
7133   // that may refer to the image_id are executed on the service side.
7134   helper_->CommandBufferHelper::Flush();
7135   gpu_control_->DestroyImage(image_id);
7136 }
7137 
DestroyImageCHROMIUM(GLuint image_id)7138 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id) {
7139   GPU_CLIENT_SINGLE_THREAD_CHECK();
7140   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
7141                      << image_id << ")");
7142   DestroyImageCHROMIUMHelper(image_id);
7143   CheckGLError();
7144 }
7145 
ValidateSize(const char * func,GLsizeiptr size)7146 bool GLES2Implementation::ValidateSize(const char* func, GLsizeiptr size) {
7147   if (size < 0) {
7148     SetGLError(GL_INVALID_VALUE, func, "size < 0");
7149     return false;
7150   }
7151   if (!base::IsValueInRangeForNumericType<int32_t>(size)) {
7152     SetGLError(GL_INVALID_OPERATION, func, "size more than 32-bit");
7153     return false;
7154   }
7155   return true;
7156 }
7157 
ValidateOffset(const char * func,GLintptr offset)7158 bool GLES2Implementation::ValidateOffset(const char* func, GLintptr offset) {
7159   if (offset < 0) {
7160     SetGLError(GL_INVALID_VALUE, func, "offset < 0");
7161     return false;
7162   }
7163   if (!base::IsValueInRangeForNumericType<int32_t>(offset)) {
7164     SetGLError(GL_INVALID_OPERATION, func, "offset more than 32-bit");
7165     return false;
7166   }
7167   return true;
7168 }
7169 
GetSamplerParameterfvHelper(GLuint,GLenum,GLfloat *)7170 bool GLES2Implementation::GetSamplerParameterfvHelper(GLuint /* sampler */,
7171                                                       GLenum /* pname */,
7172                                                       GLfloat* /* params */) {
7173   // TODO(zmo): Implement client side caching.
7174   return false;
7175 }
7176 
GetSamplerParameterivHelper(GLuint,GLenum,GLint *)7177 bool GLES2Implementation::GetSamplerParameterivHelper(GLuint /* sampler */,
7178                                                       GLenum /* pname */,
7179                                                       GLint* /* params */) {
7180   // TODO(zmo): Implement client side caching.
7181   return false;
7182 }
7183 
PackStringsToBucket(GLsizei count,const char * const * str,const GLint * length,const char * func_name)7184 bool GLES2Implementation::PackStringsToBucket(GLsizei count,
7185                                               const char* const* str,
7186                                               const GLint* length,
7187                                               const char* func_name) {
7188   DCHECK_LE(0, count);
7189   // Compute the total size.
7190   base::CheckedNumeric<uint32_t> total_size = count;
7191   total_size += 1;
7192   total_size *= sizeof(GLint);
7193   uint32_t header_size = 0;
7194   if (!total_size.AssignIfValid(&header_size)) {
7195     SetGLError(GL_INVALID_VALUE, func_name, "overflow");
7196     return false;
7197   }
7198   std::vector<GLint> header(count + 1);
7199   header[0] = static_cast<GLint>(count);
7200   for (GLsizei ii = 0; ii < count; ++ii) {
7201     GLint len = 0;
7202     if (str[ii]) {
7203       len = (length && length[ii] >= 0)
7204                 ? length[ii]
7205                 : base::checked_cast<GLint>(strlen(str[ii]));
7206     }
7207     total_size += len;
7208     total_size += 1;  // NULL at the end of each char array.
7209     header[ii + 1] = len;
7210   }
7211   // Pack data into a bucket on the service.
7212   uint32_t validated_size = 0;
7213   if (!total_size.AssignIfValid(&validated_size)) {
7214     SetGLError(GL_INVALID_VALUE, func_name, "overflow");
7215     return false;
7216   }
7217   helper_->SetBucketSize(kResultBucketId, validated_size);
7218   uint32_t offset = 0;
7219   for (GLsizei ii = 0; ii <= count; ++ii) {
7220     const char* src =
7221         (ii == 0) ? reinterpret_cast<const char*>(&header[0]) : str[ii - 1];
7222     uint32_t size = (ii == 0) ? header_size : header[ii];
7223     if (ii > 0) {
7224       size += 1;  // NULL in the end.
7225     }
7226     while (size) {
7227       ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
7228       if (!buffer.valid() || buffer.size() == 0) {
7229         SetGLError(GL_OUT_OF_MEMORY, func_name, "too large");
7230         return false;
7231       }
7232       uint32_t copy_size = buffer.size();
7233       if (ii > 0 && buffer.size() == size)
7234         --copy_size;
7235       if (copy_size)
7236         memcpy(buffer.address(), src, copy_size);
7237       if (copy_size < buffer.size()) {
7238         // Append NULL in the end.
7239         DCHECK(copy_size + 1 == buffer.size());
7240         char* str = reinterpret_cast<char*>(buffer.address());
7241         str[copy_size] = 0;
7242       }
7243       helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
7244                              buffer.shm_id(), buffer.offset());
7245       offset += buffer.size();
7246       src += buffer.size();
7247       size -= buffer.size();
7248     }
7249   }
7250   DCHECK_EQ(total_size.ValueOrDefault(0), offset);
7251   return true;
7252 }
7253 
UniformBlockBinding(GLuint program,GLuint index,GLuint binding)7254 void GLES2Implementation::UniformBlockBinding(GLuint program,
7255                                               GLuint index,
7256                                               GLuint binding) {
7257   GPU_CLIENT_SINGLE_THREAD_CHECK();
7258   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
7259                      << ", " << index << ", " << binding << ")");
7260   share_group_->program_info_manager()->UniformBlockBinding(this, program,
7261                                                             index, binding);
7262   helper_->UniformBlockBinding(program, index, binding);
7263   CheckGLError();
7264 }
7265 
ClientWaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)7266 GLenum GLES2Implementation::ClientWaitSync(GLsync sync,
7267                                            GLbitfield flags,
7268                                            GLuint64 timeout) {
7269   GPU_CLIENT_SINGLE_THREAD_CHECK();
7270   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync << ", "
7271                      << flags << ", " << timeout << ")");
7272   typedef cmds::ClientWaitSync::Result Result;
7273   auto result = GetResultAs<Result>();
7274   if (!result) {
7275     SetGLError(GL_OUT_OF_MEMORY, "ClientWaitSync", "");
7276     return GL_WAIT_FAILED;
7277   }
7278   *result = GL_WAIT_FAILED;
7279   helper_->ClientWaitSync(ToGLuint(sync), flags, timeout, GetResultShmId(),
7280                           result.offset());
7281   WaitForCmd();
7282   GPU_CLIENT_LOG("returned " << *result);
7283   CheckGLError();
7284   return *result;
7285 }
7286 
CopyBufferSubData(GLenum readtarget,GLenum writetarget,GLintptr readoffset,GLintptr writeoffset,GLsizeiptr size)7287 void GLES2Implementation::CopyBufferSubData(GLenum readtarget,
7288                                             GLenum writetarget,
7289                                             GLintptr readoffset,
7290                                             GLintptr writeoffset,
7291                                             GLsizeiptr size) {
7292   GPU_CLIENT_SINGLE_THREAD_CHECK();
7293   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCopyBufferSubData("
7294                      << GLES2Util::GetStringBufferTarget(readtarget) << ", "
7295                      << GLES2Util::GetStringBufferTarget(writetarget) << ", "
7296                      << readoffset << ", " << writeoffset << ", " << size
7297                      << ")");
7298   if (readoffset < 0) {
7299     SetGLError(GL_INVALID_VALUE, "glCopyBufferSubData", "readoffset < 0");
7300     return;
7301   }
7302   if (writeoffset < 0) {
7303     SetGLError(GL_INVALID_VALUE, "glCopyBufferSubData", "writeoffset < 0");
7304     return;
7305   }
7306   if (size < 0) {
7307     SetGLError(GL_INVALID_VALUE, "glCopyBufferSubData", "size < 0");
7308     return;
7309   }
7310   helper_->CopyBufferSubData(readtarget, writetarget, readoffset, writeoffset,
7311                              size);
7312   InvalidateReadbackBufferShadowDataCHROMIUM(GetBoundBufferHelper(writetarget));
7313   CheckGLError();
7314 }
7315 
WaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)7316 void GLES2Implementation::WaitSync(GLsync sync,
7317                                    GLbitfield flags,
7318                                    GLuint64 timeout) {
7319   GPU_CLIENT_SINGLE_THREAD_CHECK();
7320   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync << ", "
7321                      << flags << ", " << timeout << ")");
7322   helper_->WaitSync(ToGLuint(sync), flags, timeout);
7323   CheckGLError();
7324 }
7325 
GetInternalformativ(GLenum target,GLenum format,GLenum pname,GLsizei buf_size,GLint * params)7326 void GLES2Implementation::GetInternalformativ(GLenum target,
7327                                               GLenum format,
7328                                               GLenum pname,
7329                                               GLsizei buf_size,
7330                                               GLint* params) {
7331   GPU_CLIENT_SINGLE_THREAD_CHECK();
7332   GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params);
7333   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ("
7334                      << GLES2Util::GetStringRenderBufferTarget(target) << ", "
7335                      << GLES2Util::GetStringRenderBufferFormat(format) << ", "
7336                      << GLES2Util::GetStringInternalFormatParameter(pname)
7337                      << ", " << buf_size << ", "
7338                      << static_cast<const void*>(params) << ")");
7339   if (buf_size < 0) {
7340     SetGLError(GL_INVALID_VALUE, "glGetInternalformativ", "bufSize < 0");
7341     return;
7342   }
7343   TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ");
7344   if (GetInternalformativHelper(target, format, pname, buf_size, params)) {
7345     return;
7346   }
7347   typedef cmds::GetInternalformativ::Result Result;
7348   auto result = GetResultAs<Result>();
7349   if (!result) {
7350     return;
7351   }
7352   result->SetNumResults(0);
7353   helper_->GetInternalformativ(target, format, pname, GetResultShmId(),
7354                                result.offset());
7355   WaitForCmd();
7356   GPU_CLIENT_LOG_CODE_BLOCK({
7357     for (int32_t i = 0; i < result->GetNumResults(); ++i) {
7358       GPU_CLIENT_LOG("  " << i << ": " << result->GetData()[i]);
7359     }
7360   });
7361   if (buf_size > 0 && params) {
7362     GLint* data = result->GetData();
7363     if (buf_size >= result->GetNumResults()) {
7364       buf_size = result->GetNumResults();
7365     }
7366     for (GLsizei ii = 0; ii < buf_size; ++ii) {
7367       params[ii] = data[ii];
7368     }
7369   }
7370   CheckGLError();
7371 }
7372 
InitializeDiscardableTextureCHROMIUM(GLuint texture_id)7373 void GLES2Implementation::InitializeDiscardableTextureCHROMIUM(
7374     GLuint texture_id) {
7375   ClientDiscardableTextureManager* manager =
7376       share_group()->discardable_texture_manager();
7377   if (manager->TextureIsValid(texture_id)) {
7378     SetGLError(GL_INVALID_VALUE, "glInitializeDiscardableTextureCHROMIUM",
7379                "Texture ID already initialized");
7380     return;
7381   }
7382   ClientDiscardableHandle handle =
7383       manager->InitializeTexture(helper_->command_buffer(), texture_id);
7384   if (!handle.IsValid())
7385     return;
7386 
7387   helper_->InitializeDiscardableTextureCHROMIUM(texture_id, handle.shm_id(),
7388                                                 handle.byte_offset());
7389 }
7390 
UnlockDiscardableTextureCHROMIUM(GLuint texture_id)7391 void GLES2Implementation::UnlockDiscardableTextureCHROMIUM(GLuint texture_id) {
7392   ClientDiscardableTextureManager* manager =
7393       share_group()->discardable_texture_manager();
7394   if (!manager->TextureIsValid(texture_id)) {
7395     SetGLError(GL_INVALID_VALUE, "glUnlockDiscardableTextureCHROMIUM",
7396                "Texture ID not initialized");
7397     return;
7398   }
7399 
7400   // |should_unbind_texture| will be set to true if the texture has been fully
7401   // unlocked. In this case, ensure the texture is unbound.
7402   bool should_unbind_texture = false;
7403   manager->UnlockTexture(texture_id, &should_unbind_texture);
7404   if (should_unbind_texture)
7405     UnbindTexturesHelper(1, &texture_id);
7406 
7407   helper_->UnlockDiscardableTextureCHROMIUM(texture_id);
7408 }
7409 
LockDiscardableTextureCHROMIUM(GLuint texture_id)7410 bool GLES2Implementation::LockDiscardableTextureCHROMIUM(GLuint texture_id) {
7411   ClientDiscardableTextureManager* manager =
7412       share_group()->discardable_texture_manager();
7413   if (!manager->TextureIsValid(texture_id)) {
7414     SetGLError(GL_INVALID_VALUE, "glLockDiscardableTextureCHROMIUM",
7415                "Texture ID not initialized");
7416     return false;
7417   }
7418   if (!manager->LockTexture(texture_id)) {
7419     // Failure to lock means that this texture has been deleted on the service
7420     // side. Delete it here as well.
7421     DeleteTexturesHelper(1, &texture_id);
7422     return false;
7423   }
7424   helper_->LockDiscardableTextureCHROMIUM(texture_id);
7425   return true;
7426 }
7427 
UpdateCachedExtensionsIfNeeded()7428 void GLES2Implementation::UpdateCachedExtensionsIfNeeded() {
7429   if (cached_extension_string_) {
7430     return;
7431   }
7432   GetStringHelper(GL_EXTENSIONS);
7433 }
7434 
InvalidateCachedExtensions()7435 void GLES2Implementation::InvalidateCachedExtensions() {
7436   cached_extension_string_ = nullptr;
7437   cached_extensions_.clear();
7438 }
7439 
Viewport(GLint x,GLint y,GLsizei width,GLsizei height)7440 void GLES2Implementation::Viewport(GLint x,
7441                                    GLint y,
7442                                    GLsizei width,
7443                                    GLsizei height) {
7444   GPU_CLIENT_SINGLE_THREAD_CHECK();
7445   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glViewport(" << x << ", " << y
7446                      << ", " << width << ", " << height << ")");
7447   if (width < 0 || height < 0) {
7448     SetGLError(GL_INVALID_VALUE, "glViewport", "negative width/height");
7449     return;
7450   }
7451   state_.SetViewport(x, y, width, height);
7452   helper_->Viewport(x, y, width, height);
7453   CheckGLError();
7454 }
7455 
IssueBeginQuery(GLenum target,GLuint id,uint32_t sync_data_shm_id,uint32_t sync_data_shm_offset)7456 void GLES2Implementation::IssueBeginQuery(GLenum target,
7457                                           GLuint id,
7458                                           uint32_t sync_data_shm_id,
7459                                           uint32_t sync_data_shm_offset) {
7460   helper_->BeginQueryEXT(target, id, sync_data_shm_id, sync_data_shm_offset);
7461 }
7462 
IssueEndQuery(GLenum target,GLuint submit_count)7463 void GLES2Implementation::IssueEndQuery(GLenum target, GLuint submit_count) {
7464   helper_->EndQueryEXT(target, submit_count);
7465 }
7466 
IssueQueryCounter(GLuint id,GLenum target,uint32_t sync_data_shm_id,uint32_t sync_data_shm_offset,GLuint submit_count)7467 void GLES2Implementation::IssueQueryCounter(GLuint id,
7468                                             GLenum target,
7469                                             uint32_t sync_data_shm_id,
7470                                             uint32_t sync_data_shm_offset,
7471                                             GLuint submit_count) {
7472   helper_->QueryCounterEXT(id, target, sync_data_shm_id, sync_data_shm_offset,
7473                            submit_count);
7474 }
7475 
IssueSetDisjointValueSync(uint32_t sync_data_shm_id,uint32_t sync_data_shm_offset)7476 void GLES2Implementation::IssueSetDisjointValueSync(
7477     uint32_t sync_data_shm_id,
7478     uint32_t sync_data_shm_offset) {
7479   helper_->SetDisjointValueSyncCHROMIUM(sync_data_shm_id, sync_data_shm_offset);
7480 }
7481 
GetClientSideGLError()7482 GLenum GLES2Implementation::GetClientSideGLError() {
7483   if (error_bits_ == 0) {
7484     return GL_NO_ERROR;
7485   }
7486 
7487   GLenum error = GL_NO_ERROR;
7488   for (uint32_t mask = 1; mask != 0; mask = mask << 1) {
7489     if ((error_bits_ & mask) != 0) {
7490       error = GLES2Util::GLErrorBitToGLError(mask);
7491       break;
7492     }
7493   }
7494   error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
7495   return error;
7496 }
7497 
cmd_buffer_helper()7498 CommandBufferHelper* GLES2Implementation::cmd_buffer_helper() {
7499   return helper_;
7500 }
7501 
command_buffer() const7502 CommandBuffer* GLES2Implementation::command_buffer() const {
7503   return helper_->command_buffer();
7504 }
7505 
SetActiveURLCHROMIUM(const char * url)7506 void GLES2Implementation::SetActiveURLCHROMIUM(const char* url) {
7507   DCHECK(url);
7508   GPU_CLIENT_SINGLE_THREAD_CHECK();
7509   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSetActiveURLCHROMIUM(" << url);
7510 
7511   if (last_active_url_ == url)
7512     return;
7513 
7514   last_active_url_ = url;
7515   static constexpr uint32_t kMaxStrLen = 1024;
7516   size_t len = strlen(url);
7517   if (len == 0)
7518     return;
7519 
7520   SetBucketContents(kResultBucketId, url,
7521                     base::CheckMin(len, kMaxStrLen).ValueOrDie());
7522   helper_->SetActiveURLCHROMIUM(kResultBucketId);
7523   helper_->SetBucketSize(kResultBucketId, 0);
7524 }
7525 
7526 // Include the auto-generated part of this file. We split this because it means
7527 // we can easily edit the non-auto generated parts right here in this file
7528 // instead of having to edit some template or the code generator.
7529 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
7530 
7531 }  // namespace gles2
7532 }  // namespace gpu
7533