1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // A class to emulate GLES2 over command buffers.
7 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include <GLES2/gl2ext.h>
10 #include <GLES2/gl2extchromium.h>
11 #include <GLES3/gl3.h>
19 #include "base/bind.h"
20 #include "base/compiler_specific.h"
21 #include "base/numerics/safe_math.h"
22 #include "gpu/command_buffer/client/buffer_tracker.h"
23 #include "gpu/command_buffer/client/gpu_control.h"
24 #include "gpu/command_buffer/client/program_info_manager.h"
25 #include "gpu/command_buffer/client/query_tracker.h"
26 #include "gpu/command_buffer/client/transfer_buffer.h"
27 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
28 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
29 #include "gpu/command_buffer/common/trace_event.h"
31 #if defined(GPU_CLIENT_DEBUG)
32 #include "base/command_line.h"
33 #include "gpu/command_buffer/client/gpu_switches.h"
39 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
40 static GLuint
ToGLuint(const void* ptr
) {
41 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
44 #if !defined(_MSC_VER)
45 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
46 const unsigned int GLES2Implementation::kStartingOffset
;
49 GLES2Implementation::GLStaticState::GLStaticState() {
52 GLES2Implementation::GLStaticState::~GLStaticState() {
55 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
56 GLES2Implementation
* gles2_implementation
)
57 : gles2_implementation_(gles2_implementation
) {
58 CHECK_EQ(0, gles2_implementation_
->use_count_
);
59 ++gles2_implementation_
->use_count_
;
62 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
63 --gles2_implementation_
->use_count_
;
64 CHECK_EQ(0, gles2_implementation_
->use_count_
);
67 GLES2Implementation::GLES2Implementation(
68 GLES2CmdHelper
* helper
,
69 ShareGroup
* share_group
,
70 TransferBufferInterface
* transfer_buffer
,
71 bool bind_generates_resource
,
72 bool lose_context_when_out_of_memory
,
73 bool support_client_side_arrays
,
74 GpuControl
* gpu_control
)
76 transfer_buffer_(transfer_buffer
),
77 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
78 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
81 unpack_flip_y_(false),
82 unpack_row_length_(0),
83 unpack_image_height_(0),
85 unpack_skip_pixels_(0),
86 unpack_skip_images_(0),
87 pack_reverse_row_order_(false),
88 active_texture_unit_(0),
89 bound_framebuffer_(0),
90 bound_read_framebuffer_(0),
91 bound_renderbuffer_(0),
92 bound_valuebuffer_(0),
94 bound_array_buffer_(0),
95 bound_copy_read_buffer_(0),
96 bound_copy_write_buffer_(0),
97 bound_pixel_pack_buffer_(0),
98 bound_pixel_unpack_buffer_(0),
99 bound_transform_feedback_buffer_(0),
100 bound_uniform_buffer_(0),
101 bound_pixel_pack_transfer_buffer_id_(0),
102 bound_pixel_unpack_transfer_buffer_id_(0),
103 async_upload_token_(0),
104 async_upload_sync_(NULL
),
105 async_upload_sync_shm_id_(0),
106 async_upload_sync_shm_offset_(0),
109 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
110 support_client_side_arrays_(support_client_side_arrays
),
112 error_message_callback_(NULL
),
113 current_trace_stack_(0),
114 gpu_control_(gpu_control
),
115 capabilities_(gpu_control
->GetCapabilities()),
116 weak_ptr_factory_(this) {
118 DCHECK(transfer_buffer
);
121 std::stringstream ss
;
122 ss
<< std::hex
<< this;
123 this_in_hex_
= ss
.str();
125 GPU_CLIENT_LOG_CODE_BLOCK({
126 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
127 switches::kEnableGPUClientLogging
);
131 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
132 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
134 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
137 bool GLES2Implementation::Initialize(
138 unsigned int starting_transfer_buffer_size
,
139 unsigned int min_transfer_buffer_size
,
140 unsigned int max_transfer_buffer_size
,
141 unsigned int mapped_memory_limit
) {
142 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
143 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
144 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
145 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
147 if (!transfer_buffer_
->Initialize(
148 starting_transfer_buffer_size
,
150 min_transfer_buffer_size
,
151 max_transfer_buffer_size
,
157 mapped_memory_
.reset(
158 new MappedMemoryManager(
160 base::Bind(&GLES2Implementation::PollAsyncUploads
,
161 // The mapped memory manager is owned by |this| here, and
162 // since its destroyed before before we destroy ourselves
163 // we don't need extra safety measures for this closure.
164 base::Unretained(this)),
165 mapped_memory_limit
));
167 unsigned chunk_size
= 2 * 1024 * 1024;
168 if (mapped_memory_limit
!= kNoLimit
) {
169 // Use smaller chunks if the client is very memory conscientious.
170 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
172 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
174 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
175 &static_state_
.shader_precisions
;
176 capabilities_
.VisitPrecisions([shader_precisions
](
177 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
178 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
179 cmds::GetShaderPrecisionFormat::Result cached_result
= {
180 true, result
->min_range
, result
->max_range
, result
->precision
};
181 shader_precisions
->insert(std::make_pair(key
, cached_result
));
184 util_
.set_num_compressed_texture_formats(
185 capabilities_
.num_compressed_texture_formats
);
186 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
188 texture_units_
.reset(
189 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
191 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
192 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
194 query_id_allocator_
.reset(new IdAllocator());
195 if (support_client_side_arrays_
) {
196 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
197 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
200 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
201 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
202 support_client_side_arrays_
));
204 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
205 // on Client & Service.
206 if (capabilities_
.bind_generates_resource_chromium
!=
207 (share_group_
->bind_generates_resource() ? 1 : 0)) {
208 SetGLError(GL_INVALID_OPERATION
,
210 "Service bind_generates_resource mismatch.");
217 GLES2Implementation::~GLES2Implementation() {
218 // Make sure the queries are finished otherwise we'll delete the
219 // shared memory (mapped_memory_) which will free the memory used
220 // by the queries. The GPU process when validating that memory is still
221 // shared will fail and abort (ie, it will stop running).
223 query_tracker_
.reset();
225 // GLES2Implementation::Initialize() could fail before allocating
226 // reserved_ids_, so we need delete them carefully.
227 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
228 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
231 // Release remaining BufferRange mem; This is when a MapBufferRange() is
232 // called but not the UnmapBuffer() pair.
233 ClearMappedBufferRangeMap();
235 // Release any per-context data in share group.
236 share_group_
->FreeContext(this);
238 buffer_tracker_
.reset();
240 FreeAllAsyncUploadBuffers();
242 if (async_upload_sync_
) {
243 mapped_memory_
->Free(async_upload_sync_
);
244 async_upload_sync_
= NULL
;
247 // Make sure the commands make it the service.
251 GLES2CmdHelper
* GLES2Implementation::helper() const {
255 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
256 return share_group_
->GetIdHandler(namespace_id
);
259 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
260 if (namespace_id
== id_namespaces::kQueries
)
261 return query_id_allocator_
.get();
266 void* GLES2Implementation::GetResultBuffer() {
267 return transfer_buffer_
->GetResultBuffer();
270 int32
GLES2Implementation::GetResultShmId() {
271 return transfer_buffer_
->GetShmId();
274 uint32
GLES2Implementation::GetResultShmOffset() {
275 return transfer_buffer_
->GetResultOffset();
278 void GLES2Implementation::FreeUnusedSharedMemory() {
279 mapped_memory_
->FreeUnused();
282 void GLES2Implementation::FreeEverything() {
283 FreeAllAsyncUploadBuffers();
285 query_tracker_
->Shrink();
286 FreeUnusedSharedMemory();
287 transfer_buffer_
->Free();
288 helper_
->FreeRingBuffer();
291 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
292 if (!helper_
->IsContextLost())
296 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
297 const base::Closure
& callback
) {
298 gpu_control_
->SignalSyncPoint(
300 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
301 weak_ptr_factory_
.GetWeakPtr(),
305 void GLES2Implementation::SignalQuery(uint32 query
,
306 const base::Closure
& callback
) {
307 // Flush previously entered commands to ensure ordering with any
308 // glBeginQueryEXT() calls that may have been put into the context.
309 ShallowFlushCHROMIUM();
310 gpu_control_
->SignalQuery(
312 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
313 weak_ptr_factory_
.GetWeakPtr(),
317 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
319 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
320 // TODO(piman): This probably should be ShallowFlushCHROMIUM().
322 gpu_control_
->SetSurfaceVisible(visible
);
327 void GLES2Implementation::WaitForCmd() {
328 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
329 helper_
->CommandBufferHelper::Finish();
332 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
333 const char* extensions
=
334 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
338 int length
= strlen(ext
);
340 int n
= strcspn(extensions
, " ");
341 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
344 if ('\0' == extensions
[n
]) {
351 bool GLES2Implementation::IsExtensionAvailableHelper(
352 const char* extension
, ExtensionStatus
* status
) {
354 case kAvailableExtensionStatus
:
356 case kUnavailableExtensionStatus
:
359 bool available
= IsExtensionAvailable(extension
);
360 *status
= available
? kAvailableExtensionStatus
:
361 kUnavailableExtensionStatus
;
367 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
368 return IsExtensionAvailableHelper(
369 "GL_ANGLE_pack_reverse_row_order",
370 &angle_pack_reverse_row_order_status_
);
373 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
374 return IsExtensionAvailableHelper(
375 "GL_CHROMIUM_framebuffer_multisample",
376 &chromium_framebuffer_multisample_
);
379 const std::string
& GLES2Implementation::GetLogPrefix() const {
380 const std::string
& prefix(debug_marker_manager_
.GetMarker());
381 return prefix
.empty() ? this_in_hex_
: prefix
;
384 GLenum
GLES2Implementation::GetError() {
385 GPU_CLIENT_SINGLE_THREAD_CHECK();
386 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
387 GLenum err
= GetGLError();
388 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
392 GLenum
GLES2Implementation::GetClientSideGLError() {
393 if (error_bits_
== 0) {
397 GLenum error
= GL_NO_ERROR
;
398 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
399 if ((error_bits_
& mask
) != 0) {
400 error
= GLES2Util::GLErrorBitToGLError(mask
);
404 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
408 GLenum
GLES2Implementation::GetGLError() {
409 TRACE_EVENT0("gpu", "GLES2::GetGLError");
410 // Check the GL error first, then our wrapped error.
411 typedef cmds::GetError::Result Result
;
412 Result
* result
= GetResultAs
<Result
*>();
413 // If we couldn't allocate a result the context is lost.
417 *result
= GL_NO_ERROR
;
418 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
420 GLenum error
= *result
;
421 if (error
== GL_NO_ERROR
) {
422 error
= GetClientSideGLError();
424 // There was an error, clear the corresponding wrapped error.
425 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
430 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
431 void GLES2Implementation::FailGLError(GLenum error
) {
432 if (error
!= GL_NO_ERROR
) {
433 NOTREACHED() << "Error";
436 // NOTE: Calling GetGLError overwrites data in the result buffer.
437 void GLES2Implementation::CheckGLError() {
438 FailGLError(GetGLError());
440 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
442 void GLES2Implementation::SetGLError(
443 GLenum error
, const char* function_name
, const char* msg
) {
444 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
445 << GLES2Util::GetStringError(error
) << ": "
446 << function_name
<< ": " << msg
);
451 if (error_message_callback_
) {
452 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
453 function_name
+ ": " + (msg
? msg
: ""));
454 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
456 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
458 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
459 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
460 GL_UNKNOWN_CONTEXT_RESET_ARB
);
464 void GLES2Implementation::SetGLErrorInvalidEnum(
465 const char* function_name
, GLenum value
, const char* label
) {
466 SetGLError(GL_INVALID_ENUM
, function_name
,
467 (std::string(label
) + " was " +
468 GLES2Util::GetStringEnum(value
)).c_str());
471 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
472 std::vector
<int8
>* data
) {
473 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
475 const uint32 kStartSize
= 32 * 1024;
476 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
477 if (!buffer
.valid()) {
480 typedef cmd::GetBucketStart::Result Result
;
481 Result
* result
= GetResultAs
<Result
*>();
486 helper_
->GetBucketStart(
487 bucket_id
, GetResultShmId(), GetResultShmOffset(),
488 buffer
.size(), buffer
.shm_id(), buffer
.offset());
490 uint32 size
= *result
;
495 if (!buffer
.valid()) {
497 if (!buffer
.valid()) {
500 helper_
->GetBucketData(
501 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
504 uint32 size_to_copy
= std::min(size
, buffer
.size());
505 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
506 offset
+= size_to_copy
;
507 size
-= size_to_copy
;
510 // Free the bucket. This is not required but it does free up the memory.
511 // and we don't have to wait for the result so from the client's perspective
513 helper_
->SetBucketSize(bucket_id
, 0);
518 void GLES2Implementation::SetBucketContents(
519 uint32 bucket_id
, const void* data
, size_t size
) {
521 helper_
->SetBucketSize(bucket_id
, size
);
525 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
526 if (!buffer
.valid()) {
529 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
531 helper_
->SetBucketData(
532 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
533 offset
+= buffer
.size();
534 size
-= buffer
.size();
539 void GLES2Implementation::SetBucketAsCString(
540 uint32 bucket_id
, const char* str
) {
541 // NOTE: strings are passed NULL terminated. That means the empty
542 // string will have a size of 1 and no-string will have a size of 0
544 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
546 helper_
->SetBucketSize(bucket_id
, 0);
550 bool GLES2Implementation::GetBucketAsString(
551 uint32 bucket_id
, std::string
* str
) {
553 std::vector
<int8
> data
;
554 // NOTE: strings are passed NULL terminated. That means the empty
555 // string will have a size of 1 and no-string will have a size of 0
556 if (!GetBucketContents(bucket_id
, &data
)) {
562 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
566 void GLES2Implementation::SetBucketAsString(
567 uint32 bucket_id
, const std::string
& str
) {
568 // NOTE: strings are passed NULL terminated. That means the empty
569 // string will have a size of 1 and no-string will have a size of 0
570 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
573 void GLES2Implementation::Disable(GLenum cap
) {
574 GPU_CLIENT_SINGLE_THREAD_CHECK();
575 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
576 << GLES2Util::GetStringCapability(cap
) << ")");
577 bool changed
= false;
578 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
579 helper_
->Disable(cap
);
584 void GLES2Implementation::Enable(GLenum cap
) {
585 GPU_CLIENT_SINGLE_THREAD_CHECK();
586 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
587 << GLES2Util::GetStringCapability(cap
) << ")");
588 bool changed
= false;
589 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
590 helper_
->Enable(cap
);
595 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
596 GPU_CLIENT_SINGLE_THREAD_CHECK();
597 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
598 << GLES2Util::GetStringCapability(cap
) << ")");
600 if (!state_
.GetEnabled(cap
, &state
)) {
601 typedef cmds::IsEnabled::Result Result
;
602 Result
* result
= GetResultAs
<Result
*>();
607 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
609 state
= (*result
) != 0;
612 GPU_CLIENT_LOG("returned " << state
);
617 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
618 // TODO(zmo): For all the BINDING points, there is a possibility where
619 // resources are shared among multiple contexts, that the cached points
620 // are invalid. It is not a problem for now, but once we allow resource
621 // sharing in WebGL, we need to implement a mechanism to allow correct
622 // client side binding points tracking. crbug.com/465562.
626 case GL_ACTIVE_TEXTURE
:
627 *params
= active_texture_unit_
+ GL_TEXTURE0
;
629 case GL_ARRAY_BUFFER_BINDING
:
630 *params
= bound_array_buffer_
;
632 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
634 vertex_array_object_manager_
->bound_element_array_buffer();
636 case GL_FRAMEBUFFER_BINDING
:
637 *params
= bound_framebuffer_
;
639 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
640 *params
= capabilities_
.max_combined_texture_image_units
;
642 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
643 *params
= capabilities_
.max_cube_map_texture_size
;
645 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
646 *params
= capabilities_
.max_fragment_uniform_vectors
;
648 case GL_MAX_RENDERBUFFER_SIZE
:
649 *params
= capabilities_
.max_renderbuffer_size
;
651 case GL_MAX_TEXTURE_IMAGE_UNITS
:
652 *params
= capabilities_
.max_texture_image_units
;
654 case GL_MAX_TEXTURE_SIZE
:
655 *params
= capabilities_
.max_texture_size
;
657 case GL_MAX_VARYING_VECTORS
:
658 *params
= capabilities_
.max_varying_vectors
;
660 case GL_MAX_VERTEX_ATTRIBS
:
661 *params
= capabilities_
.max_vertex_attribs
;
663 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
664 *params
= capabilities_
.max_vertex_texture_image_units
;
666 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
667 *params
= capabilities_
.max_vertex_uniform_vectors
;
669 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
670 *params
= capabilities_
.num_compressed_texture_formats
;
672 case GL_NUM_SHADER_BINARY_FORMATS
:
673 *params
= capabilities_
.num_shader_binary_formats
;
675 case GL_RENDERBUFFER_BINDING
:
676 *params
= bound_renderbuffer_
;
678 case GL_TEXTURE_BINDING_2D
:
679 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
681 case GL_TEXTURE_BINDING_CUBE_MAP
:
682 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
685 // Non-standard parameters.
686 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
688 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
690 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
691 *params
= bound_pixel_pack_transfer_buffer_id_
;
693 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
694 *params
= bound_pixel_unpack_transfer_buffer_id_
;
696 case GL_READ_FRAMEBUFFER_BINDING
:
697 if (IsChromiumFramebufferMultisampleAvailable()) {
698 *params
= bound_read_framebuffer_
;
703 // Non-cached parameters.
704 case GL_ALIASED_LINE_WIDTH_RANGE
:
705 case GL_ALIASED_POINT_SIZE_RANGE
:
709 case GL_BLEND_DST_ALPHA
:
710 case GL_BLEND_DST_RGB
:
711 case GL_BLEND_EQUATION_ALPHA
:
712 case GL_BLEND_EQUATION_RGB
:
713 case GL_BLEND_SRC_ALPHA
:
714 case GL_BLEND_SRC_RGB
:
716 case GL_COLOR_CLEAR_VALUE
:
717 case GL_COLOR_WRITEMASK
:
718 case GL_COMPRESSED_TEXTURE_FORMATS
:
720 case GL_CULL_FACE_MODE
:
721 case GL_CURRENT_PROGRAM
:
723 case GL_DEPTH_CLEAR_VALUE
:
727 case GL_DEPTH_WRITEMASK
:
730 case GL_GENERATE_MIPMAP_HINT
:
732 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
733 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
735 case GL_MAX_VIEWPORT_DIMS
:
736 case GL_PACK_ALIGNMENT
:
737 case GL_POLYGON_OFFSET_FACTOR
:
738 case GL_POLYGON_OFFSET_FILL
:
739 case GL_POLYGON_OFFSET_UNITS
:
741 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
742 case GL_SAMPLE_BUFFERS
:
743 case GL_SAMPLE_COVERAGE
:
744 case GL_SAMPLE_COVERAGE_INVERT
:
745 case GL_SAMPLE_COVERAGE_VALUE
:
748 case GL_SCISSOR_TEST
:
749 case GL_SHADER_BINARY_FORMATS
:
750 case GL_SHADER_COMPILER
:
751 case GL_STENCIL_BACK_FAIL
:
752 case GL_STENCIL_BACK_FUNC
:
753 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
754 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
755 case GL_STENCIL_BACK_REF
:
756 case GL_STENCIL_BACK_VALUE_MASK
:
757 case GL_STENCIL_BACK_WRITEMASK
:
758 case GL_STENCIL_BITS
:
759 case GL_STENCIL_CLEAR_VALUE
:
760 case GL_STENCIL_FAIL
:
761 case GL_STENCIL_FUNC
:
762 case GL_STENCIL_PASS_DEPTH_FAIL
:
763 case GL_STENCIL_PASS_DEPTH_PASS
:
765 case GL_STENCIL_TEST
:
766 case GL_STENCIL_VALUE_MASK
:
767 case GL_STENCIL_WRITEMASK
:
768 case GL_SUBPIXEL_BITS
:
769 case GL_UNPACK_ALIGNMENT
:
776 if (capabilities_
.major_version
< 3) {
782 case GL_COPY_READ_BUFFER_BINDING
:
783 *params
= bound_copy_read_buffer_
;
785 case GL_COPY_WRITE_BUFFER_BINDING
:
786 *params
= bound_copy_write_buffer_
;
788 case GL_MAJOR_VERSION
:
789 *params
= capabilities_
.major_version
;
791 case GL_MAX_3D_TEXTURE_SIZE
:
792 *params
= capabilities_
.max_3d_texture_size
;
794 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
795 *params
= capabilities_
.max_array_texture_layers
;
797 case GL_MAX_COLOR_ATTACHMENTS
:
798 *params
= capabilities_
.max_color_attachments
;
800 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
801 *params
= static_cast<GLint
>(
802 capabilities_
.max_combined_fragment_uniform_components
);
804 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
805 *params
= capabilities_
.max_combined_uniform_blocks
;
807 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
808 *params
= static_cast<GLint
>(
809 capabilities_
.max_combined_vertex_uniform_components
);
811 case GL_MAX_DRAW_BUFFERS
:
812 *params
= capabilities_
.max_draw_buffers
;
814 case GL_MAX_ELEMENT_INDEX
:
815 *params
= static_cast<GLint
>(capabilities_
.max_element_index
);
817 case GL_MAX_ELEMENTS_INDICES
:
818 *params
= capabilities_
.max_elements_indices
;
820 case GL_MAX_ELEMENTS_VERTICES
:
821 *params
= capabilities_
.max_elements_vertices
;
823 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
824 *params
= capabilities_
.max_fragment_input_components
;
826 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
827 *params
= capabilities_
.max_fragment_uniform_blocks
;
829 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
830 *params
= capabilities_
.max_fragment_uniform_components
;
832 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
833 *params
= capabilities_
.max_program_texel_offset
;
836 *params
= capabilities_
.max_samples
;
838 case GL_MAX_SERVER_WAIT_TIMEOUT
:
839 *params
= static_cast<GLint
>(capabilities_
.max_server_wait_timeout
);
841 case GL_MAX_TEXTURE_LOD_BIAS
:
842 *params
= static_cast<GLint
>(capabilities_
.max_texture_lod_bias
);
844 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
845 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
847 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
848 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
850 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
851 *params
= capabilities_
.max_transform_feedback_separate_components
;
853 case GL_MAX_UNIFORM_BLOCK_SIZE
:
854 *params
= static_cast<GLint
>(capabilities_
.max_uniform_block_size
);
856 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
857 *params
= capabilities_
.max_uniform_buffer_bindings
;
859 case GL_MAX_VARYING_COMPONENTS
:
860 *params
= capabilities_
.max_varying_components
;
862 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
863 *params
= capabilities_
.max_vertex_output_components
;
865 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
866 *params
= capabilities_
.max_vertex_uniform_blocks
;
868 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
869 *params
= capabilities_
.max_vertex_uniform_components
;
871 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
872 *params
= capabilities_
.min_program_texel_offset
;
874 case GL_MINOR_VERSION
:
875 *params
= capabilities_
.minor_version
;
877 case GL_NUM_EXTENSIONS
:
878 *params
= capabilities_
.num_extensions
;
880 case GL_NUM_PROGRAM_BINARY_FORMATS
:
881 *params
= capabilities_
.num_program_binary_formats
;
883 case GL_PIXEL_PACK_BUFFER_BINDING
:
884 *params
= bound_pixel_pack_buffer_
;
886 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
887 *params
= bound_pixel_unpack_buffer_
;
889 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
890 *params
= bound_transform_feedback_buffer_
;
892 case GL_UNIFORM_BUFFER_BINDING
:
893 *params
= bound_uniform_buffer_
;
895 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
896 *params
= capabilities_
.uniform_buffer_offset_alignment
;
899 // Non-cached ES3 parameters.
900 case GL_DRAW_BUFFER0
:
901 case GL_DRAW_BUFFER1
:
902 case GL_DRAW_BUFFER2
:
903 case GL_DRAW_BUFFER3
:
904 case GL_DRAW_BUFFER4
:
905 case GL_DRAW_BUFFER5
:
906 case GL_DRAW_BUFFER6
:
907 case GL_DRAW_BUFFER7
:
908 case GL_DRAW_BUFFER8
:
909 case GL_DRAW_BUFFER9
:
910 case GL_DRAW_BUFFER10
:
911 case GL_DRAW_BUFFER11
:
912 case GL_DRAW_BUFFER12
:
913 case GL_DRAW_BUFFER13
:
914 case GL_DRAW_BUFFER14
:
915 case GL_DRAW_BUFFER15
:
916 case GL_DRAW_FRAMEBUFFER_BINDING
:
917 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
918 case GL_PACK_ROW_LENGTH
:
919 case GL_PACK_SKIP_PIXELS
:
920 case GL_PACK_SKIP_ROWS
:
921 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
922 case GL_PROGRAM_BINARY_FORMATS
:
923 case GL_RASTERIZER_DISCARD
:
925 case GL_READ_FRAMEBUFFER_BINDING
:
926 case GL_SAMPLER_BINDING
:
927 case GL_TEXTURE_BINDING_2D_ARRAY
:
928 case GL_TEXTURE_BINDING_3D
:
929 case GL_TRANSFORM_FEEDBACK_BINDING
:
930 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
931 case GL_TRANSFORM_FEEDBACK_PAUSED
:
932 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
933 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
934 case GL_UNIFORM_BUFFER_SIZE
:
935 case GL_UNIFORM_BUFFER_START
:
936 case GL_UNPACK_IMAGE_HEIGHT
:
937 case GL_UNPACK_ROW_LENGTH
:
938 case GL_UNPACK_SKIP_IMAGES
:
939 case GL_UNPACK_SKIP_PIXELS
:
940 case GL_UNPACK_SKIP_ROWS
:
941 case GL_VERTEX_ARRAY_BINDING
:
948 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
949 // TODO(gman): Make this handle pnames that return more than 1 value.
951 if (!GetHelper(pname
, &value
)) {
954 *params
= static_cast<GLboolean
>(value
);
958 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
959 // TODO(gman): Make this handle pnames that return more than 1 value.
961 case GL_MAX_TEXTURE_LOD_BIAS
:
962 *params
= capabilities_
.max_texture_lod_bias
;
968 if (!GetHelper(pname
, &value
)) {
971 *params
= static_cast<GLfloat
>(value
);
975 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
977 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
978 *params
= capabilities_
.max_combined_fragment_uniform_components
;
980 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
981 *params
= capabilities_
.max_combined_vertex_uniform_components
;
983 case GL_MAX_ELEMENT_INDEX
:
984 *params
= capabilities_
.max_element_index
;
986 case GL_MAX_SERVER_WAIT_TIMEOUT
:
987 *params
= capabilities_
.max_server_wait_timeout
;
989 case GL_MAX_UNIFORM_BLOCK_SIZE
:
990 *params
= capabilities_
.max_uniform_block_size
;
996 if (!GetHelper(pname
, &value
)) {
999 *params
= static_cast<GLint64
>(value
);
1003 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
1004 return GetHelper(pname
, params
);
1007 bool GLES2Implementation::GetIntegeri_vHelper(
1008 GLenum pname
, GLuint index
, GLint
* data
) {
1009 // TODO(zmo): Implement client side caching.
1013 bool GLES2Implementation::GetInteger64i_vHelper(
1014 GLenum pname
, GLuint index
, GLint64
* data
) {
1015 // TODO(zmo): Implement client side caching.
1019 bool GLES2Implementation::GetInternalformativHelper(
1020 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
1022 // TODO(zmo): Implement the client side caching.
1026 bool GLES2Implementation::GetSyncivHelper(
1027 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
1031 case GL_OBJECT_TYPE
:
1032 value
= GL_SYNC_FENCE
;
1034 case GL_SYNC_CONDITION
:
1035 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1053 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1054 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1055 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1056 Result
* result
= GetResultAs
<Result
*>();
1061 helper_
->GetMaxValueInBufferCHROMIUM(
1062 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1067 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1068 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1069 GPU_CLIENT_SINGLE_THREAD_CHECK();
1070 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1071 << buffer_id
<< ", " << count
<< ", "
1072 << GLES2Util::GetStringGetMaxIndexType(type
)
1073 << ", " << offset
<< ")");
1074 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1075 buffer_id
, count
, type
, offset
);
1076 GPU_CLIENT_LOG("returned " << result
);
1081 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1083 RestoreArrayBuffer(restore
);
1084 // Restore the element array binding.
1085 // We only need to restore it if it wasn't a client side array.
1086 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1087 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1092 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1094 // Restore the user's current binding.
1095 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_
);
1099 void GLES2Implementation::DrawElements(
1100 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1101 GPU_CLIENT_SINGLE_THREAD_CHECK();
1102 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1103 << GLES2Util::GetStringDrawMode(mode
) << ", "
1105 << GLES2Util::GetStringIndexType(type
) << ", "
1106 << static_cast<const void*>(indices
) << ")");
1107 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1110 void GLES2Implementation::DrawRangeElements(
1111 GLenum mode
, GLuint start
, GLuint end
,
1112 GLsizei count
, GLenum type
, const void* indices
) {
1113 GPU_CLIENT_SINGLE_THREAD_CHECK();
1114 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1115 << GLES2Util::GetStringDrawMode(mode
) << ", "
1116 << start
<< ", " << end
<< ", " << count
<< ", "
1117 << GLES2Util::GetStringIndexType(type
) << ", "
1118 << static_cast<const void*>(indices
) << ")");
1120 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1123 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1126 void GLES2Implementation::DrawElementsImpl(
1127 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1128 const char* func_name
) {
1130 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1133 bool simulated
= false;
1134 GLuint offset
= ToGLuint(indices
);
1136 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1137 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1140 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1141 func_name
, this, helper_
, count
, type
, 0, indices
,
1142 &offset
, &simulated
)) {
1146 helper_
->DrawElements(mode
, count
, type
, offset
);
1147 RestoreElementAndArrayBuffers(simulated
);
1151 void GLES2Implementation::Flush() {
1152 GPU_CLIENT_SINGLE_THREAD_CHECK();
1153 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1154 // Insert the cmd to call glFlush
1156 // Flush our command buffer
1157 // (tell the service to execute up to the flush cmd.)
1158 helper_
->CommandBufferHelper::Flush();
1161 void GLES2Implementation::ShallowFlushCHROMIUM() {
1162 GPU_CLIENT_SINGLE_THREAD_CHECK();
1163 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1164 // Flush our command buffer
1165 // (tell the service to execute up to the flush cmd.)
1166 helper_
->CommandBufferHelper::Flush();
1167 // TODO(piman): Add the FreeEverything() logic here.
1170 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1171 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1172 // Flush command buffer at the GPU channel level. May be implemented as
1174 helper_
->CommandBufferHelper::OrderingBarrier();
1177 void GLES2Implementation::Finish() {
1178 GPU_CLIENT_SINGLE_THREAD_CHECK();
1182 void GLES2Implementation::ShallowFinishCHROMIUM() {
1183 GPU_CLIENT_SINGLE_THREAD_CHECK();
1184 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1185 // Flush our command buffer (tell the service to execute up to the flush cmd
1186 // and don't return until it completes).
1187 helper_
->CommandBufferHelper::Finish();
1190 void GLES2Implementation::FinishHelper() {
1191 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1192 TRACE_EVENT0("gpu", "GLES2::Finish");
1193 // Insert the cmd to call glFinish
1195 // Finish our command buffer
1196 // (tell the service to execute up to the Finish cmd and wait for it to
1198 helper_
->CommandBufferHelper::Finish();
1201 void GLES2Implementation::SwapBuffers() {
1202 GPU_CLIENT_SINGLE_THREAD_CHECK();
1203 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1204 // TODO(piman): Strictly speaking we'd want to insert the token after the
1205 // swap, but the state update with the updated token might not have happened
1206 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1207 // with the GPU process more than needed. So instead, make it happen before.
1208 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1209 // semantics if the client doesn't use the callback mechanism, and by chance
1210 // the scheduler yields between the InsertToken and the SwapBuffers.
1211 swap_buffers_tokens_
.push(helper_
->InsertToken());
1212 helper_
->SwapBuffers();
1213 helper_
->CommandBufferHelper::Flush();
1214 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1215 // compensate for TODO above.
1216 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1217 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1218 swap_buffers_tokens_
.pop();
1222 void GLES2Implementation::SwapInterval(int interval
) {
1223 GPU_CLIENT_SINGLE_THREAD_CHECK();
1224 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1225 << interval
<< ")");
1226 helper_
->SwapInterval(interval
);
1229 void GLES2Implementation::BindAttribLocation(
1230 GLuint program
, GLuint index
, const char* name
) {
1231 GPU_CLIENT_SINGLE_THREAD_CHECK();
1232 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1233 << program
<< ", " << index
<< ", " << name
<< ")");
1234 SetBucketAsString(kResultBucketId
, name
);
1235 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1236 helper_
->SetBucketSize(kResultBucketId
, 0);
1240 void GLES2Implementation::BindUniformLocationCHROMIUM(
1241 GLuint program
, GLint location
, const char* name
) {
1242 GPU_CLIENT_SINGLE_THREAD_CHECK();
1243 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1244 << program
<< ", " << location
<< ", " << name
<< ")");
1245 SetBucketAsString(kResultBucketId
, name
);
1246 helper_
->BindUniformLocationCHROMIUMBucket(
1247 program
, location
, kResultBucketId
);
1248 helper_
->SetBucketSize(kResultBucketId
, 0);
1252 void GLES2Implementation::GetVertexAttribPointerv(
1253 GLuint index
, GLenum pname
, void** ptr
) {
1254 GPU_CLIENT_SINGLE_THREAD_CHECK();
1255 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1256 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1257 << static_cast<void*>(ptr
) << ")");
1258 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1259 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1260 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1261 typedef cmds::GetVertexAttribPointerv::Result Result
;
1262 Result
* result
= GetResultAs
<Result
*>();
1266 result
->SetNumResults(0);
1267 helper_
->GetVertexAttribPointerv(
1268 index
, pname
, GetResultShmId(), GetResultShmOffset());
1270 result
->CopyResult(ptr
);
1271 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1273 GPU_CLIENT_LOG_CODE_BLOCK({
1274 for (int32 i
= 0; i
< num_results
; ++i
) {
1275 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1281 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1282 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1283 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1286 "glDeleteProgram", "id not created by this context.");
1289 if (program
== current_program_
) {
1290 current_program_
= 0;
1295 void GLES2Implementation::DeleteProgramStub(
1296 GLsizei n
, const GLuint
* programs
) {
1298 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1299 helper_
->DeleteProgram(programs
[0]);
1302 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1303 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1304 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1307 "glDeleteShader", "id not created by this context.");
1313 void GLES2Implementation::DeleteShaderStub(
1314 GLsizei n
, const GLuint
* shaders
) {
1316 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1317 helper_
->DeleteShader(shaders
[0]);
1320 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1321 GLuint sync_uint
= ToGLuint(sync
);
1322 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1323 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1326 "glDeleteSync", "id not created by this context.");
1330 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1332 helper_
->DeleteSync(syncs
[0]);
1335 GLint
GLES2Implementation::GetAttribLocationHelper(
1336 GLuint program
, const char* name
) {
1337 typedef cmds::GetAttribLocation::Result Result
;
1338 Result
* result
= GetResultAs
<Result
*>();
1343 SetBucketAsCString(kResultBucketId
, name
);
1344 helper_
->GetAttribLocation(
1345 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1347 helper_
->SetBucketSize(kResultBucketId
, 0);
1351 GLint
GLES2Implementation::GetAttribLocation(
1352 GLuint program
, const char* name
) {
1353 GPU_CLIENT_SINGLE_THREAD_CHECK();
1354 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1355 << ", " << name
<< ")");
1356 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1357 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1358 this, program
, name
);
1359 GPU_CLIENT_LOG("returned " << loc
);
1364 GLint
GLES2Implementation::GetUniformLocationHelper(
1365 GLuint program
, const char* name
) {
1366 typedef cmds::GetUniformLocation::Result Result
;
1367 Result
* result
= GetResultAs
<Result
*>();
1372 SetBucketAsCString(kResultBucketId
, name
);
1373 helper_
->GetUniformLocation(program
, kResultBucketId
,
1374 GetResultShmId(), GetResultShmOffset());
1376 helper_
->SetBucketSize(kResultBucketId
, 0);
1380 GLint
GLES2Implementation::GetUniformLocation(
1381 GLuint program
, const char* name
) {
1382 GPU_CLIENT_SINGLE_THREAD_CHECK();
1383 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1384 << ", " << name
<< ")");
1385 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1386 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1387 this, program
, name
);
1388 GPU_CLIENT_LOG("returned " << loc
);
1393 bool GLES2Implementation::GetUniformIndicesHelper(
1394 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1395 typedef cmds::GetUniformIndices::Result Result
;
1396 Result
* result
= GetResultAs
<Result
*>();
1400 result
->SetNumResults(0);
1401 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1404 helper_
->GetUniformIndices(program
, kResultBucketId
,
1405 GetResultShmId(), GetResultShmOffset());
1407 if (result
->GetNumResults() != count
) {
1410 result
->CopyResult(indices
);
1414 void GLES2Implementation::GetUniformIndices(
1415 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1416 GPU_CLIENT_SINGLE_THREAD_CHECK();
1417 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1418 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1419 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1421 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1427 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1428 this, program
, count
, names
, indices
);
1430 GPU_CLIENT_LOG_CODE_BLOCK({
1431 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1432 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1439 bool GLES2Implementation::GetProgramivHelper(
1440 GLuint program
, GLenum pname
, GLint
* params
) {
1441 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1442 this, program
, pname
, params
);
1443 GPU_CLIENT_LOG_CODE_BLOCK({
1445 GPU_CLIENT_LOG(" 0: " << *params
);
1451 GLint
GLES2Implementation::GetFragDataLocationHelper(
1452 GLuint program
, const char* name
) {
1453 typedef cmds::GetFragDataLocation::Result Result
;
1454 Result
* result
= GetResultAs
<Result
*>();
1459 SetBucketAsCString(kResultBucketId
, name
);
1460 helper_
->GetFragDataLocation(
1461 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1463 helper_
->SetBucketSize(kResultBucketId
, 0);
1467 GLint
GLES2Implementation::GetFragDataLocation(
1468 GLuint program
, const char* name
) {
1469 GPU_CLIENT_SINGLE_THREAD_CHECK();
1470 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1471 << program
<< ", " << name
<< ")");
1472 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1473 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1474 this, program
, name
);
1475 GPU_CLIENT_LOG("returned " << loc
);
1480 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1481 GLuint program
, const char* name
) {
1482 typedef cmds::GetUniformBlockIndex::Result Result
;
1483 Result
* result
= GetResultAs
<Result
*>();
1485 return GL_INVALID_INDEX
;
1487 *result
= GL_INVALID_INDEX
;
1488 SetBucketAsCString(kResultBucketId
, name
);
1489 helper_
->GetUniformBlockIndex(
1490 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1492 helper_
->SetBucketSize(kResultBucketId
, 0);
1496 GLuint
GLES2Implementation::GetUniformBlockIndex(
1497 GLuint program
, const char* name
) {
1498 GPU_CLIENT_SINGLE_THREAD_CHECK();
1499 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1500 << program
<< ", " << name
<< ")");
1501 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1502 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1503 this, program
, name
);
1504 GPU_CLIENT_LOG("returned " << index
);
1509 void GLES2Implementation::LinkProgram(GLuint program
) {
1510 GPU_CLIENT_SINGLE_THREAD_CHECK();
1511 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1512 helper_
->LinkProgram(program
);
1513 share_group_
->program_info_manager()->CreateInfo(program
);
1517 void GLES2Implementation::ShaderBinary(
1518 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1520 GPU_CLIENT_SINGLE_THREAD_CHECK();
1521 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1522 << static_cast<const void*>(shaders
) << ", "
1523 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1524 << static_cast<const void*>(binary
) << ", "
1527 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1531 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1534 // TODO(gman): ShaderBinary should use buckets.
1535 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1536 ScopedTransferBufferArray
<GLint
> buffer(
1537 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1538 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1539 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1542 void* shader_ids
= buffer
.elements();
1543 void* shader_data
= buffer
.elements() + shader_id_size
;
1544 memcpy(shader_ids
, shaders
, shader_id_size
);
1545 memcpy(shader_data
, binary
, length
);
1546 helper_
->ShaderBinary(
1552 buffer
.offset() + shader_id_size
,
1557 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1558 GPU_CLIENT_SINGLE_THREAD_CHECK();
1559 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1560 << GLES2Util::GetStringPixelStore(pname
) << ", "
1563 case GL_PACK_ALIGNMENT
:
1564 pack_alignment_
= param
;
1566 case GL_UNPACK_ALIGNMENT
:
1567 unpack_alignment_
= param
;
1569 case GL_UNPACK_ROW_LENGTH_EXT
:
1570 unpack_row_length_
= param
;
1572 case GL_UNPACK_IMAGE_HEIGHT
:
1573 unpack_image_height_
= param
;
1575 case GL_UNPACK_SKIP_ROWS_EXT
:
1576 unpack_skip_rows_
= param
;
1578 case GL_UNPACK_SKIP_PIXELS_EXT
:
1579 unpack_skip_pixels_
= param
;
1581 case GL_UNPACK_SKIP_IMAGES
:
1582 unpack_skip_images_
= param
;
1584 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1585 unpack_flip_y_
= (param
!= 0);
1587 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1588 pack_reverse_row_order_
=
1589 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1594 helper_
->PixelStorei(pname
, param
);
1598 void GLES2Implementation::VertexAttribIPointer(
1599 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1600 GPU_CLIENT_SINGLE_THREAD_CHECK();
1601 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1604 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1607 // Record the info on the client side.
1608 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1616 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1617 "client side arrays are not allowed in vertex array objects.");
1620 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1621 // Only report NON client side buffers to the service.
1622 if (!ValidateOffset("glVertexAttribIPointer",
1623 reinterpret_cast<GLintptr
>(ptr
))) {
1626 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1631 void GLES2Implementation::VertexAttribPointer(
1632 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1634 GPU_CLIENT_SINGLE_THREAD_CHECK();
1635 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1638 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1639 << GLES2Util::GetStringBool(normalized
) << ", "
1642 // Record the info on the client side.
1643 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1651 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1652 "client side arrays are not allowed in vertex array objects.");
1655 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1656 // Only report NON client side buffers to the service.
1657 if (!ValidateOffset("glVertexAttribPointer",
1658 reinterpret_cast<GLintptr
>(ptr
))) {
1661 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1667 void GLES2Implementation::VertexAttribDivisorANGLE(
1668 GLuint index
, GLuint divisor
) {
1669 GPU_CLIENT_SINGLE_THREAD_CHECK();
1670 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1672 << divisor
<< ") ");
1673 // Record the info on the client side.
1674 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1675 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1679 void GLES2Implementation::BufferDataHelper(
1680 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1681 if (!ValidateSize("glBufferData", size
))
1684 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1685 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1686 // bogus MSan report during a readback later. This is because MSan doesn't
1687 // understand shared memory and would assume we were reading back the same
1688 // unintialized data.
1689 if (data
) __msan_check_mem_is_initialized(data
, size
);
1693 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1698 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1700 RemoveTransferBuffer(buffer
);
1702 // Create new buffer.
1703 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1705 if (buffer
->address() && data
)
1706 memcpy(buffer
->address(), data
, size
);
1710 RemoveMappedBufferRangeByTarget(target
);
1712 // If there is no data just send BufferData
1713 if (size
== 0 || !data
) {
1714 helper_
->BufferData(target
, size
, 0, 0, usage
);
1718 // See if we can send all at once.
1719 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1720 if (!buffer
.valid()) {
1724 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1725 memcpy(buffer
.address(), data
, size
);
1726 helper_
->BufferData(
1735 // Make the buffer with BufferData then send via BufferSubData
1736 helper_
->BufferData(target
, size
, 0, 0, usage
);
1737 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1741 void GLES2Implementation::BufferData(
1742 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1743 GPU_CLIENT_SINGLE_THREAD_CHECK();
1744 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1745 << GLES2Util::GetStringBufferTarget(target
) << ", "
1747 << static_cast<const void*>(data
) << ", "
1748 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1749 BufferDataHelper(target
, size
, data
, usage
);
1753 void GLES2Implementation::BufferSubDataHelper(
1754 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1759 if (!ValidateSize("glBufferSubData", size
) ||
1760 !ValidateOffset("glBufferSubData", offset
)) {
1765 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1769 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1771 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1776 int32 buffer_size
= buffer
->size();
1777 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1778 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1782 if (buffer
->address() && data
)
1783 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1787 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1788 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1791 void GLES2Implementation::BufferSubDataHelperImpl(
1792 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1793 ScopedTransferBufferPtr
* buffer
) {
1797 const int8
* source
= static_cast<const int8
*>(data
);
1799 if (!buffer
->valid() || buffer
->size() == 0) {
1800 buffer
->Reset(size
);
1801 if (!buffer
->valid()) {
1805 memcpy(buffer
->address(), source
, buffer
->size());
1806 helper_
->BufferSubData(
1807 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1808 offset
+= buffer
->size();
1809 source
+= buffer
->size();
1810 size
-= buffer
->size();
1815 void GLES2Implementation::BufferSubData(
1816 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1817 GPU_CLIENT_SINGLE_THREAD_CHECK();
1818 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1819 << GLES2Util::GetStringBufferTarget(target
) << ", "
1820 << offset
<< ", " << size
<< ", "
1821 << static_cast<const void*>(data
) << ")");
1822 BufferSubDataHelper(target
, offset
, size
, data
);
1826 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1827 int32 token
= buffer
->last_usage_token();
1828 uint32 async_token
= buffer
->last_async_upload_token();
1831 if (HasAsyncUploadTokenPassed(async_token
)) {
1832 buffer_tracker_
->Free(buffer
);
1834 detached_async_upload_memory_
.push_back(
1835 std::make_pair(buffer
->address(), async_token
));
1836 buffer_tracker_
->Unmanage(buffer
);
1839 if (helper_
->HasTokenPassed(token
))
1840 buffer_tracker_
->Free(buffer
);
1842 buffer_tracker_
->FreePendingToken(buffer
, token
);
1844 buffer_tracker_
->Free(buffer
);
1847 buffer_tracker_
->RemoveBuffer(buffer
->id());
1850 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1852 const char* function_name
,
1853 GLuint
* buffer_id
) {
1857 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1858 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1860 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1861 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1868 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1873 BufferTracker::Buffer
*
1874 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1876 const char* function_name
,
1877 GLuint offset
, GLsizei size
) {
1879 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1881 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1884 if (buffer
->mapped()) {
1885 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1888 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1889 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1895 void GLES2Implementation::CompressedTexImage2D(
1896 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1897 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1898 GPU_CLIENT_SINGLE_THREAD_CHECK();
1899 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1900 << GLES2Util::GetStringTextureTarget(target
) << ", "
1902 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1903 << width
<< ", " << height
<< ", " << border
<< ", "
1904 << image_size
<< ", "
1905 << static_cast<const void*>(data
) << ")");
1906 if (width
< 0 || height
< 0 || level
< 0) {
1907 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1911 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
1914 if (height
== 0 || width
== 0) {
1917 // If there's a pixel unpack buffer bound use it when issuing
1918 // CompressedTexImage2D.
1919 if (bound_pixel_unpack_transfer_buffer_id_
) {
1920 GLuint offset
= ToGLuint(data
);
1921 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1922 bound_pixel_unpack_transfer_buffer_id_
,
1923 "glCompressedTexImage2D", offset
, image_size
);
1924 if (buffer
&& buffer
->shm_id() != -1) {
1925 helper_
->CompressedTexImage2D(
1926 target
, level
, internalformat
, width
, height
, image_size
,
1927 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1928 buffer
->set_last_usage_token(helper_
->InsertToken());
1932 SetBucketContents(kResultBucketId
, data
, image_size
);
1933 helper_
->CompressedTexImage2DBucket(
1934 target
, level
, internalformat
, width
, height
, kResultBucketId
);
1935 // Free the bucket. This is not required but it does free up the memory.
1936 // and we don't have to wait for the result so from the client's perspective
1938 helper_
->SetBucketSize(kResultBucketId
, 0);
1942 void GLES2Implementation::CompressedTexSubImage2D(
1943 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1944 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1945 GPU_CLIENT_SINGLE_THREAD_CHECK();
1946 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1947 << GLES2Util::GetStringTextureTarget(target
) << ", "
1949 << xoffset
<< ", " << yoffset
<< ", "
1950 << width
<< ", " << height
<< ", "
1951 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1952 << image_size
<< ", "
1953 << static_cast<const void*>(data
) << ")");
1954 if (width
< 0 || height
< 0 || level
< 0) {
1955 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1958 // If there's a pixel unpack buffer bound use it when issuing
1959 // CompressedTexSubImage2D.
1960 if (bound_pixel_unpack_transfer_buffer_id_
) {
1961 GLuint offset
= ToGLuint(data
);
1962 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1963 bound_pixel_unpack_transfer_buffer_id_
,
1964 "glCompressedTexSubImage2D", offset
, image_size
);
1965 if (buffer
&& buffer
->shm_id() != -1) {
1966 helper_
->CompressedTexSubImage2D(
1967 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1968 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1969 buffer
->set_last_usage_token(helper_
->InsertToken());
1974 SetBucketContents(kResultBucketId
, data
, image_size
);
1975 helper_
->CompressedTexSubImage2DBucket(
1976 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1977 // Free the bucket. This is not required but it does free up the memory.
1978 // and we don't have to wait for the result so from the client's perspective
1980 helper_
->SetBucketSize(kResultBucketId
, 0);
1984 void GLES2Implementation::CompressedTexImage3D(
1985 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1986 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
1988 GPU_CLIENT_SINGLE_THREAD_CHECK();
1989 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
1990 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
1991 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1992 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
1993 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
1994 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
1995 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
1999 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
2002 if (height
== 0 || width
== 0 || depth
== 0) {
2005 // If there's a pixel unpack buffer bound use it when issuing
2006 // CompressedTexImage3D.
2007 if (bound_pixel_unpack_transfer_buffer_id_
) {
2008 GLuint offset
= ToGLuint(data
);
2009 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2010 bound_pixel_unpack_transfer_buffer_id_
,
2011 "glCompressedTexImage3D", offset
, image_size
);
2012 if (buffer
&& buffer
->shm_id() != -1) {
2013 helper_
->CompressedTexImage3D(
2014 target
, level
, internalformat
, width
, height
, depth
, image_size
,
2015 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2016 buffer
->set_last_usage_token(helper_
->InsertToken());
2020 SetBucketContents(kResultBucketId
, data
, image_size
);
2021 helper_
->CompressedTexImage3DBucket(
2022 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
2023 // Free the bucket. This is not required but it does free up the memory.
2024 // and we don't have to wait for the result so from the client's perspective
2026 helper_
->SetBucketSize(kResultBucketId
, 0);
2030 void GLES2Implementation::CompressedTexSubImage3D(
2031 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2032 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
2033 GLsizei image_size
, const void* data
) {
2034 GPU_CLIENT_SINGLE_THREAD_CHECK();
2035 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
2036 << GLES2Util::GetStringTextureTarget(target
) << ", "
2038 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2039 << width
<< ", " << height
<< ", " << depth
<< ", "
2040 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2041 << image_size
<< ", "
2042 << static_cast<const void*>(data
) << ")");
2043 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2044 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "dimension < 0");
2047 // If there's a pixel unpack buffer bound use it when issuing
2048 // CompressedTexSubImage3D.
2049 if (bound_pixel_unpack_transfer_buffer_id_
) {
2050 GLuint offset
= ToGLuint(data
);
2051 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2052 bound_pixel_unpack_transfer_buffer_id_
,
2053 "glCompressedTexSubImage3D", offset
, image_size
);
2054 if (buffer
&& buffer
->shm_id() != -1) {
2055 helper_
->CompressedTexSubImage3D(
2056 target
, level
, xoffset
, yoffset
, zoffset
,
2057 width
, height
, depth
, format
, image_size
,
2058 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2059 buffer
->set_last_usage_token(helper_
->InsertToken());
2064 SetBucketContents(kResultBucketId
, data
, image_size
);
2065 helper_
->CompressedTexSubImage3DBucket(
2066 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
2068 // Free the bucket. This is not required but it does free up the memory.
2069 // and we don't have to wait for the result so from the client's perspective
2071 helper_
->SetBucketSize(kResultBucketId
, 0);
2077 void CopyRectToBuffer(
2080 uint32 unpadded_row_size
,
2081 uint32 pixels_padded_row_size
,
2084 uint32 buffer_padded_row_size
) {
2085 const int8
* source
= static_cast<const int8
*>(pixels
);
2086 int8
* dest
= static_cast<int8
*>(buffer
);
2087 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
2089 dest
+= buffer_padded_row_size
* (height
- 1);
2091 // the last row is copied unpadded at the end
2092 for (; height
> 1; --height
) {
2093 memcpy(dest
, source
, buffer_padded_row_size
);
2095 dest
-= buffer_padded_row_size
;
2097 dest
+= buffer_padded_row_size
;
2099 source
+= pixels_padded_row_size
;
2101 memcpy(dest
, source
, unpadded_row_size
);
2103 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2104 memcpy(dest
, source
, size
);
2108 } // anonymous namespace
2110 void GLES2Implementation::TexImage2D(
2111 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2112 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2113 const void* pixels
) {
2114 GPU_CLIENT_SINGLE_THREAD_CHECK();
2115 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2116 << GLES2Util::GetStringTextureTarget(target
) << ", "
2118 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2119 << width
<< ", " << height
<< ", " << border
<< ", "
2120 << GLES2Util::GetStringTextureFormat(format
) << ", "
2121 << GLES2Util::GetStringPixelType(type
) << ", "
2122 << static_cast<const void*>(pixels
) << ")");
2123 if (level
< 0 || height
< 0 || width
< 0) {
2124 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2128 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2132 uint32 unpadded_row_size
;
2133 uint32 padded_row_size
;
2134 if (!GLES2Util::ComputeImageDataSizes(
2135 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2136 &unpadded_row_size
, &padded_row_size
)) {
2137 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2141 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2142 if (bound_pixel_unpack_transfer_buffer_id_
) {
2143 GLuint offset
= ToGLuint(pixels
);
2144 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2145 bound_pixel_unpack_transfer_buffer_id_
,
2146 "glTexImage2D", offset
, size
);
2147 if (buffer
&& buffer
->shm_id() != -1) {
2148 helper_
->TexImage2D(
2149 target
, level
, internalformat
, width
, height
, format
, type
,
2150 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2151 buffer
->set_last_usage_token(helper_
->InsertToken());
2157 // If there's no data just issue TexImage2D
2159 helper_
->TexImage2D(
2160 target
, level
, internalformat
, width
, height
, format
, type
,
2166 // compute the advance bytes per row for the src pixels
2167 uint32 src_padded_row_size
;
2168 if (unpack_row_length_
> 0) {
2169 if (!GLES2Util::ComputeImagePaddedRowSize(
2170 unpack_row_length_
, format
, type
, unpack_alignment_
,
2171 &src_padded_row_size
)) {
2173 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2177 src_padded_row_size
= padded_row_size
;
2180 // advance pixels pointer past the skip rows and skip pixels
2181 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2182 unpack_skip_rows_
* src_padded_row_size
;
2183 if (unpack_skip_pixels_
) {
2184 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2185 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2186 unpack_skip_pixels_
* group_size
;
2189 // Check if we can send it all at once.
2190 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
2191 if (!buffer
.valid()) {
2195 if (buffer
.size() >= size
) {
2197 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
2198 buffer
.address(), padded_row_size
);
2199 helper_
->TexImage2D(
2200 target
, level
, internalformat
, width
, height
, format
, type
,
2201 buffer
.shm_id(), buffer
.offset());
2206 // No, so send it using TexSubImage2D.
2207 helper_
->TexImage2D(
2208 target
, level
, internalformat
, width
, height
, format
, type
,
2211 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2212 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
2216 void GLES2Implementation::TexImage3D(
2217 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2218 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2219 const void* pixels
) {
2220 GPU_CLIENT_SINGLE_THREAD_CHECK();
2221 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2222 << GLES2Util::GetStringTextureTarget(target
) << ", "
2224 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2225 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2226 << GLES2Util::GetStringTextureFormat(format
) << ", "
2227 << GLES2Util::GetStringPixelType(type
) << ", "
2228 << static_cast<const void*>(pixels
) << ")");
2229 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2230 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2234 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2238 uint32 unpadded_row_size
;
2239 uint32 padded_row_size
;
2240 if (!GLES2Util::ComputeImageDataSizes(
2241 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2242 &unpadded_row_size
, &padded_row_size
)) {
2243 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2247 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2248 if (bound_pixel_unpack_transfer_buffer_id_
) {
2249 GLuint offset
= ToGLuint(pixels
);
2250 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2251 bound_pixel_unpack_transfer_buffer_id_
,
2252 "glTexImage3D", offset
, size
);
2253 if (buffer
&& buffer
->shm_id() != -1) {
2254 helper_
->TexImage3D(
2255 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2256 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2257 buffer
->set_last_usage_token(helper_
->InsertToken());
2263 // If there's no data just issue TexImage3D
2265 helper_
->TexImage3D(
2266 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2272 // compute the advance bytes per row for the src pixels
2273 uint32 src_padded_row_size
;
2274 if (unpack_row_length_
> 0) {
2275 if (!GLES2Util::ComputeImagePaddedRowSize(
2276 unpack_row_length_
, format
, type
, unpack_alignment_
,
2277 &src_padded_row_size
)) {
2279 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2283 src_padded_row_size
= padded_row_size
;
2285 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2287 // advance pixels pointer past the skip images/rows/pixels
2288 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2289 unpack_skip_images_
* src_padded_row_size
* src_height
+
2290 unpack_skip_rows_
* src_padded_row_size
;
2291 if (unpack_skip_pixels_
) {
2292 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2293 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2294 unpack_skip_pixels_
* group_size
;
2297 // Check if we can send it all at once.
2298 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
2299 if (!buffer
.valid()) {
2303 if (buffer
.size() >= size
) {
2304 void* buffer_pointer
= buffer
.address();
2305 for (GLsizei z
= 0; z
< depth
; ++z
) {
2306 // Only the last row of the last image is unpadded.
2307 uint32 src_unpadded_row_size
=
2308 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2309 // TODO(zmo): Ignore flip_y flag for now.
2311 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
, false,
2312 buffer_pointer
, padded_row_size
);
2313 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2314 src_padded_row_size
* src_height
;
2315 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2316 padded_row_size
* height
;
2318 helper_
->TexImage3D(
2319 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2320 buffer
.shm_id(), buffer
.offset());
2325 // No, so send it using TexSubImage3D.
2326 helper_
->TexImage3D(
2327 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2330 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2331 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &buffer
,
2336 void GLES2Implementation::TexSubImage2D(
2337 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2338 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2339 GPU_CLIENT_SINGLE_THREAD_CHECK();
2340 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2341 << GLES2Util::GetStringTextureTarget(target
) << ", "
2343 << xoffset
<< ", " << yoffset
<< ", "
2344 << width
<< ", " << height
<< ", "
2345 << GLES2Util::GetStringTextureFormat(format
) << ", "
2346 << GLES2Util::GetStringPixelType(type
) << ", "
2347 << static_cast<const void*>(pixels
) << ")");
2349 if (level
< 0 || height
< 0 || width
< 0) {
2350 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2353 if (height
== 0 || width
== 0) {
2358 uint32 unpadded_row_size
;
2359 uint32 padded_row_size
;
2360 if (!GLES2Util::ComputeImageDataSizes(
2361 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2362 &unpadded_row_size
, &padded_row_size
)) {
2363 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2367 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2368 if (bound_pixel_unpack_transfer_buffer_id_
) {
2369 GLuint offset
= ToGLuint(pixels
);
2370 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2371 bound_pixel_unpack_transfer_buffer_id_
,
2372 "glTexSubImage2D", offset
, temp_size
);
2373 if (buffer
&& buffer
->shm_id() != -1) {
2374 helper_
->TexSubImage2D(
2375 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2376 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2377 buffer
->set_last_usage_token(helper_
->InsertToken());
2383 // compute the advance bytes per row for the src pixels
2384 uint32 src_padded_row_size
;
2385 if (unpack_row_length_
> 0) {
2386 if (!GLES2Util::ComputeImagePaddedRowSize(
2387 unpack_row_length_
, format
, type
, unpack_alignment_
,
2388 &src_padded_row_size
)) {
2390 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2394 src_padded_row_size
= padded_row_size
;
2397 // advance pixels pointer past the skip rows and skip pixels
2398 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2399 unpack_skip_rows_
* src_padded_row_size
;
2400 if (unpack_skip_pixels_
) {
2401 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2402 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2403 unpack_skip_pixels_
* group_size
;
2406 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2408 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2409 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2414 void GLES2Implementation::TexSubImage3D(
2415 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2416 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2417 const void* pixels
) {
2418 GPU_CLIENT_SINGLE_THREAD_CHECK();
2419 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2420 << GLES2Util::GetStringTextureTarget(target
) << ", "
2422 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2423 << width
<< ", " << height
<< ", " << depth
<< ", "
2424 << GLES2Util::GetStringTextureFormat(format
) << ", "
2425 << GLES2Util::GetStringPixelType(type
) << ", "
2426 << static_cast<const void*>(pixels
) << ")");
2428 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2429 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2432 if (height
== 0 || width
== 0 || depth
== 0) {
2437 uint32 unpadded_row_size
;
2438 uint32 padded_row_size
;
2439 if (!GLES2Util::ComputeImageDataSizes(
2440 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2441 &unpadded_row_size
, &padded_row_size
)) {
2442 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2446 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2447 if (bound_pixel_unpack_transfer_buffer_id_
) {
2448 GLuint offset
= ToGLuint(pixels
);
2449 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2450 bound_pixel_unpack_transfer_buffer_id_
,
2451 "glTexSubImage3D", offset
, temp_size
);
2452 if (buffer
&& buffer
->shm_id() != -1) {
2453 helper_
->TexSubImage3D(
2454 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2455 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2456 buffer
->set_last_usage_token(helper_
->InsertToken());
2462 // compute the advance bytes per row for the src pixels
2463 uint32 src_padded_row_size
;
2464 if (unpack_row_length_
> 0) {
2465 if (!GLES2Util::ComputeImagePaddedRowSize(
2466 unpack_row_length_
, format
, type
, unpack_alignment_
,
2467 &src_padded_row_size
)) {
2469 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2473 src_padded_row_size
= padded_row_size
;
2475 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2477 // advance pixels pointer past the skip images/rows/pixels
2478 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2479 unpack_skip_images_
* src_padded_row_size
* src_height
+
2480 unpack_skip_rows_
* src_padded_row_size
;
2481 if (unpack_skip_pixels_
) {
2482 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2483 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2484 unpack_skip_pixels_
* group_size
;
2487 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2489 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2490 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2491 &buffer
, padded_row_size
);
2495 static GLint
ComputeNumRowsThatFitInBuffer(
2496 uint32 padded_row_size
, uint32 unpadded_row_size
,
2497 unsigned int size
, GLsizei remaining_rows
) {
2498 DCHECK_GE(unpadded_row_size
, 0u);
2499 if (padded_row_size
== 0) {
2502 GLint num_rows
= size
/ padded_row_size
;
2503 if (num_rows
+ 1 == remaining_rows
&&
2504 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2510 void GLES2Implementation::TexSubImage2DImpl(
2511 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2512 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2513 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2514 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2516 DCHECK_GE(level
, 0);
2517 DCHECK_GT(height
, 0);
2518 DCHECK_GT(width
, 0);
2520 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2521 GLint original_yoffset
= yoffset
;
2522 // Transfer by rows.
2524 unsigned int desired_size
=
2525 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2526 if (!buffer
->valid() || buffer
->size() == 0) {
2527 buffer
->Reset(desired_size
);
2528 if (!buffer
->valid()) {
2533 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2534 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2535 num_rows
= std::min(num_rows
, height
);
2537 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2538 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
2539 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
2540 helper_
->TexSubImage2D(
2541 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
2542 buffer
->shm_id(), buffer
->offset(), internal
);
2544 yoffset
+= num_rows
;
2545 source
+= num_rows
* pixels_padded_row_size
;
2550 void GLES2Implementation::TexSubImage3DImpl(
2551 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2552 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2553 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2554 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2555 uint32 buffer_padded_row_size
) {
2557 DCHECK_GE(level
, 0);
2558 DCHECK_GT(height
, 0);
2559 DCHECK_GT(width
, 0);
2560 DCHECK_GT(depth
, 0);
2561 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2562 GLsizei total_rows
= height
* depth
;
2563 GLint row_index
= 0, depth_index
= 0;
2564 while (total_rows
) {
2565 // Each time, we either copy one or more images, or copy one or more rows
2566 // within a single image, depending on the buffer size limit.
2568 unsigned int desired_size
;
2569 if (row_index
> 0) {
2570 // We are in the middle of an image. Send the remaining of the image.
2571 max_rows
= height
- row_index
;
2572 if (total_rows
<= height
) {
2573 // Last image, so last row is unpadded.
2574 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2577 desired_size
= buffer_padded_row_size
* max_rows
;
2580 // Send all the remaining data if possible.
2581 max_rows
= total_rows
;
2583 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2585 if (!buffer
->valid() || buffer
->size() == 0) {
2586 buffer
->Reset(desired_size
);
2587 if (!buffer
->valid()) {
2591 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2592 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2593 num_rows
= std::min(num_rows
, max_rows
);
2594 GLint num_images
= num_rows
/ height
;
2595 GLsizei my_height
, my_depth
;
2596 if (num_images
> 0) {
2597 num_rows
= num_images
* height
;
2599 my_depth
= num_images
;
2601 my_height
= num_rows
;
2605 // TODO(zmo): Ignore flip_y flag for now.
2606 if (num_images
> 0) {
2607 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2609 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2610 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2611 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2612 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2613 uint32 my_unpadded_row_size
;
2614 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2615 my_unpadded_row_size
= unpadded_row_size
;
2617 my_unpadded_row_size
= pixels_padded_row_size
;
2619 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2620 pixels_padded_row_size
, false, buffer_pointer
+ ii
* image_size_dst
,
2621 buffer_padded_row_size
);
2624 uint32 my_unpadded_row_size
;
2625 if (total_rows
== num_rows
)
2626 my_unpadded_row_size
= unpadded_row_size
;
2628 my_unpadded_row_size
= pixels_padded_row_size
;
2630 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2631 false, buffer
->address(), buffer_padded_row_size
);
2633 helper_
->TexSubImage3D(
2634 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2635 width
, my_height
, my_depth
,
2636 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2639 total_rows
-= num_rows
;
2640 if (total_rows
> 0) {
2641 GLint num_image_paddings
;
2642 if (num_images
> 0) {
2643 DCHECK_EQ(row_index
, 0);
2644 depth_index
+= num_images
;
2645 num_image_paddings
= num_images
;
2647 row_index
= (row_index
+ my_height
) % height
;
2648 num_image_paddings
= 0;
2649 if (my_height
> 0 && row_index
== 0) {
2651 num_image_paddings
++;
2654 source
+= num_rows
* pixels_padded_row_size
;
2655 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2656 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2657 pixels_padded_row_size
;
2663 bool GLES2Implementation::GetActiveAttribHelper(
2664 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2665 GLenum
* type
, char* name
) {
2666 // Clear the bucket so if the command fails nothing will be in it.
2667 helper_
->SetBucketSize(kResultBucketId
, 0);
2668 typedef cmds::GetActiveAttrib::Result Result
;
2669 Result
* result
= GetResultAs
<Result
*>();
2673 // Set as failed so if the command fails we'll recover.
2674 result
->success
= false;
2675 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2676 GetResultShmId(), GetResultShmOffset());
2678 if (result
->success
) {
2680 *size
= result
->size
;
2683 *type
= result
->type
;
2685 if (length
|| name
) {
2686 std::vector
<int8
> str
;
2687 GetBucketContents(kResultBucketId
, &str
);
2688 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2689 std::max(static_cast<size_t>(0),
2694 if (name
&& bufsize
> 0) {
2695 memcpy(name
, &str
[0], max_size
);
2696 name
[max_size
] = '\0';
2700 return result
->success
!= 0;
2703 void GLES2Implementation::GetActiveAttrib(
2704 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2705 GLenum
* type
, char* name
) {
2706 GPU_CLIENT_SINGLE_THREAD_CHECK();
2707 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2708 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2709 << static_cast<const void*>(length
) << ", "
2710 << static_cast<const void*>(size
) << ", "
2711 << static_cast<const void*>(type
) << ", "
2712 << static_cast<const void*>(name
) << ", ");
2714 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2717 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2718 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2719 this, program
, index
, bufsize
, length
, size
, type
, name
);
2722 GPU_CLIENT_LOG(" size: " << *size
);
2725 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2728 GPU_CLIENT_LOG(" name: " << name
);
2734 bool GLES2Implementation::GetActiveUniformHelper(
2735 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2736 GLenum
* type
, char* name
) {
2737 // Clear the bucket so if the command fails nothing will be in it.
2738 helper_
->SetBucketSize(kResultBucketId
, 0);
2739 typedef cmds::GetActiveUniform::Result Result
;
2740 Result
* result
= GetResultAs
<Result
*>();
2744 // Set as failed so if the command fails we'll recover.
2745 result
->success
= false;
2746 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2747 GetResultShmId(), GetResultShmOffset());
2749 if (result
->success
) {
2751 *size
= result
->size
;
2754 *type
= result
->type
;
2756 if (length
|| name
) {
2757 std::vector
<int8
> str
;
2758 GetBucketContents(kResultBucketId
, &str
);
2759 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2760 std::max(static_cast<size_t>(0),
2765 if (name
&& bufsize
> 0) {
2766 memcpy(name
, &str
[0], max_size
);
2767 name
[max_size
] = '\0';
2771 return result
->success
!= 0;
2774 void GLES2Implementation::GetActiveUniform(
2775 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2776 GLenum
* type
, char* name
) {
2777 GPU_CLIENT_SINGLE_THREAD_CHECK();
2778 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2779 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2780 << static_cast<const void*>(length
) << ", "
2781 << static_cast<const void*>(size
) << ", "
2782 << static_cast<const void*>(type
) << ", "
2783 << static_cast<const void*>(name
) << ", ");
2785 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2788 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2789 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2790 this, program
, index
, bufsize
, length
, size
, type
, name
);
2793 GPU_CLIENT_LOG(" size: " << *size
);
2796 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2799 GPU_CLIENT_LOG(" name: " << name
);
2805 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2806 GLuint program
, GLuint index
, GLsizei bufsize
,
2807 GLsizei
* length
, char* name
) {
2808 DCHECK_LE(0, bufsize
);
2809 // Clear the bucket so if the command fails nothing will be in it.
2810 helper_
->SetBucketSize(kResultBucketId
, 0);
2811 typedef cmds::GetActiveUniformBlockName::Result Result
;
2812 Result
* result
= GetResultAs
<Result
*>();
2816 // Set as failed so if the command fails we'll recover.
2818 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2819 GetResultShmId(), GetResultShmOffset());
2826 } else if (length
|| name
) {
2827 std::vector
<int8
> str
;
2828 GetBucketContents(kResultBucketId
, &str
);
2829 DCHECK_GT(str
.size(), 0u);
2831 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2836 memcpy(name
, &str
[0], max_size
);
2837 name
[max_size
] = '\0';
2841 return *result
!= 0;
2844 void GLES2Implementation::GetActiveUniformBlockName(
2845 GLuint program
, GLuint index
, GLsizei bufsize
,
2846 GLsizei
* length
, char* name
) {
2847 GPU_CLIENT_SINGLE_THREAD_CHECK();
2848 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2849 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2850 << static_cast<const void*>(length
) << ", "
2851 << static_cast<const void*>(name
) << ")");
2853 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2856 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2858 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2859 this, program
, index
, bufsize
, length
, name
);
2862 GPU_CLIENT_LOG(" name: " << name
);
2868 bool GLES2Implementation::GetActiveUniformBlockivHelper(
2869 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2870 typedef cmds::GetActiveUniformBlockiv::Result Result
;
2871 Result
* result
= GetResultAs
<Result
*>();
2875 result
->SetNumResults(0);
2876 helper_
->GetActiveUniformBlockiv(
2877 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
2879 if (result
->GetNumResults() > 0) {
2881 result
->CopyResult(params
);
2883 GPU_CLIENT_LOG_CODE_BLOCK({
2884 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2885 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2893 void GLES2Implementation::GetActiveUniformBlockiv(
2894 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2895 GPU_CLIENT_SINGLE_THREAD_CHECK();
2896 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
2897 << program
<< ", " << index
<< ", "
2898 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
2899 << static_cast<const void*>(params
) << ")");
2900 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
2902 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
2903 this, program
, index
, pname
, params
);
2906 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
2907 // be more than one value returned in params.
2908 GPU_CLIENT_LOG(" params: " << params
[0]);
2914 bool GLES2Implementation::GetActiveUniformsivHelper(
2915 GLuint program
, GLsizei count
, const GLuint
* indices
,
2916 GLenum pname
, GLint
* params
) {
2917 typedef cmds::GetActiveUniformsiv::Result Result
;
2918 Result
* result
= GetResultAs
<Result
*>();
2922 result
->SetNumResults(0);
2923 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
2924 bytes
*= sizeof(GLuint
);
2925 if (!bytes
.IsValid()) {
2926 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
2929 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
2930 helper_
->GetActiveUniformsiv(
2931 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
2933 bool success
= result
->GetNumResults() == count
;
2936 result
->CopyResult(params
);
2938 GPU_CLIENT_LOG_CODE_BLOCK({
2939 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2940 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2944 helper_
->SetBucketSize(kResultBucketId
, 0);
2948 void GLES2Implementation::GetActiveUniformsiv(
2949 GLuint program
, GLsizei count
, const GLuint
* indices
,
2950 GLenum pname
, GLint
* params
) {
2951 GPU_CLIENT_SINGLE_THREAD_CHECK();
2952 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
2953 << program
<< ", " << count
<< ", "
2954 << static_cast<const void*>(indices
) << ", "
2955 << GLES2Util::GetStringUniformParameter(pname
) << ", "
2956 << static_cast<const void*>(params
) << ")");
2957 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
2959 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
2962 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
2963 this, program
, count
, indices
, pname
, params
);
2966 GPU_CLIENT_LOG_CODE_BLOCK({
2967 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
2968 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
2976 void GLES2Implementation::GetAttachedShaders(
2977 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
2978 GPU_CLIENT_SINGLE_THREAD_CHECK();
2979 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
2980 << program
<< ", " << maxcount
<< ", "
2981 << static_cast<const void*>(count
) << ", "
2982 << static_cast<const void*>(shaders
) << ", ");
2984 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2987 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2988 typedef cmds::GetAttachedShaders::Result Result
;
2989 uint32 size
= Result::ComputeSize(maxcount
);
2990 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2994 result
->SetNumResults(0);
2995 helper_
->GetAttachedShaders(
2997 transfer_buffer_
->GetShmId(),
2998 transfer_buffer_
->GetOffset(result
),
3000 int32 token
= helper_
->InsertToken();
3003 *count
= result
->GetNumResults();
3005 result
->CopyResult(shaders
);
3006 GPU_CLIENT_LOG_CODE_BLOCK({
3007 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3008 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3011 transfer_buffer_
->FreePendingToken(result
, token
);
3015 void GLES2Implementation::GetShaderPrecisionFormat(
3016 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
3017 GPU_CLIENT_SINGLE_THREAD_CHECK();
3018 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
3019 << GLES2Util::GetStringShaderType(shadertype
) << ", "
3020 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
3021 << static_cast<const void*>(range
) << ", "
3022 << static_cast<const void*>(precision
) << ", ");
3023 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
3024 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3025 Result
* result
= GetResultAs
<Result
*>();
3030 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
3031 GLStaticState::ShaderPrecisionMap::iterator i
=
3032 static_state_
.shader_precisions
.find(key
);
3033 if (i
!= static_state_
.shader_precisions
.end()) {
3034 *result
= i
->second
;
3036 result
->success
= false;
3037 helper_
->GetShaderPrecisionFormat(
3038 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
3040 if (result
->success
)
3041 static_state_
.shader_precisions
[key
] = *result
;
3044 if (result
->success
) {
3046 range
[0] = result
->min_range
;
3047 range
[1] = result
->max_range
;
3048 GPU_CLIENT_LOG(" min_range: " << range
[0]);
3049 GPU_CLIENT_LOG(" min_range: " << range
[1]);
3052 precision
[0] = result
->precision
;
3053 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
3059 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
3060 const char* result
= NULL
;
3061 // Clears the bucket so if the command fails nothing will be in it.
3062 helper_
->SetBucketSize(kResultBucketId
, 0);
3063 helper_
->GetString(name
, kResultBucketId
);
3065 if (GetBucketAsString(kResultBucketId
, &str
)) {
3066 // Adds extensions implemented on client side only.
3069 str
+= std::string(str
.empty() ? "" : " ") +
3070 "GL_CHROMIUM_flipy "
3071 "GL_EXT_unpack_subimage "
3072 "GL_CHROMIUM_map_sub";
3073 if (capabilities_
.image
)
3074 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
3075 if (capabilities_
.future_sync_points
)
3076 str
+= " GL_CHROMIUM_future_sync_point";
3082 // Because of WebGL the extensions can change. We have to cache each unique
3083 // result since we don't know when the client will stop referring to a
3084 // previous one it queries.
3085 GLStringMap::iterator it
= gl_strings_
.find(name
);
3086 if (it
== gl_strings_
.end()) {
3087 std::set
<std::string
> strings
;
3088 std::pair
<GLStringMap::iterator
, bool> insert_result
=
3089 gl_strings_
.insert(std::make_pair(name
, strings
));
3090 DCHECK(insert_result
.second
);
3091 it
= insert_result
.first
;
3093 std::set
<std::string
>& string_set
= it
->second
;
3094 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
3095 if (sit
!= string_set
.end()) {
3096 result
= sit
->c_str();
3098 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3099 string_set
.insert(str
);
3100 DCHECK(insert_result
.second
);
3101 result
= insert_result
.first
->c_str();
3104 return reinterpret_cast<const GLubyte
*>(result
);
3107 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3108 GPU_CLIENT_SINGLE_THREAD_CHECK();
3109 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3110 << GLES2Util::GetStringStringType(name
) << ")");
3111 TRACE_EVENT0("gpu", "GLES2::GetString");
3112 const GLubyte
* result
= GetStringHelper(name
);
3113 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3118 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3119 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3120 GLenum
* type
, char* name
) {
3121 // Clear the bucket so if the command fails nothing will be in it.
3122 helper_
->SetBucketSize(kResultBucketId
, 0);
3123 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3124 Result
* result
= GetResultAs
<Result
*>();
3128 // Set as failed so if the command fails we'll recover.
3129 result
->success
= false;
3130 helper_
->GetTransformFeedbackVarying(
3131 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3133 if (result
->success
) {
3135 *size
= result
->size
;
3138 *type
= result
->type
;
3140 if (length
|| name
) {
3141 std::vector
<int8
> str
;
3142 GetBucketContents(kResultBucketId
, &str
);
3143 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3152 memcpy(name
, &str
[0], max_size
);
3153 name
[max_size
] = '\0';
3154 } else if (bufsize
> 0) {
3160 return result
->success
!= 0;
3163 void GLES2Implementation::GetTransformFeedbackVarying(
3164 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3165 GLenum
* type
, char* name
) {
3166 GPU_CLIENT_SINGLE_THREAD_CHECK();
3167 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3168 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3169 << static_cast<const void*>(length
) << ", "
3170 << static_cast<const void*>(size
) << ", "
3171 << static_cast<const void*>(type
) << ", "
3172 << static_cast<const void*>(name
) << ", ");
3174 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3178 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3180 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3181 this, program
, index
, bufsize
, length
, size
, type
, name
);
3184 GPU_CLIENT_LOG(" size: " << *size
);
3187 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3190 GPU_CLIENT_LOG(" name: " << name
);
3196 void GLES2Implementation::GetUniformfv(
3197 GLuint program
, GLint location
, GLfloat
* params
) {
3198 GPU_CLIENT_SINGLE_THREAD_CHECK();
3199 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3200 << program
<< ", " << location
<< ", "
3201 << static_cast<const void*>(params
) << ")");
3202 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3203 typedef cmds::GetUniformfv::Result Result
;
3204 Result
* result
= GetResultAs
<Result
*>();
3208 result
->SetNumResults(0);
3209 helper_
->GetUniformfv(
3210 program
, location
, GetResultShmId(), GetResultShmOffset());
3212 result
->CopyResult(params
);
3213 GPU_CLIENT_LOG_CODE_BLOCK({
3214 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3215 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3221 void GLES2Implementation::GetUniformiv(
3222 GLuint program
, GLint location
, GLint
* params
) {
3223 GPU_CLIENT_SINGLE_THREAD_CHECK();
3224 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3225 << program
<< ", " << location
<< ", "
3226 << static_cast<const void*>(params
) << ")");
3227 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3228 typedef cmds::GetUniformiv::Result Result
;
3229 Result
* result
= GetResultAs
<Result
*>();
3233 result
->SetNumResults(0);
3234 helper_
->GetUniformiv(
3235 program
, location
, GetResultShmId(), GetResultShmOffset());
3237 GetResultAs
<cmds::GetUniformiv::Result
*>()->CopyResult(params
);
3238 GPU_CLIENT_LOG_CODE_BLOCK({
3239 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3240 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3246 void GLES2Implementation::GetUniformuiv(
3247 GLuint program
, GLint location
, GLuint
* params
) {
3248 GPU_CLIENT_SINGLE_THREAD_CHECK();
3249 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv("
3250 << program
<< ", " << location
<< ", "
3251 << static_cast<const void*>(params
) << ")");
3252 TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
3253 typedef cmds::GetUniformuiv::Result Result
;
3254 Result
* result
= GetResultAs
<Result
*>();
3258 result
->SetNumResults(0);
3259 helper_
->GetUniformuiv(
3260 program
, location
, GetResultShmId(), GetResultShmOffset());
3262 GetResultAs
<cmds::GetUniformuiv::Result
*>()->CopyResult(params
);
3263 GPU_CLIENT_LOG_CODE_BLOCK({
3264 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3265 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3271 void GLES2Implementation::ReadPixels(
3272 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3273 GLenum type
, void* pixels
) {
3274 GPU_CLIENT_SINGLE_THREAD_CHECK();
3275 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3276 << xoffset
<< ", " << yoffset
<< ", "
3277 << width
<< ", " << height
<< ", "
3278 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3279 << GLES2Util::GetStringPixelType(type
) << ", "
3280 << static_cast<const void*>(pixels
) << ")");
3281 if (width
< 0 || height
< 0) {
3282 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3285 if (width
== 0 || height
== 0) {
3289 // glReadPixel pads the size of each row of pixels by an amount specified by
3290 // glPixelStorei. So, we have to take that into account both in the fact that
3291 // the pixels returned from the ReadPixel command will include that padding
3292 // and that when we copy the results to the user's buffer we need to not
3293 // write those padding bytes but leave them as they are.
3295 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3296 typedef cmds::ReadPixels::Result Result
;
3298 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3300 uint32 unpadded_row_size
;
3301 uint32 padded_row_size
;
3302 if (!GLES2Util::ComputeImageDataSizes(
3303 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3304 &unpadded_row_size
, &padded_row_size
)) {
3305 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3309 if (bound_pixel_pack_transfer_buffer_id_
) {
3310 GLuint offset
= ToGLuint(pixels
);
3311 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3312 bound_pixel_pack_transfer_buffer_id_
,
3313 "glReadPixels", offset
, padded_row_size
* height
);
3314 if (buffer
&& buffer
->shm_id() != -1) {
3315 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3316 buffer
->shm_id(), buffer
->shm_offset(),
3324 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3328 // Transfer by rows.
3329 // The max rows we can transfer.
3331 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3332 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3333 if (!buffer
.valid()) {
3336 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3337 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3338 num_rows
= std::min(num_rows
, height
);
3339 // NOTE: We must look up the address of the result area AFTER allocation
3340 // of the transfer buffer since the transfer buffer may be reallocated.
3341 Result
* result
= GetResultAs
<Result
*>();
3345 *result
= 0; // mark as failed.
3346 helper_
->ReadPixels(
3347 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3348 buffer
.shm_id(), buffer
.offset(),
3349 GetResultShmId(), GetResultShmOffset(),
3353 // when doing a y-flip we have to iterate through top-to-bottom chunks
3354 // of the dst. The service side handles reversing the rows within a
3357 if (pack_reverse_row_order_
) {
3358 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3362 // We have to copy 1 row at a time to avoid writing pad bytes.
3363 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3364 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3365 memcpy(rows_dst
, src
, unpadded_row_size
);
3366 rows_dst
+= padded_row_size
;
3367 src
+= padded_row_size
;
3369 if (!pack_reverse_row_order_
) {
3373 // If it was not marked as successful exit.
3377 yoffset
+= num_rows
;
3383 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3384 GPU_CLIENT_SINGLE_THREAD_CHECK();
3385 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3386 << GLES2Util::GetStringEnum(texture
) << ")");
3387 GLuint texture_index
= texture
- GL_TEXTURE0
;
3388 if (texture_index
>=
3389 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3390 SetGLErrorInvalidEnum(
3391 "glActiveTexture", texture
, "texture");
3395 active_texture_unit_
= texture_index
;
3396 helper_
->ActiveTexture(texture
);
3400 void GLES2Implementation::GenBuffersHelper(
3401 GLsizei
/* n */, const GLuint
* /* buffers */) {
3404 void GLES2Implementation::GenFramebuffersHelper(
3405 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3408 void GLES2Implementation::GenRenderbuffersHelper(
3409 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3412 void GLES2Implementation::GenTexturesHelper(
3413 GLsizei
/* n */, const GLuint
* /* textures */) {
3416 void GLES2Implementation::GenVertexArraysOESHelper(
3417 GLsizei n
, const GLuint
* arrays
) {
3418 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3421 void GLES2Implementation::GenQueriesEXTHelper(
3422 GLsizei
/* n */, const GLuint
* /* queries */) {
3425 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3427 const GLuint
* /* valuebuffers */) {
3430 void GLES2Implementation::GenSamplersHelper(
3431 GLsizei
/* n */, const GLuint
* /* samplers */) {
3434 void GLES2Implementation::GenTransformFeedbacksHelper(
3435 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3438 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3439 // generates a new resource. On newer versions of OpenGL they don't. The code
3440 // related to binding below will need to change if we switch to the new OpenGL
3441 // model. Specifically it assumes a bind will succeed which is always true in
3442 // the old model but possibly not true in the new model if another context has
3443 // deleted the resource.
3445 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3446 // used even when Bind has failed. However, the bug is minor compared to the
3447 // overhead & duplicated checking in client side.
3449 void GLES2Implementation::BindBufferHelper(
3450 GLenum target
, GLuint buffer_id
) {
3451 // TODO(gman): See note #1 above.
3452 bool changed
= false;
3454 case GL_ARRAY_BUFFER
:
3455 if (bound_array_buffer_
!= buffer_id
) {
3456 bound_array_buffer_
= buffer_id
;
3460 case GL_COPY_READ_BUFFER
:
3461 if (bound_copy_read_buffer_
!= buffer_id
) {
3462 bound_copy_read_buffer_
= buffer_id
;
3466 case GL_COPY_WRITE_BUFFER
:
3467 if (bound_copy_write_buffer_
!= buffer_id
) {
3468 bound_copy_write_buffer_
= buffer_id
;
3472 case GL_ELEMENT_ARRAY_BUFFER
:
3473 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3475 case GL_PIXEL_PACK_BUFFER
:
3476 if (bound_pixel_pack_buffer_
!= buffer_id
) {
3477 bound_pixel_pack_buffer_
= buffer_id
;
3481 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3482 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3484 case GL_PIXEL_UNPACK_BUFFER
:
3485 if (bound_pixel_unpack_buffer_
!= buffer_id
) {
3486 bound_pixel_unpack_buffer_
= buffer_id
;
3490 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3491 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3493 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3494 if (bound_transform_feedback_buffer_
!= buffer_id
) {
3495 bound_transform_feedback_buffer_
= buffer_id
;
3499 case GL_UNIFORM_BUFFER
:
3500 if (bound_uniform_buffer_
!= buffer_id
) {
3501 bound_uniform_buffer_
= buffer_id
;
3509 // TODO(gman): See note #2 above.
3511 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3512 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3516 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3517 helper_
->BindBuffer(target
, buffer
);
3518 if (share_group_
->bind_generates_resource())
3519 helper_
->CommandBufferHelper::Flush();
3522 void GLES2Implementation::BindBufferBaseHelper(
3523 GLenum target
, GLuint index
, GLuint buffer_id
) {
3524 // TODO(zmo): See note #1 above.
3525 // TODO(zmo): See note #2 above.
3526 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3527 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3530 void GLES2Implementation::BindBufferBaseStub(
3531 GLenum target
, GLuint index
, GLuint buffer
) {
3532 helper_
->BindBufferBase(target
, index
, buffer
);
3533 if (share_group_
->bind_generates_resource())
3534 helper_
->CommandBufferHelper::Flush();
3537 void GLES2Implementation::BindBufferRangeHelper(
3538 GLenum target
, GLuint index
, GLuint buffer_id
,
3539 GLintptr offset
, GLsizeiptr size
) {
3540 // TODO(zmo): See note #1 above.
3541 // TODO(zmo): See note #2 above.
3542 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3543 this, target
, index
, buffer_id
, offset
, size
,
3544 &GLES2Implementation::BindBufferRangeStub
);
3547 void GLES2Implementation::BindBufferRangeStub(
3548 GLenum target
, GLuint index
, GLuint buffer
,
3549 GLintptr offset
, GLsizeiptr size
) {
3550 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3551 if (share_group_
->bind_generates_resource())
3552 helper_
->CommandBufferHelper::Flush();
3555 void GLES2Implementation::BindFramebufferHelper(
3556 GLenum target
, GLuint framebuffer
) {
3557 // TODO(gman): See note #1 above.
3558 bool changed
= false;
3560 case GL_FRAMEBUFFER
:
3561 if (bound_framebuffer_
!= framebuffer
||
3562 bound_read_framebuffer_
!= framebuffer
) {
3563 bound_framebuffer_
= framebuffer
;
3564 bound_read_framebuffer_
= framebuffer
;
3568 case GL_READ_FRAMEBUFFER
:
3569 if (!IsChromiumFramebufferMultisampleAvailable()) {
3570 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3573 if (bound_read_framebuffer_
!= framebuffer
) {
3574 bound_read_framebuffer_
= framebuffer
;
3578 case GL_DRAW_FRAMEBUFFER
:
3579 if (!IsChromiumFramebufferMultisampleAvailable()) {
3580 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3583 if (bound_framebuffer_
!= framebuffer
) {
3584 bound_framebuffer_
= framebuffer
;
3589 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3594 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3595 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3599 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3600 GLuint framebuffer
) {
3601 helper_
->BindFramebuffer(target
, framebuffer
);
3602 if (share_group_
->bind_generates_resource())
3603 helper_
->CommandBufferHelper::Flush();
3606 void GLES2Implementation::BindRenderbufferHelper(
3607 GLenum target
, GLuint renderbuffer
) {
3608 // TODO(gman): See note #1 above.
3609 bool changed
= false;
3611 case GL_RENDERBUFFER
:
3612 if (bound_renderbuffer_
!= renderbuffer
) {
3613 bound_renderbuffer_
= renderbuffer
;
3621 // TODO(zmo): See note #2 above.
3623 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3624 this, target
, renderbuffer
,
3625 &GLES2Implementation::BindRenderbufferStub
);
3629 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3630 GLuint renderbuffer
) {
3631 helper_
->BindRenderbuffer(target
, renderbuffer
);
3632 if (share_group_
->bind_generates_resource())
3633 helper_
->CommandBufferHelper::Flush();
3636 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3638 helper_
->BindSampler(unit
, sampler
);
3641 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3642 // TODO(gman): See note #1 above.
3643 // TODO(gman): Change this to false once we figure out why it's failing
3645 bool changed
= true;
3646 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3649 if (unit
.bound_texture_2d
!= texture
) {
3650 unit
.bound_texture_2d
= texture
;
3654 case GL_TEXTURE_CUBE_MAP
:
3655 if (unit
.bound_texture_cube_map
!= texture
) {
3656 unit
.bound_texture_cube_map
= texture
;
3660 case GL_TEXTURE_EXTERNAL_OES
:
3661 if (unit
.bound_texture_external_oes
!= texture
) {
3662 unit
.bound_texture_external_oes
= texture
;
3670 // TODO(gman): See note #2 above.
3672 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3673 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3677 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3678 helper_
->BindTexture(target
, texture
);
3679 if (share_group_
->bind_generates_resource())
3680 helper_
->CommandBufferHelper::Flush();
3683 void GLES2Implementation::BindTransformFeedbackHelper(
3684 GLenum target
, GLuint transformfeedback
) {
3685 helper_
->BindTransformFeedback(target
, transformfeedback
);
3688 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3689 bool changed
= false;
3690 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3692 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3693 // because unlike other resources VertexArrayObject ids must
3694 // be generated by GenVertexArrays. A random id to Bind will not
3695 // generate a new object.
3696 helper_
->BindVertexArrayOES(array
);
3700 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3701 "id was not generated with glGenVertexArrayOES");
3705 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3706 GLuint valuebuffer
) {
3707 bool changed
= false;
3709 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3710 if (bound_valuebuffer_
!= valuebuffer
) {
3711 bound_valuebuffer_
= valuebuffer
;
3719 // TODO(gman): See note #2 above.
3721 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3722 this, target
, valuebuffer
,
3723 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3727 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3728 GLuint valuebuffer
) {
3729 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3730 if (share_group_
->bind_generates_resource())
3731 helper_
->CommandBufferHelper::Flush();
3734 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3735 if (current_program_
!= program
) {
3736 current_program_
= program
;
3737 helper_
->UseProgram(program
);
3741 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3742 return vertex_array_object_manager_
->IsReservedId(id
);
3745 void GLES2Implementation::DeleteBuffersHelper(
3746 GLsizei n
, const GLuint
* buffers
) {
3747 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3748 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3751 "glDeleteBuffers", "id not created by this context.");
3754 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3755 if (buffers
[ii
] == bound_array_buffer_
) {
3756 bound_array_buffer_
= 0;
3758 if (buffers
[ii
] == bound_copy_read_buffer_
) {
3759 bound_copy_read_buffer_
= 0;
3761 if (buffers
[ii
] == bound_copy_write_buffer_
) {
3762 bound_copy_write_buffer_
= 0;
3764 if (buffers
[ii
] == bound_pixel_pack_buffer_
) {
3765 bound_pixel_pack_buffer_
= 0;
3767 if (buffers
[ii
] == bound_pixel_unpack_buffer_
) {
3768 bound_pixel_unpack_buffer_
= 0;
3770 if (buffers
[ii
] == bound_transform_feedback_buffer_
) {
3771 bound_transform_feedback_buffer_
= 0;
3773 if (buffers
[ii
] == bound_uniform_buffer_
) {
3774 bound_uniform_buffer_
= 0;
3776 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3778 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3780 RemoveTransferBuffer(buffer
);
3782 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3783 bound_pixel_unpack_transfer_buffer_id_
= 0;
3786 RemoveMappedBufferRangeById(buffers
[ii
]);
3790 void GLES2Implementation::DeleteBuffersStub(
3791 GLsizei n
, const GLuint
* buffers
) {
3792 helper_
->DeleteBuffersImmediate(n
, buffers
);
3796 void GLES2Implementation::DeleteFramebuffersHelper(
3797 GLsizei n
, const GLuint
* framebuffers
) {
3798 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3799 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3802 "glDeleteFramebuffers", "id not created by this context.");
3805 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3806 if (framebuffers
[ii
] == bound_framebuffer_
) {
3807 bound_framebuffer_
= 0;
3809 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3810 bound_read_framebuffer_
= 0;
3815 void GLES2Implementation::DeleteFramebuffersStub(
3816 GLsizei n
, const GLuint
* framebuffers
) {
3817 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3820 void GLES2Implementation::DeleteRenderbuffersHelper(
3821 GLsizei n
, const GLuint
* renderbuffers
) {
3822 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3823 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3826 "glDeleteRenderbuffers", "id not created by this context.");
3829 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3830 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3831 bound_renderbuffer_
= 0;
3836 void GLES2Implementation::DeleteRenderbuffersStub(
3837 GLsizei n
, const GLuint
* renderbuffers
) {
3838 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3841 void GLES2Implementation::DeleteTexturesHelper(
3842 GLsizei n
, const GLuint
* textures
) {
3843 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3844 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3847 "glDeleteTextures", "id not created by this context.");
3850 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3851 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3853 TextureUnit
& unit
= texture_units_
[tt
];
3854 if (textures
[ii
] == unit
.bound_texture_2d
) {
3855 unit
.bound_texture_2d
= 0;
3857 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3858 unit
.bound_texture_cube_map
= 0;
3860 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3861 unit
.bound_texture_external_oes
= 0;
3867 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
3868 const GLuint
* textures
) {
3869 helper_
->DeleteTexturesImmediate(n
, textures
);
3872 void GLES2Implementation::DeleteVertexArraysOESHelper(
3873 GLsizei n
, const GLuint
* arrays
) {
3874 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
3875 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
3876 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
3879 "glDeleteVertexArraysOES", "id not created by this context.");
3884 void GLES2Implementation::DeleteVertexArraysOESStub(
3885 GLsizei n
, const GLuint
* arrays
) {
3886 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
3889 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
3891 const GLuint
* valuebuffers
) {
3892 if (!GetIdHandler(id_namespaces::kValuebuffers
)
3893 ->FreeIds(this, n
, valuebuffers
,
3894 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
3895 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
3896 "id not created by this context.");
3899 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3900 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
3901 bound_valuebuffer_
= 0;
3906 void GLES2Implementation::DeleteSamplersStub(
3907 GLsizei n
, const GLuint
* samplers
) {
3908 helper_
->DeleteSamplersImmediate(n
, samplers
);
3911 void GLES2Implementation::DeleteSamplersHelper(
3912 GLsizei n
, const GLuint
* samplers
) {
3913 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
3914 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
3917 "glDeleteSamplers", "id not created by this context.");
3922 void GLES2Implementation::DeleteTransformFeedbacksStub(
3923 GLsizei n
, const GLuint
* transformfeedbacks
) {
3924 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
3927 void GLES2Implementation::DeleteTransformFeedbacksHelper(
3928 GLsizei n
, const GLuint
* transformfeedbacks
) {
3929 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
3930 this, n
, transformfeedbacks
,
3931 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
3934 "glDeleteTransformFeedbacks", "id not created by this context.");
3939 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
3941 const GLuint
* valuebuffers
) {
3942 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
3945 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
3946 GPU_CLIENT_SINGLE_THREAD_CHECK();
3948 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
3949 vertex_array_object_manager_
->SetAttribEnable(index
, false);
3950 helper_
->DisableVertexAttribArray(index
);
3954 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
3955 GPU_CLIENT_SINGLE_THREAD_CHECK();
3956 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
3958 vertex_array_object_manager_
->SetAttribEnable(index
, true);
3959 helper_
->EnableVertexAttribArray(index
);
3963 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
3964 GPU_CLIENT_SINGLE_THREAD_CHECK();
3965 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
3966 << GLES2Util::GetStringDrawMode(mode
) << ", "
3967 << first
<< ", " << count
<< ")");
3969 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
3972 bool simulated
= false;
3973 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3974 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
3977 helper_
->DrawArrays(mode
, first
, count
);
3978 RestoreArrayBuffer(simulated
);
3982 void GLES2Implementation::GetVertexAttribfv(
3983 GLuint index
, GLenum pname
, GLfloat
* params
) {
3984 GPU_CLIENT_SINGLE_THREAD_CHECK();
3985 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
3987 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
3988 << static_cast<const void*>(params
) << ")");
3990 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
3991 *params
= static_cast<GLfloat
>(value
);
3994 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
3995 typedef cmds::GetVertexAttribfv::Result Result
;
3996 Result
* result
= GetResultAs
<Result
*>();
4000 result
->SetNumResults(0);
4001 helper_
->GetVertexAttribfv(
4002 index
, pname
, GetResultShmId(), GetResultShmOffset());
4004 result
->CopyResult(params
);
4005 GPU_CLIENT_LOG_CODE_BLOCK({
4006 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4007 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4013 void GLES2Implementation::GetVertexAttribiv(
4014 GLuint index
, GLenum pname
, GLint
* params
) {
4015 GPU_CLIENT_SINGLE_THREAD_CHECK();
4016 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
4018 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4019 << static_cast<const void*>(params
) << ")");
4021 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4022 *params
= static_cast<GLint
>(value
);
4025 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
4026 typedef cmds::GetVertexAttribiv::Result Result
;
4027 Result
* result
= GetResultAs
<Result
*>();
4031 result
->SetNumResults(0);
4032 helper_
->GetVertexAttribiv(
4033 index
, pname
, GetResultShmId(), GetResultShmOffset());
4035 result
->CopyResult(params
);
4036 GPU_CLIENT_LOG_CODE_BLOCK({
4037 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4038 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4044 void GLES2Implementation::GetVertexAttribIiv(
4045 GLuint index
, GLenum pname
, GLint
* params
) {
4046 GPU_CLIENT_SINGLE_THREAD_CHECK();
4047 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv("
4049 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4050 << static_cast<const void*>(params
) << ")");
4052 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4053 *params
= static_cast<GLint
>(value
);
4056 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
4057 typedef cmds::GetVertexAttribiv::Result Result
;
4058 Result
* result
= GetResultAs
<Result
*>();
4062 result
->SetNumResults(0);
4063 helper_
->GetVertexAttribIiv(
4064 index
, pname
, GetResultShmId(), GetResultShmOffset());
4066 result
->CopyResult(params
);
4067 GPU_CLIENT_LOG_CODE_BLOCK({
4068 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4069 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4075 void GLES2Implementation::GetVertexAttribIuiv(
4076 GLuint index
, GLenum pname
, GLuint
* params
) {
4077 GPU_CLIENT_SINGLE_THREAD_CHECK();
4078 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv("
4080 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4081 << static_cast<const void*>(params
) << ")");
4083 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4084 *params
= static_cast<GLuint
>(value
);
4087 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
4088 typedef cmds::GetVertexAttribiv::Result Result
;
4089 Result
* result
= GetResultAs
<Result
*>();
4093 result
->SetNumResults(0);
4094 helper_
->GetVertexAttribIuiv(
4095 index
, pname
, GetResultShmId(), GetResultShmOffset());
4097 result
->CopyResult(params
);
4098 GPU_CLIENT_LOG_CODE_BLOCK({
4099 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4100 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4106 void GLES2Implementation::Swap() {
4110 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
4111 PostSubBufferCHROMIUM(
4112 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
4115 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
4116 switch (plane_transform
) {
4117 case gfx::OVERLAY_TRANSFORM_INVALID
:
4119 case gfx::OVERLAY_TRANSFORM_NONE
:
4120 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4121 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
4122 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
4123 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
4124 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
4125 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
4126 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
4127 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
4128 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
4129 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
4130 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
4133 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4136 void GLES2Implementation::ScheduleOverlayPlane(
4138 gfx::OverlayTransform plane_transform
,
4139 unsigned overlay_texture_id
,
4140 const gfx::Rect
& display_bounds
,
4141 const gfx::RectF
& uv_rect
) {
4142 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
4143 GetGLESOverlayTransform(plane_transform
),
4147 display_bounds
.width(),
4148 display_bounds
.height(),
4155 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
4156 const char* feature
) {
4157 GPU_CLIENT_SINGLE_THREAD_CHECK();
4158 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
4160 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
4161 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
4162 Result
* result
= GetResultAs
<Result
*>();
4167 SetBucketAsCString(kResultBucketId
, feature
);
4168 helper_
->EnableFeatureCHROMIUM(
4169 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
4171 helper_
->SetBucketSize(kResultBucketId
, 0);
4172 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
4173 return *result
!= 0;
4176 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
4177 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
4178 GPU_CLIENT_SINGLE_THREAD_CHECK();
4179 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
4180 << target
<< ", " << offset
<< ", " << size
<< ", "
4181 << GLES2Util::GetStringEnum(access
) << ")");
4182 // NOTE: target is NOT checked because the service will check it
4183 // and we don't know what targets are valid.
4184 if (access
!= GL_WRITE_ONLY
) {
4185 SetGLErrorInvalidEnum(
4186 "glMapBufferSubDataCHROMIUM", access
, "access");
4189 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
4190 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
4195 unsigned int shm_offset
;
4196 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4198 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
4202 std::pair
<MappedBufferMap::iterator
, bool> result
=
4203 mapped_buffers_
.insert(std::make_pair(
4206 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4207 DCHECK(result
.second
);
4208 GPU_CLIENT_LOG(" returned " << mem
);
4212 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
4213 GPU_CLIENT_SINGLE_THREAD_CHECK();
4215 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
4216 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
4217 if (it
== mapped_buffers_
.end()) {
4219 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
4222 const MappedBuffer
& mb
= it
->second
;
4223 helper_
->BufferSubData(
4224 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
4225 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
4226 mapped_buffers_
.erase(it
);
4230 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
4231 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
4233 bool cached
= GetHelper(binding
, &id
);
4235 return static_cast<GLuint
>(id
);
4238 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
4239 GLuint buffer
= GetBoundBufferHelper(target
);
4240 RemoveMappedBufferRangeById(buffer
);
4243 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4245 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4246 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4247 mapped_memory_
->FreePendingToken(
4248 iter
->second
.shm_memory
, helper_
->InsertToken());
4249 mapped_buffer_range_map_
.erase(iter
);
4254 void GLES2Implementation::ClearMappedBufferRangeMap() {
4255 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4256 if (buffer_range
.second
.shm_memory
) {
4257 mapped_memory_
->FreePendingToken(
4258 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4261 mapped_buffer_range_map_
.clear();
4264 void* GLES2Implementation::MapBufferRange(
4265 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4266 GPU_CLIENT_SINGLE_THREAD_CHECK();
4267 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4268 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4269 << size
<< ", " << access
<< ")");
4270 if (!ValidateSize("glMapBufferRange", size
) ||
4271 !ValidateOffset("glMapBufferRange", offset
)) {
4276 unsigned int shm_offset
;
4277 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4279 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4283 typedef cmds::MapBufferRange::Result Result
;
4284 Result
* result
= GetResultAs
<Result
*>();
4286 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4287 GetResultShmId(), GetResultShmOffset());
4288 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4289 // consider an early return without WaitForCmd(). crbug.com/465804.
4292 const GLbitfield kInvalidateBits
=
4293 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4294 if ((access
& kInvalidateBits
) != 0) {
4295 // We do not read back from the buffer, therefore, we set the client
4296 // side memory to zero to avoid uninitialized data.
4297 memset(mem
, 0, size
);
4299 GLuint buffer
= GetBoundBufferHelper(target
);
4300 DCHECK_NE(0u, buffer
);
4301 // glMapBufferRange fails on an already mapped buffer.
4302 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4303 mapped_buffer_range_map_
.end());
4304 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4306 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4307 DCHECK(iter
.second
);
4309 mapped_memory_
->Free(mem
);
4313 GPU_CLIENT_LOG(" returned " << mem
);
4318 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4319 GPU_CLIENT_SINGLE_THREAD_CHECK();
4320 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4321 << GLES2Util::GetStringEnum(target
) << ")");
4323 case GL_ARRAY_BUFFER
:
4324 case GL_ELEMENT_ARRAY_BUFFER
:
4325 case GL_COPY_READ_BUFFER
:
4326 case GL_COPY_WRITE_BUFFER
:
4327 case GL_PIXEL_PACK_BUFFER
:
4328 case GL_PIXEL_UNPACK_BUFFER
:
4329 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4330 case GL_UNIFORM_BUFFER
:
4333 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4336 GLuint buffer
= GetBoundBufferHelper(target
);
4338 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4341 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4342 if (iter
== mapped_buffer_range_map_
.end()) {
4343 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4347 helper_
->UnmapBuffer(target
);
4348 RemoveMappedBufferRangeById(buffer
);
4349 // TODO(zmo): There is a rare situation that data might be corrupted and
4350 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4351 // don't have to WaitForCmd().
4352 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4357 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4367 GPU_CLIENT_SINGLE_THREAD_CHECK();
4368 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4369 << target
<< ", " << level
<< ", "
4370 << xoffset
<< ", " << yoffset
<< ", "
4371 << width
<< ", " << height
<< ", "
4372 << GLES2Util::GetStringTextureFormat(format
) << ", "
4373 << GLES2Util::GetStringPixelType(type
) << ", "
4374 << GLES2Util::GetStringEnum(access
) << ")");
4375 if (access
!= GL_WRITE_ONLY
) {
4376 SetGLErrorInvalidEnum(
4377 "glMapTexSubImage2DCHROMIUM", access
, "access");
4380 // NOTE: target is NOT checked because the service will check it
4381 // and we don't know what targets are valid.
4382 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4384 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4388 if (!GLES2Util::ComputeImageDataSizes(
4389 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4391 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4395 unsigned int shm_offset
;
4396 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4398 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4402 std::pair
<MappedTextureMap::iterator
, bool> result
=
4403 mapped_textures_
.insert(std::make_pair(
4406 access
, shm_id
, mem
, shm_offset
,
4407 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4408 DCHECK(result
.second
);
4409 GPU_CLIENT_LOG(" returned " << mem
);
4413 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4414 GPU_CLIENT_SINGLE_THREAD_CHECK();
4416 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4417 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4418 if (it
== mapped_textures_
.end()) {
4420 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4423 const MappedTexture
& mt
= it
->second
;
4424 helper_
->TexSubImage2D(
4425 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4426 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4427 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4428 mapped_textures_
.erase(it
);
4432 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4433 float scale_factor
) {
4434 GPU_CLIENT_SINGLE_THREAD_CHECK();
4435 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4436 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4437 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4441 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4442 GPU_CLIENT_SINGLE_THREAD_CHECK();
4443 GPU_CLIENT_LOG("[" << GetLogPrefix()
4444 << "] glGetRequestableExtensionsCHROMIUM()");
4446 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4447 const char* result
= NULL
;
4448 // Clear the bucket so if the command fails nothing will be in it.
4449 helper_
->SetBucketSize(kResultBucketId
, 0);
4450 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4452 if (GetBucketAsString(kResultBucketId
, &str
)) {
4453 // The set of requestable extensions shrinks as we enable
4454 // them. Because we don't know when the client will stop referring
4455 // to a previous one it queries (see GetString) we need to cache
4456 // the unique results.
4457 std::set
<std::string
>::const_iterator sit
=
4458 requestable_extensions_set_
.find(str
);
4459 if (sit
!= requestable_extensions_set_
.end()) {
4460 result
= sit
->c_str();
4462 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4463 requestable_extensions_set_
.insert(str
);
4464 DCHECK(insert_result
.second
);
4465 result
= insert_result
.first
->c_str();
4468 GPU_CLIENT_LOG(" returned " << result
);
4469 return reinterpret_cast<const GLchar
*>(result
);
4472 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4473 // with VirtualGL contexts.
4474 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4475 GPU_CLIENT_SINGLE_THREAD_CHECK();
4476 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4477 << extension
<< ")");
4478 SetBucketAsCString(kResultBucketId
, extension
);
4479 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4480 helper_
->SetBucketSize(kResultBucketId
, 0);
4482 struct ExtensionCheck
{
4483 const char* extension
;
4484 ExtensionStatus
* status
;
4486 const ExtensionCheck checks
[] = {
4488 "GL_ANGLE_pack_reverse_row_order",
4489 &angle_pack_reverse_row_order_status_
,
4492 "GL_CHROMIUM_framebuffer_multisample",
4493 &chromium_framebuffer_multisample_
,
4496 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4497 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4498 const ExtensionCheck
& check
= checks
[ii
];
4499 if (*check
.status
== kUnavailableExtensionStatus
&&
4500 !strcmp(extension
, check
.extension
)) {
4501 *check
.status
= kUnknownExtensionStatus
;
4506 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4507 GPU_CLIENT_SINGLE_THREAD_CHECK();
4508 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4509 // Wait if this would add too many rate limit tokens.
4510 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4511 helper_
->WaitForToken(rate_limit_tokens_
.front());
4512 rate_limit_tokens_
.pop();
4514 rate_limit_tokens_
.push(helper_
->InsertToken());
4517 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4518 GLuint program
, std::vector
<int8
>* result
) {
4520 // Clear the bucket so if the command fails nothing will be in it.
4521 helper_
->SetBucketSize(kResultBucketId
, 0);
4522 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4523 GetBucketContents(kResultBucketId
, result
);
4526 void GLES2Implementation::GetProgramInfoCHROMIUM(
4527 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4528 GPU_CLIENT_SINGLE_THREAD_CHECK();
4531 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4535 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4538 // Make sure they've set size to 0 else the value will be undefined on
4540 DCHECK_EQ(0, *size
);
4541 std::vector
<int8
> result
;
4542 GetProgramInfoCHROMIUMHelper(program
, &result
);
4543 if (result
.empty()) {
4546 *size
= result
.size();
4550 if (static_cast<size_t>(bufsize
) < result
.size()) {
4551 SetGLError(GL_INVALID_OPERATION
,
4552 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4555 memcpy(info
, &result
[0], result
.size());
4558 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4559 GLuint program
, std::vector
<int8
>* result
) {
4561 // Clear the bucket so if the command fails nothing will be in it.
4562 helper_
->SetBucketSize(kResultBucketId
, 0);
4563 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4564 GetBucketContents(kResultBucketId
, result
);
4567 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4568 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4569 GPU_CLIENT_SINGLE_THREAD_CHECK();
4572 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4576 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4579 // Make sure they've set size to 0 else the value will be undefined on
4581 DCHECK_EQ(0, *size
);
4582 std::vector
<int8
> result
;
4583 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4584 if (result
.empty()) {
4587 *size
= result
.size();
4591 if (static_cast<size_t>(bufsize
) < result
.size()) {
4592 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4593 "bufsize is too small for result.");
4596 memcpy(info
, &result
[0], result
.size());
4599 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4600 GLuint program
, std::vector
<int8
>* result
) {
4602 // Clear the bucket so if the command fails nothing will be in it.
4603 helper_
->SetBucketSize(kResultBucketId
, 0);
4604 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4605 GetBucketContents(kResultBucketId
, result
);
4608 void GLES2Implementation::GetUniformsES3CHROMIUM(
4609 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4610 GPU_CLIENT_SINGLE_THREAD_CHECK();
4613 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4617 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4620 // Make sure they've set size to 0 else the value will be undefined on
4622 DCHECK_EQ(0, *size
);
4623 std::vector
<int8
> result
;
4624 GetUniformsES3CHROMIUMHelper(program
, &result
);
4625 if (result
.empty()) {
4628 *size
= result
.size();
4632 if (static_cast<size_t>(bufsize
) < result
.size()) {
4633 SetGLError(GL_INVALID_OPERATION
,
4634 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4637 memcpy(info
, &result
[0], result
.size());
4640 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4641 GLuint program
, std::vector
<int8
>* result
) {
4643 // Clear the bucket so if the command fails nothing will be in it.
4644 helper_
->SetBucketSize(kResultBucketId
, 0);
4645 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4646 GetBucketContents(kResultBucketId
, result
);
4649 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4650 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4651 GPU_CLIENT_SINGLE_THREAD_CHECK();
4653 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4654 "bufsize less than 0.");
4658 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4662 // Make sure they've set size to 0 else the value will be undefined on
4664 DCHECK_EQ(0, *size
);
4665 std::vector
<int8
> result
;
4666 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4667 if (result
.empty()) {
4670 *size
= result
.size();
4674 if (static_cast<size_t>(bufsize
) < result
.size()) {
4675 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4676 "bufsize is too small for result.");
4679 memcpy(info
, &result
[0], result
.size());
4682 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4683 GPU_CLIENT_SINGLE_THREAD_CHECK();
4684 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4686 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4687 helper_
->CommandBufferHelper::Flush();
4688 return gpu_control_
->CreateStreamTexture(texture
);
4691 void GLES2Implementation::PostSubBufferCHROMIUM(
4692 GLint x
, GLint y
, GLint width
, GLint height
) {
4693 GPU_CLIENT_SINGLE_THREAD_CHECK();
4694 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4695 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4696 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4697 "width", width
, "height", height
);
4699 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4700 swap_buffers_tokens_
.push(helper_
->InsertToken());
4701 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4702 helper_
->CommandBufferHelper::Flush();
4703 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4704 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4705 swap_buffers_tokens_
.pop();
4709 void GLES2Implementation::DeleteQueriesEXTHelper(
4710 GLsizei n
, const GLuint
* queries
) {
4711 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4712 query_tracker_
->RemoveQuery(queries
[ii
]);
4713 query_id_allocator_
->FreeID(queries
[ii
]);
4716 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4719 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4720 GPU_CLIENT_SINGLE_THREAD_CHECK();
4721 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4723 // TODO(gman): To be spec compliant IDs from other contexts sharing
4724 // resources need to return true here even though you can't share
4725 // queries across contexts?
4726 return query_tracker_
->GetQuery(id
) != NULL
;
4729 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4730 GPU_CLIENT_SINGLE_THREAD_CHECK();
4731 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4732 << GLES2Util::GetStringQueryTarget(target
)
4733 << ", " << id
<< ")");
4735 // if any outstanding queries INV_OP
4736 QueryMap::iterator it
= current_queries_
.find(target
);
4737 if (it
!= current_queries_
.end()) {
4739 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4745 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4749 // if not GENned INV_OPERATION
4750 if (!query_id_allocator_
->InUse(id
)) {
4751 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4755 // if id does not have an object
4756 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4758 query
= query_tracker_
->CreateQuery(id
, target
);
4760 SetGLError(GL_OUT_OF_MEMORY
,
4762 "transfer buffer allocation failed");
4765 } else if (query
->target() != target
) {
4767 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
4771 current_queries_
[target
] = query
;
4777 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4778 GPU_CLIENT_SINGLE_THREAD_CHECK();
4779 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4780 << GLES2Util::GetStringQueryTarget(target
) << ")");
4781 // Don't do anything if the context is lost.
4782 if (helper_
->IsContextLost()) {
4786 QueryMap::iterator it
= current_queries_
.find(target
);
4787 if (it
== current_queries_
.end()) {
4788 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
4792 QueryTracker::Query
* query
= it
->second
;
4794 current_queries_
.erase(it
);
4798 void GLES2Implementation::GetQueryivEXT(
4799 GLenum target
, GLenum pname
, GLint
* params
) {
4800 GPU_CLIENT_SINGLE_THREAD_CHECK();
4801 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
4802 << GLES2Util::GetStringQueryTarget(target
) << ", "
4803 << GLES2Util::GetStringQueryParameter(pname
) << ", "
4804 << static_cast<const void*>(params
) << ")");
4806 if (pname
!= GL_CURRENT_QUERY_EXT
) {
4807 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
4810 QueryMap::iterator it
= current_queries_
.find(target
);
4811 if (it
!= current_queries_
.end()) {
4812 QueryTracker::Query
* query
= it
->second
;
4813 *params
= query
->id();
4817 GPU_CLIENT_LOG(" " << *params
);
4821 void GLES2Implementation::GetQueryObjectuivEXT(
4822 GLuint id
, GLenum pname
, GLuint
* params
) {
4823 GPU_CLIENT_SINGLE_THREAD_CHECK();
4824 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
4825 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
4826 << static_cast<const void*>(params
) << ")");
4828 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4830 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
4834 QueryMap::iterator it
= current_queries_
.find(query
->target());
4835 if (it
!= current_queries_
.end()) {
4837 GL_INVALID_OPERATION
,
4838 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
4842 if (query
->NeverUsed()) {
4844 GL_INVALID_OPERATION
,
4845 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
4850 case GL_QUERY_RESULT_EXT
:
4851 if (!query
->CheckResultsAvailable(helper_
)) {
4852 helper_
->WaitForToken(query
->token());
4853 if (!query
->CheckResultsAvailable(helper_
)) {
4855 CHECK(query
->CheckResultsAvailable(helper_
));
4858 *params
= query
->GetResult();
4860 case GL_QUERY_RESULT_AVAILABLE_EXT
:
4861 *params
= query
->CheckResultsAvailable(helper_
);
4864 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
4867 GPU_CLIENT_LOG(" " << *params
);
4871 void GLES2Implementation::DrawArraysInstancedANGLE(
4872 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
4873 GPU_CLIENT_SINGLE_THREAD_CHECK();
4874 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
4875 << GLES2Util::GetStringDrawMode(mode
) << ", "
4876 << first
<< ", " << count
<< ", " << primcount
<< ")");
4878 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
4881 if (primcount
< 0) {
4882 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
4885 if (primcount
== 0) {
4888 bool simulated
= false;
4889 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4890 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
4894 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
4895 RestoreArrayBuffer(simulated
);
4899 void GLES2Implementation::DrawElementsInstancedANGLE(
4900 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
4901 GLsizei primcount
) {
4902 GPU_CLIENT_SINGLE_THREAD_CHECK();
4903 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
4904 << GLES2Util::GetStringDrawMode(mode
) << ", "
4906 << GLES2Util::GetStringIndexType(type
) << ", "
4907 << static_cast<const void*>(indices
) << ", "
4908 << primcount
<< ")");
4910 SetGLError(GL_INVALID_VALUE
,
4911 "glDrawElementsInstancedANGLE", "count less than 0.");
4917 if (primcount
< 0) {
4918 SetGLError(GL_INVALID_VALUE
,
4919 "glDrawElementsInstancedANGLE", "primcount < 0");
4922 if (primcount
== 0) {
4925 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
4926 !ValidateOffset("glDrawElementsInstancedANGLE",
4927 reinterpret_cast<GLintptr
>(indices
))) {
4931 bool simulated
= false;
4932 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
4933 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
4934 indices
, &offset
, &simulated
)) {
4937 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
4938 RestoreElementAndArrayBuffers(simulated
);
4942 void GLES2Implementation::GenMailboxCHROMIUM(
4944 GPU_CLIENT_SINGLE_THREAD_CHECK();
4945 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
4946 << static_cast<const void*>(mailbox
) << ")");
4947 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
4949 gpu::Mailbox result
= gpu::Mailbox::Generate();
4950 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
4953 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
4954 const GLbyte
* data
) {
4955 GPU_CLIENT_SINGLE_THREAD_CHECK();
4956 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
4957 << static_cast<const void*>(data
) << ")");
4958 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4959 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
4960 "mailbox that was not generated by "
4961 "GenMailboxCHROMIUM.";
4962 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
4966 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
4967 GLuint texture
, GLenum target
, const GLbyte
* data
) {
4968 GPU_CLIENT_SINGLE_THREAD_CHECK();
4969 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
4970 << static_cast<const void*>(data
) << ")");
4971 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4972 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
4973 "mailbox that was not generated by "
4974 "GenMailboxCHROMIUM.";
4975 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
4979 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
4980 const GLbyte
* data
) {
4981 GPU_CLIENT_SINGLE_THREAD_CHECK();
4982 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
4983 << static_cast<const void*>(data
) << ")");
4984 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4985 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
4986 "mailbox that was not generated by "
4987 "GenMailboxCHROMIUM.";
4988 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
4992 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
4993 GLenum target
, const GLbyte
* data
) {
4994 GPU_CLIENT_SINGLE_THREAD_CHECK();
4995 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
4996 << static_cast<const void*>(data
) << ")");
4997 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4998 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
4999 "mailbox that was not generated by "
5000 "GenMailboxCHROMIUM.";
5002 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
5003 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
5005 if (share_group_
->bind_generates_resource())
5006 helper_
->CommandBufferHelper::Flush();
5011 void GLES2Implementation::PushGroupMarkerEXT(
5012 GLsizei length
, const GLchar
* marker
) {
5013 GPU_CLIENT_SINGLE_THREAD_CHECK();
5014 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
5015 << length
<< ", " << marker
<< ")");
5021 (length
? std::string(marker
, length
) : std::string(marker
)));
5022 helper_
->PushGroupMarkerEXT(kResultBucketId
);
5023 helper_
->SetBucketSize(kResultBucketId
, 0);
5024 debug_marker_manager_
.PushGroup(
5025 length
? std::string(marker
, length
) : std::string(marker
));
5028 void GLES2Implementation::InsertEventMarkerEXT(
5029 GLsizei length
, const GLchar
* marker
) {
5030 GPU_CLIENT_SINGLE_THREAD_CHECK();
5031 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
5032 << length
<< ", " << marker
<< ")");
5038 (length
? std::string(marker
, length
) : std::string(marker
)));
5039 helper_
->InsertEventMarkerEXT(kResultBucketId
);
5040 helper_
->SetBucketSize(kResultBucketId
, 0);
5041 debug_marker_manager_
.SetMarker(
5042 length
? std::string(marker
, length
) : std::string(marker
));
5045 void GLES2Implementation::PopGroupMarkerEXT() {
5046 GPU_CLIENT_SINGLE_THREAD_CHECK();
5047 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
5048 helper_
->PopGroupMarkerEXT();
5049 debug_marker_manager_
.PopGroup();
5052 void GLES2Implementation::TraceBeginCHROMIUM(
5053 const char* category_name
, const char* trace_name
) {
5054 GPU_CLIENT_SINGLE_THREAD_CHECK();
5055 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
5056 << category_name
<< ", " << trace_name
<< ")");
5057 SetBucketAsCString(kResultBucketId
, category_name
);
5058 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
5059 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
5060 helper_
->SetBucketSize(kResultBucketId
, 0);
5061 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
5062 current_trace_stack_
++;
5065 void GLES2Implementation::TraceEndCHROMIUM() {
5066 GPU_CLIENT_SINGLE_THREAD_CHECK();
5067 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
5068 if (current_trace_stack_
== 0) {
5069 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
5070 "missing begin trace");
5073 helper_
->TraceEndCHROMIUM();
5074 current_trace_stack_
--;
5077 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
5078 GPU_CLIENT_SINGLE_THREAD_CHECK();
5079 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
5080 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
5082 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
5083 if (access
!= GL_READ_ONLY
) {
5084 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5088 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
5089 if (access
!= GL_WRITE_ONLY
) {
5090 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5096 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
5100 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
5104 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5106 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
5109 if (buffer
->mapped()) {
5110 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
5113 // Here we wait for previous transfer operations to be finished.
5114 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
5115 // with this method of synchronization. Until this is fixed,
5116 // MapBufferCHROMIUM will not block even if the transfer is not ready
5118 if (buffer
->last_usage_token()) {
5119 helper_
->WaitForToken(buffer
->last_usage_token());
5120 buffer
->set_last_usage_token(0);
5122 buffer
->set_mapped(true);
5124 GPU_CLIENT_LOG(" returned " << buffer
->address());
5126 return buffer
->address();
5129 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
5130 GPU_CLIENT_SINGLE_THREAD_CHECK();
5132 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
5134 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
5135 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
5140 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5142 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
5145 if (!buffer
->mapped()) {
5146 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
5149 buffer
->set_mapped(false);
5154 bool GLES2Implementation::EnsureAsyncUploadSync() {
5155 if (async_upload_sync_
)
5159 unsigned int shm_offset
;
5160 void* mem
= mapped_memory_
->Alloc(sizeof(AsyncUploadSync
),
5166 async_upload_sync_shm_id_
= shm_id
;
5167 async_upload_sync_shm_offset_
= shm_offset
;
5168 async_upload_sync_
= static_cast<AsyncUploadSync
*>(mem
);
5169 async_upload_sync_
->Reset();
5174 uint32
GLES2Implementation::NextAsyncUploadToken() {
5175 async_upload_token_
++;
5176 if (async_upload_token_
== 0)
5177 async_upload_token_
++;
5178 return async_upload_token_
;
5181 void GLES2Implementation::PollAsyncUploads() {
5182 if (!async_upload_sync_
)
5185 if (helper_
->IsContextLost()) {
5186 DetachedAsyncUploadMemoryList::iterator it
=
5187 detached_async_upload_memory_
.begin();
5188 while (it
!= detached_async_upload_memory_
.end()) {
5189 mapped_memory_
->Free(it
->first
);
5190 it
= detached_async_upload_memory_
.erase(it
);
5195 DetachedAsyncUploadMemoryList::iterator it
=
5196 detached_async_upload_memory_
.begin();
5197 while (it
!= detached_async_upload_memory_
.end()) {
5198 if (HasAsyncUploadTokenPassed(it
->second
)) {
5199 mapped_memory_
->Free(it
->first
);
5200 it
= detached_async_upload_memory_
.erase(it
);
5207 void GLES2Implementation::FreeAllAsyncUploadBuffers() {
5208 // Free all completed unmanaged async uploads buffers.
5211 // Synchronously free rest of the unmanaged async upload buffers.
5212 if (!detached_async_upload_memory_
.empty()) {
5213 WaitAllAsyncTexImage2DCHROMIUM();
5219 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
5220 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
5221 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
5222 const void* pixels
) {
5223 GPU_CLIENT_SINGLE_THREAD_CHECK();
5224 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
5225 << GLES2Util::GetStringTextureTarget(target
) << ", "
5227 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
5228 << width
<< ", " << height
<< ", " << border
<< ", "
5229 << GLES2Util::GetStringTextureFormat(format
) << ", "
5230 << GLES2Util::GetStringPixelType(type
) << ", "
5231 << static_cast<const void*>(pixels
) << ")");
5232 if (level
< 0 || height
< 0 || width
< 0) {
5233 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
5237 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
5241 uint32 unpadded_row_size
;
5242 uint32 padded_row_size
;
5243 if (!GLES2Util::ComputeImageDataSizes(
5244 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5245 &unpadded_row_size
, &padded_row_size
)) {
5246 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
5250 // If there's no data/buffer just issue the AsyncTexImage2D
5251 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
5252 helper_
->AsyncTexImage2DCHROMIUM(
5253 target
, level
, internalformat
, width
, height
, format
, type
,
5258 if (!EnsureAsyncUploadSync()) {
5259 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5263 // Otherwise, async uploads require a transfer buffer to be bound.
5264 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5265 // the buffer before the transfer is finished. (Currently such
5266 // synchronization has to be handled manually.)
5267 GLuint offset
= ToGLuint(pixels
);
5268 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5269 bound_pixel_unpack_transfer_buffer_id_
,
5270 "glAsyncTexImage2DCHROMIUM", offset
, size
);
5271 if (buffer
&& buffer
->shm_id() != -1) {
5272 uint32 async_token
= NextAsyncUploadToken();
5273 buffer
->set_last_async_upload_token(async_token
);
5274 helper_
->AsyncTexImage2DCHROMIUM(
5275 target
, level
, internalformat
, width
, height
, format
, type
,
5276 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5278 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5282 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
5283 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
5284 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
5285 GPU_CLIENT_SINGLE_THREAD_CHECK();
5286 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
5287 << GLES2Util::GetStringTextureTarget(target
) << ", "
5289 << xoffset
<< ", " << yoffset
<< ", "
5290 << width
<< ", " << height
<< ", "
5291 << GLES2Util::GetStringTextureFormat(format
) << ", "
5292 << GLES2Util::GetStringPixelType(type
) << ", "
5293 << static_cast<const void*>(pixels
) << ")");
5294 if (level
< 0 || height
< 0 || width
< 0) {
5296 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
5301 uint32 unpadded_row_size
;
5302 uint32 padded_row_size
;
5303 if (!GLES2Util::ComputeImageDataSizes(
5304 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5305 &unpadded_row_size
, &padded_row_size
)) {
5307 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
5311 if (!EnsureAsyncUploadSync()) {
5312 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5316 // Async uploads require a transfer buffer to be bound.
5317 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5318 // the buffer before the transfer is finished. (Currently such
5319 // synchronization has to be handled manually.)
5320 GLuint offset
= ToGLuint(pixels
);
5321 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5322 bound_pixel_unpack_transfer_buffer_id_
,
5323 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
5324 if (buffer
&& buffer
->shm_id() != -1) {
5325 uint32 async_token
= NextAsyncUploadToken();
5326 buffer
->set_last_async_upload_token(async_token
);
5327 helper_
->AsyncTexSubImage2DCHROMIUM(
5328 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
5329 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5331 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5335 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
5336 GPU_CLIENT_SINGLE_THREAD_CHECK();
5337 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
5338 << GLES2Util::GetStringTextureTarget(target
) << ")");
5339 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
5343 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() {
5344 GPU_CLIENT_SINGLE_THREAD_CHECK();
5345 GPU_CLIENT_LOG("[" << GetLogPrefix()
5346 << "] glWaitAllAsyncTexImage2DCHROMIUM()");
5347 helper_
->WaitAllAsyncTexImage2DCHROMIUM();
5351 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5352 GPU_CLIENT_SINGLE_THREAD_CHECK();
5353 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5354 helper_
->CommandBufferHelper::Flush();
5355 return gpu_control_
->InsertSyncPoint();
5358 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5359 GPU_CLIENT_SINGLE_THREAD_CHECK();
5360 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5361 DCHECK(capabilities_
.future_sync_points
);
5362 return gpu_control_
->InsertFutureSyncPoint();
5365 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5366 GPU_CLIENT_SINGLE_THREAD_CHECK();
5367 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5368 << sync_point
<< ")");
5369 DCHECK(capabilities_
.future_sync_points
);
5370 helper_
->CommandBufferHelper::Flush();
5371 gpu_control_
->RetireSyncPoint(sync_point
);
5376 bool ValidImageFormat(GLenum internalformat
,
5377 const Capabilities
& capabilities
) {
5378 switch (internalformat
) {
5379 case GL_ATC_RGB_AMD
:
5380 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
5381 return capabilities
.texture_format_atc
;
5382 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
5383 return capabilities
.texture_format_dxt1
;
5384 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
5385 return capabilities
.texture_format_dxt5
;
5386 case GL_ETC1_RGB8_OES
:
5387 return capabilities
.texture_format_etc1
;
5398 bool ValidImageUsage(GLenum usage
) {
5400 case GL_MAP_CHROMIUM
:
5401 case GL_SCANOUT_CHROMIUM
:
5410 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5413 GLenum internalformat
) {
5415 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5420 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5424 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5425 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5430 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5432 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5438 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5441 GLenum internalformat
) {
5442 GPU_CLIENT_SINGLE_THREAD_CHECK();
5443 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5444 << ", " << height
<< ", "
5445 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5448 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5453 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5454 // Flush the command stream to make sure all pending commands
5455 // that may refer to the image_id are executed on the service side.
5456 helper_
->CommandBufferHelper::Flush();
5457 gpu_control_
->DestroyImage(image_id
);
5460 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5461 GPU_CLIENT_SINGLE_THREAD_CHECK();
5462 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5463 << image_id
<< ")");
5464 DestroyImageCHROMIUMHelper(image_id
);
5468 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5471 GLenum internalformat
,
5475 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5480 SetGLError(GL_INVALID_VALUE
,
5481 "glCreateGpuMemoryBufferImageCHROMIUM",
5486 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5487 SetGLError(GL_INVALID_VALUE
,
5488 "glCreateGpuMemoryBufferImageCHROMIUM",
5493 if (!ValidImageUsage(usage
)) {
5494 SetGLError(GL_INVALID_VALUE
,
5495 "glCreateGpuMemoryBufferImageCHROMIUM",
5500 // Flush the command stream to ensure ordering in case the newly
5501 // returned image_id has recently been in use with a different buffer.
5502 helper_
->CommandBufferHelper::Flush();
5503 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5504 width
, height
, internalformat
, usage
);
5506 SetGLError(GL_OUT_OF_MEMORY
,
5507 "glCreateGpuMemoryBufferImageCHROMIUM",
5514 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5517 GLenum internalformat
,
5519 GPU_CLIENT_SINGLE_THREAD_CHECK();
5520 GPU_CLIENT_LOG("[" << GetLogPrefix()
5521 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5522 << ", " << height
<< ", "
5523 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5524 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5525 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5526 width
, height
, internalformat
, usage
);
5531 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5533 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5536 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5537 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5543 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5545 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5548 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5549 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5555 bool GLES2Implementation::GetSamplerParameterfvHelper(
5556 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5557 // TODO(zmo): Implement client side caching.
5561 bool GLES2Implementation::GetSamplerParameterivHelper(
5562 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5563 // TODO(zmo): Implement client side caching.
5567 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5568 const char* const* str
,
5569 const GLint
* length
,
5570 const char* func_name
) {
5571 DCHECK_LE(0, count
);
5572 // Compute the total size.
5573 base::CheckedNumeric
<size_t> total_size
= count
;
5575 total_size
*= sizeof(GLint
);
5576 if (!total_size
.IsValid()) {
5577 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5580 size_t header_size
= total_size
.ValueOrDefault(0);
5581 std::vector
<GLint
> header(count
+ 1);
5582 header
[0] = static_cast<GLint
>(count
);
5583 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5586 len
= (length
&& length
[ii
] >= 0)
5588 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5591 total_size
+= 1; // NULL at the end of each char array.
5592 if (!total_size
.IsValid()) {
5593 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5596 header
[ii
+ 1] = len
;
5598 // Pack data into a bucket on the service.
5599 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5601 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5603 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5604 base::CheckedNumeric
<size_t> checked_size
=
5605 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5607 checked_size
+= 1; // NULL in the end.
5609 if (!checked_size
.IsValid()) {
5610 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5613 size_t size
= checked_size
.ValueOrDefault(0);
5615 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5616 if (!buffer
.valid() || buffer
.size() == 0) {
5617 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5620 size_t copy_size
= buffer
.size();
5621 if (ii
> 0 && buffer
.size() == size
)
5624 memcpy(buffer
.address(), src
, copy_size
);
5625 if (copy_size
< buffer
.size()) {
5626 // Append NULL in the end.
5627 DCHECK(copy_size
+ 1 == buffer
.size());
5628 char* str
= reinterpret_cast<char*>(buffer
.address());
5631 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5632 buffer
.shm_id(), buffer
.offset());
5633 offset
+= buffer
.size();
5634 src
+= buffer
.size();
5635 size
-= buffer
.size();
5638 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5642 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5645 GPU_CLIENT_SINGLE_THREAD_CHECK();
5646 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5647 << ", " << index
<< ", " << binding
<< ")");
5648 share_group_
->program_info_manager()->UniformBlockBinding(
5649 this, program
, index
, binding
);
5650 helper_
->UniformBlockBinding(program
, index
, binding
);
5654 GLenum
GLES2Implementation::ClientWaitSync(
5655 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5656 GPU_CLIENT_SINGLE_THREAD_CHECK();
5657 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5658 << ", " << flags
<< ", " << timeout
<< ")");
5659 typedef cmds::ClientWaitSync::Result Result
;
5660 Result
* result
= GetResultAs
<Result
*>();
5662 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5663 return GL_WAIT_FAILED
;
5665 *result
= GL_WAIT_FAILED
;
5666 uint32_t v32_0
= 0, v32_1
= 0;
5667 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5668 helper_
->ClientWaitSync(
5669 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5670 GetResultShmId(), GetResultShmOffset());
5672 GPU_CLIENT_LOG("returned " << *result
);
5677 void GLES2Implementation::WaitSync(
5678 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5679 GPU_CLIENT_SINGLE_THREAD_CHECK();
5680 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5681 << flags
<< ", " << timeout
<< ")");
5682 uint32_t v32_0
= 0, v32_1
= 0;
5683 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5684 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5688 // Include the auto-generated part of this file. We split this because it means
5689 // we can easily edit the non-auto generated parts right here in this file
5690 // instead of having to edit some template or the code generator.
5691 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5693 } // namespace gles2