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