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"
10 #include <GLES2/gl2ext.h>
11 #include <GLES2/gl2extchromium.h>
12 #include <GLES3/gl3.h>
18 #include "base/compiler_specific.h"
19 #include "gpu/command_buffer/client/buffer_tracker.h"
20 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
21 #include "gpu/command_buffer/client/gpu_control.h"
22 #include "gpu/command_buffer/client/program_info_manager.h"
23 #include "gpu/command_buffer/client/query_tracker.h"
24 #include "gpu/command_buffer/client/transfer_buffer.h"
25 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
26 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
27 #include "gpu/command_buffer/common/id_allocator.h"
28 #include "gpu/command_buffer/common/trace_event.h"
30 #if defined(GPU_CLIENT_DEBUG)
31 #include "base/command_line.h"
32 #include "gpu/command_buffer/client/gpu_switches.h"
38 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
39 static GLuint
ToGLuint(const void* ptr
) {
40 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
43 #if !defined(_MSC_VER)
44 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
45 const unsigned int GLES2Implementation::kStartingOffset
;
48 GLES2Implementation::GLStaticState::GLStaticState() {
51 GLES2Implementation::GLStaticState::~GLStaticState() {
54 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
55 GLES2Implementation
* gles2_implementation
)
56 : gles2_implementation_(gles2_implementation
) {
57 CHECK_EQ(0, gles2_implementation_
->use_count_
);
58 ++gles2_implementation_
->use_count_
;
61 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
62 --gles2_implementation_
->use_count_
;
63 CHECK_EQ(0, gles2_implementation_
->use_count_
);
66 GLES2Implementation::GLES2Implementation(
67 GLES2CmdHelper
* helper
,
68 ShareGroup
* share_group
,
69 TransferBufferInterface
* transfer_buffer
,
70 bool bind_generates_resource
,
71 bool lose_context_when_out_of_memory
,
72 bool support_client_side_arrays
,
73 GpuControl
* gpu_control
)
75 transfer_buffer_(transfer_buffer
),
76 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
77 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
80 unpack_row_length_(0),
81 unpack_image_height_(0),
83 unpack_skip_pixels_(0),
84 unpack_skip_images_(0),
85 pack_reverse_row_order_(false),
86 active_texture_unit_(0),
87 bound_framebuffer_(0),
88 bound_read_framebuffer_(0),
89 bound_renderbuffer_(0),
90 bound_valuebuffer_(0),
92 bound_array_buffer_(0),
93 bound_copy_read_buffer_(0),
94 bound_copy_write_buffer_(0),
95 bound_pixel_pack_buffer_(0),
96 bound_pixel_unpack_buffer_(0),
97 bound_transform_feedback_buffer_(0),
98 bound_uniform_buffer_(0),
99 bound_pixel_pack_transfer_buffer_id_(0),
100 bound_pixel_unpack_transfer_buffer_id_(0),
101 async_upload_token_(0),
102 async_upload_sync_(NULL
),
103 async_upload_sync_shm_id_(0),
104 async_upload_sync_shm_offset_(0),
107 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
108 support_client_side_arrays_(support_client_side_arrays
),
110 error_message_callback_(NULL
),
111 current_trace_stack_(0),
112 gpu_control_(gpu_control
),
113 capabilities_(gpu_control
->GetCapabilities()),
114 aggressively_free_resources_(false),
115 weak_ptr_factory_(this) {
117 DCHECK(transfer_buffer
);
120 std::stringstream ss
;
121 ss
<< std::hex
<< this;
122 this_in_hex_
= ss
.str();
124 GPU_CLIENT_LOG_CODE_BLOCK({
125 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
126 switches::kEnableGPUClientLogging
);
130 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
131 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
133 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
136 bool GLES2Implementation::Initialize(
137 unsigned int starting_transfer_buffer_size
,
138 unsigned int min_transfer_buffer_size
,
139 unsigned int max_transfer_buffer_size
,
140 unsigned int mapped_memory_limit
) {
141 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
142 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
143 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
144 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
146 if (!transfer_buffer_
->Initialize(
147 starting_transfer_buffer_size
,
149 min_transfer_buffer_size
,
150 max_transfer_buffer_size
,
156 mapped_memory_
.reset(
157 new MappedMemoryManager(
159 base::Bind(&GLES2Implementation::PollAsyncUploads
,
160 // The mapped memory manager is owned by |this| here, and
161 // since its destroyed before before we destroy ourselves
162 // we don't need extra safety measures for this closure.
163 base::Unretained(this)),
164 mapped_memory_limit
));
166 unsigned chunk_size
= 2 * 1024 * 1024;
167 if (mapped_memory_limit
!= kNoLimit
) {
168 // Use smaller chunks if the client is very memory conscientious.
169 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
171 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
173 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
174 &static_state_
.shader_precisions
;
175 capabilities_
.VisitPrecisions([shader_precisions
](
176 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
177 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
178 cmds::GetShaderPrecisionFormat::Result cached_result
= {
179 true, result
->min_range
, result
->max_range
, result
->precision
};
180 shader_precisions
->insert(std::make_pair(key
, cached_result
));
183 util_
.set_num_compressed_texture_formats(
184 capabilities_
.num_compressed_texture_formats
);
185 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
187 texture_units_
.reset(
188 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
190 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
191 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
193 query_id_allocator_
.reset(new IdAllocator());
194 if (support_client_side_arrays_
) {
195 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
196 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
199 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
200 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
201 support_client_side_arrays_
));
203 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
204 // on Client & Service.
205 if (capabilities_
.bind_generates_resource_chromium
!=
206 (share_group_
->bind_generates_resource() ? 1 : 0)) {
207 SetGLError(GL_INVALID_OPERATION
,
209 "Service bind_generates_resource mismatch.");
216 GLES2Implementation::~GLES2Implementation() {
217 // Make sure the queries are finished otherwise we'll delete the
218 // shared memory (mapped_memory_) which will free the memory used
219 // by the queries. The GPU process when validating that memory is still
220 // shared will fail and abort (ie, it will stop running).
222 query_tracker_
.reset();
224 // GLES2Implementation::Initialize() could fail before allocating
225 // reserved_ids_, so we need delete them carefully.
226 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
227 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
230 // Release remaining BufferRange mem; This is when a MapBufferRange() is
231 // called but not the UnmapBuffer() pair.
232 ClearMappedBufferRangeMap();
234 // Release any per-context data in share group.
235 share_group_
->FreeContext(this);
237 buffer_tracker_
.reset();
239 FreeAllAsyncUploadBuffers();
241 if (async_upload_sync_
) {
242 mapped_memory_
->Free(async_upload_sync_
);
243 async_upload_sync_
= NULL
;
246 // Make sure the commands make it the service.
250 GLES2CmdHelper
* GLES2Implementation::helper() const {
254 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
255 return share_group_
->GetIdHandler(namespace_id
);
258 RangeIdHandlerInterface
* GLES2Implementation::GetRangeIdHandler(
259 int namespace_id
) const {
260 return share_group_
->GetRangeIdHandler(namespace_id
);
263 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
264 if (namespace_id
== id_namespaces::kQueries
)
265 return query_id_allocator_
.get();
270 void* GLES2Implementation::GetResultBuffer() {
271 return transfer_buffer_
->GetResultBuffer();
274 int32
GLES2Implementation::GetResultShmId() {
275 return transfer_buffer_
->GetShmId();
278 uint32
GLES2Implementation::GetResultShmOffset() {
279 return transfer_buffer_
->GetResultOffset();
282 void GLES2Implementation::FreeUnusedSharedMemory() {
283 mapped_memory_
->FreeUnused();
286 void GLES2Implementation::FreeEverything() {
287 FreeAllAsyncUploadBuffers();
289 query_tracker_
->Shrink();
290 FreeUnusedSharedMemory();
291 transfer_buffer_
->Free();
292 helper_
->FreeRingBuffer();
295 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
296 if (!helper_
->IsContextLost())
300 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
301 const base::Closure
& callback
) {
302 gpu_control_
->SignalSyncPoint(
304 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
305 weak_ptr_factory_
.GetWeakPtr(),
309 void GLES2Implementation::SignalQuery(uint32 query
,
310 const base::Closure
& callback
) {
311 // Flush previously entered commands to ensure ordering with any
312 // glBeginQueryEXT() calls that may have been put into the context.
313 ShallowFlushCHROMIUM();
314 gpu_control_
->SignalQuery(
316 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
317 weak_ptr_factory_
.GetWeakPtr(),
321 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
323 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
324 ShallowFlushCHROMIUM();
325 gpu_control_
->SetSurfaceVisible(visible
);
328 void GLES2Implementation::SetAggressivelyFreeResources(
329 bool aggressively_free_resources
) {
330 TRACE_EVENT1("gpu", "GLES2Implementation::SetAggressivelyFreeResources",
331 "aggressively_free_resources", aggressively_free_resources
);
332 aggressively_free_resources_
= aggressively_free_resources
;
334 if (aggressively_free_resources_
&& helper_
->HaveRingBuffer()) {
335 // Ensure that we clean up as much cache memory as possible and fully flush.
336 FlushDriverCachesCHROMIUM();
338 // Flush will delete transfer buffer resources if
339 // |aggressively_free_resources_| is true.
342 ShallowFlushCHROMIUM();
346 void GLES2Implementation::WaitForCmd() {
347 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
348 helper_
->CommandBufferHelper::Finish();
351 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
352 const char* extensions
=
353 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
357 int length
= strlen(ext
);
359 int n
= strcspn(extensions
, " ");
360 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
363 if ('\0' == extensions
[n
]) {
370 bool GLES2Implementation::IsExtensionAvailableHelper(
371 const char* extension
, ExtensionStatus
* status
) {
373 case kAvailableExtensionStatus
:
375 case kUnavailableExtensionStatus
:
378 bool available
= IsExtensionAvailable(extension
);
379 *status
= available
? kAvailableExtensionStatus
:
380 kUnavailableExtensionStatus
;
386 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
387 return IsExtensionAvailableHelper(
388 "GL_ANGLE_pack_reverse_row_order",
389 &angle_pack_reverse_row_order_status_
);
392 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
393 return IsExtensionAvailableHelper(
394 "GL_CHROMIUM_framebuffer_multisample",
395 &chromium_framebuffer_multisample_
);
398 const std::string
& GLES2Implementation::GetLogPrefix() const {
399 const std::string
& prefix(debug_marker_manager_
.GetMarker());
400 return prefix
.empty() ? this_in_hex_
: prefix
;
403 GLenum
GLES2Implementation::GetError() {
404 GPU_CLIENT_SINGLE_THREAD_CHECK();
405 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
406 GLenum err
= GetGLError();
407 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
411 GLenum
GLES2Implementation::GetClientSideGLError() {
412 if (error_bits_
== 0) {
416 GLenum error
= GL_NO_ERROR
;
417 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
418 if ((error_bits_
& mask
) != 0) {
419 error
= GLES2Util::GLErrorBitToGLError(mask
);
423 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
427 GLenum
GLES2Implementation::GetGLError() {
428 TRACE_EVENT0("gpu", "GLES2::GetGLError");
429 // Check the GL error first, then our wrapped error.
430 typedef cmds::GetError::Result Result
;
431 Result
* result
= GetResultAs
<Result
*>();
432 // If we couldn't allocate a result the context is lost.
436 *result
= GL_NO_ERROR
;
437 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
439 GLenum error
= *result
;
440 if (error
== GL_NO_ERROR
) {
441 error
= GetClientSideGLError();
443 // There was an error, clear the corresponding wrapped error.
444 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
449 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
450 void GLES2Implementation::FailGLError(GLenum error
) {
451 if (error
!= GL_NO_ERROR
) {
452 NOTREACHED() << "Error";
455 // NOTE: Calling GetGLError overwrites data in the result buffer.
456 void GLES2Implementation::CheckGLError() {
457 FailGLError(GetGLError());
459 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
461 void GLES2Implementation::SetGLError(
462 GLenum error
, const char* function_name
, const char* msg
) {
463 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
464 << GLES2Util::GetStringError(error
) << ": "
465 << function_name
<< ": " << msg
);
470 if (error_message_callback_
) {
471 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
472 function_name
+ ": " + (msg
? msg
: ""));
473 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
475 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
477 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
478 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
479 GL_UNKNOWN_CONTEXT_RESET_ARB
);
483 void GLES2Implementation::SetGLErrorInvalidEnum(
484 const char* function_name
, GLenum value
, const char* label
) {
485 SetGLError(GL_INVALID_ENUM
, function_name
,
486 (std::string(label
) + " was " +
487 GLES2Util::GetStringEnum(value
)).c_str());
490 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
491 std::vector
<int8
>* data
) {
492 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
494 const uint32 kStartSize
= 32 * 1024;
495 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
496 if (!buffer
.valid()) {
499 typedef cmd::GetBucketStart::Result Result
;
500 Result
* result
= GetResultAs
<Result
*>();
505 helper_
->GetBucketStart(
506 bucket_id
, GetResultShmId(), GetResultShmOffset(),
507 buffer
.size(), buffer
.shm_id(), buffer
.offset());
509 uint32 size
= *result
;
514 if (!buffer
.valid()) {
516 if (!buffer
.valid()) {
519 helper_
->GetBucketData(
520 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
523 uint32 size_to_copy
= std::min(size
, buffer
.size());
524 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
525 offset
+= size_to_copy
;
526 size
-= size_to_copy
;
529 // Free the bucket. This is not required but it does free up the memory.
530 // and we don't have to wait for the result so from the client's perspective
532 helper_
->SetBucketSize(bucket_id
, 0);
537 void GLES2Implementation::SetBucketContents(
538 uint32 bucket_id
, const void* data
, size_t size
) {
540 helper_
->SetBucketSize(bucket_id
, size
);
544 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
545 if (!buffer
.valid()) {
548 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
550 helper_
->SetBucketData(
551 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
552 offset
+= buffer
.size();
553 size
-= buffer
.size();
558 void GLES2Implementation::SetBucketAsCString(
559 uint32 bucket_id
, const char* str
) {
560 // NOTE: strings are passed NULL terminated. That means the empty
561 // string will have a size of 1 and no-string will have a size of 0
563 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
565 helper_
->SetBucketSize(bucket_id
, 0);
569 bool GLES2Implementation::GetBucketAsString(
570 uint32 bucket_id
, std::string
* str
) {
572 std::vector
<int8
> data
;
573 // NOTE: strings are passed NULL terminated. That means the empty
574 // string will have a size of 1 and no-string will have a size of 0
575 if (!GetBucketContents(bucket_id
, &data
)) {
581 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
585 void GLES2Implementation::SetBucketAsString(
586 uint32 bucket_id
, const std::string
& str
) {
587 // NOTE: strings are passed NULL terminated. That means the empty
588 // string will have a size of 1 and no-string will have a size of 0
589 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
592 void GLES2Implementation::Disable(GLenum cap
) {
593 GPU_CLIENT_SINGLE_THREAD_CHECK();
594 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
595 << GLES2Util::GetStringCapability(cap
) << ")");
596 bool changed
= false;
597 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
598 helper_
->Disable(cap
);
603 void GLES2Implementation::Enable(GLenum cap
) {
604 GPU_CLIENT_SINGLE_THREAD_CHECK();
605 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
606 << GLES2Util::GetStringCapability(cap
) << ")");
607 bool changed
= false;
608 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
609 helper_
->Enable(cap
);
614 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
615 GPU_CLIENT_SINGLE_THREAD_CHECK();
616 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
617 << GLES2Util::GetStringCapability(cap
) << ")");
619 if (!state_
.GetEnabled(cap
, &state
)) {
620 typedef cmds::IsEnabled::Result Result
;
621 Result
* result
= GetResultAs
<Result
*>();
626 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
628 state
= (*result
) != 0;
631 GPU_CLIENT_LOG("returned " << state
);
636 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
637 // TODO(zmo): For all the BINDING points, there is a possibility where
638 // resources are shared among multiple contexts, that the cached points
639 // are invalid. It is not a problem for now, but once we allow resource
640 // sharing in WebGL, we need to implement a mechanism to allow correct
641 // client side binding points tracking. crbug.com/465562.
645 case GL_ACTIVE_TEXTURE
:
646 *params
= active_texture_unit_
+ GL_TEXTURE0
;
648 case GL_ARRAY_BUFFER_BINDING
:
649 *params
= bound_array_buffer_
;
651 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
653 vertex_array_object_manager_
->bound_element_array_buffer();
655 case GL_FRAMEBUFFER_BINDING
:
656 *params
= bound_framebuffer_
;
658 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
659 *params
= capabilities_
.max_combined_texture_image_units
;
661 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
662 *params
= capabilities_
.max_cube_map_texture_size
;
664 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
665 *params
= capabilities_
.max_fragment_uniform_vectors
;
667 case GL_MAX_RENDERBUFFER_SIZE
:
668 *params
= capabilities_
.max_renderbuffer_size
;
670 case GL_MAX_TEXTURE_IMAGE_UNITS
:
671 *params
= capabilities_
.max_texture_image_units
;
673 case GL_MAX_TEXTURE_SIZE
:
674 *params
= capabilities_
.max_texture_size
;
676 case GL_MAX_VARYING_VECTORS
:
677 *params
= capabilities_
.max_varying_vectors
;
679 case GL_MAX_VERTEX_ATTRIBS
:
680 *params
= capabilities_
.max_vertex_attribs
;
682 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
683 *params
= capabilities_
.max_vertex_texture_image_units
;
685 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
686 *params
= capabilities_
.max_vertex_uniform_vectors
;
688 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
689 *params
= capabilities_
.num_compressed_texture_formats
;
691 case GL_NUM_SHADER_BINARY_FORMATS
:
692 *params
= capabilities_
.num_shader_binary_formats
;
694 case GL_RENDERBUFFER_BINDING
:
695 *params
= bound_renderbuffer_
;
697 case GL_TEXTURE_BINDING_2D
:
698 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
700 case GL_TEXTURE_BINDING_CUBE_MAP
:
701 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
704 // Non-standard parameters.
705 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
707 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
709 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
710 *params
= bound_pixel_pack_transfer_buffer_id_
;
712 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
713 *params
= bound_pixel_unpack_transfer_buffer_id_
;
715 case GL_READ_FRAMEBUFFER_BINDING
:
716 if (IsChromiumFramebufferMultisampleAvailable()) {
717 *params
= bound_read_framebuffer_
;
721 case GL_TIMESTAMP_EXT
:
722 // We convert all GPU timestamps to CPU time.
723 *params
= base::saturated_cast
<GLint
>(
724 (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
725 * base::Time::kNanosecondsPerMicrosecond
);
727 case GL_GPU_DISJOINT_EXT
:
728 *params
= static_cast<GLint
>(query_tracker_
->CheckAndResetDisjoint());
731 // Non-cached parameters.
732 case GL_ALIASED_LINE_WIDTH_RANGE
:
733 case GL_ALIASED_POINT_SIZE_RANGE
:
737 case GL_BLEND_DST_ALPHA
:
738 case GL_BLEND_DST_RGB
:
739 case GL_BLEND_EQUATION_ALPHA
:
740 case GL_BLEND_EQUATION_RGB
:
741 case GL_BLEND_SRC_ALPHA
:
742 case GL_BLEND_SRC_RGB
:
744 case GL_COLOR_CLEAR_VALUE
:
745 case GL_COLOR_WRITEMASK
:
746 case GL_COMPRESSED_TEXTURE_FORMATS
:
748 case GL_CULL_FACE_MODE
:
749 case GL_CURRENT_PROGRAM
:
751 case GL_DEPTH_CLEAR_VALUE
:
755 case GL_DEPTH_WRITEMASK
:
758 case GL_GENERATE_MIPMAP_HINT
:
760 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
761 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
763 case GL_MAX_VIEWPORT_DIMS
:
764 case GL_PACK_ALIGNMENT
:
765 case GL_POLYGON_OFFSET_FACTOR
:
766 case GL_POLYGON_OFFSET_FILL
:
767 case GL_POLYGON_OFFSET_UNITS
:
769 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
770 case GL_SAMPLE_BUFFERS
:
771 case GL_SAMPLE_COVERAGE
:
772 case GL_SAMPLE_COVERAGE_INVERT
:
773 case GL_SAMPLE_COVERAGE_VALUE
:
776 case GL_SCISSOR_TEST
:
777 case GL_SHADER_BINARY_FORMATS
:
778 case GL_SHADER_COMPILER
:
779 case GL_STENCIL_BACK_FAIL
:
780 case GL_STENCIL_BACK_FUNC
:
781 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
782 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
783 case GL_STENCIL_BACK_REF
:
784 case GL_STENCIL_BACK_VALUE_MASK
:
785 case GL_STENCIL_BACK_WRITEMASK
:
786 case GL_STENCIL_BITS
:
787 case GL_STENCIL_CLEAR_VALUE
:
788 case GL_STENCIL_FAIL
:
789 case GL_STENCIL_FUNC
:
790 case GL_STENCIL_PASS_DEPTH_FAIL
:
791 case GL_STENCIL_PASS_DEPTH_PASS
:
793 case GL_STENCIL_TEST
:
794 case GL_STENCIL_VALUE_MASK
:
795 case GL_STENCIL_WRITEMASK
:
796 case GL_SUBPIXEL_BITS
:
797 case GL_UNPACK_ALIGNMENT
:
804 if (capabilities_
.major_version
< 3) {
810 case GL_COPY_READ_BUFFER_BINDING
:
811 *params
= bound_copy_read_buffer_
;
813 case GL_COPY_WRITE_BUFFER_BINDING
:
814 *params
= bound_copy_write_buffer_
;
816 case GL_MAJOR_VERSION
:
817 *params
= capabilities_
.major_version
;
819 case GL_MAX_3D_TEXTURE_SIZE
:
820 *params
= capabilities_
.max_3d_texture_size
;
822 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
823 *params
= capabilities_
.max_array_texture_layers
;
825 case GL_MAX_COLOR_ATTACHMENTS
:
826 *params
= capabilities_
.max_color_attachments
;
828 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
829 *params
= static_cast<GLint
>(
830 capabilities_
.max_combined_fragment_uniform_components
);
832 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
833 *params
= capabilities_
.max_combined_uniform_blocks
;
835 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
836 *params
= static_cast<GLint
>(
837 capabilities_
.max_combined_vertex_uniform_components
);
839 case GL_MAX_DRAW_BUFFERS
:
840 *params
= capabilities_
.max_draw_buffers
;
842 case GL_MAX_ELEMENT_INDEX
:
843 *params
= static_cast<GLint
>(capabilities_
.max_element_index
);
845 case GL_MAX_ELEMENTS_INDICES
:
846 *params
= capabilities_
.max_elements_indices
;
848 case GL_MAX_ELEMENTS_VERTICES
:
849 *params
= capabilities_
.max_elements_vertices
;
851 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
852 *params
= capabilities_
.max_fragment_input_components
;
854 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
855 *params
= capabilities_
.max_fragment_uniform_blocks
;
857 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
858 *params
= capabilities_
.max_fragment_uniform_components
;
860 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
861 *params
= capabilities_
.max_program_texel_offset
;
864 *params
= capabilities_
.max_samples
;
866 case GL_MAX_SERVER_WAIT_TIMEOUT
:
867 *params
= static_cast<GLint
>(capabilities_
.max_server_wait_timeout
);
869 case GL_MAX_TEXTURE_LOD_BIAS
:
870 *params
= static_cast<GLint
>(capabilities_
.max_texture_lod_bias
);
872 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
873 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
875 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
876 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
878 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
879 *params
= capabilities_
.max_transform_feedback_separate_components
;
881 case GL_MAX_UNIFORM_BLOCK_SIZE
:
882 *params
= static_cast<GLint
>(capabilities_
.max_uniform_block_size
);
884 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
885 *params
= capabilities_
.max_uniform_buffer_bindings
;
887 case GL_MAX_VARYING_COMPONENTS
:
888 *params
= capabilities_
.max_varying_components
;
890 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
891 *params
= capabilities_
.max_vertex_output_components
;
893 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
894 *params
= capabilities_
.max_vertex_uniform_blocks
;
896 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
897 *params
= capabilities_
.max_vertex_uniform_components
;
899 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
900 *params
= capabilities_
.min_program_texel_offset
;
902 case GL_MINOR_VERSION
:
903 *params
= capabilities_
.minor_version
;
905 case GL_NUM_EXTENSIONS
:
906 *params
= capabilities_
.num_extensions
;
908 case GL_NUM_PROGRAM_BINARY_FORMATS
:
909 *params
= capabilities_
.num_program_binary_formats
;
911 case GL_PIXEL_PACK_BUFFER_BINDING
:
912 *params
= bound_pixel_pack_buffer_
;
914 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
915 *params
= bound_pixel_unpack_buffer_
;
917 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
918 *params
= bound_transform_feedback_buffer_
;
920 case GL_UNIFORM_BUFFER_BINDING
:
921 *params
= bound_uniform_buffer_
;
923 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
924 *params
= capabilities_
.uniform_buffer_offset_alignment
;
927 // Non-cached ES3 parameters.
928 case GL_DRAW_BUFFER0
:
929 case GL_DRAW_BUFFER1
:
930 case GL_DRAW_BUFFER2
:
931 case GL_DRAW_BUFFER3
:
932 case GL_DRAW_BUFFER4
:
933 case GL_DRAW_BUFFER5
:
934 case GL_DRAW_BUFFER6
:
935 case GL_DRAW_BUFFER7
:
936 case GL_DRAW_BUFFER8
:
937 case GL_DRAW_BUFFER9
:
938 case GL_DRAW_BUFFER10
:
939 case GL_DRAW_BUFFER11
:
940 case GL_DRAW_BUFFER12
:
941 case GL_DRAW_BUFFER13
:
942 case GL_DRAW_BUFFER14
:
943 case GL_DRAW_BUFFER15
:
944 case GL_DRAW_FRAMEBUFFER_BINDING
:
945 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
946 case GL_PACK_ROW_LENGTH
:
947 case GL_PACK_SKIP_PIXELS
:
948 case GL_PACK_SKIP_ROWS
:
949 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
950 case GL_PROGRAM_BINARY_FORMATS
:
951 case GL_RASTERIZER_DISCARD
:
953 case GL_READ_FRAMEBUFFER_BINDING
:
954 case GL_SAMPLER_BINDING
:
955 case GL_TEXTURE_BINDING_2D_ARRAY
:
956 case GL_TEXTURE_BINDING_3D
:
957 case GL_TRANSFORM_FEEDBACK_BINDING
:
958 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
959 case GL_TRANSFORM_FEEDBACK_PAUSED
:
960 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
961 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
962 case GL_UNIFORM_BUFFER_SIZE
:
963 case GL_UNIFORM_BUFFER_START
:
964 case GL_UNPACK_IMAGE_HEIGHT
:
965 case GL_UNPACK_ROW_LENGTH
:
966 case GL_UNPACK_SKIP_IMAGES
:
967 case GL_UNPACK_SKIP_PIXELS
:
968 case GL_UNPACK_SKIP_ROWS
:
969 case GL_VERTEX_ARRAY_BINDING
:
976 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
977 // TODO(gman): Make this handle pnames that return more than 1 value.
979 if (!GetHelper(pname
, &value
)) {
982 *params
= static_cast<GLboolean
>(value
);
986 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
987 // TODO(gman): Make this handle pnames that return more than 1 value.
989 case GL_MAX_TEXTURE_LOD_BIAS
:
990 *params
= capabilities_
.max_texture_lod_bias
;
996 if (!GetHelper(pname
, &value
)) {
999 *params
= static_cast<GLfloat
>(value
);
1003 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
1005 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
1006 *params
= capabilities_
.max_combined_fragment_uniform_components
;
1008 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
1009 *params
= capabilities_
.max_combined_vertex_uniform_components
;
1011 case GL_MAX_ELEMENT_INDEX
:
1012 *params
= capabilities_
.max_element_index
;
1014 case GL_MAX_SERVER_WAIT_TIMEOUT
:
1015 *params
= capabilities_
.max_server_wait_timeout
;
1017 case GL_MAX_UNIFORM_BLOCK_SIZE
:
1018 *params
= capabilities_
.max_uniform_block_size
;
1020 case GL_TIMESTAMP_EXT
:
1021 // We convert all GPU timestamps to CPU time.
1022 *params
= (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
1023 * base::Time::kNanosecondsPerMicrosecond
;
1029 if (!GetHelper(pname
, &value
)) {
1032 *params
= static_cast<GLint64
>(value
);
1036 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
1037 return GetHelper(pname
, params
);
1040 bool GLES2Implementation::GetIntegeri_vHelper(
1041 GLenum pname
, GLuint index
, GLint
* data
) {
1042 // TODO(zmo): Implement client side caching.
1046 bool GLES2Implementation::GetInteger64i_vHelper(
1047 GLenum pname
, GLuint index
, GLint64
* data
) {
1048 // TODO(zmo): Implement client side caching.
1052 bool GLES2Implementation::GetInternalformativHelper(
1053 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
1055 // TODO(zmo): Implement the client side caching.
1059 bool GLES2Implementation::GetSyncivHelper(
1060 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
1064 case GL_OBJECT_TYPE
:
1065 value
= GL_SYNC_FENCE
;
1067 case GL_SYNC_CONDITION
:
1068 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1086 bool GLES2Implementation::GetQueryObjectValueHelper(
1087 const char* function_name
, GLuint id
, GLenum pname
, GLuint64
* params
) {
1088 GPU_CLIENT_SINGLE_THREAD_CHECK();
1089 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper("
1091 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
1092 << static_cast<const void*>(params
) << ")");
1094 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
1096 SetGLError(GL_INVALID_OPERATION
,
1097 function_name
, "unknown query id");
1101 if (query
->Active()) {
1103 GL_INVALID_OPERATION
,
1105 "query active. Did you to call glEndQueryEXT?");
1109 if (query
->NeverUsed()) {
1111 GL_INVALID_OPERATION
,
1112 function_name
, "Never used. Did you call glBeginQueryEXT?");
1116 bool valid_value
= false;
1118 case GL_QUERY_RESULT_EXT
:
1119 if (!query
->CheckResultsAvailable(helper_
)) {
1120 helper_
->WaitForToken(query
->token());
1121 if (!query
->CheckResultsAvailable(helper_
)) {
1123 CHECK(query
->CheckResultsAvailable(helper_
));
1126 *params
= query
->GetResult();
1129 case GL_QUERY_RESULT_AVAILABLE_EXT
:
1130 *params
= query
->CheckResultsAvailable(helper_
);
1134 SetGLErrorInvalidEnum(function_name
, pname
, "pname");
1137 GPU_CLIENT_LOG(" " << *params
);
1142 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1143 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1144 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1145 Result
* result
= GetResultAs
<Result
*>();
1150 helper_
->GetMaxValueInBufferCHROMIUM(
1151 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1156 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1157 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1158 GPU_CLIENT_SINGLE_THREAD_CHECK();
1159 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1160 << buffer_id
<< ", " << count
<< ", "
1161 << GLES2Util::GetStringGetMaxIndexType(type
)
1162 << ", " << offset
<< ")");
1163 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1164 buffer_id
, count
, type
, offset
);
1165 GPU_CLIENT_LOG("returned " << result
);
1170 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1172 RestoreArrayBuffer(restore
);
1173 // Restore the element array binding.
1174 // We only need to restore it if it wasn't a client side array.
1175 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1176 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1181 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1183 // Restore the user's current binding.
1184 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_
);
1188 void GLES2Implementation::DrawElements(
1189 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1190 GPU_CLIENT_SINGLE_THREAD_CHECK();
1191 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1192 << GLES2Util::GetStringDrawMode(mode
) << ", "
1194 << GLES2Util::GetStringIndexType(type
) << ", "
1195 << static_cast<const void*>(indices
) << ")");
1196 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1199 void GLES2Implementation::DrawRangeElements(
1200 GLenum mode
, GLuint start
, GLuint end
,
1201 GLsizei count
, GLenum type
, const void* indices
) {
1202 GPU_CLIENT_SINGLE_THREAD_CHECK();
1203 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1204 << GLES2Util::GetStringDrawMode(mode
) << ", "
1205 << start
<< ", " << end
<< ", " << count
<< ", "
1206 << GLES2Util::GetStringIndexType(type
) << ", "
1207 << static_cast<const void*>(indices
) << ")");
1209 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1212 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1215 void GLES2Implementation::DrawElementsImpl(
1216 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1217 const char* func_name
) {
1219 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1222 bool simulated
= false;
1223 GLuint offset
= ToGLuint(indices
);
1225 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1226 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1229 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1230 func_name
, this, helper_
, count
, type
, 0, indices
,
1231 &offset
, &simulated
)) {
1235 helper_
->DrawElements(mode
, count
, type
, offset
);
1236 RestoreElementAndArrayBuffers(simulated
);
1240 void GLES2Implementation::Flush() {
1241 GPU_CLIENT_SINGLE_THREAD_CHECK();
1242 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1243 // Insert the cmd to call glFlush
1248 void GLES2Implementation::ShallowFlushCHROMIUM() {
1249 GPU_CLIENT_SINGLE_THREAD_CHECK();
1250 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1254 void GLES2Implementation::FlushHelper() {
1255 // Flush our command buffer
1256 // (tell the service to execute up to the flush cmd.)
1257 helper_
->CommandBufferHelper::Flush();
1259 if (aggressively_free_resources_
)
1263 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1264 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1265 // Flush command buffer at the GPU channel level. May be implemented as
1267 helper_
->CommandBufferHelper::OrderingBarrier();
1270 void GLES2Implementation::Finish() {
1271 GPU_CLIENT_SINGLE_THREAD_CHECK();
1275 void GLES2Implementation::ShallowFinishCHROMIUM() {
1276 GPU_CLIENT_SINGLE_THREAD_CHECK();
1277 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1278 // Flush our command buffer (tell the service to execute up to the flush cmd
1279 // and don't return until it completes).
1280 helper_
->CommandBufferHelper::Finish();
1282 if (aggressively_free_resources_
)
1286 void GLES2Implementation::FinishHelper() {
1287 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1288 TRACE_EVENT0("gpu", "GLES2::Finish");
1289 // Insert the cmd to call glFinish
1291 // Finish our command buffer
1292 // (tell the service to execute up to the Finish cmd and wait for it to
1294 helper_
->CommandBufferHelper::Finish();
1296 if (aggressively_free_resources_
)
1300 void GLES2Implementation::SwapBuffers() {
1301 GPU_CLIENT_SINGLE_THREAD_CHECK();
1302 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1303 // TODO(piman): Strictly speaking we'd want to insert the token after the
1304 // swap, but the state update with the updated token might not have happened
1305 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1306 // with the GPU process more than needed. So instead, make it happen before.
1307 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1308 // semantics if the client doesn't use the callback mechanism, and by chance
1309 // the scheduler yields between the InsertToken and the SwapBuffers.
1310 swap_buffers_tokens_
.push(helper_
->InsertToken());
1311 helper_
->SwapBuffers();
1312 helper_
->CommandBufferHelper::Flush();
1313 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1314 // compensate for TODO above.
1315 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1316 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1317 swap_buffers_tokens_
.pop();
1321 void GLES2Implementation::SwapInterval(int interval
) {
1322 GPU_CLIENT_SINGLE_THREAD_CHECK();
1323 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1324 << interval
<< ")");
1325 helper_
->SwapInterval(interval
);
1328 void GLES2Implementation::BindAttribLocation(
1329 GLuint program
, GLuint index
, const char* name
) {
1330 GPU_CLIENT_SINGLE_THREAD_CHECK();
1331 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1332 << program
<< ", " << index
<< ", " << name
<< ")");
1333 SetBucketAsString(kResultBucketId
, name
);
1334 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1335 helper_
->SetBucketSize(kResultBucketId
, 0);
1339 void GLES2Implementation::BindUniformLocationCHROMIUM(
1340 GLuint program
, GLint location
, const char* name
) {
1341 GPU_CLIENT_SINGLE_THREAD_CHECK();
1342 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1343 << program
<< ", " << location
<< ", " << name
<< ")");
1344 SetBucketAsString(kResultBucketId
, name
);
1345 helper_
->BindUniformLocationCHROMIUMBucket(
1346 program
, location
, kResultBucketId
);
1347 helper_
->SetBucketSize(kResultBucketId
, 0);
1351 void GLES2Implementation::GetVertexAttribPointerv(
1352 GLuint index
, GLenum pname
, void** ptr
) {
1353 GPU_CLIENT_SINGLE_THREAD_CHECK();
1354 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1355 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1356 << static_cast<void*>(ptr
) << ")");
1357 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1358 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1359 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1360 typedef cmds::GetVertexAttribPointerv::Result Result
;
1361 Result
* result
= GetResultAs
<Result
*>();
1365 result
->SetNumResults(0);
1366 helper_
->GetVertexAttribPointerv(
1367 index
, pname
, GetResultShmId(), GetResultShmOffset());
1369 result
->CopyResult(ptr
);
1370 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1372 GPU_CLIENT_LOG_CODE_BLOCK({
1373 for (int32 i
= 0; i
< num_results
; ++i
) {
1374 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1380 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1381 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1382 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1385 "glDeleteProgram", "id not created by this context.");
1388 if (program
== current_program_
) {
1389 current_program_
= 0;
1394 void GLES2Implementation::DeleteProgramStub(
1395 GLsizei n
, const GLuint
* programs
) {
1397 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1398 helper_
->DeleteProgram(programs
[0]);
1401 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1402 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1403 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1406 "glDeleteShader", "id not created by this context.");
1412 void GLES2Implementation::DeleteShaderStub(
1413 GLsizei n
, const GLuint
* shaders
) {
1415 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1416 helper_
->DeleteShader(shaders
[0]);
1419 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1420 GLuint sync_uint
= ToGLuint(sync
);
1421 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1422 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1425 "glDeleteSync", "id not created by this context.");
1429 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1431 helper_
->DeleteSync(syncs
[0]);
1434 GLint
GLES2Implementation::GetAttribLocationHelper(
1435 GLuint program
, const char* name
) {
1436 typedef cmds::GetAttribLocation::Result Result
;
1437 Result
* result
= GetResultAs
<Result
*>();
1442 SetBucketAsCString(kResultBucketId
, name
);
1443 helper_
->GetAttribLocation(
1444 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1446 helper_
->SetBucketSize(kResultBucketId
, 0);
1450 GLint
GLES2Implementation::GetAttribLocation(
1451 GLuint program
, const char* name
) {
1452 GPU_CLIENT_SINGLE_THREAD_CHECK();
1453 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1454 << ", " << name
<< ")");
1455 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1456 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1457 this, program
, name
);
1458 GPU_CLIENT_LOG("returned " << loc
);
1463 GLint
GLES2Implementation::GetUniformLocationHelper(
1464 GLuint program
, const char* name
) {
1465 typedef cmds::GetUniformLocation::Result Result
;
1466 Result
* result
= GetResultAs
<Result
*>();
1471 SetBucketAsCString(kResultBucketId
, name
);
1472 helper_
->GetUniformLocation(program
, kResultBucketId
,
1473 GetResultShmId(), GetResultShmOffset());
1475 helper_
->SetBucketSize(kResultBucketId
, 0);
1479 GLint
GLES2Implementation::GetUniformLocation(
1480 GLuint program
, const char* name
) {
1481 GPU_CLIENT_SINGLE_THREAD_CHECK();
1482 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1483 << ", " << name
<< ")");
1484 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1485 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1486 this, program
, name
);
1487 GPU_CLIENT_LOG("returned " << loc
);
1492 bool GLES2Implementation::GetUniformIndicesHelper(
1493 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1494 typedef cmds::GetUniformIndices::Result Result
;
1495 Result
* result
= GetResultAs
<Result
*>();
1499 result
->SetNumResults(0);
1500 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1503 helper_
->GetUniformIndices(program
, kResultBucketId
,
1504 GetResultShmId(), GetResultShmOffset());
1506 if (result
->GetNumResults() != count
) {
1509 result
->CopyResult(indices
);
1513 void GLES2Implementation::GetUniformIndices(
1514 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1515 GPU_CLIENT_SINGLE_THREAD_CHECK();
1516 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1517 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1518 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1520 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1526 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1527 this, program
, count
, names
, indices
);
1529 GPU_CLIENT_LOG_CODE_BLOCK({
1530 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1531 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1538 bool GLES2Implementation::GetProgramivHelper(
1539 GLuint program
, GLenum pname
, GLint
* params
) {
1540 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1541 this, program
, pname
, params
);
1542 GPU_CLIENT_LOG_CODE_BLOCK({
1544 GPU_CLIENT_LOG(" 0: " << *params
);
1550 GLint
GLES2Implementation::GetFragDataLocationHelper(
1551 GLuint program
, const char* name
) {
1552 typedef cmds::GetFragDataLocation::Result Result
;
1553 Result
* result
= GetResultAs
<Result
*>();
1558 SetBucketAsCString(kResultBucketId
, name
);
1559 helper_
->GetFragDataLocation(
1560 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1562 helper_
->SetBucketSize(kResultBucketId
, 0);
1566 GLint
GLES2Implementation::GetFragDataLocation(
1567 GLuint program
, const char* name
) {
1568 GPU_CLIENT_SINGLE_THREAD_CHECK();
1569 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1570 << program
<< ", " << name
<< ")");
1571 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1572 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1573 this, program
, name
);
1574 GPU_CLIENT_LOG("returned " << loc
);
1579 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1580 GLuint program
, const char* name
) {
1581 typedef cmds::GetUniformBlockIndex::Result Result
;
1582 Result
* result
= GetResultAs
<Result
*>();
1584 return GL_INVALID_INDEX
;
1586 *result
= GL_INVALID_INDEX
;
1587 SetBucketAsCString(kResultBucketId
, name
);
1588 helper_
->GetUniformBlockIndex(
1589 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1591 helper_
->SetBucketSize(kResultBucketId
, 0);
1595 GLuint
GLES2Implementation::GetUniformBlockIndex(
1596 GLuint program
, const char* name
) {
1597 GPU_CLIENT_SINGLE_THREAD_CHECK();
1598 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1599 << program
<< ", " << name
<< ")");
1600 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1601 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1602 this, program
, name
);
1603 GPU_CLIENT_LOG("returned " << index
);
1608 void GLES2Implementation::LinkProgram(GLuint program
) {
1609 GPU_CLIENT_SINGLE_THREAD_CHECK();
1610 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1611 helper_
->LinkProgram(program
);
1612 share_group_
->program_info_manager()->CreateInfo(program
);
1616 void GLES2Implementation::ShaderBinary(
1617 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1619 GPU_CLIENT_SINGLE_THREAD_CHECK();
1620 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1621 << static_cast<const void*>(shaders
) << ", "
1622 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1623 << static_cast<const void*>(binary
) << ", "
1626 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1630 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1633 // TODO(gman): ShaderBinary should use buckets.
1634 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1635 ScopedTransferBufferArray
<GLint
> buffer(
1636 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1637 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1638 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1641 void* shader_ids
= buffer
.elements();
1642 void* shader_data
= buffer
.elements() + shader_id_size
;
1643 memcpy(shader_ids
, shaders
, shader_id_size
);
1644 memcpy(shader_data
, binary
, length
);
1645 helper_
->ShaderBinary(
1651 buffer
.offset() + shader_id_size
,
1656 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1657 GPU_CLIENT_SINGLE_THREAD_CHECK();
1658 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1659 << GLES2Util::GetStringPixelStore(pname
) << ", "
1662 case GL_PACK_ALIGNMENT
:
1663 pack_alignment_
= param
;
1665 case GL_UNPACK_ALIGNMENT
:
1666 unpack_alignment_
= param
;
1668 case GL_UNPACK_ROW_LENGTH_EXT
:
1669 unpack_row_length_
= param
;
1671 case GL_UNPACK_IMAGE_HEIGHT
:
1672 unpack_image_height_
= param
;
1674 case GL_UNPACK_SKIP_ROWS_EXT
:
1675 unpack_skip_rows_
= param
;
1677 case GL_UNPACK_SKIP_PIXELS_EXT
:
1678 unpack_skip_pixels_
= param
;
1680 case GL_UNPACK_SKIP_IMAGES
:
1681 unpack_skip_images_
= param
;
1683 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1684 pack_reverse_row_order_
=
1685 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1690 helper_
->PixelStorei(pname
, param
);
1694 void GLES2Implementation::VertexAttribIPointer(
1695 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1696 GPU_CLIENT_SINGLE_THREAD_CHECK();
1697 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1700 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1703 // Record the info on the client side.
1704 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1712 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1713 "client side arrays are not allowed in vertex array objects.");
1716 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1717 // Only report NON client side buffers to the service.
1718 if (!ValidateOffset("glVertexAttribIPointer",
1719 reinterpret_cast<GLintptr
>(ptr
))) {
1722 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1727 void GLES2Implementation::VertexAttribPointer(
1728 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1730 GPU_CLIENT_SINGLE_THREAD_CHECK();
1731 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1734 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1735 << GLES2Util::GetStringBool(normalized
) << ", "
1738 // Record the info on the client side.
1739 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1747 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1748 "client side arrays are not allowed in vertex array objects.");
1751 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1752 // Only report NON client side buffers to the service.
1753 if (!ValidateOffset("glVertexAttribPointer",
1754 reinterpret_cast<GLintptr
>(ptr
))) {
1757 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1763 void GLES2Implementation::VertexAttribDivisorANGLE(
1764 GLuint index
, GLuint divisor
) {
1765 GPU_CLIENT_SINGLE_THREAD_CHECK();
1766 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1768 << divisor
<< ") ");
1769 // Record the info on the client side.
1770 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1771 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1775 void GLES2Implementation::BufferDataHelper(
1776 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1777 if (!ValidateSize("glBufferData", size
))
1780 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1781 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1782 // bogus MSan report during a readback later. This is because MSan doesn't
1783 // understand shared memory and would assume we were reading back the same
1784 // unintialized data.
1785 if (data
) __msan_check_mem_is_initialized(data
, size
);
1789 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1794 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1796 RemoveTransferBuffer(buffer
);
1798 // Create new buffer.
1799 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1801 if (buffer
->address() && data
)
1802 memcpy(buffer
->address(), data
, size
);
1806 RemoveMappedBufferRangeByTarget(target
);
1808 // If there is no data just send BufferData
1809 if (size
== 0 || !data
) {
1810 helper_
->BufferData(target
, size
, 0, 0, usage
);
1814 // See if we can send all at once.
1815 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1816 if (!buffer
.valid()) {
1820 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1821 memcpy(buffer
.address(), data
, size
);
1822 helper_
->BufferData(
1831 // Make the buffer with BufferData then send via BufferSubData
1832 helper_
->BufferData(target
, size
, 0, 0, usage
);
1833 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1837 void GLES2Implementation::BufferData(
1838 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1839 GPU_CLIENT_SINGLE_THREAD_CHECK();
1840 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1841 << GLES2Util::GetStringBufferTarget(target
) << ", "
1843 << static_cast<const void*>(data
) << ", "
1844 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1845 BufferDataHelper(target
, size
, data
, usage
);
1849 void GLES2Implementation::BufferSubDataHelper(
1850 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1855 if (!ValidateSize("glBufferSubData", size
) ||
1856 !ValidateOffset("glBufferSubData", offset
)) {
1861 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1865 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1867 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1872 int32 buffer_size
= buffer
->size();
1873 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1874 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1878 if (buffer
->address() && data
)
1879 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1883 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1884 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1887 void GLES2Implementation::BufferSubDataHelperImpl(
1888 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1889 ScopedTransferBufferPtr
* buffer
) {
1893 const int8
* source
= static_cast<const int8
*>(data
);
1895 if (!buffer
->valid() || buffer
->size() == 0) {
1896 buffer
->Reset(size
);
1897 if (!buffer
->valid()) {
1901 memcpy(buffer
->address(), source
, buffer
->size());
1902 helper_
->BufferSubData(
1903 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1904 offset
+= buffer
->size();
1905 source
+= buffer
->size();
1906 size
-= buffer
->size();
1911 void GLES2Implementation::BufferSubData(
1912 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1913 GPU_CLIENT_SINGLE_THREAD_CHECK();
1914 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1915 << GLES2Util::GetStringBufferTarget(target
) << ", "
1916 << offset
<< ", " << size
<< ", "
1917 << static_cast<const void*>(data
) << ")");
1918 BufferSubDataHelper(target
, offset
, size
, data
);
1922 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1923 int32 token
= buffer
->last_usage_token();
1924 uint32 async_token
= buffer
->last_async_upload_token();
1927 if (HasAsyncUploadTokenPassed(async_token
)) {
1928 buffer_tracker_
->Free(buffer
);
1930 detached_async_upload_memory_
.push_back(
1931 std::make_pair(buffer
->address(), async_token
));
1932 buffer_tracker_
->Unmanage(buffer
);
1935 if (helper_
->HasTokenPassed(token
))
1936 buffer_tracker_
->Free(buffer
);
1938 buffer_tracker_
->FreePendingToken(buffer
, token
);
1940 buffer_tracker_
->Free(buffer
);
1943 buffer_tracker_
->RemoveBuffer(buffer
->id());
1946 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1948 const char* function_name
,
1949 GLuint
* buffer_id
) {
1953 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1954 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1956 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1957 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1964 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1969 BufferTracker::Buffer
*
1970 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1972 const char* function_name
,
1973 GLuint offset
, GLsizei size
) {
1975 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1977 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1980 if (buffer
->mapped()) {
1981 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1984 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1985 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1991 void GLES2Implementation::CompressedTexImage2D(
1992 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1993 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1994 GPU_CLIENT_SINGLE_THREAD_CHECK();
1995 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1996 << GLES2Util::GetStringTextureTarget(target
) << ", "
1998 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1999 << width
<< ", " << height
<< ", " << border
<< ", "
2000 << image_size
<< ", "
2001 << static_cast<const void*>(data
) << ")");
2002 if (width
< 0 || height
< 0 || level
< 0) {
2003 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
2007 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
2010 if (height
== 0 || width
== 0) {
2013 // If there's a pixel unpack buffer bound use it when issuing
2014 // CompressedTexImage2D.
2015 if (bound_pixel_unpack_transfer_buffer_id_
) {
2016 GLuint offset
= ToGLuint(data
);
2017 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2018 bound_pixel_unpack_transfer_buffer_id_
,
2019 "glCompressedTexImage2D", offset
, image_size
);
2020 if (buffer
&& buffer
->shm_id() != -1) {
2021 helper_
->CompressedTexImage2D(
2022 target
, level
, internalformat
, width
, height
, image_size
,
2023 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2024 buffer
->set_last_usage_token(helper_
->InsertToken());
2028 SetBucketContents(kResultBucketId
, data
, image_size
);
2029 helper_
->CompressedTexImage2DBucket(
2030 target
, level
, internalformat
, width
, height
, kResultBucketId
);
2031 // Free the bucket. This is not required but it does free up the memory.
2032 // and we don't have to wait for the result so from the client's perspective
2034 helper_
->SetBucketSize(kResultBucketId
, 0);
2038 void GLES2Implementation::CompressedTexSubImage2D(
2039 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2040 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
2041 GPU_CLIENT_SINGLE_THREAD_CHECK();
2042 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
2043 << GLES2Util::GetStringTextureTarget(target
) << ", "
2045 << xoffset
<< ", " << yoffset
<< ", "
2046 << width
<< ", " << height
<< ", "
2047 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2048 << image_size
<< ", "
2049 << static_cast<const void*>(data
) << ")");
2050 if (width
< 0 || height
< 0 || level
< 0) {
2051 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
2054 // If there's a pixel unpack buffer bound use it when issuing
2055 // CompressedTexSubImage2D.
2056 if (bound_pixel_unpack_transfer_buffer_id_
) {
2057 GLuint offset
= ToGLuint(data
);
2058 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2059 bound_pixel_unpack_transfer_buffer_id_
,
2060 "glCompressedTexSubImage2D", offset
, image_size
);
2061 if (buffer
&& buffer
->shm_id() != -1) {
2062 helper_
->CompressedTexSubImage2D(
2063 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
2064 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2065 buffer
->set_last_usage_token(helper_
->InsertToken());
2070 SetBucketContents(kResultBucketId
, data
, image_size
);
2071 helper_
->CompressedTexSubImage2DBucket(
2072 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
2073 // Free the bucket. This is not required but it does free up the memory.
2074 // and we don't have to wait for the result so from the client's perspective
2076 helper_
->SetBucketSize(kResultBucketId
, 0);
2080 void GLES2Implementation::CompressedTexImage3D(
2081 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2082 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
2084 GPU_CLIENT_SINGLE_THREAD_CHECK();
2085 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
2086 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
2087 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2088 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2089 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
2090 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2091 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
2095 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
2098 if (height
== 0 || width
== 0 || depth
== 0) {
2101 // If there's a pixel unpack buffer bound use it when issuing
2102 // CompressedTexImage3D.
2103 if (bound_pixel_unpack_transfer_buffer_id_
) {
2104 GLuint offset
= ToGLuint(data
);
2105 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2106 bound_pixel_unpack_transfer_buffer_id_
,
2107 "glCompressedTexImage3D", offset
, image_size
);
2108 if (buffer
&& buffer
->shm_id() != -1) {
2109 helper_
->CompressedTexImage3D(
2110 target
, level
, internalformat
, width
, height
, depth
, image_size
,
2111 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2112 buffer
->set_last_usage_token(helper_
->InsertToken());
2116 SetBucketContents(kResultBucketId
, data
, image_size
);
2117 helper_
->CompressedTexImage3DBucket(
2118 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
2119 // Free the bucket. This is not required but it does free up the memory.
2120 // and we don't have to wait for the result so from the client's perspective
2122 helper_
->SetBucketSize(kResultBucketId
, 0);
2126 void GLES2Implementation::CompressedTexSubImage3D(
2127 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2128 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
2129 GLsizei image_size
, const void* data
) {
2130 GPU_CLIENT_SINGLE_THREAD_CHECK();
2131 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
2132 << GLES2Util::GetStringTextureTarget(target
) << ", "
2134 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2135 << width
<< ", " << height
<< ", " << depth
<< ", "
2136 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2137 << image_size
<< ", "
2138 << static_cast<const void*>(data
) << ")");
2139 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2140 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "dimension < 0");
2143 // If there's a pixel unpack buffer bound use it when issuing
2144 // CompressedTexSubImage3D.
2145 if (bound_pixel_unpack_transfer_buffer_id_
) {
2146 GLuint offset
= ToGLuint(data
);
2147 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2148 bound_pixel_unpack_transfer_buffer_id_
,
2149 "glCompressedTexSubImage3D", offset
, image_size
);
2150 if (buffer
&& buffer
->shm_id() != -1) {
2151 helper_
->CompressedTexSubImage3D(
2152 target
, level
, xoffset
, yoffset
, zoffset
,
2153 width
, height
, depth
, format
, image_size
,
2154 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2155 buffer
->set_last_usage_token(helper_
->InsertToken());
2160 SetBucketContents(kResultBucketId
, data
, image_size
);
2161 helper_
->CompressedTexSubImage3DBucket(
2162 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
2164 // Free the bucket. This is not required but it does free up the memory.
2165 // and we don't have to wait for the result so from the client's perspective
2167 helper_
->SetBucketSize(kResultBucketId
, 0);
2173 void CopyRectToBuffer(
2176 uint32 unpadded_row_size
,
2177 uint32 pixels_padded_row_size
,
2179 uint32 buffer_padded_row_size
) {
2180 const int8
* source
= static_cast<const int8
*>(pixels
);
2181 int8
* dest
= static_cast<int8
*>(buffer
);
2182 if (pixels_padded_row_size
!= buffer_padded_row_size
) {
2183 // the last row is copied unpadded at the end
2184 for (; height
> 1; --height
) {
2185 memcpy(dest
, source
, buffer_padded_row_size
);
2186 dest
+= buffer_padded_row_size
;
2187 source
+= pixels_padded_row_size
;
2189 memcpy(dest
, source
, unpadded_row_size
);
2191 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2192 memcpy(dest
, source
, size
);
2196 } // anonymous namespace
2198 void GLES2Implementation::TexImage2D(
2199 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2200 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2201 const void* pixels
) {
2202 GPU_CLIENT_SINGLE_THREAD_CHECK();
2203 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2204 << GLES2Util::GetStringTextureTarget(target
) << ", "
2206 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2207 << width
<< ", " << height
<< ", " << border
<< ", "
2208 << GLES2Util::GetStringTextureFormat(format
) << ", "
2209 << GLES2Util::GetStringPixelType(type
) << ", "
2210 << static_cast<const void*>(pixels
) << ")");
2211 if (level
< 0 || height
< 0 || width
< 0) {
2212 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2216 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2220 uint32 unpadded_row_size
;
2221 uint32 padded_row_size
;
2222 if (!GLES2Util::ComputeImageDataSizes(
2223 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2224 &unpadded_row_size
, &padded_row_size
)) {
2225 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2229 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2230 if (bound_pixel_unpack_transfer_buffer_id_
) {
2231 GLuint offset
= ToGLuint(pixels
);
2232 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2233 bound_pixel_unpack_transfer_buffer_id_
,
2234 "glTexImage2D", offset
, size
);
2235 if (buffer
&& buffer
->shm_id() != -1) {
2236 helper_
->TexImage2D(
2237 target
, level
, internalformat
, width
, height
, format
, type
,
2238 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2239 buffer
->set_last_usage_token(helper_
->InsertToken());
2245 // If there's no data just issue TexImage2D
2247 helper_
->TexImage2D(
2248 target
, level
, internalformat
, width
, height
, format
, type
,
2254 // compute the advance bytes per row for the src pixels
2255 uint32 src_padded_row_size
;
2256 if (unpack_row_length_
> 0) {
2257 if (!GLES2Util::ComputeImagePaddedRowSize(
2258 unpack_row_length_
, format
, type
, unpack_alignment_
,
2259 &src_padded_row_size
)) {
2261 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2265 src_padded_row_size
= padded_row_size
;
2268 // advance pixels pointer past the skip rows and skip pixels
2269 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2270 unpack_skip_rows_
* src_padded_row_size
;
2271 if (unpack_skip_pixels_
) {
2272 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2273 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2274 unpack_skip_pixels_
* group_size
;
2277 // Check if we can send it all at once.
2279 uint32_t shm_offset
= 0;
2280 void* buffer_pointer
= nullptr;
2282 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2283 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2285 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2286 shm_id
= transfer_alloc
.shm_id();
2287 shm_offset
= transfer_alloc
.offset();
2288 buffer_pointer
= transfer_alloc
.address();
2290 mapped_alloc
.Reset(size
);
2291 if (mapped_alloc
.valid()) {
2292 transfer_alloc
.Discard();
2294 mapped_alloc
.SetFlushAfterRelease(true);
2295 shm_id
= mapped_alloc
.shm_id();
2296 shm_offset
= mapped_alloc
.offset();
2297 buffer_pointer
= mapped_alloc
.address();
2301 if (buffer_pointer
) {
2303 pixels
, height
, unpadded_row_size
, src_padded_row_size
,
2304 buffer_pointer
, padded_row_size
);
2305 helper_
->TexImage2D(
2306 target
, level
, internalformat
, width
, height
, format
, type
,
2307 shm_id
, shm_offset
);
2312 // No, so send it using TexSubImage2D.
2313 helper_
->TexImage2D(
2314 target
, level
, internalformat
, width
, height
, format
, type
,
2317 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2318 pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
, padded_row_size
);
2322 void GLES2Implementation::TexImage3D(
2323 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2324 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2325 const void* pixels
) {
2326 GPU_CLIENT_SINGLE_THREAD_CHECK();
2327 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2328 << GLES2Util::GetStringTextureTarget(target
) << ", "
2330 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2331 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2332 << GLES2Util::GetStringTextureFormat(format
) << ", "
2333 << GLES2Util::GetStringPixelType(type
) << ", "
2334 << static_cast<const void*>(pixels
) << ")");
2335 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2336 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2340 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2344 uint32 unpadded_row_size
;
2345 uint32 padded_row_size
;
2346 if (!GLES2Util::ComputeImageDataSizes(
2347 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2348 &unpadded_row_size
, &padded_row_size
)) {
2349 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2353 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2354 if (bound_pixel_unpack_transfer_buffer_id_
) {
2355 GLuint offset
= ToGLuint(pixels
);
2356 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2357 bound_pixel_unpack_transfer_buffer_id_
,
2358 "glTexImage3D", offset
, size
);
2359 if (buffer
&& buffer
->shm_id() != -1) {
2360 helper_
->TexImage3D(
2361 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2362 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2363 buffer
->set_last_usage_token(helper_
->InsertToken());
2369 // If there's no data just issue TexImage3D
2371 helper_
->TexImage3D(
2372 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2378 // compute the advance bytes per row for the src pixels
2379 uint32 src_padded_row_size
;
2380 if (unpack_row_length_
> 0) {
2381 if (!GLES2Util::ComputeImagePaddedRowSize(
2382 unpack_row_length_
, format
, type
, unpack_alignment_
,
2383 &src_padded_row_size
)) {
2385 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2389 src_padded_row_size
= padded_row_size
;
2391 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2393 // advance pixels pointer past the skip images/rows/pixels
2394 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2395 unpack_skip_images_
* src_padded_row_size
* src_height
+
2396 unpack_skip_rows_
* src_padded_row_size
;
2397 if (unpack_skip_pixels_
) {
2398 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2399 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2400 unpack_skip_pixels_
* group_size
;
2403 // Check if we can send it all at once.
2405 uint32_t shm_offset
= 0;
2406 void* buffer_pointer
= nullptr;
2408 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2409 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2411 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2412 shm_id
= transfer_alloc
.shm_id();
2413 shm_offset
= transfer_alloc
.offset();
2414 buffer_pointer
= transfer_alloc
.address();
2416 mapped_alloc
.Reset(size
);
2417 if (mapped_alloc
.valid()) {
2418 transfer_alloc
.Discard();
2420 mapped_alloc
.SetFlushAfterRelease(true);
2421 shm_id
= mapped_alloc
.shm_id();
2422 shm_offset
= mapped_alloc
.offset();
2423 buffer_pointer
= mapped_alloc
.address();
2427 if (buffer_pointer
) {
2428 for (GLsizei z
= 0; z
< depth
; ++z
) {
2429 // Only the last row of the last image is unpadded.
2430 uint32 src_unpadded_row_size
=
2431 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2433 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
,
2434 buffer_pointer
, padded_row_size
);
2435 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2436 src_padded_row_size
* src_height
;
2437 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2438 padded_row_size
* height
;
2440 helper_
->TexImage3D(
2441 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2442 shm_id
, shm_offset
);
2447 // No, so send it using TexSubImage3D.
2448 helper_
->TexImage3D(
2449 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2452 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2453 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
,
2458 void GLES2Implementation::TexSubImage2D(
2459 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2460 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2461 GPU_CLIENT_SINGLE_THREAD_CHECK();
2462 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2463 << GLES2Util::GetStringTextureTarget(target
) << ", "
2465 << xoffset
<< ", " << yoffset
<< ", "
2466 << width
<< ", " << height
<< ", "
2467 << GLES2Util::GetStringTextureFormat(format
) << ", "
2468 << GLES2Util::GetStringPixelType(type
) << ", "
2469 << static_cast<const void*>(pixels
) << ")");
2471 if (level
< 0 || height
< 0 || width
< 0) {
2472 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2475 if (height
== 0 || width
== 0) {
2480 uint32 unpadded_row_size
;
2481 uint32 padded_row_size
;
2482 if (!GLES2Util::ComputeImageDataSizes(
2483 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2484 &unpadded_row_size
, &padded_row_size
)) {
2485 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2489 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2490 if (bound_pixel_unpack_transfer_buffer_id_
) {
2491 GLuint offset
= ToGLuint(pixels
);
2492 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2493 bound_pixel_unpack_transfer_buffer_id_
,
2494 "glTexSubImage2D", offset
, temp_size
);
2495 if (buffer
&& buffer
->shm_id() != -1) {
2496 helper_
->TexSubImage2D(
2497 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2498 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2499 buffer
->set_last_usage_token(helper_
->InsertToken());
2505 // compute the advance bytes per row for the src pixels
2506 uint32 src_padded_row_size
;
2507 if (unpack_row_length_
> 0) {
2508 if (!GLES2Util::ComputeImagePaddedRowSize(
2509 unpack_row_length_
, format
, type
, unpack_alignment_
,
2510 &src_padded_row_size
)) {
2512 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2516 src_padded_row_size
= padded_row_size
;
2519 // advance pixels pointer past the skip rows and skip pixels
2520 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2521 unpack_skip_rows_
* src_padded_row_size
;
2522 if (unpack_skip_pixels_
) {
2523 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2524 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2525 unpack_skip_pixels_
* group_size
;
2528 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2530 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2531 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2536 void GLES2Implementation::TexSubImage3D(
2537 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2538 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2539 const void* pixels
) {
2540 GPU_CLIENT_SINGLE_THREAD_CHECK();
2541 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2542 << GLES2Util::GetStringTextureTarget(target
) << ", "
2544 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2545 << width
<< ", " << height
<< ", " << depth
<< ", "
2546 << GLES2Util::GetStringTextureFormat(format
) << ", "
2547 << GLES2Util::GetStringPixelType(type
) << ", "
2548 << static_cast<const void*>(pixels
) << ")");
2550 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2551 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2554 if (height
== 0 || width
== 0 || depth
== 0) {
2559 uint32 unpadded_row_size
;
2560 uint32 padded_row_size
;
2561 if (!GLES2Util::ComputeImageDataSizes(
2562 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2563 &unpadded_row_size
, &padded_row_size
)) {
2564 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2568 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2569 if (bound_pixel_unpack_transfer_buffer_id_
) {
2570 GLuint offset
= ToGLuint(pixels
);
2571 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2572 bound_pixel_unpack_transfer_buffer_id_
,
2573 "glTexSubImage3D", offset
, temp_size
);
2574 if (buffer
&& buffer
->shm_id() != -1) {
2575 helper_
->TexSubImage3D(
2576 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2577 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2578 buffer
->set_last_usage_token(helper_
->InsertToken());
2584 // compute the advance bytes per row for the src pixels
2585 uint32 src_padded_row_size
;
2586 if (unpack_row_length_
> 0) {
2587 if (!GLES2Util::ComputeImagePaddedRowSize(
2588 unpack_row_length_
, format
, type
, unpack_alignment_
,
2589 &src_padded_row_size
)) {
2591 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2595 src_padded_row_size
= padded_row_size
;
2597 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2599 // advance pixels pointer past the skip images/rows/pixels
2600 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2601 unpack_skip_images_
* src_padded_row_size
* src_height
+
2602 unpack_skip_rows_
* src_padded_row_size
;
2603 if (unpack_skip_pixels_
) {
2604 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2605 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2606 unpack_skip_pixels_
* group_size
;
2609 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2611 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2612 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2613 &buffer
, padded_row_size
);
2617 static GLint
ComputeNumRowsThatFitInBuffer(
2618 uint32 padded_row_size
, uint32 unpadded_row_size
,
2619 unsigned int size
, GLsizei remaining_rows
) {
2620 DCHECK_GE(unpadded_row_size
, 0u);
2621 if (padded_row_size
== 0) {
2624 GLint num_rows
= size
/ padded_row_size
;
2625 if (num_rows
+ 1 == remaining_rows
&&
2626 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2632 void GLES2Implementation::TexSubImage2DImpl(
2633 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2634 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2635 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2636 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2638 DCHECK_GE(level
, 0);
2639 DCHECK_GT(height
, 0);
2640 DCHECK_GT(width
, 0);
2642 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2643 // Transfer by rows.
2645 unsigned int desired_size
=
2646 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2647 if (!buffer
->valid() || buffer
->size() == 0) {
2648 buffer
->Reset(desired_size
);
2649 if (!buffer
->valid()) {
2654 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2655 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2656 num_rows
= std::min(num_rows
, height
);
2658 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2659 buffer
->address(), buffer_padded_row_size
);
2660 helper_
->TexSubImage2D(
2661 target
, level
, xoffset
, yoffset
, width
, num_rows
, format
, type
,
2662 buffer
->shm_id(), buffer
->offset(), internal
);
2664 yoffset
+= num_rows
;
2665 source
+= num_rows
* pixels_padded_row_size
;
2670 void GLES2Implementation::TexSubImage3DImpl(
2671 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2672 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2673 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2674 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2675 uint32 buffer_padded_row_size
) {
2677 DCHECK_GE(level
, 0);
2678 DCHECK_GT(height
, 0);
2679 DCHECK_GT(width
, 0);
2680 DCHECK_GT(depth
, 0);
2681 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2682 GLsizei total_rows
= height
* depth
;
2683 GLint row_index
= 0, depth_index
= 0;
2684 while (total_rows
) {
2685 // Each time, we either copy one or more images, or copy one or more rows
2686 // within a single image, depending on the buffer size limit.
2688 unsigned int desired_size
;
2689 if (row_index
> 0) {
2690 // We are in the middle of an image. Send the remaining of the image.
2691 max_rows
= height
- row_index
;
2692 if (total_rows
<= height
) {
2693 // Last image, so last row is unpadded.
2694 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2697 desired_size
= buffer_padded_row_size
* max_rows
;
2700 // Send all the remaining data if possible.
2701 max_rows
= total_rows
;
2703 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2705 if (!buffer
->valid() || buffer
->size() == 0) {
2706 buffer
->Reset(desired_size
);
2707 if (!buffer
->valid()) {
2711 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2712 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2713 num_rows
= std::min(num_rows
, max_rows
);
2714 GLint num_images
= num_rows
/ height
;
2715 GLsizei my_height
, my_depth
;
2716 if (num_images
> 0) {
2717 num_rows
= num_images
* height
;
2719 my_depth
= num_images
;
2721 my_height
= num_rows
;
2725 if (num_images
> 0) {
2726 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2728 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2729 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2730 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2731 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2732 uint32 my_unpadded_row_size
;
2733 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2734 my_unpadded_row_size
= unpadded_row_size
;
2736 my_unpadded_row_size
= pixels_padded_row_size
;
2738 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2739 pixels_padded_row_size
, buffer_pointer
+ ii
* image_size_dst
,
2740 buffer_padded_row_size
);
2743 uint32 my_unpadded_row_size
;
2744 if (total_rows
== num_rows
)
2745 my_unpadded_row_size
= unpadded_row_size
;
2747 my_unpadded_row_size
= pixels_padded_row_size
;
2749 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2750 buffer
->address(), buffer_padded_row_size
);
2752 helper_
->TexSubImage3D(
2753 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2754 width
, my_height
, my_depth
,
2755 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2758 total_rows
-= num_rows
;
2759 if (total_rows
> 0) {
2760 GLint num_image_paddings
;
2761 if (num_images
> 0) {
2762 DCHECK_EQ(row_index
, 0);
2763 depth_index
+= num_images
;
2764 num_image_paddings
= num_images
;
2766 row_index
= (row_index
+ my_height
) % height
;
2767 num_image_paddings
= 0;
2768 if (my_height
> 0 && row_index
== 0) {
2770 num_image_paddings
++;
2773 source
+= num_rows
* pixels_padded_row_size
;
2774 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2775 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2776 pixels_padded_row_size
;
2782 bool GLES2Implementation::GetActiveAttribHelper(
2783 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2784 GLenum
* type
, char* name
) {
2785 // Clear the bucket so if the command fails nothing will be in it.
2786 helper_
->SetBucketSize(kResultBucketId
, 0);
2787 typedef cmds::GetActiveAttrib::Result Result
;
2788 Result
* result
= GetResultAs
<Result
*>();
2792 // Set as failed so if the command fails we'll recover.
2793 result
->success
= false;
2794 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2795 GetResultShmId(), GetResultShmOffset());
2797 if (result
->success
) {
2799 *size
= result
->size
;
2802 *type
= result
->type
;
2804 if (length
|| name
) {
2805 std::vector
<int8
> str
;
2806 GetBucketContents(kResultBucketId
, &str
);
2807 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2808 std::max(static_cast<size_t>(0),
2813 if (name
&& bufsize
> 0) {
2814 memcpy(name
, &str
[0], max_size
);
2815 name
[max_size
] = '\0';
2819 return result
->success
!= 0;
2822 void GLES2Implementation::GetActiveAttrib(
2823 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2824 GLenum
* type
, char* name
) {
2825 GPU_CLIENT_SINGLE_THREAD_CHECK();
2826 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2827 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2828 << static_cast<const void*>(length
) << ", "
2829 << static_cast<const void*>(size
) << ", "
2830 << static_cast<const void*>(type
) << ", "
2831 << static_cast<const void*>(name
) << ", ");
2833 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2836 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2837 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2838 this, program
, index
, bufsize
, length
, size
, type
, name
);
2841 GPU_CLIENT_LOG(" size: " << *size
);
2844 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2847 GPU_CLIENT_LOG(" name: " << name
);
2853 bool GLES2Implementation::GetActiveUniformHelper(
2854 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2855 GLenum
* type
, char* name
) {
2856 // Clear the bucket so if the command fails nothing will be in it.
2857 helper_
->SetBucketSize(kResultBucketId
, 0);
2858 typedef cmds::GetActiveUniform::Result Result
;
2859 Result
* result
= GetResultAs
<Result
*>();
2863 // Set as failed so if the command fails we'll recover.
2864 result
->success
= false;
2865 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2866 GetResultShmId(), GetResultShmOffset());
2868 if (result
->success
) {
2870 *size
= result
->size
;
2873 *type
= result
->type
;
2875 if (length
|| name
) {
2876 std::vector
<int8
> str
;
2877 GetBucketContents(kResultBucketId
, &str
);
2878 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2879 std::max(static_cast<size_t>(0),
2884 if (name
&& bufsize
> 0) {
2885 memcpy(name
, &str
[0], max_size
);
2886 name
[max_size
] = '\0';
2890 return result
->success
!= 0;
2893 void GLES2Implementation::GetActiveUniform(
2894 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2895 GLenum
* type
, char* name
) {
2896 GPU_CLIENT_SINGLE_THREAD_CHECK();
2897 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2898 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2899 << static_cast<const void*>(length
) << ", "
2900 << static_cast<const void*>(size
) << ", "
2901 << static_cast<const void*>(type
) << ", "
2902 << static_cast<const void*>(name
) << ", ");
2904 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2907 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2908 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2909 this, program
, index
, bufsize
, length
, size
, type
, name
);
2912 GPU_CLIENT_LOG(" size: " << *size
);
2915 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2918 GPU_CLIENT_LOG(" name: " << name
);
2924 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2925 GLuint program
, GLuint index
, GLsizei bufsize
,
2926 GLsizei
* length
, char* name
) {
2927 DCHECK_LE(0, bufsize
);
2928 // Clear the bucket so if the command fails nothing will be in it.
2929 helper_
->SetBucketSize(kResultBucketId
, 0);
2930 typedef cmds::GetActiveUniformBlockName::Result Result
;
2931 Result
* result
= GetResultAs
<Result
*>();
2935 // Set as failed so if the command fails we'll recover.
2937 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2938 GetResultShmId(), GetResultShmOffset());
2945 } else if (length
|| name
) {
2946 std::vector
<int8
> str
;
2947 GetBucketContents(kResultBucketId
, &str
);
2948 DCHECK_GT(str
.size(), 0u);
2950 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2955 memcpy(name
, &str
[0], max_size
);
2956 name
[max_size
] = '\0';
2960 return *result
!= 0;
2963 void GLES2Implementation::GetActiveUniformBlockName(
2964 GLuint program
, GLuint index
, GLsizei bufsize
,
2965 GLsizei
* length
, char* name
) {
2966 GPU_CLIENT_SINGLE_THREAD_CHECK();
2967 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2968 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2969 << static_cast<const void*>(length
) << ", "
2970 << static_cast<const void*>(name
) << ")");
2972 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2975 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2977 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2978 this, program
, index
, bufsize
, length
, name
);
2981 GPU_CLIENT_LOG(" name: " << name
);
2987 bool GLES2Implementation::GetActiveUniformBlockivHelper(
2988 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2989 typedef cmds::GetActiveUniformBlockiv::Result Result
;
2990 Result
* result
= GetResultAs
<Result
*>();
2994 result
->SetNumResults(0);
2995 helper_
->GetActiveUniformBlockiv(
2996 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
2998 if (result
->GetNumResults() > 0) {
3000 result
->CopyResult(params
);
3002 GPU_CLIENT_LOG_CODE_BLOCK({
3003 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3004 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3012 void GLES2Implementation::GetActiveUniformBlockiv(
3013 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
3014 GPU_CLIENT_SINGLE_THREAD_CHECK();
3015 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
3016 << program
<< ", " << index
<< ", "
3017 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
3018 << static_cast<const void*>(params
) << ")");
3019 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
3021 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
3022 this, program
, index
, pname
, params
);
3025 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
3026 // be more than one value returned in params.
3027 GPU_CLIENT_LOG(" params: " << params
[0]);
3033 bool GLES2Implementation::GetActiveUniformsivHelper(
3034 GLuint program
, GLsizei count
, const GLuint
* indices
,
3035 GLenum pname
, GLint
* params
) {
3036 typedef cmds::GetActiveUniformsiv::Result Result
;
3037 Result
* result
= GetResultAs
<Result
*>();
3041 result
->SetNumResults(0);
3042 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
3043 bytes
*= sizeof(GLuint
);
3044 if (!bytes
.IsValid()) {
3045 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
3048 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
3049 helper_
->GetActiveUniformsiv(
3050 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
3052 bool success
= result
->GetNumResults() == count
;
3055 result
->CopyResult(params
);
3057 GPU_CLIENT_LOG_CODE_BLOCK({
3058 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3059 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3063 helper_
->SetBucketSize(kResultBucketId
, 0);
3067 void GLES2Implementation::GetActiveUniformsiv(
3068 GLuint program
, GLsizei count
, const GLuint
* indices
,
3069 GLenum pname
, GLint
* params
) {
3070 GPU_CLIENT_SINGLE_THREAD_CHECK();
3071 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
3072 << program
<< ", " << count
<< ", "
3073 << static_cast<const void*>(indices
) << ", "
3074 << GLES2Util::GetStringUniformParameter(pname
) << ", "
3075 << static_cast<const void*>(params
) << ")");
3076 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
3078 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
3081 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
3082 this, program
, count
, indices
, pname
, params
);
3085 GPU_CLIENT_LOG_CODE_BLOCK({
3086 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
3087 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
3095 void GLES2Implementation::GetAttachedShaders(
3096 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
3097 GPU_CLIENT_SINGLE_THREAD_CHECK();
3098 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
3099 << program
<< ", " << maxcount
<< ", "
3100 << static_cast<const void*>(count
) << ", "
3101 << static_cast<const void*>(shaders
) << ", ");
3103 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
3106 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
3107 typedef cmds::GetAttachedShaders::Result Result
;
3108 uint32 size
= Result::ComputeSize(maxcount
);
3109 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
3113 result
->SetNumResults(0);
3114 helper_
->GetAttachedShaders(
3116 transfer_buffer_
->GetShmId(),
3117 transfer_buffer_
->GetOffset(result
),
3119 int32 token
= helper_
->InsertToken();
3122 *count
= result
->GetNumResults();
3124 result
->CopyResult(shaders
);
3125 GPU_CLIENT_LOG_CODE_BLOCK({
3126 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3127 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3130 transfer_buffer_
->FreePendingToken(result
, token
);
3134 void GLES2Implementation::GetShaderPrecisionFormat(
3135 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
3136 GPU_CLIENT_SINGLE_THREAD_CHECK();
3137 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
3138 << GLES2Util::GetStringShaderType(shadertype
) << ", "
3139 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
3140 << static_cast<const void*>(range
) << ", "
3141 << static_cast<const void*>(precision
) << ", ");
3142 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
3143 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3144 Result
* result
= GetResultAs
<Result
*>();
3149 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
3150 GLStaticState::ShaderPrecisionMap::iterator i
=
3151 static_state_
.shader_precisions
.find(key
);
3152 if (i
!= static_state_
.shader_precisions
.end()) {
3153 *result
= i
->second
;
3155 result
->success
= false;
3156 helper_
->GetShaderPrecisionFormat(
3157 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
3159 if (result
->success
)
3160 static_state_
.shader_precisions
[key
] = *result
;
3163 if (result
->success
) {
3165 range
[0] = result
->min_range
;
3166 range
[1] = result
->max_range
;
3167 GPU_CLIENT_LOG(" min_range: " << range
[0]);
3168 GPU_CLIENT_LOG(" min_range: " << range
[1]);
3171 precision
[0] = result
->precision
;
3172 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
3178 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
3179 const char* result
= NULL
;
3180 // Clears the bucket so if the command fails nothing will be in it.
3181 helper_
->SetBucketSize(kResultBucketId
, 0);
3182 helper_
->GetString(name
, kResultBucketId
);
3184 if (GetBucketAsString(kResultBucketId
, &str
)) {
3185 // Adds extensions implemented on client side only.
3188 str
+= std::string(str
.empty() ? "" : " ") +
3189 "GL_EXT_unpack_subimage "
3190 "GL_CHROMIUM_map_sub";
3191 if (capabilities_
.image
)
3192 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
3193 if (capabilities_
.future_sync_points
)
3194 str
+= " GL_CHROMIUM_future_sync_point";
3200 // Because of WebGL the extensions can change. We have to cache each unique
3201 // result since we don't know when the client will stop referring to a
3202 // previous one it queries.
3203 GLStringMap::iterator it
= gl_strings_
.find(name
);
3204 if (it
== gl_strings_
.end()) {
3205 std::set
<std::string
> strings
;
3206 std::pair
<GLStringMap::iterator
, bool> insert_result
=
3207 gl_strings_
.insert(std::make_pair(name
, strings
));
3208 DCHECK(insert_result
.second
);
3209 it
= insert_result
.first
;
3211 std::set
<std::string
>& string_set
= it
->second
;
3212 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
3213 if (sit
!= string_set
.end()) {
3214 result
= sit
->c_str();
3216 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3217 string_set
.insert(str
);
3218 DCHECK(insert_result
.second
);
3219 result
= insert_result
.first
->c_str();
3222 return reinterpret_cast<const GLubyte
*>(result
);
3225 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3226 GPU_CLIENT_SINGLE_THREAD_CHECK();
3227 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3228 << GLES2Util::GetStringStringType(name
) << ")");
3229 TRACE_EVENT0("gpu", "GLES2::GetString");
3230 const GLubyte
* result
= GetStringHelper(name
);
3231 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3236 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3237 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3238 GLenum
* type
, char* name
) {
3239 // Clear the bucket so if the command fails nothing will be in it.
3240 helper_
->SetBucketSize(kResultBucketId
, 0);
3241 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3242 Result
* result
= GetResultAs
<Result
*>();
3246 // Set as failed so if the command fails we'll recover.
3247 result
->success
= false;
3248 helper_
->GetTransformFeedbackVarying(
3249 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3251 if (result
->success
) {
3253 *size
= result
->size
;
3256 *type
= result
->type
;
3258 if (length
|| name
) {
3259 std::vector
<int8
> str
;
3260 GetBucketContents(kResultBucketId
, &str
);
3261 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3270 memcpy(name
, &str
[0], max_size
);
3271 name
[max_size
] = '\0';
3272 } else if (bufsize
> 0) {
3278 return result
->success
!= 0;
3281 void GLES2Implementation::GetTransformFeedbackVarying(
3282 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3283 GLenum
* type
, char* name
) {
3284 GPU_CLIENT_SINGLE_THREAD_CHECK();
3285 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3286 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3287 << static_cast<const void*>(length
) << ", "
3288 << static_cast<const void*>(size
) << ", "
3289 << static_cast<const void*>(type
) << ", "
3290 << static_cast<const void*>(name
) << ", ");
3292 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3296 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3298 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3299 this, program
, index
, bufsize
, length
, size
, type
, name
);
3302 GPU_CLIENT_LOG(" size: " << *size
);
3305 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3308 GPU_CLIENT_LOG(" name: " << name
);
3314 void GLES2Implementation::GetUniformfv(
3315 GLuint program
, GLint location
, GLfloat
* params
) {
3316 GPU_CLIENT_SINGLE_THREAD_CHECK();
3317 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3318 << program
<< ", " << location
<< ", "
3319 << static_cast<const void*>(params
) << ")");
3320 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3321 typedef cmds::GetUniformfv::Result Result
;
3322 Result
* result
= GetResultAs
<Result
*>();
3326 result
->SetNumResults(0);
3327 helper_
->GetUniformfv(
3328 program
, location
, GetResultShmId(), GetResultShmOffset());
3330 result
->CopyResult(params
);
3331 GPU_CLIENT_LOG_CODE_BLOCK({
3332 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3333 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3339 void GLES2Implementation::GetUniformiv(
3340 GLuint program
, GLint location
, GLint
* params
) {
3341 GPU_CLIENT_SINGLE_THREAD_CHECK();
3342 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3343 << program
<< ", " << location
<< ", "
3344 << static_cast<const void*>(params
) << ")");
3345 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3346 typedef cmds::GetUniformiv::Result Result
;
3347 Result
* result
= GetResultAs
<Result
*>();
3351 result
->SetNumResults(0);
3352 helper_
->GetUniformiv(
3353 program
, location
, GetResultShmId(), GetResultShmOffset());
3355 GetResultAs
<cmds::GetUniformiv::Result
*>()->CopyResult(params
);
3356 GPU_CLIENT_LOG_CODE_BLOCK({
3357 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3358 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3364 void GLES2Implementation::GetUniformuiv(
3365 GLuint program
, GLint location
, GLuint
* params
) {
3366 GPU_CLIENT_SINGLE_THREAD_CHECK();
3367 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv("
3368 << program
<< ", " << location
<< ", "
3369 << static_cast<const void*>(params
) << ")");
3370 TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
3371 typedef cmds::GetUniformuiv::Result Result
;
3372 Result
* result
= GetResultAs
<Result
*>();
3376 result
->SetNumResults(0);
3377 helper_
->GetUniformuiv(
3378 program
, location
, GetResultShmId(), GetResultShmOffset());
3380 GetResultAs
<cmds::GetUniformuiv::Result
*>()->CopyResult(params
);
3381 GPU_CLIENT_LOG_CODE_BLOCK({
3382 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3383 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3389 void GLES2Implementation::ReadPixels(
3390 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3391 GLenum type
, void* pixels
) {
3392 GPU_CLIENT_SINGLE_THREAD_CHECK();
3393 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3394 << xoffset
<< ", " << yoffset
<< ", "
3395 << width
<< ", " << height
<< ", "
3396 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3397 << GLES2Util::GetStringPixelType(type
) << ", "
3398 << static_cast<const void*>(pixels
) << ")");
3399 if (width
< 0 || height
< 0) {
3400 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3403 if (width
== 0 || height
== 0) {
3407 // glReadPixel pads the size of each row of pixels by an amount specified by
3408 // glPixelStorei. So, we have to take that into account both in the fact that
3409 // the pixels returned from the ReadPixel command will include that padding
3410 // and that when we copy the results to the user's buffer we need to not
3411 // write those padding bytes but leave them as they are.
3413 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3414 typedef cmds::ReadPixels::Result Result
;
3416 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3418 uint32 unpadded_row_size
;
3419 uint32 padded_row_size
;
3420 if (!GLES2Util::ComputeImageDataSizes(
3421 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3422 &unpadded_row_size
, &padded_row_size
)) {
3423 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3427 if (bound_pixel_pack_transfer_buffer_id_
) {
3428 GLuint offset
= ToGLuint(pixels
);
3429 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3430 bound_pixel_pack_transfer_buffer_id_
,
3431 "glReadPixels", offset
, padded_row_size
* height
);
3432 if (buffer
&& buffer
->shm_id() != -1) {
3433 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3434 buffer
->shm_id(), buffer
->shm_offset(),
3442 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3446 // Transfer by rows.
3447 // The max rows we can transfer.
3449 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3450 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3451 if (!buffer
.valid()) {
3454 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3455 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3456 num_rows
= std::min(num_rows
, height
);
3457 // NOTE: We must look up the address of the result area AFTER allocation
3458 // of the transfer buffer since the transfer buffer may be reallocated.
3459 Result
* result
= GetResultAs
<Result
*>();
3463 *result
= 0; // mark as failed.
3464 helper_
->ReadPixels(
3465 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3466 buffer
.shm_id(), buffer
.offset(),
3467 GetResultShmId(), GetResultShmOffset(),
3471 // when doing a y-flip we have to iterate through top-to-bottom chunks
3472 // of the dst. The service side handles reversing the rows within a
3475 if (pack_reverse_row_order_
) {
3476 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3480 // We have to copy 1 row at a time to avoid writing pad bytes.
3481 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3482 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3483 memcpy(rows_dst
, src
, unpadded_row_size
);
3484 rows_dst
+= padded_row_size
;
3485 src
+= padded_row_size
;
3487 if (!pack_reverse_row_order_
) {
3491 // If it was not marked as successful exit.
3495 yoffset
+= num_rows
;
3501 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3502 GPU_CLIENT_SINGLE_THREAD_CHECK();
3503 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3504 << GLES2Util::GetStringEnum(texture
) << ")");
3505 GLuint texture_index
= texture
- GL_TEXTURE0
;
3506 if (texture_index
>=
3507 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3508 SetGLErrorInvalidEnum(
3509 "glActiveTexture", texture
, "texture");
3513 active_texture_unit_
= texture_index
;
3514 helper_
->ActiveTexture(texture
);
3518 void GLES2Implementation::GenBuffersHelper(
3519 GLsizei
/* n */, const GLuint
* /* buffers */) {
3522 void GLES2Implementation::GenFramebuffersHelper(
3523 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3526 void GLES2Implementation::GenRenderbuffersHelper(
3527 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3530 void GLES2Implementation::GenTexturesHelper(
3531 GLsizei
/* n */, const GLuint
* /* textures */) {
3534 void GLES2Implementation::GenVertexArraysOESHelper(
3535 GLsizei n
, const GLuint
* arrays
) {
3536 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3539 void GLES2Implementation::GenQueriesEXTHelper(
3540 GLsizei
/* n */, const GLuint
* /* queries */) {
3543 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3545 const GLuint
* /* valuebuffers */) {
3548 void GLES2Implementation::GenSamplersHelper(
3549 GLsizei
/* n */, const GLuint
* /* samplers */) {
3552 void GLES2Implementation::GenTransformFeedbacksHelper(
3553 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3556 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3557 // generates a new resource. On newer versions of OpenGL they don't. The code
3558 // related to binding below will need to change if we switch to the new OpenGL
3559 // model. Specifically it assumes a bind will succeed which is always true in
3560 // the old model but possibly not true in the new model if another context has
3561 // deleted the resource.
3563 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3564 // used even when Bind has failed. However, the bug is minor compared to the
3565 // overhead & duplicated checking in client side.
3567 void GLES2Implementation::BindBufferHelper(
3568 GLenum target
, GLuint buffer_id
) {
3569 // TODO(gman): See note #1 above.
3570 bool changed
= false;
3572 case GL_ARRAY_BUFFER
:
3573 if (bound_array_buffer_
!= buffer_id
) {
3574 bound_array_buffer_
= buffer_id
;
3578 case GL_COPY_READ_BUFFER
:
3579 if (bound_copy_read_buffer_
!= buffer_id
) {
3580 bound_copy_read_buffer_
= buffer_id
;
3584 case GL_COPY_WRITE_BUFFER
:
3585 if (bound_copy_write_buffer_
!= buffer_id
) {
3586 bound_copy_write_buffer_
= buffer_id
;
3590 case GL_ELEMENT_ARRAY_BUFFER
:
3591 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3593 case GL_PIXEL_PACK_BUFFER
:
3594 if (bound_pixel_pack_buffer_
!= buffer_id
) {
3595 bound_pixel_pack_buffer_
= buffer_id
;
3599 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3600 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3602 case GL_PIXEL_UNPACK_BUFFER
:
3603 if (bound_pixel_unpack_buffer_
!= buffer_id
) {
3604 bound_pixel_unpack_buffer_
= buffer_id
;
3608 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3609 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3611 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3612 if (bound_transform_feedback_buffer_
!= buffer_id
) {
3613 bound_transform_feedback_buffer_
= buffer_id
;
3617 case GL_UNIFORM_BUFFER
:
3618 if (bound_uniform_buffer_
!= buffer_id
) {
3619 bound_uniform_buffer_
= buffer_id
;
3627 // TODO(gman): See note #2 above.
3629 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3630 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3634 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3635 helper_
->BindBuffer(target
, buffer
);
3636 if (share_group_
->bind_generates_resource())
3637 helper_
->CommandBufferHelper::OrderingBarrier();
3640 void GLES2Implementation::BindBufferBaseHelper(
3641 GLenum target
, GLuint index
, GLuint buffer_id
) {
3642 // TODO(zmo): See note #1 above.
3643 // TODO(zmo): See note #2 above.
3644 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3645 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3648 void GLES2Implementation::BindBufferBaseStub(
3649 GLenum target
, GLuint index
, GLuint buffer
) {
3650 helper_
->BindBufferBase(target
, index
, buffer
);
3651 if (share_group_
->bind_generates_resource())
3652 helper_
->CommandBufferHelper::Flush();
3655 void GLES2Implementation::BindBufferRangeHelper(
3656 GLenum target
, GLuint index
, GLuint buffer_id
,
3657 GLintptr offset
, GLsizeiptr size
) {
3658 // TODO(zmo): See note #1 above.
3659 // TODO(zmo): See note #2 above.
3660 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3661 this, target
, index
, buffer_id
, offset
, size
,
3662 &GLES2Implementation::BindBufferRangeStub
);
3665 void GLES2Implementation::BindBufferRangeStub(
3666 GLenum target
, GLuint index
, GLuint buffer
,
3667 GLintptr offset
, GLsizeiptr size
) {
3668 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3669 if (share_group_
->bind_generates_resource())
3670 helper_
->CommandBufferHelper::Flush();
3673 void GLES2Implementation::BindFramebufferHelper(
3674 GLenum target
, GLuint framebuffer
) {
3675 // TODO(gman): See note #1 above.
3676 bool changed
= false;
3678 case GL_FRAMEBUFFER
:
3679 if (bound_framebuffer_
!= framebuffer
||
3680 bound_read_framebuffer_
!= framebuffer
) {
3681 bound_framebuffer_
= framebuffer
;
3682 bound_read_framebuffer_
= framebuffer
;
3686 case GL_READ_FRAMEBUFFER
:
3687 if (!IsChromiumFramebufferMultisampleAvailable()) {
3688 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3691 if (bound_read_framebuffer_
!= framebuffer
) {
3692 bound_read_framebuffer_
= framebuffer
;
3696 case GL_DRAW_FRAMEBUFFER
:
3697 if (!IsChromiumFramebufferMultisampleAvailable()) {
3698 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3701 if (bound_framebuffer_
!= framebuffer
) {
3702 bound_framebuffer_
= framebuffer
;
3707 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3712 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3713 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3717 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3718 GLuint framebuffer
) {
3719 helper_
->BindFramebuffer(target
, framebuffer
);
3720 if (share_group_
->bind_generates_resource())
3721 helper_
->CommandBufferHelper::OrderingBarrier();
3724 void GLES2Implementation::BindRenderbufferHelper(
3725 GLenum target
, GLuint renderbuffer
) {
3726 // TODO(gman): See note #1 above.
3727 bool changed
= false;
3729 case GL_RENDERBUFFER
:
3730 if (bound_renderbuffer_
!= renderbuffer
) {
3731 bound_renderbuffer_
= renderbuffer
;
3739 // TODO(zmo): See note #2 above.
3741 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3742 this, target
, renderbuffer
,
3743 &GLES2Implementation::BindRenderbufferStub
);
3747 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3748 GLuint renderbuffer
) {
3749 helper_
->BindRenderbuffer(target
, renderbuffer
);
3750 if (share_group_
->bind_generates_resource())
3751 helper_
->CommandBufferHelper::OrderingBarrier();
3754 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3756 helper_
->BindSampler(unit
, sampler
);
3759 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3760 // TODO(gman): See note #1 above.
3761 // TODO(gman): Change this to false once we figure out why it's failing
3763 bool changed
= true;
3764 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3767 if (unit
.bound_texture_2d
!= texture
) {
3768 unit
.bound_texture_2d
= texture
;
3772 case GL_TEXTURE_CUBE_MAP
:
3773 if (unit
.bound_texture_cube_map
!= texture
) {
3774 unit
.bound_texture_cube_map
= texture
;
3778 case GL_TEXTURE_EXTERNAL_OES
:
3779 if (unit
.bound_texture_external_oes
!= texture
) {
3780 unit
.bound_texture_external_oes
= texture
;
3788 // TODO(gman): See note #2 above.
3790 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3791 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3795 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3796 helper_
->BindTexture(target
, texture
);
3797 if (share_group_
->bind_generates_resource())
3798 helper_
->CommandBufferHelper::OrderingBarrier();
3801 void GLES2Implementation::BindTransformFeedbackHelper(
3802 GLenum target
, GLuint transformfeedback
) {
3803 helper_
->BindTransformFeedback(target
, transformfeedback
);
3806 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3807 bool changed
= false;
3808 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3810 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3811 // because unlike other resources VertexArrayObject ids must
3812 // be generated by GenVertexArrays. A random id to Bind will not
3813 // generate a new object.
3814 helper_
->BindVertexArrayOES(array
);
3818 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3819 "id was not generated with glGenVertexArrayOES");
3823 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3824 GLuint valuebuffer
) {
3825 bool changed
= false;
3827 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3828 if (bound_valuebuffer_
!= valuebuffer
) {
3829 bound_valuebuffer_
= valuebuffer
;
3837 // TODO(gman): See note #2 above.
3839 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3840 this, target
, valuebuffer
,
3841 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3845 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3846 GLuint valuebuffer
) {
3847 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3848 if (share_group_
->bind_generates_resource())
3849 helper_
->CommandBufferHelper::OrderingBarrier();
3852 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3853 if (current_program_
!= program
) {
3854 current_program_
= program
;
3855 helper_
->UseProgram(program
);
3859 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3860 return vertex_array_object_manager_
->IsReservedId(id
);
3863 void GLES2Implementation::DeleteBuffersHelper(
3864 GLsizei n
, const GLuint
* buffers
) {
3865 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3866 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3869 "glDeleteBuffers", "id not created by this context.");
3872 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3873 if (buffers
[ii
] == bound_array_buffer_
) {
3874 bound_array_buffer_
= 0;
3876 if (buffers
[ii
] == bound_copy_read_buffer_
) {
3877 bound_copy_read_buffer_
= 0;
3879 if (buffers
[ii
] == bound_copy_write_buffer_
) {
3880 bound_copy_write_buffer_
= 0;
3882 if (buffers
[ii
] == bound_pixel_pack_buffer_
) {
3883 bound_pixel_pack_buffer_
= 0;
3885 if (buffers
[ii
] == bound_pixel_unpack_buffer_
) {
3886 bound_pixel_unpack_buffer_
= 0;
3888 if (buffers
[ii
] == bound_transform_feedback_buffer_
) {
3889 bound_transform_feedback_buffer_
= 0;
3891 if (buffers
[ii
] == bound_uniform_buffer_
) {
3892 bound_uniform_buffer_
= 0;
3894 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3896 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3898 RemoveTransferBuffer(buffer
);
3900 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3901 bound_pixel_unpack_transfer_buffer_id_
= 0;
3904 RemoveMappedBufferRangeById(buffers
[ii
]);
3908 void GLES2Implementation::DeleteBuffersStub(
3909 GLsizei n
, const GLuint
* buffers
) {
3910 helper_
->DeleteBuffersImmediate(n
, buffers
);
3914 void GLES2Implementation::DeleteFramebuffersHelper(
3915 GLsizei n
, const GLuint
* framebuffers
) {
3916 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3917 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3920 "glDeleteFramebuffers", "id not created by this context.");
3923 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3924 if (framebuffers
[ii
] == bound_framebuffer_
) {
3925 bound_framebuffer_
= 0;
3927 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3928 bound_read_framebuffer_
= 0;
3933 void GLES2Implementation::DeleteFramebuffersStub(
3934 GLsizei n
, const GLuint
* framebuffers
) {
3935 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3938 void GLES2Implementation::DeleteRenderbuffersHelper(
3939 GLsizei n
, const GLuint
* renderbuffers
) {
3940 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3941 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3944 "glDeleteRenderbuffers", "id not created by this context.");
3947 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3948 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3949 bound_renderbuffer_
= 0;
3954 void GLES2Implementation::DeleteRenderbuffersStub(
3955 GLsizei n
, const GLuint
* renderbuffers
) {
3956 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3959 void GLES2Implementation::DeleteTexturesHelper(
3960 GLsizei n
, const GLuint
* textures
) {
3961 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3962 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3965 "glDeleteTextures", "id not created by this context.");
3968 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3969 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3971 TextureUnit
& unit
= texture_units_
[tt
];
3972 if (textures
[ii
] == unit
.bound_texture_2d
) {
3973 unit
.bound_texture_2d
= 0;
3975 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3976 unit
.bound_texture_cube_map
= 0;
3978 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3979 unit
.bound_texture_external_oes
= 0;
3985 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
3986 const GLuint
* textures
) {
3987 helper_
->DeleteTexturesImmediate(n
, textures
);
3990 void GLES2Implementation::DeleteVertexArraysOESHelper(
3991 GLsizei n
, const GLuint
* arrays
) {
3992 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
3993 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
3994 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
3997 "glDeleteVertexArraysOES", "id not created by this context.");
4002 void GLES2Implementation::DeleteVertexArraysOESStub(
4003 GLsizei n
, const GLuint
* arrays
) {
4004 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
4007 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
4009 const GLuint
* valuebuffers
) {
4010 if (!GetIdHandler(id_namespaces::kValuebuffers
)
4011 ->FreeIds(this, n
, valuebuffers
,
4012 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
4013 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
4014 "id not created by this context.");
4017 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4018 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
4019 bound_valuebuffer_
= 0;
4024 void GLES2Implementation::DeleteSamplersStub(
4025 GLsizei n
, const GLuint
* samplers
) {
4026 helper_
->DeleteSamplersImmediate(n
, samplers
);
4029 void GLES2Implementation::DeleteSamplersHelper(
4030 GLsizei n
, const GLuint
* samplers
) {
4031 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
4032 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
4035 "glDeleteSamplers", "id not created by this context.");
4040 void GLES2Implementation::DeleteTransformFeedbacksStub(
4041 GLsizei n
, const GLuint
* transformfeedbacks
) {
4042 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
4045 void GLES2Implementation::DeleteTransformFeedbacksHelper(
4046 GLsizei n
, const GLuint
* transformfeedbacks
) {
4047 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
4048 this, n
, transformfeedbacks
,
4049 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
4052 "glDeleteTransformFeedbacks", "id not created by this context.");
4057 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
4059 const GLuint
* valuebuffers
) {
4060 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
4063 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
4064 GPU_CLIENT_SINGLE_THREAD_CHECK();
4066 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
4067 vertex_array_object_manager_
->SetAttribEnable(index
, false);
4068 helper_
->DisableVertexAttribArray(index
);
4072 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
4073 GPU_CLIENT_SINGLE_THREAD_CHECK();
4074 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
4076 vertex_array_object_manager_
->SetAttribEnable(index
, true);
4077 helper_
->EnableVertexAttribArray(index
);
4081 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
4082 GPU_CLIENT_SINGLE_THREAD_CHECK();
4083 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
4084 << GLES2Util::GetStringDrawMode(mode
) << ", "
4085 << first
<< ", " << count
<< ")");
4087 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
4090 bool simulated
= false;
4091 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4092 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
4095 helper_
->DrawArrays(mode
, first
, count
);
4096 RestoreArrayBuffer(simulated
);
4100 void GLES2Implementation::GetVertexAttribfv(
4101 GLuint index
, GLenum pname
, GLfloat
* params
) {
4102 GPU_CLIENT_SINGLE_THREAD_CHECK();
4103 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
4105 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4106 << static_cast<const void*>(params
) << ")");
4108 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4109 *params
= static_cast<GLfloat
>(value
);
4112 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
4113 typedef cmds::GetVertexAttribfv::Result Result
;
4114 Result
* result
= GetResultAs
<Result
*>();
4118 result
->SetNumResults(0);
4119 helper_
->GetVertexAttribfv(
4120 index
, pname
, GetResultShmId(), GetResultShmOffset());
4122 result
->CopyResult(params
);
4123 GPU_CLIENT_LOG_CODE_BLOCK({
4124 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4125 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4131 void GLES2Implementation::GetVertexAttribiv(
4132 GLuint index
, GLenum pname
, GLint
* params
) {
4133 GPU_CLIENT_SINGLE_THREAD_CHECK();
4134 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
4136 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4137 << static_cast<const void*>(params
) << ")");
4139 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4140 *params
= static_cast<GLint
>(value
);
4143 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
4144 typedef cmds::GetVertexAttribiv::Result Result
;
4145 Result
* result
= GetResultAs
<Result
*>();
4149 result
->SetNumResults(0);
4150 helper_
->GetVertexAttribiv(
4151 index
, pname
, GetResultShmId(), GetResultShmOffset());
4153 result
->CopyResult(params
);
4154 GPU_CLIENT_LOG_CODE_BLOCK({
4155 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4156 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4162 void GLES2Implementation::GetVertexAttribIiv(
4163 GLuint index
, GLenum pname
, GLint
* params
) {
4164 GPU_CLIENT_SINGLE_THREAD_CHECK();
4165 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv("
4167 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4168 << static_cast<const void*>(params
) << ")");
4170 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4171 *params
= static_cast<GLint
>(value
);
4174 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
4175 typedef cmds::GetVertexAttribiv::Result Result
;
4176 Result
* result
= GetResultAs
<Result
*>();
4180 result
->SetNumResults(0);
4181 helper_
->GetVertexAttribIiv(
4182 index
, pname
, GetResultShmId(), GetResultShmOffset());
4184 result
->CopyResult(params
);
4185 GPU_CLIENT_LOG_CODE_BLOCK({
4186 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4187 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4193 void GLES2Implementation::GetVertexAttribIuiv(
4194 GLuint index
, GLenum pname
, GLuint
* params
) {
4195 GPU_CLIENT_SINGLE_THREAD_CHECK();
4196 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv("
4198 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4199 << static_cast<const void*>(params
) << ")");
4201 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4202 *params
= static_cast<GLuint
>(value
);
4205 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
4206 typedef cmds::GetVertexAttribiv::Result Result
;
4207 Result
* result
= GetResultAs
<Result
*>();
4211 result
->SetNumResults(0);
4212 helper_
->GetVertexAttribIuiv(
4213 index
, pname
, GetResultShmId(), GetResultShmOffset());
4215 result
->CopyResult(params
);
4216 GPU_CLIENT_LOG_CODE_BLOCK({
4217 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4218 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4224 GLenum
GLES2Implementation::GetGraphicsResetStatusKHR() {
4225 GPU_CLIENT_SINGLE_THREAD_CHECK();
4226 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");
4227 // If we can't make command buffers then the context is lost.
4228 if (gpu_control_
->IsGpuChannelLost())
4229 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4230 // Otherwise, check the command buffer if it is lost.
4231 if (helper_
->IsContextLost()) {
4232 // TODO(danakj): We could GetLastState() off the CommandBuffer and return
4233 // the actual reason here if we cared to.
4234 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4239 void GLES2Implementation::Swap() {
4243 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
4244 PostSubBufferCHROMIUM(
4245 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
4248 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
4249 switch (plane_transform
) {
4250 case gfx::OVERLAY_TRANSFORM_INVALID
:
4252 case gfx::OVERLAY_TRANSFORM_NONE
:
4253 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4254 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
4255 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
4256 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
4257 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
4258 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
4259 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
4260 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
4261 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
4262 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
4263 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
4266 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4269 void GLES2Implementation::ScheduleOverlayPlane(
4271 gfx::OverlayTransform plane_transform
,
4272 unsigned overlay_texture_id
,
4273 const gfx::Rect
& display_bounds
,
4274 const gfx::RectF
& uv_rect
) {
4275 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
4276 GetGLESOverlayTransform(plane_transform
),
4280 display_bounds
.width(),
4281 display_bounds
.height(),
4288 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
4289 const char* feature
) {
4290 GPU_CLIENT_SINGLE_THREAD_CHECK();
4291 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
4293 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
4294 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
4295 Result
* result
= GetResultAs
<Result
*>();
4300 SetBucketAsCString(kResultBucketId
, feature
);
4301 helper_
->EnableFeatureCHROMIUM(
4302 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
4304 helper_
->SetBucketSize(kResultBucketId
, 0);
4305 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
4306 return *result
!= 0;
4309 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
4310 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
4311 GPU_CLIENT_SINGLE_THREAD_CHECK();
4312 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
4313 << target
<< ", " << offset
<< ", " << size
<< ", "
4314 << GLES2Util::GetStringEnum(access
) << ")");
4315 // NOTE: target is NOT checked because the service will check it
4316 // and we don't know what targets are valid.
4317 if (access
!= GL_WRITE_ONLY
) {
4318 SetGLErrorInvalidEnum(
4319 "glMapBufferSubDataCHROMIUM", access
, "access");
4322 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
4323 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
4328 unsigned int shm_offset
;
4329 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4331 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
4335 std::pair
<MappedBufferMap::iterator
, bool> result
=
4336 mapped_buffers_
.insert(std::make_pair(
4339 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4340 DCHECK(result
.second
);
4341 GPU_CLIENT_LOG(" returned " << mem
);
4345 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
4346 GPU_CLIENT_SINGLE_THREAD_CHECK();
4348 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
4349 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
4350 if (it
== mapped_buffers_
.end()) {
4352 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
4355 const MappedBuffer
& mb
= it
->second
;
4356 helper_
->BufferSubData(
4357 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
4358 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
4359 mapped_buffers_
.erase(it
);
4363 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
4364 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
4366 bool cached
= GetHelper(binding
, &id
);
4368 return static_cast<GLuint
>(id
);
4371 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
4372 GLuint buffer
= GetBoundBufferHelper(target
);
4373 RemoveMappedBufferRangeById(buffer
);
4376 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4378 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4379 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4380 mapped_memory_
->FreePendingToken(
4381 iter
->second
.shm_memory
, helper_
->InsertToken());
4382 mapped_buffer_range_map_
.erase(iter
);
4387 void GLES2Implementation::ClearMappedBufferRangeMap() {
4388 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4389 if (buffer_range
.second
.shm_memory
) {
4390 mapped_memory_
->FreePendingToken(
4391 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4394 mapped_buffer_range_map_
.clear();
4397 void* GLES2Implementation::MapBufferRange(
4398 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4399 GPU_CLIENT_SINGLE_THREAD_CHECK();
4400 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4401 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4402 << size
<< ", " << access
<< ")");
4403 if (!ValidateSize("glMapBufferRange", size
) ||
4404 !ValidateOffset("glMapBufferRange", offset
)) {
4409 unsigned int shm_offset
;
4410 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4412 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4416 typedef cmds::MapBufferRange::Result Result
;
4417 Result
* result
= GetResultAs
<Result
*>();
4419 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4420 GetResultShmId(), GetResultShmOffset());
4421 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4422 // consider an early return without WaitForCmd(). crbug.com/465804.
4425 const GLbitfield kInvalidateBits
=
4426 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4427 if ((access
& kInvalidateBits
) != 0) {
4428 // We do not read back from the buffer, therefore, we set the client
4429 // side memory to zero to avoid uninitialized data.
4430 memset(mem
, 0, size
);
4432 GLuint buffer
= GetBoundBufferHelper(target
);
4433 DCHECK_NE(0u, buffer
);
4434 // glMapBufferRange fails on an already mapped buffer.
4435 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4436 mapped_buffer_range_map_
.end());
4437 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4439 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4440 DCHECK(iter
.second
);
4442 mapped_memory_
->Free(mem
);
4446 GPU_CLIENT_LOG(" returned " << mem
);
4451 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4452 GPU_CLIENT_SINGLE_THREAD_CHECK();
4453 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4454 << GLES2Util::GetStringEnum(target
) << ")");
4456 case GL_ARRAY_BUFFER
:
4457 case GL_ELEMENT_ARRAY_BUFFER
:
4458 case GL_COPY_READ_BUFFER
:
4459 case GL_COPY_WRITE_BUFFER
:
4460 case GL_PIXEL_PACK_BUFFER
:
4461 case GL_PIXEL_UNPACK_BUFFER
:
4462 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4463 case GL_UNIFORM_BUFFER
:
4466 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4469 GLuint buffer
= GetBoundBufferHelper(target
);
4471 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4474 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4475 if (iter
== mapped_buffer_range_map_
.end()) {
4476 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4480 helper_
->UnmapBuffer(target
);
4481 RemoveMappedBufferRangeById(buffer
);
4482 // TODO(zmo): There is a rare situation that data might be corrupted and
4483 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4484 // don't have to WaitForCmd().
4485 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4490 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4500 GPU_CLIENT_SINGLE_THREAD_CHECK();
4501 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4502 << target
<< ", " << level
<< ", "
4503 << xoffset
<< ", " << yoffset
<< ", "
4504 << width
<< ", " << height
<< ", "
4505 << GLES2Util::GetStringTextureFormat(format
) << ", "
4506 << GLES2Util::GetStringPixelType(type
) << ", "
4507 << GLES2Util::GetStringEnum(access
) << ")");
4508 if (access
!= GL_WRITE_ONLY
) {
4509 SetGLErrorInvalidEnum(
4510 "glMapTexSubImage2DCHROMIUM", access
, "access");
4513 // NOTE: target is NOT checked because the service will check it
4514 // and we don't know what targets are valid.
4515 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4517 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4521 if (!GLES2Util::ComputeImageDataSizes(
4522 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4524 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4528 unsigned int shm_offset
;
4529 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4531 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4535 std::pair
<MappedTextureMap::iterator
, bool> result
=
4536 mapped_textures_
.insert(std::make_pair(
4539 access
, shm_id
, mem
, shm_offset
,
4540 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4541 DCHECK(result
.second
);
4542 GPU_CLIENT_LOG(" returned " << mem
);
4546 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4547 GPU_CLIENT_SINGLE_THREAD_CHECK();
4549 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4550 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4551 if (it
== mapped_textures_
.end()) {
4553 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4556 const MappedTexture
& mt
= it
->second
;
4557 helper_
->TexSubImage2D(
4558 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4559 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4560 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4561 mapped_textures_
.erase(it
);
4565 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4566 float scale_factor
) {
4567 GPU_CLIENT_SINGLE_THREAD_CHECK();
4568 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4569 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4570 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4574 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4575 GPU_CLIENT_SINGLE_THREAD_CHECK();
4576 GPU_CLIENT_LOG("[" << GetLogPrefix()
4577 << "] glGetRequestableExtensionsCHROMIUM()");
4579 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4580 const char* result
= NULL
;
4581 // Clear the bucket so if the command fails nothing will be in it.
4582 helper_
->SetBucketSize(kResultBucketId
, 0);
4583 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4585 if (GetBucketAsString(kResultBucketId
, &str
)) {
4586 // The set of requestable extensions shrinks as we enable
4587 // them. Because we don't know when the client will stop referring
4588 // to a previous one it queries (see GetString) we need to cache
4589 // the unique results.
4590 std::set
<std::string
>::const_iterator sit
=
4591 requestable_extensions_set_
.find(str
);
4592 if (sit
!= requestable_extensions_set_
.end()) {
4593 result
= sit
->c_str();
4595 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4596 requestable_extensions_set_
.insert(str
);
4597 DCHECK(insert_result
.second
);
4598 result
= insert_result
.first
->c_str();
4601 GPU_CLIENT_LOG(" returned " << result
);
4602 return reinterpret_cast<const GLchar
*>(result
);
4605 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4606 // with VirtualGL contexts.
4607 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4608 GPU_CLIENT_SINGLE_THREAD_CHECK();
4609 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4610 << extension
<< ")");
4611 SetBucketAsCString(kResultBucketId
, extension
);
4612 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4613 helper_
->SetBucketSize(kResultBucketId
, 0);
4615 struct ExtensionCheck
{
4616 const char* extension
;
4617 ExtensionStatus
* status
;
4619 const ExtensionCheck checks
[] = {
4621 "GL_ANGLE_pack_reverse_row_order",
4622 &angle_pack_reverse_row_order_status_
,
4625 "GL_CHROMIUM_framebuffer_multisample",
4626 &chromium_framebuffer_multisample_
,
4629 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4630 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4631 const ExtensionCheck
& check
= checks
[ii
];
4632 if (*check
.status
== kUnavailableExtensionStatus
&&
4633 !strcmp(extension
, check
.extension
)) {
4634 *check
.status
= kUnknownExtensionStatus
;
4639 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4640 GPU_CLIENT_SINGLE_THREAD_CHECK();
4641 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4642 // Wait if this would add too many rate limit tokens.
4643 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4644 helper_
->WaitForToken(rate_limit_tokens_
.front());
4645 rate_limit_tokens_
.pop();
4647 rate_limit_tokens_
.push(helper_
->InsertToken());
4650 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4651 GLuint program
, std::vector
<int8
>* result
) {
4653 // Clear the bucket so if the command fails nothing will be in it.
4654 helper_
->SetBucketSize(kResultBucketId
, 0);
4655 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4656 GetBucketContents(kResultBucketId
, result
);
4659 void GLES2Implementation::GetProgramInfoCHROMIUM(
4660 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4661 GPU_CLIENT_SINGLE_THREAD_CHECK();
4664 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4668 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4671 // Make sure they've set size to 0 else the value will be undefined on
4673 DCHECK_EQ(0, *size
);
4674 std::vector
<int8
> result
;
4675 GetProgramInfoCHROMIUMHelper(program
, &result
);
4676 if (result
.empty()) {
4679 *size
= result
.size();
4683 if (static_cast<size_t>(bufsize
) < result
.size()) {
4684 SetGLError(GL_INVALID_OPERATION
,
4685 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4688 memcpy(info
, &result
[0], result
.size());
4691 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4692 GLuint program
, std::vector
<int8
>* result
) {
4694 // Clear the bucket so if the command fails nothing will be in it.
4695 helper_
->SetBucketSize(kResultBucketId
, 0);
4696 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4697 GetBucketContents(kResultBucketId
, result
);
4700 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4701 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4702 GPU_CLIENT_SINGLE_THREAD_CHECK();
4705 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4709 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4712 // Make sure they've set size to 0 else the value will be undefined on
4714 DCHECK_EQ(0, *size
);
4715 std::vector
<int8
> result
;
4716 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4717 if (result
.empty()) {
4720 *size
= result
.size();
4724 if (static_cast<size_t>(bufsize
) < result
.size()) {
4725 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4726 "bufsize is too small for result.");
4729 memcpy(info
, &result
[0], result
.size());
4732 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4733 GLuint program
, std::vector
<int8
>* result
) {
4735 // Clear the bucket so if the command fails nothing will be in it.
4736 helper_
->SetBucketSize(kResultBucketId
, 0);
4737 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4738 GetBucketContents(kResultBucketId
, result
);
4741 void GLES2Implementation::GetUniformsES3CHROMIUM(
4742 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4743 GPU_CLIENT_SINGLE_THREAD_CHECK();
4746 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4750 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4753 // Make sure they've set size to 0 else the value will be undefined on
4755 DCHECK_EQ(0, *size
);
4756 std::vector
<int8
> result
;
4757 GetUniformsES3CHROMIUMHelper(program
, &result
);
4758 if (result
.empty()) {
4761 *size
= result
.size();
4765 if (static_cast<size_t>(bufsize
) < result
.size()) {
4766 SetGLError(GL_INVALID_OPERATION
,
4767 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4770 memcpy(info
, &result
[0], result
.size());
4773 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4774 GLuint program
, std::vector
<int8
>* result
) {
4776 // Clear the bucket so if the command fails nothing will be in it.
4777 helper_
->SetBucketSize(kResultBucketId
, 0);
4778 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4779 GetBucketContents(kResultBucketId
, result
);
4782 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4783 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4784 GPU_CLIENT_SINGLE_THREAD_CHECK();
4786 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4787 "bufsize less than 0.");
4791 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4795 // Make sure they've set size to 0 else the value will be undefined on
4797 DCHECK_EQ(0, *size
);
4798 std::vector
<int8
> result
;
4799 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4800 if (result
.empty()) {
4803 *size
= result
.size();
4807 if (static_cast<size_t>(bufsize
) < result
.size()) {
4808 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4809 "bufsize is too small for result.");
4812 memcpy(info
, &result
[0], result
.size());
4815 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4816 GPU_CLIENT_SINGLE_THREAD_CHECK();
4817 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4819 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4820 helper_
->CommandBufferHelper::Flush();
4821 return gpu_control_
->CreateStreamTexture(texture
);
4824 void GLES2Implementation::PostSubBufferCHROMIUM(
4825 GLint x
, GLint y
, GLint width
, GLint height
) {
4826 GPU_CLIENT_SINGLE_THREAD_CHECK();
4827 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4828 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4829 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4830 "width", width
, "height", height
);
4832 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4833 swap_buffers_tokens_
.push(helper_
->InsertToken());
4834 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4835 helper_
->CommandBufferHelper::Flush();
4836 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4837 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4838 swap_buffers_tokens_
.pop();
4842 void GLES2Implementation::DeleteQueriesEXTHelper(
4843 GLsizei n
, const GLuint
* queries
) {
4844 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4845 query_tracker_
->RemoveQuery(queries
[ii
]);
4846 query_id_allocator_
->FreeID(queries
[ii
]);
4849 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4852 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4853 GPU_CLIENT_SINGLE_THREAD_CHECK();
4854 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4856 // TODO(gman): To be spec compliant IDs from other contexts sharing
4857 // resources need to return true here even though you can't share
4858 // queries across contexts?
4859 return query_tracker_
->GetQuery(id
) != NULL
;
4862 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4863 GPU_CLIENT_SINGLE_THREAD_CHECK();
4864 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4865 << GLES2Util::GetStringQueryTarget(target
)
4866 << ", " << id
<< ")");
4869 case GL_COMMANDS_ISSUED_CHROMIUM
:
4870 case GL_LATENCY_QUERY_CHROMIUM
:
4871 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
4872 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
4873 case GL_GET_ERROR_QUERY_CHROMIUM
:
4875 case GL_COMMANDS_COMPLETED_CHROMIUM
:
4876 if (!capabilities_
.sync_query
) {
4878 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4879 "not enabled for commands completed queries");
4883 case GL_ANY_SAMPLES_PASSED
:
4884 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
4885 if (!capabilities_
.occlusion_query_boolean
) {
4887 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4888 "not enabled for occlusion queries");
4892 case GL_TIME_ELAPSED_EXT
:
4893 if (!capabilities_
.timer_queries
) {
4895 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4896 "not enabled for timing queries");
4902 GL_INVALID_ENUM
, "glBeginQueryEXT", "unknown query target");
4906 // if any outstanding queries INV_OP
4907 if (query_tracker_
->GetCurrentQuery(target
)) {
4909 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4914 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4918 if (!query_id_allocator_
->InUse(id
)) {
4919 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4923 // Extra setups some targets might need.
4925 case GL_TIME_ELAPSED_EXT
:
4926 if (!query_tracker_
->SetDisjointSync(this)) {
4927 SetGLError(GL_OUT_OF_MEMORY
,
4929 "buffer allocation failed");
4937 if (query_tracker_
->BeginQuery(id
, target
, this))
4941 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4942 GPU_CLIENT_SINGLE_THREAD_CHECK();
4943 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4944 << GLES2Util::GetStringQueryTarget(target
) << ")");
4945 // Don't do anything if the context is lost.
4946 if (helper_
->IsContextLost()) {
4950 if (query_tracker_
->EndQuery(target
, this))
4954 void GLES2Implementation::QueryCounterEXT(GLuint id
, GLenum target
) {
4955 GPU_CLIENT_SINGLE_THREAD_CHECK();
4956 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] QueryCounterEXT("
4958 << ", " << GLES2Util::GetStringQueryTarget(target
) << ")");
4961 case GL_TIMESTAMP_EXT
:
4962 if (!capabilities_
.timer_queries
) {
4964 GL_INVALID_OPERATION
, "glQueryCounterEXT",
4965 "not enabled for timing queries");
4971 GL_INVALID_ENUM
, "glQueryCounterEXT", "unknown query target");
4976 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "id is 0");
4980 if (!query_id_allocator_
->InUse(id
)) {
4981 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "invalid id");
4985 // Extra setups some targets might need.
4987 case GL_TIMESTAMP_EXT
:
4988 if (!query_tracker_
->SetDisjointSync(this)) {
4989 SetGLError(GL_OUT_OF_MEMORY
,
4990 "glQueryCounterEXT",
4991 "buffer allocation failed");
4999 if (query_tracker_
->QueryCounter(id
, target
, this))
5003 void GLES2Implementation::GetQueryivEXT(
5004 GLenum target
, GLenum pname
, GLint
* params
) {
5005 GPU_CLIENT_SINGLE_THREAD_CHECK();
5006 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
5007 << GLES2Util::GetStringQueryTarget(target
) << ", "
5008 << GLES2Util::GetStringQueryParameter(pname
) << ", "
5009 << static_cast<const void*>(params
) << ")");
5010 if (pname
== GL_QUERY_COUNTER_BITS_EXT
) {
5011 // We convert all queries to CPU time so we support 64 bits.
5014 } else if (pname
!= GL_CURRENT_QUERY_EXT
) {
5015 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
5018 QueryTracker::Query
* query
= query_tracker_
->GetCurrentQuery(target
);
5019 *params
= query
? query
->id() : 0;
5020 GPU_CLIENT_LOG(" " << *params
);
5024 void GLES2Implementation::GetQueryObjectivEXT(
5025 GLuint id
, GLenum pname
, GLint
* params
) {
5026 GLuint64 result
= 0;
5027 if (GetQueryObjectValueHelper("glGetQueryObjectivEXT", id
, pname
, &result
))
5028 *params
= base::saturated_cast
<GLint
>(result
);
5031 void GLES2Implementation::GetQueryObjectuivEXT(
5032 GLuint id
, GLenum pname
, GLuint
* params
) {
5033 GLuint64 result
= 0;
5034 if (GetQueryObjectValueHelper("glGetQueryObjectuivEXT", id
, pname
, &result
))
5035 *params
= base::saturated_cast
<GLuint
>(result
);
5038 void GLES2Implementation::GetQueryObjecti64vEXT(
5039 GLuint id
, GLenum pname
, GLint64
* params
) {
5040 GLuint64 result
= 0;
5041 if (GetQueryObjectValueHelper("glGetQueryObjectiv64vEXT", id
, pname
, &result
))
5042 *params
= base::saturated_cast
<GLint64
>(result
);
5045 void GLES2Implementation::GetQueryObjectui64vEXT(
5046 GLuint id
, GLenum pname
, GLuint64
* params
) {
5047 GLuint64 result
= 0;
5048 if (GetQueryObjectValueHelper("glGetQueryObjectui64vEXT", id
, pname
, &result
))
5052 void GLES2Implementation::SetDisjointValueSyncCHROMIUM() {
5053 query_tracker_
->SetDisjointSync(this);
5056 void GLES2Implementation::DrawArraysInstancedANGLE(
5057 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
5058 GPU_CLIENT_SINGLE_THREAD_CHECK();
5059 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
5060 << GLES2Util::GetStringDrawMode(mode
) << ", "
5061 << first
<< ", " << count
<< ", " << primcount
<< ")");
5063 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
5066 if (primcount
< 0) {
5067 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
5070 if (primcount
== 0) {
5073 bool simulated
= false;
5074 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
5075 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
5079 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
5080 RestoreArrayBuffer(simulated
);
5084 void GLES2Implementation::DrawElementsInstancedANGLE(
5085 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
5086 GLsizei primcount
) {
5087 GPU_CLIENT_SINGLE_THREAD_CHECK();
5088 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
5089 << GLES2Util::GetStringDrawMode(mode
) << ", "
5091 << GLES2Util::GetStringIndexType(type
) << ", "
5092 << static_cast<const void*>(indices
) << ", "
5093 << primcount
<< ")");
5095 SetGLError(GL_INVALID_VALUE
,
5096 "glDrawElementsInstancedANGLE", "count less than 0.");
5102 if (primcount
< 0) {
5103 SetGLError(GL_INVALID_VALUE
,
5104 "glDrawElementsInstancedANGLE", "primcount < 0");
5107 if (primcount
== 0) {
5110 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
5111 !ValidateOffset("glDrawElementsInstancedANGLE",
5112 reinterpret_cast<GLintptr
>(indices
))) {
5116 bool simulated
= false;
5117 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
5118 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
5119 indices
, &offset
, &simulated
)) {
5122 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
5123 RestoreElementAndArrayBuffers(simulated
);
5127 void GLES2Implementation::GenMailboxCHROMIUM(
5129 GPU_CLIENT_SINGLE_THREAD_CHECK();
5130 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
5131 << static_cast<const void*>(mailbox
) << ")");
5132 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
5134 gpu::Mailbox result
= gpu::Mailbox::Generate();
5135 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
5138 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
5139 const GLbyte
* data
) {
5140 GPU_CLIENT_SINGLE_THREAD_CHECK();
5141 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
5142 << static_cast<const void*>(data
) << ")");
5143 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5144 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
5145 "mailbox that was not generated by "
5146 "GenMailboxCHROMIUM.";
5147 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
5151 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
5152 GLuint texture
, GLenum target
, const GLbyte
* data
) {
5153 GPU_CLIENT_SINGLE_THREAD_CHECK();
5154 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
5155 << static_cast<const void*>(data
) << ")");
5156 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5157 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
5158 "mailbox that was not generated by "
5159 "GenMailboxCHROMIUM.";
5160 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
5164 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
5165 const GLbyte
* data
) {
5166 GPU_CLIENT_SINGLE_THREAD_CHECK();
5167 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
5168 << static_cast<const void*>(data
) << ")");
5169 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5170 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
5171 "mailbox that was not generated by "
5172 "GenMailboxCHROMIUM.";
5173 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
5177 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
5178 GLenum target
, const GLbyte
* data
) {
5179 GPU_CLIENT_SINGLE_THREAD_CHECK();
5180 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
5181 << static_cast<const void*>(data
) << ")");
5182 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5183 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
5184 "mailbox that was not generated by "
5185 "GenMailboxCHROMIUM.";
5187 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
5188 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
5190 if (share_group_
->bind_generates_resource())
5191 helper_
->CommandBufferHelper::Flush();
5196 void GLES2Implementation::PushGroupMarkerEXT(
5197 GLsizei length
, const GLchar
* marker
) {
5198 GPU_CLIENT_SINGLE_THREAD_CHECK();
5199 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
5200 << length
<< ", " << marker
<< ")");
5206 (length
? std::string(marker
, length
) : std::string(marker
)));
5207 helper_
->PushGroupMarkerEXT(kResultBucketId
);
5208 helper_
->SetBucketSize(kResultBucketId
, 0);
5209 debug_marker_manager_
.PushGroup(
5210 length
? std::string(marker
, length
) : std::string(marker
));
5213 void GLES2Implementation::InsertEventMarkerEXT(
5214 GLsizei length
, const GLchar
* marker
) {
5215 GPU_CLIENT_SINGLE_THREAD_CHECK();
5216 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
5217 << length
<< ", " << marker
<< ")");
5223 (length
? std::string(marker
, length
) : std::string(marker
)));
5224 helper_
->InsertEventMarkerEXT(kResultBucketId
);
5225 helper_
->SetBucketSize(kResultBucketId
, 0);
5226 debug_marker_manager_
.SetMarker(
5227 length
? std::string(marker
, length
) : std::string(marker
));
5230 void GLES2Implementation::PopGroupMarkerEXT() {
5231 GPU_CLIENT_SINGLE_THREAD_CHECK();
5232 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
5233 helper_
->PopGroupMarkerEXT();
5234 debug_marker_manager_
.PopGroup();
5237 void GLES2Implementation::TraceBeginCHROMIUM(
5238 const char* category_name
, const char* trace_name
) {
5239 GPU_CLIENT_SINGLE_THREAD_CHECK();
5240 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
5241 << category_name
<< ", " << trace_name
<< ")");
5242 SetBucketAsCString(kResultBucketId
, category_name
);
5243 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
5244 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
5245 helper_
->SetBucketSize(kResultBucketId
, 0);
5246 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
5247 current_trace_stack_
++;
5250 void GLES2Implementation::TraceEndCHROMIUM() {
5251 GPU_CLIENT_SINGLE_THREAD_CHECK();
5252 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
5253 if (current_trace_stack_
== 0) {
5254 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
5255 "missing begin trace");
5258 helper_
->TraceEndCHROMIUM();
5259 current_trace_stack_
--;
5262 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
5263 GPU_CLIENT_SINGLE_THREAD_CHECK();
5264 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
5265 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
5267 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
5268 if (access
!= GL_READ_ONLY
) {
5269 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5273 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
5274 if (access
!= GL_WRITE_ONLY
) {
5275 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5281 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
5285 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
5289 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5291 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
5294 if (buffer
->mapped()) {
5295 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
5298 // Here we wait for previous transfer operations to be finished.
5299 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
5300 // with this method of synchronization. Until this is fixed,
5301 // MapBufferCHROMIUM will not block even if the transfer is not ready
5303 if (buffer
->last_usage_token()) {
5304 helper_
->WaitForToken(buffer
->last_usage_token());
5305 buffer
->set_last_usage_token(0);
5307 buffer
->set_mapped(true);
5309 GPU_CLIENT_LOG(" returned " << buffer
->address());
5311 return buffer
->address();
5314 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
5315 GPU_CLIENT_SINGLE_THREAD_CHECK();
5317 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
5319 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
5320 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
5325 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5327 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
5330 if (!buffer
->mapped()) {
5331 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
5334 buffer
->set_mapped(false);
5339 bool GLES2Implementation::EnsureAsyncUploadSync() {
5340 if (async_upload_sync_
)
5344 unsigned int shm_offset
;
5345 void* mem
= mapped_memory_
->Alloc(sizeof(AsyncUploadSync
),
5351 async_upload_sync_shm_id_
= shm_id
;
5352 async_upload_sync_shm_offset_
= shm_offset
;
5353 async_upload_sync_
= static_cast<AsyncUploadSync
*>(mem
);
5354 async_upload_sync_
->Reset();
5359 uint32
GLES2Implementation::NextAsyncUploadToken() {
5360 async_upload_token_
++;
5361 if (async_upload_token_
== 0)
5362 async_upload_token_
++;
5363 return async_upload_token_
;
5366 void GLES2Implementation::PollAsyncUploads() {
5367 if (!async_upload_sync_
)
5370 if (helper_
->IsContextLost()) {
5371 DetachedAsyncUploadMemoryList::iterator it
=
5372 detached_async_upload_memory_
.begin();
5373 while (it
!= detached_async_upload_memory_
.end()) {
5374 mapped_memory_
->Free(it
->first
);
5375 it
= detached_async_upload_memory_
.erase(it
);
5380 DetachedAsyncUploadMemoryList::iterator it
=
5381 detached_async_upload_memory_
.begin();
5382 while (it
!= detached_async_upload_memory_
.end()) {
5383 if (HasAsyncUploadTokenPassed(it
->second
)) {
5384 mapped_memory_
->Free(it
->first
);
5385 it
= detached_async_upload_memory_
.erase(it
);
5392 void GLES2Implementation::FreeAllAsyncUploadBuffers() {
5393 // Free all completed unmanaged async uploads buffers.
5396 // Synchronously free rest of the unmanaged async upload buffers.
5397 if (!detached_async_upload_memory_
.empty()) {
5398 WaitAllAsyncTexImage2DCHROMIUMHelper();
5404 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
5405 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
5406 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
5407 const void* pixels
) {
5408 GPU_CLIENT_SINGLE_THREAD_CHECK();
5409 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
5410 << GLES2Util::GetStringTextureTarget(target
) << ", "
5412 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
5413 << width
<< ", " << height
<< ", " << border
<< ", "
5414 << GLES2Util::GetStringTextureFormat(format
) << ", "
5415 << GLES2Util::GetStringPixelType(type
) << ", "
5416 << static_cast<const void*>(pixels
) << ")");
5417 if (level
< 0 || height
< 0 || width
< 0) {
5418 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
5422 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
5426 uint32 unpadded_row_size
;
5427 uint32 padded_row_size
;
5428 if (!GLES2Util::ComputeImageDataSizes(
5429 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5430 &unpadded_row_size
, &padded_row_size
)) {
5431 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
5435 // If there's no data/buffer just issue the AsyncTexImage2D
5436 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
5437 helper_
->AsyncTexImage2DCHROMIUM(
5438 target
, level
, internalformat
, width
, height
, format
, type
,
5443 if (!EnsureAsyncUploadSync()) {
5444 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5448 // Otherwise, async uploads require a transfer buffer to be bound.
5449 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5450 // the buffer before the transfer is finished. (Currently such
5451 // synchronization has to be handled manually.)
5452 GLuint offset
= ToGLuint(pixels
);
5453 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5454 bound_pixel_unpack_transfer_buffer_id_
,
5455 "glAsyncTexImage2DCHROMIUM", offset
, size
);
5456 if (buffer
&& buffer
->shm_id() != -1) {
5457 uint32 async_token
= NextAsyncUploadToken();
5458 buffer
->set_last_async_upload_token(async_token
);
5459 helper_
->AsyncTexImage2DCHROMIUM(
5460 target
, level
, internalformat
, width
, height
, format
, type
,
5461 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5463 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5467 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
5468 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
5469 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
5470 GPU_CLIENT_SINGLE_THREAD_CHECK();
5471 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
5472 << GLES2Util::GetStringTextureTarget(target
) << ", "
5474 << xoffset
<< ", " << yoffset
<< ", "
5475 << width
<< ", " << height
<< ", "
5476 << GLES2Util::GetStringTextureFormat(format
) << ", "
5477 << GLES2Util::GetStringPixelType(type
) << ", "
5478 << static_cast<const void*>(pixels
) << ")");
5479 if (level
< 0 || height
< 0 || width
< 0) {
5481 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
5486 uint32 unpadded_row_size
;
5487 uint32 padded_row_size
;
5488 if (!GLES2Util::ComputeImageDataSizes(
5489 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5490 &unpadded_row_size
, &padded_row_size
)) {
5492 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
5496 if (!EnsureAsyncUploadSync()) {
5497 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5501 // Async uploads require a transfer buffer to be bound.
5502 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5503 // the buffer before the transfer is finished. (Currently such
5504 // synchronization has to be handled manually.)
5505 GLuint offset
= ToGLuint(pixels
);
5506 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5507 bound_pixel_unpack_transfer_buffer_id_
,
5508 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
5509 if (buffer
&& buffer
->shm_id() != -1) {
5510 uint32 async_token
= NextAsyncUploadToken();
5511 buffer
->set_last_async_upload_token(async_token
);
5512 helper_
->AsyncTexSubImage2DCHROMIUM(
5513 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
5514 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5516 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5520 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
5521 GPU_CLIENT_SINGLE_THREAD_CHECK();
5522 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
5523 << GLES2Util::GetStringTextureTarget(target
) << ")");
5524 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
5528 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUMHelper() {
5529 helper_
->WaitAllAsyncTexImage2DCHROMIUM();
5532 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() {
5533 GPU_CLIENT_SINGLE_THREAD_CHECK();
5534 GPU_CLIENT_LOG("[" << GetLogPrefix()
5535 << "] glWaitAllAsyncTexImage2DCHROMIUM()");
5536 WaitAllAsyncTexImage2DCHROMIUMHelper();
5540 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5541 GPU_CLIENT_SINGLE_THREAD_CHECK();
5542 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5543 helper_
->CommandBufferHelper::Flush();
5544 return gpu_control_
->InsertSyncPoint();
5547 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5548 GPU_CLIENT_SINGLE_THREAD_CHECK();
5549 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5550 DCHECK(capabilities_
.future_sync_points
);
5551 return gpu_control_
->InsertFutureSyncPoint();
5554 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5555 GPU_CLIENT_SINGLE_THREAD_CHECK();
5556 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5557 << sync_point
<< ")");
5558 DCHECK(capabilities_
.future_sync_points
);
5559 helper_
->CommandBufferHelper::Flush();
5560 gpu_control_
->RetireSyncPoint(sync_point
);
5565 bool ValidImageFormat(GLenum internalformat
,
5566 const Capabilities
& capabilities
) {
5567 switch (internalformat
) {
5568 case GL_ATC_RGB_AMD
:
5569 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
5570 return capabilities
.texture_format_atc
;
5571 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
5572 return capabilities
.texture_format_dxt1
;
5573 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
5574 return capabilities
.texture_format_dxt5
;
5575 case GL_ETC1_RGB8_OES
:
5576 return capabilities
.texture_format_etc1
;
5587 bool ValidImageUsage(GLenum usage
) {
5589 case GL_MAP_CHROMIUM
:
5590 case GL_SCANOUT_CHROMIUM
:
5599 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5602 GLenum internalformat
) {
5604 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5609 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5613 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5614 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5619 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5621 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5627 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5630 GLenum internalformat
) {
5631 GPU_CLIENT_SINGLE_THREAD_CHECK();
5632 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5633 << ", " << height
<< ", "
5634 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5637 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5642 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5643 // Flush the command stream to make sure all pending commands
5644 // that may refer to the image_id are executed on the service side.
5645 helper_
->CommandBufferHelper::Flush();
5646 gpu_control_
->DestroyImage(image_id
);
5649 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5650 GPU_CLIENT_SINGLE_THREAD_CHECK();
5651 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5652 << image_id
<< ")");
5653 DestroyImageCHROMIUMHelper(image_id
);
5657 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5660 GLenum internalformat
,
5664 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5669 SetGLError(GL_INVALID_VALUE
,
5670 "glCreateGpuMemoryBufferImageCHROMIUM",
5675 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5676 SetGLError(GL_INVALID_VALUE
,
5677 "glCreateGpuMemoryBufferImageCHROMIUM",
5682 if (!ValidImageUsage(usage
)) {
5683 SetGLError(GL_INVALID_VALUE
,
5684 "glCreateGpuMemoryBufferImageCHROMIUM",
5689 // Flush the command stream to ensure ordering in case the newly
5690 // returned image_id has recently been in use with a different buffer.
5691 helper_
->CommandBufferHelper::Flush();
5692 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5693 width
, height
, internalformat
, usage
);
5695 SetGLError(GL_OUT_OF_MEMORY
,
5696 "glCreateGpuMemoryBufferImageCHROMIUM",
5703 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5706 GLenum internalformat
,
5708 GPU_CLIENT_SINGLE_THREAD_CHECK();
5709 GPU_CLIENT_LOG("[" << GetLogPrefix()
5710 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5711 << ", " << height
<< ", "
5712 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5713 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5714 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5715 width
, height
, internalformat
, usage
);
5720 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5722 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5725 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5726 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5732 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5734 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5737 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5738 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5744 bool GLES2Implementation::GetSamplerParameterfvHelper(
5745 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5746 // TODO(zmo): Implement client side caching.
5750 bool GLES2Implementation::GetSamplerParameterivHelper(
5751 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5752 // TODO(zmo): Implement client side caching.
5756 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5757 const char* const* str
,
5758 const GLint
* length
,
5759 const char* func_name
) {
5760 DCHECK_LE(0, count
);
5761 // Compute the total size.
5762 base::CheckedNumeric
<size_t> total_size
= count
;
5764 total_size
*= sizeof(GLint
);
5765 if (!total_size
.IsValid()) {
5766 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5769 size_t header_size
= total_size
.ValueOrDefault(0);
5770 std::vector
<GLint
> header(count
+ 1);
5771 header
[0] = static_cast<GLint
>(count
);
5772 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5775 len
= (length
&& length
[ii
] >= 0)
5777 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5780 total_size
+= 1; // NULL at the end of each char array.
5781 if (!total_size
.IsValid()) {
5782 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5785 header
[ii
+ 1] = len
;
5787 // Pack data into a bucket on the service.
5788 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5790 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5792 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5793 base::CheckedNumeric
<size_t> checked_size
=
5794 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5796 checked_size
+= 1; // NULL in the end.
5798 if (!checked_size
.IsValid()) {
5799 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5802 size_t size
= checked_size
.ValueOrDefault(0);
5804 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5805 if (!buffer
.valid() || buffer
.size() == 0) {
5806 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5809 size_t copy_size
= buffer
.size();
5810 if (ii
> 0 && buffer
.size() == size
)
5813 memcpy(buffer
.address(), src
, copy_size
);
5814 if (copy_size
< buffer
.size()) {
5815 // Append NULL in the end.
5816 DCHECK(copy_size
+ 1 == buffer
.size());
5817 char* str
= reinterpret_cast<char*>(buffer
.address());
5820 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5821 buffer
.shm_id(), buffer
.offset());
5822 offset
+= buffer
.size();
5823 src
+= buffer
.size();
5824 size
-= buffer
.size();
5827 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5831 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5834 GPU_CLIENT_SINGLE_THREAD_CHECK();
5835 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5836 << ", " << index
<< ", " << binding
<< ")");
5837 share_group_
->program_info_manager()->UniformBlockBinding(
5838 this, program
, index
, binding
);
5839 helper_
->UniformBlockBinding(program
, index
, binding
);
5843 GLenum
GLES2Implementation::ClientWaitSync(
5844 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5845 GPU_CLIENT_SINGLE_THREAD_CHECK();
5846 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5847 << ", " << flags
<< ", " << timeout
<< ")");
5848 typedef cmds::ClientWaitSync::Result Result
;
5849 Result
* result
= GetResultAs
<Result
*>();
5851 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5852 return GL_WAIT_FAILED
;
5854 *result
= GL_WAIT_FAILED
;
5855 uint32_t v32_0
= 0, v32_1
= 0;
5856 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5857 helper_
->ClientWaitSync(
5858 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5859 GetResultShmId(), GetResultShmOffset());
5861 GPU_CLIENT_LOG("returned " << *result
);
5866 void GLES2Implementation::WaitSync(
5867 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5868 GPU_CLIENT_SINGLE_THREAD_CHECK();
5869 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5870 << flags
<< ", " << timeout
<< ")");
5871 uint32_t v32_0
= 0, v32_1
= 0;
5872 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5873 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5877 void GLES2Implementation::GetInternalformativ(
5878 GLenum target
, GLenum format
, GLenum pname
,
5879 GLsizei buf_size
, GLint
* params
) {
5880 GPU_CLIENT_SINGLE_THREAD_CHECK();
5881 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
5882 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ("
5883 << GLES2Util::GetStringRenderBufferTarget(target
) << ", "
5884 << GLES2Util::GetStringRenderBufferFormat(format
) << ", "
5885 << GLES2Util::GetStringInternalFormatParameter(pname
)
5886 << ", " << buf_size
<< ", "
5887 << static_cast<const void*>(params
) << ")");
5889 SetGLError(GL_INVALID_VALUE
, "glGetInternalformativ", "bufSize < 0");
5892 TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ");
5893 if (GetInternalformativHelper(target
, format
, pname
, buf_size
, params
)) {
5896 typedef cmds::GetInternalformativ::Result Result
;
5897 Result
* result
= GetResultAs
<Result
*>();
5901 result
->SetNumResults(0);
5902 helper_
->GetInternalformativ(target
, format
, pname
,
5903 GetResultShmId(), GetResultShmOffset());
5905 GPU_CLIENT_LOG_CODE_BLOCK({
5906 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
5907 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
5910 if (buf_size
> 0 && params
) {
5911 GLint
* data
= result
->GetData();
5912 if (buf_size
>= result
->GetNumResults()) {
5913 buf_size
= result
->GetNumResults();
5915 for (GLsizei ii
= 0; ii
< buf_size
; ++ii
) {
5916 params
[ii
] = data
[ii
];
5922 GLuint
GLES2Implementation::GenPathsCHROMIUM(GLsizei range
) {
5923 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenPathsCHROMIUM(" << range
5925 GPU_CLIENT_SINGLE_THREAD_CHECK();
5926 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
5928 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5931 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5932 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5938 GLuint first_client_id
= 0;
5939 GetRangeIdHandler(id_namespaces::kPaths
)
5940 ->MakeIdRange(this, range
, &first_client_id
);
5942 if (first_client_id
== 0) {
5943 // Ran out of id space. Is not specified to raise any gl errors.
5947 helper_
->GenPathsCHROMIUM(first_client_id
, range
);
5949 GPU_CLIENT_LOG_CODE_BLOCK({
5950 for (GLsizei i
= 0; i
< range
; ++i
) {
5951 GPU_CLIENT_LOG(" " << i
<< ": " << (first_client_id
+ i
));
5955 return first_client_id
;
5958 void GLES2Implementation::DeletePathsCHROMIUM(GLuint first_client_id
,
5960 GPU_CLIENT_SINGLE_THREAD_CHECK();
5961 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeletePathsCHROMIUM("
5962 << first_client_id
<< ", " << range
<< ")");
5963 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
5966 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5969 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5970 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5976 GLuint last_client_id
;
5977 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
)) {
5978 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5982 GetRangeIdHandler(id_namespaces::kPaths
)
5983 ->FreeIdRange(this, first_client_id
, range
,
5984 &GLES2Implementation::DeletePathsCHROMIUMStub
);
5988 void GLES2Implementation::DeletePathsCHROMIUMStub(GLuint first_client_id
,
5990 helper_
->DeletePathsCHROMIUM(first_client_id
, range
);
5993 void GLES2Implementation::PathCommandsCHROMIUM(GLuint path
,
5994 GLsizei num_commands
,
5995 const GLubyte
* commands
,
5998 const void* coords
) {
5999 GPU_CLIENT_SINGLE_THREAD_CHECK();
6000 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathCommandsCHROMIUM(" << path
6001 << ", " << num_commands
<< ", " << commands
<< ", "
6002 << num_coords
<< ", " << coords
<< ")");
6003 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
6005 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "invalid path object");
6008 if (num_commands
< 0) {
6009 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
6012 if (num_commands
!= 0 && !commands
) {
6013 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing commands");
6016 if (num_coords
< 0) {
6017 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
6020 if (num_coords
!= 0 && !coords
) {
6021 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing coords");
6024 uint32 coord_type_size
= GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
6025 if (coord_type_size
== 0) {
6026 SetGLError(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
6029 if (num_commands
== 0) {
6030 // No commands must mean no coords, thus nothing to memcpy. Let
6031 // the service validate the call. Validate coord_type above, so
6032 // that the parameters will be checked the in the same order
6033 // regardless of num_commands.
6034 helper_
->PathCommandsCHROMIUM(path
, num_commands
, 0, 0, num_coords
,
6041 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
)) {
6042 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
6046 uint32 required_buffer_size
;
6047 if (!SafeAddUint32(coords_size
, num_commands
, &required_buffer_size
)) {
6048 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
6052 ScopedTransferBufferPtr
buffer(required_buffer_size
, helper_
,
6054 if (!buffer
.valid() || buffer
.size() < required_buffer_size
) {
6055 SetGLError(GL_OUT_OF_MEMORY
, kFunctionName
, "too large");
6059 uint32 coords_shm_id
= 0;
6060 uint32 coords_shm_offset
= 0;
6061 // Copy coords first because they need more strict alignment.
6062 if (coords_size
> 0) {
6063 unsigned char* coords_addr
= static_cast<unsigned char*>(buffer
.address());
6064 memcpy(coords_addr
, coords
, coords_size
);
6065 coords_shm_id
= buffer
.shm_id();
6066 coords_shm_offset
= buffer
.offset();
6069 DCHECK(num_commands
> 0);
6070 unsigned char* commands_addr
=
6071 static_cast<unsigned char*>(buffer
.address()) + coords_size
;
6072 memcpy(commands_addr
, commands
, num_commands
);
6074 helper_
->PathCommandsCHROMIUM(path
, num_commands
, buffer
.shm_id(),
6075 buffer
.offset() + coords_size
, num_coords
,
6076 coord_type
, coords_shm_id
, coords_shm_offset
);
6080 // Include the auto-generated part of this file. We split this because it means
6081 // we can easily edit the non-auto generated parts right here in this file
6082 // instead of having to edit some template or the code generator.
6083 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
6085 } // namespace gles2