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_id_(0),
95 bound_pixel_pack_transfer_buffer_id_(0),
96 bound_pixel_unpack_transfer_buffer_id_(0),
97 async_upload_token_(0),
98 async_upload_sync_(NULL
),
99 async_upload_sync_shm_id_(0),
100 async_upload_sync_shm_offset_(0),
103 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
104 support_client_side_arrays_(support_client_side_arrays
),
106 error_message_callback_(NULL
),
107 current_trace_stack_(0),
108 gpu_control_(gpu_control
),
109 capabilities_(gpu_control
->GetCapabilities()),
110 weak_ptr_factory_(this) {
112 DCHECK(transfer_buffer
);
115 std::stringstream ss
;
116 ss
<< std::hex
<< this;
117 this_in_hex_
= ss
.str();
119 GPU_CLIENT_LOG_CODE_BLOCK({
120 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
121 switches::kEnableGPUClientLogging
);
125 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
126 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
128 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
131 bool GLES2Implementation::Initialize(
132 unsigned int starting_transfer_buffer_size
,
133 unsigned int min_transfer_buffer_size
,
134 unsigned int max_transfer_buffer_size
,
135 unsigned int mapped_memory_limit
) {
136 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
137 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
138 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
139 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
141 if (!transfer_buffer_
->Initialize(
142 starting_transfer_buffer_size
,
144 min_transfer_buffer_size
,
145 max_transfer_buffer_size
,
151 mapped_memory_
.reset(
152 new MappedMemoryManager(
154 base::Bind(&GLES2Implementation::PollAsyncUploads
,
155 // The mapped memory manager is owned by |this| here, and
156 // since its destroyed before before we destroy ourselves
157 // we don't need extra safety measures for this closure.
158 base::Unretained(this)),
159 mapped_memory_limit
));
161 unsigned chunk_size
= 2 * 1024 * 1024;
162 if (mapped_memory_limit
!= kNoLimit
) {
163 // Use smaller chunks if the client is very memory conscientious.
164 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
166 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
168 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
169 &static_state_
.shader_precisions
;
170 capabilities_
.VisitPrecisions([shader_precisions
](
171 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
172 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
173 cmds::GetShaderPrecisionFormat::Result cached_result
= {
174 true, result
->min_range
, result
->max_range
, result
->precision
};
175 shader_precisions
->insert(std::make_pair(key
, cached_result
));
178 util_
.set_num_compressed_texture_formats(
179 capabilities_
.num_compressed_texture_formats
);
180 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
182 texture_units_
.reset(
183 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
185 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
186 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
188 query_id_allocator_
.reset(new IdAllocator());
189 if (support_client_side_arrays_
) {
190 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
191 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
194 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
195 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
196 support_client_side_arrays_
));
198 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
199 // on Client & Service.
200 if (capabilities_
.bind_generates_resource_chromium
!=
201 (share_group_
->bind_generates_resource() ? 1 : 0)) {
202 SetGLError(GL_INVALID_OPERATION
,
204 "Service bind_generates_resource mismatch.");
211 GLES2Implementation::~GLES2Implementation() {
212 // Make sure the queries are finished otherwise we'll delete the
213 // shared memory (mapped_memory_) which will free the memory used
214 // by the queries. The GPU process when validating that memory is still
215 // shared will fail and abort (ie, it will stop running).
217 query_tracker_
.reset();
219 // GLES2Implementation::Initialize() could fail before allocating
220 // reserved_ids_, so we need delete them carefully.
221 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
222 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
225 // Release remaining BufferRange mem; This is when a MapBufferRange() is
226 // called but not the UnmapBuffer() pair.
227 ClearMappedBufferRangeMap();
229 // Release any per-context data in share group.
230 share_group_
->FreeContext(this);
232 buffer_tracker_
.reset();
234 FreeAllAsyncUploadBuffers();
236 if (async_upload_sync_
) {
237 mapped_memory_
->Free(async_upload_sync_
);
238 async_upload_sync_
= NULL
;
241 // Make sure the commands make it the service.
245 GLES2CmdHelper
* GLES2Implementation::helper() const {
249 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
250 return share_group_
->GetIdHandler(namespace_id
);
253 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
254 if (namespace_id
== id_namespaces::kQueries
)
255 return query_id_allocator_
.get();
260 void* GLES2Implementation::GetResultBuffer() {
261 return transfer_buffer_
->GetResultBuffer();
264 int32
GLES2Implementation::GetResultShmId() {
265 return transfer_buffer_
->GetShmId();
268 uint32
GLES2Implementation::GetResultShmOffset() {
269 return transfer_buffer_
->GetResultOffset();
272 void GLES2Implementation::FreeUnusedSharedMemory() {
273 mapped_memory_
->FreeUnused();
276 void GLES2Implementation::FreeEverything() {
277 FreeAllAsyncUploadBuffers();
279 query_tracker_
->Shrink();
280 FreeUnusedSharedMemory();
281 transfer_buffer_
->Free();
282 helper_
->FreeRingBuffer();
285 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
286 if (!helper_
->IsContextLost())
290 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
291 const base::Closure
& callback
) {
292 gpu_control_
->SignalSyncPoint(
294 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
295 weak_ptr_factory_
.GetWeakPtr(),
299 void GLES2Implementation::SignalQuery(uint32 query
,
300 const base::Closure
& callback
) {
301 // Flush previously entered commands to ensure ordering with any
302 // glBeginQueryEXT() calls that may have been put into the context.
303 ShallowFlushCHROMIUM();
304 gpu_control_
->SignalQuery(
306 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
307 weak_ptr_factory_
.GetWeakPtr(),
311 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
313 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
314 // TODO(piman): This probably should be ShallowFlushCHROMIUM().
316 gpu_control_
->SetSurfaceVisible(visible
);
321 void GLES2Implementation::WaitForCmd() {
322 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
323 helper_
->CommandBufferHelper::Finish();
326 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
327 const char* extensions
=
328 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
332 int length
= strlen(ext
);
334 int n
= strcspn(extensions
, " ");
335 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
338 if ('\0' == extensions
[n
]) {
345 bool GLES2Implementation::IsExtensionAvailableHelper(
346 const char* extension
, ExtensionStatus
* status
) {
348 case kAvailableExtensionStatus
:
350 case kUnavailableExtensionStatus
:
353 bool available
= IsExtensionAvailable(extension
);
354 *status
= available
? kAvailableExtensionStatus
:
355 kUnavailableExtensionStatus
;
361 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
362 return IsExtensionAvailableHelper(
363 "GL_ANGLE_pack_reverse_row_order",
364 &angle_pack_reverse_row_order_status_
);
367 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
368 return IsExtensionAvailableHelper(
369 "GL_CHROMIUM_framebuffer_multisample",
370 &chromium_framebuffer_multisample_
);
373 const std::string
& GLES2Implementation::GetLogPrefix() const {
374 const std::string
& prefix(debug_marker_manager_
.GetMarker());
375 return prefix
.empty() ? this_in_hex_
: prefix
;
378 GLenum
GLES2Implementation::GetError() {
379 GPU_CLIENT_SINGLE_THREAD_CHECK();
380 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
381 GLenum err
= GetGLError();
382 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
386 GLenum
GLES2Implementation::GetClientSideGLError() {
387 if (error_bits_
== 0) {
391 GLenum error
= GL_NO_ERROR
;
392 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
393 if ((error_bits_
& mask
) != 0) {
394 error
= GLES2Util::GLErrorBitToGLError(mask
);
398 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
402 GLenum
GLES2Implementation::GetGLError() {
403 TRACE_EVENT0("gpu", "GLES2::GetGLError");
404 // Check the GL error first, then our wrapped error.
405 typedef cmds::GetError::Result Result
;
406 Result
* result
= GetResultAs
<Result
*>();
407 // If we couldn't allocate a result the context is lost.
411 *result
= GL_NO_ERROR
;
412 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
414 GLenum error
= *result
;
415 if (error
== GL_NO_ERROR
) {
416 error
= GetClientSideGLError();
418 // There was an error, clear the corresponding wrapped error.
419 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
424 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
425 void GLES2Implementation::FailGLError(GLenum error
) {
426 if (error
!= GL_NO_ERROR
) {
427 NOTREACHED() << "Error";
430 // NOTE: Calling GetGLError overwrites data in the result buffer.
431 void GLES2Implementation::CheckGLError() {
432 FailGLError(GetGLError());
434 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
436 void GLES2Implementation::SetGLError(
437 GLenum error
, const char* function_name
, const char* msg
) {
438 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
439 << GLES2Util::GetStringError(error
) << ": "
440 << function_name
<< ": " << msg
);
445 if (error_message_callback_
) {
446 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
447 function_name
+ ": " + (msg
? msg
: ""));
448 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
450 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
452 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
453 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
454 GL_UNKNOWN_CONTEXT_RESET_ARB
);
458 void GLES2Implementation::SetGLErrorInvalidEnum(
459 const char* function_name
, GLenum value
, const char* label
) {
460 SetGLError(GL_INVALID_ENUM
, function_name
,
461 (std::string(label
) + " was " +
462 GLES2Util::GetStringEnum(value
)).c_str());
465 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
466 std::vector
<int8
>* data
) {
467 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
469 const uint32 kStartSize
= 32 * 1024;
470 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
471 if (!buffer
.valid()) {
474 typedef cmd::GetBucketStart::Result Result
;
475 Result
* result
= GetResultAs
<Result
*>();
480 helper_
->GetBucketStart(
481 bucket_id
, GetResultShmId(), GetResultShmOffset(),
482 buffer
.size(), buffer
.shm_id(), buffer
.offset());
484 uint32 size
= *result
;
489 if (!buffer
.valid()) {
491 if (!buffer
.valid()) {
494 helper_
->GetBucketData(
495 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
498 uint32 size_to_copy
= std::min(size
, buffer
.size());
499 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
500 offset
+= size_to_copy
;
501 size
-= size_to_copy
;
504 // Free the bucket. This is not required but it does free up the memory.
505 // and we don't have to wait for the result so from the client's perspective
507 helper_
->SetBucketSize(bucket_id
, 0);
512 void GLES2Implementation::SetBucketContents(
513 uint32 bucket_id
, const void* data
, size_t size
) {
515 helper_
->SetBucketSize(bucket_id
, size
);
519 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
520 if (!buffer
.valid()) {
523 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
525 helper_
->SetBucketData(
526 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
527 offset
+= buffer
.size();
528 size
-= buffer
.size();
533 void GLES2Implementation::SetBucketAsCString(
534 uint32 bucket_id
, const char* str
) {
535 // NOTE: strings are passed NULL terminated. That means the empty
536 // string will have a size of 1 and no-string will have a size of 0
538 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
540 helper_
->SetBucketSize(bucket_id
, 0);
544 bool GLES2Implementation::GetBucketAsString(
545 uint32 bucket_id
, std::string
* str
) {
547 std::vector
<int8
> data
;
548 // NOTE: strings are passed NULL terminated. That means the empty
549 // string will have a size of 1 and no-string will have a size of 0
550 if (!GetBucketContents(bucket_id
, &data
)) {
556 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
560 void GLES2Implementation::SetBucketAsString(
561 uint32 bucket_id
, const std::string
& str
) {
562 // NOTE: strings are passed NULL terminated. That means the empty
563 // string will have a size of 1 and no-string will have a size of 0
564 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
567 void GLES2Implementation::Disable(GLenum cap
) {
568 GPU_CLIENT_SINGLE_THREAD_CHECK();
569 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
570 << GLES2Util::GetStringCapability(cap
) << ")");
571 bool changed
= false;
572 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
573 helper_
->Disable(cap
);
578 void GLES2Implementation::Enable(GLenum cap
) {
579 GPU_CLIENT_SINGLE_THREAD_CHECK();
580 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
581 << GLES2Util::GetStringCapability(cap
) << ")");
582 bool changed
= false;
583 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
584 helper_
->Enable(cap
);
589 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
590 GPU_CLIENT_SINGLE_THREAD_CHECK();
591 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
592 << GLES2Util::GetStringCapability(cap
) << ")");
594 if (!state_
.GetEnabled(cap
, &state
)) {
595 typedef cmds::IsEnabled::Result Result
;
596 Result
* result
= GetResultAs
<Result
*>();
601 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
603 state
= (*result
) != 0;
606 GPU_CLIENT_LOG("returned " << state
);
611 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
612 // TODO(zmo): For all the BINDING points, there is a possibility where
613 // resources are shared among multiple contexts, that the cached points
614 // are invalid. It is not a problem for now, but once we allow resource
615 // sharing in WebGL, we need to implement a mechanism to allow correct
616 // client side binding points tracking. crbug.com/465562.
618 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
619 *params
= capabilities_
.max_combined_texture_image_units
;
621 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
622 *params
= capabilities_
.max_cube_map_texture_size
;
624 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
625 *params
= capabilities_
.max_fragment_uniform_vectors
;
627 case GL_MAX_RENDERBUFFER_SIZE
:
628 *params
= capabilities_
.max_renderbuffer_size
;
630 case GL_MAX_TEXTURE_IMAGE_UNITS
:
631 *params
= capabilities_
.max_texture_image_units
;
633 case GL_MAX_TEXTURE_SIZE
:
634 *params
= capabilities_
.max_texture_size
;
636 case GL_MAX_VARYING_VECTORS
:
637 *params
= capabilities_
.max_varying_vectors
;
639 case GL_MAX_VERTEX_ATTRIBS
:
640 *params
= capabilities_
.max_vertex_attribs
;
642 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
643 *params
= capabilities_
.max_vertex_texture_image_units
;
645 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
646 *params
= capabilities_
.max_vertex_uniform_vectors
;
648 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
649 *params
= capabilities_
.num_compressed_texture_formats
;
651 case GL_NUM_SHADER_BINARY_FORMATS
:
652 *params
= capabilities_
.num_shader_binary_formats
;
654 case GL_ARRAY_BUFFER_BINDING
:
655 *params
= bound_array_buffer_id_
;
657 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
659 vertex_array_object_manager_
->bound_element_array_buffer();
661 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
662 *params
= bound_pixel_pack_transfer_buffer_id_
;
664 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
665 *params
= bound_pixel_unpack_transfer_buffer_id_
;
667 case GL_ACTIVE_TEXTURE
:
668 *params
= active_texture_unit_
+ GL_TEXTURE0
;
670 case GL_TEXTURE_BINDING_2D
:
671 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
673 case GL_TEXTURE_BINDING_CUBE_MAP
:
674 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
676 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
678 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
680 case GL_FRAMEBUFFER_BINDING
:
681 *params
= bound_framebuffer_
;
683 case GL_READ_FRAMEBUFFER_BINDING
:
684 if (IsChromiumFramebufferMultisampleAvailable()) {
685 *params
= bound_read_framebuffer_
;
689 case GL_RENDERBUFFER_BINDING
:
690 *params
= bound_renderbuffer_
;
692 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
693 *params
= capabilities_
.max_uniform_buffer_bindings
;
695 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
696 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
698 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
699 *params
= capabilities_
.uniform_buffer_offset_alignment
;
701 // TODO(zmo): Support ES3 pnames.
707 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
708 // TODO(gman): Make this handle pnames that return more than 1 value.
710 if (!GetHelper(pname
, &value
)) {
713 *params
= static_cast<GLboolean
>(value
);
717 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
718 // TODO(gman): Make this handle pnames that return more than 1 value.
720 if (!GetHelper(pname
, &value
)) {
723 *params
= static_cast<GLfloat
>(value
);
727 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
728 return GetHelper(pname
, params
);
731 bool GLES2Implementation::GetInternalformativHelper(
732 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
734 // TODO(zmo): Implement the client side caching.
738 bool GLES2Implementation::GetSyncivHelper(
739 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
744 value
= GL_SYNC_FENCE
;
746 case GL_SYNC_CONDITION
:
747 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
765 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
766 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
767 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
768 Result
* result
= GetResultAs
<Result
*>();
773 helper_
->GetMaxValueInBufferCHROMIUM(
774 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
779 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
780 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
781 GPU_CLIENT_SINGLE_THREAD_CHECK();
782 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
783 << buffer_id
<< ", " << count
<< ", "
784 << GLES2Util::GetStringGetMaxIndexType(type
)
785 << ", " << offset
<< ")");
786 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
787 buffer_id
, count
, type
, offset
);
788 GPU_CLIENT_LOG("returned " << result
);
793 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
795 RestoreArrayBuffer(restore
);
796 // Restore the element array binding.
797 // We only need to restore it if it wasn't a client side array.
798 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
799 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
804 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
806 // Restore the user's current binding.
807 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_id_
);
811 void GLES2Implementation::DrawElements(
812 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
813 GPU_CLIENT_SINGLE_THREAD_CHECK();
814 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
815 << GLES2Util::GetStringDrawMode(mode
) << ", "
817 << GLES2Util::GetStringIndexType(type
) << ", "
818 << static_cast<const void*>(indices
) << ")");
819 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
822 void GLES2Implementation::DrawRangeElements(
823 GLenum mode
, GLuint start
, GLuint end
,
824 GLsizei count
, GLenum type
, const void* indices
) {
825 GPU_CLIENT_SINGLE_THREAD_CHECK();
826 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
827 << GLES2Util::GetStringDrawMode(mode
) << ", "
828 << start
<< ", " << end
<< ", " << count
<< ", "
829 << GLES2Util::GetStringIndexType(type
) << ", "
830 << static_cast<const void*>(indices
) << ")");
832 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
835 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
838 void GLES2Implementation::DrawElementsImpl(
839 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
840 const char* func_name
) {
842 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
845 bool simulated
= false;
846 GLuint offset
= ToGLuint(indices
);
848 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
849 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
852 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
853 func_name
, this, helper_
, count
, type
, 0, indices
,
854 &offset
, &simulated
)) {
858 helper_
->DrawElements(mode
, count
, type
, offset
);
859 RestoreElementAndArrayBuffers(simulated
);
863 void GLES2Implementation::Flush() {
864 GPU_CLIENT_SINGLE_THREAD_CHECK();
865 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
866 // Insert the cmd to call glFlush
868 // Flush our command buffer
869 // (tell the service to execute up to the flush cmd.)
870 helper_
->CommandBufferHelper::Flush();
873 void GLES2Implementation::ShallowFlushCHROMIUM() {
874 GPU_CLIENT_SINGLE_THREAD_CHECK();
875 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
876 // Flush our command buffer
877 // (tell the service to execute up to the flush cmd.)
878 helper_
->CommandBufferHelper::Flush();
879 // TODO(piman): Add the FreeEverything() logic here.
882 void GLES2Implementation::OrderingBarrierCHROMIUM() {
883 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
884 // Flush command buffer at the GPU channel level. May be implemented as
886 helper_
->CommandBufferHelper::OrderingBarrier();
889 void GLES2Implementation::Finish() {
890 GPU_CLIENT_SINGLE_THREAD_CHECK();
894 void GLES2Implementation::ShallowFinishCHROMIUM() {
895 GPU_CLIENT_SINGLE_THREAD_CHECK();
896 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
897 // Flush our command buffer (tell the service to execute up to the flush cmd
898 // and don't return until it completes).
899 helper_
->CommandBufferHelper::Finish();
902 void GLES2Implementation::FinishHelper() {
903 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
904 TRACE_EVENT0("gpu", "GLES2::Finish");
905 // Insert the cmd to call glFinish
907 // Finish our command buffer
908 // (tell the service to execute up to the Finish cmd and wait for it to
910 helper_
->CommandBufferHelper::Finish();
913 void GLES2Implementation::SwapBuffers() {
914 GPU_CLIENT_SINGLE_THREAD_CHECK();
915 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
916 // TODO(piman): Strictly speaking we'd want to insert the token after the
917 // swap, but the state update with the updated token might not have happened
918 // by the time the SwapBuffer callback gets called, forcing us to synchronize
919 // with the GPU process more than needed. So instead, make it happen before.
920 // All it means is that we could be slightly looser on the kMaxSwapBuffers
921 // semantics if the client doesn't use the callback mechanism, and by chance
922 // the scheduler yields between the InsertToken and the SwapBuffers.
923 swap_buffers_tokens_
.push(helper_
->InsertToken());
924 helper_
->SwapBuffers();
925 helper_
->CommandBufferHelper::Flush();
926 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
927 // compensate for TODO above.
928 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
929 helper_
->WaitForToken(swap_buffers_tokens_
.front());
930 swap_buffers_tokens_
.pop();
934 void GLES2Implementation::SwapInterval(int interval
) {
935 GPU_CLIENT_SINGLE_THREAD_CHECK();
936 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
938 helper_
->SwapInterval(interval
);
941 void GLES2Implementation::BindAttribLocation(
942 GLuint program
, GLuint index
, const char* name
) {
943 GPU_CLIENT_SINGLE_THREAD_CHECK();
944 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
945 << program
<< ", " << index
<< ", " << name
<< ")");
946 SetBucketAsString(kResultBucketId
, name
);
947 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
948 helper_
->SetBucketSize(kResultBucketId
, 0);
952 void GLES2Implementation::BindUniformLocationCHROMIUM(
953 GLuint program
, GLint location
, const char* name
) {
954 GPU_CLIENT_SINGLE_THREAD_CHECK();
955 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
956 << program
<< ", " << location
<< ", " << name
<< ")");
957 SetBucketAsString(kResultBucketId
, name
);
958 helper_
->BindUniformLocationCHROMIUMBucket(
959 program
, location
, kResultBucketId
);
960 helper_
->SetBucketSize(kResultBucketId
, 0);
964 void GLES2Implementation::GetVertexAttribPointerv(
965 GLuint index
, GLenum pname
, void** ptr
) {
966 GPU_CLIENT_SINGLE_THREAD_CHECK();
967 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
968 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
969 << static_cast<void*>(ptr
) << ")");
970 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
971 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
972 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
973 typedef cmds::GetVertexAttribPointerv::Result Result
;
974 Result
* result
= GetResultAs
<Result
*>();
978 result
->SetNumResults(0);
979 helper_
->GetVertexAttribPointerv(
980 index
, pname
, GetResultShmId(), GetResultShmOffset());
982 result
->CopyResult(ptr
);
983 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
985 GPU_CLIENT_LOG_CODE_BLOCK({
986 for (int32 i
= 0; i
< num_results
; ++i
) {
987 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
993 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
994 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
995 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
998 "glDeleteProgram", "id not created by this context.");
1001 if (program
== current_program_
) {
1002 current_program_
= 0;
1007 void GLES2Implementation::DeleteProgramStub(
1008 GLsizei n
, const GLuint
* programs
) {
1010 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1011 helper_
->DeleteProgram(programs
[0]);
1014 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1015 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1016 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1019 "glDeleteShader", "id not created by this context.");
1025 void GLES2Implementation::DeleteShaderStub(
1026 GLsizei n
, const GLuint
* shaders
) {
1028 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1029 helper_
->DeleteShader(shaders
[0]);
1032 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1033 GLuint sync_uint
= ToGLuint(sync
);
1034 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1035 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1038 "glDeleteSync", "id not created by this context.");
1042 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1044 helper_
->DeleteSync(syncs
[0]);
1047 GLint
GLES2Implementation::GetAttribLocationHelper(
1048 GLuint program
, const char* name
) {
1049 typedef cmds::GetAttribLocation::Result Result
;
1050 Result
* result
= GetResultAs
<Result
*>();
1055 SetBucketAsCString(kResultBucketId
, name
);
1056 helper_
->GetAttribLocation(
1057 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1059 helper_
->SetBucketSize(kResultBucketId
, 0);
1063 GLint
GLES2Implementation::GetAttribLocation(
1064 GLuint program
, const char* name
) {
1065 GPU_CLIENT_SINGLE_THREAD_CHECK();
1066 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1067 << ", " << name
<< ")");
1068 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1069 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1070 this, program
, name
);
1071 GPU_CLIENT_LOG("returned " << loc
);
1076 GLint
GLES2Implementation::GetUniformLocationHelper(
1077 GLuint program
, const char* name
) {
1078 typedef cmds::GetUniformLocation::Result Result
;
1079 Result
* result
= GetResultAs
<Result
*>();
1084 SetBucketAsCString(kResultBucketId
, name
);
1085 helper_
->GetUniformLocation(program
, kResultBucketId
,
1086 GetResultShmId(), GetResultShmOffset());
1088 helper_
->SetBucketSize(kResultBucketId
, 0);
1092 GLint
GLES2Implementation::GetUniformLocation(
1093 GLuint program
, const char* name
) {
1094 GPU_CLIENT_SINGLE_THREAD_CHECK();
1095 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1096 << ", " << name
<< ")");
1097 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1098 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1099 this, program
, name
);
1100 GPU_CLIENT_LOG("returned " << loc
);
1105 bool GLES2Implementation::GetUniformIndicesHelper(
1106 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1107 typedef cmds::GetUniformIndices::Result Result
;
1108 Result
* result
= GetResultAs
<Result
*>();
1112 result
->SetNumResults(0);
1113 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1116 helper_
->GetUniformIndices(program
, kResultBucketId
,
1117 GetResultShmId(), GetResultShmOffset());
1119 if (result
->GetNumResults() != count
) {
1122 result
->CopyResult(indices
);
1126 void GLES2Implementation::GetUniformIndices(
1127 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1128 GPU_CLIENT_SINGLE_THREAD_CHECK();
1129 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1130 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1131 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1133 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1139 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1140 this, program
, count
, names
, indices
);
1142 GPU_CLIENT_LOG_CODE_BLOCK({
1143 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1144 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1151 bool GLES2Implementation::GetProgramivHelper(
1152 GLuint program
, GLenum pname
, GLint
* params
) {
1153 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1154 this, program
, pname
, params
);
1155 GPU_CLIENT_LOG_CODE_BLOCK({
1157 GPU_CLIENT_LOG(" 0: " << *params
);
1163 GLint
GLES2Implementation::GetFragDataLocationHelper(
1164 GLuint program
, const char* name
) {
1165 typedef cmds::GetFragDataLocation::Result Result
;
1166 Result
* result
= GetResultAs
<Result
*>();
1171 SetBucketAsCString(kResultBucketId
, name
);
1172 helper_
->GetFragDataLocation(
1173 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1175 helper_
->SetBucketSize(kResultBucketId
, 0);
1179 GLint
GLES2Implementation::GetFragDataLocation(
1180 GLuint program
, const char* name
) {
1181 GPU_CLIENT_SINGLE_THREAD_CHECK();
1182 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1183 << program
<< ", " << name
<< ")");
1184 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1185 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1186 this, program
, name
);
1187 GPU_CLIENT_LOG("returned " << loc
);
1192 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1193 GLuint program
, const char* name
) {
1194 typedef cmds::GetUniformBlockIndex::Result Result
;
1195 Result
* result
= GetResultAs
<Result
*>();
1197 return GL_INVALID_INDEX
;
1199 *result
= GL_INVALID_INDEX
;
1200 SetBucketAsCString(kResultBucketId
, name
);
1201 helper_
->GetUniformBlockIndex(
1202 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1204 helper_
->SetBucketSize(kResultBucketId
, 0);
1208 GLuint
GLES2Implementation::GetUniformBlockIndex(
1209 GLuint program
, const char* name
) {
1210 GPU_CLIENT_SINGLE_THREAD_CHECK();
1211 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1212 << program
<< ", " << name
<< ")");
1213 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1214 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1215 this, program
, name
);
1216 GPU_CLIENT_LOG("returned " << index
);
1221 void GLES2Implementation::LinkProgram(GLuint program
) {
1222 GPU_CLIENT_SINGLE_THREAD_CHECK();
1223 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1224 helper_
->LinkProgram(program
);
1225 share_group_
->program_info_manager()->CreateInfo(program
);
1229 void GLES2Implementation::ShaderBinary(
1230 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1232 GPU_CLIENT_SINGLE_THREAD_CHECK();
1233 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1234 << static_cast<const void*>(shaders
) << ", "
1235 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1236 << static_cast<const void*>(binary
) << ", "
1239 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1243 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1246 // TODO(gman): ShaderBinary should use buckets.
1247 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1248 ScopedTransferBufferArray
<GLint
> buffer(
1249 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1250 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1251 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1254 void* shader_ids
= buffer
.elements();
1255 void* shader_data
= buffer
.elements() + shader_id_size
;
1256 memcpy(shader_ids
, shaders
, shader_id_size
);
1257 memcpy(shader_data
, binary
, length
);
1258 helper_
->ShaderBinary(
1264 buffer
.offset() + shader_id_size
,
1269 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1270 GPU_CLIENT_SINGLE_THREAD_CHECK();
1271 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1272 << GLES2Util::GetStringPixelStore(pname
) << ", "
1275 case GL_PACK_ALIGNMENT
:
1276 pack_alignment_
= param
;
1278 case GL_UNPACK_ALIGNMENT
:
1279 unpack_alignment_
= param
;
1281 case GL_UNPACK_ROW_LENGTH_EXT
:
1282 unpack_row_length_
= param
;
1284 case GL_UNPACK_IMAGE_HEIGHT
:
1285 unpack_image_height_
= param
;
1287 case GL_UNPACK_SKIP_ROWS_EXT
:
1288 unpack_skip_rows_
= param
;
1290 case GL_UNPACK_SKIP_PIXELS_EXT
:
1291 unpack_skip_pixels_
= param
;
1293 case GL_UNPACK_SKIP_IMAGES
:
1294 unpack_skip_images_
= param
;
1296 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1297 unpack_flip_y_
= (param
!= 0);
1299 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1300 pack_reverse_row_order_
=
1301 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1306 helper_
->PixelStorei(pname
, param
);
1310 void GLES2Implementation::VertexAttribIPointer(
1311 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1312 GPU_CLIENT_SINGLE_THREAD_CHECK();
1313 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1316 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1319 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1323 void GLES2Implementation::VertexAttribPointer(
1324 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1326 GPU_CLIENT_SINGLE_THREAD_CHECK();
1327 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1330 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1331 << GLES2Util::GetStringBool(normalized
) << ", "
1334 // Record the info on the client side.
1335 if (!vertex_array_object_manager_
->SetAttribPointer(
1336 bound_array_buffer_id_
, index
, size
, type
, normalized
, stride
, ptr
)) {
1337 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1338 "client side arrays are not allowed in vertex array objects.");
1341 if (!support_client_side_arrays_
|| bound_array_buffer_id_
!= 0) {
1342 // Only report NON client side buffers to the service.
1343 if (!ValidateOffset("glVertexAttribPointer",
1344 reinterpret_cast<GLintptr
>(ptr
))) {
1347 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1353 void GLES2Implementation::VertexAttribDivisorANGLE(
1354 GLuint index
, GLuint divisor
) {
1355 GPU_CLIENT_SINGLE_THREAD_CHECK();
1356 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1358 << divisor
<< ") ");
1359 // Record the info on the client side.
1360 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1361 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1365 void GLES2Implementation::BufferDataHelper(
1366 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1367 if (!ValidateSize("glBufferData", size
))
1370 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1371 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1372 // bogus MSan report during a readback later. This is because MSan doesn't
1373 // understand shared memory and would assume we were reading back the same
1374 // unintialized data.
1375 if (data
) __msan_check_mem_is_initialized(data
, size
);
1379 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1384 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1386 RemoveTransferBuffer(buffer
);
1388 // Create new buffer.
1389 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1391 if (buffer
->address() && data
)
1392 memcpy(buffer
->address(), data
, size
);
1396 RemoveMappedBufferRangeByTarget(target
);
1398 // If there is no data just send BufferData
1399 if (size
== 0 || !data
) {
1400 helper_
->BufferData(target
, size
, 0, 0, usage
);
1404 // See if we can send all at once.
1405 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1406 if (!buffer
.valid()) {
1410 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1411 memcpy(buffer
.address(), data
, size
);
1412 helper_
->BufferData(
1421 // Make the buffer with BufferData then send via BufferSubData
1422 helper_
->BufferData(target
, size
, 0, 0, usage
);
1423 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1427 void GLES2Implementation::BufferData(
1428 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1429 GPU_CLIENT_SINGLE_THREAD_CHECK();
1430 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1431 << GLES2Util::GetStringBufferTarget(target
) << ", "
1433 << static_cast<const void*>(data
) << ", "
1434 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1435 BufferDataHelper(target
, size
, data
, usage
);
1439 void GLES2Implementation::BufferSubDataHelper(
1440 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1445 if (!ValidateSize("glBufferSubData", size
) ||
1446 !ValidateOffset("glBufferSubData", offset
)) {
1451 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1455 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1457 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1462 int32 buffer_size
= buffer
->size();
1463 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1464 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1468 if (buffer
->address() && data
)
1469 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1473 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1474 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1477 void GLES2Implementation::BufferSubDataHelperImpl(
1478 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1479 ScopedTransferBufferPtr
* buffer
) {
1483 const int8
* source
= static_cast<const int8
*>(data
);
1485 if (!buffer
->valid() || buffer
->size() == 0) {
1486 buffer
->Reset(size
);
1487 if (!buffer
->valid()) {
1491 memcpy(buffer
->address(), source
, buffer
->size());
1492 helper_
->BufferSubData(
1493 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1494 offset
+= buffer
->size();
1495 source
+= buffer
->size();
1496 size
-= buffer
->size();
1501 void GLES2Implementation::BufferSubData(
1502 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1503 GPU_CLIENT_SINGLE_THREAD_CHECK();
1504 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1505 << GLES2Util::GetStringBufferTarget(target
) << ", "
1506 << offset
<< ", " << size
<< ", "
1507 << static_cast<const void*>(data
) << ")");
1508 BufferSubDataHelper(target
, offset
, size
, data
);
1512 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1513 int32 token
= buffer
->last_usage_token();
1514 uint32 async_token
= buffer
->last_async_upload_token();
1517 if (HasAsyncUploadTokenPassed(async_token
)) {
1518 buffer_tracker_
->Free(buffer
);
1520 detached_async_upload_memory_
.push_back(
1521 std::make_pair(buffer
->address(), async_token
));
1522 buffer_tracker_
->Unmanage(buffer
);
1525 if (helper_
->HasTokenPassed(token
))
1526 buffer_tracker_
->Free(buffer
);
1528 buffer_tracker_
->FreePendingToken(buffer
, token
);
1530 buffer_tracker_
->Free(buffer
);
1533 buffer_tracker_
->RemoveBuffer(buffer
->id());
1536 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1538 const char* function_name
,
1539 GLuint
* buffer_id
) {
1543 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1544 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1546 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1547 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1554 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1559 BufferTracker::Buffer
*
1560 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1562 const char* function_name
,
1563 GLuint offset
, GLsizei size
) {
1565 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1567 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1570 if (buffer
->mapped()) {
1571 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1574 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1575 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1581 void GLES2Implementation::CompressedTexImage2D(
1582 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1583 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1584 GPU_CLIENT_SINGLE_THREAD_CHECK();
1585 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1586 << GLES2Util::GetStringTextureTarget(target
) << ", "
1588 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1589 << width
<< ", " << height
<< ", " << border
<< ", "
1590 << image_size
<< ", "
1591 << static_cast<const void*>(data
) << ")");
1592 if (width
< 0 || height
< 0 || level
< 0) {
1593 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1597 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
1600 if (height
== 0 || width
== 0) {
1603 // If there's a pixel unpack buffer bound use it when issuing
1604 // CompressedTexImage2D.
1605 if (bound_pixel_unpack_transfer_buffer_id_
) {
1606 GLuint offset
= ToGLuint(data
);
1607 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1608 bound_pixel_unpack_transfer_buffer_id_
,
1609 "glCompressedTexImage2D", offset
, image_size
);
1610 if (buffer
&& buffer
->shm_id() != -1) {
1611 helper_
->CompressedTexImage2D(
1612 target
, level
, internalformat
, width
, height
, image_size
,
1613 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1614 buffer
->set_last_usage_token(helper_
->InsertToken());
1618 SetBucketContents(kResultBucketId
, data
, image_size
);
1619 helper_
->CompressedTexImage2DBucket(
1620 target
, level
, internalformat
, width
, height
, kResultBucketId
);
1621 // Free the bucket. This is not required but it does free up the memory.
1622 // and we don't have to wait for the result so from the client's perspective
1624 helper_
->SetBucketSize(kResultBucketId
, 0);
1628 void GLES2Implementation::CompressedTexSubImage2D(
1629 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1630 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1631 GPU_CLIENT_SINGLE_THREAD_CHECK();
1632 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1633 << GLES2Util::GetStringTextureTarget(target
) << ", "
1635 << xoffset
<< ", " << yoffset
<< ", "
1636 << width
<< ", " << height
<< ", "
1637 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1638 << image_size
<< ", "
1639 << static_cast<const void*>(data
) << ")");
1640 if (width
< 0 || height
< 0 || level
< 0) {
1641 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1644 // If there's a pixel unpack buffer bound use it when issuing
1645 // CompressedTexSubImage2D.
1646 if (bound_pixel_unpack_transfer_buffer_id_
) {
1647 GLuint offset
= ToGLuint(data
);
1648 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1649 bound_pixel_unpack_transfer_buffer_id_
,
1650 "glCompressedTexSubImage2D", offset
, image_size
);
1651 if (buffer
&& buffer
->shm_id() != -1) {
1652 helper_
->CompressedTexSubImage2D(
1653 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1654 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1655 buffer
->set_last_usage_token(helper_
->InsertToken());
1660 SetBucketContents(kResultBucketId
, data
, image_size
);
1661 helper_
->CompressedTexSubImage2DBucket(
1662 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1663 // Free the bucket. This is not required but it does free up the memory.
1664 // and we don't have to wait for the result so from the client's perspective
1666 helper_
->SetBucketSize(kResultBucketId
, 0);
1672 void CopyRectToBuffer(
1675 uint32 unpadded_row_size
,
1676 uint32 pixels_padded_row_size
,
1679 uint32 buffer_padded_row_size
) {
1680 const int8
* source
= static_cast<const int8
*>(pixels
);
1681 int8
* dest
= static_cast<int8
*>(buffer
);
1682 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
1684 dest
+= buffer_padded_row_size
* (height
- 1);
1686 // the last row is copied unpadded at the end
1687 for (; height
> 1; --height
) {
1688 memcpy(dest
, source
, buffer_padded_row_size
);
1690 dest
-= buffer_padded_row_size
;
1692 dest
+= buffer_padded_row_size
;
1694 source
+= pixels_padded_row_size
;
1696 memcpy(dest
, source
, unpadded_row_size
);
1698 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
1699 memcpy(dest
, source
, size
);
1703 } // anonymous namespace
1705 void GLES2Implementation::TexImage2D(
1706 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
1707 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
1708 const void* pixels
) {
1709 GPU_CLIENT_SINGLE_THREAD_CHECK();
1710 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
1711 << GLES2Util::GetStringTextureTarget(target
) << ", "
1713 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
1714 << width
<< ", " << height
<< ", " << border
<< ", "
1715 << GLES2Util::GetStringTextureFormat(format
) << ", "
1716 << GLES2Util::GetStringPixelType(type
) << ", "
1717 << static_cast<const void*>(pixels
) << ")");
1718 if (level
< 0 || height
< 0 || width
< 0) {
1719 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
1723 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
1727 uint32 unpadded_row_size
;
1728 uint32 padded_row_size
;
1729 if (!GLES2Util::ComputeImageDataSizes(
1730 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
1731 &unpadded_row_size
, &padded_row_size
)) {
1732 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
1736 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
1737 if (bound_pixel_unpack_transfer_buffer_id_
) {
1738 GLuint offset
= ToGLuint(pixels
);
1739 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1740 bound_pixel_unpack_transfer_buffer_id_
,
1741 "glTexImage2D", offset
, size
);
1742 if (buffer
&& buffer
->shm_id() != -1) {
1743 helper_
->TexImage2D(
1744 target
, level
, internalformat
, width
, height
, format
, type
,
1745 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1746 buffer
->set_last_usage_token(helper_
->InsertToken());
1752 // If there's no data just issue TexImage2D
1754 helper_
->TexImage2D(
1755 target
, level
, internalformat
, width
, height
, format
, type
,
1761 // compute the advance bytes per row for the src pixels
1762 uint32 src_padded_row_size
;
1763 if (unpack_row_length_
> 0) {
1764 if (!GLES2Util::ComputeImagePaddedRowSize(
1765 unpack_row_length_
, format
, type
, unpack_alignment_
,
1766 &src_padded_row_size
)) {
1768 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1772 src_padded_row_size
= padded_row_size
;
1775 // advance pixels pointer past the skip rows and skip pixels
1776 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1777 unpack_skip_rows_
* src_padded_row_size
;
1778 if (unpack_skip_pixels_
) {
1779 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1780 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1781 unpack_skip_pixels_
* group_size
;
1784 // Check if we can send it all at once.
1785 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1786 if (!buffer
.valid()) {
1790 if (buffer
.size() >= size
) {
1792 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
1793 buffer
.address(), padded_row_size
);
1794 helper_
->TexImage2D(
1795 target
, level
, internalformat
, width
, height
, format
, type
,
1796 buffer
.shm_id(), buffer
.offset());
1801 // No, so send it using TexSubImage2D.
1802 helper_
->TexImage2D(
1803 target
, level
, internalformat
, width
, height
, format
, type
,
1806 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
1807 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
1811 void GLES2Implementation::TexImage3D(
1812 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
1813 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
1814 const void* pixels
) {
1815 GPU_CLIENT_SINGLE_THREAD_CHECK();
1816 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
1817 << GLES2Util::GetStringTextureTarget(target
) << ", "
1819 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
1820 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
1821 << GLES2Util::GetStringTextureFormat(format
) << ", "
1822 << GLES2Util::GetStringPixelType(type
) << ", "
1823 << static_cast<const void*>(pixels
) << ")");
1824 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
1825 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
1829 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
1833 uint32 unpadded_row_size
;
1834 uint32 padded_row_size
;
1835 if (!GLES2Util::ComputeImageDataSizes(
1836 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
1837 &unpadded_row_size
, &padded_row_size
)) {
1838 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
1842 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
1843 if (bound_pixel_unpack_transfer_buffer_id_
) {
1844 GLuint offset
= ToGLuint(pixels
);
1845 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1846 bound_pixel_unpack_transfer_buffer_id_
,
1847 "glTexImage3D", offset
, size
);
1848 if (buffer
&& buffer
->shm_id() != -1) {
1849 helper_
->TexImage3D(
1850 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
1851 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1852 buffer
->set_last_usage_token(helper_
->InsertToken());
1858 // If there's no data just issue TexImage3D
1860 helper_
->TexImage3D(
1861 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
1867 // compute the advance bytes per row for the src pixels
1868 uint32 src_padded_row_size
;
1869 if (unpack_row_length_
> 0) {
1870 if (!GLES2Util::ComputeImagePaddedRowSize(
1871 unpack_row_length_
, format
, type
, unpack_alignment_
,
1872 &src_padded_row_size
)) {
1874 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
1878 src_padded_row_size
= padded_row_size
;
1880 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
1882 // advance pixels pointer past the skip images/rows/pixels
1883 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1884 unpack_skip_images_
* src_padded_row_size
* src_height
+
1885 unpack_skip_rows_
* src_padded_row_size
;
1886 if (unpack_skip_pixels_
) {
1887 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1888 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1889 unpack_skip_pixels_
* group_size
;
1892 // Check if we can send it all at once.
1893 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1894 if (!buffer
.valid()) {
1898 if (buffer
.size() >= size
) {
1899 void* buffer_pointer
= buffer
.address();
1900 for (GLsizei z
= 0; z
< depth
; ++z
) {
1901 // Only the last row of the last image is unpadded.
1902 uint32 src_unpadded_row_size
=
1903 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
1904 // TODO(zmo): Ignore flip_y flag for now.
1906 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
, false,
1907 buffer_pointer
, padded_row_size
);
1908 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1909 src_padded_row_size
* src_height
;
1910 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
1911 padded_row_size
* height
;
1913 helper_
->TexImage3D(
1914 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
1915 buffer
.shm_id(), buffer
.offset());
1920 // No, so send it using TexSubImage3D.
1921 helper_
->TexImage3D(
1922 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
1925 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
1926 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &buffer
,
1931 void GLES2Implementation::TexSubImage2D(
1932 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1933 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
1934 GPU_CLIENT_SINGLE_THREAD_CHECK();
1935 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
1936 << GLES2Util::GetStringTextureTarget(target
) << ", "
1938 << xoffset
<< ", " << yoffset
<< ", "
1939 << width
<< ", " << height
<< ", "
1940 << GLES2Util::GetStringTextureFormat(format
) << ", "
1941 << GLES2Util::GetStringPixelType(type
) << ", "
1942 << static_cast<const void*>(pixels
) << ")");
1944 if (level
< 0 || height
< 0 || width
< 0) {
1945 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
1948 if (height
== 0 || width
== 0) {
1953 uint32 unpadded_row_size
;
1954 uint32 padded_row_size
;
1955 if (!GLES2Util::ComputeImageDataSizes(
1956 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
1957 &unpadded_row_size
, &padded_row_size
)) {
1958 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
1962 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
1963 if (bound_pixel_unpack_transfer_buffer_id_
) {
1964 GLuint offset
= ToGLuint(pixels
);
1965 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1966 bound_pixel_unpack_transfer_buffer_id_
,
1967 "glTexSubImage2D", offset
, temp_size
);
1968 if (buffer
&& buffer
->shm_id() != -1) {
1969 helper_
->TexSubImage2D(
1970 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1971 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
1972 buffer
->set_last_usage_token(helper_
->InsertToken());
1978 // compute the advance bytes per row for the src pixels
1979 uint32 src_padded_row_size
;
1980 if (unpack_row_length_
> 0) {
1981 if (!GLES2Util::ComputeImagePaddedRowSize(
1982 unpack_row_length_
, format
, type
, unpack_alignment_
,
1983 &src_padded_row_size
)) {
1985 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1989 src_padded_row_size
= padded_row_size
;
1992 // advance pixels pointer past the skip rows and skip pixels
1993 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1994 unpack_skip_rows_
* src_padded_row_size
;
1995 if (unpack_skip_pixels_
) {
1996 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1997 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1998 unpack_skip_pixels_
* group_size
;
2001 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2003 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2004 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2009 void GLES2Implementation::TexSubImage3D(
2010 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2011 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2012 const void* pixels
) {
2013 GPU_CLIENT_SINGLE_THREAD_CHECK();
2014 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2015 << GLES2Util::GetStringTextureTarget(target
) << ", "
2017 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2018 << width
<< ", " << height
<< ", " << depth
<< ", "
2019 << GLES2Util::GetStringTextureFormat(format
) << ", "
2020 << GLES2Util::GetStringPixelType(type
) << ", "
2021 << static_cast<const void*>(pixels
) << ")");
2023 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2024 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2027 if (height
== 0 || width
== 0 || depth
== 0) {
2032 uint32 unpadded_row_size
;
2033 uint32 padded_row_size
;
2034 if (!GLES2Util::ComputeImageDataSizes(
2035 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2036 &unpadded_row_size
, &padded_row_size
)) {
2037 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2041 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2042 if (bound_pixel_unpack_transfer_buffer_id_
) {
2043 GLuint offset
= ToGLuint(pixels
);
2044 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2045 bound_pixel_unpack_transfer_buffer_id_
,
2046 "glTexSubImage3D", offset
, temp_size
);
2047 if (buffer
&& buffer
->shm_id() != -1) {
2048 helper_
->TexSubImage3D(
2049 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2050 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2051 buffer
->set_last_usage_token(helper_
->InsertToken());
2057 // compute the advance bytes per row for the src pixels
2058 uint32 src_padded_row_size
;
2059 if (unpack_row_length_
> 0) {
2060 if (!GLES2Util::ComputeImagePaddedRowSize(
2061 unpack_row_length_
, format
, type
, unpack_alignment_
,
2062 &src_padded_row_size
)) {
2064 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2068 src_padded_row_size
= padded_row_size
;
2070 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2072 // advance pixels pointer past the skip images/rows/pixels
2073 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2074 unpack_skip_images_
* src_padded_row_size
* src_height
+
2075 unpack_skip_rows_
* src_padded_row_size
;
2076 if (unpack_skip_pixels_
) {
2077 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2078 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2079 unpack_skip_pixels_
* group_size
;
2082 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2084 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2085 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2086 &buffer
, padded_row_size
);
2090 static GLint
ComputeNumRowsThatFitInBuffer(
2091 uint32 padded_row_size
, uint32 unpadded_row_size
,
2092 unsigned int size
, GLsizei remaining_rows
) {
2093 DCHECK_GE(unpadded_row_size
, 0u);
2094 if (padded_row_size
== 0) {
2097 GLint num_rows
= size
/ padded_row_size
;
2098 if (num_rows
+ 1 == remaining_rows
&&
2099 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2105 void GLES2Implementation::TexSubImage2DImpl(
2106 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2107 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2108 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2109 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2111 DCHECK_GE(level
, 0);
2112 DCHECK_GT(height
, 0);
2113 DCHECK_GT(width
, 0);
2115 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2116 GLint original_yoffset
= yoffset
;
2117 // Transfer by rows.
2119 unsigned int desired_size
=
2120 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2121 if (!buffer
->valid() || buffer
->size() == 0) {
2122 buffer
->Reset(desired_size
);
2123 if (!buffer
->valid()) {
2128 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2129 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2130 num_rows
= std::min(num_rows
, height
);
2132 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2133 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
2134 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
2135 helper_
->TexSubImage2D(
2136 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
2137 buffer
->shm_id(), buffer
->offset(), internal
);
2139 yoffset
+= num_rows
;
2140 source
+= num_rows
* pixels_padded_row_size
;
2145 void GLES2Implementation::TexSubImage3DImpl(
2146 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2147 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2148 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2149 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2150 uint32 buffer_padded_row_size
) {
2152 DCHECK_GE(level
, 0);
2153 DCHECK_GT(height
, 0);
2154 DCHECK_GT(width
, 0);
2155 DCHECK_GT(depth
, 0);
2156 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2157 GLsizei total_rows
= height
* depth
;
2158 GLint row_index
= 0, depth_index
= 0;
2159 while (total_rows
) {
2160 // Each time, we either copy one or more images, or copy one or more rows
2161 // within a single image, depending on the buffer size limit.
2163 unsigned int desired_size
;
2164 if (row_index
> 0) {
2165 // We are in the middle of an image. Send the remaining of the image.
2166 max_rows
= height
- row_index
;
2167 if (total_rows
<= height
) {
2168 // Last image, so last row is unpadded.
2169 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2172 desired_size
= buffer_padded_row_size
* max_rows
;
2175 // Send all the remaining data if possible.
2176 max_rows
= total_rows
;
2178 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2180 if (!buffer
->valid() || buffer
->size() == 0) {
2181 buffer
->Reset(desired_size
);
2182 if (!buffer
->valid()) {
2186 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2187 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2188 num_rows
= std::min(num_rows
, max_rows
);
2189 GLint num_images
= num_rows
/ height
;
2190 GLsizei my_height
, my_depth
;
2191 if (num_images
> 0) {
2192 num_rows
= num_images
* height
;
2194 my_depth
= num_images
;
2196 my_height
= num_rows
;
2200 // TODO(zmo): Ignore flip_y flag for now.
2201 if (num_images
> 0) {
2202 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2204 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2205 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2206 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2207 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2208 uint32 my_unpadded_row_size
;
2209 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2210 my_unpadded_row_size
= unpadded_row_size
;
2212 my_unpadded_row_size
= pixels_padded_row_size
;
2214 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2215 pixels_padded_row_size
, false, buffer_pointer
+ ii
* image_size_dst
,
2216 buffer_padded_row_size
);
2219 uint32 my_unpadded_row_size
;
2220 if (total_rows
== num_rows
)
2221 my_unpadded_row_size
= unpadded_row_size
;
2223 my_unpadded_row_size
= pixels_padded_row_size
;
2225 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2226 false, buffer
->address(), buffer_padded_row_size
);
2228 helper_
->TexSubImage3D(
2229 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2230 width
, my_height
, my_depth
,
2231 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2234 total_rows
-= num_rows
;
2235 if (total_rows
> 0) {
2236 GLint num_image_paddings
;
2237 if (num_images
> 0) {
2238 DCHECK_EQ(row_index
, 0);
2239 depth_index
+= num_images
;
2240 num_image_paddings
= num_images
;
2242 row_index
= (row_index
+ my_height
) % height
;
2243 num_image_paddings
= 0;
2244 if (my_height
> 0 && row_index
== 0) {
2246 num_image_paddings
++;
2249 source
+= num_rows
* pixels_padded_row_size
;
2250 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2251 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2252 pixels_padded_row_size
;
2258 bool GLES2Implementation::GetActiveAttribHelper(
2259 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2260 GLenum
* type
, char* name
) {
2261 // Clear the bucket so if the command fails nothing will be in it.
2262 helper_
->SetBucketSize(kResultBucketId
, 0);
2263 typedef cmds::GetActiveAttrib::Result Result
;
2264 Result
* result
= GetResultAs
<Result
*>();
2268 // Set as failed so if the command fails we'll recover.
2269 result
->success
= false;
2270 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2271 GetResultShmId(), GetResultShmOffset());
2273 if (result
->success
) {
2275 *size
= result
->size
;
2278 *type
= result
->type
;
2280 if (length
|| name
) {
2281 std::vector
<int8
> str
;
2282 GetBucketContents(kResultBucketId
, &str
);
2283 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2284 std::max(static_cast<size_t>(0),
2289 if (name
&& bufsize
> 0) {
2290 memcpy(name
, &str
[0], max_size
);
2291 name
[max_size
] = '\0';
2295 return result
->success
!= 0;
2298 void GLES2Implementation::GetActiveAttrib(
2299 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2300 GLenum
* type
, char* name
) {
2301 GPU_CLIENT_SINGLE_THREAD_CHECK();
2302 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2303 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2304 << static_cast<const void*>(length
) << ", "
2305 << static_cast<const void*>(size
) << ", "
2306 << static_cast<const void*>(type
) << ", "
2307 << static_cast<const void*>(name
) << ", ");
2309 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2312 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2313 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2314 this, program
, index
, bufsize
, length
, size
, type
, name
);
2317 GPU_CLIENT_LOG(" size: " << *size
);
2320 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2323 GPU_CLIENT_LOG(" name: " << name
);
2329 bool GLES2Implementation::GetActiveUniformHelper(
2330 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2331 GLenum
* type
, char* name
) {
2332 // Clear the bucket so if the command fails nothing will be in it.
2333 helper_
->SetBucketSize(kResultBucketId
, 0);
2334 typedef cmds::GetActiveUniform::Result Result
;
2335 Result
* result
= GetResultAs
<Result
*>();
2339 // Set as failed so if the command fails we'll recover.
2340 result
->success
= false;
2341 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2342 GetResultShmId(), GetResultShmOffset());
2344 if (result
->success
) {
2346 *size
= result
->size
;
2349 *type
= result
->type
;
2351 if (length
|| name
) {
2352 std::vector
<int8
> str
;
2353 GetBucketContents(kResultBucketId
, &str
);
2354 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2355 std::max(static_cast<size_t>(0),
2360 if (name
&& bufsize
> 0) {
2361 memcpy(name
, &str
[0], max_size
);
2362 name
[max_size
] = '\0';
2366 return result
->success
!= 0;
2369 void GLES2Implementation::GetActiveUniform(
2370 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2371 GLenum
* type
, char* name
) {
2372 GPU_CLIENT_SINGLE_THREAD_CHECK();
2373 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2374 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2375 << static_cast<const void*>(length
) << ", "
2376 << static_cast<const void*>(size
) << ", "
2377 << static_cast<const void*>(type
) << ", "
2378 << static_cast<const void*>(name
) << ", ");
2380 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2383 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2384 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2385 this, program
, index
, bufsize
, length
, size
, type
, name
);
2388 GPU_CLIENT_LOG(" size: " << *size
);
2391 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2394 GPU_CLIENT_LOG(" name: " << name
);
2400 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2401 GLuint program
, GLuint index
, GLsizei bufsize
,
2402 GLsizei
* length
, char* name
) {
2403 DCHECK_LE(0, bufsize
);
2404 // Clear the bucket so if the command fails nothing will be in it.
2405 helper_
->SetBucketSize(kResultBucketId
, 0);
2406 typedef cmds::GetActiveUniformBlockName::Result Result
;
2407 Result
* result
= GetResultAs
<Result
*>();
2411 // Set as failed so if the command fails we'll recover.
2413 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2414 GetResultShmId(), GetResultShmOffset());
2421 } else if (length
|| name
) {
2422 std::vector
<int8
> str
;
2423 GetBucketContents(kResultBucketId
, &str
);
2424 DCHECK_GT(str
.size(), 0u);
2426 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2431 memcpy(name
, &str
[0], max_size
);
2432 name
[max_size
] = '\0';
2436 return *result
!= 0;
2439 void GLES2Implementation::GetActiveUniformBlockName(
2440 GLuint program
, GLuint index
, GLsizei bufsize
,
2441 GLsizei
* length
, char* name
) {
2442 GPU_CLIENT_SINGLE_THREAD_CHECK();
2443 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2444 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2445 << static_cast<const void*>(length
) << ", "
2446 << static_cast<const void*>(name
) << ")");
2448 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2451 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2453 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2454 this, program
, index
, bufsize
, length
, name
);
2457 GPU_CLIENT_LOG(" name: " << name
);
2463 bool GLES2Implementation::GetActiveUniformBlockivHelper(
2464 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2465 typedef cmds::GetActiveUniformBlockiv::Result Result
;
2466 Result
* result
= GetResultAs
<Result
*>();
2470 result
->SetNumResults(0);
2471 helper_
->GetActiveUniformBlockiv(
2472 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
2474 if (result
->GetNumResults() > 0) {
2476 result
->CopyResult(params
);
2478 GPU_CLIENT_LOG_CODE_BLOCK({
2479 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2480 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2488 void GLES2Implementation::GetActiveUniformBlockiv(
2489 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2490 GPU_CLIENT_SINGLE_THREAD_CHECK();
2491 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
2492 << program
<< ", " << index
<< ", "
2493 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
2494 << static_cast<const void*>(params
) << ")");
2495 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
2497 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
2498 this, program
, index
, pname
, params
);
2501 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
2502 // be more than one value returned in params.
2503 GPU_CLIENT_LOG(" params: " << params
[0]);
2509 bool GLES2Implementation::GetActiveUniformsivHelper(
2510 GLuint program
, GLsizei count
, const GLuint
* indices
,
2511 GLenum pname
, GLint
* params
) {
2512 typedef cmds::GetActiveUniformsiv::Result Result
;
2513 Result
* result
= GetResultAs
<Result
*>();
2517 result
->SetNumResults(0);
2518 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
2519 bytes
*= sizeof(GLuint
);
2520 if (!bytes
.IsValid()) {
2521 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
2524 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
2525 helper_
->GetActiveUniformsiv(
2526 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
2528 bool success
= result
->GetNumResults() == count
;
2531 result
->CopyResult(params
);
2533 GPU_CLIENT_LOG_CODE_BLOCK({
2534 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2535 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2539 helper_
->SetBucketSize(kResultBucketId
, 0);
2543 void GLES2Implementation::GetActiveUniformsiv(
2544 GLuint program
, GLsizei count
, const GLuint
* indices
,
2545 GLenum pname
, GLint
* params
) {
2546 GPU_CLIENT_SINGLE_THREAD_CHECK();
2547 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
2548 << program
<< ", " << count
<< ", "
2549 << static_cast<const void*>(indices
) << ", "
2550 << GLES2Util::GetStringUniformParameter(pname
) << ", "
2551 << static_cast<const void*>(params
) << ")");
2552 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
2554 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
2557 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
2558 this, program
, count
, indices
, pname
, params
);
2561 GPU_CLIENT_LOG_CODE_BLOCK({
2562 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
2563 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
2571 void GLES2Implementation::GetAttachedShaders(
2572 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
2573 GPU_CLIENT_SINGLE_THREAD_CHECK();
2574 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
2575 << program
<< ", " << maxcount
<< ", "
2576 << static_cast<const void*>(count
) << ", "
2577 << static_cast<const void*>(shaders
) << ", ");
2579 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2582 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2583 typedef cmds::GetAttachedShaders::Result Result
;
2584 uint32 size
= Result::ComputeSize(maxcount
);
2585 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2589 result
->SetNumResults(0);
2590 helper_
->GetAttachedShaders(
2592 transfer_buffer_
->GetShmId(),
2593 transfer_buffer_
->GetOffset(result
),
2595 int32 token
= helper_
->InsertToken();
2598 *count
= result
->GetNumResults();
2600 result
->CopyResult(shaders
);
2601 GPU_CLIENT_LOG_CODE_BLOCK({
2602 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2603 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2606 transfer_buffer_
->FreePendingToken(result
, token
);
2610 void GLES2Implementation::GetShaderPrecisionFormat(
2611 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2612 GPU_CLIENT_SINGLE_THREAD_CHECK();
2613 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
2614 << GLES2Util::GetStringShaderType(shadertype
) << ", "
2615 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
2616 << static_cast<const void*>(range
) << ", "
2617 << static_cast<const void*>(precision
) << ", ");
2618 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
2619 typedef cmds::GetShaderPrecisionFormat::Result Result
;
2620 Result
* result
= GetResultAs
<Result
*>();
2625 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
2626 GLStaticState::ShaderPrecisionMap::iterator i
=
2627 static_state_
.shader_precisions
.find(key
);
2628 if (i
!= static_state_
.shader_precisions
.end()) {
2629 *result
= i
->second
;
2631 result
->success
= false;
2632 helper_
->GetShaderPrecisionFormat(
2633 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
2635 if (result
->success
)
2636 static_state_
.shader_precisions
[key
] = *result
;
2639 if (result
->success
) {
2641 range
[0] = result
->min_range
;
2642 range
[1] = result
->max_range
;
2643 GPU_CLIENT_LOG(" min_range: " << range
[0]);
2644 GPU_CLIENT_LOG(" min_range: " << range
[1]);
2647 precision
[0] = result
->precision
;
2648 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
2654 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
2655 const char* result
= NULL
;
2656 // Clears the bucket so if the command fails nothing will be in it.
2657 helper_
->SetBucketSize(kResultBucketId
, 0);
2658 helper_
->GetString(name
, kResultBucketId
);
2660 if (GetBucketAsString(kResultBucketId
, &str
)) {
2661 // Adds extensions implemented on client side only.
2664 str
+= std::string(str
.empty() ? "" : " ") +
2665 "GL_CHROMIUM_flipy "
2666 "GL_EXT_unpack_subimage "
2667 "GL_CHROMIUM_map_sub";
2668 if (capabilities_
.image
)
2669 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
2670 if (capabilities_
.future_sync_points
)
2671 str
+= " GL_CHROMIUM_future_sync_point";
2677 // Because of WebGL the extensions can change. We have to cache each unique
2678 // result since we don't know when the client will stop referring to a
2679 // previous one it queries.
2680 GLStringMap::iterator it
= gl_strings_
.find(name
);
2681 if (it
== gl_strings_
.end()) {
2682 std::set
<std::string
> strings
;
2683 std::pair
<GLStringMap::iterator
, bool> insert_result
=
2684 gl_strings_
.insert(std::make_pair(name
, strings
));
2685 DCHECK(insert_result
.second
);
2686 it
= insert_result
.first
;
2688 std::set
<std::string
>& string_set
= it
->second
;
2689 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
2690 if (sit
!= string_set
.end()) {
2691 result
= sit
->c_str();
2693 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2694 string_set
.insert(str
);
2695 DCHECK(insert_result
.second
);
2696 result
= insert_result
.first
->c_str();
2699 return reinterpret_cast<const GLubyte
*>(result
);
2702 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
2703 GPU_CLIENT_SINGLE_THREAD_CHECK();
2704 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
2705 << GLES2Util::GetStringStringType(name
) << ")");
2706 TRACE_EVENT0("gpu", "GLES2::GetString");
2707 const GLubyte
* result
= GetStringHelper(name
);
2708 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
2713 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
2714 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2715 GLenum
* type
, char* name
) {
2716 // Clear the bucket so if the command fails nothing will be in it.
2717 helper_
->SetBucketSize(kResultBucketId
, 0);
2718 typedef cmds::GetTransformFeedbackVarying::Result Result
;
2719 Result
* result
= GetResultAs
<Result
*>();
2723 // Set as failed so if the command fails we'll recover.
2724 result
->success
= false;
2725 helper_
->GetTransformFeedbackVarying(
2726 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
2728 if (result
->success
) {
2730 *size
= result
->size
;
2733 *type
= result
->type
;
2735 if (length
|| name
) {
2736 std::vector
<int8
> str
;
2737 GetBucketContents(kResultBucketId
, &str
);
2738 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
2747 memcpy(name
, &str
[0], max_size
);
2748 name
[max_size
] = '\0';
2749 } else if (bufsize
> 0) {
2755 return result
->success
!= 0;
2758 void GLES2Implementation::GetTransformFeedbackVarying(
2759 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2760 GLenum
* type
, char* name
) {
2761 GPU_CLIENT_SINGLE_THREAD_CHECK();
2762 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
2763 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2764 << static_cast<const void*>(length
) << ", "
2765 << static_cast<const void*>(size
) << ", "
2766 << static_cast<const void*>(type
) << ", "
2767 << static_cast<const void*>(name
) << ", ");
2769 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
2773 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
2775 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
2776 this, program
, index
, bufsize
, length
, size
, type
, name
);
2779 GPU_CLIENT_LOG(" size: " << *size
);
2782 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2785 GPU_CLIENT_LOG(" name: " << name
);
2791 void GLES2Implementation::GetUniformfv(
2792 GLuint program
, GLint location
, GLfloat
* params
) {
2793 GPU_CLIENT_SINGLE_THREAD_CHECK();
2794 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
2795 << program
<< ", " << location
<< ", "
2796 << static_cast<const void*>(params
) << ")");
2797 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
2798 typedef cmds::GetUniformfv::Result Result
;
2799 Result
* result
= GetResultAs
<Result
*>();
2803 result
->SetNumResults(0);
2804 helper_
->GetUniformfv(
2805 program
, location
, GetResultShmId(), GetResultShmOffset());
2807 result
->CopyResult(params
);
2808 GPU_CLIENT_LOG_CODE_BLOCK({
2809 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2810 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2816 void GLES2Implementation::GetUniformiv(
2817 GLuint program
, GLint location
, GLint
* params
) {
2818 GPU_CLIENT_SINGLE_THREAD_CHECK();
2819 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
2820 << program
<< ", " << location
<< ", "
2821 << static_cast<const void*>(params
) << ")");
2822 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
2823 typedef cmds::GetUniformiv::Result Result
;
2824 Result
* result
= GetResultAs
<Result
*>();
2828 result
->SetNumResults(0);
2829 helper_
->GetUniformiv(
2830 program
, location
, GetResultShmId(), GetResultShmOffset());
2832 GetResultAs
<cmds::GetUniformfv::Result
*>()->CopyResult(params
);
2833 GPU_CLIENT_LOG_CODE_BLOCK({
2834 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2835 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2841 void GLES2Implementation::ReadPixels(
2842 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
2843 GLenum type
, void* pixels
) {
2844 GPU_CLIENT_SINGLE_THREAD_CHECK();
2845 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
2846 << xoffset
<< ", " << yoffset
<< ", "
2847 << width
<< ", " << height
<< ", "
2848 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
2849 << GLES2Util::GetStringPixelType(type
) << ", "
2850 << static_cast<const void*>(pixels
) << ")");
2851 if (width
< 0 || height
< 0) {
2852 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
2855 if (width
== 0 || height
== 0) {
2859 // glReadPixel pads the size of each row of pixels by an amount specified by
2860 // glPixelStorei. So, we have to take that into account both in the fact that
2861 // the pixels returned from the ReadPixel command will include that padding
2862 // and that when we copy the results to the user's buffer we need to not
2863 // write those padding bytes but leave them as they are.
2865 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
2866 typedef cmds::ReadPixels::Result Result
;
2868 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
2870 uint32 unpadded_row_size
;
2871 uint32 padded_row_size
;
2872 if (!GLES2Util::ComputeImageDataSizes(
2873 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
2874 &unpadded_row_size
, &padded_row_size
)) {
2875 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
2879 if (bound_pixel_pack_transfer_buffer_id_
) {
2880 GLuint offset
= ToGLuint(pixels
);
2881 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2882 bound_pixel_pack_transfer_buffer_id_
,
2883 "glReadPixels", offset
, padded_row_size
* height
);
2884 if (buffer
&& buffer
->shm_id() != -1) {
2885 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
2886 buffer
->shm_id(), buffer
->shm_offset(),
2894 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
2898 // Transfer by rows.
2899 // The max rows we can transfer.
2901 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
2902 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
2903 if (!buffer
.valid()) {
2906 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2907 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
2908 num_rows
= std::min(num_rows
, height
);
2909 // NOTE: We must look up the address of the result area AFTER allocation
2910 // of the transfer buffer since the transfer buffer may be reallocated.
2911 Result
* result
= GetResultAs
<Result
*>();
2915 *result
= 0; // mark as failed.
2916 helper_
->ReadPixels(
2917 xoffset
, yoffset
, width
, num_rows
, format
, type
,
2918 buffer
.shm_id(), buffer
.offset(),
2919 GetResultShmId(), GetResultShmOffset(),
2923 // when doing a y-flip we have to iterate through top-to-bottom chunks
2924 // of the dst. The service side handles reversing the rows within a
2927 if (pack_reverse_row_order_
) {
2928 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
2932 // We have to copy 1 row at a time to avoid writing pad bytes.
2933 const int8
* src
= static_cast<const int8
*>(buffer
.address());
2934 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
2935 memcpy(rows_dst
, src
, unpadded_row_size
);
2936 rows_dst
+= padded_row_size
;
2937 src
+= padded_row_size
;
2939 if (!pack_reverse_row_order_
) {
2943 // If it was not marked as successful exit.
2947 yoffset
+= num_rows
;
2953 void GLES2Implementation::ActiveTexture(GLenum texture
) {
2954 GPU_CLIENT_SINGLE_THREAD_CHECK();
2955 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
2956 << GLES2Util::GetStringEnum(texture
) << ")");
2957 GLuint texture_index
= texture
- GL_TEXTURE0
;
2958 if (texture_index
>=
2959 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
2960 SetGLErrorInvalidEnum(
2961 "glActiveTexture", texture
, "texture");
2965 active_texture_unit_
= texture_index
;
2966 helper_
->ActiveTexture(texture
);
2970 void GLES2Implementation::GenBuffersHelper(
2971 GLsizei
/* n */, const GLuint
* /* buffers */) {
2974 void GLES2Implementation::GenFramebuffersHelper(
2975 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
2978 void GLES2Implementation::GenRenderbuffersHelper(
2979 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
2982 void GLES2Implementation::GenTexturesHelper(
2983 GLsizei
/* n */, const GLuint
* /* textures */) {
2986 void GLES2Implementation::GenVertexArraysOESHelper(
2987 GLsizei n
, const GLuint
* arrays
) {
2988 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
2991 void GLES2Implementation::GenQueriesEXTHelper(
2992 GLsizei
/* n */, const GLuint
* /* queries */) {
2995 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
2997 const GLuint
* /* valuebuffers */) {
3000 void GLES2Implementation::GenSamplersHelper(
3001 GLsizei
/* n */, const GLuint
* /* samplers */) {
3004 void GLES2Implementation::GenTransformFeedbacksHelper(
3005 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3008 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3009 // generates a new resource. On newer versions of OpenGL they don't. The code
3010 // related to binding below will need to change if we switch to the new OpenGL
3011 // model. Specifically it assumes a bind will succeed which is always true in
3012 // the old model but possibly not true in the new model if another context has
3013 // deleted the resource.
3015 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3016 // used even when Bind has failed. However, the bug is minor compared to the
3017 // overhead & duplicated checking in client side.
3019 void GLES2Implementation::BindBufferHelper(
3020 GLenum target
, GLuint buffer_id
) {
3021 // TODO(gman): See note #1 above.
3022 bool changed
= false;
3024 case GL_ARRAY_BUFFER
:
3025 if (bound_array_buffer_id_
!= buffer_id
) {
3026 bound_array_buffer_id_
= buffer_id
;
3030 case GL_ELEMENT_ARRAY_BUFFER
:
3031 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3033 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3034 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3036 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3037 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3043 // TODO(gman): See note #2 above.
3045 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3046 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3050 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3051 helper_
->BindBuffer(target
, buffer
);
3052 if (share_group_
->bind_generates_resource())
3053 helper_
->CommandBufferHelper::Flush();
3056 void GLES2Implementation::BindBufferBaseHelper(
3057 GLenum target
, GLuint index
, GLuint buffer_id
) {
3058 // TODO(zmo): See note #1 above.
3059 // TODO(zmo): See note #2 above.
3060 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3061 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3064 void GLES2Implementation::BindBufferBaseStub(
3065 GLenum target
, GLuint index
, GLuint buffer
) {
3066 helper_
->BindBufferBase(target
, index
, buffer
);
3067 if (share_group_
->bind_generates_resource())
3068 helper_
->CommandBufferHelper::Flush();
3071 void GLES2Implementation::BindBufferRangeHelper(
3072 GLenum target
, GLuint index
, GLuint buffer_id
,
3073 GLintptr offset
, GLsizeiptr size
) {
3074 // TODO(zmo): See note #1 above.
3075 // TODO(zmo): See note #2 above.
3076 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3077 this, target
, index
, buffer_id
, offset
, size
,
3078 &GLES2Implementation::BindBufferRangeStub
);
3081 void GLES2Implementation::BindBufferRangeStub(
3082 GLenum target
, GLuint index
, GLuint buffer
,
3083 GLintptr offset
, GLsizeiptr size
) {
3084 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3085 if (share_group_
->bind_generates_resource())
3086 helper_
->CommandBufferHelper::Flush();
3089 void GLES2Implementation::BindFramebufferHelper(
3090 GLenum target
, GLuint framebuffer
) {
3091 // TODO(gman): See note #1 above.
3092 bool changed
= false;
3094 case GL_FRAMEBUFFER
:
3095 if (bound_framebuffer_
!= framebuffer
||
3096 bound_read_framebuffer_
!= framebuffer
) {
3097 bound_framebuffer_
= framebuffer
;
3098 bound_read_framebuffer_
= framebuffer
;
3102 case GL_READ_FRAMEBUFFER
:
3103 if (!IsChromiumFramebufferMultisampleAvailable()) {
3104 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3107 if (bound_read_framebuffer_
!= framebuffer
) {
3108 bound_read_framebuffer_
= framebuffer
;
3112 case GL_DRAW_FRAMEBUFFER
:
3113 if (!IsChromiumFramebufferMultisampleAvailable()) {
3114 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3117 if (bound_framebuffer_
!= framebuffer
) {
3118 bound_framebuffer_
= framebuffer
;
3123 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3128 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3129 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3133 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3134 GLuint framebuffer
) {
3135 helper_
->BindFramebuffer(target
, framebuffer
);
3136 if (share_group_
->bind_generates_resource())
3137 helper_
->CommandBufferHelper::Flush();
3140 void GLES2Implementation::BindRenderbufferHelper(
3141 GLenum target
, GLuint renderbuffer
) {
3142 // TODO(gman): See note #1 above.
3143 bool changed
= false;
3145 case GL_RENDERBUFFER
:
3146 if (bound_renderbuffer_
!= renderbuffer
) {
3147 bound_renderbuffer_
= renderbuffer
;
3155 // TODO(zmo): See note #2 above.
3157 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3158 this, target
, renderbuffer
,
3159 &GLES2Implementation::BindRenderbufferStub
);
3163 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3164 GLuint renderbuffer
) {
3165 helper_
->BindRenderbuffer(target
, renderbuffer
);
3166 if (share_group_
->bind_generates_resource())
3167 helper_
->CommandBufferHelper::Flush();
3170 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3172 helper_
->BindSampler(unit
, sampler
);
3175 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3176 // TODO(gman): See note #1 above.
3177 // TODO(gman): Change this to false once we figure out why it's failing
3179 bool changed
= true;
3180 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3183 if (unit
.bound_texture_2d
!= texture
) {
3184 unit
.bound_texture_2d
= texture
;
3188 case GL_TEXTURE_CUBE_MAP
:
3189 if (unit
.bound_texture_cube_map
!= texture
) {
3190 unit
.bound_texture_cube_map
= texture
;
3194 case GL_TEXTURE_EXTERNAL_OES
:
3195 if (unit
.bound_texture_external_oes
!= texture
) {
3196 unit
.bound_texture_external_oes
= texture
;
3204 // TODO(gman): See note #2 above.
3206 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3207 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3211 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3212 helper_
->BindTexture(target
, texture
);
3213 if (share_group_
->bind_generates_resource())
3214 helper_
->CommandBufferHelper::Flush();
3217 void GLES2Implementation::BindTransformFeedbackHelper(
3218 GLenum target
, GLuint transformfeedback
) {
3219 helper_
->BindTransformFeedback(target
, transformfeedback
);
3222 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3223 bool changed
= false;
3224 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3226 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3227 // because unlike other resources VertexArrayObject ids must
3228 // be generated by GenVertexArrays. A random id to Bind will not
3229 // generate a new object.
3230 helper_
->BindVertexArrayOES(array
);
3234 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3235 "id was not generated with glGenVertexArrayOES");
3239 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3240 GLuint valuebuffer
) {
3241 bool changed
= false;
3243 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3244 if (bound_valuebuffer_
!= valuebuffer
) {
3245 bound_valuebuffer_
= valuebuffer
;
3253 // TODO(gman): See note #2 above.
3255 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3256 this, target
, valuebuffer
,
3257 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3261 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3262 GLuint valuebuffer
) {
3263 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3264 if (share_group_
->bind_generates_resource())
3265 helper_
->CommandBufferHelper::Flush();
3268 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3269 if (current_program_
!= program
) {
3270 current_program_
= program
;
3271 helper_
->UseProgram(program
);
3275 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3276 return vertex_array_object_manager_
->IsReservedId(id
);
3279 void GLES2Implementation::DeleteBuffersHelper(
3280 GLsizei n
, const GLuint
* buffers
) {
3281 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3282 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3285 "glDeleteBuffers", "id not created by this context.");
3288 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3289 if (buffers
[ii
] == bound_array_buffer_id_
) {
3290 bound_array_buffer_id_
= 0;
3292 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3294 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3296 RemoveTransferBuffer(buffer
);
3298 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3299 bound_pixel_unpack_transfer_buffer_id_
= 0;
3302 RemoveMappedBufferRangeById(buffers
[ii
]);
3306 void GLES2Implementation::DeleteBuffersStub(
3307 GLsizei n
, const GLuint
* buffers
) {
3308 helper_
->DeleteBuffersImmediate(n
, buffers
);
3312 void GLES2Implementation::DeleteFramebuffersHelper(
3313 GLsizei n
, const GLuint
* framebuffers
) {
3314 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3315 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3318 "glDeleteFramebuffers", "id not created by this context.");
3321 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3322 if (framebuffers
[ii
] == bound_framebuffer_
) {
3323 bound_framebuffer_
= 0;
3325 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3326 bound_read_framebuffer_
= 0;
3331 void GLES2Implementation::DeleteFramebuffersStub(
3332 GLsizei n
, const GLuint
* framebuffers
) {
3333 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3336 void GLES2Implementation::DeleteRenderbuffersHelper(
3337 GLsizei n
, const GLuint
* renderbuffers
) {
3338 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3339 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3342 "glDeleteRenderbuffers", "id not created by this context.");
3345 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3346 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3347 bound_renderbuffer_
= 0;
3352 void GLES2Implementation::DeleteRenderbuffersStub(
3353 GLsizei n
, const GLuint
* renderbuffers
) {
3354 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3357 void GLES2Implementation::DeleteTexturesHelper(
3358 GLsizei n
, const GLuint
* textures
) {
3359 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3360 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3363 "glDeleteTextures", "id not created by this context.");
3366 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3367 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3369 TextureUnit
& unit
= texture_units_
[tt
];
3370 if (textures
[ii
] == unit
.bound_texture_2d
) {
3371 unit
.bound_texture_2d
= 0;
3373 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3374 unit
.bound_texture_cube_map
= 0;
3376 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3377 unit
.bound_texture_external_oes
= 0;
3383 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
3384 const GLuint
* textures
) {
3385 helper_
->DeleteTexturesImmediate(n
, textures
);
3388 void GLES2Implementation::DeleteVertexArraysOESHelper(
3389 GLsizei n
, const GLuint
* arrays
) {
3390 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
3391 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
3392 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
3395 "glDeleteVertexArraysOES", "id not created by this context.");
3400 void GLES2Implementation::DeleteVertexArraysOESStub(
3401 GLsizei n
, const GLuint
* arrays
) {
3402 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
3405 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
3407 const GLuint
* valuebuffers
) {
3408 if (!GetIdHandler(id_namespaces::kValuebuffers
)
3409 ->FreeIds(this, n
, valuebuffers
,
3410 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
3411 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
3412 "id not created by this context.");
3415 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3416 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
3417 bound_valuebuffer_
= 0;
3422 void GLES2Implementation::DeleteSamplersStub(
3423 GLsizei n
, const GLuint
* samplers
) {
3424 helper_
->DeleteSamplersImmediate(n
, samplers
);
3427 void GLES2Implementation::DeleteSamplersHelper(
3428 GLsizei n
, const GLuint
* samplers
) {
3429 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
3430 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
3433 "glDeleteSamplers", "id not created by this context.");
3438 void GLES2Implementation::DeleteTransformFeedbacksStub(
3439 GLsizei n
, const GLuint
* transformfeedbacks
) {
3440 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
3443 void GLES2Implementation::DeleteTransformFeedbacksHelper(
3444 GLsizei n
, const GLuint
* transformfeedbacks
) {
3445 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
3446 this, n
, transformfeedbacks
,
3447 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
3450 "glDeleteTransformFeedbacks", "id not created by this context.");
3455 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
3457 const GLuint
* valuebuffers
) {
3458 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
3461 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
3462 GPU_CLIENT_SINGLE_THREAD_CHECK();
3464 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
3465 vertex_array_object_manager_
->SetAttribEnable(index
, false);
3466 helper_
->DisableVertexAttribArray(index
);
3470 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
3471 GPU_CLIENT_SINGLE_THREAD_CHECK();
3472 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
3474 vertex_array_object_manager_
->SetAttribEnable(index
, true);
3475 helper_
->EnableVertexAttribArray(index
);
3479 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
3480 GPU_CLIENT_SINGLE_THREAD_CHECK();
3481 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
3482 << GLES2Util::GetStringDrawMode(mode
) << ", "
3483 << first
<< ", " << count
<< ")");
3485 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
3488 bool simulated
= false;
3489 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3490 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
3493 helper_
->DrawArrays(mode
, first
, count
);
3494 RestoreArrayBuffer(simulated
);
3498 void GLES2Implementation::GetVertexAttribfv(
3499 GLuint index
, GLenum pname
, GLfloat
* params
) {
3500 GPU_CLIENT_SINGLE_THREAD_CHECK();
3501 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
3503 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
3504 << static_cast<const void*>(params
) << ")");
3506 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
3507 *params
= static_cast<float>(value
);
3510 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
3511 typedef cmds::GetVertexAttribfv::Result Result
;
3512 Result
* result
= GetResultAs
<Result
*>();
3516 result
->SetNumResults(0);
3517 helper_
->GetVertexAttribfv(
3518 index
, pname
, GetResultShmId(), GetResultShmOffset());
3520 result
->CopyResult(params
);
3521 GPU_CLIENT_LOG_CODE_BLOCK({
3522 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3523 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3529 void GLES2Implementation::GetVertexAttribiv(
3530 GLuint index
, GLenum pname
, GLint
* params
) {
3531 GPU_CLIENT_SINGLE_THREAD_CHECK();
3532 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
3534 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
3535 << static_cast<const void*>(params
) << ")");
3537 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
3541 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
3542 typedef cmds::GetVertexAttribiv::Result Result
;
3543 Result
* result
= GetResultAs
<Result
*>();
3547 result
->SetNumResults(0);
3548 helper_
->GetVertexAttribiv(
3549 index
, pname
, GetResultShmId(), GetResultShmOffset());
3551 result
->CopyResult(params
);
3552 GPU_CLIENT_LOG_CODE_BLOCK({
3553 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3554 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3560 void GLES2Implementation::Swap() {
3564 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
3565 PostSubBufferCHROMIUM(
3566 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
3569 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
3570 switch (plane_transform
) {
3571 case gfx::OVERLAY_TRANSFORM_INVALID
:
3573 case gfx::OVERLAY_TRANSFORM_NONE
:
3574 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
3575 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
3576 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
3577 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
3578 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
3579 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
3580 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
3581 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
3582 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
3583 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
3584 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
3587 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
3590 void GLES2Implementation::ScheduleOverlayPlane(
3592 gfx::OverlayTransform plane_transform
,
3593 unsigned overlay_texture_id
,
3594 const gfx::Rect
& display_bounds
,
3595 const gfx::RectF
& uv_rect
) {
3596 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
3597 GetGLESOverlayTransform(plane_transform
),
3601 display_bounds
.width(),
3602 display_bounds
.height(),
3609 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
3610 const char* feature
) {
3611 GPU_CLIENT_SINGLE_THREAD_CHECK();
3612 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
3614 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
3615 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
3616 Result
* result
= GetResultAs
<Result
*>();
3621 SetBucketAsCString(kResultBucketId
, feature
);
3622 helper_
->EnableFeatureCHROMIUM(
3623 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3625 helper_
->SetBucketSize(kResultBucketId
, 0);
3626 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
3627 return *result
!= 0;
3630 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
3631 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
3632 GPU_CLIENT_SINGLE_THREAD_CHECK();
3633 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
3634 << target
<< ", " << offset
<< ", " << size
<< ", "
3635 << GLES2Util::GetStringEnum(access
) << ")");
3636 // NOTE: target is NOT checked because the service will check it
3637 // and we don't know what targets are valid.
3638 if (access
!= GL_WRITE_ONLY
) {
3639 SetGLErrorInvalidEnum(
3640 "glMapBufferSubDataCHROMIUM", access
, "access");
3643 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
3644 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
3649 unsigned int shm_offset
;
3650 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
3652 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
3656 std::pair
<MappedBufferMap::iterator
, bool> result
=
3657 mapped_buffers_
.insert(std::make_pair(
3660 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
3661 DCHECK(result
.second
);
3662 GPU_CLIENT_LOG(" returned " << mem
);
3666 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
3667 GPU_CLIENT_SINGLE_THREAD_CHECK();
3669 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
3670 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
3671 if (it
== mapped_buffers_
.end()) {
3673 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
3676 const MappedBuffer
& mb
= it
->second
;
3677 helper_
->BufferSubData(
3678 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
3679 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
3680 mapped_buffers_
.erase(it
);
3684 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
3685 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
3687 bool cached
= GetHelper(binding
, &id
);
3689 return static_cast<GLuint
>(id
);
3692 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
3693 GLuint buffer
= GetBoundBufferHelper(target
);
3694 RemoveMappedBufferRangeById(buffer
);
3697 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
3699 auto iter
= mapped_buffer_range_map_
.find(buffer
);
3700 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
3701 mapped_memory_
->FreePendingToken(
3702 iter
->second
.shm_memory
, helper_
->InsertToken());
3703 mapped_buffer_range_map_
.erase(iter
);
3708 void GLES2Implementation::ClearMappedBufferRangeMap() {
3709 for (auto& buffer_range
: mapped_buffer_range_map_
) {
3710 if (buffer_range
.second
.shm_memory
) {
3711 mapped_memory_
->FreePendingToken(
3712 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
3715 mapped_buffer_range_map_
.clear();
3718 void* GLES2Implementation::MapBufferRange(
3719 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
3720 GPU_CLIENT_SINGLE_THREAD_CHECK();
3721 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
3722 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
3723 << size
<< ", " << access
<< ")");
3724 if (!ValidateSize("glMapBufferRange", size
) ||
3725 !ValidateOffset("glMapBufferRange", offset
)) {
3730 unsigned int shm_offset
;
3731 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
3733 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
3737 typedef cmds::MapBufferRange::Result Result
;
3738 Result
* result
= GetResultAs
<Result
*>();
3740 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
3741 GetResultShmId(), GetResultShmOffset());
3742 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
3743 // consider an early return without WaitForCmd(). crbug.com/465804.
3746 const GLbitfield kInvalidateBits
=
3747 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
3748 if ((access
& kInvalidateBits
) != 0) {
3749 // We do not read back from the buffer, therefore, we set the client
3750 // side memory to zero to avoid uninitialized data.
3751 memset(mem
, 0, size
);
3753 GLuint buffer
= GetBoundBufferHelper(target
);
3754 DCHECK_NE(0u, buffer
);
3755 // glMapBufferRange fails on an already mapped buffer.
3756 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
3757 mapped_buffer_range_map_
.end());
3758 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
3760 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
3761 DCHECK(iter
.second
);
3763 mapped_memory_
->Free(mem
);
3767 GPU_CLIENT_LOG(" returned " << mem
);
3772 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
3773 GPU_CLIENT_SINGLE_THREAD_CHECK();
3774 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
3775 << GLES2Util::GetStringEnum(target
) << ")");
3777 case GL_ARRAY_BUFFER
:
3778 case GL_ELEMENT_ARRAY_BUFFER
:
3779 case GL_COPY_READ_BUFFER
:
3780 case GL_COPY_WRITE_BUFFER
:
3781 case GL_PIXEL_PACK_BUFFER
:
3782 case GL_PIXEL_UNPACK_BUFFER
:
3783 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3784 case GL_UNIFORM_BUFFER
:
3787 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
3790 GLuint buffer
= GetBoundBufferHelper(target
);
3792 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
3795 auto iter
= mapped_buffer_range_map_
.find(buffer
);
3796 if (iter
== mapped_buffer_range_map_
.end()) {
3797 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
3801 helper_
->UnmapBuffer(target
);
3802 RemoveMappedBufferRangeById(buffer
);
3803 // TODO(zmo): There is a rare situation that data might be corrupted and
3804 // GL_FALSE should be returned. We lose context on that sitatuon, so we
3805 // don't have to WaitForCmd().
3806 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
3811 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
3821 GPU_CLIENT_SINGLE_THREAD_CHECK();
3822 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
3823 << target
<< ", " << level
<< ", "
3824 << xoffset
<< ", " << yoffset
<< ", "
3825 << width
<< ", " << height
<< ", "
3826 << GLES2Util::GetStringTextureFormat(format
) << ", "
3827 << GLES2Util::GetStringPixelType(type
) << ", "
3828 << GLES2Util::GetStringEnum(access
) << ")");
3829 if (access
!= GL_WRITE_ONLY
) {
3830 SetGLErrorInvalidEnum(
3831 "glMapTexSubImage2DCHROMIUM", access
, "access");
3834 // NOTE: target is NOT checked because the service will check it
3835 // and we don't know what targets are valid.
3836 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
3838 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
3842 if (!GLES2Util::ComputeImageDataSizes(
3843 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
3845 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
3849 unsigned int shm_offset
;
3850 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
3852 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
3856 std::pair
<MappedTextureMap::iterator
, bool> result
=
3857 mapped_textures_
.insert(std::make_pair(
3860 access
, shm_id
, mem
, shm_offset
,
3861 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
3862 DCHECK(result
.second
);
3863 GPU_CLIENT_LOG(" returned " << mem
);
3867 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
3868 GPU_CLIENT_SINGLE_THREAD_CHECK();
3870 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
3871 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
3872 if (it
== mapped_textures_
.end()) {
3874 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
3877 const MappedTexture
& mt
= it
->second
;
3878 helper_
->TexSubImage2D(
3879 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
3880 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
3881 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
3882 mapped_textures_
.erase(it
);
3886 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
3887 float scale_factor
) {
3888 GPU_CLIENT_SINGLE_THREAD_CHECK();
3889 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
3890 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
3891 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
3895 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
3896 GPU_CLIENT_SINGLE_THREAD_CHECK();
3897 GPU_CLIENT_LOG("[" << GetLogPrefix()
3898 << "] glGetRequestableExtensionsCHROMIUM()");
3900 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
3901 const char* result
= NULL
;
3902 // Clear the bucket so if the command fails nothing will be in it.
3903 helper_
->SetBucketSize(kResultBucketId
, 0);
3904 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
3906 if (GetBucketAsString(kResultBucketId
, &str
)) {
3907 // The set of requestable extensions shrinks as we enable
3908 // them. Because we don't know when the client will stop referring
3909 // to a previous one it queries (see GetString) we need to cache
3910 // the unique results.
3911 std::set
<std::string
>::const_iterator sit
=
3912 requestable_extensions_set_
.find(str
);
3913 if (sit
!= requestable_extensions_set_
.end()) {
3914 result
= sit
->c_str();
3916 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3917 requestable_extensions_set_
.insert(str
);
3918 DCHECK(insert_result
.second
);
3919 result
= insert_result
.first
->c_str();
3922 GPU_CLIENT_LOG(" returned " << result
);
3923 return reinterpret_cast<const GLchar
*>(result
);
3926 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
3927 // with VirtualGL contexts.
3928 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
3929 GPU_CLIENT_SINGLE_THREAD_CHECK();
3930 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
3931 << extension
<< ")");
3932 SetBucketAsCString(kResultBucketId
, extension
);
3933 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
3934 helper_
->SetBucketSize(kResultBucketId
, 0);
3936 struct ExtensionCheck
{
3937 const char* extension
;
3938 ExtensionStatus
* status
;
3940 const ExtensionCheck checks
[] = {
3942 "GL_ANGLE_pack_reverse_row_order",
3943 &angle_pack_reverse_row_order_status_
,
3946 "GL_CHROMIUM_framebuffer_multisample",
3947 &chromium_framebuffer_multisample_
,
3950 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
3951 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
3952 const ExtensionCheck
& check
= checks
[ii
];
3953 if (*check
.status
== kUnavailableExtensionStatus
&&
3954 !strcmp(extension
, check
.extension
)) {
3955 *check
.status
= kUnknownExtensionStatus
;
3960 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
3961 GPU_CLIENT_SINGLE_THREAD_CHECK();
3962 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
3963 // Wait if this would add too many rate limit tokens.
3964 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
3965 helper_
->WaitForToken(rate_limit_tokens_
.front());
3966 rate_limit_tokens_
.pop();
3968 rate_limit_tokens_
.push(helper_
->InsertToken());
3971 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
3972 GLuint program
, std::vector
<int8
>* result
) {
3974 // Clear the bucket so if the command fails nothing will be in it.
3975 helper_
->SetBucketSize(kResultBucketId
, 0);
3976 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
3977 GetBucketContents(kResultBucketId
, result
);
3980 void GLES2Implementation::GetProgramInfoCHROMIUM(
3981 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
3982 GPU_CLIENT_SINGLE_THREAD_CHECK();
3985 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
3989 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
3992 // Make sure they've set size to 0 else the value will be undefined on
3994 DCHECK_EQ(0, *size
);
3995 std::vector
<int8
> result
;
3996 GetProgramInfoCHROMIUMHelper(program
, &result
);
3997 if (result
.empty()) {
4000 *size
= result
.size();
4004 if (static_cast<size_t>(bufsize
) < result
.size()) {
4005 SetGLError(GL_INVALID_OPERATION
,
4006 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4009 memcpy(info
, &result
[0], result
.size());
4012 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4013 GLuint program
, std::vector
<int8
>* result
) {
4015 // Clear the bucket so if the command fails nothing will be in it.
4016 helper_
->SetBucketSize(kResultBucketId
, 0);
4017 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4018 GetBucketContents(kResultBucketId
, result
);
4021 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4022 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4023 GPU_CLIENT_SINGLE_THREAD_CHECK();
4026 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4030 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4033 // Make sure they've set size to 0 else the value will be undefined on
4035 DCHECK_EQ(0, *size
);
4036 std::vector
<int8
> result
;
4037 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4038 if (result
.empty()) {
4041 *size
= result
.size();
4045 if (static_cast<size_t>(bufsize
) < result
.size()) {
4046 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4047 "bufsize is too small for result.");
4050 memcpy(info
, &result
[0], result
.size());
4053 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4054 GLuint program
, std::vector
<int8
>* result
) {
4056 // Clear the bucket so if the command fails nothing will be in it.
4057 helper_
->SetBucketSize(kResultBucketId
, 0);
4058 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4059 GetBucketContents(kResultBucketId
, result
);
4062 void GLES2Implementation::GetUniformsES3CHROMIUM(
4063 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4064 GPU_CLIENT_SINGLE_THREAD_CHECK();
4067 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4071 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4074 // Make sure they've set size to 0 else the value will be undefined on
4076 DCHECK_EQ(0, *size
);
4077 std::vector
<int8
> result
;
4078 GetUniformsES3CHROMIUMHelper(program
, &result
);
4079 if (result
.empty()) {
4082 *size
= result
.size();
4086 if (static_cast<size_t>(bufsize
) < result
.size()) {
4087 SetGLError(GL_INVALID_OPERATION
,
4088 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4091 memcpy(info
, &result
[0], result
.size());
4094 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4095 GLuint program
, std::vector
<int8
>* result
) {
4097 // Clear the bucket so if the command fails nothing will be in it.
4098 helper_
->SetBucketSize(kResultBucketId
, 0);
4099 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4100 GetBucketContents(kResultBucketId
, result
);
4103 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4104 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4105 GPU_CLIENT_SINGLE_THREAD_CHECK();
4107 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4108 "bufsize less than 0.");
4112 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4116 // Make sure they've set size to 0 else the value will be undefined on
4118 DCHECK_EQ(0, *size
);
4119 std::vector
<int8
> result
;
4120 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4121 if (result
.empty()) {
4124 *size
= result
.size();
4128 if (static_cast<size_t>(bufsize
) < result
.size()) {
4129 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4130 "bufsize is too small for result.");
4133 memcpy(info
, &result
[0], result
.size());
4136 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4137 GPU_CLIENT_SINGLE_THREAD_CHECK();
4138 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4140 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4141 helper_
->CommandBufferHelper::Flush();
4142 return gpu_control_
->CreateStreamTexture(texture
);
4145 void GLES2Implementation::PostSubBufferCHROMIUM(
4146 GLint x
, GLint y
, GLint width
, GLint height
) {
4147 GPU_CLIENT_SINGLE_THREAD_CHECK();
4148 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4149 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4150 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4151 "width", width
, "height", height
);
4153 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4154 swap_buffers_tokens_
.push(helper_
->InsertToken());
4155 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4156 helper_
->CommandBufferHelper::Flush();
4157 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4158 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4159 swap_buffers_tokens_
.pop();
4163 void GLES2Implementation::DeleteQueriesEXTHelper(
4164 GLsizei n
, const GLuint
* queries
) {
4165 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4166 query_tracker_
->RemoveQuery(queries
[ii
]);
4167 query_id_allocator_
->FreeID(queries
[ii
]);
4170 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4173 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4174 GPU_CLIENT_SINGLE_THREAD_CHECK();
4175 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4177 // TODO(gman): To be spec compliant IDs from other contexts sharing
4178 // resources need to return true here even though you can't share
4179 // queries across contexts?
4180 return query_tracker_
->GetQuery(id
) != NULL
;
4183 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4184 GPU_CLIENT_SINGLE_THREAD_CHECK();
4185 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4186 << GLES2Util::GetStringQueryTarget(target
)
4187 << ", " << id
<< ")");
4189 // if any outstanding queries INV_OP
4190 QueryMap::iterator it
= current_queries_
.find(target
);
4191 if (it
!= current_queries_
.end()) {
4193 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4199 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4203 // if not GENned INV_OPERATION
4204 if (!query_id_allocator_
->InUse(id
)) {
4205 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4209 // if id does not have an object
4210 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4212 query
= query_tracker_
->CreateQuery(id
, target
);
4214 SetGLError(GL_OUT_OF_MEMORY
,
4216 "transfer buffer allocation failed");
4219 } else if (query
->target() != target
) {
4221 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
4225 current_queries_
[target
] = query
;
4231 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4232 GPU_CLIENT_SINGLE_THREAD_CHECK();
4233 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4234 << GLES2Util::GetStringQueryTarget(target
) << ")");
4235 // Don't do anything if the context is lost.
4236 if (helper_
->IsContextLost()) {
4240 QueryMap::iterator it
= current_queries_
.find(target
);
4241 if (it
== current_queries_
.end()) {
4242 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
4246 QueryTracker::Query
* query
= it
->second
;
4248 current_queries_
.erase(it
);
4252 void GLES2Implementation::GetQueryivEXT(
4253 GLenum target
, GLenum pname
, GLint
* params
) {
4254 GPU_CLIENT_SINGLE_THREAD_CHECK();
4255 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
4256 << GLES2Util::GetStringQueryTarget(target
) << ", "
4257 << GLES2Util::GetStringQueryParameter(pname
) << ", "
4258 << static_cast<const void*>(params
) << ")");
4260 if (pname
!= GL_CURRENT_QUERY_EXT
) {
4261 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
4264 QueryMap::iterator it
= current_queries_
.find(target
);
4265 if (it
!= current_queries_
.end()) {
4266 QueryTracker::Query
* query
= it
->second
;
4267 *params
= query
->id();
4271 GPU_CLIENT_LOG(" " << *params
);
4275 void GLES2Implementation::GetQueryObjectuivEXT(
4276 GLuint id
, GLenum pname
, GLuint
* params
) {
4277 GPU_CLIENT_SINGLE_THREAD_CHECK();
4278 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
4279 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
4280 << static_cast<const void*>(params
) << ")");
4282 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4284 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
4288 QueryMap::iterator it
= current_queries_
.find(query
->target());
4289 if (it
!= current_queries_
.end()) {
4291 GL_INVALID_OPERATION
,
4292 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
4296 if (query
->NeverUsed()) {
4298 GL_INVALID_OPERATION
,
4299 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
4304 case GL_QUERY_RESULT_EXT
:
4305 if (!query
->CheckResultsAvailable(helper_
)) {
4306 helper_
->WaitForToken(query
->token());
4307 if (!query
->CheckResultsAvailable(helper_
)) {
4309 CHECK(query
->CheckResultsAvailable(helper_
));
4312 *params
= query
->GetResult();
4314 case GL_QUERY_RESULT_AVAILABLE_EXT
:
4315 *params
= query
->CheckResultsAvailable(helper_
);
4318 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
4321 GPU_CLIENT_LOG(" " << *params
);
4325 void GLES2Implementation::DrawArraysInstancedANGLE(
4326 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
4327 GPU_CLIENT_SINGLE_THREAD_CHECK();
4328 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
4329 << GLES2Util::GetStringDrawMode(mode
) << ", "
4330 << first
<< ", " << count
<< ", " << primcount
<< ")");
4332 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
4335 if (primcount
< 0) {
4336 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
4339 if (primcount
== 0) {
4342 bool simulated
= false;
4343 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4344 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
4348 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
4349 RestoreArrayBuffer(simulated
);
4353 void GLES2Implementation::DrawElementsInstancedANGLE(
4354 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
4355 GLsizei primcount
) {
4356 GPU_CLIENT_SINGLE_THREAD_CHECK();
4357 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
4358 << GLES2Util::GetStringDrawMode(mode
) << ", "
4360 << GLES2Util::GetStringIndexType(type
) << ", "
4361 << static_cast<const void*>(indices
) << ", "
4362 << primcount
<< ")");
4364 SetGLError(GL_INVALID_VALUE
,
4365 "glDrawElementsInstancedANGLE", "count less than 0.");
4371 if (primcount
< 0) {
4372 SetGLError(GL_INVALID_VALUE
,
4373 "glDrawElementsInstancedANGLE", "primcount < 0");
4376 if (primcount
== 0) {
4379 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
4380 !ValidateOffset("glDrawElementsInstancedANGLE",
4381 reinterpret_cast<GLintptr
>(indices
))) {
4385 bool simulated
= false;
4386 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
4387 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
4388 indices
, &offset
, &simulated
)) {
4391 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
4392 RestoreElementAndArrayBuffers(simulated
);
4396 void GLES2Implementation::GenMailboxCHROMIUM(
4398 GPU_CLIENT_SINGLE_THREAD_CHECK();
4399 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
4400 << static_cast<const void*>(mailbox
) << ")");
4401 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
4403 gpu::Mailbox result
= gpu::Mailbox::Generate();
4404 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
4407 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
4408 const GLbyte
* data
) {
4409 GPU_CLIENT_SINGLE_THREAD_CHECK();
4410 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
4411 << static_cast<const void*>(data
) << ")");
4412 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4413 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
4414 "mailbox that was not generated by "
4415 "GenMailboxCHROMIUM.";
4416 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
4420 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
4421 GLuint texture
, GLenum target
, const GLbyte
* data
) {
4422 GPU_CLIENT_SINGLE_THREAD_CHECK();
4423 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
4424 << static_cast<const void*>(data
) << ")");
4425 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4426 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
4427 "mailbox that was not generated by "
4428 "GenMailboxCHROMIUM.";
4429 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
4433 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
4434 const GLbyte
* data
) {
4435 GPU_CLIENT_SINGLE_THREAD_CHECK();
4436 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
4437 << static_cast<const void*>(data
) << ")");
4438 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4439 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
4440 "mailbox that was not generated by "
4441 "GenMailboxCHROMIUM.";
4442 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
4446 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
4447 GLenum target
, const GLbyte
* data
) {
4448 GPU_CLIENT_SINGLE_THREAD_CHECK();
4449 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
4450 << static_cast<const void*>(data
) << ")");
4451 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4452 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
4453 "mailbox that was not generated by "
4454 "GenMailboxCHROMIUM.";
4456 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
4457 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
4459 if (share_group_
->bind_generates_resource())
4460 helper_
->CommandBufferHelper::Flush();
4465 void GLES2Implementation::PushGroupMarkerEXT(
4466 GLsizei length
, const GLchar
* marker
) {
4467 GPU_CLIENT_SINGLE_THREAD_CHECK();
4468 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
4469 << length
<< ", " << marker
<< ")");
4475 (length
? std::string(marker
, length
) : std::string(marker
)));
4476 helper_
->PushGroupMarkerEXT(kResultBucketId
);
4477 helper_
->SetBucketSize(kResultBucketId
, 0);
4478 debug_marker_manager_
.PushGroup(
4479 length
? std::string(marker
, length
) : std::string(marker
));
4482 void GLES2Implementation::InsertEventMarkerEXT(
4483 GLsizei length
, const GLchar
* marker
) {
4484 GPU_CLIENT_SINGLE_THREAD_CHECK();
4485 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
4486 << length
<< ", " << marker
<< ")");
4492 (length
? std::string(marker
, length
) : std::string(marker
)));
4493 helper_
->InsertEventMarkerEXT(kResultBucketId
);
4494 helper_
->SetBucketSize(kResultBucketId
, 0);
4495 debug_marker_manager_
.SetMarker(
4496 length
? std::string(marker
, length
) : std::string(marker
));
4499 void GLES2Implementation::PopGroupMarkerEXT() {
4500 GPU_CLIENT_SINGLE_THREAD_CHECK();
4501 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
4502 helper_
->PopGroupMarkerEXT();
4503 debug_marker_manager_
.PopGroup();
4506 void GLES2Implementation::TraceBeginCHROMIUM(
4507 const char* category_name
, const char* trace_name
) {
4508 GPU_CLIENT_SINGLE_THREAD_CHECK();
4509 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
4510 << category_name
<< ", " << trace_name
<< ")");
4511 SetBucketAsCString(kResultBucketId
, category_name
);
4512 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
4513 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
4514 helper_
->SetBucketSize(kResultBucketId
, 0);
4515 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
4516 current_trace_stack_
++;
4519 void GLES2Implementation::TraceEndCHROMIUM() {
4520 GPU_CLIENT_SINGLE_THREAD_CHECK();
4521 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
4522 if (current_trace_stack_
== 0) {
4523 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
4524 "missing begin trace");
4527 helper_
->TraceEndCHROMIUM();
4528 current_trace_stack_
--;
4531 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
4532 GPU_CLIENT_SINGLE_THREAD_CHECK();
4533 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
4534 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
4536 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
4537 if (access
!= GL_READ_ONLY
) {
4538 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
4542 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
4543 if (access
!= GL_WRITE_ONLY
) {
4544 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
4550 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
4554 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
4558 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
4560 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
4563 if (buffer
->mapped()) {
4564 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
4567 // Here we wait for previous transfer operations to be finished.
4568 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
4569 // with this method of synchronization. Until this is fixed,
4570 // MapBufferCHROMIUM will not block even if the transfer is not ready
4572 if (buffer
->last_usage_token()) {
4573 helper_
->WaitForToken(buffer
->last_usage_token());
4574 buffer
->set_last_usage_token(0);
4576 buffer
->set_mapped(true);
4578 GPU_CLIENT_LOG(" returned " << buffer
->address());
4580 return buffer
->address();
4583 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
4584 GPU_CLIENT_SINGLE_THREAD_CHECK();
4586 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
4588 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
4589 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
4594 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
4596 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
4599 if (!buffer
->mapped()) {
4600 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
4603 buffer
->set_mapped(false);
4608 bool GLES2Implementation::EnsureAsyncUploadSync() {
4609 if (async_upload_sync_
)
4613 unsigned int shm_offset
;
4614 void* mem
= mapped_memory_
->Alloc(sizeof(AsyncUploadSync
),
4620 async_upload_sync_shm_id_
= shm_id
;
4621 async_upload_sync_shm_offset_
= shm_offset
;
4622 async_upload_sync_
= static_cast<AsyncUploadSync
*>(mem
);
4623 async_upload_sync_
->Reset();
4628 uint32
GLES2Implementation::NextAsyncUploadToken() {
4629 async_upload_token_
++;
4630 if (async_upload_token_
== 0)
4631 async_upload_token_
++;
4632 return async_upload_token_
;
4635 void GLES2Implementation::PollAsyncUploads() {
4636 if (!async_upload_sync_
)
4639 if (helper_
->IsContextLost()) {
4640 DetachedAsyncUploadMemoryList::iterator it
=
4641 detached_async_upload_memory_
.begin();
4642 while (it
!= detached_async_upload_memory_
.end()) {
4643 mapped_memory_
->Free(it
->first
);
4644 it
= detached_async_upload_memory_
.erase(it
);
4649 DetachedAsyncUploadMemoryList::iterator it
=
4650 detached_async_upload_memory_
.begin();
4651 while (it
!= detached_async_upload_memory_
.end()) {
4652 if (HasAsyncUploadTokenPassed(it
->second
)) {
4653 mapped_memory_
->Free(it
->first
);
4654 it
= detached_async_upload_memory_
.erase(it
);
4661 void GLES2Implementation::FreeAllAsyncUploadBuffers() {
4662 // Free all completed unmanaged async uploads buffers.
4665 // Synchronously free rest of the unmanaged async upload buffers.
4666 if (!detached_async_upload_memory_
.empty()) {
4667 WaitAllAsyncTexImage2DCHROMIUM();
4673 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
4674 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
4675 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
4676 const void* pixels
) {
4677 GPU_CLIENT_SINGLE_THREAD_CHECK();
4678 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
4679 << GLES2Util::GetStringTextureTarget(target
) << ", "
4681 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
4682 << width
<< ", " << height
<< ", " << border
<< ", "
4683 << GLES2Util::GetStringTextureFormat(format
) << ", "
4684 << GLES2Util::GetStringPixelType(type
) << ", "
4685 << static_cast<const void*>(pixels
) << ")");
4686 if (level
< 0 || height
< 0 || width
< 0) {
4687 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
4691 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
4695 uint32 unpadded_row_size
;
4696 uint32 padded_row_size
;
4697 if (!GLES2Util::ComputeImageDataSizes(
4698 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
4699 &unpadded_row_size
, &padded_row_size
)) {
4700 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
4704 // If there's no data/buffer just issue the AsyncTexImage2D
4705 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
4706 helper_
->AsyncTexImage2DCHROMIUM(
4707 target
, level
, internalformat
, width
, height
, format
, type
,
4712 if (!EnsureAsyncUploadSync()) {
4713 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
4717 // Otherwise, async uploads require a transfer buffer to be bound.
4718 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
4719 // the buffer before the transfer is finished. (Currently such
4720 // synchronization has to be handled manually.)
4721 GLuint offset
= ToGLuint(pixels
);
4722 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
4723 bound_pixel_unpack_transfer_buffer_id_
,
4724 "glAsyncTexImage2DCHROMIUM", offset
, size
);
4725 if (buffer
&& buffer
->shm_id() != -1) {
4726 uint32 async_token
= NextAsyncUploadToken();
4727 buffer
->set_last_async_upload_token(async_token
);
4728 helper_
->AsyncTexImage2DCHROMIUM(
4729 target
, level
, internalformat
, width
, height
, format
, type
,
4730 buffer
->shm_id(), buffer
->shm_offset() + offset
,
4732 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
4736 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
4737 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
4738 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
4739 GPU_CLIENT_SINGLE_THREAD_CHECK();
4740 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
4741 << GLES2Util::GetStringTextureTarget(target
) << ", "
4743 << xoffset
<< ", " << yoffset
<< ", "
4744 << width
<< ", " << height
<< ", "
4745 << GLES2Util::GetStringTextureFormat(format
) << ", "
4746 << GLES2Util::GetStringPixelType(type
) << ", "
4747 << static_cast<const void*>(pixels
) << ")");
4748 if (level
< 0 || height
< 0 || width
< 0) {
4750 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
4755 uint32 unpadded_row_size
;
4756 uint32 padded_row_size
;
4757 if (!GLES2Util::ComputeImageDataSizes(
4758 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
4759 &unpadded_row_size
, &padded_row_size
)) {
4761 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
4765 if (!EnsureAsyncUploadSync()) {
4766 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
4770 // Async uploads require a transfer buffer to be bound.
4771 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
4772 // the buffer before the transfer is finished. (Currently such
4773 // synchronization has to be handled manually.)
4774 GLuint offset
= ToGLuint(pixels
);
4775 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
4776 bound_pixel_unpack_transfer_buffer_id_
,
4777 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
4778 if (buffer
&& buffer
->shm_id() != -1) {
4779 uint32 async_token
= NextAsyncUploadToken();
4780 buffer
->set_last_async_upload_token(async_token
);
4781 helper_
->AsyncTexSubImage2DCHROMIUM(
4782 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
4783 buffer
->shm_id(), buffer
->shm_offset() + offset
,
4785 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
4789 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
4790 GPU_CLIENT_SINGLE_THREAD_CHECK();
4791 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
4792 << GLES2Util::GetStringTextureTarget(target
) << ")");
4793 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
4797 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() {
4798 GPU_CLIENT_SINGLE_THREAD_CHECK();
4799 GPU_CLIENT_LOG("[" << GetLogPrefix()
4800 << "] glWaitAllAsyncTexImage2DCHROMIUM()");
4801 helper_
->WaitAllAsyncTexImage2DCHROMIUM();
4805 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
4806 GPU_CLIENT_SINGLE_THREAD_CHECK();
4807 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
4808 helper_
->CommandBufferHelper::Flush();
4809 return gpu_control_
->InsertSyncPoint();
4812 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
4813 GPU_CLIENT_SINGLE_THREAD_CHECK();
4814 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
4815 DCHECK(capabilities_
.future_sync_points
);
4816 return gpu_control_
->InsertFutureSyncPoint();
4819 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
4820 GPU_CLIENT_SINGLE_THREAD_CHECK();
4821 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
4822 << sync_point
<< ")");
4823 DCHECK(capabilities_
.future_sync_points
);
4824 helper_
->CommandBufferHelper::Flush();
4825 gpu_control_
->RetireSyncPoint(sync_point
);
4830 bool ValidImageFormat(GLenum internalformat
) {
4831 switch (internalformat
) {
4841 bool ValidImageUsage(GLenum usage
) {
4843 case GL_MAP_CHROMIUM
:
4844 case GL_SCANOUT_CHROMIUM
:
4853 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
4856 GLenum internalformat
) {
4858 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
4863 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
4867 if (!ValidImageFormat(internalformat
)) {
4868 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
4873 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
4875 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
4881 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
4884 GLenum internalformat
) {
4885 GPU_CLIENT_SINGLE_THREAD_CHECK();
4886 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
4887 << ", " << height
<< ", "
4888 << GLES2Util::GetStringImageInternalFormat(internalformat
)
4891 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
4896 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
4897 // Flush the command stream to make sure all pending commands
4898 // that may refer to the image_id are executed on the service side.
4899 helper_
->CommandBufferHelper::Flush();
4900 gpu_control_
->DestroyImage(image_id
);
4903 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
4904 GPU_CLIENT_SINGLE_THREAD_CHECK();
4905 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
4906 << image_id
<< ")");
4907 DestroyImageCHROMIUMHelper(image_id
);
4911 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
4914 GLenum internalformat
,
4918 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
4923 SetGLError(GL_INVALID_VALUE
,
4924 "glCreateGpuMemoryBufferImageCHROMIUM",
4929 if (!ValidImageFormat(internalformat
)) {
4930 SetGLError(GL_INVALID_VALUE
,
4931 "glCreateGpuMemoryBufferImageCHROMIUM",
4936 if (!ValidImageUsage(usage
)) {
4937 SetGLError(GL_INVALID_VALUE
,
4938 "glCreateGpuMemoryBufferImageCHROMIUM",
4943 // Flush the command stream to ensure ordering in case the newly
4944 // returned image_id has recently been in use with a different buffer.
4945 helper_
->CommandBufferHelper::Flush();
4946 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
4947 width
, height
, internalformat
, usage
);
4949 SetGLError(GL_OUT_OF_MEMORY
,
4950 "glCreateGpuMemoryBufferImageCHROMIUM",
4957 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
4960 GLenum internalformat
,
4962 GPU_CLIENT_SINGLE_THREAD_CHECK();
4963 GPU_CLIENT_LOG("[" << GetLogPrefix()
4964 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
4965 << ", " << height
<< ", "
4966 << GLES2Util::GetStringImageInternalFormat(internalformat
)
4967 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
4968 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
4969 width
, height
, internalformat
, usage
);
4974 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
4976 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
4979 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
4980 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
4986 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
4988 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
4991 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
4992 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
4998 bool GLES2Implementation::GetSamplerParameterfvHelper(
4999 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5000 // TODO(zmo): Implement client side caching.
5004 bool GLES2Implementation::GetSamplerParameterivHelper(
5005 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5006 // TODO(zmo): Implement client side caching.
5010 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5011 const char* const* str
,
5012 const GLint
* length
,
5013 const char* func_name
) {
5014 DCHECK_LE(0, count
);
5015 // Compute the total size.
5016 base::CheckedNumeric
<size_t> total_size
= count
;
5018 total_size
*= sizeof(GLint
);
5019 if (!total_size
.IsValid()) {
5020 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5023 size_t header_size
= total_size
.ValueOrDefault(0);
5024 std::vector
<GLint
> header(count
+ 1);
5025 header
[0] = static_cast<GLint
>(count
);
5026 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5029 len
= (length
&& length
[ii
] >= 0)
5031 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5034 total_size
+= 1; // NULL at the end of each char array.
5035 if (!total_size
.IsValid()) {
5036 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5039 header
[ii
+ 1] = len
;
5041 // Pack data into a bucket on the service.
5042 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5044 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5046 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5047 base::CheckedNumeric
<size_t> checked_size
=
5048 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5050 checked_size
+= 1; // NULL in the end.
5052 if (!checked_size
.IsValid()) {
5053 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5056 size_t size
= checked_size
.ValueOrDefault(0);
5058 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5059 if (!buffer
.valid() || buffer
.size() == 0) {
5060 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5063 size_t copy_size
= buffer
.size();
5064 if (ii
> 0 && buffer
.size() == size
)
5067 memcpy(buffer
.address(), src
, copy_size
);
5068 if (copy_size
< buffer
.size()) {
5069 // Append NULL in the end.
5070 DCHECK(copy_size
+ 1 == buffer
.size());
5071 char* str
= reinterpret_cast<char*>(buffer
.address());
5074 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5075 buffer
.shm_id(), buffer
.offset());
5076 offset
+= buffer
.size();
5077 src
+= buffer
.size();
5078 size
-= buffer
.size();
5081 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5085 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5088 GPU_CLIENT_SINGLE_THREAD_CHECK();
5089 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5090 << ", " << index
<< ", " << binding
<< ")");
5091 share_group_
->program_info_manager()->UniformBlockBinding(
5092 this, program
, index
, binding
);
5093 helper_
->UniformBlockBinding(program
, index
, binding
);
5097 GLenum
GLES2Implementation::ClientWaitSync(
5098 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5099 GPU_CLIENT_SINGLE_THREAD_CHECK();
5100 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5101 << ", " << flags
<< ", " << timeout
<< ")");
5102 typedef cmds::ClientWaitSync::Result Result
;
5103 Result
* result
= GetResultAs
<Result
*>();
5105 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5106 return GL_WAIT_FAILED
;
5108 *result
= GL_WAIT_FAILED
;
5109 uint32_t v32_0
= 0, v32_1
= 0;
5110 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5111 helper_
->ClientWaitSync(
5112 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5113 GetResultShmId(), GetResultShmOffset());
5115 GPU_CLIENT_LOG("returned " << *result
);
5120 void GLES2Implementation::WaitSync(
5121 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5122 GPU_CLIENT_SINGLE_THREAD_CHECK();
5123 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5124 << flags
<< ", " << timeout
<< ")");
5125 uint32_t v32_0
= 0, v32_1
= 0;
5126 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5127 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5131 // Include the auto-generated part of this file. We split this because it means
5132 // we can easily edit the non-auto generated parts right here in this file
5133 // instead of having to edit some template or the code generator.
5134 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5136 } // namespace gles2