1 // Copyright (c) 2016 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 #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/numerics/ranges.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "build/build_config.h"
12 #include "gpu/command_buffer/common/discardable_handle.h"
13 #include "gpu/command_buffer/service/decoder_client.h"
14 #include "gpu/command_buffer/service/gpu_fence_manager.h"
15 #include "gpu/command_buffer/service/gpu_tracer.h"
16 #include "gpu/command_buffer/service/image_factory.h"
17 #include "gpu/command_buffer/service/multi_draw_manager.h"
18 #include "gpu/command_buffer/service/passthrough_discardable_manager.h"
19 #include "gpu/command_buffer/service/shared_image_factory.h"
20 #include "gpu/command_buffer/service/shared_image_representation.h"
21 #include "ui/gfx/geometry/rect_conversions.h"
22 #include "ui/gl/ca_renderer_layer_params.h"
23 #include "ui/gl/dc_renderer_layer_params.h"
24 #include "ui/gl/gl_version_info.h"
25
26 namespace gpu {
27 namespace gles2 {
28
29 // Temporarily allows compilation of shaders that use the
30 // ARB_texture_rectangle/ANGLE_texture_rectangle extension. We don't want to
31 // expose the extension to WebGL user shaders but we still need to use it for
32 // parts of the implementation on macOS. Note that the extension is always
33 // enabled on macOS and this only controls shader compilation.
34 class GLES2DecoderPassthroughImpl::
35 ScopedEnableTextureRectangleInShaderCompiler {
36 public:
37 ScopedEnableTextureRectangleInShaderCompiler(
38 const ScopedEnableTextureRectangleInShaderCompiler&) = delete;
39 ScopedEnableTextureRectangleInShaderCompiler& operator=(
40 const ScopedEnableTextureRectangleInShaderCompiler&) = delete;
41
42 // This class is a no-op except on macOS.
43 #if !defined(OS_MAC)
ScopedEnableTextureRectangleInShaderCompiler(GLES2DecoderPassthroughImpl * decoder)44 explicit ScopedEnableTextureRectangleInShaderCompiler(
45 GLES2DecoderPassthroughImpl* decoder) {}
46
47 private:
48 #else
49 explicit ScopedEnableTextureRectangleInShaderCompiler(
50 GLES2DecoderPassthroughImpl* decoder)
51 : decoder_(decoder) {
52 if (decoder_->feature_info_->IsWebGLContext())
53 decoder_->api_->glEnableFn(GL_TEXTURE_RECTANGLE_ANGLE);
54 }
55 ~ScopedEnableTextureRectangleInShaderCompiler() {
56 if (decoder_->feature_info_->IsWebGLContext())
57 decoder_->api_->glDisableFn(GL_TEXTURE_RECTANGLE_ANGLE);
58 }
59
60 private:
61 GLES2DecoderPassthroughImpl* decoder_;
62 #endif
63 };
64
65 namespace {
66
67 template <typename ClientType, typename ServiceType, typename GenFunction>
GenHelper(GLsizei n,const volatile ClientType * client_ids,ClientServiceMap<ClientType,ServiceType> * id_map,GenFunction gen_function)68 error::Error GenHelper(GLsizei n,
69 const volatile ClientType* client_ids,
70 ClientServiceMap<ClientType, ServiceType>* id_map,
71 GenFunction gen_function) {
72 DCHECK(n >= 0);
73 std::vector<ClientType> client_ids_copy(client_ids, client_ids + n);
74 for (GLsizei ii = 0; ii < n; ++ii) {
75 if (id_map->HasClientID(client_ids_copy[ii])) {
76 return error::kInvalidArguments;
77 }
78 }
79 if (!CheckUniqueAndNonNullIds(n, client_ids_copy.data())) {
80 return error::kInvalidArguments;
81 }
82
83 std::vector<ServiceType> service_ids(n, 0);
84 gen_function(n, service_ids.data());
85 for (GLsizei ii = 0; ii < n; ++ii) {
86 id_map->SetIDMapping(client_ids_copy[ii], service_ids[ii]);
87 }
88
89 return error::kNoError;
90 }
91
92 template <typename ClientType, typename ServiceType, typename GenFunction>
CreateHelper(ClientType client_id,ClientServiceMap<ClientType,ServiceType> * id_map,GenFunction create_function)93 error::Error CreateHelper(ClientType client_id,
94 ClientServiceMap<ClientType, ServiceType>* id_map,
95 GenFunction create_function) {
96 if (id_map->HasClientID(client_id)) {
97 return error::kInvalidArguments;
98 }
99 ServiceType service_id = create_function();
100 id_map->SetIDMapping(client_id, service_id);
101 return error::kNoError;
102 }
103
104 template <typename ClientType, typename ServiceType, typename DeleteFunction>
DeleteHelper(GLsizei n,const volatile ClientType * client_ids,ClientServiceMap<ClientType,ServiceType> * id_map,DeleteFunction delete_function)105 error::Error DeleteHelper(GLsizei n,
106 const volatile ClientType* client_ids,
107 ClientServiceMap<ClientType, ServiceType>* id_map,
108 DeleteFunction delete_function) {
109 DCHECK(n >= 0);
110 std::vector<ServiceType> service_ids(n, 0);
111 for (GLsizei ii = 0; ii < n; ++ii) {
112 ClientType client_id = client_ids[ii];
113
114 // Don't pass service IDs of objects with a client ID of 0. They are
115 // emulated and should not be deleteable
116 if (client_id != 0) {
117 service_ids[ii] = id_map->GetServiceIDOrInvalid(client_id);
118 id_map->RemoveClientID(client_id);
119 }
120 }
121
122 delete_function(n, service_ids.data());
123
124 return error::kNoError;
125 }
126
127 template <typename ClientType, typename ServiceType, typename DeleteFunction>
DeleteHelper(ClientType client_id,ClientServiceMap<ClientType,ServiceType> * id_map,DeleteFunction delete_function)128 error::Error DeleteHelper(ClientType client_id,
129 ClientServiceMap<ClientType, ServiceType>* id_map,
130 DeleteFunction delete_function) {
131 delete_function(id_map->GetServiceIDOrInvalid(client_id));
132 id_map->RemoveClientID(client_id);
133 return error::kNoError;
134 }
135
136 template <typename ClientType, typename ServiceType, typename GenFunction>
137 ServiceType GetServiceID(ClientType client_id,
138 ClientServiceMap<ClientType, ServiceType>* id_map,
139 bool create_if_missing,
140 GenFunction gen_function) {
141 ServiceType service_id = id_map->invalid_service_id();
142 if (id_map->GetServiceID(client_id, &service_id)) {
143 return service_id;
144 }
145
146 if (create_if_missing) {
147 service_id = gen_function();
148 id_map->SetIDMapping(client_id, service_id);
149 return service_id;
150 }
151
152 return id_map->invalid_service_id();
153 }
154
GetTextureServiceID(gl::GLApi * api,GLuint client_id,PassthroughResources * resources,bool create_if_missing)155 GLuint GetTextureServiceID(gl::GLApi* api,
156 GLuint client_id,
157 PassthroughResources* resources,
158 bool create_if_missing) {
159 GLuint service_id = resources->texture_id_map.invalid_service_id();
160 if (resources->texture_id_map.GetServiceID(client_id, &service_id)) {
161 return service_id;
162 }
163
164 if (create_if_missing) {
165 service_id = 0;
166 api->glGenTexturesFn(1, &service_id);
167 resources->texture_id_map.SetIDMapping(client_id, service_id);
168 return service_id;
169 }
170
171 return resources->texture_id_map.invalid_service_id();
172 }
173
GetBufferServiceID(gl::GLApi * api,GLuint client_id,PassthroughResources * resources,bool create_if_missing)174 GLuint GetBufferServiceID(gl::GLApi* api,
175 GLuint client_id,
176 PassthroughResources* resources,
177 bool create_if_missing) {
178 return GetServiceID(client_id, &resources->buffer_id_map, create_if_missing,
179 [api]() {
180 GLuint service_id = 0;
181 api->glGenBuffersARBFn(1, &service_id);
182 return service_id;
183 });
184 }
185
GetRenderbufferServiceID(gl::GLApi * api,GLuint client_id,PassthroughResources * resources,bool create_if_missing)186 GLuint GetRenderbufferServiceID(gl::GLApi* api,
187 GLuint client_id,
188 PassthroughResources* resources,
189 bool create_if_missing) {
190 return GetServiceID(client_id, &resources->renderbuffer_id_map,
191 create_if_missing, [api]() {
192 GLuint service_id = 0;
193 api->glGenRenderbuffersEXTFn(1, &service_id);
194 return service_id;
195 });
196 }
197
GetFramebufferServiceID(gl::GLApi * api,GLuint client_id,ClientServiceMap<GLuint,GLuint> * id_map,bool create_if_missing)198 GLuint GetFramebufferServiceID(gl::GLApi* api,
199 GLuint client_id,
200 ClientServiceMap<GLuint, GLuint>* id_map,
201 bool create_if_missing) {
202 return GetServiceID(client_id, id_map, create_if_missing, [api]() {
203 GLuint service_id = 0;
204 api->glGenFramebuffersEXTFn(1, &service_id);
205 return service_id;
206 });
207 }
208
GetTransformFeedbackServiceID(GLuint client_id,ClientServiceMap<GLuint,GLuint> * id_map)209 GLuint GetTransformFeedbackServiceID(GLuint client_id,
210 ClientServiceMap<GLuint, GLuint>* id_map) {
211 return id_map->GetServiceIDOrInvalid(client_id);
212 }
213
GetVertexArrayServiceID(GLuint client_id,ClientServiceMap<GLuint,GLuint> * id_map)214 GLuint GetVertexArrayServiceID(GLuint client_id,
215 ClientServiceMap<GLuint, GLuint>* id_map) {
216 return id_map->GetServiceIDOrInvalid(client_id);
217 }
218
GetProgramServiceID(GLuint client_id,PassthroughResources * resources)219 GLuint GetProgramServiceID(GLuint client_id, PassthroughResources* resources) {
220 return resources->program_id_map.GetServiceIDOrInvalid(client_id);
221 }
222
GetShaderServiceID(GLuint client_id,PassthroughResources * resources)223 GLuint GetShaderServiceID(GLuint client_id, PassthroughResources* resources) {
224 return resources->shader_id_map.GetServiceIDOrInvalid(client_id);
225 }
226
GetQueryServiceID(GLuint client_id,ClientServiceMap<GLuint,GLuint> * id_map)227 GLuint GetQueryServiceID(GLuint client_id,
228 ClientServiceMap<GLuint, GLuint>* id_map) {
229 return id_map->GetServiceIDOrInvalid(client_id);
230 }
231
GetSamplerServiceID(GLuint client_id,PassthroughResources * resources)232 GLuint GetSamplerServiceID(GLuint client_id, PassthroughResources* resources) {
233 return resources->sampler_id_map.GetServiceIDOrInvalid(client_id);
234 }
235
GetSyncServiceID(GLuint client_id,PassthroughResources * resources)236 GLsync GetSyncServiceID(GLuint client_id, PassthroughResources* resources) {
237 return reinterpret_cast<GLsync>(
238 resources->sync_id_map.GetServiceIDOrInvalid(client_id));
239 }
240
241 template <typename T>
InsertValueIntoBuffer(std::vector<uint8_t> * data,const T & value,size_t offset)242 void InsertValueIntoBuffer(std::vector<uint8_t>* data,
243 const T& value,
244 size_t offset) {
245 DCHECK_LE(offset + sizeof(T), data->size());
246 memcpy(data->data() + offset, &value, sizeof(T));
247 }
248
249 template <typename T>
AppendValueToBuffer(std::vector<uint8_t> * data,const T & value)250 void AppendValueToBuffer(std::vector<uint8_t>* data, const T& value) {
251 const base::CheckedNumeric<size_t> old_size = data->size();
252 data->resize((old_size + sizeof(T)).ValueOrDie());
253 memcpy(data->data() + old_size.ValueOrDie(), &value, sizeof(T));
254 }
255
AppendStringToBuffer(std::vector<uint8_t> * data,const char * str,size_t len)256 void AppendStringToBuffer(std::vector<uint8_t>* data,
257 const char* str,
258 size_t len) {
259 const base::CheckedNumeric<size_t> old_size = data->size();
260 data->resize((old_size + len).ValueOrDie());
261 memcpy(data->data() + old_size.ValueOrDie(), str, len);
262 }
263
AssignGLRectangle(GLint rectangle[4],GLint x,GLint y,GLint width,GLint height)264 void AssignGLRectangle(GLint rectangle[4],
265 GLint x,
266 GLint y,
267 GLint width,
268 GLint height) {
269 rectangle[0] = x;
270 rectangle[1] = y;
271 rectangle[2] = width;
272 rectangle[3] = height;
273 }
274
275 // In order to minimize the amount of data copied, the command buffer client
276 // unpack pixels before sending the glTex[Sub]Image[2|3]D calls. The only
277 // parameter it doesn't handle is the alignment. Resetting the unpack state is
278 // not needed when uploading from a PBO and for compressed formats which the
279 // client sends untouched. This class handles resetting and restoring the unpack
280 // state.
281 // TODO(cwallez@chromium.org) it would be nicer to handle the resetting /
282 // restoring on the client side.
283 class ScopedUnpackStateButAlignmentReset {
284 public:
ScopedUnpackStateButAlignmentReset(gl::GLApi * api,bool enable,bool is_3d)285 ScopedUnpackStateButAlignmentReset(gl::GLApi* api, bool enable, bool is_3d)
286 : api_(api) {
287 if (!enable) {
288 return;
289 }
290
291 api_->glGetIntegervFn(GL_UNPACK_SKIP_PIXELS, &skip_pixels_);
292 api_->glPixelStoreiFn(GL_UNPACK_SKIP_PIXELS, 0);
293 api_->glGetIntegervFn(GL_UNPACK_SKIP_ROWS, &skip_rows_);
294 api_->glPixelStoreiFn(GL_UNPACK_SKIP_ROWS, 0);
295 api_->glGetIntegervFn(GL_UNPACK_ROW_LENGTH, &row_length_);
296 api_->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, 0);
297
298 if (is_3d) {
299 api_->glGetIntegervFn(GL_UNPACK_SKIP_IMAGES, &skip_images_);
300 api_->glPixelStoreiFn(GL_UNPACK_SKIP_IMAGES, 0);
301 api_->glGetIntegervFn(GL_UNPACK_IMAGE_HEIGHT, &image_height_);
302 api_->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, 0);
303 }
304 }
305
~ScopedUnpackStateButAlignmentReset()306 ~ScopedUnpackStateButAlignmentReset() {
307 if (skip_pixels_ != 0) {
308 api_->glPixelStoreiFn(GL_UNPACK_SKIP_PIXELS, skip_pixels_);
309 }
310 if (skip_rows_ != 0) {
311 api_->glPixelStoreiFn(GL_UNPACK_SKIP_ROWS, skip_rows_);
312 }
313 if (skip_images_ != 0) {
314 api_->glPixelStoreiFn(GL_UNPACK_SKIP_IMAGES, skip_images_);
315 }
316 if (row_length_ != 0) {
317 api_->glPixelStoreiFn(GL_UNPACK_ROW_LENGTH, row_length_);
318 }
319 if (image_height_ != 0) {
320 api_->glPixelStoreiFn(GL_UNPACK_IMAGE_HEIGHT, image_height_);
321 }
322 }
323
324 private:
325 gl::GLApi* api_;
326 GLint skip_pixels_ = 0;
327 GLint skip_rows_ = 0;
328 GLint skip_images_ = 0;
329 GLint row_length_ = 0;
330 GLint image_height_ = 0;
331 };
332
333 class ScopedPackStateRowLengthReset {
334 public:
ScopedPackStateRowLengthReset(gl::GLApi * api,bool enable)335 ScopedPackStateRowLengthReset(gl::GLApi* api, bool enable) : api_(api) {
336 if (!enable) {
337 return;
338 }
339
340 api_->glGetIntegervFn(GL_PACK_ROW_LENGTH, &row_length_);
341 api_->glPixelStoreiFn(GL_PACK_ROW_LENGTH, 0);
342 }
343
~ScopedPackStateRowLengthReset()344 ~ScopedPackStateRowLengthReset() {
345 if (row_length_ != 0) {
346 api_->glPixelStoreiFn(GL_PACK_ROW_LENGTH, row_length_);
347 }
348 }
349
350 private:
351 gl::GLApi* api_;
352 GLint row_length_ = 0;
353 };
354
ModifyAttachmentForEmulatedFramebuffer(GLenum * attachment)355 bool ModifyAttachmentForEmulatedFramebuffer(GLenum* attachment) {
356 switch (*attachment) {
357 case GL_BACK:
358 *attachment = GL_COLOR_ATTACHMENT0;
359 return true;
360
361 case GL_DEPTH:
362 *attachment = GL_DEPTH_ATTACHMENT;
363 return true;
364
365 case GL_STENCIL:
366 *attachment = GL_STENCIL_ATTACHMENT;
367 return true;
368
369 default:
370 return false;
371 }
372 }
373
ModifyAttachmentsForEmulatedFramebuffer(std::vector<GLenum> * attachments)374 bool ModifyAttachmentsForEmulatedFramebuffer(std::vector<GLenum>* attachments) {
375 for (GLenum& attachment : *attachments) {
376 if (!ModifyAttachmentForEmulatedFramebuffer(&attachment)) {
377 return false;
378 }
379 }
380
381 return true;
382 }
383
384 } // anonymous namespace
385
386 // Implementations of commands
DoActiveTexture(GLenum texture)387 error::Error GLES2DecoderPassthroughImpl::DoActiveTexture(GLenum texture) {
388 CheckErrorCallbackState();
389 api()->glActiveTextureFn(texture);
390 if (CheckErrorCallbackState()) {
391 return error::kNoError;
392 }
393
394 active_texture_unit_ = static_cast<size_t>(texture) - GL_TEXTURE0;
395 DCHECK(active_texture_unit_ < kMaxTextureUnits);
396
397 return error::kNoError;
398 }
399
DoAttachShader(GLuint program,GLuint shader)400 error::Error GLES2DecoderPassthroughImpl::DoAttachShader(GLuint program,
401 GLuint shader) {
402 api()->glAttachShaderFn(GetProgramServiceID(program, resources_),
403 GetShaderServiceID(shader, resources_));
404 return error::kNoError;
405 }
406
DoBindAttribLocation(GLuint program,GLuint index,const char * name)407 error::Error GLES2DecoderPassthroughImpl::DoBindAttribLocation(
408 GLuint program,
409 GLuint index,
410 const char* name) {
411 api()->glBindAttribLocationFn(GetProgramServiceID(program, resources_), index,
412 name);
413 return error::kNoError;
414 }
415
DoBindBuffer(GLenum target,GLuint buffer)416 error::Error GLES2DecoderPassthroughImpl::DoBindBuffer(GLenum target,
417 GLuint buffer) {
418 CheckErrorCallbackState();
419 api()->glBindBufferFn(target, GetBufferServiceID(api(), buffer, resources_,
420 bind_generates_resource_));
421 if (CheckErrorCallbackState()) {
422 return error::kNoError;
423 }
424
425 DCHECK(bound_buffers_.find(target) != bound_buffers_.end());
426 bound_buffers_[target] = buffer;
427
428 return error::kNoError;
429 }
430
DoBindBufferBase(GLenum target,GLuint index,GLuint buffer)431 error::Error GLES2DecoderPassthroughImpl::DoBindBufferBase(GLenum target,
432 GLuint index,
433 GLuint buffer) {
434 CheckErrorCallbackState();
435 api()->glBindBufferBaseFn(
436 target, index,
437 GetBufferServiceID(api(), buffer, resources_, bind_generates_resource_));
438 if (CheckErrorCallbackState()) {
439 return error::kNoError;
440 }
441
442 DCHECK(bound_buffers_.find(target) != bound_buffers_.end());
443 bound_buffers_[target] = buffer;
444
445 return error::kNoError;
446 }
447
DoBindBufferRange(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)448 error::Error GLES2DecoderPassthroughImpl::DoBindBufferRange(GLenum target,
449 GLuint index,
450 GLuint buffer,
451 GLintptr offset,
452 GLsizeiptr size) {
453 CheckErrorCallbackState();
454 api()->glBindBufferRangeFn(
455 target, index,
456 GetBufferServiceID(api(), buffer, resources_, bind_generates_resource_),
457 offset, size);
458 if (CheckErrorCallbackState()) {
459 return error::kNoError;
460 }
461
462 DCHECK(bound_buffers_.find(target) != bound_buffers_.end());
463 bound_buffers_[target] = buffer;
464
465 return error::kNoError;
466 }
467
DoBindFramebuffer(GLenum target,GLuint framebuffer)468 error::Error GLES2DecoderPassthroughImpl::DoBindFramebuffer(
469 GLenum target,
470 GLuint framebuffer) {
471 CheckErrorCallbackState();
472 api()->glBindFramebufferEXTFn(
473 target, GetFramebufferServiceID(api(), framebuffer, &framebuffer_id_map_,
474 bind_generates_resource_));
475 if (CheckErrorCallbackState()) {
476 return error::kNoError;
477 }
478
479 // Update tracking of the bound framebuffer
480 bool draw_framebuffer_changed = false;
481 switch (target) {
482 case GL_FRAMEBUFFER_EXT:
483 draw_framebuffer_changed = true;
484 bound_draw_framebuffer_ = framebuffer;
485 bound_read_framebuffer_ = framebuffer;
486 break;
487
488 case GL_DRAW_FRAMEBUFFER:
489 draw_framebuffer_changed = true;
490 bound_draw_framebuffer_ = framebuffer;
491 break;
492
493 case GL_READ_FRAMEBUFFER:
494 bound_read_framebuffer_ = framebuffer;
495 break;
496
497 default:
498 NOTREACHED();
499 break;
500 }
501
502 // Resync the surface offset if the draw framebuffer has changed to or from
503 // the default framebuffer
504 if (draw_framebuffer_changed && bound_draw_framebuffer_ != framebuffer &&
505 (bound_draw_framebuffer_ == 0 || framebuffer == 0)) {
506 ApplySurfaceDrawOffset();
507 }
508
509 return error::kNoError;
510 }
511
DoBindImageTexture(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)512 error::Error GLES2DecoderPassthroughImpl::DoBindImageTexture(GLuint unit,
513 GLuint texture,
514 GLint level,
515 GLboolean layered,
516 GLint layer,
517 GLenum access,
518 GLenum format) {
519 api()->glBindImageTextureEXTFn(
520 unit,
521 GetTextureServiceID(api(), texture, resources_, bind_generates_resource_),
522 level, layered, layer, access, format);
523 return error::kNoError;
524 }
525
DoBindRenderbuffer(GLenum target,GLuint renderbuffer)526 error::Error GLES2DecoderPassthroughImpl::DoBindRenderbuffer(
527 GLenum target,
528 GLuint renderbuffer) {
529 api()->glBindRenderbufferEXTFn(
530 target, GetRenderbufferServiceID(api(), renderbuffer, resources_,
531 bind_generates_resource_));
532 return error::kNoError;
533 }
534
DoBindSampler(GLuint unit,GLuint sampler)535 error::Error GLES2DecoderPassthroughImpl::DoBindSampler(GLuint unit,
536 GLuint sampler) {
537 api()->glBindSamplerFn(unit, GetSamplerServiceID(sampler, resources_));
538 return error::kNoError;
539 }
540
DoBindTexture(GLenum target,GLuint texture)541 error::Error GLES2DecoderPassthroughImpl::DoBindTexture(GLenum target,
542 GLuint texture) {
543 GLuint service_id =
544 GetTextureServiceID(api(), texture, resources_, bind_generates_resource_);
545
546 CheckErrorCallbackState();
547
548 api()->glBindTextureFn(target, service_id);
549
550 // Only update tracking if no error was generated in the bind call
551 if (CheckErrorCallbackState()) {
552 return error::kNoError;
553 }
554
555 // Track the currently bound textures
556 DCHECK(GLenumToTextureTarget(target) != TextureTarget::kUnkown);
557 scoped_refptr<TexturePassthrough> texture_passthrough = nullptr;
558
559 // If there was anything bound that required an image bind / copy,
560 // forget it since it's no longer bound to a sampler.
561 RemovePendingBindingTexture(target, active_texture_unit_);
562
563 if (service_id != 0) {
564 // Create a new texture object to track this texture
565 if (!resources_->texture_object_map.GetServiceID(texture,
566 &texture_passthrough) ||
567 texture_passthrough == nullptr) {
568 texture_passthrough = new TexturePassthrough(service_id, target);
569 resources_->texture_object_map.SetIDMapping(texture, texture_passthrough);
570 } else {
571 // Shouldn't be possible to get here if this texture has a different
572 // target than the one it was just bound to
573 DCHECK(texture_passthrough->target() == target);
574 }
575
576 DCHECK(texture_passthrough);
577
578 // If |texture_passthrough| has a bound image that requires processing
579 // before a draw, then keep track of it.
580 if (texture_passthrough->is_bind_pending()) {
581 textures_pending_binding_.emplace_back(target, active_texture_unit_,
582 texture_passthrough->AsWeakPtr());
583 }
584 }
585
586 BoundTexture* bound_texture =
587 &bound_textures_[static_cast<size_t>(GLenumToTextureTarget(target))]
588 [active_texture_unit_];
589 bound_texture->client_id = texture;
590 bound_texture->texture = std::move(texture_passthrough);
591
592 return error::kNoError;
593 }
594
DoBindTransformFeedback(GLenum target,GLuint transformfeedback)595 error::Error GLES2DecoderPassthroughImpl::DoBindTransformFeedback(
596 GLenum target,
597 GLuint transformfeedback) {
598 api()->glBindTransformFeedbackFn(
599 target, GetTransformFeedbackServiceID(transformfeedback,
600 &transform_feedback_id_map_));
601 return error::kNoError;
602 }
603
DoBlendColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)604 error::Error GLES2DecoderPassthroughImpl::DoBlendColor(GLclampf red,
605 GLclampf green,
606 GLclampf blue,
607 GLclampf alpha) {
608 api()->glBlendColorFn(red, green, blue, alpha);
609 return error::kNoError;
610 }
611
DoBlendEquation(GLenum mode)612 error::Error GLES2DecoderPassthroughImpl::DoBlendEquation(GLenum mode) {
613 api()->glBlendEquationFn(mode);
614 return error::kNoError;
615 }
616
DoBlendEquationiOES(GLuint buf,GLenum mode)617 error::Error GLES2DecoderPassthroughImpl::DoBlendEquationiOES(GLuint buf,
618 GLenum mode) {
619 api()->glBlendEquationiOESFn(buf, mode);
620 return error::kNoError;
621 }
622
DoBlendEquationSeparate(GLenum modeRGB,GLenum modeAlpha)623 error::Error GLES2DecoderPassthroughImpl::DoBlendEquationSeparate(
624 GLenum modeRGB,
625 GLenum modeAlpha) {
626 api()->glBlendEquationSeparateFn(modeRGB, modeAlpha);
627 return error::kNoError;
628 }
629
DoBlendEquationSeparateiOES(GLuint buf,GLenum modeRGB,GLenum modeAlpha)630 error::Error GLES2DecoderPassthroughImpl::DoBlendEquationSeparateiOES(
631 GLuint buf,
632 GLenum modeRGB,
633 GLenum modeAlpha) {
634 api()->glBlendEquationSeparateiOESFn(buf, modeRGB, modeAlpha);
635 return error::kNoError;
636 }
637
DoBlendFunc(GLenum sfactor,GLenum dfactor)638 error::Error GLES2DecoderPassthroughImpl::DoBlendFunc(GLenum sfactor,
639 GLenum dfactor) {
640 api()->glBlendFuncFn(sfactor, dfactor);
641 return error::kNoError;
642 }
643
DoBlendFunciOES(GLuint buf,GLenum sfactor,GLenum dfactor)644 error::Error GLES2DecoderPassthroughImpl::DoBlendFunciOES(GLuint buf,
645 GLenum sfactor,
646 GLenum dfactor) {
647 api()->glBlendFunciOESFn(buf, sfactor, dfactor);
648 return error::kNoError;
649 }
650
DoBlendFuncSeparate(GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)651 error::Error GLES2DecoderPassthroughImpl::DoBlendFuncSeparate(GLenum srcRGB,
652 GLenum dstRGB,
653 GLenum srcAlpha,
654 GLenum dstAlpha) {
655 api()->glBlendFuncSeparateFn(srcRGB, dstRGB, srcAlpha, dstAlpha);
656 return error::kNoError;
657 }
658
DoBlendFuncSeparateiOES(GLuint buf,GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)659 error::Error GLES2DecoderPassthroughImpl::DoBlendFuncSeparateiOES(
660 GLuint buf,
661 GLenum srcRGB,
662 GLenum dstRGB,
663 GLenum srcAlpha,
664 GLenum dstAlpha) {
665 api()->glBlendFuncSeparateiOESFn(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
666 return error::kNoError;
667 }
668
DoBufferData(GLenum target,GLsizeiptr size,const void * data,GLenum usage)669 error::Error GLES2DecoderPassthroughImpl::DoBufferData(GLenum target,
670 GLsizeiptr size,
671 const void* data,
672 GLenum usage) {
673 CheckErrorCallbackState();
674 api()->glBufferDataFn(target, size, data, usage);
675 if (CheckErrorCallbackState()) {
676 return error::kNoError;
677 }
678
679 // Calling buffer data on a mapped buffer will implicitly unmap it
680 resources_->mapped_buffer_map.erase(bound_buffers_[target]);
681
682 return error::kNoError;
683 }
684
DoBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const void * data)685 error::Error GLES2DecoderPassthroughImpl::DoBufferSubData(GLenum target,
686 GLintptr offset,
687 GLsizeiptr size,
688 const void* data) {
689 api()->glBufferSubDataFn(target, offset, size, data);
690 return error::kNoError;
691 }
692
DoCheckFramebufferStatus(GLenum target,uint32_t * result)693 error::Error GLES2DecoderPassthroughImpl::DoCheckFramebufferStatus(
694 GLenum target,
695 uint32_t* result) {
696 *result = api()->glCheckFramebufferStatusEXTFn(target);
697 return error::kNoError;
698 }
699
DoClear(GLbitfield mask)700 error::Error GLES2DecoderPassthroughImpl::DoClear(GLbitfield mask) {
701 api()->glClearFn(mask);
702 return error::kNoError;
703 }
704
DoClearBufferfi(GLenum buffer,GLint drawbuffers,GLfloat depth,GLint stencil)705 error::Error GLES2DecoderPassthroughImpl::DoClearBufferfi(GLenum buffer,
706 GLint drawbuffers,
707 GLfloat depth,
708 GLint stencil) {
709 api()->glClearBufferfiFn(buffer, drawbuffers, depth, stencil);
710 return error::kNoError;
711 }
712
DoClearBufferfv(GLenum buffer,GLint drawbuffers,const volatile GLfloat * value)713 error::Error GLES2DecoderPassthroughImpl::DoClearBufferfv(
714 GLenum buffer,
715 GLint drawbuffers,
716 const volatile GLfloat* value) {
717 api()->glClearBufferfvFn(buffer, drawbuffers,
718 const_cast<const GLfloat*>(value));
719 return error::kNoError;
720 }
721
DoClearBufferiv(GLenum buffer,GLint drawbuffers,const volatile GLint * value)722 error::Error GLES2DecoderPassthroughImpl::DoClearBufferiv(
723 GLenum buffer,
724 GLint drawbuffers,
725 const volatile GLint* value) {
726 api()->glClearBufferivFn(buffer, drawbuffers,
727 const_cast<const GLint*>(value));
728 return error::kNoError;
729 }
730
DoClearBufferuiv(GLenum buffer,GLint drawbuffers,const volatile GLuint * value)731 error::Error GLES2DecoderPassthroughImpl::DoClearBufferuiv(
732 GLenum buffer,
733 GLint drawbuffers,
734 const volatile GLuint* value) {
735 api()->glClearBufferuivFn(buffer, drawbuffers,
736 const_cast<const GLuint*>(value));
737 return error::kNoError;
738 }
739
DoClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)740 error::Error GLES2DecoderPassthroughImpl::DoClearColor(GLclampf red,
741 GLclampf green,
742 GLclampf blue,
743 GLclampf alpha) {
744 api()->glClearColorFn(red, green, blue, alpha);
745 return error::kNoError;
746 }
747
DoClearDepthf(GLclampf depth)748 error::Error GLES2DecoderPassthroughImpl::DoClearDepthf(GLclampf depth) {
749 api()->glClearDepthfFn(depth);
750 return error::kNoError;
751 }
752
DoClearStencil(GLint s)753 error::Error GLES2DecoderPassthroughImpl::DoClearStencil(GLint s) {
754 api()->glClearStencilFn(s);
755 return error::kNoError;
756 }
757
DoClientWaitSync(GLuint sync,GLbitfield flags,GLuint64 timeout,GLenum * result)758 error::Error GLES2DecoderPassthroughImpl::DoClientWaitSync(GLuint sync,
759 GLbitfield flags,
760 GLuint64 timeout,
761 GLenum* result) {
762 // Force GL_SYNC_FLUSH_COMMANDS_BIT to avoid infinite wait.
763 GLbitfield modified_flags = flags | GL_SYNC_FLUSH_COMMANDS_BIT;
764 *result = api()->glClientWaitSyncFn(GetSyncServiceID(sync, resources_),
765 modified_flags, timeout);
766 return error::kNoError;
767 }
768
DoColorMask(GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)769 error::Error GLES2DecoderPassthroughImpl::DoColorMask(GLboolean red,
770 GLboolean green,
771 GLboolean blue,
772 GLboolean alpha) {
773 api()->glColorMaskFn(red, green, blue, alpha);
774 return error::kNoError;
775 }
776
DoColorMaskiOES(GLuint buf,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)777 error::Error GLES2DecoderPassthroughImpl::DoColorMaskiOES(GLuint buf,
778 GLboolean red,
779 GLboolean green,
780 GLboolean blue,
781 GLboolean alpha) {
782 api()->glColorMaskiOESFn(buf, red, green, blue, alpha);
783 return error::kNoError;
784 }
785
DoCompileShader(GLuint shader)786 error::Error GLES2DecoderPassthroughImpl::DoCompileShader(GLuint shader) {
787 api()->glCompileShaderFn(GetShaderServiceID(shader, resources_));
788 return error::kNoError;
789 }
790
DoCompressedTexImage2D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei image_size,GLsizei data_size,const void * data)791 error::Error GLES2DecoderPassthroughImpl::DoCompressedTexImage2D(
792 GLenum target,
793 GLint level,
794 GLenum internalformat,
795 GLsizei width,
796 GLsizei height,
797 GLint border,
798 GLsizei image_size,
799 GLsizei data_size,
800 const void* data) {
801 CheckErrorCallbackState();
802 api()->glCompressedTexImage2DRobustANGLEFn(target, level, internalformat,
803 width, height, border, image_size,
804 data_size, data);
805 if (CheckErrorCallbackState()) {
806 return error::kNoError;
807 }
808
809 UpdateTextureSizeFromTarget(target);
810
811 // Texture data upload can be slow. Exit command processing to allow for
812 // context preemption and GPU watchdog checks.
813 ExitCommandProcessingEarly();
814
815 return error::kNoError;
816 }
817
DoCompressedTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei image_size,GLsizei data_size,const void * data)818 error::Error GLES2DecoderPassthroughImpl::DoCompressedTexSubImage2D(
819 GLenum target,
820 GLint level,
821 GLint xoffset,
822 GLint yoffset,
823 GLsizei width,
824 GLsizei height,
825 GLenum format,
826 GLsizei image_size,
827 GLsizei data_size,
828 const void* data) {
829 api()->glCompressedTexSubImage2DRobustANGLEFn(target, level, xoffset, yoffset,
830 width, height, format,
831 image_size, data_size, data);
832
833 // Texture data upload can be slow. Exit command processing to allow for
834 // context preemption and GPU watchdog checks.
835 ExitCommandProcessingEarly();
836
837 return error::kNoError;
838 }
839
DoCompressedTexImage3D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei image_size,GLsizei data_size,const void * data)840 error::Error GLES2DecoderPassthroughImpl::DoCompressedTexImage3D(
841 GLenum target,
842 GLint level,
843 GLenum internalformat,
844 GLsizei width,
845 GLsizei height,
846 GLsizei depth,
847 GLint border,
848 GLsizei image_size,
849 GLsizei data_size,
850 const void* data) {
851 CheckErrorCallbackState();
852 api()->glCompressedTexImage3DRobustANGLEFn(target, level, internalformat,
853 width, height, depth, border,
854 image_size, data_size, data);
855 if (CheckErrorCallbackState()) {
856 return error::kNoError;
857 }
858
859 UpdateTextureSizeFromTarget(target);
860
861 // Texture data upload can be slow. Exit command processing to allow for
862 // context preemption and GPU watchdog checks.
863 ExitCommandProcessingEarly();
864
865 return error::kNoError;
866 }
867
DoCompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei image_size,GLsizei data_size,const void * data)868 error::Error GLES2DecoderPassthroughImpl::DoCompressedTexSubImage3D(
869 GLenum target,
870 GLint level,
871 GLint xoffset,
872 GLint yoffset,
873 GLint zoffset,
874 GLsizei width,
875 GLsizei height,
876 GLsizei depth,
877 GLenum format,
878 GLsizei image_size,
879 GLsizei data_size,
880 const void* data) {
881 api()->glCompressedTexSubImage3DRobustANGLEFn(
882 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
883 image_size, data_size, data);
884
885 // Texture data upload can be slow. Exit command processing to allow for
886 // context preemption and GPU watchdog checks.
887 ExitCommandProcessingEarly();
888
889 return error::kNoError;
890 }
891
DoContextVisibilityHintCHROMIUM(GLboolean visibility)892 error::Error GLES2DecoderPassthroughImpl::DoContextVisibilityHintCHROMIUM(
893 GLboolean visibility) {
894 if (feature_info_->IsWebGLContext())
895 context_->SetVisibility(visibility == GL_TRUE);
896 return error::kNoError;
897 }
898
DoCopyBufferSubData(GLenum readtarget,GLenum writetarget,GLintptr readoffset,GLintptr writeoffset,GLsizeiptr size)899 error::Error GLES2DecoderPassthroughImpl::DoCopyBufferSubData(
900 GLenum readtarget,
901 GLenum writetarget,
902 GLintptr readoffset,
903 GLintptr writeoffset,
904 GLsizeiptr size) {
905 api()->glCopyBufferSubDataFn(readtarget, writetarget, readoffset, writeoffset,
906 size);
907 return error::kNoError;
908 }
909
DoCopyTexImage2D(GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)910 error::Error GLES2DecoderPassthroughImpl::DoCopyTexImage2D(
911 GLenum target,
912 GLint level,
913 GLenum internalformat,
914 GLint x,
915 GLint y,
916 GLsizei width,
917 GLsizei height,
918 GLint border) {
919 CheckErrorCallbackState();
920 api()->glCopyTexImage2DFn(target, level, internalformat, x, y, width, height,
921 border);
922 if (CheckErrorCallbackState()) {
923 return error::kNoError;
924 }
925
926 UpdateTextureSizeFromTarget(target);
927
928 // Texture data copying can be slow. Exit command processing to allow for
929 // context preemption and GPU watchdog checks.
930 ExitCommandProcessingEarly();
931
932 return error::kNoError;
933 }
934
DoCopyTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)935 error::Error GLES2DecoderPassthroughImpl::DoCopyTexSubImage2D(GLenum target,
936 GLint level,
937 GLint xoffset,
938 GLint yoffset,
939 GLint x,
940 GLint y,
941 GLsizei width,
942 GLsizei height) {
943 api()->glCopyTexSubImage2DFn(target, level, xoffset, yoffset, x, y, width,
944 height);
945
946 // Texture data copying can be slow. Exit command processing to allow for
947 // context preemption and GPU watchdog checks.
948 ExitCommandProcessingEarly();
949
950 return error::kNoError;
951 }
952
DoCopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)953 error::Error GLES2DecoderPassthroughImpl::DoCopyTexSubImage3D(GLenum target,
954 GLint level,
955 GLint xoffset,
956 GLint yoffset,
957 GLint zoffset,
958 GLint x,
959 GLint y,
960 GLsizei width,
961 GLsizei height) {
962 api()->glCopyTexSubImage3DFn(target, level, xoffset, yoffset, zoffset, x, y,
963 width, height);
964
965 // Texture data copying can be slow. Exit command processing to allow for
966 // context preemption and GPU watchdog checks.
967 ExitCommandProcessingEarly();
968
969 return error::kNoError;
970 }
971
DoCreateProgram(GLuint client_id)972 error::Error GLES2DecoderPassthroughImpl::DoCreateProgram(GLuint client_id) {
973 return CreateHelper(client_id, &resources_->program_id_map,
974 [this]() { return api()->glCreateProgramFn(); });
975 }
976
DoCreateShader(GLenum type,GLuint client_id)977 error::Error GLES2DecoderPassthroughImpl::DoCreateShader(GLenum type,
978 GLuint client_id) {
979 return CreateHelper(client_id, &resources_->shader_id_map,
980 [this, type]() { return api()->glCreateShaderFn(type); });
981 }
982
DoCullFace(GLenum mode)983 error::Error GLES2DecoderPassthroughImpl::DoCullFace(GLenum mode) {
984 api()->glCullFaceFn(mode);
985 return error::kNoError;
986 }
987
DoDeleteBuffers(GLsizei n,const volatile GLuint * buffers)988 error::Error GLES2DecoderPassthroughImpl::DoDeleteBuffers(
989 GLsizei n,
990 const volatile GLuint* buffers) {
991 // DeleteHelper requires that n is non-negative because it allocates a copy of
992 // the IDs
993 if (n < 0) {
994 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
995 return error::kNoError;
996 }
997
998 std::vector<GLuint> service_ids(n, 0);
999 for (GLsizei ii = 0; ii < n; ++ii) {
1000 GLuint client_id = buffers[ii];
1001
1002 // Update the bound and mapped buffer state tracking
1003 for (auto& buffer_binding : bound_buffers_) {
1004 if (buffer_binding.second == client_id) {
1005 buffer_binding.second = 0;
1006 }
1007 resources_->mapped_buffer_map.erase(client_id);
1008 }
1009
1010 service_ids[ii] =
1011 resources_->buffer_id_map.GetServiceIDOrInvalid(client_id);
1012 resources_->buffer_id_map.RemoveClientID(client_id);
1013
1014 auto is_the_deleted_buffer = [client_id](const auto& update) {
1015 return update.first == client_id;
1016 };
1017 base::EraseIf(buffer_shadow_updates_, is_the_deleted_buffer);
1018 for (PendingQuery& pending_query : pending_queries_) {
1019 base::EraseIf(pending_query.buffer_shadow_updates, is_the_deleted_buffer);
1020 }
1021 }
1022 api()->glDeleteBuffersARBFn(n, service_ids.data());
1023
1024 return error::kNoError;
1025 }
1026
DoDeleteFramebuffers(GLsizei n,const volatile GLuint * framebuffers)1027 error::Error GLES2DecoderPassthroughImpl::DoDeleteFramebuffers(
1028 GLsizei n,
1029 const volatile GLuint* framebuffers) {
1030 // DeleteHelper requires that n is non-negative because it allocates a copy of
1031 // the IDs
1032 if (n < 0) {
1033 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
1034 return error::kNoError;
1035 }
1036
1037 std::vector<GLuint> framebuffers_copy(framebuffers, framebuffers + n);
1038
1039 // If a bound framebuffer is deleted, it's binding is reset to 0. In the case
1040 // of an emulated default framebuffer, bind the emulated one.
1041 for (GLuint framebuffer : framebuffers_copy) {
1042 if (framebuffer == bound_draw_framebuffer_) {
1043 bound_draw_framebuffer_ = 0;
1044 if (emulated_back_buffer_) {
1045 api()->glBindFramebufferEXTFn(
1046 GL_DRAW_FRAMEBUFFER, emulated_back_buffer_->framebuffer_service_id);
1047 }
1048
1049 // Update the surface offset if the bound draw framebuffer is deleted
1050 ApplySurfaceDrawOffset();
1051 }
1052 if (framebuffer == bound_read_framebuffer_) {
1053 bound_read_framebuffer_ = 0;
1054 if (emulated_back_buffer_) {
1055 api()->glBindFramebufferEXTFn(
1056 GL_READ_FRAMEBUFFER, emulated_back_buffer_->framebuffer_service_id);
1057 }
1058 }
1059 }
1060
1061 return DeleteHelper(n, framebuffers_copy.data(), &framebuffer_id_map_,
1062 [this](GLsizei n, GLuint* framebuffers) {
1063 api()->glDeleteFramebuffersEXTFn(n, framebuffers);
1064 });
1065 }
1066
DoDeleteProgram(GLuint program)1067 error::Error GLES2DecoderPassthroughImpl::DoDeleteProgram(GLuint program) {
1068 return DeleteHelper(
1069 program, &resources_->program_id_map,
1070 [this](GLuint program) { api()->glDeleteProgramFn(program); });
1071 }
1072
DoDeleteRenderbuffers(GLsizei n,const volatile GLuint * renderbuffers)1073 error::Error GLES2DecoderPassthroughImpl::DoDeleteRenderbuffers(
1074 GLsizei n,
1075 const volatile GLuint* renderbuffers) {
1076 // DeleteHelper requires that n is non-negative because it allocates a copy of
1077 // the IDs
1078 if (n < 0) {
1079 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
1080 return error::kNoError;
1081 }
1082 return DeleteHelper(n, renderbuffers, &resources_->renderbuffer_id_map,
1083 [this](GLsizei n, GLuint* renderbuffers) {
1084 api()->glDeleteRenderbuffersEXTFn(n, renderbuffers);
1085 });
1086 }
1087
DoDeleteSamplers(GLsizei n,const volatile GLuint * samplers)1088 error::Error GLES2DecoderPassthroughImpl::DoDeleteSamplers(
1089 GLsizei n,
1090 const volatile GLuint* samplers) {
1091 // DeleteHelper requires that n is non-negative because it allocates a copy of
1092 // the IDs
1093 if (n < 0) {
1094 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
1095 return error::kNoError;
1096 }
1097 return DeleteHelper(n, samplers, &resources_->sampler_id_map,
1098 [this](GLsizei n, GLuint* samplers) {
1099 api()->glDeleteSamplersFn(n, samplers);
1100 });
1101 }
1102
DoDeleteSync(GLuint sync)1103 error::Error GLES2DecoderPassthroughImpl::DoDeleteSync(GLuint sync) {
1104 return DeleteHelper(sync, &resources_->sync_id_map, [this](uintptr_t sync) {
1105 api()->glDeleteSyncFn(reinterpret_cast<GLsync>(sync));
1106 });
1107 }
1108
DoDeleteShader(GLuint shader)1109 error::Error GLES2DecoderPassthroughImpl::DoDeleteShader(GLuint shader) {
1110 return DeleteHelper(
1111 shader, &resources_->shader_id_map,
1112 [this](GLuint shader) { api()->glDeleteShaderFn(shader); });
1113 }
1114
DoDeleteTextures(GLsizei n,const volatile GLuint * textures)1115 error::Error GLES2DecoderPassthroughImpl::DoDeleteTextures(
1116 GLsizei n,
1117 const volatile GLuint* textures) {
1118 // DeleteHelper requires that n is non-negative because it allocates a copy of
1119 // the IDs
1120 if (n < 0) {
1121 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
1122 return error::kNoError;
1123 }
1124
1125 // Textures that are currently associated with a mailbox are stored in the
1126 // texture_object_map_ and are deleted automatically when they are
1127 // unreferenced. Only delete textures that are not in this map.
1128 std::vector<GLuint> non_mailbox_client_ids;
1129 for (GLsizei ii = 0; ii < n; ++ii) {
1130 GLuint client_id = textures[ii];
1131 scoped_refptr<TexturePassthrough> texture = nullptr;
1132 if (!resources_->texture_object_map.GetServiceID(client_id, &texture) ||
1133 texture == nullptr) {
1134 // Delete with DeleteHelper
1135 non_mailbox_client_ids.push_back(client_id);
1136 } else {
1137 // Deleted when unreferenced
1138 resources_->texture_id_map.RemoveClientID(client_id);
1139 resources_->texture_object_map.RemoveClientID(client_id);
1140 resources_->texture_shared_image_map.erase(client_id);
1141 UpdateTextureBinding(texture->target(), client_id, nullptr);
1142 }
1143
1144 // Notify the discardable manager that the texture is deleted
1145 group_->passthrough_discardable_manager()->DeleteTexture(client_id,
1146 group_.get());
1147 }
1148 return DeleteHelper(
1149 non_mailbox_client_ids.size(), non_mailbox_client_ids.data(),
1150 &resources_->texture_id_map, [this](GLsizei n, GLuint* textures) {
1151 api()->glDeleteTexturesFn(n, textures);
1152 });
1153 }
1154
DoDeleteTransformFeedbacks(GLsizei n,const volatile GLuint * ids)1155 error::Error GLES2DecoderPassthroughImpl::DoDeleteTransformFeedbacks(
1156 GLsizei n,
1157 const volatile GLuint* ids) {
1158 // DeleteHelper requires that n is non-negative because it allocates a copy of
1159 // the IDs
1160 if (n < 0) {
1161 InsertError(GL_INVALID_VALUE, "n cannot be negative.");
1162 return error::kNoError;
1163 }
1164 return DeleteHelper(n, ids, &transform_feedback_id_map_,
1165 [this](GLsizei n, GLuint* transform_feedbacks) {
1166 api()->glDeleteTransformFeedbacksFn(
1167 n, transform_feedbacks);
1168 });
1169 }
1170
DoDepthFunc(GLenum func)1171 error::Error GLES2DecoderPassthroughImpl::DoDepthFunc(GLenum func) {
1172 api()->glDepthFuncFn(func);
1173 return error::kNoError;
1174 }
1175
DoDepthMask(GLboolean flag)1176 error::Error GLES2DecoderPassthroughImpl::DoDepthMask(GLboolean flag) {
1177 api()->glDepthMaskFn(flag);
1178 return error::kNoError;
1179 }
1180
DoDepthRangef(GLclampf zNear,GLclampf zFar)1181 error::Error GLES2DecoderPassthroughImpl::DoDepthRangef(GLclampf zNear,
1182 GLclampf zFar) {
1183 api()->glDepthRangefFn(zNear, zFar);
1184 return error::kNoError;
1185 }
1186
DoDetachShader(GLuint program,GLuint shader)1187 error::Error GLES2DecoderPassthroughImpl::DoDetachShader(GLuint program,
1188 GLuint shader) {
1189 api()->glDetachShaderFn(GetProgramServiceID(program, resources_),
1190 GetShaderServiceID(shader, resources_));
1191 return error::kNoError;
1192 }
1193
DoDisable(GLenum cap)1194 error::Error GLES2DecoderPassthroughImpl::DoDisable(GLenum cap) {
1195 api()->glDisableFn(cap);
1196 return error::kNoError;
1197 }
1198
DoDisableVertexAttribArray(GLuint index)1199 error::Error GLES2DecoderPassthroughImpl::DoDisableVertexAttribArray(
1200 GLuint index) {
1201 api()->glDisableVertexAttribArrayFn(index);
1202 return error::kNoError;
1203 }
1204
DoDispatchCompute(GLuint num_groups_x,GLuint num_groups_y,GLuint num_groups_z)1205 error::Error GLES2DecoderPassthroughImpl::DoDispatchCompute(
1206 GLuint num_groups_x,
1207 GLuint num_groups_y,
1208 GLuint num_groups_z) {
1209 BindPendingImagesForSamplersIfNeeded();
1210 api()->glDispatchComputeFn(num_groups_x, num_groups_y, num_groups_z);
1211 return error::kNoError;
1212 }
1213
DoDispatchComputeIndirect(GLintptr offset)1214 error::Error GLES2DecoderPassthroughImpl::DoDispatchComputeIndirect(
1215 GLintptr offset) {
1216 BindPendingImagesForSamplersIfNeeded();
1217 // TODO(jiajie.hu@intel.com): Use glDispatchComputeIndirectRobustANGLEFn()
1218 // when it's ready in ANGLE.
1219 api()->glDispatchComputeIndirectFn(offset);
1220 return error::kNoError;
1221 }
1222
DoDrawArrays(GLenum mode,GLint first,GLsizei count)1223 error::Error GLES2DecoderPassthroughImpl::DoDrawArrays(GLenum mode,
1224 GLint first,
1225 GLsizei count) {
1226 BindPendingImagesForSamplersIfNeeded();
1227 api()->glDrawArraysFn(mode, first, count);
1228 return error::kNoError;
1229 }
1230
DoDrawArraysIndirect(GLenum mode,const void * offset)1231 error::Error GLES2DecoderPassthroughImpl::DoDrawArraysIndirect(
1232 GLenum mode,
1233 const void* offset) {
1234 BindPendingImagesForSamplersIfNeeded();
1235 // TODO(jiajie.hu@intel.com): Use glDrawArraysIndirectRobustANGLEFn() when
1236 // it's ready in ANGLE.
1237 api()->glDrawArraysIndirectFn(mode, offset);
1238 return error::kNoError;
1239 }
1240
DoDrawElements(GLenum mode,GLsizei count,GLenum type,const void * indices)1241 error::Error GLES2DecoderPassthroughImpl::DoDrawElements(GLenum mode,
1242 GLsizei count,
1243 GLenum type,
1244 const void* indices) {
1245 BindPendingImagesForSamplersIfNeeded();
1246 api()->glDrawElementsFn(mode, count, type, indices);
1247 return error::kNoError;
1248 }
1249
DoDrawElementsIndirect(GLenum mode,GLenum type,const void * offset)1250 error::Error GLES2DecoderPassthroughImpl::DoDrawElementsIndirect(
1251 GLenum mode,
1252 GLenum type,
1253 const void* offset) {
1254 BindPendingImagesForSamplersIfNeeded();
1255 // TODO(jiajie.hu@intel.com): Use glDrawElementsIndirectRobustANGLEFn() when
1256 // it's ready in ANGLE.
1257 api()->glDrawElementsIndirectFn(mode, type, offset);
1258 return error::kNoError;
1259 }
1260
DoEnable(GLenum cap)1261 error::Error GLES2DecoderPassthroughImpl::DoEnable(GLenum cap) {
1262 api()->glEnableFn(cap);
1263 return error::kNoError;
1264 }
1265
DoEnableVertexAttribArray(GLuint index)1266 error::Error GLES2DecoderPassthroughImpl::DoEnableVertexAttribArray(
1267 GLuint index) {
1268 api()->glEnableVertexAttribArrayFn(index);
1269 return error::kNoError;
1270 }
1271
DoFenceSync(GLenum condition,GLbitfield flags,GLuint client_id)1272 error::Error GLES2DecoderPassthroughImpl::DoFenceSync(GLenum condition,
1273 GLbitfield flags,
1274 GLuint client_id) {
1275 if (resources_->sync_id_map.HasClientID(client_id)) {
1276 return error::kInvalidArguments;
1277 }
1278
1279 CheckErrorCallbackState();
1280 GLsync service_id = api()->glFenceSyncFn(condition, flags);
1281 if (CheckErrorCallbackState()) {
1282 return error::kNoError;
1283 }
1284
1285 resources_->sync_id_map.SetIDMapping(client_id,
1286 reinterpret_cast<uintptr_t>(service_id));
1287
1288 return error::kNoError;
1289 }
1290
DoFinish()1291 error::Error GLES2DecoderPassthroughImpl::DoFinish() {
1292 // Finish can take a long time, make sure the watchdog gives it the most
1293 // amount of time to complete.
1294 group_->ReportProgress();
1295
1296 api()->glFinishFn();
1297
1298 group_->ReportProgress();
1299
1300 error::Error error = ProcessReadPixels(true);
1301 if (error != error::kNoError) {
1302 return error;
1303 }
1304 return ProcessQueries(true);
1305 }
1306
DoFlush()1307 error::Error GLES2DecoderPassthroughImpl::DoFlush() {
1308 api()->glFlushFn();
1309
1310 error::Error error = ProcessReadPixels(false);
1311 if (error != error::kNoError) {
1312 return error;
1313 }
1314 return ProcessQueries(false);
1315 }
1316
DoFlushMappedBufferRange(GLenum target,GLintptr offset,GLsizeiptr size)1317 error::Error GLES2DecoderPassthroughImpl::DoFlushMappedBufferRange(
1318 GLenum target,
1319 GLintptr offset,
1320 GLsizeiptr size) {
1321 auto bound_buffers_iter = bound_buffers_.find(target);
1322 if (bound_buffers_iter == bound_buffers_.end() ||
1323 bound_buffers_iter->second == 0) {
1324 InsertError(GL_INVALID_OPERATION, "No buffer bound to this target.");
1325 return error::kNoError;
1326 }
1327
1328 GLuint client_buffer = bound_buffers_iter->second;
1329 auto mapped_buffer_info_iter =
1330 resources_->mapped_buffer_map.find(client_buffer);
1331 if (mapped_buffer_info_iter == resources_->mapped_buffer_map.end()) {
1332 InsertError(GL_INVALID_OPERATION, "Buffer is not mapped.");
1333 return error::kNoError;
1334 }
1335
1336 const MappedBuffer& map_info = mapped_buffer_info_iter->second;
1337
1338 if (offset < 0) {
1339 InsertError(GL_INVALID_VALUE, "Offset cannot be negative.");
1340 return error::kNoError;
1341 }
1342
1343 if (size < 0) {
1344 InsertError(GL_INVALID_VALUE, "Size cannot be negative.");
1345 return error::kNoError;
1346 }
1347
1348 base::CheckedNumeric<size_t> range_start(offset);
1349 base::CheckedNumeric<size_t> range_end = offset + size;
1350 if (!range_end.IsValid() || range_end.ValueOrDefault(0) > map_info.size) {
1351 InsertError(GL_INVALID_OPERATION,
1352 "Flush range is not within the original mapping size.");
1353 return error::kNoError;
1354 }
1355
1356 uint8_t* mem = GetSharedMemoryAs<uint8_t*>(
1357 map_info.data_shm_id, map_info.data_shm_offset, map_info.size);
1358 if (!mem) {
1359 return error::kOutOfBounds;
1360 }
1361
1362 memcpy(map_info.map_ptr + offset, mem + offset, size);
1363 api()->glFlushMappedBufferRangeFn(target, offset, size);
1364
1365 return error::kNoError;
1366 }
1367
DoFramebufferParameteri(GLenum target,GLenum pname,GLint param)1368 error::Error GLES2DecoderPassthroughImpl::DoFramebufferParameteri(GLenum target,
1369 GLenum pname,
1370 GLint param) {
1371 api()->glFramebufferParameteriFn(target, pname, param);
1372 return error::kNoError;
1373 }
1374
DoFramebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)1375 error::Error GLES2DecoderPassthroughImpl::DoFramebufferRenderbuffer(
1376 GLenum target,
1377 GLenum attachment,
1378 GLenum renderbuffertarget,
1379 GLuint renderbuffer) {
1380 if (IsEmulatedFramebufferBound(target)) {
1381 InsertError(GL_INVALID_OPERATION,
1382 "Cannot change the attachments of the default framebuffer.");
1383 return error::kNoError;
1384 }
1385 api()->glFramebufferRenderbufferEXTFn(
1386 target, attachment, renderbuffertarget,
1387 GetRenderbufferServiceID(api(), renderbuffer, resources_, false));
1388 return error::kNoError;
1389 }
1390
DoFramebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)1391 error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2D(
1392 GLenum target,
1393 GLenum attachment,
1394 GLenum textarget,
1395 GLuint texture,
1396 GLint level) {
1397 if (IsEmulatedFramebufferBound(target)) {
1398 InsertError(GL_INVALID_OPERATION,
1399 "Cannot change the attachments of the default framebuffer.");
1400 return error::kNoError;
1401 }
1402 BindPendingImageForClientIDIfNeeded(texture);
1403 api()->glFramebufferTexture2DEXTFn(
1404 target, attachment, textarget,
1405 GetTextureServiceID(api(), texture, resources_, false), level);
1406 return error::kNoError;
1407 }
1408
DoFramebufferTextureLayer(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)1409 error::Error GLES2DecoderPassthroughImpl::DoFramebufferTextureLayer(
1410 GLenum target,
1411 GLenum attachment,
1412 GLuint texture,
1413 GLint level,
1414 GLint layer) {
1415 if (IsEmulatedFramebufferBound(target)) {
1416 InsertError(GL_INVALID_OPERATION,
1417 "Cannot change the attachments of the default framebuffer.");
1418 return error::kNoError;
1419 }
1420 api()->glFramebufferTextureLayerFn(
1421 target, attachment,
1422 GetTextureServiceID(api(), texture, resources_, false), level, layer);
1423 return error::kNoError;
1424 }
1425
DoFramebufferTextureMultiviewOVR(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint base_view_index,GLsizei num_views)1426 error::Error GLES2DecoderPassthroughImpl::DoFramebufferTextureMultiviewOVR(
1427 GLenum target,
1428 GLenum attachment,
1429 GLuint texture,
1430 GLint level,
1431 GLint base_view_index,
1432 GLsizei num_views) {
1433 if (IsEmulatedFramebufferBound(target)) {
1434 InsertError(GL_INVALID_OPERATION,
1435 "Cannot change the attachments of the default framebuffer.");
1436 return error::kNoError;
1437 }
1438 api()->glFramebufferTextureMultiviewOVRFn(
1439 target, attachment,
1440 GetTextureServiceID(api(), texture, resources_, false), level,
1441 base_view_index, num_views);
1442 return error::kNoError;
1443 }
1444
DoFrontFace(GLenum mode)1445 error::Error GLES2DecoderPassthroughImpl::DoFrontFace(GLenum mode) {
1446 api()->glFrontFaceFn(mode);
1447 return error::kNoError;
1448 }
1449
DoGenBuffers(GLsizei n,volatile GLuint * buffers)1450 error::Error GLES2DecoderPassthroughImpl::DoGenBuffers(
1451 GLsizei n,
1452 volatile GLuint* buffers) {
1453 return GenHelper(n, buffers, &resources_->buffer_id_map,
1454 [this](GLsizei n, GLuint* buffers) {
1455 api()->glGenBuffersARBFn(n, buffers);
1456 });
1457 }
1458
DoGenerateMipmap(GLenum target)1459 error::Error GLES2DecoderPassthroughImpl::DoGenerateMipmap(GLenum target) {
1460 api()->glGenerateMipmapEXTFn(target);
1461 return error::kNoError;
1462 }
1463
DoGenFramebuffers(GLsizei n,volatile GLuint * framebuffers)1464 error::Error GLES2DecoderPassthroughImpl::DoGenFramebuffers(
1465 GLsizei n,
1466 volatile GLuint* framebuffers) {
1467 return GenHelper(n, framebuffers, &framebuffer_id_map_,
1468 [this](GLsizei n, GLuint* framebuffers) {
1469 api()->glGenFramebuffersEXTFn(n, framebuffers);
1470 });
1471 }
1472
DoGenRenderbuffers(GLsizei n,volatile GLuint * renderbuffers)1473 error::Error GLES2DecoderPassthroughImpl::DoGenRenderbuffers(
1474 GLsizei n,
1475 volatile GLuint* renderbuffers) {
1476 return GenHelper(n, renderbuffers, &resources_->renderbuffer_id_map,
1477 [this](GLsizei n, GLuint* renderbuffers) {
1478 api()->glGenRenderbuffersEXTFn(n, renderbuffers);
1479 });
1480 }
1481
DoGenSamplers(GLsizei n,volatile GLuint * samplers)1482 error::Error GLES2DecoderPassthroughImpl::DoGenSamplers(
1483 GLsizei n,
1484 volatile GLuint* samplers) {
1485 return GenHelper(n, samplers, &resources_->sampler_id_map,
1486 [this](GLsizei n, GLuint* samplers) {
1487 api()->glGenSamplersFn(n, samplers);
1488 });
1489 }
1490
DoGenTextures(GLsizei n,volatile GLuint * textures)1491 error::Error GLES2DecoderPassthroughImpl::DoGenTextures(
1492 GLsizei n,
1493 volatile GLuint* textures) {
1494 return GenHelper(n, textures, &resources_->texture_id_map,
1495 [this](GLsizei n, GLuint* textures) {
1496 api()->glGenTexturesFn(n, textures);
1497 });
1498 }
1499
DoGenTransformFeedbacks(GLsizei n,volatile GLuint * ids)1500 error::Error GLES2DecoderPassthroughImpl::DoGenTransformFeedbacks(
1501 GLsizei n,
1502 volatile GLuint* ids) {
1503 return GenHelper(n, ids, &transform_feedback_id_map_,
1504 [this](GLsizei n, GLuint* transform_feedbacks) {
1505 api()->glGenTransformFeedbacksFn(n, transform_feedbacks);
1506 });
1507 }
1508
DoGetActiveAttrib(GLuint program,GLuint index,GLint * size,GLenum * type,std::string * name,int32_t * success)1509 error::Error GLES2DecoderPassthroughImpl::DoGetActiveAttrib(GLuint program,
1510 GLuint index,
1511 GLint* size,
1512 GLenum* type,
1513 std::string* name,
1514 int32_t* success) {
1515 CheckErrorCallbackState();
1516
1517 GLuint service_id = GetProgramServiceID(program, resources_);
1518 GLint active_attribute_max_length = 0;
1519 api()->glGetProgramivFn(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
1520 &active_attribute_max_length);
1521 if (CheckErrorCallbackState()) {
1522 *success = 0;
1523 return error::kNoError;
1524 }
1525
1526 std::vector<char> name_buffer(active_attribute_max_length, 0);
1527 GLsizei length = 0;
1528 api()->glGetActiveAttribFn(service_id, index, name_buffer.size(), &length,
1529 size, type, name_buffer.data());
1530 DCHECK(length <= active_attribute_max_length);
1531 *name = length > 0 ? std::string(name_buffer.data(), length) : std::string();
1532 *success = CheckErrorCallbackState() ? 0 : 1;
1533 return error::kNoError;
1534 }
1535
DoGetActiveUniform(GLuint program,GLuint index,GLint * size,GLenum * type,std::string * name,int32_t * success)1536 error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniform(GLuint program,
1537 GLuint index,
1538 GLint* size,
1539 GLenum* type,
1540 std::string* name,
1541 int32_t* success) {
1542 CheckErrorCallbackState();
1543
1544 GLuint service_id = GetProgramServiceID(program, resources_);
1545 GLint active_uniform_max_length = 0;
1546 api()->glGetProgramivFn(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH,
1547 &active_uniform_max_length);
1548 if (CheckErrorCallbackState()) {
1549 *success = 0;
1550 return error::kNoError;
1551 }
1552
1553 std::vector<char> name_buffer(active_uniform_max_length, 0);
1554 GLsizei length = 0;
1555 api()->glGetActiveUniformFn(service_id, index, name_buffer.size(), &length,
1556 size, type, name_buffer.data());
1557 DCHECK(length <= active_uniform_max_length);
1558 *name = length > 0 ? std::string(name_buffer.data(), length) : std::string();
1559 *success = CheckErrorCallbackState() ? 0 : 1;
1560 return error::kNoError;
1561 }
1562
DoGetActiveUniformBlockiv(GLuint program,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)1563 error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformBlockiv(
1564 GLuint program,
1565 GLuint index,
1566 GLenum pname,
1567 GLsizei bufSize,
1568 GLsizei* length,
1569 GLint* params) {
1570 api()->glGetActiveUniformBlockivRobustANGLEFn(
1571 GetProgramServiceID(program, resources_), index, pname, bufSize, length,
1572 params);
1573 return error::kNoError;
1574 }
1575
DoGetActiveUniformBlockName(GLuint program,GLuint index,std::string * name)1576 error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformBlockName(
1577 GLuint program,
1578 GLuint index,
1579 std::string* name) {
1580 CheckErrorCallbackState();
1581
1582 GLuint program_service_id = GetProgramServiceID(program, resources_);
1583 GLint max_name_length = 0;
1584 api()->glGetProgramivFn(program_service_id,
1585 GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
1586 &max_name_length);
1587
1588 if (CheckErrorCallbackState()) {
1589 return error::kNoError;
1590 }
1591
1592 std::vector<GLchar> buffer(max_name_length, 0);
1593 GLsizei length = 0;
1594 api()->glGetActiveUniformBlockNameFn(program_service_id, index,
1595 max_name_length, &length, buffer.data());
1596 DCHECK(length <= max_name_length);
1597 *name = length > 0 ? std::string(buffer.data(), length) : std::string();
1598
1599 return error::kNoError;
1600 }
1601
DoGetActiveUniformsiv(GLuint program,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)1602 error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniformsiv(
1603 GLuint program,
1604 GLsizei count,
1605 const GLuint* indices,
1606 GLenum pname,
1607 GLint* params) {
1608 api()->glGetActiveUniformsivFn(GetProgramServiceID(program, resources_),
1609 count, indices, pname, params);
1610 return error::kNoError;
1611 }
1612
DoGetAttachedShaders(GLuint program,GLsizei maxcount,GLsizei * count,GLuint * shaders)1613 error::Error GLES2DecoderPassthroughImpl::DoGetAttachedShaders(
1614 GLuint program,
1615 GLsizei maxcount,
1616 GLsizei* count,
1617 GLuint* shaders) {
1618 api()->glGetAttachedShadersFn(GetProgramServiceID(program, resources_),
1619 maxcount, count, shaders);
1620 return error::kNoError;
1621 }
1622
DoGetAttribLocation(GLuint program,const char * name,GLint * result)1623 error::Error GLES2DecoderPassthroughImpl::DoGetAttribLocation(GLuint program,
1624 const char* name,
1625 GLint* result) {
1626 *result = api()->glGetAttribLocationFn(
1627 GetProgramServiceID(program, resources_), name);
1628 return error::kNoError;
1629 }
1630
DoGetBooleanv(GLenum pname,GLsizei bufsize,GLsizei * length,GLboolean * params)1631 error::Error GLES2DecoderPassthroughImpl::DoGetBooleanv(GLenum pname,
1632 GLsizei bufsize,
1633 GLsizei* length,
1634 GLboolean* params) {
1635 return GetNumericHelper(pname, bufsize, length, params,
1636 [this](GLenum pname, GLsizei bufsize, GLsizei* length,
1637 GLboolean* params) {
1638 api()->glGetBooleanvRobustANGLEFn(pname, bufsize,
1639 length, params);
1640 });
1641 }
1642
DoGetBooleani_v(GLenum pname,GLuint index,GLsizei bufsize,GLsizei * length,GLboolean * data)1643 error::Error GLES2DecoderPassthroughImpl::DoGetBooleani_v(GLenum pname,
1644 GLuint index,
1645 GLsizei bufsize,
1646 GLsizei* length,
1647 GLboolean* data) {
1648 glGetBooleani_vRobustANGLE(pname, index, bufsize, length, data);
1649 return error::kNoError;
1650 }
1651
DoGetBufferParameteri64v(GLenum target,GLenum pname,GLsizei bufsize,GLsizei * length,GLint64 * params)1652 error::Error GLES2DecoderPassthroughImpl::DoGetBufferParameteri64v(
1653 GLenum target,
1654 GLenum pname,
1655 GLsizei bufsize,
1656 GLsizei* length,
1657 GLint64* params) {
1658 CheckErrorCallbackState();
1659 api()->glGetBufferParameteri64vRobustANGLEFn(target, pname, bufsize, length,
1660 params);
1661 if (CheckErrorCallbackState()) {
1662 return error::kNoError;
1663 }
1664 PatchGetBufferResults(target, pname, bufsize, length, params);
1665 return error::kNoError;
1666 }
1667
DoGetBufferParameteriv(GLenum target,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1668 error::Error GLES2DecoderPassthroughImpl::DoGetBufferParameteriv(
1669 GLenum target,
1670 GLenum pname,
1671 GLsizei bufsize,
1672 GLsizei* length,
1673 GLint* params) {
1674 CheckErrorCallbackState();
1675 api()->glGetBufferParameterivRobustANGLEFn(target, pname, bufsize, length,
1676 params);
1677 if (CheckErrorCallbackState()) {
1678 return error::kNoError;
1679 }
1680 PatchGetBufferResults(target, pname, bufsize, length, params);
1681 return error::kNoError;
1682 }
1683
DoGetError(uint32_t * result)1684 error::Error GLES2DecoderPassthroughImpl::DoGetError(uint32_t* result) {
1685 FlushErrors();
1686 *result = PopError();
1687 return error::kNoError;
1688 }
1689
DoGetFloatv(GLenum pname,GLsizei bufsize,GLsizei * length,GLfloat * params)1690 error::Error GLES2DecoderPassthroughImpl::DoGetFloatv(GLenum pname,
1691 GLsizei bufsize,
1692 GLsizei* length,
1693 GLfloat* params) {
1694 return GetNumericHelper(
1695 pname, bufsize, length, params,
1696 [this](GLenum pname, GLsizei bufsize, GLsizei* length, GLfloat* params) {
1697 api()->glGetFloatvRobustANGLEFn(pname, bufsize, length, params);
1698 });
1699 }
1700
DoGetFragDataLocation(GLuint program,const char * name,GLint * result)1701 error::Error GLES2DecoderPassthroughImpl::DoGetFragDataLocation(
1702 GLuint program,
1703 const char* name,
1704 GLint* result) {
1705 *result = api()->glGetFragDataLocationFn(
1706 GetProgramServiceID(program, resources_), name);
1707 return error::kNoError;
1708 }
1709
DoGetFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1710 error::Error GLES2DecoderPassthroughImpl::DoGetFramebufferAttachmentParameteriv(
1711 GLenum target,
1712 GLenum attachment,
1713 GLenum pname,
1714 GLsizei bufsize,
1715 GLsizei* length,
1716 GLint* params) {
1717 GLenum updated_attachment = attachment;
1718 if (IsEmulatedFramebufferBound(target)) {
1719 // Update the attachment do the equivalent one in the emulated framebuffer
1720 if (!ModifyAttachmentForEmulatedFramebuffer(&updated_attachment)) {
1721 InsertError(GL_INVALID_OPERATION, "Invalid attachment.");
1722 *length = 0;
1723 return error::kNoError;
1724 }
1725
1726 // Generate errors for parameter names that are only valid for non-default
1727 // framebuffers
1728 switch (pname) {
1729 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
1730 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
1731 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
1732 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
1733 InsertError(GL_INVALID_ENUM, "Invalid parameter name.");
1734 *length = 0;
1735 return error::kNoError;
1736 }
1737 }
1738
1739 CheckErrorCallbackState();
1740
1741 api()->glGetFramebufferAttachmentParameterivRobustANGLEFn(
1742 target, updated_attachment, pname, bufsize, length, params);
1743
1744 if (CheckErrorCallbackState()) {
1745 DCHECK(*length == 0);
1746 return error::kNoError;
1747 }
1748
1749 // Update the results of the query, if needed
1750 const error::Error error = PatchGetFramebufferAttachmentParameter(
1751 target, updated_attachment, pname, *length, params);
1752 if (error != error::kNoError) {
1753 *length = 0;
1754 return error;
1755 }
1756
1757 return error::kNoError;
1758 }
1759
DoGetInteger64v(GLenum pname,GLsizei bufsize,GLsizei * length,GLint64 * params)1760 error::Error GLES2DecoderPassthroughImpl::DoGetInteger64v(GLenum pname,
1761 GLsizei bufsize,
1762 GLsizei* length,
1763 GLint64* params) {
1764 return GetNumericHelper(
1765 pname, bufsize, length, params,
1766 [this](GLenum pname, GLsizei bufsize, GLsizei* length, GLint64* params) {
1767 api()->glGetInteger64vRobustANGLEFn(pname, bufsize, length, params);
1768 });
1769 }
1770
DoGetIntegeri_v(GLenum pname,GLuint index,GLsizei bufsize,GLsizei * length,GLint * data)1771 error::Error GLES2DecoderPassthroughImpl::DoGetIntegeri_v(GLenum pname,
1772 GLuint index,
1773 GLsizei bufsize,
1774 GLsizei* length,
1775 GLint* data) {
1776 glGetIntegeri_vRobustANGLE(pname, index, bufsize, length, data);
1777 return error::kNoError;
1778 }
1779
DoGetInteger64i_v(GLenum pname,GLuint index,GLsizei bufsize,GLsizei * length,GLint64 * data)1780 error::Error GLES2DecoderPassthroughImpl::DoGetInteger64i_v(GLenum pname,
1781 GLuint index,
1782 GLsizei bufsize,
1783 GLsizei* length,
1784 GLint64* data) {
1785 glGetInteger64i_vRobustANGLE(pname, index, bufsize, length, data);
1786 return error::kNoError;
1787 }
1788
DoGetIntegerv(GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1789 error::Error GLES2DecoderPassthroughImpl::DoGetIntegerv(GLenum pname,
1790 GLsizei bufsize,
1791 GLsizei* length,
1792 GLint* params) {
1793 return GetNumericHelper(
1794 pname, bufsize, length, params,
1795 [this](GLenum pname, GLsizei bufsize, GLsizei* length, GLint* params) {
1796 api()->glGetIntegervRobustANGLEFn(pname, bufsize, length, params);
1797 });
1798 }
1799
DoGetInternalformativ(GLenum target,GLenum format,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)1800 error::Error GLES2DecoderPassthroughImpl::DoGetInternalformativ(GLenum target,
1801 GLenum format,
1802 GLenum pname,
1803 GLsizei bufSize,
1804 GLsizei* length,
1805 GLint* params) {
1806 api()->glGetInternalformativRobustANGLEFn(target, format, pname, bufSize,
1807 length, params);
1808 return error::kNoError;
1809 }
1810
DoGetProgramiv(GLuint program,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1811 error::Error GLES2DecoderPassthroughImpl::DoGetProgramiv(GLuint program,
1812 GLenum pname,
1813 GLsizei bufsize,
1814 GLsizei* length,
1815 GLint* params) {
1816 api()->glGetProgramivRobustANGLEFn(GetProgramServiceID(program, resources_),
1817 pname, bufsize, length, params);
1818 return error::kNoError;
1819 }
1820
DoGetProgramInfoLog(GLuint program,std::string * infolog)1821 error::Error GLES2DecoderPassthroughImpl::DoGetProgramInfoLog(
1822 GLuint program,
1823 std::string* infolog) {
1824 CheckErrorCallbackState();
1825 GLint info_log_len = 0;
1826 api()->glGetProgramivFn(GetProgramServiceID(program, resources_),
1827 GL_INFO_LOG_LENGTH, &info_log_len);
1828
1829 if (CheckErrorCallbackState()) {
1830 return error::kNoError;
1831 }
1832
1833 std::vector<char> buffer(info_log_len, 0);
1834 GLsizei length = 0;
1835 api()->glGetProgramInfoLogFn(GetProgramServiceID(program, resources_),
1836 info_log_len, &length, buffer.data());
1837 DCHECK(length <= info_log_len);
1838 *infolog = length > 0 ? std::string(buffer.data(), length) : std::string();
1839 return error::kNoError;
1840 }
1841
DoGetProgramInterfaceiv(GLuint program,GLenum program_interface,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1842 error::Error GLES2DecoderPassthroughImpl::DoGetProgramInterfaceiv(
1843 GLuint program,
1844 GLenum program_interface,
1845 GLenum pname,
1846 GLsizei bufsize,
1847 GLsizei* length,
1848 GLint* params) {
1849 // glGetProgramInterfaceivRobustANGLE remains to be implemented in ANGLE.
1850 if (bufsize < 1) {
1851 return error::kOutOfBounds;
1852 }
1853 *length = 1;
1854 api()->glGetProgramInterfaceivFn(GetProgramServiceID(program, resources_),
1855 program_interface, pname, params);
1856 return error::kNoError;
1857 }
1858
DoGetProgramResourceiv(GLuint program,GLenum program_interface,GLuint index,GLsizei prop_count,const GLenum * props,GLsizei bufsize,GLsizei * length,GLint * params)1859 error::Error GLES2DecoderPassthroughImpl::DoGetProgramResourceiv(
1860 GLuint program,
1861 GLenum program_interface,
1862 GLuint index,
1863 GLsizei prop_count,
1864 const GLenum* props,
1865 GLsizei bufsize,
1866 GLsizei* length,
1867 GLint* params) {
1868 api()->glGetProgramResourceivFn(GetProgramServiceID(program, resources_),
1869 program_interface, index, prop_count, props,
1870 bufsize, length, params);
1871 return error::kNoError;
1872 }
1873
DoGetProgramResourceIndex(GLuint program,GLenum program_interface,const char * name,GLuint * index)1874 error::Error GLES2DecoderPassthroughImpl::DoGetProgramResourceIndex(
1875 GLuint program,
1876 GLenum program_interface,
1877 const char* name,
1878 GLuint* index) {
1879 *index = api()->glGetProgramResourceIndexFn(
1880 GetProgramServiceID(program, resources_), program_interface, name);
1881 return error::kNoError;
1882 }
1883
DoGetProgramResourceLocation(GLuint program,GLenum program_interface,const char * name,GLint * location)1884 error::Error GLES2DecoderPassthroughImpl::DoGetProgramResourceLocation(
1885 GLuint program,
1886 GLenum program_interface,
1887 const char* name,
1888 GLint* location) {
1889 *location = api()->glGetProgramResourceLocationFn(
1890 GetProgramServiceID(program, resources_), program_interface, name);
1891 return error::kNoError;
1892 }
1893
DoGetProgramResourceName(GLuint program,GLenum program_interface,GLuint index,std::string * name)1894 error::Error GLES2DecoderPassthroughImpl::DoGetProgramResourceName(
1895 GLuint program,
1896 GLenum program_interface,
1897 GLuint index,
1898 std::string* name) {
1899 CheckErrorCallbackState();
1900
1901 GLuint service_id = GetProgramServiceID(program, resources_);
1902 GLint max_name_length = 0;
1903 api()->glGetProgramInterfaceivFn(service_id, program_interface,
1904 GL_MAX_NAME_LENGTH, &max_name_length);
1905 if (CheckErrorCallbackState()) {
1906 return error::kNoError;
1907 }
1908
1909 std::vector<GLchar> buffer(max_name_length, 0);
1910 GLsizei length = 0;
1911 api()->glGetProgramResourceNameFn(service_id, program_interface, index,
1912 max_name_length, &length, buffer.data());
1913 DCHECK_LE(length, max_name_length);
1914 *name = length > 0 ? std::string(buffer.data(), length) : std::string();
1915 return error::kNoError;
1916 }
1917
DoGetRenderbufferParameteriv(GLenum target,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1918 error::Error GLES2DecoderPassthroughImpl::DoGetRenderbufferParameteriv(
1919 GLenum target,
1920 GLenum pname,
1921 GLsizei bufsize,
1922 GLsizei* length,
1923 GLint* params) {
1924 api()->glGetRenderbufferParameterivRobustANGLEFn(target, pname, bufsize,
1925 length, params);
1926 return error::kNoError;
1927 }
1928
DoGetSamplerParameterfv(GLuint sampler,GLenum pname,GLsizei bufsize,GLsizei * length,GLfloat * params)1929 error::Error GLES2DecoderPassthroughImpl::DoGetSamplerParameterfv(
1930 GLuint sampler,
1931 GLenum pname,
1932 GLsizei bufsize,
1933 GLsizei* length,
1934 GLfloat* params) {
1935 api()->glGetSamplerParameterfvRobustANGLEFn(
1936 GetSamplerServiceID(sampler, resources_), pname, bufsize, length, params);
1937 return error::kNoError;
1938 }
1939
DoGetSamplerParameteriv(GLuint sampler,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1940 error::Error GLES2DecoderPassthroughImpl::DoGetSamplerParameteriv(
1941 GLuint sampler,
1942 GLenum pname,
1943 GLsizei bufsize,
1944 GLsizei* length,
1945 GLint* params) {
1946 api()->glGetSamplerParameterivRobustANGLEFn(
1947 GetSamplerServiceID(sampler, resources_), pname, bufsize, length, params);
1948 return error::kNoError;
1949 }
1950
DoGetShaderiv(GLuint shader,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)1951 error::Error GLES2DecoderPassthroughImpl::DoGetShaderiv(GLuint shader,
1952 GLenum pname,
1953 GLsizei bufsize,
1954 GLsizei* length,
1955 GLint* params) {
1956 api()->glGetShaderivRobustANGLEFn(GetShaderServiceID(shader, resources_),
1957 pname, bufsize, length, params);
1958 return error::kNoError;
1959 }
1960
DoGetShaderInfoLog(GLuint shader,std::string * infolog)1961 error::Error GLES2DecoderPassthroughImpl::DoGetShaderInfoLog(
1962 GLuint shader,
1963 std::string* infolog) {
1964 CheckErrorCallbackState();
1965
1966 GLuint service_id = GetShaderServiceID(shader, resources_);
1967 GLint info_log_len = 0;
1968 api()->glGetShaderivFn(service_id, GL_INFO_LOG_LENGTH, &info_log_len);
1969 if (CheckErrorCallbackState()) {
1970 return error::kNoError;
1971 }
1972
1973 std::vector<char> buffer(info_log_len, 0);
1974 GLsizei length = 0;
1975 api()->glGetShaderInfoLogFn(service_id, info_log_len, &length, buffer.data());
1976 DCHECK(length <= info_log_len);
1977 *infolog = length > 0 ? std::string(buffer.data(), length) : std::string();
1978 return error::kNoError;
1979 }
1980
DoGetShaderPrecisionFormat(GLenum shadertype,GLenum precisiontype,GLint * range,GLint * precision,int32_t * success)1981 error::Error GLES2DecoderPassthroughImpl::DoGetShaderPrecisionFormat(
1982 GLenum shadertype,
1983 GLenum precisiontype,
1984 GLint* range,
1985 GLint* precision,
1986 int32_t* success) {
1987 CheckErrorCallbackState();
1988 api()->glGetShaderPrecisionFormatFn(shadertype, precisiontype, range,
1989 precision);
1990 *success = CheckErrorCallbackState() ? 0 : 1;
1991 return error::kNoError;
1992 }
1993
DoGetShaderSource(GLuint shader,std::string * source)1994 error::Error GLES2DecoderPassthroughImpl::DoGetShaderSource(
1995 GLuint shader,
1996 std::string* source) {
1997 CheckErrorCallbackState();
1998
1999 GLuint shader_service_id = GetShaderServiceID(shader, resources_);
2000 GLint shader_source_length = 0;
2001 api()->glGetShaderivFn(shader_service_id, GL_SHADER_SOURCE_LENGTH,
2002 &shader_source_length);
2003 if (CheckErrorCallbackState()) {
2004 return error::kNoError;
2005 }
2006
2007 std::vector<char> buffer(shader_source_length, 0);
2008 GLsizei length = 0;
2009 api()->glGetShaderSourceFn(shader_service_id, shader_source_length, &length,
2010 buffer.data());
2011 DCHECK(length <= shader_source_length);
2012 *source = shader_source_length > 0 ? std::string(buffer.data(), length)
2013 : std::string();
2014 return error::kNoError;
2015 }
2016
DoGetString(GLenum name,uint32_t bucket_id)2017 error::Error GLES2DecoderPassthroughImpl::DoGetString(GLenum name,
2018 uint32_t bucket_id) {
2019 std::string extensions;
2020 const char* str = nullptr;
2021
2022 switch (name) {
2023 case GL_VERSION:
2024 str = GetServiceVersionString(feature_info_.get());
2025 break;
2026 case GL_SHADING_LANGUAGE_VERSION:
2027 str = GetServiceShadingLanguageVersionString(feature_info_.get());
2028 break;
2029 case GL_EXTENSIONS: {
2030 extensions = gfx::MakeExtensionString(feature_info_->extensions());
2031 str = extensions.c_str();
2032 break;
2033 }
2034 default:
2035 str = reinterpret_cast<const char*>(api()->glGetStringFn(name));
2036 break;
2037 }
2038
2039 Bucket* bucket = CreateBucket(bucket_id);
2040 bucket->SetFromString(str);
2041 return error::kNoError;
2042 }
2043
DoGetSynciv(GLuint sync,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * values)2044 error::Error GLES2DecoderPassthroughImpl::DoGetSynciv(GLuint sync,
2045 GLenum pname,
2046 GLsizei bufsize,
2047 GLsizei* length,
2048 GLint* values) {
2049 api()->glGetSyncivFn(GetSyncServiceID(sync, resources_), pname, bufsize,
2050 length, values);
2051 return error::kNoError;
2052 }
2053
DoGetTexParameterfv(GLenum target,GLenum pname,GLsizei bufsize,GLsizei * length,GLfloat * params)2054 error::Error GLES2DecoderPassthroughImpl::DoGetTexParameterfv(GLenum target,
2055 GLenum pname,
2056 GLsizei bufsize,
2057 GLsizei* length,
2058 GLfloat* params) {
2059 api()->glGetTexParameterfvRobustANGLEFn(target, pname, bufsize, length,
2060 params);
2061 return error::kNoError;
2062 }
2063
DoGetTexParameteriv(GLenum target,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)2064 error::Error GLES2DecoderPassthroughImpl::DoGetTexParameteriv(GLenum target,
2065 GLenum pname,
2066 GLsizei bufsize,
2067 GLsizei* length,
2068 GLint* params) {
2069 api()->glGetTexParameterivRobustANGLEFn(target, pname, bufsize, length,
2070 params);
2071 return error::kNoError;
2072 }
2073
DoGetTransformFeedbackVarying(GLuint program,GLuint index,GLsizei * size,GLenum * type,std::string * name,int32_t * success)2074 error::Error GLES2DecoderPassthroughImpl::DoGetTransformFeedbackVarying(
2075 GLuint program,
2076 GLuint index,
2077 GLsizei* size,
2078 GLenum* type,
2079 std::string* name,
2080 int32_t* success) {
2081 CheckErrorCallbackState();
2082
2083 GLuint service_id = GetProgramServiceID(program, resources_);
2084 GLint transform_feedback_varying_max_length = 0;
2085 api()->glGetProgramivFn(service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
2086 &transform_feedback_varying_max_length);
2087 if (CheckErrorCallbackState()) {
2088 *success = 0;
2089 return error::kNoError;
2090 }
2091
2092 std::vector<char> name_buffer(transform_feedback_varying_max_length, 0);
2093 GLsizei length = 0;
2094 api()->glGetTransformFeedbackVaryingFn(service_id, index, name_buffer.size(),
2095 &length, size, type,
2096 name_buffer.data());
2097 DCHECK(length <= transform_feedback_varying_max_length);
2098 *name = length > 0 ? std::string(name_buffer.data(), length) : std::string();
2099 *success = CheckErrorCallbackState() ? 0 : 1;
2100 return error::kNoError;
2101 }
2102
DoGetUniformBlockIndex(GLuint program,const char * name,GLint * index)2103 error::Error GLES2DecoderPassthroughImpl::DoGetUniformBlockIndex(
2104 GLuint program,
2105 const char* name,
2106 GLint* index) {
2107 *index = api()->glGetUniformBlockIndexFn(
2108 GetProgramServiceID(program, resources_), name);
2109 return error::kNoError;
2110 }
2111
DoGetUniformfv(GLuint program,GLint location,GLsizei bufsize,GLsizei * length,GLfloat * params)2112 error::Error GLES2DecoderPassthroughImpl::DoGetUniformfv(GLuint program,
2113 GLint location,
2114 GLsizei bufsize,
2115 GLsizei* length,
2116 GLfloat* params) {
2117 // GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
2118 // points in GL_EXT_robustness
2119 api()->glGetUniformfvRobustANGLEFn(GetProgramServiceID(program, resources_),
2120 location, bufsize * sizeof(*params),
2121 length, params);
2122 return error::kNoError;
2123 }
2124
DoGetUniformiv(GLuint program,GLint location,GLsizei bufsize,GLsizei * length,GLint * params)2125 error::Error GLES2DecoderPassthroughImpl::DoGetUniformiv(GLuint program,
2126 GLint location,
2127 GLsizei bufsize,
2128 GLsizei* length,
2129 GLint* params) {
2130 // GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
2131 // points in GL_EXT_robustness
2132 api()->glGetUniformivRobustANGLEFn(GetProgramServiceID(program, resources_),
2133 location, bufsize * sizeof(*params),
2134 length, params);
2135 return error::kNoError;
2136 }
2137
DoGetUniformuiv(GLuint program,GLint location,GLsizei bufsize,GLsizei * length,GLuint * params)2138 error::Error GLES2DecoderPassthroughImpl::DoGetUniformuiv(GLuint program,
2139 GLint location,
2140 GLsizei bufsize,
2141 GLsizei* length,
2142 GLuint* params) {
2143 // GetUniform*RobustANGLE entry points expect bufsize in bytes like the entry
2144 // points in GL_EXT_robustness
2145 api()->glGetUniformuivRobustANGLEFn(GetProgramServiceID(program, resources_),
2146 location, bufsize * sizeof(*params),
2147 length, params);
2148 return error::kNoError;
2149 }
2150
DoGetUniformIndices(GLuint program,GLsizei count,const char * const * names,GLsizei bufSize,GLuint * indices)2151 error::Error GLES2DecoderPassthroughImpl::DoGetUniformIndices(
2152 GLuint program,
2153 GLsizei count,
2154 const char* const* names,
2155 GLsizei bufSize,
2156 GLuint* indices) {
2157 api()->glGetUniformIndicesFn(GetProgramServiceID(program, resources_), count,
2158 names, indices);
2159 return error::kNoError;
2160 }
2161
DoGetUniformLocation(GLuint program,const char * name,GLint * location)2162 error::Error GLES2DecoderPassthroughImpl::DoGetUniformLocation(
2163 GLuint program,
2164 const char* name,
2165 GLint* location) {
2166 *location = api()->glGetUniformLocationFn(
2167 GetProgramServiceID(program, resources_), name);
2168 return error::kNoError;
2169 }
2170
DoGetVertexAttribfv(GLuint index,GLenum pname,GLsizei bufsize,GLsizei * length,GLfloat * params)2171 error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribfv(GLuint index,
2172 GLenum pname,
2173 GLsizei bufsize,
2174 GLsizei* length,
2175 GLfloat* params) {
2176 api()->glGetVertexAttribfvRobustANGLEFn(index, pname, bufsize, length,
2177 params);
2178 return error::kNoError;
2179 }
2180
DoGetVertexAttribiv(GLuint index,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)2181 error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribiv(GLuint index,
2182 GLenum pname,
2183 GLsizei bufsize,
2184 GLsizei* length,
2185 GLint* params) {
2186 api()->glGetVertexAttribivRobustANGLEFn(index, pname, bufsize, length,
2187 params);
2188 return error::kNoError;
2189 }
2190
DoGetVertexAttribIiv(GLuint index,GLenum pname,GLsizei bufsize,GLsizei * length,GLint * params)2191 error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribIiv(GLuint index,
2192 GLenum pname,
2193 GLsizei bufsize,
2194 GLsizei* length,
2195 GLint* params) {
2196 api()->glGetVertexAttribIivRobustANGLEFn(index, pname, bufsize, length,
2197 params);
2198 return error::kNoError;
2199 }
2200
DoGetVertexAttribIuiv(GLuint index,GLenum pname,GLsizei bufsize,GLsizei * length,GLuint * params)2201 error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribIuiv(
2202 GLuint index,
2203 GLenum pname,
2204 GLsizei bufsize,
2205 GLsizei* length,
2206 GLuint* params) {
2207 api()->glGetVertexAttribIuivRobustANGLEFn(index, pname, bufsize, length,
2208 params);
2209 return error::kNoError;
2210 }
2211
DoGetVertexAttribPointerv(GLuint index,GLenum pname,GLsizei bufsize,GLsizei * length,GLuint * pointer)2212 error::Error GLES2DecoderPassthroughImpl::DoGetVertexAttribPointerv(
2213 GLuint index,
2214 GLenum pname,
2215 GLsizei bufsize,
2216 GLsizei* length,
2217 GLuint* pointer) {
2218 std::array<void*, 1> temp_pointers{{nullptr}};
2219 GLsizei temp_length = 0;
2220 api()->glGetVertexAttribPointervRobustANGLEFn(
2221 index, pname, static_cast<GLsizei>(temp_pointers.size()), &temp_length,
2222 temp_pointers.data());
2223 DCHECK(temp_length >= 0 &&
2224 temp_length <= static_cast<GLsizei>(temp_pointers.size()) &&
2225 temp_length <= bufsize);
2226 for (GLsizei ii = 0; ii < temp_length; ii++) {
2227 pointer[ii] =
2228 static_cast<GLuint>(reinterpret_cast<uintptr_t>(temp_pointers[ii]));
2229 }
2230 *length = temp_length;
2231 return error::kNoError;
2232 }
2233
DoHint(GLenum target,GLenum mode)2234 error::Error GLES2DecoderPassthroughImpl::DoHint(GLenum target, GLenum mode) {
2235 api()->glHintFn(target, mode);
2236 return error::kNoError;
2237 }
2238
DoInvalidateFramebuffer(GLenum target,GLsizei count,const volatile GLenum * attachments)2239 error::Error GLES2DecoderPassthroughImpl::DoInvalidateFramebuffer(
2240 GLenum target,
2241 GLsizei count,
2242 const volatile GLenum* attachments) {
2243 // Validate that count is non-negative before allocating a vector
2244 if (count < 0) {
2245 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
2246 return error::kNoError;
2247 }
2248
2249 std::vector<GLenum> attachments_copy(attachments, attachments + count);
2250 if (IsEmulatedFramebufferBound(target)) {
2251 // Update the attachment do the equivalent one in the emulated framebuffer
2252 if (!ModifyAttachmentsForEmulatedFramebuffer(&attachments_copy)) {
2253 InsertError(GL_INVALID_OPERATION, "Invalid attachment.");
2254 return error::kNoError;
2255 }
2256 }
2257 api()->glInvalidateFramebufferFn(target, count, attachments_copy.data());
2258 return error::kNoError;
2259 }
2260
DoInvalidateSubFramebuffer(GLenum target,GLsizei count,const volatile GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)2261 error::Error GLES2DecoderPassthroughImpl::DoInvalidateSubFramebuffer(
2262 GLenum target,
2263 GLsizei count,
2264 const volatile GLenum* attachments,
2265 GLint x,
2266 GLint y,
2267 GLsizei width,
2268 GLsizei height) {
2269 // Validate that count is non-negative before allocating a vector
2270 if (count < 0) {
2271 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
2272 return error::kNoError;
2273 }
2274
2275 std::vector<GLenum> attachments_copy(attachments, attachments + count);
2276 if (IsEmulatedFramebufferBound(target)) {
2277 // Update the attachment do the equivalent one in the emulated framebuffer
2278 if (!ModifyAttachmentsForEmulatedFramebuffer(&attachments_copy)) {
2279 InsertError(GL_INVALID_OPERATION, "Invalid attachment.");
2280 return error::kNoError;
2281 }
2282 }
2283 api()->glInvalidateSubFramebufferFn(target, count, attachments_copy.data(), x,
2284 y, width, height);
2285 return error::kNoError;
2286 }
2287
DoIsBuffer(GLuint buffer,uint32_t * result)2288 error::Error GLES2DecoderPassthroughImpl::DoIsBuffer(GLuint buffer,
2289 uint32_t* result) {
2290 *result =
2291 api()->glIsBufferFn(GetBufferServiceID(api(), buffer, resources_, false));
2292 return error::kNoError;
2293 }
2294
DoIsEnabled(GLenum cap,uint32_t * result)2295 error::Error GLES2DecoderPassthroughImpl::DoIsEnabled(GLenum cap,
2296 uint32_t* result) {
2297 *result = api()->glIsEnabledFn(cap);
2298 return error::kNoError;
2299 }
2300
DoIsEnablediOES(GLenum target,GLuint index,uint32_t * result)2301 error::Error GLES2DecoderPassthroughImpl::DoIsEnablediOES(GLenum target,
2302 GLuint index,
2303 uint32_t* result) {
2304 *result = api()->glIsEnablediOESFn(target, index);
2305 return error::kNoError;
2306 }
2307
DoIsFramebuffer(GLuint framebuffer,uint32_t * result)2308 error::Error GLES2DecoderPassthroughImpl::DoIsFramebuffer(GLuint framebuffer,
2309 uint32_t* result) {
2310 *result = api()->glIsFramebufferEXTFn(
2311 GetFramebufferServiceID(api(), framebuffer, &framebuffer_id_map_, false));
2312 return error::kNoError;
2313 }
2314
DoIsProgram(GLuint program,uint32_t * result)2315 error::Error GLES2DecoderPassthroughImpl::DoIsProgram(GLuint program,
2316 uint32_t* result) {
2317 *result = api()->glIsProgramFn(GetProgramServiceID(program, resources_));
2318 return error::kNoError;
2319 }
2320
DoIsRenderbuffer(GLuint renderbuffer,uint32_t * result)2321 error::Error GLES2DecoderPassthroughImpl::DoIsRenderbuffer(GLuint renderbuffer,
2322 uint32_t* result) {
2323 *result = api()->glIsRenderbufferEXTFn(
2324 GetRenderbufferServiceID(api(), renderbuffer, resources_, false));
2325 return error::kNoError;
2326 }
2327
DoIsSampler(GLuint sampler,uint32_t * result)2328 error::Error GLES2DecoderPassthroughImpl::DoIsSampler(GLuint sampler,
2329 uint32_t* result) {
2330 *result = api()->glIsSamplerFn(GetSamplerServiceID(sampler, resources_));
2331 return error::kNoError;
2332 }
2333
DoIsShader(GLuint shader,uint32_t * result)2334 error::Error GLES2DecoderPassthroughImpl::DoIsShader(GLuint shader,
2335 uint32_t* result) {
2336 *result = api()->glIsShaderFn(GetShaderServiceID(shader, resources_));
2337 return error::kNoError;
2338 }
2339
DoIsSync(GLuint sync,uint32_t * result)2340 error::Error GLES2DecoderPassthroughImpl::DoIsSync(GLuint sync,
2341 uint32_t* result) {
2342 *result = api()->glIsSyncFn(GetSyncServiceID(sync, resources_));
2343 return error::kNoError;
2344 }
2345
DoIsTexture(GLuint texture,uint32_t * result)2346 error::Error GLES2DecoderPassthroughImpl::DoIsTexture(GLuint texture,
2347 uint32_t* result) {
2348 *result = api()->glIsTextureFn(
2349 GetTextureServiceID(api(), texture, resources_, false));
2350 return error::kNoError;
2351 }
2352
DoIsTransformFeedback(GLuint transformfeedback,uint32_t * result)2353 error::Error GLES2DecoderPassthroughImpl::DoIsTransformFeedback(
2354 GLuint transformfeedback,
2355 uint32_t* result) {
2356 *result = api()->glIsTransformFeedbackFn(GetTransformFeedbackServiceID(
2357 transformfeedback, &transform_feedback_id_map_));
2358 return error::kNoError;
2359 }
2360
DoLineWidth(GLfloat width)2361 error::Error GLES2DecoderPassthroughImpl::DoLineWidth(GLfloat width) {
2362 api()->glLineWidthFn(width);
2363 return error::kNoError;
2364 }
2365
DoLinkProgram(GLuint program)2366 error::Error GLES2DecoderPassthroughImpl::DoLinkProgram(GLuint program) {
2367 TRACE_EVENT0("gpu", "GLES2DecoderPassthroughImpl::DoLinkProgram");
2368 SCOPED_UMA_HISTOGRAM_TIMER("GPU.PassthroughDoLinkProgramTime");
2369 GLuint program_service_id = GetProgramServiceID(program, resources_);
2370 api()->glLinkProgramFn(program_service_id);
2371
2372 // Program linking can be very slow. Exit command processing to allow for
2373 // context preemption and GPU watchdog checks.
2374 ExitCommandProcessingEarly();
2375
2376 linking_program_service_id_ = program_service_id;
2377
2378 return error::kNoError;
2379 }
2380
DoMemoryBarrierEXT(GLbitfield barriers)2381 error::Error GLES2DecoderPassthroughImpl::DoMemoryBarrierEXT(
2382 GLbitfield barriers) {
2383 api()->glMemoryBarrierEXTFn(barriers);
2384 return error::kNoError;
2385 }
2386
DoMemoryBarrierByRegion(GLbitfield barriers)2387 error::Error GLES2DecoderPassthroughImpl::DoMemoryBarrierByRegion(
2388 GLbitfield barriers) {
2389 api()->glMemoryBarrierByRegionFn(barriers);
2390 return error::kNoError;
2391 }
2392
DoMultiDrawBeginCHROMIUM(GLsizei drawcount)2393 error::Error GLES2DecoderPassthroughImpl::DoMultiDrawBeginCHROMIUM(
2394 GLsizei drawcount) {
2395 if (drawcount < 0) {
2396 InsertError(GL_INVALID_VALUE, "drawcount cannot be negative.");
2397 return error::kNoError;
2398 }
2399
2400 if (!multi_draw_manager_->Begin(drawcount)) {
2401 return error::kInvalidArguments;
2402 }
2403 return error::kNoError;
2404 }
2405
DoMultiDrawEndCHROMIUM()2406 error::Error GLES2DecoderPassthroughImpl::DoMultiDrawEndCHROMIUM() {
2407 MultiDrawManager::ResultData result;
2408 if (!multi_draw_manager_->End(&result)) {
2409 return error::kInvalidArguments;
2410 }
2411 switch (result.draw_function) {
2412 case MultiDrawManager::DrawFunction::DrawArrays:
2413 api()->glMultiDrawArraysANGLEFn(result.mode, result.firsts.data(),
2414 result.counts.data(), result.drawcount);
2415 return error::kNoError;
2416 case MultiDrawManager::DrawFunction::DrawArraysInstanced:
2417 api()->glMultiDrawArraysInstancedANGLEFn(
2418 result.mode, result.firsts.data(), result.counts.data(),
2419 result.instance_counts.data(), result.drawcount);
2420 return error::kNoError;
2421 case MultiDrawManager::DrawFunction::DrawArraysInstancedBaseInstance:
2422 api()->glMultiDrawArraysInstancedBaseInstanceANGLEFn(
2423 result.mode, result.firsts.data(), result.counts.data(),
2424 result.instance_counts.data(), result.baseinstances.data(),
2425 result.drawcount);
2426 return error::kNoError;
2427 case MultiDrawManager::DrawFunction::DrawElements:
2428 api()->glMultiDrawElementsANGLEFn(result.mode, result.counts.data(),
2429 result.type, result.indices.data(),
2430 result.drawcount);
2431 return error::kNoError;
2432 case MultiDrawManager::DrawFunction::DrawElementsInstanced:
2433 api()->glMultiDrawElementsInstancedANGLEFn(
2434 result.mode, result.counts.data(), result.type, result.indices.data(),
2435 result.instance_counts.data(), result.drawcount);
2436 return error::kNoError;
2437 case MultiDrawManager::DrawFunction::
2438 DrawElementsInstancedBaseVertexBaseInstance:
2439 api()->glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLEFn(
2440 result.mode, result.counts.data(), result.type, result.indices.data(),
2441 result.instance_counts.data(), result.basevertices.data(),
2442 result.baseinstances.data(), result.drawcount);
2443 return error::kNoError;
2444 default:
2445 NOTREACHED();
2446 return error::kLostContext;
2447 }
2448 }
2449
DoPauseTransformFeedback()2450 error::Error GLES2DecoderPassthroughImpl::DoPauseTransformFeedback() {
2451 api()->glPauseTransformFeedbackFn();
2452 return error::kNoError;
2453 }
2454
DoPixelStorei(GLenum pname,GLint param)2455 error::Error GLES2DecoderPassthroughImpl::DoPixelStorei(GLenum pname,
2456 GLint param) {
2457 api()->glPixelStoreiFn(pname, param);
2458 return error::kNoError;
2459 }
2460
DoPolygonOffset(GLfloat factor,GLfloat units)2461 error::Error GLES2DecoderPassthroughImpl::DoPolygonOffset(GLfloat factor,
2462 GLfloat units) {
2463 api()->glPolygonOffsetFn(factor, units);
2464 return error::kNoError;
2465 }
2466
DoReadBuffer(GLenum src)2467 error::Error GLES2DecoderPassthroughImpl::DoReadBuffer(GLenum src) {
2468 api()->glReadBufferFn(src);
2469 return error::kNoError;
2470 }
2471
DoReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufsize,GLsizei * length,GLsizei * columns,GLsizei * rows,void * pixels,int32_t * success)2472 error::Error GLES2DecoderPassthroughImpl::DoReadPixels(GLint x,
2473 GLint y,
2474 GLsizei width,
2475 GLsizei height,
2476 GLenum format,
2477 GLenum type,
2478 GLsizei bufsize,
2479 GLsizei* length,
2480 GLsizei* columns,
2481 GLsizei* rows,
2482 void* pixels,
2483 int32_t* success) {
2484 CheckErrorCallbackState();
2485 ScopedPackStateRowLengthReset reset_row_length(
2486 api(), bufsize != 0 && feature_info_->gl_version_info().is_es3);
2487 api()->glReadPixelsRobustANGLEFn(x, y, width, height, format, type, bufsize,
2488 length, columns, rows, pixels);
2489 *success = CheckErrorCallbackState() ? 0 : 1;
2490 return error::kNoError;
2491 }
2492
DoReadPixelsAsync(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufsize,GLsizei * length,GLsizei * columns,GLsizei * rows,uint32_t pixels_shm_id,uint32_t pixels_shm_offset,uint32_t result_shm_id,uint32_t result_shm_offset)2493 error::Error GLES2DecoderPassthroughImpl::DoReadPixelsAsync(
2494 GLint x,
2495 GLint y,
2496 GLsizei width,
2497 GLsizei height,
2498 GLenum format,
2499 GLenum type,
2500 GLsizei bufsize,
2501 GLsizei* length,
2502 GLsizei* columns,
2503 GLsizei* rows,
2504 uint32_t pixels_shm_id,
2505 uint32_t pixels_shm_offset,
2506 uint32_t result_shm_id,
2507 uint32_t result_shm_offset) {
2508 DCHECK(feature_info_->feature_flags().use_async_readpixels &&
2509 bound_buffers_[GL_PIXEL_PACK_BUFFER] == 0);
2510
2511 CheckErrorCallbackState();
2512 ScopedPackStateRowLengthReset reset_row_length(
2513 api(), bufsize != 0 && feature_info_->gl_version_info().is_es3);
2514
2515 PendingReadPixels pending_read_pixels;
2516 pending_read_pixels.pixels_shm_id = pixels_shm_id;
2517 pending_read_pixels.pixels_shm_offset = pixels_shm_offset;
2518 pending_read_pixels.result_shm_id = result_shm_id;
2519 pending_read_pixels.result_shm_offset = result_shm_offset;
2520
2521 api()->glGenBuffersARBFn(1, &pending_read_pixels.buffer_service_id);
2522 api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER_ARB,
2523 pending_read_pixels.buffer_service_id);
2524
2525 // GL_STREAM_READ is not available until ES3.
2526 const GLenum usage_hint = feature_info_->gl_version_info().IsAtLeastGLES(3, 0)
2527 ? GL_STREAM_READ
2528 : GL_STATIC_DRAW;
2529
2530 const uint32_t bytes_per_pixel =
2531 GLES2Util::ComputeImageGroupSize(format, type);
2532 if (bytes_per_pixel == 0) {
2533 InsertError(GL_INVALID_ENUM, "Invalid ReadPixels format or type.");
2534 return error::kNoError;
2535 }
2536
2537 if (width < 0 || height < 0) {
2538 InsertError(GL_INVALID_VALUE, "Width and height cannot be negative.");
2539 return error::kNoError;
2540 }
2541
2542 if (!base::CheckMul(bytes_per_pixel, width, height)
2543 .AssignIfValid(&pending_read_pixels.pixels_size)) {
2544 return error::kOutOfBounds;
2545 }
2546
2547 api()->glBufferDataFn(GL_PIXEL_PACK_BUFFER_ARB,
2548 pending_read_pixels.pixels_size, nullptr, usage_hint);
2549
2550 // No need to worry about ES3 pixel pack parameters, because no
2551 // PIXEL_PACK_BUFFER is bound, and all these settings haven't been
2552 // sent to GL.
2553 api()->glReadPixelsFn(x, y, width, height, format, type, nullptr);
2554
2555 api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER_ARB, 0);
2556
2557 // Test for errors now before creating a fence
2558 if (CheckErrorCallbackState()) {
2559 return error::kNoError;
2560 }
2561
2562 pending_read_pixels.fence = gl::GLFence::Create();
2563
2564 if (CheckErrorCallbackState()) {
2565 return error::kNoError;
2566 }
2567
2568 pending_read_pixels_.push_back(std::move(pending_read_pixels));
2569 return error::kNoError;
2570 }
2571
DoReleaseShaderCompiler()2572 error::Error GLES2DecoderPassthroughImpl::DoReleaseShaderCompiler() {
2573 api()->glReleaseShaderCompilerFn();
2574 return error::kNoError;
2575 }
2576
DoRenderbufferStorage(GLenum target,GLenum internalformat,GLsizei width,GLsizei height)2577 error::Error GLES2DecoderPassthroughImpl::DoRenderbufferStorage(
2578 GLenum target,
2579 GLenum internalformat,
2580 GLsizei width,
2581 GLsizei height) {
2582 api()->glRenderbufferStorageEXTFn(target, internalformat, width, height);
2583 return error::kNoError;
2584 }
2585
DoResumeTransformFeedback()2586 error::Error GLES2DecoderPassthroughImpl::DoResumeTransformFeedback() {
2587 api()->glResumeTransformFeedbackFn();
2588 return error::kNoError;
2589 }
2590
DoSampleCoverage(GLclampf value,GLboolean invert)2591 error::Error GLES2DecoderPassthroughImpl::DoSampleCoverage(GLclampf value,
2592 GLboolean invert) {
2593 api()->glSampleCoverageFn(value, invert);
2594 return error::kNoError;
2595 }
2596
DoSamplerParameterf(GLuint sampler,GLenum pname,GLfloat param)2597 error::Error GLES2DecoderPassthroughImpl::DoSamplerParameterf(GLuint sampler,
2598 GLenum pname,
2599 GLfloat param) {
2600 api()->glSamplerParameterfFn(GetSamplerServiceID(sampler, resources_), pname,
2601 param);
2602 return error::kNoError;
2603 }
2604
DoSamplerParameterfv(GLuint sampler,GLenum pname,const volatile GLfloat * params)2605 error::Error GLES2DecoderPassthroughImpl::DoSamplerParameterfv(
2606 GLuint sampler,
2607 GLenum pname,
2608 const volatile GLfloat* params) {
2609 std::array<GLfloat, 1> params_copy{{params[0]}};
2610 api()->glSamplerParameterfvRobustANGLEFn(
2611 GetSamplerServiceID(sampler, resources_), pname,
2612 static_cast<GLsizei>(params_copy.size()), params_copy.data());
2613 return error::kNoError;
2614 }
2615
DoSamplerParameteri(GLuint sampler,GLenum pname,GLint param)2616 error::Error GLES2DecoderPassthroughImpl::DoSamplerParameteri(GLuint sampler,
2617 GLenum pname,
2618 GLint param) {
2619 api()->glSamplerParameteriFn(GetSamplerServiceID(sampler, resources_), pname,
2620 param);
2621 return error::kNoError;
2622 }
2623
DoSamplerParameteriv(GLuint sampler,GLenum pname,const volatile GLint * params)2624 error::Error GLES2DecoderPassthroughImpl::DoSamplerParameteriv(
2625 GLuint sampler,
2626 GLenum pname,
2627 const volatile GLint* params) {
2628 std::array<GLint, 1> params_copy{{params[0]}};
2629 api()->glSamplerParameterivRobustANGLEFn(
2630 GetSamplerServiceID(sampler, resources_), pname,
2631 static_cast<GLsizei>(params_copy.size()), params_copy.data());
2632 return error::kNoError;
2633 }
2634
DoScissor(GLint x,GLint y,GLsizei width,GLsizei height)2635 error::Error GLES2DecoderPassthroughImpl::DoScissor(GLint x,
2636 GLint y,
2637 GLsizei width,
2638 GLsizei height) {
2639 CheckErrorCallbackState();
2640
2641 gfx::Vector2d scissor_offset = GetSurfaceDrawOffset();
2642 api()->glScissorFn(x + scissor_offset.x(), y + scissor_offset.y(), width,
2643 height);
2644
2645 if (CheckErrorCallbackState()) {
2646 // Skip any state tracking updates if an error was generated
2647 return error::kNoError;
2648 }
2649
2650 AssignGLRectangle(scissor_, x, y, width, height);
2651
2652 return error::kNoError;
2653 }
2654
DoShaderBinary(GLsizei n,const GLuint * shaders,GLenum binaryformat,const void * binary,GLsizei length)2655 error::Error GLES2DecoderPassthroughImpl::DoShaderBinary(GLsizei n,
2656 const GLuint* shaders,
2657 GLenum binaryformat,
2658 const void* binary,
2659 GLsizei length) {
2660 std::vector<GLuint> service_shaders(n, 0);
2661 for (GLsizei i = 0; i < n; i++) {
2662 service_shaders[i] = GetShaderServiceID(shaders[i], resources_);
2663 }
2664 api()->glShaderBinaryFn(n, service_shaders.data(), binaryformat, binary,
2665 length);
2666 return error::kNoError;
2667 }
2668
DoShaderSource(GLuint shader,GLsizei count,const char ** string,const GLint * length)2669 error::Error GLES2DecoderPassthroughImpl::DoShaderSource(GLuint shader,
2670 GLsizei count,
2671 const char** string,
2672 const GLint* length) {
2673 api()->glShaderSourceFn(GetShaderServiceID(shader, resources_), count, string,
2674 length);
2675 return error::kNoError;
2676 }
2677
DoStencilFunc(GLenum func,GLint ref,GLuint mask)2678 error::Error GLES2DecoderPassthroughImpl::DoStencilFunc(GLenum func,
2679 GLint ref,
2680 GLuint mask) {
2681 api()->glStencilFuncFn(func, ref, mask);
2682 return error::kNoError;
2683 }
2684
DoStencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)2685 error::Error GLES2DecoderPassthroughImpl::DoStencilFuncSeparate(GLenum face,
2686 GLenum func,
2687 GLint ref,
2688 GLuint mask) {
2689 api()->glStencilFuncSeparateFn(face, func, ref, mask);
2690 return error::kNoError;
2691 }
2692
DoStencilMask(GLuint mask)2693 error::Error GLES2DecoderPassthroughImpl::DoStencilMask(GLuint mask) {
2694 api()->glStencilMaskFn(mask);
2695 return error::kNoError;
2696 }
2697
DoStencilMaskSeparate(GLenum face,GLuint mask)2698 error::Error GLES2DecoderPassthroughImpl::DoStencilMaskSeparate(GLenum face,
2699 GLuint mask) {
2700 api()->glStencilMaskSeparateFn(face, mask);
2701 return error::kNoError;
2702 }
2703
DoStencilOp(GLenum fail,GLenum zfail,GLenum zpass)2704 error::Error GLES2DecoderPassthroughImpl::DoStencilOp(GLenum fail,
2705 GLenum zfail,
2706 GLenum zpass) {
2707 api()->glStencilOpFn(fail, zfail, zpass);
2708 return error::kNoError;
2709 }
2710
DoStencilOpSeparate(GLenum face,GLenum fail,GLenum zfail,GLenum zpass)2711 error::Error GLES2DecoderPassthroughImpl::DoStencilOpSeparate(GLenum face,
2712 GLenum fail,
2713 GLenum zfail,
2714 GLenum zpass) {
2715 api()->glStencilOpSeparateFn(face, fail, zfail, zpass);
2716 return error::kNoError;
2717 }
2718
DoTexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei image_size,const void * pixels)2719 error::Error GLES2DecoderPassthroughImpl::DoTexImage2D(GLenum target,
2720 GLint level,
2721 GLint internalformat,
2722 GLsizei width,
2723 GLsizei height,
2724 GLint border,
2725 GLenum format,
2726 GLenum type,
2727 GLsizei image_size,
2728 const void* pixels) {
2729 ScopedUnpackStateButAlignmentReset reset_unpack(
2730 api(), image_size != 0 && feature_info_->gl_version_info().is_es3, false);
2731
2732 CheckErrorCallbackState();
2733 api()->glTexImage2DRobustANGLEFn(target, level, internalformat, width, height,
2734 border, format, type, image_size, pixels);
2735 if (CheckErrorCallbackState()) {
2736 return error::kNoError;
2737 }
2738
2739 UpdateTextureSizeFromTarget(target);
2740
2741 // Texture data upload can be slow. Exit command processing to allow for
2742 // context preemption and GPU watchdog checks.
2743 ExitCommandProcessingEarly();
2744
2745 return error::kNoError;
2746 }
2747
DoTexImage3D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei image_size,const void * pixels)2748 error::Error GLES2DecoderPassthroughImpl::DoTexImage3D(GLenum target,
2749 GLint level,
2750 GLint internalformat,
2751 GLsizei width,
2752 GLsizei height,
2753 GLsizei depth,
2754 GLint border,
2755 GLenum format,
2756 GLenum type,
2757 GLsizei image_size,
2758 const void* pixels) {
2759 ScopedUnpackStateButAlignmentReset reset_unpack(
2760 api(), image_size != 0 && feature_info_->gl_version_info().is_es3, true);
2761
2762 CheckErrorCallbackState();
2763 api()->glTexImage3DRobustANGLEFn(target, level, internalformat, width, height,
2764 depth, border, format, type, image_size,
2765 pixels);
2766 if (CheckErrorCallbackState()) {
2767 return error::kNoError;
2768 }
2769
2770 UpdateTextureSizeFromTarget(target);
2771
2772 // Texture data upload can be slow. Exit command processing to allow for
2773 // context preemption and GPU watchdog checks.
2774 ExitCommandProcessingEarly();
2775
2776 return error::kNoError;
2777 }
2778
DoTexParameterf(GLenum target,GLenum pname,GLfloat param)2779 error::Error GLES2DecoderPassthroughImpl::DoTexParameterf(GLenum target,
2780 GLenum pname,
2781 GLfloat param) {
2782 // Don't allow clients to modify the resource initialization state.
2783 if (pname == GL_RESOURCE_INITIALIZED_ANGLE) {
2784 InsertError(GL_INVALID_ENUM, "Invalid enum.");
2785 return error::kNoError;
2786 }
2787
2788 api()->glTexParameterfFn(target, pname, param);
2789 return error::kNoError;
2790 }
2791
DoTexParameterfv(GLenum target,GLenum pname,const volatile GLfloat * params)2792 error::Error GLES2DecoderPassthroughImpl::DoTexParameterfv(
2793 GLenum target,
2794 GLenum pname,
2795 const volatile GLfloat* params) {
2796 // Don't allow clients to modify the resource initialization state.
2797 if (pname == GL_RESOURCE_INITIALIZED_ANGLE) {
2798 InsertError(GL_INVALID_ENUM, "Invalid enum.");
2799 return error::kNoError;
2800 }
2801
2802 std::array<GLfloat, 1> params_copy{{params[0]}};
2803 api()->glTexParameterfvRobustANGLEFn(target, pname,
2804 static_cast<GLsizei>(params_copy.size()),
2805 params_copy.data());
2806 return error::kNoError;
2807 }
2808
DoTexParameteri(GLenum target,GLenum pname,GLint param)2809 error::Error GLES2DecoderPassthroughImpl::DoTexParameteri(GLenum target,
2810 GLenum pname,
2811 GLint param) {
2812 // Don't allow clients to modify the resource initialization state.
2813 if (pname == GL_RESOURCE_INITIALIZED_ANGLE) {
2814 InsertError(GL_INVALID_ENUM, "Invalid enum.");
2815 return error::kNoError;
2816 }
2817
2818 api()->glTexParameteriFn(target, pname, param);
2819 return error::kNoError;
2820 }
2821
DoTexParameteriv(GLenum target,GLenum pname,const volatile GLint * params)2822 error::Error GLES2DecoderPassthroughImpl::DoTexParameteriv(
2823 GLenum target,
2824 GLenum pname,
2825 const volatile GLint* params) {
2826 // Don't allow clients to modify the resource initialization state.
2827 if (pname == GL_RESOURCE_INITIALIZED_ANGLE) {
2828 InsertError(GL_INVALID_ENUM, "Invalid enum.");
2829 return error::kNoError;
2830 }
2831
2832 std::array<GLint, 1> params_copy{{params[0]}};
2833 api()->glTexParameterivRobustANGLEFn(target, pname,
2834 static_cast<GLsizei>(params_copy.size()),
2835 params_copy.data());
2836 return error::kNoError;
2837 }
2838
DoTexStorage3D(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth)2839 error::Error GLES2DecoderPassthroughImpl::DoTexStorage3D(GLenum target,
2840 GLsizei levels,
2841 GLenum internalFormat,
2842 GLsizei width,
2843 GLsizei height,
2844 GLsizei depth) {
2845 CheckErrorCallbackState();
2846 api()->glTexStorage3DFn(target, levels, internalFormat, width, height, depth);
2847 if (CheckErrorCallbackState()) {
2848 return error::kNoError;
2849 }
2850
2851 UpdateTextureSizeFromTarget(target);
2852 return error::kNoError;
2853 }
2854
DoTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei image_size,const void * pixels)2855 error::Error GLES2DecoderPassthroughImpl::DoTexSubImage2D(GLenum target,
2856 GLint level,
2857 GLint xoffset,
2858 GLint yoffset,
2859 GLsizei width,
2860 GLsizei height,
2861 GLenum format,
2862 GLenum type,
2863 GLsizei image_size,
2864 const void* pixels) {
2865 ScopedUnpackStateButAlignmentReset reset_unpack(
2866 api(), image_size != 0 && feature_info_->gl_version_info().is_es3, false);
2867 api()->glTexSubImage2DRobustANGLEFn(target, level, xoffset, yoffset, width,
2868 height, format, type, image_size, pixels);
2869
2870 // Texture data upload can be slow. Exit command processing to allow for
2871 // context preemption and GPU watchdog checks.
2872 ExitCommandProcessingEarly();
2873
2874 return error::kNoError;
2875 }
2876
DoTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei image_size,const void * pixels)2877 error::Error GLES2DecoderPassthroughImpl::DoTexSubImage3D(GLenum target,
2878 GLint level,
2879 GLint xoffset,
2880 GLint yoffset,
2881 GLint zoffset,
2882 GLsizei width,
2883 GLsizei height,
2884 GLsizei depth,
2885 GLenum format,
2886 GLenum type,
2887 GLsizei image_size,
2888 const void* pixels) {
2889 ScopedUnpackStateButAlignmentReset reset_unpack(
2890 api(), image_size != 0 && feature_info_->gl_version_info().is_es3, true);
2891 api()->glTexSubImage3DRobustANGLEFn(target, level, xoffset, yoffset, zoffset,
2892 width, height, depth, format, type,
2893 image_size, pixels);
2894
2895 // Texture data upload can be slow. Exit command processing to allow for
2896 // context preemption and GPU watchdog checks.
2897 ExitCommandProcessingEarly();
2898
2899 return error::kNoError;
2900 }
2901
DoTransformFeedbackVaryings(GLuint program,GLsizei count,const char ** varyings,GLenum buffermode)2902 error::Error GLES2DecoderPassthroughImpl::DoTransformFeedbackVaryings(
2903 GLuint program,
2904 GLsizei count,
2905 const char** varyings,
2906 GLenum buffermode) {
2907 api()->glTransformFeedbackVaryingsFn(GetProgramServiceID(program, resources_),
2908 count, varyings, buffermode);
2909 return error::kNoError;
2910 }
2911
DoUniform1f(GLint location,GLfloat x)2912 error::Error GLES2DecoderPassthroughImpl::DoUniform1f(GLint location,
2913 GLfloat x) {
2914 api()->glUniform1fFn(location, x);
2915 return error::kNoError;
2916 }
2917
DoUniform1fv(GLint location,GLsizei count,const volatile GLfloat * v)2918 error::Error GLES2DecoderPassthroughImpl::DoUniform1fv(
2919 GLint location,
2920 GLsizei count,
2921 const volatile GLfloat* v) {
2922 api()->glUniform1fvFn(location, count, const_cast<const GLfloat*>(v));
2923 return error::kNoError;
2924 }
2925
DoUniform1i(GLint location,GLint x)2926 error::Error GLES2DecoderPassthroughImpl::DoUniform1i(GLint location, GLint x) {
2927 api()->glUniform1iFn(location, x);
2928 return error::kNoError;
2929 }
2930
DoUniform1iv(GLint location,GLsizei count,const volatile GLint * v)2931 error::Error GLES2DecoderPassthroughImpl::DoUniform1iv(
2932 GLint location,
2933 GLsizei count,
2934 const volatile GLint* v) {
2935 api()->glUniform1ivFn(location, count, const_cast<const GLint*>(v));
2936 return error::kNoError;
2937 }
2938
DoUniform1ui(GLint location,GLuint x)2939 error::Error GLES2DecoderPassthroughImpl::DoUniform1ui(GLint location,
2940 GLuint x) {
2941 api()->glUniform1uiFn(location, x);
2942 return error::kNoError;
2943 }
2944
DoUniform1uiv(GLint location,GLsizei count,const volatile GLuint * v)2945 error::Error GLES2DecoderPassthroughImpl::DoUniform1uiv(
2946 GLint location,
2947 GLsizei count,
2948 const volatile GLuint* v) {
2949 api()->glUniform1uivFn(location, count, const_cast<const GLuint*>(v));
2950 return error::kNoError;
2951 }
2952
DoUniform2f(GLint location,GLfloat x,GLfloat y)2953 error::Error GLES2DecoderPassthroughImpl::DoUniform2f(GLint location,
2954 GLfloat x,
2955 GLfloat y) {
2956 api()->glUniform2fFn(location, x, y);
2957 return error::kNoError;
2958 }
2959
DoUniform2fv(GLint location,GLsizei count,const volatile GLfloat * v)2960 error::Error GLES2DecoderPassthroughImpl::DoUniform2fv(
2961 GLint location,
2962 GLsizei count,
2963 const volatile GLfloat* v) {
2964 api()->glUniform2fvFn(location, count, const_cast<const GLfloat*>(v));
2965 return error::kNoError;
2966 }
2967
DoUniform2i(GLint location,GLint x,GLint y)2968 error::Error GLES2DecoderPassthroughImpl::DoUniform2i(GLint location,
2969 GLint x,
2970 GLint y) {
2971 api()->glUniform2iFn(location, x, y);
2972 return error::kNoError;
2973 }
2974
DoUniform2iv(GLint location,GLsizei count,const volatile GLint * v)2975 error::Error GLES2DecoderPassthroughImpl::DoUniform2iv(
2976 GLint location,
2977 GLsizei count,
2978 const volatile GLint* v) {
2979 api()->glUniform2ivFn(location, count, const_cast<const GLint*>(v));
2980 return error::kNoError;
2981 }
2982
DoUniform2ui(GLint location,GLuint x,GLuint y)2983 error::Error GLES2DecoderPassthroughImpl::DoUniform2ui(GLint location,
2984 GLuint x,
2985 GLuint y) {
2986 api()->glUniform2uiFn(location, x, y);
2987 return error::kNoError;
2988 }
2989
DoUniform2uiv(GLint location,GLsizei count,const volatile GLuint * v)2990 error::Error GLES2DecoderPassthroughImpl::DoUniform2uiv(
2991 GLint location,
2992 GLsizei count,
2993 const volatile GLuint* v) {
2994 api()->glUniform2uivFn(location, count, const_cast<const GLuint*>(v));
2995 return error::kNoError;
2996 }
2997
DoUniform3f(GLint location,GLfloat x,GLfloat y,GLfloat z)2998 error::Error GLES2DecoderPassthroughImpl::DoUniform3f(GLint location,
2999 GLfloat x,
3000 GLfloat y,
3001 GLfloat z) {
3002 api()->glUniform3fFn(location, x, y, z);
3003 return error::kNoError;
3004 }
3005
DoUniform3fv(GLint location,GLsizei count,const volatile GLfloat * v)3006 error::Error GLES2DecoderPassthroughImpl::DoUniform3fv(
3007 GLint location,
3008 GLsizei count,
3009 const volatile GLfloat* v) {
3010 api()->glUniform3fvFn(location, count, const_cast<const GLfloat*>(v));
3011 return error::kNoError;
3012 }
3013
DoUniform3i(GLint location,GLint x,GLint y,GLint z)3014 error::Error GLES2DecoderPassthroughImpl::DoUniform3i(GLint location,
3015 GLint x,
3016 GLint y,
3017 GLint z) {
3018 api()->glUniform3iFn(location, x, y, z);
3019 return error::kNoError;
3020 }
3021
DoUniform3iv(GLint location,GLsizei count,const volatile GLint * v)3022 error::Error GLES2DecoderPassthroughImpl::DoUniform3iv(
3023 GLint location,
3024 GLsizei count,
3025 const volatile GLint* v) {
3026 api()->glUniform3ivFn(location, count, const_cast<const GLint*>(v));
3027 return error::kNoError;
3028 }
3029
DoUniform3ui(GLint location,GLuint x,GLuint y,GLuint z)3030 error::Error GLES2DecoderPassthroughImpl::DoUniform3ui(GLint location,
3031 GLuint x,
3032 GLuint y,
3033 GLuint z) {
3034 api()->glUniform3uiFn(location, x, y, z);
3035 return error::kNoError;
3036 }
3037
DoUniform3uiv(GLint location,GLsizei count,const volatile GLuint * v)3038 error::Error GLES2DecoderPassthroughImpl::DoUniform3uiv(
3039 GLint location,
3040 GLsizei count,
3041 const volatile GLuint* v) {
3042 api()->glUniform3uivFn(location, count, const_cast<const GLuint*>(v));
3043 return error::kNoError;
3044 }
3045
DoUniform4f(GLint location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)3046 error::Error GLES2DecoderPassthroughImpl::DoUniform4f(GLint location,
3047 GLfloat x,
3048 GLfloat y,
3049 GLfloat z,
3050 GLfloat w) {
3051 api()->glUniform4fFn(location, x, y, z, w);
3052 return error::kNoError;
3053 }
3054
DoUniform4fv(GLint location,GLsizei count,const volatile GLfloat * v)3055 error::Error GLES2DecoderPassthroughImpl::DoUniform4fv(
3056 GLint location,
3057 GLsizei count,
3058 const volatile GLfloat* v) {
3059 api()->glUniform4fvFn(location, count, const_cast<const GLfloat*>(v));
3060 return error::kNoError;
3061 }
3062
DoUniform4i(GLint location,GLint x,GLint y,GLint z,GLint w)3063 error::Error GLES2DecoderPassthroughImpl::DoUniform4i(GLint location,
3064 GLint x,
3065 GLint y,
3066 GLint z,
3067 GLint w) {
3068 api()->glUniform4iFn(location, x, y, z, w);
3069 return error::kNoError;
3070 }
3071
DoUniform4iv(GLint location,GLsizei count,const volatile GLint * v)3072 error::Error GLES2DecoderPassthroughImpl::DoUniform4iv(
3073 GLint location,
3074 GLsizei count,
3075 const volatile GLint* v) {
3076 api()->glUniform4ivFn(location, count, const_cast<const GLint*>(v));
3077 return error::kNoError;
3078 }
3079
DoUniform4ui(GLint location,GLuint x,GLuint y,GLuint z,GLuint w)3080 error::Error GLES2DecoderPassthroughImpl::DoUniform4ui(GLint location,
3081 GLuint x,
3082 GLuint y,
3083 GLuint z,
3084 GLuint w) {
3085 api()->glUniform4uiFn(location, x, y, z, w);
3086 return error::kNoError;
3087 }
3088
DoUniform4uiv(GLint location,GLsizei count,const volatile GLuint * v)3089 error::Error GLES2DecoderPassthroughImpl::DoUniform4uiv(
3090 GLint location,
3091 GLsizei count,
3092 const volatile GLuint* v) {
3093 api()->glUniform4uivFn(location, count, const_cast<const GLuint*>(v));
3094 return error::kNoError;
3095 }
3096
DoUniformBlockBinding(GLuint program,GLuint index,GLuint binding)3097 error::Error GLES2DecoderPassthroughImpl::DoUniformBlockBinding(
3098 GLuint program,
3099 GLuint index,
3100 GLuint binding) {
3101 api()->glUniformBlockBindingFn(GetProgramServiceID(program, resources_),
3102 index, binding);
3103 return error::kNoError;
3104 }
3105
DoUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3106 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2fv(
3107 GLint location,
3108 GLsizei count,
3109 GLboolean transpose,
3110 const volatile GLfloat* value) {
3111 api()->glUniformMatrix2fvFn(location, count, transpose,
3112 const_cast<const GLfloat*>(value));
3113 return error::kNoError;
3114 }
3115
DoUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3116 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2x3fv(
3117 GLint location,
3118 GLsizei count,
3119 GLboolean transpose,
3120 const volatile GLfloat* value) {
3121 api()->glUniformMatrix2x3fvFn(location, count, transpose,
3122 const_cast<const GLfloat*>(value));
3123 return error::kNoError;
3124 }
3125
DoUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3126 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix2x4fv(
3127 GLint location,
3128 GLsizei count,
3129 GLboolean transpose,
3130 const volatile GLfloat* value) {
3131 api()->glUniformMatrix2x4fvFn(location, count, transpose,
3132 const_cast<const GLfloat*>(value));
3133 return error::kNoError;
3134 }
3135
DoUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3136 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3fv(
3137 GLint location,
3138 GLsizei count,
3139 GLboolean transpose,
3140 const volatile GLfloat* value) {
3141 api()->glUniformMatrix3fvFn(location, count, transpose,
3142 const_cast<const GLfloat*>(value));
3143 return error::kNoError;
3144 }
3145
DoUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3146 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3x2fv(
3147 GLint location,
3148 GLsizei count,
3149 GLboolean transpose,
3150 const volatile GLfloat* value) {
3151 api()->glUniformMatrix3x2fvFn(location, count, transpose,
3152 const_cast<const GLfloat*>(value));
3153 return error::kNoError;
3154 }
3155
DoUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3156 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix3x4fv(
3157 GLint location,
3158 GLsizei count,
3159 GLboolean transpose,
3160 const volatile GLfloat* value) {
3161 api()->glUniformMatrix3x4fvFn(location, count, transpose,
3162 const_cast<const GLfloat*>(value));
3163 return error::kNoError;
3164 }
3165
DoUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3166 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4fv(
3167 GLint location,
3168 GLsizei count,
3169 GLboolean transpose,
3170 const volatile GLfloat* value) {
3171 api()->glUniformMatrix4fvFn(location, count, transpose,
3172 const_cast<const GLfloat*>(value));
3173 return error::kNoError;
3174 }
3175
DoUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3176 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4x2fv(
3177 GLint location,
3178 GLsizei count,
3179 GLboolean transpose,
3180 const volatile GLfloat* value) {
3181 api()->glUniformMatrix4x2fvFn(location, count, transpose,
3182 const_cast<const GLfloat*>(value));
3183 return error::kNoError;
3184 }
3185
DoUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const volatile GLfloat * value)3186 error::Error GLES2DecoderPassthroughImpl::DoUniformMatrix4x3fv(
3187 GLint location,
3188 GLsizei count,
3189 GLboolean transpose,
3190 const volatile GLfloat* value) {
3191 api()->glUniformMatrix4x3fvFn(location, count, transpose,
3192 const_cast<const GLfloat*>(value));
3193 return error::kNoError;
3194 }
3195
DoUseProgram(GLuint program)3196 error::Error GLES2DecoderPassthroughImpl::DoUseProgram(GLuint program) {
3197 api()->glUseProgramFn(GetProgramServiceID(program, resources_));
3198 return error::kNoError;
3199 }
3200
DoValidateProgram(GLuint program)3201 error::Error GLES2DecoderPassthroughImpl::DoValidateProgram(GLuint program) {
3202 api()->glValidateProgramFn(GetProgramServiceID(program, resources_));
3203 return error::kNoError;
3204 }
3205
DoVertexAttrib1f(GLuint indx,GLfloat x)3206 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib1f(GLuint indx,
3207 GLfloat x) {
3208 api()->glVertexAttrib1fFn(indx, x);
3209 return error::kNoError;
3210 }
3211
DoVertexAttrib1fv(GLuint indx,const volatile GLfloat * values)3212 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib1fv(
3213 GLuint indx,
3214 const volatile GLfloat* values) {
3215 api()->glVertexAttrib1fvFn(indx, const_cast<const GLfloat*>(values));
3216 return error::kNoError;
3217 }
3218
DoVertexAttrib2f(GLuint indx,GLfloat x,GLfloat y)3219 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib2f(GLuint indx,
3220 GLfloat x,
3221 GLfloat y) {
3222 api()->glVertexAttrib2fFn(indx, x, y);
3223 return error::kNoError;
3224 }
3225
DoVertexAttrib2fv(GLuint indx,const volatile GLfloat * values)3226 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib2fv(
3227 GLuint indx,
3228 const volatile GLfloat* values) {
3229 api()->glVertexAttrib2fvFn(indx, const_cast<const GLfloat*>(values));
3230 return error::kNoError;
3231 }
3232
DoVertexAttrib3f(GLuint indx,GLfloat x,GLfloat y,GLfloat z)3233 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib3f(GLuint indx,
3234 GLfloat x,
3235 GLfloat y,
3236 GLfloat z) {
3237 api()->glVertexAttrib3fFn(indx, x, y, z);
3238 return error::kNoError;
3239 }
3240
DoVertexAttrib3fv(GLuint indx,const volatile GLfloat * values)3241 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib3fv(
3242 GLuint indx,
3243 const volatile GLfloat* values) {
3244 api()->glVertexAttrib3fvFn(indx, const_cast<const GLfloat*>(values));
3245 return error::kNoError;
3246 }
3247
DoVertexAttrib4f(GLuint indx,GLfloat x,GLfloat y,GLfloat z,GLfloat w)3248 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib4f(GLuint indx,
3249 GLfloat x,
3250 GLfloat y,
3251 GLfloat z,
3252 GLfloat w) {
3253 api()->glVertexAttrib4fFn(indx, x, y, z, w);
3254 return error::kNoError;
3255 }
3256
DoVertexAttrib4fv(GLuint indx,const volatile GLfloat * values)3257 error::Error GLES2DecoderPassthroughImpl::DoVertexAttrib4fv(
3258 GLuint indx,
3259 const volatile GLfloat* values) {
3260 api()->glVertexAttrib4fvFn(indx, const_cast<const GLfloat*>(values));
3261 return error::kNoError;
3262 }
3263
DoVertexAttribI4i(GLuint indx,GLint x,GLint y,GLint z,GLint w)3264 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4i(GLuint indx,
3265 GLint x,
3266 GLint y,
3267 GLint z,
3268 GLint w) {
3269 api()->glVertexAttribI4iFn(indx, x, y, z, w);
3270 return error::kNoError;
3271 }
3272
DoVertexAttribI4iv(GLuint indx,const volatile GLint * values)3273 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4iv(
3274 GLuint indx,
3275 const volatile GLint* values) {
3276 api()->glVertexAttribI4ivFn(indx, const_cast<const GLint*>(values));
3277 return error::kNoError;
3278 }
3279
DoVertexAttribI4ui(GLuint indx,GLuint x,GLuint y,GLuint z,GLuint w)3280 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4ui(GLuint indx,
3281 GLuint x,
3282 GLuint y,
3283 GLuint z,
3284 GLuint w) {
3285 api()->glVertexAttribI4uiFn(indx, x, y, z, w);
3286 return error::kNoError;
3287 }
3288
DoVertexAttribI4uiv(GLuint indx,const volatile GLuint * values)3289 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribI4uiv(
3290 GLuint indx,
3291 const volatile GLuint* values) {
3292 api()->glVertexAttribI4uivFn(indx, const_cast<const GLuint*>(values));
3293 return error::kNoError;
3294 }
3295
DoVertexAttribIPointer(GLuint indx,GLint size,GLenum type,GLsizei stride,const void * ptr)3296 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribIPointer(
3297 GLuint indx,
3298 GLint size,
3299 GLenum type,
3300 GLsizei stride,
3301 const void* ptr) {
3302 api()->glVertexAttribIPointerFn(indx, size, type, stride, ptr);
3303 return error::kNoError;
3304 }
3305
DoVertexAttribPointer(GLuint indx,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const void * ptr)3306 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribPointer(
3307 GLuint indx,
3308 GLint size,
3309 GLenum type,
3310 GLboolean normalized,
3311 GLsizei stride,
3312 const void* ptr) {
3313 api()->glVertexAttribPointerFn(indx, size, type, normalized, stride, ptr);
3314 return error::kNoError;
3315 }
3316
DoViewport(GLint x,GLint y,GLsizei width,GLsizei height)3317 error::Error GLES2DecoderPassthroughImpl::DoViewport(GLint x,
3318 GLint y,
3319 GLsizei width,
3320 GLsizei height) {
3321 CheckErrorCallbackState();
3322
3323 gfx::Vector2d viewport_offset = GetSurfaceDrawOffset();
3324 api()->glViewportFn(x + viewport_offset.x(), y + viewport_offset.y(), width,
3325 height);
3326
3327 if (CheckErrorCallbackState()) {
3328 // Skip any state tracking updates if an error was generated. Viewport may
3329 // have been out of bounds.
3330 return error::kNoError;
3331 }
3332
3333 AssignGLRectangle(viewport_, x, y, width, height);
3334
3335 return error::kNoError;
3336 }
3337
DoWaitSync(GLuint sync,GLbitfield flags,GLuint64 timeout)3338 error::Error GLES2DecoderPassthroughImpl::DoWaitSync(GLuint sync,
3339 GLbitfield flags,
3340 GLuint64 timeout) {
3341 api()->glWaitSyncFn(GetSyncServiceID(sync, resources_), flags, timeout);
3342 return error::kNoError;
3343 }
3344
DoBlitFramebufferCHROMIUM(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)3345 error::Error GLES2DecoderPassthroughImpl::DoBlitFramebufferCHROMIUM(
3346 GLint srcX0,
3347 GLint srcY0,
3348 GLint srcX1,
3349 GLint srcY1,
3350 GLint dstX0,
3351 GLint dstY0,
3352 GLint dstX1,
3353 GLint dstY1,
3354 GLbitfield mask,
3355 GLenum filter) {
3356 DCHECK(feature_info_->feature_flags().chromium_framebuffer_multisample);
3357 api()->glBlitFramebufferFn(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
3358 dstY1, mask, filter);
3359 return error::kNoError;
3360 }
3361
3362 error::Error
DoRenderbufferStorageMultisampleCHROMIUM(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3363 GLES2DecoderPassthroughImpl::DoRenderbufferStorageMultisampleCHROMIUM(
3364 GLenum target,
3365 GLsizei samples,
3366 GLenum internalformat,
3367 GLsizei width,
3368 GLsizei height) {
3369 DCHECK(feature_info_->feature_flags().chromium_framebuffer_multisample);
3370 api()->glRenderbufferStorageMultisampleFn(target, samples, internalformat,
3371 width, height);
3372 return error::kNoError;
3373 }
3374
3375 error::Error
DoRenderbufferStorageMultisampleAdvancedAMD(GLenum target,GLsizei samples,GLsizei storageSamples,GLenum internalformat,GLsizei width,GLsizei height)3376 GLES2DecoderPassthroughImpl::DoRenderbufferStorageMultisampleAdvancedAMD(
3377 GLenum target,
3378 GLsizei samples,
3379 GLsizei storageSamples,
3380 GLenum internalformat,
3381 GLsizei width,
3382 GLsizei height) {
3383 DCHECK(feature_info_->feature_flags().amd_framebuffer_multisample_advanced);
3384 api()->glRenderbufferStorageMultisampleAdvancedAMDFn(
3385 target, samples, storageSamples, internalformat, width, height);
3386 return error::kNoError;
3387 }
3388
DoRenderbufferStorageMultisampleEXT(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3389 error::Error GLES2DecoderPassthroughImpl::DoRenderbufferStorageMultisampleEXT(
3390 GLenum target,
3391 GLsizei samples,
3392 GLenum internalformat,
3393 GLsizei width,
3394 GLsizei height) {
3395 DCHECK(feature_info_->feature_flags().multisampled_render_to_texture);
3396 api()->glRenderbufferStorageMultisampleEXTFn(target, samples, internalformat,
3397 width, height);
3398 return error::kNoError;
3399 }
3400
DoFramebufferTexture2DMultisampleEXT(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLsizei samples)3401 error::Error GLES2DecoderPassthroughImpl::DoFramebufferTexture2DMultisampleEXT(
3402 GLenum target,
3403 GLenum attachment,
3404 GLenum textarget,
3405 GLuint texture,
3406 GLint level,
3407 GLsizei samples) {
3408 DCHECK(feature_info_->feature_flags().multisampled_render_to_texture);
3409 if (IsEmulatedFramebufferBound(target)) {
3410 InsertError(GL_INVALID_OPERATION,
3411 "Cannot change the attachments of the default framebuffer.");
3412 return error::kNoError;
3413 }
3414 BindPendingImageForClientIDIfNeeded(texture);
3415 api()->glFramebufferTexture2DMultisampleEXTFn(
3416 target, attachment, textarget,
3417 GetTextureServiceID(api(), texture, resources_, false), level, samples);
3418 return error::kNoError;
3419 }
3420
DoTexStorage2DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height)3421 error::Error GLES2DecoderPassthroughImpl::DoTexStorage2DEXT(
3422 GLenum target,
3423 GLsizei levels,
3424 GLenum internalFormat,
3425 GLsizei width,
3426 GLsizei height) {
3427 CheckErrorCallbackState();
3428 api()->glTexStorage2DEXTFn(target, levels, internalFormat, width, height);
3429 if (CheckErrorCallbackState()) {
3430 return error::kNoError;
3431 }
3432 UpdateTextureSizeFromTarget(target);
3433 return error::kNoError;
3434 }
3435
DoTexStorage2DImageCHROMIUM(GLenum target,GLenum internalFormat,GLenum bufferUsage,GLsizei width,GLsizei height)3436 error::Error GLES2DecoderPassthroughImpl::DoTexStorage2DImageCHROMIUM(
3437 GLenum target,
3438 GLenum internalFormat,
3439 GLenum bufferUsage,
3440 GLsizei width,
3441 GLsizei height) {
3442 TextureTarget target_enum = GLenumToTextureTarget(target);
3443 if (target_enum == TextureTarget::kCubeMap ||
3444 target_enum == TextureTarget::kUnkown) {
3445 InsertError(GL_INVALID_ENUM, "Invalid target");
3446 return error::kNoError;
3447 }
3448
3449 const BoundTexture& bound_texture =
3450 bound_textures_[static_cast<size_t>(target_enum)][active_texture_unit_];
3451 if (bound_texture.texture == nullptr) {
3452 InsertError(GL_INVALID_OPERATION, "No texture bound");
3453 return error::kNoError;
3454 }
3455
3456 gfx::BufferFormat buffer_format;
3457 if (!GetGFXBufferFormat(internalFormat, &buffer_format)) {
3458 InsertError(GL_INVALID_ENUM, "Invalid buffer format");
3459 return error::kNoError;
3460 }
3461
3462 gfx::BufferUsage buffer_usage;
3463 if (!GetGFXBufferUsage(bufferUsage, &buffer_usage)) {
3464 InsertError(GL_INVALID_ENUM, "Invalid buffer usage");
3465 return error::kNoError;
3466 }
3467
3468 if (!GetContextGroup()->image_factory()) {
3469 InsertError(GL_INVALID_OPERATION, "Cannot create GL image");
3470 return error::kNoError;
3471 }
3472
3473 bool is_cleared;
3474 scoped_refptr<gl::GLImage> image =
3475 GetContextGroup()->image_factory()->CreateAnonymousImage(
3476 gfx::Size(width, height), buffer_format, buffer_usage,
3477 gpu::kNullSurfaceHandle, &is_cleared);
3478 if (!image || !image->BindTexImage(target)) {
3479 InsertError(GL_INVALID_OPERATION, "Failed to create or bind GL Image");
3480 return error::kNoError;
3481 }
3482
3483 bound_texture.texture->SetLevelImage(target, 0, image.get());
3484
3485 // Target is already validated
3486 UpdateTextureSizeFromTarget(target);
3487
3488 return error::kNoError;
3489 }
3490
DoGenQueriesEXT(GLsizei n,volatile GLuint * queries)3491 error::Error GLES2DecoderPassthroughImpl::DoGenQueriesEXT(
3492 GLsizei n,
3493 volatile GLuint* queries) {
3494 return GenHelper(
3495 n, queries, &query_id_map_, [this](GLsizei n, GLuint* queries) {
3496 if (feature_info_->feature_flags().occlusion_query_boolean) {
3497 // glGenQueries is not loaded unless GL_EXT_occlusion_query_boolean is
3498 // present. All queries must be emulated so they don't need to be
3499 // generated.
3500 api()->glGenQueriesFn(n, queries);
3501 } else {
3502 for (GLsizei i = 0; i < n; i++) {
3503 queries[i] = 0;
3504 }
3505 }
3506 });
3507 }
3508
DoDeleteQueriesEXT(GLsizei n,const volatile GLuint * queries)3509 error::Error GLES2DecoderPassthroughImpl::DoDeleteQueriesEXT(
3510 GLsizei n,
3511 const volatile GLuint* queries) {
3512 // Validate n is non-negative before allcoating a vector of size n
3513 if (n < 0) {
3514 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
3515 return error::kNoError;
3516 }
3517
3518 std::vector<GLuint> queries_copy(queries, queries + n);
3519 // If any of these queries are pending or active, remove them from the lists
3520 for (GLuint query_client_id : queries_copy) {
3521 GLuint query_service_id = 0;
3522 if (!query_id_map_.GetServiceID(query_client_id, &query_service_id) ||
3523 query_service_id == 0) {
3524 continue;
3525 }
3526
3527 QueryInfo query_info = query_info_map_[query_service_id];
3528 query_info_map_.erase(query_service_id);
3529
3530 if (query_info.type == GL_NONE) {
3531 // Query was never started
3532 continue;
3533 }
3534
3535 auto active_queries_iter = active_queries_.find(query_info.type);
3536 if (active_queries_iter != active_queries_.end()) {
3537 active_queries_.erase(active_queries_iter);
3538 }
3539
3540 RemovePendingQuery(query_service_id);
3541 }
3542 return DeleteHelper(
3543 queries_copy.size(), queries_copy.data(), &query_id_map_,
3544 [this](GLsizei n, GLuint* queries) {
3545 if (feature_info_->feature_flags().occlusion_query_boolean) {
3546 // glDeleteQueries is not loaded unless GL_EXT_occlusion_query_boolean
3547 // is present. All queries must be emulated so they don't need to be
3548 // deleted.
3549 api()->glDeleteQueriesFn(n, queries);
3550 }
3551 });
3552 }
3553
DoQueryCounterEXT(GLuint id,GLenum target,int32_t sync_shm_id,uint32_t sync_shm_offset,uint32_t submit_count)3554 error::Error GLES2DecoderPassthroughImpl::DoQueryCounterEXT(
3555 GLuint id,
3556 GLenum target,
3557 int32_t sync_shm_id,
3558 uint32_t sync_shm_offset,
3559 uint32_t submit_count) {
3560 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_shm_id);
3561 if (!buffer)
3562 return error::kInvalidArguments;
3563 QuerySync* sync = static_cast<QuerySync*>(
3564 buffer->GetDataAddress(sync_shm_offset, sizeof(QuerySync)));
3565 if (!sync)
3566 return error::kOutOfBounds;
3567
3568 GLuint service_id = GetQueryServiceID(id, &query_id_map_);
3569
3570 if (IsEmulatedQueryTarget(target)) {
3571 DCHECK_EQ(target,
3572 static_cast<GLenum>(GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM));
3573 } else {
3574 // glQueryCounter is not loaded unless GL_EXT_disjoint_timer_query is present
3575 if (!feature_info_->feature_flags().ext_disjoint_timer_query) {
3576 InsertError(GL_INVALID_ENUM, "Invalid query target.");
3577 return error::kNoError;
3578 }
3579
3580 // Flush all previous errors
3581 CheckErrorCallbackState();
3582
3583 api()->glQueryCounterFn(service_id, target);
3584
3585 // Check if a new error was generated
3586 if (CheckErrorCallbackState()) {
3587 return error::kNoError;
3588 }
3589 }
3590
3591 QueryInfo* query_info = &query_info_map_[service_id];
3592 query_info->type = target;
3593
3594 // Make sure to stop tracking this query if it was still pending a result from
3595 // a previous glEndQuery
3596 RemovePendingQuery(service_id);
3597
3598 PendingQuery pending_query;
3599 pending_query.target = target;
3600 pending_query.service_id = service_id;
3601 pending_query.shm = std::move(buffer);
3602 pending_query.sync = sync;
3603 pending_query.submit_count = submit_count;
3604 if (target == GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM)
3605 pending_query.commands_issued_timestamp = base::TimeTicks::Now();
3606 pending_queries_.push_back(std::move(pending_query));
3607
3608 return ProcessQueries(false);
3609 }
3610
DoBeginQueryEXT(GLenum target,GLuint id,int32_t sync_shm_id,uint32_t sync_shm_offset)3611 error::Error GLES2DecoderPassthroughImpl::DoBeginQueryEXT(
3612 GLenum target,
3613 GLuint id,
3614 int32_t sync_shm_id,
3615 uint32_t sync_shm_offset) {
3616 GLuint service_id = GetQueryServiceID(id, &query_id_map_);
3617 QueryInfo* query_info = &query_info_map_[service_id];
3618
3619 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_shm_id);
3620 if (!buffer)
3621 return error::kInvalidArguments;
3622 QuerySync* sync = static_cast<QuerySync*>(
3623 buffer->GetDataAddress(sync_shm_offset, sizeof(QuerySync)));
3624 if (!sync)
3625 return error::kOutOfBounds;
3626
3627 if (target == GL_PROGRAM_COMPLETION_QUERY_CHROMIUM) {
3628 linking_program_service_id_ = 0u;
3629 }
3630 if (IsEmulatedQueryTarget(target)) {
3631 if (active_queries_.find(target) != active_queries_.end()) {
3632 InsertError(GL_INVALID_OPERATION, "Query already active on target.");
3633 return error::kNoError;
3634 }
3635
3636 if (id == 0) {
3637 InsertError(GL_INVALID_OPERATION, "Query id is 0.");
3638 return error::kNoError;
3639 }
3640
3641 if (query_info->type != GL_NONE && query_info->type != target) {
3642 InsertError(GL_INVALID_OPERATION,
3643 "Query type does not match the target.");
3644 return error::kNoError;
3645 }
3646 } else {
3647 // glBeginQuery is not loaded unless GL_EXT_occlusion_query_boolean is
3648 // present
3649 if (!feature_info_->feature_flags().occlusion_query_boolean) {
3650 InsertError(GL_INVALID_ENUM, "Invalid query target.");
3651 return error::kNoError;
3652 }
3653
3654 // Flush all previous errors
3655 CheckErrorCallbackState();
3656
3657 api()->glBeginQueryFn(target, service_id);
3658
3659 // Check if a new error was generated
3660 if (CheckErrorCallbackState()) {
3661 return error::kNoError;
3662 }
3663 }
3664
3665 query_info->type = target;
3666
3667 // Make sure to stop tracking this query if it was still pending a result from
3668 // a previous glEndQuery
3669 RemovePendingQuery(service_id);
3670
3671 ActiveQuery query;
3672 query.service_id = service_id;
3673 query.shm = std::move(buffer);
3674 query.sync = sync;
3675 if (target == GL_COMMANDS_ISSUED_CHROMIUM)
3676 query.command_processing_start_time = base::TimeTicks::Now();
3677 active_queries_[target] = std::move(query);
3678
3679 return error::kNoError;
3680 }
3681
DoBeginTransformFeedback(GLenum primitivemode)3682 error::Error GLES2DecoderPassthroughImpl::DoBeginTransformFeedback(
3683 GLenum primitivemode) {
3684 api()->glBeginTransformFeedbackFn(primitivemode);
3685 return error::kNoError;
3686 }
3687
DoEndQueryEXT(GLenum target,uint32_t submit_count)3688 error::Error GLES2DecoderPassthroughImpl::DoEndQueryEXT(GLenum target,
3689 uint32_t submit_count) {
3690 if (IsEmulatedQueryTarget(target)) {
3691 auto active_query_iter = active_queries_.find(target);
3692 if (active_query_iter == active_queries_.end()) {
3693 InsertError(GL_INVALID_OPERATION, "No active query on target.");
3694 return error::kNoError;
3695 }
3696 if (target == GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM &&
3697 !pending_read_pixels_.empty()) {
3698 GLuint query_service_id = active_query_iter->second.service_id;
3699 pending_read_pixels_.back().waiting_async_pack_queries.insert(
3700 query_service_id);
3701 }
3702 } else {
3703 // glEndQuery is not loaded unless GL_EXT_occlusion_query_boolean is present
3704 if (!feature_info_->feature_flags().occlusion_query_boolean) {
3705 InsertError(GL_INVALID_ENUM, "Invalid query target.");
3706 return error::kNoError;
3707 }
3708
3709 // Flush all previous errors
3710 CheckErrorCallbackState();
3711
3712 api()->glEndQueryFn(target);
3713
3714 // Check if a new error was generated
3715 if (CheckErrorCallbackState()) {
3716 return error::kNoError;
3717 }
3718 }
3719
3720 DCHECK(active_queries_.find(target) != active_queries_.end());
3721 ActiveQuery active_query = std::move(active_queries_[target]);
3722 active_queries_.erase(target);
3723
3724 PendingQuery pending_query;
3725 pending_query.target = target;
3726 pending_query.service_id = active_query.service_id;
3727 pending_query.shm = std::move(active_query.shm);
3728 pending_query.sync = active_query.sync;
3729 pending_query.submit_count = submit_count;
3730 switch (target) {
3731 case GL_COMMANDS_COMPLETED_CHROMIUM:
3732 pending_query.commands_completed_fence = gl::GLFence::Create();
3733 break;
3734
3735 case GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM:
3736 pending_query.buffer_shadow_update_fence = gl::GLFence::Create();
3737 pending_query.buffer_shadow_updates = std::move(buffer_shadow_updates_);
3738 buffer_shadow_updates_.clear();
3739 break;
3740
3741 case GL_PROGRAM_COMPLETION_QUERY_CHROMIUM:
3742 pending_query.program_service_id = linking_program_service_id_;
3743 break;
3744
3745 case GL_COMMANDS_ISSUED_CHROMIUM:
3746 pending_query.commands_issued_time =
3747 active_query.active_time +
3748 (base::TimeTicks::Now() - active_query.command_processing_start_time);
3749 break;
3750
3751 default:
3752 break;
3753 }
3754 pending_queries_.push_back(std::move(pending_query));
3755 return ProcessQueries(false);
3756 }
3757
DoEndTransformFeedback()3758 error::Error GLES2DecoderPassthroughImpl::DoEndTransformFeedback() {
3759 api()->glEndTransformFeedbackFn();
3760 return error::kNoError;
3761 }
3762
DoSetDisjointValueSyncCHROMIUM(DisjointValueSync * sync)3763 error::Error GLES2DecoderPassthroughImpl::DoSetDisjointValueSyncCHROMIUM(
3764 DisjointValueSync* sync) {
3765 NOTIMPLEMENTED();
3766 return error::kNoError;
3767 }
3768
DoInsertEventMarkerEXT(GLsizei length,const char * marker)3769 error::Error GLES2DecoderPassthroughImpl::DoInsertEventMarkerEXT(
3770 GLsizei length,
3771 const char* marker) {
3772 api()->glInsertEventMarkerEXTFn(length, marker);
3773 return error::kNoError;
3774 }
3775
DoPushGroupMarkerEXT(GLsizei length,const char * marker)3776 error::Error GLES2DecoderPassthroughImpl::DoPushGroupMarkerEXT(
3777 GLsizei length,
3778 const char* marker) {
3779 api()->glPushGroupMarkerEXTFn(length, marker);
3780 return error::kNoError;
3781 }
3782
DoPopGroupMarkerEXT()3783 error::Error GLES2DecoderPassthroughImpl::DoPopGroupMarkerEXT() {
3784 api()->glPopGroupMarkerEXTFn();
3785 return error::kNoError;
3786 }
3787
DoGenVertexArraysOES(GLsizei n,volatile GLuint * arrays)3788 error::Error GLES2DecoderPassthroughImpl::DoGenVertexArraysOES(
3789 GLsizei n,
3790 volatile GLuint* arrays) {
3791 return GenHelper(n, arrays, &vertex_array_id_map_,
3792 [this](GLsizei n, GLuint* arrays) {
3793 api()->glGenVertexArraysOESFn(n, arrays);
3794 });
3795 }
3796
DoDeleteVertexArraysOES(GLsizei n,const volatile GLuint * arrays)3797 error::Error GLES2DecoderPassthroughImpl::DoDeleteVertexArraysOES(
3798 GLsizei n,
3799 const volatile GLuint* arrays) {
3800 return DeleteHelper(n, arrays, &vertex_array_id_map_,
3801 [this](GLsizei n, GLuint* arrays) {
3802 api()->glDeleteVertexArraysOESFn(n, arrays);
3803 });
3804 }
3805
DoIsVertexArrayOES(GLuint array,uint32_t * result)3806 error::Error GLES2DecoderPassthroughImpl::DoIsVertexArrayOES(GLuint array,
3807 uint32_t* result) {
3808 *result = api()->glIsVertexArrayOESFn(
3809 GetVertexArrayServiceID(array, &vertex_array_id_map_));
3810 return error::kNoError;
3811 }
3812
DoBindVertexArrayOES(GLuint array)3813 error::Error GLES2DecoderPassthroughImpl::DoBindVertexArrayOES(GLuint array) {
3814 api()->glBindVertexArrayOESFn(
3815 GetVertexArrayServiceID(array, &vertex_array_id_map_));
3816 return error::kNoError;
3817 }
3818
DoSwapBuffers(uint64_t swap_id,GLbitfield flags)3819 error::Error GLES2DecoderPassthroughImpl::DoSwapBuffers(uint64_t swap_id,
3820 GLbitfield flags) {
3821 ca_layer_shared_state_ = nullptr;
3822
3823 if (offscreen_) {
3824 if (offscreen_single_buffer_) {
3825 return error::kNoError;
3826 }
3827
3828 DCHECK(emulated_back_buffer_);
3829
3830 // Make sure the emulated front buffer is allocated and the correct size
3831 if (emulated_front_buffer_ &&
3832 emulated_front_buffer_->size != emulated_back_buffer_->size) {
3833 emulated_front_buffer_->Destroy(true);
3834 emulated_front_buffer_ = nullptr;
3835 }
3836
3837 if (emulated_front_buffer_ == nullptr) {
3838 if (!available_color_textures_.empty()) {
3839 emulated_front_buffer_ = std::move(available_color_textures_.back());
3840 available_color_textures_.pop_back();
3841 } else {
3842 emulated_front_buffer_ = std::make_unique<EmulatedColorBuffer>(
3843 api(), emulated_default_framebuffer_format_);
3844 emulated_front_buffer_->Resize(emulated_back_buffer_->size);
3845 }
3846 }
3847
3848 DCHECK_EQ(emulated_front_buffer_->size, emulated_back_buffer_->size);
3849
3850 if (emulated_default_framebuffer_format_.samples > 0) {
3851 // Resolve the multisampled renderbuffer into the emulated_front_buffer_
3852 emulated_back_buffer_->Blit(emulated_front_buffer_.get());
3853 } else {
3854 DCHECK(emulated_back_buffer_->color_texture != nullptr);
3855 // If the offscreen buffer should be preserved, copy the old backbuffer
3856 // into the new one
3857 if (offscreen_target_buffer_preserved_) {
3858 emulated_back_buffer_->Blit(emulated_front_buffer_.get());
3859 }
3860
3861 // Swap the front and back buffer textures and update the framebuffer
3862 // attachment.
3863 std::unique_ptr<EmulatedColorBuffer> old_front_buffer =
3864 std::move(emulated_front_buffer_);
3865 emulated_front_buffer_ =
3866 emulated_back_buffer_->SetColorBuffer(std::move(old_front_buffer));
3867 }
3868
3869 return error::kNoError;
3870 }
3871
3872 client()->OnSwapBuffers(swap_id, flags);
3873 if (surface_->SupportsAsyncSwap()) {
3874 TRACE_EVENT_ASYNC_BEGIN0("gpu", "AsyncSwapBuffers", swap_id);
3875 surface_->SwapBuffersAsync(
3876 base::BindOnce(
3877 &GLES2DecoderPassthroughImpl::CheckSwapBuffersAsyncResult,
3878 weak_ptr_factory_.GetWeakPtr(), "SwapBuffers", swap_id),
3879 base::DoNothing());
3880 return error::kNoError;
3881 } else {
3882 return CheckSwapBuffersResult(surface_->SwapBuffers(base::DoNothing()),
3883 "SwapBuffers");
3884 }
3885 }
3886
DoGetMaxValueInBufferCHROMIUM(GLuint buffer_id,GLsizei count,GLenum type,GLuint offset,uint32_t * result)3887 error::Error GLES2DecoderPassthroughImpl::DoGetMaxValueInBufferCHROMIUM(
3888 GLuint buffer_id,
3889 GLsizei count,
3890 GLenum type,
3891 GLuint offset,
3892 uint32_t* result) {
3893 NOTIMPLEMENTED();
3894 return error::kNoError;
3895 }
3896
DoEnableFeatureCHROMIUM(const char * feature)3897 error::Error GLES2DecoderPassthroughImpl::DoEnableFeatureCHROMIUM(
3898 const char* feature) {
3899 NOTIMPLEMENTED();
3900 return error::kNoError;
3901 }
3902
DoMapBufferRange(GLenum target,GLintptr offset,GLsizeiptr size,GLbitfield access,void * ptr,int32_t data_shm_id,uint32_t data_shm_offset,uint32_t * result)3903 error::Error GLES2DecoderPassthroughImpl::DoMapBufferRange(
3904 GLenum target,
3905 GLintptr offset,
3906 GLsizeiptr size,
3907 GLbitfield access,
3908 void* ptr,
3909 int32_t data_shm_id,
3910 uint32_t data_shm_offset,
3911 uint32_t* result) {
3912 CheckErrorCallbackState();
3913
3914 GLbitfield filtered_access = access;
3915
3916 // Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of undefined
3917 // behaviors.
3918 filtered_access = (filtered_access & ~GL_MAP_UNSYNCHRONIZED_BIT);
3919
3920 if ((filtered_access & GL_MAP_INVALIDATE_BUFFER_BIT) != 0) {
3921 // To be on the safe side, always map GL_MAP_INVALIDATE_BUFFER_BIT to
3922 // GL_MAP_INVALIDATE_RANGE_BIT.
3923 filtered_access = (filtered_access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
3924 filtered_access = (filtered_access | GL_MAP_INVALIDATE_RANGE_BIT);
3925 }
3926 if ((filtered_access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
3927 // If this user intends to use this buffer without invalidating the data, we
3928 // need to also add GL_MAP_READ_BIT to preserve the original data when
3929 // copying it to shared memory.
3930 filtered_access = (filtered_access | GL_MAP_READ_BIT);
3931 }
3932
3933 void* mapped_ptr =
3934 api()->glMapBufferRangeFn(target, offset, size, filtered_access);
3935 if (CheckErrorCallbackState() || mapped_ptr == nullptr) {
3936 // Had an error while mapping, don't copy any data
3937 *result = 0;
3938 return error::kNoError;
3939 }
3940
3941 if ((filtered_access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
3942 memcpy(ptr, mapped_ptr, size);
3943 }
3944
3945 // Track the mapping of this buffer so that data can be synchronized when it
3946 // is unmapped
3947 DCHECK(bound_buffers_.find(target) != bound_buffers_.end());
3948 GLuint client_buffer = bound_buffers_.at(target);
3949
3950 MappedBuffer mapped_buffer_info;
3951 mapped_buffer_info.size = size;
3952 mapped_buffer_info.original_access = access;
3953 mapped_buffer_info.filtered_access = filtered_access;
3954 mapped_buffer_info.map_ptr = static_cast<uint8_t*>(mapped_ptr);
3955 mapped_buffer_info.data_shm_id = data_shm_id;
3956 mapped_buffer_info.data_shm_offset = data_shm_offset;
3957
3958 DCHECK(resources_->mapped_buffer_map.find(client_buffer) ==
3959 resources_->mapped_buffer_map.end());
3960 resources_->mapped_buffer_map.insert(
3961 std::make_pair(client_buffer, mapped_buffer_info));
3962
3963 *result = 1;
3964 return error::kNoError;
3965 }
3966
DoUnmapBuffer(GLenum target)3967 error::Error GLES2DecoderPassthroughImpl::DoUnmapBuffer(GLenum target) {
3968 auto bound_buffers_iter = bound_buffers_.find(target);
3969 if (bound_buffers_iter == bound_buffers_.end()) {
3970 InsertError(GL_INVALID_ENUM, "Invalid buffer target.");
3971 return error::kNoError;
3972 }
3973
3974 if (bound_buffers_iter->second == 0) {
3975 InsertError(GL_INVALID_OPERATION, "No buffer bound to this target.");
3976 return error::kNoError;
3977 }
3978
3979 GLuint client_buffer = bound_buffers_iter->second;
3980 auto mapped_buffer_info_iter =
3981 resources_->mapped_buffer_map.find(client_buffer);
3982 if (mapped_buffer_info_iter == resources_->mapped_buffer_map.end()) {
3983 InsertError(GL_INVALID_OPERATION, "Buffer is not mapped.");
3984 return error::kNoError;
3985 }
3986
3987 const MappedBuffer& map_info = mapped_buffer_info_iter->second;
3988 if ((map_info.filtered_access & GL_MAP_WRITE_BIT) != 0 &&
3989 (map_info.filtered_access & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
3990 uint8_t* mem = GetSharedMemoryAs<uint8_t*>(
3991 map_info.data_shm_id, map_info.data_shm_offset, map_info.size);
3992 if (!mem) {
3993 return error::kOutOfBounds;
3994 }
3995
3996 memcpy(map_info.map_ptr, mem, map_info.size);
3997 }
3998
3999 api()->glUnmapBufferFn(target);
4000
4001 resources_->mapped_buffer_map.erase(mapped_buffer_info_iter);
4002
4003 return error::kNoError;
4004 }
4005
DoResizeCHROMIUM(GLuint width,GLuint height,GLfloat scale_factor,gfx::ColorSpace color_space,GLboolean alpha)4006 error::Error GLES2DecoderPassthroughImpl::DoResizeCHROMIUM(
4007 GLuint width,
4008 GLuint height,
4009 GLfloat scale_factor,
4010 gfx::ColorSpace color_space,
4011 GLboolean alpha) {
4012 // gfx::Size uses integers, make sure width and height do not overflow
4013 static_assert(sizeof(GLuint) >= sizeof(int), "Unexpected GLuint size.");
4014 static const GLuint kMaxDimension =
4015 static_cast<GLuint>(std::numeric_limits<int>::max());
4016 gfx::Size safe_size(base::ClampToRange(width, 1U, kMaxDimension),
4017 base::ClampToRange(height, 1U, kMaxDimension));
4018 if (offscreen_) {
4019 if (!ResizeOffscreenFramebuffer(safe_size)) {
4020 LOG(ERROR) << "GLES2DecoderPassthroughImpl: Context lost because "
4021 << "ResizeOffscreenFramebuffer failed.";
4022 return error::kLostContext;
4023 }
4024 } else {
4025 if (!surface_->Resize(safe_size, scale_factor, color_space, !!alpha)) {
4026 LOG(ERROR)
4027 << "GLES2DecoderPassthroughImpl: Context lost because resize failed.";
4028 return error::kLostContext;
4029 }
4030 DCHECK(context_->IsCurrent(surface_.get()));
4031 if (!context_->IsCurrent(surface_.get())) {
4032 LOG(ERROR) << "GLES2DecoderPassthroughImpl: Context lost because context "
4033 "no longer current after resize callback.";
4034 return error::kLostContext;
4035 }
4036 }
4037 return error::kNoError;
4038 }
4039
DoGetRequestableExtensionsCHROMIUM(const char ** extensions)4040 error::Error GLES2DecoderPassthroughImpl::DoGetRequestableExtensionsCHROMIUM(
4041 const char** extensions) {
4042 *extensions = reinterpret_cast<const char*>(
4043 api()->glGetStringFn(GL_REQUESTABLE_EXTENSIONS_ANGLE));
4044 return error::kNoError;
4045 }
4046
DoRequestExtensionCHROMIUM(const char * extension)4047 error::Error GLES2DecoderPassthroughImpl::DoRequestExtensionCHROMIUM(
4048 const char* extension) {
4049 api()->glRequestExtensionANGLEFn(extension);
4050
4051 // Make sure there are no pending GL errors before re-initializing feature
4052 // info
4053 FlushErrors();
4054
4055 // Make sure newly enabled extensions are exposed and usable.
4056 context_->ReinitializeDynamicBindings();
4057 InitializeFeatureInfo(feature_info_->context_type(),
4058 feature_info_->disallowed_features(), true);
4059
4060 // Support for CHROMIUM_texture_storage_image depends on the underlying
4061 // ImageFactory's ability to create anonymous images.
4062 gpu::ImageFactory* image_factory = group_->image_factory();
4063 if (image_factory && image_factory->SupportsCreateAnonymousImage()) {
4064 feature_info_->EnableCHROMIUMTextureStorageImage();
4065 }
4066
4067 return error::kNoError;
4068 }
4069
DoGetProgramInfoCHROMIUM(GLuint program,std::vector<uint8_t> * data)4070 error::Error GLES2DecoderPassthroughImpl::DoGetProgramInfoCHROMIUM(
4071 GLuint program,
4072 std::vector<uint8_t>* data) {
4073 GLuint service_program = 0;
4074 if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
4075 return error::kNoError;
4076 }
4077
4078 GLint num_attributes = 0;
4079 api()->glGetProgramivFn(service_program, GL_ACTIVE_ATTRIBUTES,
4080 &num_attributes);
4081
4082 GLint num_uniforms = 0;
4083 api()->glGetProgramivFn(service_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
4084
4085 const base::CheckedNumeric<size_t> buffer_header_size(
4086 sizeof(ProgramInfoHeader));
4087 const base::CheckedNumeric<size_t> buffer_block_size(sizeof(ProgramInput));
4088 const base::CheckedNumeric<size_t> attribute_block_size =
4089 buffer_block_size * num_attributes;
4090 const base::CheckedNumeric<size_t> uniform_block_size =
4091 buffer_block_size * num_uniforms;
4092 data->resize((buffer_header_size + attribute_block_size + uniform_block_size)
4093 .ValueOrDie(),
4094 0);
4095
4096 GLint link_status = 0;
4097 api()->glGetProgramivFn(service_program, GL_LINK_STATUS, &link_status);
4098
4099 ProgramInfoHeader header;
4100 header.link_status = link_status;
4101 header.num_attribs = num_attributes;
4102 header.num_uniforms = num_uniforms;
4103 InsertValueIntoBuffer(data, header, 0);
4104
4105 GLint active_attribute_max_length = 0;
4106 api()->glGetProgramivFn(service_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
4107 &active_attribute_max_length);
4108
4109 std::vector<char> attrib_name_buf(active_attribute_max_length, 0);
4110 for (GLint attrib_index = 0; attrib_index < num_attributes; attrib_index++) {
4111 GLsizei length = 0;
4112 GLint size = 0;
4113 GLenum type = GL_NONE;
4114 api()->glGetActiveAttribFn(service_program, attrib_index,
4115 attrib_name_buf.size(), &length, &size, &type,
4116 attrib_name_buf.data());
4117
4118 ProgramInput input;
4119 input.size = size;
4120 input.type = type;
4121
4122 int32_t location =
4123 api()->glGetAttribLocationFn(service_program, attrib_name_buf.data());
4124 input.location_offset = data->size();
4125 AppendValueToBuffer(data, location);
4126
4127 input.name_offset = data->size();
4128 input.name_length = length;
4129 AppendStringToBuffer(data, attrib_name_buf.data(), length);
4130
4131 InsertValueIntoBuffer(
4132 data, input,
4133 (buffer_header_size + (buffer_block_size * attrib_index)).ValueOrDie());
4134 }
4135
4136 GLint active_uniform_max_length = 0;
4137 api()->glGetProgramivFn(service_program, GL_ACTIVE_UNIFORM_MAX_LENGTH,
4138 &active_uniform_max_length);
4139
4140 std::vector<char> uniform_name_buf(active_uniform_max_length, 0);
4141 for (GLint uniform_index = 0; uniform_index < num_uniforms; uniform_index++) {
4142 GLsizei length = 0;
4143 GLint size = 0;
4144 GLenum type = GL_NONE;
4145 api()->glGetActiveUniformFn(service_program, uniform_index,
4146 uniform_name_buf.size(), &length, &size, &type,
4147 uniform_name_buf.data());
4148
4149 ProgramInput input;
4150 input.size = size;
4151 input.type = type;
4152
4153 input.location_offset = data->size();
4154 int32_t base_location =
4155 api()->glGetUniformLocationFn(service_program, uniform_name_buf.data());
4156 AppendValueToBuffer(data, base_location);
4157
4158 GLSLArrayName parsed_service_name(uniform_name_buf.data());
4159 if (size > 1 || parsed_service_name.IsArrayName()) {
4160 for (GLint location_index = 1; location_index < size; location_index++) {
4161 std::string array_element_name = parsed_service_name.base_name() + "[" +
4162 base::NumberToString(location_index) +
4163 "]";
4164 int32_t element_location = api()->glGetUniformLocationFn(
4165 service_program, array_element_name.c_str());
4166 AppendValueToBuffer(data, element_location);
4167 }
4168 }
4169
4170 input.name_offset = data->size();
4171 input.name_length = length;
4172 AppendStringToBuffer(data, uniform_name_buf.data(), length);
4173
4174 InsertValueIntoBuffer(data, input,
4175 (buffer_header_size + attribute_block_size +
4176 (buffer_block_size * uniform_index))
4177 .ValueOrDie());
4178 }
4179
4180 return error::kNoError;
4181 }
4182
DoGetUniformBlocksCHROMIUM(GLuint program,std::vector<uint8_t> * data)4183 error::Error GLES2DecoderPassthroughImpl::DoGetUniformBlocksCHROMIUM(
4184 GLuint program,
4185 std::vector<uint8_t>* data) {
4186 GLuint service_program = 0;
4187 if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
4188 return error::kNoError;
4189 }
4190
4191 GLint num_uniform_blocks = 0;
4192 api()->glGetProgramivFn(service_program, GL_ACTIVE_UNIFORM_BLOCKS,
4193 &num_uniform_blocks);
4194
4195 // Resize the data to fit the headers and info objects so that strings can be
4196 // appended.
4197 const base::CheckedNumeric<size_t> buffer_header_size(
4198 sizeof(UniformBlocksHeader));
4199 const base::CheckedNumeric<size_t> buffer_block_size(
4200 sizeof(UniformBlockInfo));
4201 data->resize((buffer_header_size + (num_uniform_blocks * buffer_block_size))
4202 .ValueOrDie(),
4203 0);
4204
4205 UniformBlocksHeader header;
4206 header.num_uniform_blocks = num_uniform_blocks;
4207 InsertValueIntoBuffer(data, header, 0);
4208
4209 GLint active_uniform_block_max_length = 0;
4210 api()->glGetProgramivFn(service_program,
4211 GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
4212 &active_uniform_block_max_length);
4213
4214 std::vector<char> uniform_block_name_buf(active_uniform_block_max_length, 0);
4215 for (GLint uniform_block_index = 0; uniform_block_index < num_uniform_blocks;
4216 uniform_block_index++) {
4217 UniformBlockInfo block_info;
4218
4219 GLint uniform_block_binding = 0;
4220 api()->glGetActiveUniformBlockivFn(service_program, uniform_block_index,
4221 GL_UNIFORM_BLOCK_BINDING,
4222 &uniform_block_binding);
4223 block_info.binding = uniform_block_binding;
4224
4225 GLint uniform_block_data_size = 0;
4226 api()->glGetActiveUniformBlockivFn(service_program, uniform_block_index,
4227 GL_UNIFORM_BLOCK_DATA_SIZE,
4228 &uniform_block_data_size);
4229 block_info.data_size = uniform_block_data_size;
4230
4231 GLint uniform_block_name_length = 0;
4232 api()->glGetActiveUniformBlockNameFn(
4233 service_program, uniform_block_index, active_uniform_block_max_length,
4234 &uniform_block_name_length, uniform_block_name_buf.data());
4235
4236 DCHECK(uniform_block_name_length + 1 <= active_uniform_block_max_length);
4237 block_info.name_offset = data->size();
4238 block_info.name_length = uniform_block_name_length + 1;
4239 AppendStringToBuffer(data, uniform_block_name_buf.data(),
4240 uniform_block_name_length + 1);
4241
4242 GLint uniform_block_active_uniforms = 0;
4243 api()->glGetActiveUniformBlockivFn(service_program, uniform_block_index,
4244 GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
4245 &uniform_block_active_uniforms);
4246 block_info.active_uniforms = uniform_block_active_uniforms;
4247
4248 std::vector<GLint> uniform_block_indices_buf(uniform_block_active_uniforms,
4249 0);
4250 api()->glGetActiveUniformBlockivFn(service_program, uniform_block_index,
4251 GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
4252 uniform_block_indices_buf.data());
4253 block_info.active_uniform_offset = data->size();
4254 for (GLint uniform_block_uniform_index_index = 0;
4255 uniform_block_uniform_index_index < uniform_block_active_uniforms;
4256 uniform_block_uniform_index_index++) {
4257 AppendValueToBuffer(
4258 data,
4259 static_cast<uint32_t>(
4260 uniform_block_indices_buf[uniform_block_uniform_index_index]));
4261 }
4262
4263 GLint uniform_block_referenced_by_vertex_shader = 0;
4264 api()->glGetActiveUniformBlockivFn(
4265 service_program, uniform_block_index,
4266 GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
4267 &uniform_block_referenced_by_vertex_shader);
4268 block_info.referenced_by_vertex_shader =
4269 uniform_block_referenced_by_vertex_shader;
4270
4271 GLint uniform_block_referenced_by_fragment_shader = 0;
4272 api()->glGetActiveUniformBlockivFn(
4273 service_program, uniform_block_index,
4274 GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
4275 &uniform_block_referenced_by_fragment_shader);
4276 block_info.referenced_by_fragment_shader =
4277 uniform_block_referenced_by_fragment_shader;
4278
4279 InsertValueIntoBuffer(
4280 data, block_info,
4281 (buffer_header_size + (buffer_block_size * uniform_block_index))
4282 .ValueOrDie());
4283 }
4284
4285 return error::kNoError;
4286 }
4287
4288 error::Error
DoGetTransformFeedbackVaryingsCHROMIUM(GLuint program,std::vector<uint8_t> * data)4289 GLES2DecoderPassthroughImpl::DoGetTransformFeedbackVaryingsCHROMIUM(
4290 GLuint program,
4291 std::vector<uint8_t>* data) {
4292 GLuint service_program = 0;
4293 if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
4294 return error::kNoError;
4295 }
4296
4297 GLint transform_feedback_buffer_mode = 0;
4298 api()->glGetProgramivFn(service_program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE,
4299 &transform_feedback_buffer_mode);
4300
4301 GLint num_transform_feedback_varyings = 0;
4302 api()->glGetProgramivFn(service_program, GL_TRANSFORM_FEEDBACK_VARYINGS,
4303 &num_transform_feedback_varyings);
4304
4305 // Resize the data to fit the headers and info objects so that strings can be
4306 // appended.
4307 const base::CheckedNumeric<size_t> buffer_header_size(
4308 sizeof(TransformFeedbackVaryingsHeader));
4309 const base::CheckedNumeric<size_t> buffer_block_size(
4310 sizeof(TransformFeedbackVaryingInfo));
4311 data->resize((buffer_header_size +
4312 (num_transform_feedback_varyings * buffer_block_size))
4313 .ValueOrDie(),
4314 0);
4315
4316 TransformFeedbackVaryingsHeader header;
4317 header.transform_feedback_buffer_mode = transform_feedback_buffer_mode;
4318 header.num_transform_feedback_varyings = num_transform_feedback_varyings;
4319 InsertValueIntoBuffer(data, header, 0);
4320
4321 GLint max_transform_feedback_varying_length = 0;
4322 api()->glGetProgramivFn(service_program,
4323 GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
4324 &max_transform_feedback_varying_length);
4325
4326 std::vector<char> transform_feedback_varying_name_buf(
4327 max_transform_feedback_varying_length, 0);
4328 for (GLint transform_feedback_varying_index = 0;
4329 transform_feedback_varying_index < num_transform_feedback_varyings;
4330 transform_feedback_varying_index++) {
4331 GLsizei length = 0;
4332 GLint size = 0;
4333 GLenum type = GL_NONE;
4334 api()->glGetTransformFeedbackVaryingFn(
4335 service_program, transform_feedback_varying_index,
4336 max_transform_feedback_varying_length, &length, &size, &type,
4337 transform_feedback_varying_name_buf.data());
4338
4339 TransformFeedbackVaryingInfo varying_info;
4340 varying_info.size = size;
4341 varying_info.type = type;
4342
4343 DCHECK(length + 1 <= max_transform_feedback_varying_length);
4344 varying_info.name_length = data->size();
4345 varying_info.name_length = length + 1;
4346 AppendStringToBuffer(data, transform_feedback_varying_name_buf.data(),
4347 length + 1);
4348
4349 InsertValueIntoBuffer(
4350 data, varying_info,
4351 (buffer_header_size +
4352 (buffer_block_size * transform_feedback_varying_index))
4353 .ValueOrDie());
4354 }
4355
4356 return error::kNoError;
4357 }
4358
DoGetUniformsES3CHROMIUM(GLuint program,std::vector<uint8_t> * data)4359 error::Error GLES2DecoderPassthroughImpl::DoGetUniformsES3CHROMIUM(
4360 GLuint program,
4361 std::vector<uint8_t>* data) {
4362 GLuint service_program = 0;
4363 if (!resources_->program_id_map.GetServiceID(program, &service_program)) {
4364 return error::kNoError;
4365 }
4366
4367 GLint num_uniforms = 0;
4368 api()->glGetProgramivFn(service_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
4369
4370 UniformsES3Header header;
4371 header.num_uniforms = num_uniforms;
4372 AppendValueToBuffer(data, header);
4373
4374 for (GLuint uniform_index = 0;
4375 uniform_index < static_cast<GLuint>(num_uniforms); uniform_index++) {
4376 UniformES3Info uniform_info;
4377
4378 GLint uniform_block_index = 0;
4379 api()->glGetActiveUniformsivFn(service_program, 1, &uniform_index,
4380 GL_UNIFORM_BLOCK_INDEX,
4381 &uniform_block_index);
4382 uniform_info.block_index = uniform_block_index;
4383
4384 GLint uniform_offset = 0;
4385 api()->glGetActiveUniformsivFn(service_program, 1, &uniform_index,
4386 GL_UNIFORM_OFFSET, &uniform_offset);
4387 uniform_info.offset = uniform_offset;
4388
4389 GLint uniform_array_stride = 0;
4390 api()->glGetActiveUniformsivFn(service_program, 1, &uniform_index,
4391 GL_UNIFORM_ARRAY_STRIDE,
4392 &uniform_array_stride);
4393 uniform_info.array_stride = uniform_array_stride;
4394
4395 GLint uniform_matrix_stride = 0;
4396 api()->glGetActiveUniformsivFn(service_program, 1, &uniform_index,
4397 GL_UNIFORM_MATRIX_STRIDE,
4398 &uniform_matrix_stride);
4399 uniform_info.matrix_stride = uniform_matrix_stride;
4400
4401 GLint uniform_is_row_major = 0;
4402 api()->glGetActiveUniformsivFn(service_program, 1, &uniform_index,
4403 GL_UNIFORM_IS_ROW_MAJOR,
4404 &uniform_is_row_major);
4405 uniform_info.is_row_major = uniform_is_row_major;
4406
4407 AppendValueToBuffer(data, uniform_info);
4408 }
4409
4410 return error::kNoError;
4411 }
4412
DoGetTranslatedShaderSourceANGLE(GLuint shader,std::string * source)4413 error::Error GLES2DecoderPassthroughImpl::DoGetTranslatedShaderSourceANGLE(
4414 GLuint shader,
4415 std::string* source) {
4416 CheckErrorCallbackState();
4417 GLuint service_id = GetShaderServiceID(shader, resources_);
4418 GLint translated_source_length = 0;
4419 api()->glGetShaderivFn(service_id, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
4420 &translated_source_length);
4421 if (CheckErrorCallbackState()) {
4422 return error::kNoError;
4423 }
4424
4425 if (translated_source_length > 0) {
4426 std::vector<char> buffer(translated_source_length, 0);
4427 GLsizei length = 0;
4428 api()->glGetTranslatedShaderSourceANGLEFn(
4429 service_id, translated_source_length, &length, buffer.data());
4430 DCHECK(length <= translated_source_length);
4431 *source = length > 0 ? std::string(buffer.data(), length) : std::string();
4432 } else {
4433 *source = std::string();
4434 }
4435 return error::kNoError;
4436 }
4437
DoSwapBuffersWithBoundsCHROMIUM(uint64_t swap_id,GLsizei count,const volatile GLint * rects,GLbitfield flags)4438 error::Error GLES2DecoderPassthroughImpl::DoSwapBuffersWithBoundsCHROMIUM(
4439 uint64_t swap_id,
4440 GLsizei count,
4441 const volatile GLint* rects,
4442 GLbitfield flags) {
4443 if (count < 0) {
4444 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
4445 return error::kNoError;
4446 }
4447
4448 ca_layer_shared_state_ = nullptr;
4449
4450 std::vector<gfx::Rect> bounds(count);
4451 for (GLsizei i = 0; i < count; ++i) {
4452 bounds[i] = gfx::Rect(rects[i * 4 + 0], rects[i * 4 + 1], rects[i * 4 + 2],
4453 rects[i * 4 + 3]);
4454 }
4455
4456 client()->OnSwapBuffers(swap_id, flags);
4457 return CheckSwapBuffersResult(
4458 surface_->SwapBuffersWithBounds(bounds, base::DoNothing()),
4459 "SwapBuffersWithBounds");
4460 }
4461
DoPostSubBufferCHROMIUM(uint64_t swap_id,GLint x,GLint y,GLint width,GLint height,GLbitfield flags)4462 error::Error GLES2DecoderPassthroughImpl::DoPostSubBufferCHROMIUM(
4463 uint64_t swap_id,
4464 GLint x,
4465 GLint y,
4466 GLint width,
4467 GLint height,
4468 GLbitfield flags) {
4469 if (!surface_->SupportsPostSubBuffer()) {
4470 InsertError(GL_INVALID_OPERATION,
4471 "glPostSubBufferCHROMIUM is not supported for this surface.");
4472 return error::kNoError;
4473 }
4474
4475 ca_layer_shared_state_ = nullptr;
4476
4477 client()->OnSwapBuffers(swap_id, flags);
4478 if (surface_->SupportsAsyncSwap()) {
4479 TRACE_EVENT_ASYNC_BEGIN0("gpu", "AsyncSwapBuffers", swap_id);
4480 surface_->PostSubBufferAsync(
4481 x, y, width, height,
4482 base::BindOnce(
4483 &GLES2DecoderPassthroughImpl::CheckSwapBuffersAsyncResult,
4484 weak_ptr_factory_.GetWeakPtr(), "PostSubBuffer", swap_id),
4485 base::DoNothing());
4486 return error::kNoError;
4487 } else {
4488 return CheckSwapBuffersResult(
4489 surface_->PostSubBuffer(x, y, width, height, base::DoNothing()),
4490 "PostSubBuffer");
4491 }
4492 }
4493
DoCopyTextureCHROMIUM(GLuint source_id,GLint source_level,GLenum dest_target,GLuint dest_id,GLint dest_level,GLint internalformat,GLenum dest_type,GLboolean unpack_flip_y,GLboolean unpack_premultiply_alpha,GLboolean unpack_unmultiply_alpha)4494 error::Error GLES2DecoderPassthroughImpl::DoCopyTextureCHROMIUM(
4495 GLuint source_id,
4496 GLint source_level,
4497 GLenum dest_target,
4498 GLuint dest_id,
4499 GLint dest_level,
4500 GLint internalformat,
4501 GLenum dest_type,
4502 GLboolean unpack_flip_y,
4503 GLboolean unpack_premultiply_alpha,
4504 GLboolean unpack_unmultiply_alpha) {
4505 ScopedEnableTextureRectangleInShaderCompiler enable(this);
4506 BindPendingImageForClientIDIfNeeded(source_id);
4507 api()->glCopyTextureCHROMIUMFn(
4508 GetTextureServiceID(api(), source_id, resources_, false), source_level,
4509 dest_target, GetTextureServiceID(api(), dest_id, resources_, false),
4510 dest_level, internalformat, dest_type, unpack_flip_y,
4511 unpack_premultiply_alpha, unpack_unmultiply_alpha);
4512
4513 UpdateTextureSizeFromClientID(dest_id);
4514
4515 return error::kNoError;
4516 }
4517
DoCopySubTextureCHROMIUM(GLuint source_id,GLint source_level,GLenum dest_target,GLuint dest_id,GLint dest_level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLboolean unpack_flip_y,GLboolean unpack_premultiply_alpha,GLboolean unpack_unmultiply_alpha)4518 error::Error GLES2DecoderPassthroughImpl::DoCopySubTextureCHROMIUM(
4519 GLuint source_id,
4520 GLint source_level,
4521 GLenum dest_target,
4522 GLuint dest_id,
4523 GLint dest_level,
4524 GLint xoffset,
4525 GLint yoffset,
4526 GLint x,
4527 GLint y,
4528 GLsizei width,
4529 GLsizei height,
4530 GLboolean unpack_flip_y,
4531 GLboolean unpack_premultiply_alpha,
4532 GLboolean unpack_unmultiply_alpha) {
4533 ScopedEnableTextureRectangleInShaderCompiler enable(this);
4534 BindPendingImageForClientIDIfNeeded(source_id);
4535 api()->glCopySubTextureCHROMIUMFn(
4536 GetTextureServiceID(api(), source_id, resources_, false), source_level,
4537 dest_target, GetTextureServiceID(api(), dest_id, resources_, false),
4538 dest_level, xoffset, yoffset, x, y, width, height, unpack_flip_y,
4539 unpack_premultiply_alpha, unpack_unmultiply_alpha);
4540 return error::kNoError;
4541 }
4542
DoDrawArraysInstancedANGLE(GLenum mode,GLint first,GLsizei count,GLsizei primcount)4543 error::Error GLES2DecoderPassthroughImpl::DoDrawArraysInstancedANGLE(
4544 GLenum mode,
4545 GLint first,
4546 GLsizei count,
4547 GLsizei primcount) {
4548 BindPendingImagesForSamplersIfNeeded();
4549 api()->glDrawArraysInstancedANGLEFn(mode, first, count, primcount);
4550 return error::kNoError;
4551 }
4552
4553 error::Error
DoDrawArraysInstancedBaseInstanceANGLE(GLenum mode,GLint first,GLsizei count,GLsizei primcount,GLuint baseinstance)4554 GLES2DecoderPassthroughImpl::DoDrawArraysInstancedBaseInstanceANGLE(
4555 GLenum mode,
4556 GLint first,
4557 GLsizei count,
4558 GLsizei primcount,
4559 GLuint baseinstance) {
4560 BindPendingImagesForSamplersIfNeeded();
4561 api()->glDrawArraysInstancedBaseInstanceANGLEFn(mode, first, count, primcount,
4562 baseinstance);
4563 return error::kNoError;
4564 }
4565
DoDrawElementsInstancedANGLE(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount)4566 error::Error GLES2DecoderPassthroughImpl::DoDrawElementsInstancedANGLE(
4567 GLenum mode,
4568 GLsizei count,
4569 GLenum type,
4570 const void* indices,
4571 GLsizei primcount) {
4572 BindPendingImagesForSamplersIfNeeded();
4573 api()->glDrawElementsInstancedANGLEFn(mode, count, type, indices, primcount);
4574 return error::kNoError;
4575 }
4576
4577 error::Error
DoDrawElementsInstancedBaseVertexBaseInstanceANGLE(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount,GLint basevertex,GLuint baseinstance)4578 GLES2DecoderPassthroughImpl::DoDrawElementsInstancedBaseVertexBaseInstanceANGLE(
4579 GLenum mode,
4580 GLsizei count,
4581 GLenum type,
4582 const void* indices,
4583 GLsizei primcount,
4584 GLint basevertex,
4585 GLuint baseinstance) {
4586 BindPendingImagesForSamplersIfNeeded();
4587 api()->glDrawElementsInstancedBaseVertexBaseInstanceANGLEFn(
4588 mode, count, type, indices, primcount, basevertex, baseinstance);
4589 return error::kNoError;
4590 }
4591
DoVertexAttribDivisorANGLE(GLuint index,GLuint divisor)4592 error::Error GLES2DecoderPassthroughImpl::DoVertexAttribDivisorANGLE(
4593 GLuint index,
4594 GLuint divisor) {
4595 api()->glVertexAttribDivisorANGLEFn(index, divisor);
4596 return error::kNoError;
4597 }
4598
DoProduceTextureDirectCHROMIUM(GLuint texture_client_id,const volatile GLbyte * mailbox)4599 error::Error GLES2DecoderPassthroughImpl::DoProduceTextureDirectCHROMIUM(
4600 GLuint texture_client_id,
4601 const volatile GLbyte* mailbox) {
4602 scoped_refptr<TexturePassthrough> texture = nullptr;
4603 if (!resources_->texture_object_map.GetServiceID(texture_client_id,
4604 &texture) ||
4605 texture == nullptr) {
4606 InsertError(GL_INVALID_OPERATION, "Unknown texture.");
4607 return error::kNoError;
4608 }
4609
4610 const Mailbox& mb = Mailbox::FromVolatile(
4611 *reinterpret_cast<const volatile Mailbox*>(mailbox));
4612 mailbox_manager_->ProduceTexture(mb, texture.get());
4613 return error::kNoError;
4614 }
4615
DoCreateAndConsumeTextureINTERNAL(GLuint texture_client_id,const volatile GLbyte * mailbox)4616 error::Error GLES2DecoderPassthroughImpl::DoCreateAndConsumeTextureINTERNAL(
4617 GLuint texture_client_id,
4618 const volatile GLbyte* mailbox) {
4619 if (!texture_client_id ||
4620 resources_->texture_id_map.HasClientID(texture_client_id)) {
4621 return error::kInvalidArguments;
4622 }
4623
4624 const Mailbox& mb = Mailbox::FromVolatile(
4625 *reinterpret_cast<const volatile Mailbox*>(mailbox));
4626 scoped_refptr<TexturePassthrough> texture = TexturePassthrough::CheckedCast(
4627 group_->mailbox_manager()->ConsumeTexture(mb));
4628 if (texture == nullptr) {
4629 // Create texture to handle invalid mailbox (see http://crbug.com/472465 and
4630 // http://crbug.com/851878).
4631 DoGenTextures(1, &texture_client_id);
4632 InsertError(GL_INVALID_OPERATION, "Invalid mailbox name.");
4633 return error::kNoError;
4634 }
4635
4636 // Update id mappings
4637 resources_->texture_id_map.RemoveClientID(texture_client_id);
4638 resources_->texture_id_map.SetIDMapping(texture_client_id,
4639 texture->service_id());
4640 resources_->texture_object_map.RemoveClientID(texture_client_id);
4641 resources_->texture_object_map.SetIDMapping(texture_client_id, texture);
4642
4643 return error::kNoError;
4644 }
4645
DoBindUniformLocationCHROMIUM(GLuint program,GLint location,const char * name)4646 error::Error GLES2DecoderPassthroughImpl::DoBindUniformLocationCHROMIUM(
4647 GLuint program,
4648 GLint location,
4649 const char* name) {
4650 api()->glBindUniformLocationCHROMIUMFn(
4651 GetProgramServiceID(program, resources_), location, name);
4652 return error::kNoError;
4653 }
4654
DoBindTexImage2DCHROMIUM(GLenum target,GLint imageId)4655 error::Error GLES2DecoderPassthroughImpl::DoBindTexImage2DCHROMIUM(
4656 GLenum target,
4657 GLint imageId) {
4658 return BindTexImage2DCHROMIUMImpl(target, 0, imageId);
4659 }
4660
4661 error::Error
DoBindTexImage2DWithInternalformatCHROMIUM(GLenum target,GLenum internalformat,GLint imageId)4662 GLES2DecoderPassthroughImpl::DoBindTexImage2DWithInternalformatCHROMIUM(
4663 GLenum target,
4664 GLenum internalformat,
4665 GLint imageId) {
4666 return BindTexImage2DCHROMIUMImpl(target, internalformat, imageId);
4667 }
4668
DoReleaseTexImage2DCHROMIUM(GLenum target,GLint imageId)4669 error::Error GLES2DecoderPassthroughImpl::DoReleaseTexImage2DCHROMIUM(
4670 GLenum target,
4671 GLint imageId) {
4672 TextureTarget target_enum = GLenumToTextureTarget(target);
4673 if (target_enum == TextureTarget::kCubeMap ||
4674 target_enum == TextureTarget::kUnkown) {
4675 InsertError(GL_INVALID_ENUM, "Invalid target");
4676 return error::kNoError;
4677 }
4678
4679 const BoundTexture& bound_texture =
4680 bound_textures_[static_cast<size_t>(target_enum)][active_texture_unit_];
4681 if (bound_texture.texture == nullptr) {
4682 InsertError(GL_INVALID_OPERATION, "No texture bound");
4683 return error::kNoError;
4684 }
4685
4686 gl::GLImage* image = group_->image_manager()->LookupImage(imageId);
4687 if (image == nullptr) {
4688 InsertError(GL_INVALID_OPERATION, "No image found with the given ID");
4689 return error::kNoError;
4690 }
4691
4692 // Only release the image if it is currently bound
4693 if (bound_texture.texture->GetLevelImage(target, 0) == image) {
4694 image->ReleaseTexImage(target);
4695 bound_texture.texture->SetLevelImage(target, 0, nullptr);
4696 }
4697
4698 // Target is already validated
4699 UpdateTextureSizeFromTarget(target);
4700
4701 return error::kNoError;
4702 }
4703
DoTraceBeginCHROMIUM(const char * category_name,const char * trace_name)4704 error::Error GLES2DecoderPassthroughImpl::DoTraceBeginCHROMIUM(
4705 const char* category_name,
4706 const char* trace_name) {
4707 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
4708 InsertError(GL_INVALID_OPERATION, "Failed to create begin trace");
4709 return error::kNoError;
4710 }
4711 debug_marker_manager_.PushGroup(trace_name);
4712 return error::kNoError;
4713 }
4714
DoTraceEndCHROMIUM()4715 error::Error GLES2DecoderPassthroughImpl::DoTraceEndCHROMIUM() {
4716 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
4717 InsertError(GL_INVALID_OPERATION, "No trace to end");
4718 return error::kNoError;
4719 }
4720 debug_marker_manager_.PopGroup();
4721 return error::kNoError;
4722 }
4723
DoDiscardFramebufferEXT(GLenum target,GLsizei count,const volatile GLenum * attachments)4724 error::Error GLES2DecoderPassthroughImpl::DoDiscardFramebufferEXT(
4725 GLenum target,
4726 GLsizei count,
4727 const volatile GLenum* attachments) {
4728 // Validate that count is non-negative before allocating a vector
4729 if (count < 0) {
4730 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
4731 return error::kNoError;
4732 }
4733 std::vector<GLenum> attachments_copy(attachments, attachments + count);
4734
4735 if (feature_info_->gl_version_info().is_es3) {
4736 api()->glInvalidateFramebufferFn(target, count, attachments_copy.data());
4737 } else {
4738 api()->glDiscardFramebufferEXTFn(target, count, attachments_copy.data());
4739 }
4740
4741 return error::kNoError;
4742 }
4743
DoLoseContextCHROMIUM(GLenum current,GLenum other)4744 error::Error GLES2DecoderPassthroughImpl::DoLoseContextCHROMIUM(GLenum current,
4745 GLenum other) {
4746 if (!ValidContextLostReason(current) || !ValidContextLostReason(other)) {
4747 InsertError(GL_INVALID_ENUM, "invalid context loss reason.");
4748 return error::kNoError;
4749 }
4750
4751 MarkContextLost(GetContextLostReasonFromResetStatus(current));
4752 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
4753 reset_by_robustness_extension_ = true;
4754 return error::kNoError;
4755 }
4756
DoDescheduleUntilFinishedCHROMIUM()4757 error::Error GLES2DecoderPassthroughImpl::DoDescheduleUntilFinishedCHROMIUM() {
4758 if (!gl::GLFence::IsSupported()) {
4759 return error::kNoError;
4760 }
4761 deschedule_until_finished_fences_.push_back(gl::GLFence::Create());
4762
4763 if (deschedule_until_finished_fences_.size() == 1) {
4764 return error::kNoError;
4765 }
4766
4767 DCHECK_EQ(2u, deschedule_until_finished_fences_.size());
4768 if (deschedule_until_finished_fences_[0]->HasCompleted()) {
4769 deschedule_until_finished_fences_.erase(
4770 deschedule_until_finished_fences_.begin());
4771 return error::kNoError;
4772 }
4773
4774 TRACE_EVENT_ASYNC_BEGIN0(
4775 "cc", "GLES2DecoderPassthroughImpl::DescheduleUntilFinished", this);
4776 client()->OnDescheduleUntilFinished();
4777 return error::kDeferLaterCommands;
4778 }
4779
DoDrawBuffersEXT(GLsizei count,const volatile GLenum * bufs)4780 error::Error GLES2DecoderPassthroughImpl::DoDrawBuffersEXT(
4781 GLsizei count,
4782 const volatile GLenum* bufs) {
4783 if (!feature_info_->feature_flags().ext_draw_buffers &&
4784 !feature_info_->gl_version_info().is_es3) {
4785 return error::kUnknownCommand;
4786 }
4787
4788 // Validate that count is non-negative before allocating a vector
4789 if (count < 0) {
4790 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
4791 return error::kNoError;
4792 }
4793 std::vector<GLenum> bufs_copy(bufs, bufs + count);
4794 api()->glDrawBuffersARBFn(count, bufs_copy.data());
4795 return error::kNoError;
4796 }
4797
DoDiscardBackbufferCHROMIUM()4798 error::Error GLES2DecoderPassthroughImpl::DoDiscardBackbufferCHROMIUM() {
4799 NOTIMPLEMENTED();
4800 return error::kNoError;
4801 }
4802
DoScheduleOverlayPlaneCHROMIUM(GLint plane_z_order,GLenum plane_transform,GLuint overlay_texture_id,GLint bounds_x,GLint bounds_y,GLint bounds_width,GLint bounds_height,GLfloat uv_x,GLfloat uv_y,GLfloat uv_width,GLfloat uv_height,bool enable_blend,GLuint gpu_fence_id)4803 error::Error GLES2DecoderPassthroughImpl::DoScheduleOverlayPlaneCHROMIUM(
4804 GLint plane_z_order,
4805 GLenum plane_transform,
4806 GLuint overlay_texture_id,
4807 GLint bounds_x,
4808 GLint bounds_y,
4809 GLint bounds_width,
4810 GLint bounds_height,
4811 GLfloat uv_x,
4812 GLfloat uv_y,
4813 GLfloat uv_width,
4814 GLfloat uv_height,
4815 bool enable_blend,
4816 GLuint gpu_fence_id) {
4817 scoped_refptr<TexturePassthrough> passthrough_texture = nullptr;
4818 if (!resources_->texture_object_map.GetServiceID(overlay_texture_id,
4819 &passthrough_texture) ||
4820 passthrough_texture == nullptr) {
4821 InsertError(GL_INVALID_VALUE, "invalid texture id");
4822 return error::kNoError;
4823 }
4824
4825 gl::GLImage* image =
4826 passthrough_texture->GetLevelImage(passthrough_texture->target(), 0);
4827 if (!image) {
4828 InsertError(GL_INVALID_VALUE, "texture has no image");
4829 return error::kNoError;
4830 }
4831
4832 gfx::OverlayTransform transform = GetGFXOverlayTransform(plane_transform);
4833 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
4834 InsertError(GL_INVALID_ENUM, "invalid transform enum");
4835 return error::kNoError;
4836 }
4837
4838 std::unique_ptr<gfx::GpuFence> gpu_fence;
4839 if (gpu_fence_id != 0) {
4840 gpu_fence = GetGpuFenceManager()->GetGpuFence(gpu_fence_id);
4841 if (!gpu_fence) {
4842 InsertError(GL_INVALID_ENUM, "unknown fence");
4843 return error::kNoError;
4844 }
4845 }
4846
4847 if (!surface_->ScheduleOverlayPlane(
4848 plane_z_order, transform, image,
4849 gfx::Rect(bounds_x, bounds_y, bounds_width, bounds_height),
4850 gfx::RectF(uv_x, uv_y, uv_width, uv_height), enable_blend,
4851 std::move(gpu_fence))) {
4852 InsertError(GL_INVALID_OPERATION, "failed to schedule overlay");
4853 return error::kNoError;
4854 }
4855
4856 return error::kNoError;
4857 }
4858
DoScheduleCALayerSharedStateCHROMIUM(GLfloat opacity,GLboolean is_clipped,const GLfloat * clip_rect,const GLfloat * rounded_corner_bounds,GLint sorting_context_id,const GLfloat * transform)4859 error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerSharedStateCHROMIUM(
4860 GLfloat opacity,
4861 GLboolean is_clipped,
4862 const GLfloat* clip_rect,
4863 const GLfloat* rounded_corner_bounds,
4864 GLint sorting_context_id,
4865 const GLfloat* transform) {
4866 if (!ca_layer_shared_state_) {
4867 ca_layer_shared_state_.reset(new CALayerSharedState);
4868 }
4869
4870 ca_layer_shared_state_->opacity = opacity;
4871 ca_layer_shared_state_->is_clipped = is_clipped;
4872 ca_layer_shared_state_->clip_rect = gfx::ToEnclosingRect(
4873 gfx::RectF(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]));
4874
4875 ca_layer_shared_state_->rounded_corner_bounds =
4876 gfx::RRectF(rounded_corner_bounds[0], rounded_corner_bounds[1],
4877 rounded_corner_bounds[2], rounded_corner_bounds[3],
4878 rounded_corner_bounds[4]);
4879 ca_layer_shared_state_->sorting_context_id = sorting_context_id;
4880 ca_layer_shared_state_->transform =
4881 gfx::Transform(transform[0], transform[4], transform[8], transform[12],
4882 transform[1], transform[5], transform[9], transform[13],
4883 transform[2], transform[6], transform[10], transform[14],
4884 transform[3], transform[7], transform[11], transform[15]);
4885 return error::kNoError;
4886 }
4887
DoScheduleCALayerCHROMIUM(GLuint contents_texture_id,const GLfloat * contents_rect,GLuint background_color,GLuint edge_aa_mask,GLenum filter,const GLfloat * bounds_rect)4888 error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerCHROMIUM(
4889 GLuint contents_texture_id,
4890 const GLfloat* contents_rect,
4891 GLuint background_color,
4892 GLuint edge_aa_mask,
4893 GLenum filter,
4894 const GLfloat* bounds_rect) {
4895 if (!ca_layer_shared_state_) {
4896 InsertError(GL_INVALID_OPERATION,
4897 "glScheduleCALayerSharedStateCHROMIUM has not been called");
4898 return error::kNoError;
4899 }
4900
4901 gl::GLImage* image = nullptr;
4902 if (contents_texture_id) {
4903 scoped_refptr<TexturePassthrough> passthrough_texture;
4904 if (!resources_->texture_object_map.GetServiceID(contents_texture_id,
4905 &passthrough_texture) ||
4906 passthrough_texture == nullptr) {
4907 InsertError(GL_INVALID_VALUE, "unknown texture");
4908 return error::kNoError;
4909 }
4910 DCHECK(passthrough_texture);
4911 image =
4912 passthrough_texture->GetLevelImage(passthrough_texture->target(), 0);
4913 if (!image) {
4914 InsertError(GL_INVALID_VALUE, "unsupported texture format");
4915 return error::kNoError;
4916 }
4917 }
4918
4919 ui::CARendererLayerParams params = ui::CARendererLayerParams(
4920 ca_layer_shared_state_->is_clipped, ca_layer_shared_state_->clip_rect,
4921 ca_layer_shared_state_->rounded_corner_bounds,
4922 ca_layer_shared_state_->sorting_context_id,
4923 ca_layer_shared_state_->transform, image,
4924 gfx::RectF(contents_rect[0], contents_rect[1], contents_rect[2],
4925 contents_rect[3]),
4926 gfx::ToEnclosingRect(gfx::RectF(bounds_rect[0], bounds_rect[1],
4927 bounds_rect[2], bounds_rect[3])),
4928 background_color, edge_aa_mask, ca_layer_shared_state_->opacity, filter);
4929 if (!surface_->ScheduleCALayer(params)) {
4930 InsertError(GL_INVALID_OPERATION, "failed to schedule CALayer");
4931 return error::kNoError;
4932 }
4933
4934 return error::kNoError;
4935 }
4936
DoScheduleCALayerInUseQueryCHROMIUM(GLsizei n,const volatile GLuint * textures)4937 error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerInUseQueryCHROMIUM(
4938 GLsizei n,
4939 const volatile GLuint* textures) {
4940 // Validate that count is non-negative before allocating a vector
4941 if (n < 0) {
4942 InsertError(GL_INVALID_VALUE, "count cannot be negative.");
4943 return error::kNoError;
4944 }
4945
4946 std::vector<gl::GLSurface::CALayerInUseQuery> queries;
4947 queries.reserve(n);
4948 for (GLsizei i = 0; i < n; ++i) {
4949 gl::GLImage* image = nullptr;
4950 GLuint texture_id = textures[i];
4951 if (texture_id) {
4952 // If a |texture_id| is invalid (due to a client error), report that it
4953 // is not in use. Failing the GL call can result in compositor hangs.
4954 // https://crbug.com/1120795
4955 scoped_refptr<TexturePassthrough> passthrough_texture;
4956 if (resources_->texture_object_map.GetServiceID(texture_id,
4957 &passthrough_texture)) {
4958 if (passthrough_texture) {
4959 image = passthrough_texture->GetLevelImage(
4960 passthrough_texture->target(), 0);
4961 }
4962 }
4963 }
4964 gl::GLSurface::CALayerInUseQuery query;
4965 query.image = image;
4966 query.texture = texture_id;
4967 queries.push_back(query);
4968 }
4969
4970 surface_->ScheduleCALayerInUseQuery(std::move(queries));
4971 return error::kNoError;
4972 }
4973
DoScheduleDCLayerCHROMIUM(GLuint texture_0,GLuint texture_1,GLint z_order,GLint content_x,GLint content_y,GLint content_width,GLint content_height,GLint quad_x,GLint quad_y,GLint quad_width,GLint quad_height,GLfloat transform_c1r1,GLfloat transform_c2r1,GLfloat transform_c1r2,GLfloat transform_c2r2,GLfloat transform_tx,GLfloat transform_ty,GLboolean is_clipped,GLint clip_x,GLint clip_y,GLint clip_width,GLint clip_height,GLuint protected_video_type)4974 error::Error GLES2DecoderPassthroughImpl::DoScheduleDCLayerCHROMIUM(
4975 GLuint texture_0,
4976 GLuint texture_1,
4977 GLint z_order,
4978 GLint content_x,
4979 GLint content_y,
4980 GLint content_width,
4981 GLint content_height,
4982 GLint quad_x,
4983 GLint quad_y,
4984 GLint quad_width,
4985 GLint quad_height,
4986 GLfloat transform_c1r1,
4987 GLfloat transform_c2r1,
4988 GLfloat transform_c1r2,
4989 GLfloat transform_c2r2,
4990 GLfloat transform_tx,
4991 GLfloat transform_ty,
4992 GLboolean is_clipped,
4993 GLint clip_x,
4994 GLint clip_y,
4995 GLint clip_width,
4996 GLint clip_height,
4997 GLuint protected_video_type) {
4998 if (protected_video_type >
4999 static_cast<GLuint>(gfx::ProtectedVideoType::kMaxValue)) {
5000 InsertError(GL_INVALID_VALUE, "invalid protected video type");
5001 return error::kNoError;
5002 }
5003
5004 if (!texture_0) {
5005 InsertError(GL_INVALID_VALUE, "invalid texture");
5006 return error::kNoError;
5007 }
5008
5009 ui::DCRendererLayerParams params;
5010 GLuint texture_ids[] = {texture_0, texture_1};
5011 size_t i = 0;
5012 for (GLuint texture_id : texture_ids) {
5013 if (!texture_id)
5014 break;
5015 scoped_refptr<TexturePassthrough> passthrough_texture;
5016 if (!resources_->texture_object_map.GetServiceID(texture_id,
5017 &passthrough_texture) ||
5018 passthrough_texture == nullptr) {
5019 InsertError(GL_INVALID_VALUE, "unknown texture");
5020 return error::kNoError;
5021 }
5022 DCHECK(passthrough_texture);
5023 gl::GLImage* image =
5024 passthrough_texture->GetLevelImage(passthrough_texture->target(), 0);
5025 if (!image) {
5026 InsertError(GL_INVALID_VALUE, "unsupported texture format");
5027 return error::kNoError;
5028 }
5029 params.images[i++] = scoped_refptr<gl::GLImage>(image);
5030 }
5031 params.z_order = z_order;
5032 params.content_rect =
5033 gfx::Rect(content_x, content_y, content_width, content_height);
5034 params.quad_rect = gfx::Rect(quad_x, quad_y, quad_width, quad_height);
5035 params.transform =
5036 gfx::Transform(transform_c1r1, transform_c2r1, transform_c1r2,
5037 transform_c2r2, transform_tx, transform_ty);
5038 params.is_clipped = is_clipped;
5039 params.clip_rect = gfx::Rect(clip_x, clip_y, clip_width, clip_height);
5040 params.protected_video_type =
5041 static_cast<gfx::ProtectedVideoType>(protected_video_type);
5042
5043 if (!surface_->ScheduleDCLayer(params))
5044 InsertError(GL_INVALID_OPERATION, "failed to schedule DCLayer");
5045
5046 return error::kNoError;
5047 }
5048
DoCommitOverlayPlanesCHROMIUM(uint64_t swap_id,GLbitfield flags)5049 error::Error GLES2DecoderPassthroughImpl::DoCommitOverlayPlanesCHROMIUM(
5050 uint64_t swap_id,
5051 GLbitfield flags) {
5052 if (!surface_->SupportsCommitOverlayPlanes()) {
5053 InsertError(GL_INVALID_OPERATION,
5054 "glCommitOverlayPlanes not supported by surface.");
5055 return error::kNoError;
5056 }
5057
5058 ca_layer_shared_state_ = nullptr;
5059
5060 client()->OnSwapBuffers(swap_id, flags);
5061 if (surface_->SupportsAsyncSwap()) {
5062 TRACE_EVENT_ASYNC_BEGIN0("gpu", "AsyncSwapBuffers", swap_id);
5063 surface_->CommitOverlayPlanesAsync(
5064 base::BindOnce(
5065 &GLES2DecoderPassthroughImpl::CheckSwapBuffersAsyncResult,
5066 weak_ptr_factory_.GetWeakPtr(), "CommitOverlayPlanes", swap_id),
5067 base::DoNothing());
5068 return error::kNoError;
5069 } else {
5070 return CheckSwapBuffersResult(
5071 surface_->CommitOverlayPlanes(base::DoNothing()),
5072 "CommitOverlayPlanes");
5073 }
5074 }
5075
DoSetColorSpaceMetadataCHROMIUM(GLuint texture_id,gfx::ColorSpace color_space)5076 error::Error GLES2DecoderPassthroughImpl::DoSetColorSpaceMetadataCHROMIUM(
5077 GLuint texture_id,
5078 gfx::ColorSpace color_space) {
5079 scoped_refptr<TexturePassthrough> passthrough_texture = nullptr;
5080 if (!resources_->texture_object_map.GetServiceID(texture_id,
5081 &passthrough_texture) ||
5082 passthrough_texture == nullptr) {
5083 InsertError(GL_INVALID_VALUE, "unknown texture.");
5084 return error::kNoError;
5085 }
5086
5087 scoped_refptr<gl::GLImage> image =
5088 passthrough_texture->GetLevelImage(passthrough_texture->target(), 0);
5089 if (image == nullptr) {
5090 InsertError(GL_INVALID_VALUE, "no image associated with texture.");
5091 return error::kNoError;
5092 }
5093
5094 image->SetColorSpace(color_space);
5095 return error::kNoError;
5096 }
5097
DoFlushDriverCachesCHROMIUM()5098 error::Error GLES2DecoderPassthroughImpl::DoFlushDriverCachesCHROMIUM() {
5099 // On Adreno Android devices we need to use a workaround to force caches to
5100 // clear.
5101 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
5102 context_->ReleaseCurrent(nullptr);
5103 context_->MakeCurrent(surface_.get());
5104 }
5105 return error::kNoError;
5106 }
5107
DoCoverageModulationCHROMIUM(GLenum components)5108 error::Error GLES2DecoderPassthroughImpl::DoCoverageModulationCHROMIUM(
5109 GLenum components) {
5110 NOTIMPLEMENTED();
5111 return error::kNoError;
5112 }
5113
DoBlendBarrierKHR()5114 error::Error GLES2DecoderPassthroughImpl::DoBlendBarrierKHR() {
5115 NOTIMPLEMENTED();
5116 return error::kNoError;
5117 }
5118
DoBindFragDataLocationIndexedEXT(GLuint program,GLuint colorNumber,GLuint index,const char * name)5119 error::Error GLES2DecoderPassthroughImpl::DoBindFragDataLocationIndexedEXT(
5120 GLuint program,
5121 GLuint colorNumber,
5122 GLuint index,
5123 const char* name) {
5124 api()->glBindFragDataLocationIndexedFn(
5125 GetProgramServiceID(program, resources_), colorNumber, index, name);
5126 return error::kNoError;
5127 }
5128
DoBindFragDataLocationEXT(GLuint program,GLuint colorNumber,const char * name)5129 error::Error GLES2DecoderPassthroughImpl::DoBindFragDataLocationEXT(
5130 GLuint program,
5131 GLuint colorNumber,
5132 const char* name) {
5133 api()->glBindFragDataLocationFn(GetProgramServiceID(program, resources_),
5134 colorNumber, name);
5135 return error::kNoError;
5136 }
5137
DoGetFragDataIndexEXT(GLuint program,const char * name,GLint * index)5138 error::Error GLES2DecoderPassthroughImpl::DoGetFragDataIndexEXT(
5139 GLuint program,
5140 const char* name,
5141 GLint* index) {
5142 *index = api()->glGetFragDataIndexFn(GetProgramServiceID(program, resources_),
5143 name);
5144 return error::kNoError;
5145 }
5146
DoSetDrawRectangleCHROMIUM(GLint x,GLint y,GLint width,GLint height)5147 error::Error GLES2DecoderPassthroughImpl::DoSetDrawRectangleCHROMIUM(
5148 GLint x,
5149 GLint y,
5150 GLint width,
5151 GLint height) {
5152 GLint current_framebuffer = 0;
5153 api()->glGetIntegervFn(GL_FRAMEBUFFER_BINDING, ¤t_framebuffer);
5154 if (current_framebuffer != 0) {
5155 InsertError(GL_INVALID_OPERATION, "framebuffer must not be bound.");
5156 return error::kNoError;
5157 }
5158
5159 if (!surface_->SupportsDCLayers()) {
5160 InsertError(GL_INVALID_OPERATION,
5161 "surface doesn't support SetDrawRectangle.");
5162 return error::kNoError;
5163 }
5164
5165 gfx::Rect rect(x, y, width, height);
5166 if (!surface_->SetDrawRectangle(rect)) {
5167 InsertError(GL_INVALID_OPERATION, "SetDrawRectangle failed on surface");
5168 // If SetDrawRectangle failed, we may not have a current context any
5169 // more, make sure to report lost context.
5170 MarkContextLost(error::kUnknown);
5171 group_->LoseContexts(error::kUnknown);
5172 return error::kLostContext;
5173 }
5174
5175 ApplySurfaceDrawOffset();
5176
5177 return error::kNoError;
5178 }
5179
DoSetEnableDCLayersCHROMIUM(GLboolean enable)5180 error::Error GLES2DecoderPassthroughImpl::DoSetEnableDCLayersCHROMIUM(
5181 GLboolean enable) {
5182 GLint current_framebuffer = 0;
5183 api()->glGetIntegervFn(GL_FRAMEBUFFER_BINDING, ¤t_framebuffer);
5184 if (current_framebuffer != 0) {
5185 InsertError(GL_INVALID_OPERATION, "framebuffer must not be bound.");
5186 return error::kNoError;
5187 }
5188
5189 if (!surface_->SupportsDCLayers()) {
5190 InsertError(GL_INVALID_OPERATION,
5191 "surface doesn't support SetDrawRectangle.");
5192 return error::kNoError;
5193 }
5194
5195 if (!surface_->SetEnableDCLayers(!!enable)) {
5196 InsertError(GL_INVALID_OPERATION, "SetEnableDCLayers failed on surface.");
5197 // If SetEnableDCLayers failed, we may not have a current context any
5198 // more, make sure to report lost context.
5199 MarkContextLost(error::kUnknown);
5200 group_->LoseContexts(error::kUnknown);
5201 return error::kLostContext;
5202 }
5203
5204 return error::kNoError;
5205 }
5206
DoBeginRasterCHROMIUM(GLuint texture_id,GLuint sk_color,GLuint msaa_sample_count,GLboolean can_use_lcd_text,GLint color_type)5207 error::Error GLES2DecoderPassthroughImpl::DoBeginRasterCHROMIUM(
5208 GLuint texture_id,
5209 GLuint sk_color,
5210 GLuint msaa_sample_count,
5211 GLboolean can_use_lcd_text,
5212 GLint color_type) {
5213 NOTIMPLEMENTED();
5214 return error::kNoError;
5215 }
5216
DoRasterCHROMIUM(GLuint raster_shm_id,GLuint raster_shm_offset,GLsizeiptr raster_shm_size,GLuint font_shm_id,GLuint font_shm_offset,GLsizeiptr font_shm_size)5217 error::Error GLES2DecoderPassthroughImpl::DoRasterCHROMIUM(
5218 GLuint raster_shm_id,
5219 GLuint raster_shm_offset,
5220 GLsizeiptr raster_shm_size,
5221 GLuint font_shm_id,
5222 GLuint font_shm_offset,
5223 GLsizeiptr font_shm_size) {
5224 // TODO(enne): Add CHROMIUM_raster_transport extension support to the
5225 // passthrough command buffer.
5226 NOTIMPLEMENTED();
5227 return error::kNoError;
5228 }
5229
DoEndRasterCHROMIUM()5230 error::Error GLES2DecoderPassthroughImpl::DoEndRasterCHROMIUM() {
5231 NOTIMPLEMENTED();
5232 return error::kNoError;
5233 }
5234
DoCreateTransferCacheEntryINTERNAL(GLuint entry_type,GLuint entry_id,GLuint handle_shm_id,GLuint handle_shm_offset,GLuint data_shm_id,GLuint data_shm_offset,GLuint data_size)5235 error::Error GLES2DecoderPassthroughImpl::DoCreateTransferCacheEntryINTERNAL(
5236 GLuint entry_type,
5237 GLuint entry_id,
5238 GLuint handle_shm_id,
5239 GLuint handle_shm_offset,
5240 GLuint data_shm_id,
5241 GLuint data_shm_offset,
5242 GLuint data_size) {
5243 NOTIMPLEMENTED();
5244 return error::kNoError;
5245 }
5246
DoUnlockTransferCacheEntryINTERNAL(GLuint entry_type,GLuint entry_id)5247 error::Error GLES2DecoderPassthroughImpl::DoUnlockTransferCacheEntryINTERNAL(
5248 GLuint entry_type,
5249 GLuint entry_id) {
5250 NOTIMPLEMENTED();
5251 return error::kNoError;
5252 }
5253
DoDeleteTransferCacheEntryINTERNAL(GLuint entry_type,GLuint entry_id)5254 error::Error GLES2DecoderPassthroughImpl::DoDeleteTransferCacheEntryINTERNAL(
5255 GLuint entry_type,
5256 GLuint entry_id) {
5257 NOTIMPLEMENTED();
5258 return error::kNoError;
5259 }
5260
DoWindowRectanglesEXT(GLenum mode,GLsizei n,const volatile GLint * box)5261 error::Error GLES2DecoderPassthroughImpl::DoWindowRectanglesEXT(
5262 GLenum mode,
5263 GLsizei n,
5264 const volatile GLint* box) {
5265 std::vector<GLint> box_copy(box, box + (n * 4));
5266 api()->glWindowRectanglesEXTFn(mode, n, box_copy.data());
5267 return error::kNoError;
5268 }
5269
DoCreateGpuFenceINTERNAL(GLuint gpu_fence_id)5270 error::Error GLES2DecoderPassthroughImpl::DoCreateGpuFenceINTERNAL(
5271 GLuint gpu_fence_id) {
5272 if (!feature_info_->feature_flags().chromium_gpu_fence)
5273 return error::kUnknownCommand;
5274 if (!GetGpuFenceManager()->CreateGpuFence(gpu_fence_id))
5275 return error::kInvalidArguments;
5276 return error::kNoError;
5277 }
5278
DoWaitGpuFenceCHROMIUM(GLuint gpu_fence_id)5279 error::Error GLES2DecoderPassthroughImpl::DoWaitGpuFenceCHROMIUM(
5280 GLuint gpu_fence_id) {
5281 if (!feature_info_->feature_flags().chromium_gpu_fence)
5282 return error::kUnknownCommand;
5283 if (!GetGpuFenceManager()->GpuFenceServerWait(gpu_fence_id))
5284 return error::kInvalidArguments;
5285 return error::kNoError;
5286 }
5287
DoDestroyGpuFenceCHROMIUM(GLuint gpu_fence_id)5288 error::Error GLES2DecoderPassthroughImpl::DoDestroyGpuFenceCHROMIUM(
5289 GLuint gpu_fence_id) {
5290 if (!feature_info_->feature_flags().chromium_gpu_fence)
5291 return error::kUnknownCommand;
5292 if (!GetGpuFenceManager()->RemoveGpuFence(gpu_fence_id))
5293 return error::kInvalidArguments;
5294 return error::kNoError;
5295 }
5296
DoUnpremultiplyAndDitherCopyCHROMIUM(GLuint src_texture,GLuint dst_texture,GLint x,GLint y,GLsizei width,GLsizei height)5297 error::Error GLES2DecoderPassthroughImpl::DoUnpremultiplyAndDitherCopyCHROMIUM(
5298 GLuint src_texture,
5299 GLuint dst_texture,
5300 GLint x,
5301 GLint y,
5302 GLsizei width,
5303 GLsizei height) {
5304 NOTIMPLEMENTED();
5305 return error::kNoError;
5306 }
5307
5308 error::Error
DoSetReadbackBufferShadowAllocationINTERNAL(GLuint buffer_id,GLuint shm_id,GLuint shm_offset,GLuint size)5309 GLES2DecoderPassthroughImpl::DoSetReadbackBufferShadowAllocationINTERNAL(
5310 GLuint buffer_id,
5311 GLuint shm_id,
5312 GLuint shm_offset,
5313 GLuint size) {
5314 BufferShadowUpdate update;
5315 update.shm = GetSharedMemoryBuffer(shm_id);
5316 update.shm_offset = shm_offset;
5317 update.size = size;
5318
5319 GLuint buffer_service_id = 0;
5320 if (!resources_->buffer_id_map.GetServiceID(buffer_id, &buffer_service_id)) {
5321 InsertError(GL_INVALID_OPERATION, "Invalid buffer ID");
5322 return error::kNoError;
5323 }
5324
5325 if (!update.shm) {
5326 return error::kInvalidArguments;
5327 }
5328 if (update.shm->GetRemainingSize(shm_offset) < size) {
5329 return error::kOutOfBounds;
5330 }
5331
5332 buffer_shadow_updates_.emplace(buffer_id, std::move(update));
5333
5334 return error::kNoError;
5335 }
5336
DoMaxShaderCompilerThreadsKHR(GLuint count)5337 error::Error GLES2DecoderPassthroughImpl::DoMaxShaderCompilerThreadsKHR(
5338 GLuint count) {
5339 api()->glMaxShaderCompilerThreadsKHRFn(count);
5340 return error::kNoError;
5341 }
5342
5343 error::Error
DoInitializeDiscardableTextureCHROMIUM(GLuint texture_id,ServiceDiscardableHandle && discardable_handle)5344 GLES2DecoderPassthroughImpl::DoInitializeDiscardableTextureCHROMIUM(
5345 GLuint texture_id,
5346 ServiceDiscardableHandle&& discardable_handle) {
5347 scoped_refptr<TexturePassthrough> texture_passthrough = nullptr;
5348 if (!resources_->texture_object_map.GetServiceID(texture_id,
5349 &texture_passthrough) ||
5350 texture_passthrough == nullptr) {
5351 InsertError(GL_INVALID_VALUE, "Invalid texture ID");
5352 return error::kNoError;
5353 }
5354
5355 group_->passthrough_discardable_manager()->InitializeTexture(
5356 texture_id, group_.get(), texture_passthrough->estimated_size(),
5357 std::move(discardable_handle));
5358
5359 return error::kNoError;
5360 }
5361
DoLockDiscardableTextureCHROMIUM(GLuint texture_id)5362 error::Error GLES2DecoderPassthroughImpl::DoLockDiscardableTextureCHROMIUM(
5363 GLuint texture_id) {
5364 if (!group_->passthrough_discardable_manager()->LockTexture(texture_id,
5365 group_.get())) {
5366 InsertError(GL_INVALID_VALUE, "Texture ID not initialized");
5367 return error::kNoError;
5368 }
5369
5370 return error::kNoError;
5371 }
5372
DoUnlockDiscardableTextureCHROMIUM(GLuint texture_id)5373 error::Error GLES2DecoderPassthroughImpl::DoUnlockDiscardableTextureCHROMIUM(
5374 GLuint texture_id) {
5375 TexturePassthrough* texture_to_unbind = nullptr;
5376 if (!group_->passthrough_discardable_manager()->UnlockTexture(
5377 texture_id, group_.get(), &texture_to_unbind)) {
5378 InsertError(GL_INVALID_VALUE, "Texture ID not initialized");
5379 return error::kNoError;
5380 }
5381
5382 if (texture_to_unbind != nullptr) {
5383 UpdateTextureBinding(texture_to_unbind->target(), texture_id, nullptr);
5384 }
5385 return error::kNoError;
5386 }
5387
5388 error::Error
DoCreateAndTexStorage2DSharedImageINTERNAL(GLuint texture_client_id,GLenum internalformat,const volatile GLbyte * mailbox)5389 GLES2DecoderPassthroughImpl::DoCreateAndTexStorage2DSharedImageINTERNAL(
5390 GLuint texture_client_id,
5391 GLenum internalformat,
5392 const volatile GLbyte* mailbox) {
5393 // RGB emulation is not needed here.
5394 if (internalformat != GL_NONE) {
5395 InsertError(GL_INVALID_ENUM, "internal format not supported.");
5396 return error::kNoError;
5397 }
5398
5399 if (!texture_client_id ||
5400 resources_->texture_id_map.HasClientID(texture_client_id)) {
5401 InsertError(GL_INVALID_OPERATION, "invalid client ID");
5402 return error::kNoError;
5403 }
5404
5405 const Mailbox& mb = Mailbox::FromVolatile(
5406 *reinterpret_cast<const volatile Mailbox*>(mailbox));
5407 auto shared_image = group_->shared_image_representation_factory()
5408 ->ProduceGLTexturePassthrough(mb);
5409 if (shared_image == nullptr) {
5410 // Create texture to handle invalid mailbox (see http://crbug.com/472465 and
5411 // http://crbug.com/851878).
5412 DoGenTextures(1, &texture_client_id);
5413 InsertError(GL_INVALID_OPERATION, "invalid mailbox name.");
5414 return error::kNoError;
5415 }
5416
5417 auto texture = shared_image->GetTexturePassthrough();
5418
5419 // Update id mappings
5420 resources_->texture_id_map.RemoveClientID(texture_client_id);
5421 resources_->texture_id_map.SetIDMapping(texture_client_id,
5422 texture->service_id());
5423 resources_->texture_object_map.RemoveClientID(texture_client_id);
5424 resources_->texture_object_map.SetIDMapping(texture_client_id, texture);
5425 resources_->texture_shared_image_map[texture_client_id] =
5426 PassthroughResources::SharedImageData(std::move(shared_image));
5427
5428 return error::kNoError;
5429 }
5430
5431 error::Error
DoBeginSharedImageAccessDirectCHROMIUM(GLuint client_id,GLenum mode)5432 GLES2DecoderPassthroughImpl::DoBeginSharedImageAccessDirectCHROMIUM(
5433 GLuint client_id,
5434 GLenum mode) {
5435 if (mode != GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM &&
5436 mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM &&
5437 mode != GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) {
5438 InsertError(GL_INVALID_ENUM, "unrecognized access mode");
5439 return error::kNoError;
5440 }
5441
5442 auto found = resources_->texture_shared_image_map.find(client_id);
5443 if (found == resources_->texture_shared_image_map.end()) {
5444 InsertError(GL_INVALID_OPERATION, "texture is not a shared image");
5445 return error::kNoError;
5446 }
5447
5448 if (found->second.is_being_accessed()) {
5449 InsertError(GL_INVALID_OPERATION, "shared image is being accessed.");
5450 return error::kNoError;
5451 }
5452
5453 if (!found->second.BeginAccess(mode, api())) {
5454 InsertError(GL_INVALID_OPERATION, "unable to begin access");
5455 return error::kNoError;
5456 }
5457
5458 return error::kNoError;
5459 }
5460
DoEndSharedImageAccessDirectCHROMIUM(GLuint client_id)5461 error::Error GLES2DecoderPassthroughImpl::DoEndSharedImageAccessDirectCHROMIUM(
5462 GLuint client_id) {
5463 auto found = resources_->texture_shared_image_map.find(client_id);
5464 if (found == resources_->texture_shared_image_map.end()) {
5465 InsertError(GL_INVALID_OPERATION, "texture is not a shared image");
5466 return error::kNoError;
5467 }
5468 if (!found->second.is_being_accessed()) {
5469 InsertError(GL_INVALID_OPERATION, "shared image is not being accessed.");
5470 return error::kNoError;
5471 }
5472 found->second.EndAccess();
5473 return error::kNoError;
5474 }
5475
5476 error::Error
DoBeginBatchReadAccessSharedImageCHROMIUM()5477 GLES2DecoderPassthroughImpl::DoBeginBatchReadAccessSharedImageCHROMIUM() {
5478 DCHECK(group_->shared_image_manager());
5479 group_->shared_image_manager()->BeginBatchReadAccess();
5480 return error::kNoError;
5481 }
5482
5483 error::Error
DoEndBatchReadAccessSharedImageCHROMIUM()5484 GLES2DecoderPassthroughImpl::DoEndBatchReadAccessSharedImageCHROMIUM() {
5485 DCHECK(group_->shared_image_manager());
5486 group_->shared_image_manager()->EndBatchReadAccess();
5487 return error::kNoError;
5488 }
5489
DoEnableiOES(GLenum target,GLuint index)5490 error::Error GLES2DecoderPassthroughImpl::DoEnableiOES(GLenum target,
5491 GLuint index) {
5492 api()->glEnableiOESFn(target, index);
5493 return error::kNoError;
5494 }
5495
DoDisableiOES(GLenum target,GLuint index)5496 error::Error GLES2DecoderPassthroughImpl::DoDisableiOES(GLenum target,
5497 GLuint index) {
5498 api()->glDisableiOESFn(target, index);
5499 return error::kNoError;
5500 }
5501
5502 } // namespace gles2
5503 } // namespace gpu
5504