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 "base/strings/stringprintf.h"
20 #include "base/thread_task_runner_handle.h"
21 #include "base/trace_event/memory_allocator_dump.h"
22 #include "base/trace_event/memory_dump_manager.h"
23 #include "base/trace_event/process_memory_dump.h"
24 #include "gpu/command_buffer/client/buffer_tracker.h"
25 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
26 #include "gpu/command_buffer/client/gpu_control.h"
27 #include "gpu/command_buffer/client/program_info_manager.h"
28 #include "gpu/command_buffer/client/query_tracker.h"
29 #include "gpu/command_buffer/client/transfer_buffer.h"
30 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/trace_event.h"
34 #include "ui/gfx/geometry/rect.h"
35 #include "ui/gfx/geometry/rect_f.h"
37 #if defined(GPU_CLIENT_DEBUG)
38 #include "base/command_line.h"
39 #include "gpu/command_buffer/client/gpu_switches.h"
45 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
46 static GLuint
ToGLuint(const void* ptr
) {
47 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
50 #if !defined(_MSC_VER)
51 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
52 const unsigned int GLES2Implementation::kStartingOffset
;
55 GLES2Implementation::GLStaticState::GLStaticState() {
58 GLES2Implementation::GLStaticState::~GLStaticState() {
61 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
62 GLES2Implementation
* gles2_implementation
)
63 : gles2_implementation_(gles2_implementation
) {
64 CHECK_EQ(0, gles2_implementation_
->use_count_
);
65 ++gles2_implementation_
->use_count_
;
68 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
69 --gles2_implementation_
->use_count_
;
70 CHECK_EQ(0, gles2_implementation_
->use_count_
);
73 GLES2Implementation::GLES2Implementation(
74 GLES2CmdHelper
* helper
,
75 ShareGroup
* share_group
,
76 TransferBufferInterface
* transfer_buffer
,
77 bool bind_generates_resource
,
78 bool lose_context_when_out_of_memory
,
79 bool support_client_side_arrays
,
80 GpuControl
* gpu_control
)
82 transfer_buffer_(transfer_buffer
),
83 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
84 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
87 unpack_row_length_(0),
88 unpack_image_height_(0),
90 unpack_skip_pixels_(0),
91 unpack_skip_images_(0),
92 pack_reverse_row_order_(false),
93 active_texture_unit_(0),
94 bound_framebuffer_(0),
95 bound_read_framebuffer_(0),
96 bound_renderbuffer_(0),
97 bound_valuebuffer_(0),
99 bound_array_buffer_(0),
100 bound_copy_read_buffer_(0),
101 bound_copy_write_buffer_(0),
102 bound_pixel_pack_buffer_(0),
103 bound_pixel_unpack_buffer_(0),
104 bound_transform_feedback_buffer_(0),
105 bound_uniform_buffer_(0),
106 bound_pixel_pack_transfer_buffer_id_(0),
107 bound_pixel_unpack_transfer_buffer_id_(0),
110 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
111 support_client_side_arrays_(support_client_side_arrays
),
113 error_message_callback_(NULL
),
114 current_trace_stack_(0),
115 gpu_control_(gpu_control
),
116 capabilities_(gpu_control
->GetCapabilities()),
117 aggressively_free_resources_(false),
118 weak_ptr_factory_(this) {
120 DCHECK(transfer_buffer
);
123 std::stringstream ss
;
124 ss
<< std::hex
<< this;
125 this_in_hex_
= ss
.str();
127 GPU_CLIENT_LOG_CODE_BLOCK({
128 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
129 switches::kEnableGPUClientLogging
);
133 (share_group
? share_group
134 : new ShareGroup(bind_generates_resource
,
135 gpu_control_
->GetCommandBufferID()));
136 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
138 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
141 bool GLES2Implementation::Initialize(
142 unsigned int starting_transfer_buffer_size
,
143 unsigned int min_transfer_buffer_size
,
144 unsigned int max_transfer_buffer_size
,
145 unsigned int mapped_memory_limit
) {
146 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
147 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
148 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
149 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
151 if (!transfer_buffer_
->Initialize(
152 starting_transfer_buffer_size
,
154 min_transfer_buffer_size
,
155 max_transfer_buffer_size
,
161 mapped_memory_
.reset(new MappedMemoryManager(helper_
, mapped_memory_limit
));
163 unsigned chunk_size
= 2 * 1024 * 1024;
164 if (mapped_memory_limit
!= kNoLimit
) {
165 // Use smaller chunks if the client is very memory conscientious.
166 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
168 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
170 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
171 &static_state_
.shader_precisions
;
172 capabilities_
.VisitPrecisions([shader_precisions
](
173 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
174 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
175 cmds::GetShaderPrecisionFormat::Result cached_result
= {
176 true, result
->min_range
, result
->max_range
, result
->precision
};
177 shader_precisions
->insert(std::make_pair(key
, cached_result
));
180 util_
.set_num_compressed_texture_formats(
181 capabilities_
.num_compressed_texture_formats
);
182 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
184 texture_units_
.reset(
185 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
187 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
188 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
190 query_id_allocator_
.reset(new IdAllocator());
191 if (support_client_side_arrays_
) {
192 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
193 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
196 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
197 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
198 support_client_side_arrays_
));
200 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
201 // on Client & Service.
202 if (capabilities_
.bind_generates_resource_chromium
!=
203 (share_group_
->bind_generates_resource() ? 1 : 0)) {
204 SetGLError(GL_INVALID_OPERATION
,
206 "Service bind_generates_resource mismatch.");
210 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
211 // Don't register a dump provider in these cases.
212 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
213 if (base::ThreadTaskRunnerHandle::IsSet()) {
214 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
215 this, base::ThreadTaskRunnerHandle::Get());
221 GLES2Implementation::~GLES2Implementation() {
222 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
225 // Make sure the queries are finished otherwise we'll delete the
226 // shared memory (mapped_memory_) which will free the memory used
227 // by the queries. The GPU process when validating that memory is still
228 // shared will fail and abort (ie, it will stop running).
230 query_tracker_
.reset();
232 // GLES2Implementation::Initialize() could fail before allocating
233 // reserved_ids_, so we need delete them carefully.
234 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
235 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
238 // Release remaining BufferRange mem; This is when a MapBufferRange() is
239 // called but not the UnmapBuffer() pair.
240 ClearMappedBufferRangeMap();
242 // Release any per-context data in share group.
243 share_group_
->FreeContext(this);
245 buffer_tracker_
.reset();
247 // Make sure the commands make it the service.
251 GLES2CmdHelper
* GLES2Implementation::helper() const {
255 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
256 return share_group_
->GetIdHandler(namespace_id
);
259 RangeIdHandlerInterface
* GLES2Implementation::GetRangeIdHandler(
260 int namespace_id
) const {
261 return share_group_
->GetRangeIdHandler(namespace_id
);
264 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
265 if (namespace_id
== id_namespaces::kQueries
)
266 return query_id_allocator_
.get();
271 void* GLES2Implementation::GetResultBuffer() {
272 return transfer_buffer_
->GetResultBuffer();
275 int32
GLES2Implementation::GetResultShmId() {
276 return transfer_buffer_
->GetShmId();
279 uint32
GLES2Implementation::GetResultShmOffset() {
280 return transfer_buffer_
->GetResultOffset();
283 void GLES2Implementation::FreeUnusedSharedMemory() {
284 mapped_memory_
->FreeUnused();
287 void GLES2Implementation::FreeEverything() {
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 bool GLES2Implementation::OnMemoryDump(
347 const base::trace_event::MemoryDumpArgs
& args
,
348 base::trace_event::ProcessMemoryDump
* pmd
) {
349 if (!transfer_buffer_
->HaveBuffer())
352 const uint64 tracing_process_id
=
353 base::trace_event::MemoryDumpManager::GetInstance()
354 ->GetTracingProcessId();
356 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
357 base::StringPrintf("gpu/transfer_buffer_memory/buffer_%d",
358 transfer_buffer_
->GetShmId()));
359 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
360 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
361 transfer_buffer_
->GetSize());
362 dump
->AddScalar("free_size",
363 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
364 transfer_buffer_
->GetFreeSize());
366 GetBufferGUIDForTracing(tracing_process_id
, transfer_buffer_
->GetShmId());
367 const int kImportance
= 2;
368 pmd
->CreateSharedGlobalAllocatorDump(guid
);
369 pmd
->AddOwnershipEdge(dump
->guid(), guid
, kImportance
);
374 void GLES2Implementation::WaitForCmd() {
375 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
376 helper_
->CommandBufferHelper::Finish();
379 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
380 const char* extensions
=
381 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
385 int length
= strlen(ext
);
387 int n
= strcspn(extensions
, " ");
388 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
391 if ('\0' == extensions
[n
]) {
398 bool GLES2Implementation::IsExtensionAvailableHelper(
399 const char* extension
, ExtensionStatus
* status
) {
401 case kAvailableExtensionStatus
:
403 case kUnavailableExtensionStatus
:
406 bool available
= IsExtensionAvailable(extension
);
407 *status
= available
? kAvailableExtensionStatus
:
408 kUnavailableExtensionStatus
;
414 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
415 return IsExtensionAvailableHelper(
416 "GL_ANGLE_pack_reverse_row_order",
417 &angle_pack_reverse_row_order_status_
);
420 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
421 return IsExtensionAvailableHelper(
422 "GL_CHROMIUM_framebuffer_multisample",
423 &chromium_framebuffer_multisample_
);
426 const std::string
& GLES2Implementation::GetLogPrefix() const {
427 const std::string
& prefix(debug_marker_manager_
.GetMarker());
428 return prefix
.empty() ? this_in_hex_
: prefix
;
431 GLenum
GLES2Implementation::GetError() {
432 GPU_CLIENT_SINGLE_THREAD_CHECK();
433 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
434 GLenum err
= GetGLError();
435 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
439 GLenum
GLES2Implementation::GetClientSideGLError() {
440 if (error_bits_
== 0) {
444 GLenum error
= GL_NO_ERROR
;
445 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
446 if ((error_bits_
& mask
) != 0) {
447 error
= GLES2Util::GLErrorBitToGLError(mask
);
451 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
455 GLenum
GLES2Implementation::GetGLError() {
456 TRACE_EVENT0("gpu", "GLES2::GetGLError");
457 // Check the GL error first, then our wrapped error.
458 typedef cmds::GetError::Result Result
;
459 Result
* result
= GetResultAs
<Result
*>();
460 // If we couldn't allocate a result the context is lost.
464 *result
= GL_NO_ERROR
;
465 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
467 GLenum error
= *result
;
468 if (error
== GL_NO_ERROR
) {
469 error
= GetClientSideGLError();
471 // There was an error, clear the corresponding wrapped error.
472 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
477 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
478 void GLES2Implementation::FailGLError(GLenum error
) {
479 if (error
!= GL_NO_ERROR
) {
480 NOTREACHED() << "Error";
483 // NOTE: Calling GetGLError overwrites data in the result buffer.
484 void GLES2Implementation::CheckGLError() {
485 FailGLError(GetGLError());
487 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
489 void GLES2Implementation::SetGLError(
490 GLenum error
, const char* function_name
, const char* msg
) {
491 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
492 << GLES2Util::GetStringError(error
) << ": "
493 << function_name
<< ": " << msg
);
498 if (error_message_callback_
) {
499 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
500 function_name
+ ": " + (msg
? msg
: ""));
501 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
503 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
505 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
506 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
507 GL_UNKNOWN_CONTEXT_RESET_ARB
);
511 void GLES2Implementation::SetGLErrorInvalidEnum(
512 const char* function_name
, GLenum value
, const char* label
) {
513 SetGLError(GL_INVALID_ENUM
, function_name
,
514 (std::string(label
) + " was " +
515 GLES2Util::GetStringEnum(value
)).c_str());
518 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
519 std::vector
<int8
>* data
) {
520 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
522 const uint32 kStartSize
= 32 * 1024;
523 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
524 if (!buffer
.valid()) {
527 typedef cmd::GetBucketStart::Result Result
;
528 Result
* result
= GetResultAs
<Result
*>();
533 helper_
->GetBucketStart(
534 bucket_id
, GetResultShmId(), GetResultShmOffset(),
535 buffer
.size(), buffer
.shm_id(), buffer
.offset());
537 uint32 size
= *result
;
542 if (!buffer
.valid()) {
544 if (!buffer
.valid()) {
547 helper_
->GetBucketData(
548 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
551 uint32 size_to_copy
= std::min(size
, buffer
.size());
552 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
553 offset
+= size_to_copy
;
554 size
-= size_to_copy
;
557 // Free the bucket. This is not required but it does free up the memory.
558 // and we don't have to wait for the result so from the client's perspective
560 helper_
->SetBucketSize(bucket_id
, 0);
565 void GLES2Implementation::SetBucketContents(
566 uint32 bucket_id
, const void* data
, size_t size
) {
568 helper_
->SetBucketSize(bucket_id
, size
);
572 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
573 if (!buffer
.valid()) {
576 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
578 helper_
->SetBucketData(
579 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
580 offset
+= buffer
.size();
581 size
-= buffer
.size();
586 void GLES2Implementation::SetBucketAsCString(
587 uint32 bucket_id
, const char* str
) {
588 // NOTE: strings are passed NULL terminated. That means the empty
589 // string will have a size of 1 and no-string will have a size of 0
591 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
593 helper_
->SetBucketSize(bucket_id
, 0);
597 bool GLES2Implementation::GetBucketAsString(
598 uint32 bucket_id
, std::string
* str
) {
600 std::vector
<int8
> data
;
601 // NOTE: strings are passed NULL terminated. That means the empty
602 // string will have a size of 1 and no-string will have a size of 0
603 if (!GetBucketContents(bucket_id
, &data
)) {
609 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
613 void GLES2Implementation::SetBucketAsString(
614 uint32 bucket_id
, const std::string
& str
) {
615 // NOTE: strings are passed NULL terminated. That means the empty
616 // string will have a size of 1 and no-string will have a size of 0
617 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
620 void GLES2Implementation::Disable(GLenum cap
) {
621 GPU_CLIENT_SINGLE_THREAD_CHECK();
622 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
623 << GLES2Util::GetStringCapability(cap
) << ")");
624 bool changed
= false;
625 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
626 helper_
->Disable(cap
);
631 void GLES2Implementation::Enable(GLenum cap
) {
632 GPU_CLIENT_SINGLE_THREAD_CHECK();
633 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
634 << GLES2Util::GetStringCapability(cap
) << ")");
635 bool changed
= false;
636 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
637 helper_
->Enable(cap
);
642 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
643 GPU_CLIENT_SINGLE_THREAD_CHECK();
644 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
645 << GLES2Util::GetStringCapability(cap
) << ")");
647 if (!state_
.GetEnabled(cap
, &state
)) {
648 typedef cmds::IsEnabled::Result Result
;
649 Result
* result
= GetResultAs
<Result
*>();
654 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
656 state
= (*result
) != 0;
659 GPU_CLIENT_LOG("returned " << state
);
664 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
665 // TODO(zmo): For all the BINDING points, there is a possibility where
666 // resources are shared among multiple contexts, that the cached points
667 // are invalid. It is not a problem for now, but once we allow resource
668 // sharing in WebGL, we need to implement a mechanism to allow correct
669 // client side binding points tracking. crbug.com/465562.
673 case GL_ACTIVE_TEXTURE
:
674 *params
= active_texture_unit_
+ GL_TEXTURE0
;
676 case GL_ARRAY_BUFFER_BINDING
:
677 *params
= bound_array_buffer_
;
679 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
681 vertex_array_object_manager_
->bound_element_array_buffer();
683 case GL_FRAMEBUFFER_BINDING
:
684 *params
= bound_framebuffer_
;
686 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
687 *params
= capabilities_
.max_combined_texture_image_units
;
689 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
690 *params
= capabilities_
.max_cube_map_texture_size
;
692 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
693 *params
= capabilities_
.max_fragment_uniform_vectors
;
695 case GL_MAX_RENDERBUFFER_SIZE
:
696 *params
= capabilities_
.max_renderbuffer_size
;
698 case GL_MAX_TEXTURE_IMAGE_UNITS
:
699 *params
= capabilities_
.max_texture_image_units
;
701 case GL_MAX_TEXTURE_SIZE
:
702 *params
= capabilities_
.max_texture_size
;
704 case GL_MAX_VARYING_VECTORS
:
705 *params
= capabilities_
.max_varying_vectors
;
707 case GL_MAX_VERTEX_ATTRIBS
:
708 *params
= capabilities_
.max_vertex_attribs
;
710 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
711 *params
= capabilities_
.max_vertex_texture_image_units
;
713 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
714 *params
= capabilities_
.max_vertex_uniform_vectors
;
716 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
717 *params
= capabilities_
.num_compressed_texture_formats
;
719 case GL_NUM_SHADER_BINARY_FORMATS
:
720 *params
= capabilities_
.num_shader_binary_formats
;
722 case GL_RENDERBUFFER_BINDING
:
723 *params
= bound_renderbuffer_
;
725 case GL_TEXTURE_BINDING_2D
:
726 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
728 case GL_TEXTURE_BINDING_CUBE_MAP
:
729 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
732 // Non-standard parameters.
733 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
735 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
737 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
738 *params
= bound_pixel_pack_transfer_buffer_id_
;
740 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
741 *params
= bound_pixel_unpack_transfer_buffer_id_
;
743 case GL_READ_FRAMEBUFFER_BINDING
:
744 if (IsChromiumFramebufferMultisampleAvailable()) {
745 *params
= bound_read_framebuffer_
;
749 case GL_TIMESTAMP_EXT
:
750 // We convert all GPU timestamps to CPU time.
751 *params
= base::saturated_cast
<GLint
>(
752 (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
753 * base::Time::kNanosecondsPerMicrosecond
);
755 case GL_GPU_DISJOINT_EXT
:
756 *params
= static_cast<GLint
>(query_tracker_
->CheckAndResetDisjoint());
759 // Non-cached parameters.
760 case GL_ALIASED_LINE_WIDTH_RANGE
:
761 case GL_ALIASED_POINT_SIZE_RANGE
:
765 case GL_BLEND_DST_ALPHA
:
766 case GL_BLEND_DST_RGB
:
767 case GL_BLEND_EQUATION_ALPHA
:
768 case GL_BLEND_EQUATION_RGB
:
769 case GL_BLEND_SRC_ALPHA
:
770 case GL_BLEND_SRC_RGB
:
772 case GL_COLOR_CLEAR_VALUE
:
773 case GL_COLOR_WRITEMASK
:
774 case GL_COMPRESSED_TEXTURE_FORMATS
:
776 case GL_CULL_FACE_MODE
:
777 case GL_CURRENT_PROGRAM
:
779 case GL_DEPTH_CLEAR_VALUE
:
783 case GL_DEPTH_WRITEMASK
:
786 case GL_GENERATE_MIPMAP_HINT
:
788 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
789 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
791 case GL_MAX_VIEWPORT_DIMS
:
792 case GL_PACK_ALIGNMENT
:
793 case GL_POLYGON_OFFSET_FACTOR
:
794 case GL_POLYGON_OFFSET_FILL
:
795 case GL_POLYGON_OFFSET_UNITS
:
797 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
798 case GL_SAMPLE_BUFFERS
:
799 case GL_SAMPLE_COVERAGE
:
800 case GL_SAMPLE_COVERAGE_INVERT
:
801 case GL_SAMPLE_COVERAGE_VALUE
:
804 case GL_SCISSOR_TEST
:
805 case GL_SHADER_BINARY_FORMATS
:
806 case GL_SHADER_COMPILER
:
807 case GL_STENCIL_BACK_FAIL
:
808 case GL_STENCIL_BACK_FUNC
:
809 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
810 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
811 case GL_STENCIL_BACK_REF
:
812 case GL_STENCIL_BACK_VALUE_MASK
:
813 case GL_STENCIL_BACK_WRITEMASK
:
814 case GL_STENCIL_BITS
:
815 case GL_STENCIL_CLEAR_VALUE
:
816 case GL_STENCIL_FAIL
:
817 case GL_STENCIL_FUNC
:
818 case GL_STENCIL_PASS_DEPTH_FAIL
:
819 case GL_STENCIL_PASS_DEPTH_PASS
:
821 case GL_STENCIL_TEST
:
822 case GL_STENCIL_VALUE_MASK
:
823 case GL_STENCIL_WRITEMASK
:
824 case GL_SUBPIXEL_BITS
:
825 case GL_UNPACK_ALIGNMENT
:
832 if (capabilities_
.major_version
< 3) {
838 case GL_COPY_READ_BUFFER_BINDING
:
839 *params
= bound_copy_read_buffer_
;
841 case GL_COPY_WRITE_BUFFER_BINDING
:
842 *params
= bound_copy_write_buffer_
;
844 case GL_MAJOR_VERSION
:
845 *params
= capabilities_
.major_version
;
847 case GL_MAX_3D_TEXTURE_SIZE
:
848 *params
= capabilities_
.max_3d_texture_size
;
850 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
851 *params
= capabilities_
.max_array_texture_layers
;
853 case GL_MAX_COLOR_ATTACHMENTS
:
854 *params
= capabilities_
.max_color_attachments
;
856 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
857 *params
= static_cast<GLint
>(
858 capabilities_
.max_combined_fragment_uniform_components
);
860 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
861 *params
= capabilities_
.max_combined_uniform_blocks
;
863 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
864 *params
= static_cast<GLint
>(
865 capabilities_
.max_combined_vertex_uniform_components
);
867 case GL_MAX_DRAW_BUFFERS
:
868 *params
= capabilities_
.max_draw_buffers
;
870 case GL_MAX_ELEMENT_INDEX
:
871 *params
= static_cast<GLint
>(capabilities_
.max_element_index
);
873 case GL_MAX_ELEMENTS_INDICES
:
874 *params
= capabilities_
.max_elements_indices
;
876 case GL_MAX_ELEMENTS_VERTICES
:
877 *params
= capabilities_
.max_elements_vertices
;
879 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
880 *params
= capabilities_
.max_fragment_input_components
;
882 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
883 *params
= capabilities_
.max_fragment_uniform_blocks
;
885 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
886 *params
= capabilities_
.max_fragment_uniform_components
;
888 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
889 *params
= capabilities_
.max_program_texel_offset
;
892 *params
= capabilities_
.max_samples
;
894 case GL_MAX_SERVER_WAIT_TIMEOUT
:
895 *params
= static_cast<GLint
>(capabilities_
.max_server_wait_timeout
);
897 case GL_MAX_TEXTURE_LOD_BIAS
:
898 *params
= static_cast<GLint
>(capabilities_
.max_texture_lod_bias
);
900 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
901 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
903 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
904 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
906 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
907 *params
= capabilities_
.max_transform_feedback_separate_components
;
909 case GL_MAX_UNIFORM_BLOCK_SIZE
:
910 *params
= static_cast<GLint
>(capabilities_
.max_uniform_block_size
);
912 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
913 *params
= capabilities_
.max_uniform_buffer_bindings
;
915 case GL_MAX_VARYING_COMPONENTS
:
916 *params
= capabilities_
.max_varying_components
;
918 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
919 *params
= capabilities_
.max_vertex_output_components
;
921 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
922 *params
= capabilities_
.max_vertex_uniform_blocks
;
924 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
925 *params
= capabilities_
.max_vertex_uniform_components
;
927 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
928 *params
= capabilities_
.min_program_texel_offset
;
930 case GL_MINOR_VERSION
:
931 *params
= capabilities_
.minor_version
;
933 case GL_NUM_EXTENSIONS
:
934 *params
= capabilities_
.num_extensions
;
936 case GL_NUM_PROGRAM_BINARY_FORMATS
:
937 *params
= capabilities_
.num_program_binary_formats
;
939 case GL_PIXEL_PACK_BUFFER_BINDING
:
940 *params
= bound_pixel_pack_buffer_
;
942 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
943 *params
= bound_pixel_unpack_buffer_
;
945 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
946 *params
= bound_transform_feedback_buffer_
;
948 case GL_UNIFORM_BUFFER_BINDING
:
949 *params
= bound_uniform_buffer_
;
951 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
952 *params
= capabilities_
.uniform_buffer_offset_alignment
;
955 // Non-cached ES3 parameters.
956 case GL_DRAW_BUFFER0
:
957 case GL_DRAW_BUFFER1
:
958 case GL_DRAW_BUFFER2
:
959 case GL_DRAW_BUFFER3
:
960 case GL_DRAW_BUFFER4
:
961 case GL_DRAW_BUFFER5
:
962 case GL_DRAW_BUFFER6
:
963 case GL_DRAW_BUFFER7
:
964 case GL_DRAW_BUFFER8
:
965 case GL_DRAW_BUFFER9
:
966 case GL_DRAW_BUFFER10
:
967 case GL_DRAW_BUFFER11
:
968 case GL_DRAW_BUFFER12
:
969 case GL_DRAW_BUFFER13
:
970 case GL_DRAW_BUFFER14
:
971 case GL_DRAW_BUFFER15
:
972 case GL_DRAW_FRAMEBUFFER_BINDING
:
973 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
974 case GL_PACK_ROW_LENGTH
:
975 case GL_PACK_SKIP_PIXELS
:
976 case GL_PACK_SKIP_ROWS
:
977 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
978 case GL_PROGRAM_BINARY_FORMATS
:
979 case GL_RASTERIZER_DISCARD
:
981 case GL_READ_FRAMEBUFFER_BINDING
:
982 case GL_SAMPLER_BINDING
:
983 case GL_TEXTURE_BINDING_2D_ARRAY
:
984 case GL_TEXTURE_BINDING_3D
:
985 case GL_TRANSFORM_FEEDBACK_BINDING
:
986 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
987 case GL_TRANSFORM_FEEDBACK_PAUSED
:
988 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
989 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
990 case GL_UNIFORM_BUFFER_SIZE
:
991 case GL_UNIFORM_BUFFER_START
:
992 case GL_UNPACK_IMAGE_HEIGHT
:
993 case GL_UNPACK_ROW_LENGTH
:
994 case GL_UNPACK_SKIP_IMAGES
:
995 case GL_UNPACK_SKIP_PIXELS
:
996 case GL_UNPACK_SKIP_ROWS
:
997 case GL_VERTEX_ARRAY_BINDING
:
1004 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
1005 // TODO(gman): Make this handle pnames that return more than 1 value.
1007 if (!GetHelper(pname
, &value
)) {
1010 *params
= static_cast<GLboolean
>(value
);
1014 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
1015 // TODO(gman): Make this handle pnames that return more than 1 value.
1017 case GL_MAX_TEXTURE_LOD_BIAS
:
1018 *params
= capabilities_
.max_texture_lod_bias
;
1024 if (!GetHelper(pname
, &value
)) {
1027 *params
= static_cast<GLfloat
>(value
);
1031 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
1033 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
1034 *params
= capabilities_
.max_combined_fragment_uniform_components
;
1036 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
1037 *params
= capabilities_
.max_combined_vertex_uniform_components
;
1039 case GL_MAX_ELEMENT_INDEX
:
1040 *params
= capabilities_
.max_element_index
;
1042 case GL_MAX_SERVER_WAIT_TIMEOUT
:
1043 *params
= capabilities_
.max_server_wait_timeout
;
1045 case GL_MAX_UNIFORM_BLOCK_SIZE
:
1046 *params
= capabilities_
.max_uniform_block_size
;
1048 case GL_TIMESTAMP_EXT
:
1049 // We convert all GPU timestamps to CPU time.
1050 *params
= (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
1051 * base::Time::kNanosecondsPerMicrosecond
;
1057 if (!GetHelper(pname
, &value
)) {
1060 *params
= static_cast<GLint64
>(value
);
1064 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
1065 return GetHelper(pname
, params
);
1068 bool GLES2Implementation::GetIntegeri_vHelper(
1069 GLenum pname
, GLuint index
, GLint
* data
) {
1070 // TODO(zmo): Implement client side caching.
1074 bool GLES2Implementation::GetInteger64i_vHelper(
1075 GLenum pname
, GLuint index
, GLint64
* data
) {
1076 // TODO(zmo): Implement client side caching.
1080 bool GLES2Implementation::GetInternalformativHelper(
1081 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
1083 // TODO(zmo): Implement the client side caching.
1087 bool GLES2Implementation::GetSyncivHelper(
1088 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
1092 case GL_OBJECT_TYPE
:
1093 value
= GL_SYNC_FENCE
;
1095 case GL_SYNC_CONDITION
:
1096 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1114 bool GLES2Implementation::GetQueryObjectValueHelper(
1115 const char* function_name
, GLuint id
, GLenum pname
, GLuint64
* params
) {
1116 GPU_CLIENT_SINGLE_THREAD_CHECK();
1117 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper("
1119 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
1120 << static_cast<const void*>(params
) << ")");
1122 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
1124 SetGLError(GL_INVALID_OPERATION
,
1125 function_name
, "unknown query id");
1129 if (query
->Active()) {
1131 GL_INVALID_OPERATION
,
1133 "query active. Did you call glEndQueryEXT?");
1137 if (query
->NeverUsed()) {
1139 GL_INVALID_OPERATION
,
1140 function_name
, "Never used. Did you call glBeginQueryEXT?");
1144 bool valid_value
= false;
1146 case GL_QUERY_RESULT_EXT
:
1147 if (!query
->CheckResultsAvailable(helper_
)) {
1148 helper_
->WaitForToken(query
->token());
1149 if (!query
->CheckResultsAvailable(helper_
)) {
1151 CHECK(query
->CheckResultsAvailable(helper_
));
1154 *params
= query
->GetResult();
1157 case GL_QUERY_RESULT_AVAILABLE_EXT
:
1158 *params
= query
->CheckResultsAvailable(helper_
);
1162 SetGLErrorInvalidEnum(function_name
, pname
, "pname");
1165 GPU_CLIENT_LOG(" " << *params
);
1170 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1171 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1172 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1173 Result
* result
= GetResultAs
<Result
*>();
1178 helper_
->GetMaxValueInBufferCHROMIUM(
1179 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1184 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1185 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1186 GPU_CLIENT_SINGLE_THREAD_CHECK();
1187 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1188 << buffer_id
<< ", " << count
<< ", "
1189 << GLES2Util::GetStringGetMaxIndexType(type
)
1190 << ", " << offset
<< ")");
1191 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1192 buffer_id
, count
, type
, offset
);
1193 GPU_CLIENT_LOG("returned " << result
);
1198 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1200 RestoreArrayBuffer(restore
);
1201 // Restore the element array binding.
1202 // We only need to restore it if it wasn't a client side array.
1203 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1204 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1209 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1211 // Restore the user's current binding.
1212 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_
);
1216 void GLES2Implementation::DrawElements(
1217 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1218 GPU_CLIENT_SINGLE_THREAD_CHECK();
1219 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1220 << GLES2Util::GetStringDrawMode(mode
) << ", "
1222 << GLES2Util::GetStringIndexType(type
) << ", "
1223 << static_cast<const void*>(indices
) << ")");
1224 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1227 void GLES2Implementation::DrawRangeElements(
1228 GLenum mode
, GLuint start
, GLuint end
,
1229 GLsizei count
, GLenum type
, const void* indices
) {
1230 GPU_CLIENT_SINGLE_THREAD_CHECK();
1231 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1232 << GLES2Util::GetStringDrawMode(mode
) << ", "
1233 << start
<< ", " << end
<< ", " << count
<< ", "
1234 << GLES2Util::GetStringIndexType(type
) << ", "
1235 << static_cast<const void*>(indices
) << ")");
1237 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1240 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1243 void GLES2Implementation::DrawElementsImpl(
1244 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1245 const char* func_name
) {
1247 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1250 bool simulated
= false;
1251 GLuint offset
= ToGLuint(indices
);
1253 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1254 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1257 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1258 func_name
, this, helper_
, count
, type
, 0, indices
,
1259 &offset
, &simulated
)) {
1263 helper_
->DrawElements(mode
, count
, type
, offset
);
1264 RestoreElementAndArrayBuffers(simulated
);
1268 void GLES2Implementation::Flush() {
1269 GPU_CLIENT_SINGLE_THREAD_CHECK();
1270 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1271 // Insert the cmd to call glFlush
1276 void GLES2Implementation::ShallowFlushCHROMIUM() {
1277 GPU_CLIENT_SINGLE_THREAD_CHECK();
1278 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1282 void GLES2Implementation::FlushHelper() {
1283 // Flush our command buffer
1284 // (tell the service to execute up to the flush cmd.)
1285 helper_
->CommandBufferHelper::Flush();
1287 if (aggressively_free_resources_
)
1291 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1292 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1293 // Flush command buffer at the GPU channel level. May be implemented as
1295 helper_
->CommandBufferHelper::OrderingBarrier();
1298 void GLES2Implementation::Finish() {
1299 GPU_CLIENT_SINGLE_THREAD_CHECK();
1303 void GLES2Implementation::ShallowFinishCHROMIUM() {
1304 GPU_CLIENT_SINGLE_THREAD_CHECK();
1305 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1306 // Flush our command buffer (tell the service to execute up to the flush cmd
1307 // and don't return until it completes).
1308 helper_
->CommandBufferHelper::Finish();
1310 if (aggressively_free_resources_
)
1314 void GLES2Implementation::FinishHelper() {
1315 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1316 TRACE_EVENT0("gpu", "GLES2::Finish");
1317 // Insert the cmd to call glFinish
1319 // Finish our command buffer
1320 // (tell the service to execute up to the Finish cmd and wait for it to
1322 helper_
->CommandBufferHelper::Finish();
1324 if (aggressively_free_resources_
)
1328 void GLES2Implementation::SwapBuffers() {
1329 GPU_CLIENT_SINGLE_THREAD_CHECK();
1330 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1331 // TODO(piman): Strictly speaking we'd want to insert the token after the
1332 // swap, but the state update with the updated token might not have happened
1333 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1334 // with the GPU process more than needed. So instead, make it happen before.
1335 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1336 // semantics if the client doesn't use the callback mechanism, and by chance
1337 // the scheduler yields between the InsertToken and the SwapBuffers.
1338 swap_buffers_tokens_
.push(helper_
->InsertToken());
1339 helper_
->SwapBuffers();
1340 helper_
->CommandBufferHelper::Flush();
1341 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1342 // compensate for TODO above.
1343 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1344 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1345 swap_buffers_tokens_
.pop();
1349 void GLES2Implementation::SwapInterval(int interval
) {
1350 GPU_CLIENT_SINGLE_THREAD_CHECK();
1351 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1352 << interval
<< ")");
1353 helper_
->SwapInterval(interval
);
1356 void GLES2Implementation::BindAttribLocation(
1357 GLuint program
, GLuint index
, const char* name
) {
1358 GPU_CLIENT_SINGLE_THREAD_CHECK();
1359 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1360 << program
<< ", " << index
<< ", " << name
<< ")");
1361 SetBucketAsString(kResultBucketId
, name
);
1362 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1363 helper_
->SetBucketSize(kResultBucketId
, 0);
1367 void GLES2Implementation::BindUniformLocationCHROMIUM(
1368 GLuint program
, GLint location
, const char* name
) {
1369 GPU_CLIENT_SINGLE_THREAD_CHECK();
1370 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1371 << program
<< ", " << location
<< ", " << name
<< ")");
1372 SetBucketAsString(kResultBucketId
, name
);
1373 helper_
->BindUniformLocationCHROMIUMBucket(
1374 program
, location
, kResultBucketId
);
1375 helper_
->SetBucketSize(kResultBucketId
, 0);
1379 void GLES2Implementation::GetVertexAttribPointerv(
1380 GLuint index
, GLenum pname
, void** ptr
) {
1381 GPU_CLIENT_SINGLE_THREAD_CHECK();
1382 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1383 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1384 << static_cast<void*>(ptr
) << ")");
1385 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1386 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1387 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1388 typedef cmds::GetVertexAttribPointerv::Result Result
;
1389 Result
* result
= GetResultAs
<Result
*>();
1393 result
->SetNumResults(0);
1394 helper_
->GetVertexAttribPointerv(
1395 index
, pname
, GetResultShmId(), GetResultShmOffset());
1397 result
->CopyResult(ptr
);
1398 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1400 GPU_CLIENT_LOG_CODE_BLOCK({
1401 for (int32 i
= 0; i
< num_results
; ++i
) {
1402 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1408 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1409 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1410 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1413 "glDeleteProgram", "id not created by this context.");
1416 if (program
== current_program_
) {
1417 current_program_
= 0;
1422 void GLES2Implementation::DeleteProgramStub(
1423 GLsizei n
, const GLuint
* programs
) {
1425 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1426 helper_
->DeleteProgram(programs
[0]);
1429 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1430 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1431 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1434 "glDeleteShader", "id not created by this context.");
1440 void GLES2Implementation::DeleteShaderStub(
1441 GLsizei n
, const GLuint
* shaders
) {
1443 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1444 helper_
->DeleteShader(shaders
[0]);
1447 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1448 GLuint sync_uint
= ToGLuint(sync
);
1449 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1450 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1453 "glDeleteSync", "id not created by this context.");
1457 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1459 helper_
->DeleteSync(syncs
[0]);
1462 GLint
GLES2Implementation::GetAttribLocationHelper(
1463 GLuint program
, const char* name
) {
1464 typedef cmds::GetAttribLocation::Result Result
;
1465 Result
* result
= GetResultAs
<Result
*>();
1470 SetBucketAsCString(kResultBucketId
, name
);
1471 helper_
->GetAttribLocation(
1472 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1474 helper_
->SetBucketSize(kResultBucketId
, 0);
1478 GLint
GLES2Implementation::GetAttribLocation(
1479 GLuint program
, const char* name
) {
1480 GPU_CLIENT_SINGLE_THREAD_CHECK();
1481 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1482 << ", " << name
<< ")");
1483 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1484 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1485 this, program
, name
);
1486 GPU_CLIENT_LOG("returned " << loc
);
1491 GLint
GLES2Implementation::GetUniformLocationHelper(
1492 GLuint program
, const char* name
) {
1493 typedef cmds::GetUniformLocation::Result Result
;
1494 Result
* result
= GetResultAs
<Result
*>();
1499 SetBucketAsCString(kResultBucketId
, name
);
1500 helper_
->GetUniformLocation(program
, kResultBucketId
,
1501 GetResultShmId(), GetResultShmOffset());
1503 helper_
->SetBucketSize(kResultBucketId
, 0);
1507 GLint
GLES2Implementation::GetUniformLocation(
1508 GLuint program
, const char* name
) {
1509 GPU_CLIENT_SINGLE_THREAD_CHECK();
1510 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1511 << ", " << name
<< ")");
1512 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1513 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1514 this, program
, name
);
1515 GPU_CLIENT_LOG("returned " << loc
);
1520 bool GLES2Implementation::GetUniformIndicesHelper(
1521 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1522 typedef cmds::GetUniformIndices::Result Result
;
1523 Result
* result
= GetResultAs
<Result
*>();
1527 result
->SetNumResults(0);
1528 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1531 helper_
->GetUniformIndices(program
, kResultBucketId
,
1532 GetResultShmId(), GetResultShmOffset());
1534 if (result
->GetNumResults() != count
) {
1537 result
->CopyResult(indices
);
1541 void GLES2Implementation::GetUniformIndices(
1542 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1543 GPU_CLIENT_SINGLE_THREAD_CHECK();
1544 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1545 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1546 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1548 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1554 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1555 this, program
, count
, names
, indices
);
1557 GPU_CLIENT_LOG_CODE_BLOCK({
1558 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1559 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1566 bool GLES2Implementation::GetProgramivHelper(
1567 GLuint program
, GLenum pname
, GLint
* params
) {
1568 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1569 this, program
, pname
, params
);
1570 GPU_CLIENT_LOG_CODE_BLOCK({
1572 GPU_CLIENT_LOG(" 0: " << *params
);
1578 GLint
GLES2Implementation::GetFragDataLocationHelper(
1579 GLuint program
, const char* name
) {
1580 typedef cmds::GetFragDataLocation::Result Result
;
1581 Result
* result
= GetResultAs
<Result
*>();
1586 SetBucketAsCString(kResultBucketId
, name
);
1587 helper_
->GetFragDataLocation(
1588 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1590 helper_
->SetBucketSize(kResultBucketId
, 0);
1594 GLint
GLES2Implementation::GetFragDataLocation(
1595 GLuint program
, const char* name
) {
1596 GPU_CLIENT_SINGLE_THREAD_CHECK();
1597 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1598 << program
<< ", " << name
<< ")");
1599 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1600 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1601 this, program
, name
);
1602 GPU_CLIENT_LOG("returned " << loc
);
1607 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1608 GLuint program
, const char* name
) {
1609 typedef cmds::GetUniformBlockIndex::Result Result
;
1610 Result
* result
= GetResultAs
<Result
*>();
1612 return GL_INVALID_INDEX
;
1614 *result
= GL_INVALID_INDEX
;
1615 SetBucketAsCString(kResultBucketId
, name
);
1616 helper_
->GetUniformBlockIndex(
1617 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1619 helper_
->SetBucketSize(kResultBucketId
, 0);
1623 GLuint
GLES2Implementation::GetUniformBlockIndex(
1624 GLuint program
, const char* name
) {
1625 GPU_CLIENT_SINGLE_THREAD_CHECK();
1626 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1627 << program
<< ", " << name
<< ")");
1628 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1629 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1630 this, program
, name
);
1631 GPU_CLIENT_LOG("returned " << index
);
1636 void GLES2Implementation::LinkProgram(GLuint program
) {
1637 GPU_CLIENT_SINGLE_THREAD_CHECK();
1638 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1639 helper_
->LinkProgram(program
);
1640 share_group_
->program_info_manager()->CreateInfo(program
);
1644 void GLES2Implementation::ShaderBinary(
1645 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1647 GPU_CLIENT_SINGLE_THREAD_CHECK();
1648 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1649 << static_cast<const void*>(shaders
) << ", "
1650 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1651 << static_cast<const void*>(binary
) << ", "
1654 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1658 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1661 // TODO(gman): ShaderBinary should use buckets.
1662 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1663 ScopedTransferBufferArray
<GLint
> buffer(
1664 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1665 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1666 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1669 void* shader_ids
= buffer
.elements();
1670 void* shader_data
= buffer
.elements() + shader_id_size
;
1671 memcpy(shader_ids
, shaders
, shader_id_size
);
1672 memcpy(shader_data
, binary
, length
);
1673 helper_
->ShaderBinary(
1679 buffer
.offset() + shader_id_size
,
1684 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1685 GPU_CLIENT_SINGLE_THREAD_CHECK();
1686 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1687 << GLES2Util::GetStringPixelStore(pname
) << ", "
1690 case GL_PACK_ALIGNMENT
:
1691 pack_alignment_
= param
;
1693 case GL_UNPACK_ALIGNMENT
:
1694 unpack_alignment_
= param
;
1696 case GL_UNPACK_ROW_LENGTH_EXT
:
1697 unpack_row_length_
= param
;
1699 case GL_UNPACK_IMAGE_HEIGHT
:
1700 unpack_image_height_
= param
;
1702 case GL_UNPACK_SKIP_ROWS_EXT
:
1703 unpack_skip_rows_
= param
;
1705 case GL_UNPACK_SKIP_PIXELS_EXT
:
1706 unpack_skip_pixels_
= param
;
1708 case GL_UNPACK_SKIP_IMAGES
:
1709 unpack_skip_images_
= param
;
1711 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1712 pack_reverse_row_order_
=
1713 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1718 helper_
->PixelStorei(pname
, param
);
1722 void GLES2Implementation::VertexAttribIPointer(
1723 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1724 GPU_CLIENT_SINGLE_THREAD_CHECK();
1725 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1728 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1731 // Record the info on the client side.
1732 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1740 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1741 "client side arrays are not allowed in vertex array objects.");
1744 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1745 // Only report NON client side buffers to the service.
1746 if (!ValidateOffset("glVertexAttribIPointer",
1747 reinterpret_cast<GLintptr
>(ptr
))) {
1750 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1755 void GLES2Implementation::VertexAttribPointer(
1756 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1758 GPU_CLIENT_SINGLE_THREAD_CHECK();
1759 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1762 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1763 << GLES2Util::GetStringBool(normalized
) << ", "
1766 // Record the info on the client side.
1767 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1775 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1776 "client side arrays are not allowed in vertex array objects.");
1779 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1780 // Only report NON client side buffers to the service.
1781 if (!ValidateOffset("glVertexAttribPointer",
1782 reinterpret_cast<GLintptr
>(ptr
))) {
1785 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1791 void GLES2Implementation::VertexAttribDivisorANGLE(
1792 GLuint index
, GLuint divisor
) {
1793 GPU_CLIENT_SINGLE_THREAD_CHECK();
1794 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1796 << divisor
<< ") ");
1797 // Record the info on the client side.
1798 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1799 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1803 void GLES2Implementation::BufferDataHelper(
1804 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1805 if (!ValidateSize("glBufferData", size
))
1808 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1809 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1810 // bogus MSan report during a readback later. This is because MSan doesn't
1811 // understand shared memory and would assume we were reading back the same
1812 // unintialized data.
1813 if (data
) __msan_check_mem_is_initialized(data
, size
);
1817 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1822 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1824 RemoveTransferBuffer(buffer
);
1826 // Create new buffer.
1827 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1829 if (buffer
->address() && data
)
1830 memcpy(buffer
->address(), data
, size
);
1834 RemoveMappedBufferRangeByTarget(target
);
1836 // If there is no data just send BufferData
1837 if (size
== 0 || !data
) {
1838 helper_
->BufferData(target
, size
, 0, 0, usage
);
1842 // See if we can send all at once.
1843 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1844 if (!buffer
.valid()) {
1848 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1849 memcpy(buffer
.address(), data
, size
);
1850 helper_
->BufferData(
1859 // Make the buffer with BufferData then send via BufferSubData
1860 helper_
->BufferData(target
, size
, 0, 0, usage
);
1861 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1865 void GLES2Implementation::BufferData(
1866 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1867 GPU_CLIENT_SINGLE_THREAD_CHECK();
1868 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1869 << GLES2Util::GetStringBufferTarget(target
) << ", "
1871 << static_cast<const void*>(data
) << ", "
1872 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1873 BufferDataHelper(target
, size
, data
, usage
);
1877 void GLES2Implementation::BufferSubDataHelper(
1878 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1883 if (!ValidateSize("glBufferSubData", size
) ||
1884 !ValidateOffset("glBufferSubData", offset
)) {
1889 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1893 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1895 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1900 int32 buffer_size
= buffer
->size();
1901 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1902 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1906 if (buffer
->address() && data
)
1907 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1911 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1912 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1915 void GLES2Implementation::BufferSubDataHelperImpl(
1916 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1917 ScopedTransferBufferPtr
* buffer
) {
1921 const int8
* source
= static_cast<const int8
*>(data
);
1923 if (!buffer
->valid() || buffer
->size() == 0) {
1924 buffer
->Reset(size
);
1925 if (!buffer
->valid()) {
1929 memcpy(buffer
->address(), source
, buffer
->size());
1930 helper_
->BufferSubData(
1931 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1932 offset
+= buffer
->size();
1933 source
+= buffer
->size();
1934 size
-= buffer
->size();
1939 void GLES2Implementation::BufferSubData(
1940 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1941 GPU_CLIENT_SINGLE_THREAD_CHECK();
1942 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1943 << GLES2Util::GetStringBufferTarget(target
) << ", "
1944 << offset
<< ", " << size
<< ", "
1945 << static_cast<const void*>(data
) << ")");
1946 BufferSubDataHelper(target
, offset
, size
, data
);
1950 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1951 int32 token
= buffer
->last_usage_token();
1954 if (helper_
->HasTokenPassed(token
))
1955 buffer_tracker_
->Free(buffer
);
1957 buffer_tracker_
->FreePendingToken(buffer
, token
);
1959 buffer_tracker_
->Free(buffer
);
1962 buffer_tracker_
->RemoveBuffer(buffer
->id());
1965 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1967 const char* function_name
,
1968 GLuint
* buffer_id
) {
1972 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1973 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1975 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1976 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1983 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1988 BufferTracker::Buffer
*
1989 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1991 const char* function_name
,
1992 GLuint offset
, GLsizei size
) {
1994 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1996 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1999 if (buffer
->mapped()) {
2000 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
2003 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
2004 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
2010 void GLES2Implementation::CompressedTexImage2D(
2011 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2012 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
2013 GPU_CLIENT_SINGLE_THREAD_CHECK();
2014 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
2015 << GLES2Util::GetStringTextureTarget(target
) << ", "
2017 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2018 << width
<< ", " << height
<< ", " << border
<< ", "
2019 << image_size
<< ", "
2020 << static_cast<const void*>(data
) << ")");
2021 if (width
< 0 || height
< 0 || level
< 0) {
2022 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
2026 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
2029 if (height
== 0 || width
== 0) {
2032 // If there's a pixel unpack buffer bound use it when issuing
2033 // CompressedTexImage2D.
2034 if (bound_pixel_unpack_transfer_buffer_id_
) {
2035 GLuint offset
= ToGLuint(data
);
2036 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2037 bound_pixel_unpack_transfer_buffer_id_
,
2038 "glCompressedTexImage2D", offset
, image_size
);
2039 if (buffer
&& buffer
->shm_id() != -1) {
2040 helper_
->CompressedTexImage2D(
2041 target
, level
, internalformat
, width
, height
, image_size
,
2042 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2043 buffer
->set_last_usage_token(helper_
->InsertToken());
2047 SetBucketContents(kResultBucketId
, data
, image_size
);
2048 helper_
->CompressedTexImage2DBucket(
2049 target
, level
, internalformat
, width
, height
, kResultBucketId
);
2050 // Free the bucket. This is not required but it does free up the memory.
2051 // and we don't have to wait for the result so from the client's perspective
2053 helper_
->SetBucketSize(kResultBucketId
, 0);
2057 void GLES2Implementation::CompressedTexSubImage2D(
2058 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2059 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
2060 GPU_CLIENT_SINGLE_THREAD_CHECK();
2061 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
2062 << GLES2Util::GetStringTextureTarget(target
) << ", "
2064 << xoffset
<< ", " << yoffset
<< ", "
2065 << width
<< ", " << height
<< ", "
2066 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2067 << image_size
<< ", "
2068 << static_cast<const void*>(data
) << ")");
2069 if (width
< 0 || height
< 0 || level
< 0) {
2070 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
2073 // If there's a pixel unpack buffer bound use it when issuing
2074 // CompressedTexSubImage2D.
2075 if (bound_pixel_unpack_transfer_buffer_id_
) {
2076 GLuint offset
= ToGLuint(data
);
2077 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2078 bound_pixel_unpack_transfer_buffer_id_
,
2079 "glCompressedTexSubImage2D", offset
, image_size
);
2080 if (buffer
&& buffer
->shm_id() != -1) {
2081 helper_
->CompressedTexSubImage2D(
2082 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
2083 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2084 buffer
->set_last_usage_token(helper_
->InsertToken());
2089 SetBucketContents(kResultBucketId
, data
, image_size
);
2090 helper_
->CompressedTexSubImage2DBucket(
2091 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
2092 // Free the bucket. This is not required but it does free up the memory.
2093 // and we don't have to wait for the result so from the client's perspective
2095 helper_
->SetBucketSize(kResultBucketId
, 0);
2099 void GLES2Implementation::CompressedTexImage3D(
2100 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2101 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
2103 GPU_CLIENT_SINGLE_THREAD_CHECK();
2104 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
2105 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
2106 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2107 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2108 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
2109 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2110 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
2114 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
2117 if (height
== 0 || width
== 0 || depth
== 0) {
2120 // If there's a pixel unpack buffer bound use it when issuing
2121 // CompressedTexImage3D.
2122 if (bound_pixel_unpack_transfer_buffer_id_
) {
2123 GLuint offset
= ToGLuint(data
);
2124 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2125 bound_pixel_unpack_transfer_buffer_id_
,
2126 "glCompressedTexImage3D", offset
, image_size
);
2127 if (buffer
&& buffer
->shm_id() != -1) {
2128 helper_
->CompressedTexImage3D(
2129 target
, level
, internalformat
, width
, height
, depth
, image_size
,
2130 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2131 buffer
->set_last_usage_token(helper_
->InsertToken());
2135 SetBucketContents(kResultBucketId
, data
, image_size
);
2136 helper_
->CompressedTexImage3DBucket(
2137 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
2138 // Free the bucket. This is not required but it does free up the memory.
2139 // and we don't have to wait for the result so from the client's perspective
2141 helper_
->SetBucketSize(kResultBucketId
, 0);
2145 void GLES2Implementation::CompressedTexSubImage3D(
2146 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2147 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
2148 GLsizei image_size
, const void* data
) {
2149 GPU_CLIENT_SINGLE_THREAD_CHECK();
2150 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
2151 << GLES2Util::GetStringTextureTarget(target
) << ", "
2153 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2154 << width
<< ", " << height
<< ", " << depth
<< ", "
2155 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2156 << image_size
<< ", "
2157 << static_cast<const void*>(data
) << ")");
2158 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2159 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "dimension < 0");
2162 // If there's a pixel unpack buffer bound use it when issuing
2163 // CompressedTexSubImage3D.
2164 if (bound_pixel_unpack_transfer_buffer_id_
) {
2165 GLuint offset
= ToGLuint(data
);
2166 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2167 bound_pixel_unpack_transfer_buffer_id_
,
2168 "glCompressedTexSubImage3D", offset
, image_size
);
2169 if (buffer
&& buffer
->shm_id() != -1) {
2170 helper_
->CompressedTexSubImage3D(
2171 target
, level
, xoffset
, yoffset
, zoffset
,
2172 width
, height
, depth
, format
, image_size
,
2173 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2174 buffer
->set_last_usage_token(helper_
->InsertToken());
2179 SetBucketContents(kResultBucketId
, data
, image_size
);
2180 helper_
->CompressedTexSubImage3DBucket(
2181 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
2183 // Free the bucket. This is not required but it does free up the memory.
2184 // and we don't have to wait for the result so from the client's perspective
2186 helper_
->SetBucketSize(kResultBucketId
, 0);
2192 void CopyRectToBuffer(
2195 uint32 unpadded_row_size
,
2196 uint32 pixels_padded_row_size
,
2198 uint32 buffer_padded_row_size
) {
2199 const int8
* source
= static_cast<const int8
*>(pixels
);
2200 int8
* dest
= static_cast<int8
*>(buffer
);
2201 if (pixels_padded_row_size
!= buffer_padded_row_size
) {
2202 // the last row is copied unpadded at the end
2203 for (; height
> 1; --height
) {
2204 memcpy(dest
, source
, buffer_padded_row_size
);
2205 dest
+= buffer_padded_row_size
;
2206 source
+= pixels_padded_row_size
;
2208 memcpy(dest
, source
, unpadded_row_size
);
2210 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2211 memcpy(dest
, source
, size
);
2215 } // anonymous namespace
2217 void GLES2Implementation::TexImage2D(
2218 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2219 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2220 const void* pixels
) {
2221 GPU_CLIENT_SINGLE_THREAD_CHECK();
2222 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2223 << GLES2Util::GetStringTextureTarget(target
) << ", "
2225 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2226 << width
<< ", " << height
<< ", " << border
<< ", "
2227 << GLES2Util::GetStringTextureFormat(format
) << ", "
2228 << GLES2Util::GetStringPixelType(type
) << ", "
2229 << static_cast<const void*>(pixels
) << ")");
2230 if (level
< 0 || height
< 0 || width
< 0) {
2231 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2235 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2239 uint32 unpadded_row_size
;
2240 uint32 padded_row_size
;
2241 if (!GLES2Util::ComputeImageDataSizes(
2242 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2243 &unpadded_row_size
, &padded_row_size
)) {
2244 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2248 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2249 if (bound_pixel_unpack_transfer_buffer_id_
) {
2250 GLuint offset
= ToGLuint(pixels
);
2251 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2252 bound_pixel_unpack_transfer_buffer_id_
,
2253 "glTexImage2D", offset
, size
);
2254 if (buffer
&& buffer
->shm_id() != -1) {
2255 helper_
->TexImage2D(
2256 target
, level
, internalformat
, width
, height
, format
, type
,
2257 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2258 buffer
->set_last_usage_token(helper_
->InsertToken());
2264 // If there's no data just issue TexImage2D
2266 helper_
->TexImage2D(
2267 target
, level
, internalformat
, width
, height
, format
, type
,
2273 // compute the advance bytes per row for the src pixels
2274 uint32 src_padded_row_size
;
2275 if (unpack_row_length_
> 0) {
2276 if (!GLES2Util::ComputeImagePaddedRowSize(
2277 unpack_row_length_
, format
, type
, unpack_alignment_
,
2278 &src_padded_row_size
)) {
2280 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2284 src_padded_row_size
= padded_row_size
;
2287 // advance pixels pointer past the skip rows and skip pixels
2288 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2289 unpack_skip_rows_
* src_padded_row_size
;
2290 if (unpack_skip_pixels_
) {
2291 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2292 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2293 unpack_skip_pixels_
* group_size
;
2296 // Check if we can send it all at once.
2298 uint32_t shm_offset
= 0;
2299 void* buffer_pointer
= nullptr;
2301 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2302 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2304 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2305 shm_id
= transfer_alloc
.shm_id();
2306 shm_offset
= transfer_alloc
.offset();
2307 buffer_pointer
= transfer_alloc
.address();
2309 mapped_alloc
.Reset(size
);
2310 if (mapped_alloc
.valid()) {
2311 transfer_alloc
.Discard();
2313 mapped_alloc
.SetFlushAfterRelease(true);
2314 shm_id
= mapped_alloc
.shm_id();
2315 shm_offset
= mapped_alloc
.offset();
2316 buffer_pointer
= mapped_alloc
.address();
2320 if (buffer_pointer
) {
2322 pixels
, height
, unpadded_row_size
, src_padded_row_size
,
2323 buffer_pointer
, padded_row_size
);
2324 helper_
->TexImage2D(
2325 target
, level
, internalformat
, width
, height
, format
, type
,
2326 shm_id
, shm_offset
);
2331 // No, so send it using TexSubImage2D.
2332 helper_
->TexImage2D(
2333 target
, level
, internalformat
, width
, height
, format
, type
,
2336 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2337 pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
, padded_row_size
);
2341 void GLES2Implementation::TexImage3D(
2342 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2343 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2344 const void* pixels
) {
2345 GPU_CLIENT_SINGLE_THREAD_CHECK();
2346 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2347 << GLES2Util::GetStringTextureTarget(target
) << ", "
2349 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2350 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2351 << GLES2Util::GetStringTextureFormat(format
) << ", "
2352 << GLES2Util::GetStringPixelType(type
) << ", "
2353 << static_cast<const void*>(pixels
) << ")");
2354 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2355 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2359 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2363 uint32 unpadded_row_size
;
2364 uint32 padded_row_size
;
2365 if (!GLES2Util::ComputeImageDataSizes(
2366 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2367 &unpadded_row_size
, &padded_row_size
)) {
2368 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2372 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2373 if (bound_pixel_unpack_transfer_buffer_id_
) {
2374 GLuint offset
= ToGLuint(pixels
);
2375 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2376 bound_pixel_unpack_transfer_buffer_id_
,
2377 "glTexImage3D", offset
, size
);
2378 if (buffer
&& buffer
->shm_id() != -1) {
2379 helper_
->TexImage3D(
2380 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2381 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2382 buffer
->set_last_usage_token(helper_
->InsertToken());
2388 // If there's no data just issue TexImage3D
2390 helper_
->TexImage3D(
2391 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2397 // compute the advance bytes per row for the src pixels
2398 uint32 src_padded_row_size
;
2399 if (unpack_row_length_
> 0) {
2400 if (!GLES2Util::ComputeImagePaddedRowSize(
2401 unpack_row_length_
, format
, type
, unpack_alignment_
,
2402 &src_padded_row_size
)) {
2404 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2408 src_padded_row_size
= padded_row_size
;
2410 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2412 // advance pixels pointer past the skip images/rows/pixels
2413 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2414 unpack_skip_images_
* src_padded_row_size
* src_height
+
2415 unpack_skip_rows_
* src_padded_row_size
;
2416 if (unpack_skip_pixels_
) {
2417 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2418 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2419 unpack_skip_pixels_
* group_size
;
2422 // Check if we can send it all at once.
2424 uint32_t shm_offset
= 0;
2425 void* buffer_pointer
= nullptr;
2427 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2428 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2430 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2431 shm_id
= transfer_alloc
.shm_id();
2432 shm_offset
= transfer_alloc
.offset();
2433 buffer_pointer
= transfer_alloc
.address();
2435 mapped_alloc
.Reset(size
);
2436 if (mapped_alloc
.valid()) {
2437 transfer_alloc
.Discard();
2439 mapped_alloc
.SetFlushAfterRelease(true);
2440 shm_id
= mapped_alloc
.shm_id();
2441 shm_offset
= mapped_alloc
.offset();
2442 buffer_pointer
= mapped_alloc
.address();
2446 if (buffer_pointer
) {
2447 for (GLsizei z
= 0; z
< depth
; ++z
) {
2448 // Only the last row of the last image is unpadded.
2449 uint32 src_unpadded_row_size
=
2450 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2452 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
,
2453 buffer_pointer
, padded_row_size
);
2454 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2455 src_padded_row_size
* src_height
;
2456 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2457 padded_row_size
* height
;
2459 helper_
->TexImage3D(
2460 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2461 shm_id
, shm_offset
);
2466 // No, so send it using TexSubImage3D.
2467 helper_
->TexImage3D(
2468 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2471 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2472 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
,
2477 void GLES2Implementation::TexSubImage2D(
2478 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2479 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2480 GPU_CLIENT_SINGLE_THREAD_CHECK();
2481 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2482 << GLES2Util::GetStringTextureTarget(target
) << ", "
2484 << xoffset
<< ", " << yoffset
<< ", "
2485 << width
<< ", " << height
<< ", "
2486 << GLES2Util::GetStringTextureFormat(format
) << ", "
2487 << GLES2Util::GetStringPixelType(type
) << ", "
2488 << static_cast<const void*>(pixels
) << ")");
2490 if (level
< 0 || height
< 0 || width
< 0) {
2491 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2494 if (height
== 0 || width
== 0) {
2499 uint32 unpadded_row_size
;
2500 uint32 padded_row_size
;
2501 if (!GLES2Util::ComputeImageDataSizes(
2502 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2503 &unpadded_row_size
, &padded_row_size
)) {
2504 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2508 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2509 if (bound_pixel_unpack_transfer_buffer_id_
) {
2510 GLuint offset
= ToGLuint(pixels
);
2511 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2512 bound_pixel_unpack_transfer_buffer_id_
,
2513 "glTexSubImage2D", offset
, temp_size
);
2514 if (buffer
&& buffer
->shm_id() != -1) {
2515 helper_
->TexSubImage2D(
2516 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2517 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2518 buffer
->set_last_usage_token(helper_
->InsertToken());
2524 // compute the advance bytes per row for the src pixels
2525 uint32 src_padded_row_size
;
2526 if (unpack_row_length_
> 0) {
2527 if (!GLES2Util::ComputeImagePaddedRowSize(
2528 unpack_row_length_
, format
, type
, unpack_alignment_
,
2529 &src_padded_row_size
)) {
2531 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2535 src_padded_row_size
= padded_row_size
;
2538 // advance pixels pointer past the skip rows and skip pixels
2539 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2540 unpack_skip_rows_
* src_padded_row_size
;
2541 if (unpack_skip_pixels_
) {
2542 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2543 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2544 unpack_skip_pixels_
* group_size
;
2547 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2549 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2550 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2555 void GLES2Implementation::TexSubImage3D(
2556 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2557 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2558 const void* pixels
) {
2559 GPU_CLIENT_SINGLE_THREAD_CHECK();
2560 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2561 << GLES2Util::GetStringTextureTarget(target
) << ", "
2563 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2564 << width
<< ", " << height
<< ", " << depth
<< ", "
2565 << GLES2Util::GetStringTextureFormat(format
) << ", "
2566 << GLES2Util::GetStringPixelType(type
) << ", "
2567 << static_cast<const void*>(pixels
) << ")");
2569 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2570 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2573 if (height
== 0 || width
== 0 || depth
== 0) {
2578 uint32 unpadded_row_size
;
2579 uint32 padded_row_size
;
2580 if (!GLES2Util::ComputeImageDataSizes(
2581 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2582 &unpadded_row_size
, &padded_row_size
)) {
2583 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2587 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2588 if (bound_pixel_unpack_transfer_buffer_id_
) {
2589 GLuint offset
= ToGLuint(pixels
);
2590 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2591 bound_pixel_unpack_transfer_buffer_id_
,
2592 "glTexSubImage3D", offset
, temp_size
);
2593 if (buffer
&& buffer
->shm_id() != -1) {
2594 helper_
->TexSubImage3D(
2595 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2596 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2597 buffer
->set_last_usage_token(helper_
->InsertToken());
2603 // compute the advance bytes per row for the src pixels
2604 uint32 src_padded_row_size
;
2605 if (unpack_row_length_
> 0) {
2606 if (!GLES2Util::ComputeImagePaddedRowSize(
2607 unpack_row_length_
, format
, type
, unpack_alignment_
,
2608 &src_padded_row_size
)) {
2610 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2614 src_padded_row_size
= padded_row_size
;
2616 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2618 // advance pixels pointer past the skip images/rows/pixels
2619 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2620 unpack_skip_images_
* src_padded_row_size
* src_height
+
2621 unpack_skip_rows_
* src_padded_row_size
;
2622 if (unpack_skip_pixels_
) {
2623 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2624 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2625 unpack_skip_pixels_
* group_size
;
2628 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2630 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2631 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2632 &buffer
, padded_row_size
);
2636 static GLint
ComputeNumRowsThatFitInBuffer(
2637 uint32 padded_row_size
, uint32 unpadded_row_size
,
2638 unsigned int size
, GLsizei remaining_rows
) {
2639 DCHECK_GE(unpadded_row_size
, 0u);
2640 if (padded_row_size
== 0) {
2643 GLint num_rows
= size
/ padded_row_size
;
2644 if (num_rows
+ 1 == remaining_rows
&&
2645 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2651 void GLES2Implementation::TexSubImage2DImpl(
2652 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2653 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2654 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2655 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2657 DCHECK_GE(level
, 0);
2658 DCHECK_GT(height
, 0);
2659 DCHECK_GT(width
, 0);
2661 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2662 // Transfer by rows.
2664 unsigned int desired_size
=
2665 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2666 if (!buffer
->valid() || buffer
->size() == 0) {
2667 buffer
->Reset(desired_size
);
2668 if (!buffer
->valid()) {
2673 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2674 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2675 num_rows
= std::min(num_rows
, height
);
2677 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2678 buffer
->address(), buffer_padded_row_size
);
2679 helper_
->TexSubImage2D(
2680 target
, level
, xoffset
, yoffset
, width
, num_rows
, format
, type
,
2681 buffer
->shm_id(), buffer
->offset(), internal
);
2683 yoffset
+= num_rows
;
2684 source
+= num_rows
* pixels_padded_row_size
;
2689 void GLES2Implementation::TexSubImage3DImpl(
2690 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2691 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2692 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2693 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2694 uint32 buffer_padded_row_size
) {
2696 DCHECK_GE(level
, 0);
2697 DCHECK_GT(height
, 0);
2698 DCHECK_GT(width
, 0);
2699 DCHECK_GT(depth
, 0);
2700 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2701 GLsizei total_rows
= height
* depth
;
2702 GLint row_index
= 0, depth_index
= 0;
2703 while (total_rows
) {
2704 // Each time, we either copy one or more images, or copy one or more rows
2705 // within a single image, depending on the buffer size limit.
2707 unsigned int desired_size
;
2708 if (row_index
> 0) {
2709 // We are in the middle of an image. Send the remaining of the image.
2710 max_rows
= height
- row_index
;
2711 if (total_rows
<= height
) {
2712 // Last image, so last row is unpadded.
2713 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2716 desired_size
= buffer_padded_row_size
* max_rows
;
2719 // Send all the remaining data if possible.
2720 max_rows
= total_rows
;
2722 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2724 if (!buffer
->valid() || buffer
->size() == 0) {
2725 buffer
->Reset(desired_size
);
2726 if (!buffer
->valid()) {
2730 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2731 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2732 num_rows
= std::min(num_rows
, max_rows
);
2733 GLint num_images
= num_rows
/ height
;
2734 GLsizei my_height
, my_depth
;
2735 if (num_images
> 0) {
2736 num_rows
= num_images
* height
;
2738 my_depth
= num_images
;
2740 my_height
= num_rows
;
2744 if (num_images
> 0) {
2745 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2747 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2748 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2749 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2750 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2751 uint32 my_unpadded_row_size
;
2752 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2753 my_unpadded_row_size
= unpadded_row_size
;
2755 my_unpadded_row_size
= pixels_padded_row_size
;
2757 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2758 pixels_padded_row_size
, buffer_pointer
+ ii
* image_size_dst
,
2759 buffer_padded_row_size
);
2762 uint32 my_unpadded_row_size
;
2763 if (total_rows
== num_rows
)
2764 my_unpadded_row_size
= unpadded_row_size
;
2766 my_unpadded_row_size
= pixels_padded_row_size
;
2768 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2769 buffer
->address(), buffer_padded_row_size
);
2771 helper_
->TexSubImage3D(
2772 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2773 width
, my_height
, my_depth
,
2774 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2777 total_rows
-= num_rows
;
2778 if (total_rows
> 0) {
2779 GLint num_image_paddings
;
2780 if (num_images
> 0) {
2781 DCHECK_EQ(row_index
, 0);
2782 depth_index
+= num_images
;
2783 num_image_paddings
= num_images
;
2785 row_index
= (row_index
+ my_height
) % height
;
2786 num_image_paddings
= 0;
2787 if (my_height
> 0 && row_index
== 0) {
2789 num_image_paddings
++;
2792 source
+= num_rows
* pixels_padded_row_size
;
2793 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2794 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2795 pixels_padded_row_size
;
2801 bool GLES2Implementation::GetActiveAttribHelper(
2802 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2803 GLenum
* type
, char* name
) {
2804 // Clear the bucket so if the command fails nothing will be in it.
2805 helper_
->SetBucketSize(kResultBucketId
, 0);
2806 typedef cmds::GetActiveAttrib::Result Result
;
2807 Result
* result
= GetResultAs
<Result
*>();
2811 // Set as failed so if the command fails we'll recover.
2812 result
->success
= false;
2813 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2814 GetResultShmId(), GetResultShmOffset());
2816 if (result
->success
) {
2818 *size
= result
->size
;
2821 *type
= result
->type
;
2823 if (length
|| name
) {
2824 std::vector
<int8
> str
;
2825 GetBucketContents(kResultBucketId
, &str
);
2826 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2827 std::max(static_cast<size_t>(0),
2832 if (name
&& bufsize
> 0) {
2833 memcpy(name
, &str
[0], max_size
);
2834 name
[max_size
] = '\0';
2838 return result
->success
!= 0;
2841 void GLES2Implementation::GetActiveAttrib(
2842 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2843 GLenum
* type
, char* name
) {
2844 GPU_CLIENT_SINGLE_THREAD_CHECK();
2845 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2846 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2847 << static_cast<const void*>(length
) << ", "
2848 << static_cast<const void*>(size
) << ", "
2849 << static_cast<const void*>(type
) << ", "
2850 << static_cast<const void*>(name
) << ", ");
2852 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2855 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2856 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2857 this, program
, index
, bufsize
, length
, size
, type
, name
);
2860 GPU_CLIENT_LOG(" size: " << *size
);
2863 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2866 GPU_CLIENT_LOG(" name: " << name
);
2872 bool GLES2Implementation::GetActiveUniformHelper(
2873 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2874 GLenum
* type
, char* name
) {
2875 // Clear the bucket so if the command fails nothing will be in it.
2876 helper_
->SetBucketSize(kResultBucketId
, 0);
2877 typedef cmds::GetActiveUniform::Result Result
;
2878 Result
* result
= GetResultAs
<Result
*>();
2882 // Set as failed so if the command fails we'll recover.
2883 result
->success
= false;
2884 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2885 GetResultShmId(), GetResultShmOffset());
2887 if (result
->success
) {
2889 *size
= result
->size
;
2892 *type
= result
->type
;
2894 if (length
|| name
) {
2895 std::vector
<int8
> str
;
2896 GetBucketContents(kResultBucketId
, &str
);
2897 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2898 std::max(static_cast<size_t>(0),
2903 if (name
&& bufsize
> 0) {
2904 memcpy(name
, &str
[0], max_size
);
2905 name
[max_size
] = '\0';
2909 return result
->success
!= 0;
2912 void GLES2Implementation::GetActiveUniform(
2913 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2914 GLenum
* type
, char* name
) {
2915 GPU_CLIENT_SINGLE_THREAD_CHECK();
2916 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2917 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2918 << static_cast<const void*>(length
) << ", "
2919 << static_cast<const void*>(size
) << ", "
2920 << static_cast<const void*>(type
) << ", "
2921 << static_cast<const void*>(name
) << ", ");
2923 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2926 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2927 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2928 this, program
, index
, bufsize
, length
, size
, type
, name
);
2931 GPU_CLIENT_LOG(" size: " << *size
);
2934 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2937 GPU_CLIENT_LOG(" name: " << name
);
2943 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2944 GLuint program
, GLuint index
, GLsizei bufsize
,
2945 GLsizei
* length
, char* name
) {
2946 DCHECK_LE(0, bufsize
);
2947 // Clear the bucket so if the command fails nothing will be in it.
2948 helper_
->SetBucketSize(kResultBucketId
, 0);
2949 typedef cmds::GetActiveUniformBlockName::Result Result
;
2950 Result
* result
= GetResultAs
<Result
*>();
2954 // Set as failed so if the command fails we'll recover.
2956 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2957 GetResultShmId(), GetResultShmOffset());
2964 } else if (length
|| name
) {
2965 std::vector
<int8
> str
;
2966 GetBucketContents(kResultBucketId
, &str
);
2967 DCHECK_GT(str
.size(), 0u);
2969 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2974 memcpy(name
, &str
[0], max_size
);
2975 name
[max_size
] = '\0';
2979 return *result
!= 0;
2982 void GLES2Implementation::GetActiveUniformBlockName(
2983 GLuint program
, GLuint index
, GLsizei bufsize
,
2984 GLsizei
* length
, char* name
) {
2985 GPU_CLIENT_SINGLE_THREAD_CHECK();
2986 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2987 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2988 << static_cast<const void*>(length
) << ", "
2989 << static_cast<const void*>(name
) << ")");
2991 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2994 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2996 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2997 this, program
, index
, bufsize
, length
, name
);
3000 GPU_CLIENT_LOG(" name: " << name
);
3006 bool GLES2Implementation::GetActiveUniformBlockivHelper(
3007 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
3008 typedef cmds::GetActiveUniformBlockiv::Result Result
;
3009 Result
* result
= GetResultAs
<Result
*>();
3013 result
->SetNumResults(0);
3014 helper_
->GetActiveUniformBlockiv(
3015 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
3017 if (result
->GetNumResults() > 0) {
3019 result
->CopyResult(params
);
3021 GPU_CLIENT_LOG_CODE_BLOCK({
3022 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3023 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3031 void GLES2Implementation::GetActiveUniformBlockiv(
3032 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
3033 GPU_CLIENT_SINGLE_THREAD_CHECK();
3034 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
3035 << program
<< ", " << index
<< ", "
3036 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
3037 << static_cast<const void*>(params
) << ")");
3038 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
3040 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
3041 this, program
, index
, pname
, params
);
3044 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
3045 // be more than one value returned in params.
3046 GPU_CLIENT_LOG(" params: " << params
[0]);
3052 bool GLES2Implementation::GetActiveUniformsivHelper(
3053 GLuint program
, GLsizei count
, const GLuint
* indices
,
3054 GLenum pname
, GLint
* params
) {
3055 typedef cmds::GetActiveUniformsiv::Result Result
;
3056 Result
* result
= GetResultAs
<Result
*>();
3060 result
->SetNumResults(0);
3061 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
3062 bytes
*= sizeof(GLuint
);
3063 if (!bytes
.IsValid()) {
3064 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
3067 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
3068 helper_
->GetActiveUniformsiv(
3069 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
3071 bool success
= result
->GetNumResults() == count
;
3074 result
->CopyResult(params
);
3076 GPU_CLIENT_LOG_CODE_BLOCK({
3077 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3078 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3082 helper_
->SetBucketSize(kResultBucketId
, 0);
3086 void GLES2Implementation::GetActiveUniformsiv(
3087 GLuint program
, GLsizei count
, const GLuint
* indices
,
3088 GLenum pname
, GLint
* params
) {
3089 GPU_CLIENT_SINGLE_THREAD_CHECK();
3090 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
3091 << program
<< ", " << count
<< ", "
3092 << static_cast<const void*>(indices
) << ", "
3093 << GLES2Util::GetStringUniformParameter(pname
) << ", "
3094 << static_cast<const void*>(params
) << ")");
3095 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
3097 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
3100 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
3101 this, program
, count
, indices
, pname
, params
);
3104 GPU_CLIENT_LOG_CODE_BLOCK({
3105 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
3106 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
3114 void GLES2Implementation::GetAttachedShaders(
3115 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
3116 GPU_CLIENT_SINGLE_THREAD_CHECK();
3117 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
3118 << program
<< ", " << maxcount
<< ", "
3119 << static_cast<const void*>(count
) << ", "
3120 << static_cast<const void*>(shaders
) << ", ");
3122 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
3125 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
3126 typedef cmds::GetAttachedShaders::Result Result
;
3127 uint32 size
= Result::ComputeSize(maxcount
);
3128 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
3132 result
->SetNumResults(0);
3133 helper_
->GetAttachedShaders(
3135 transfer_buffer_
->GetShmId(),
3136 transfer_buffer_
->GetOffset(result
),
3138 int32 token
= helper_
->InsertToken();
3141 *count
= result
->GetNumResults();
3143 result
->CopyResult(shaders
);
3144 GPU_CLIENT_LOG_CODE_BLOCK({
3145 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3146 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3149 transfer_buffer_
->FreePendingToken(result
, token
);
3153 void GLES2Implementation::GetShaderPrecisionFormat(
3154 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
3155 GPU_CLIENT_SINGLE_THREAD_CHECK();
3156 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
3157 << GLES2Util::GetStringShaderType(shadertype
) << ", "
3158 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
3159 << static_cast<const void*>(range
) << ", "
3160 << static_cast<const void*>(precision
) << ", ");
3161 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
3162 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3163 Result
* result
= GetResultAs
<Result
*>();
3168 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
3169 GLStaticState::ShaderPrecisionMap::iterator i
=
3170 static_state_
.shader_precisions
.find(key
);
3171 if (i
!= static_state_
.shader_precisions
.end()) {
3172 *result
= i
->second
;
3174 result
->success
= false;
3175 helper_
->GetShaderPrecisionFormat(
3176 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
3178 if (result
->success
)
3179 static_state_
.shader_precisions
[key
] = *result
;
3182 if (result
->success
) {
3184 range
[0] = result
->min_range
;
3185 range
[1] = result
->max_range
;
3186 GPU_CLIENT_LOG(" min_range: " << range
[0]);
3187 GPU_CLIENT_LOG(" min_range: " << range
[1]);
3190 precision
[0] = result
->precision
;
3191 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
3197 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
3198 const char* result
= NULL
;
3199 // Clears the bucket so if the command fails nothing will be in it.
3200 helper_
->SetBucketSize(kResultBucketId
, 0);
3201 helper_
->GetString(name
, kResultBucketId
);
3203 if (GetBucketAsString(kResultBucketId
, &str
)) {
3204 // Adds extensions implemented on client side only.
3207 str
+= std::string(str
.empty() ? "" : " ") +
3208 "GL_EXT_unpack_subimage "
3209 "GL_CHROMIUM_map_sub";
3210 if (capabilities_
.image
)
3211 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
3212 if (capabilities_
.future_sync_points
)
3213 str
+= " GL_CHROMIUM_future_sync_point";
3219 // Because of WebGL the extensions can change. We have to cache each unique
3220 // result since we don't know when the client will stop referring to a
3221 // previous one it queries.
3222 GLStringMap::iterator it
= gl_strings_
.find(name
);
3223 if (it
== gl_strings_
.end()) {
3224 std::set
<std::string
> strings
;
3225 std::pair
<GLStringMap::iterator
, bool> insert_result
=
3226 gl_strings_
.insert(std::make_pair(name
, strings
));
3227 DCHECK(insert_result
.second
);
3228 it
= insert_result
.first
;
3230 std::set
<std::string
>& string_set
= it
->second
;
3231 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
3232 if (sit
!= string_set
.end()) {
3233 result
= sit
->c_str();
3235 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3236 string_set
.insert(str
);
3237 DCHECK(insert_result
.second
);
3238 result
= insert_result
.first
->c_str();
3241 return reinterpret_cast<const GLubyte
*>(result
);
3244 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3245 GPU_CLIENT_SINGLE_THREAD_CHECK();
3246 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3247 << GLES2Util::GetStringStringType(name
) << ")");
3248 TRACE_EVENT0("gpu", "GLES2::GetString");
3249 const GLubyte
* result
= GetStringHelper(name
);
3250 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3255 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3256 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3257 GLenum
* type
, char* name
) {
3258 // Clear the bucket so if the command fails nothing will be in it.
3259 helper_
->SetBucketSize(kResultBucketId
, 0);
3260 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3261 Result
* result
= GetResultAs
<Result
*>();
3265 // Set as failed so if the command fails we'll recover.
3266 result
->success
= false;
3267 helper_
->GetTransformFeedbackVarying(
3268 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3270 if (result
->success
) {
3272 *size
= result
->size
;
3275 *type
= result
->type
;
3277 if (length
|| name
) {
3278 std::vector
<int8
> str
;
3279 GetBucketContents(kResultBucketId
, &str
);
3280 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3289 memcpy(name
, &str
[0], max_size
);
3290 name
[max_size
] = '\0';
3291 } else if (bufsize
> 0) {
3297 return result
->success
!= 0;
3300 void GLES2Implementation::GetTransformFeedbackVarying(
3301 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3302 GLenum
* type
, char* name
) {
3303 GPU_CLIENT_SINGLE_THREAD_CHECK();
3304 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3305 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3306 << static_cast<const void*>(length
) << ", "
3307 << static_cast<const void*>(size
) << ", "
3308 << static_cast<const void*>(type
) << ", "
3309 << static_cast<const void*>(name
) << ", ");
3311 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3315 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3317 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3318 this, program
, index
, bufsize
, length
, size
, type
, name
);
3321 GPU_CLIENT_LOG(" size: " << *size
);
3324 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3327 GPU_CLIENT_LOG(" name: " << name
);
3333 void GLES2Implementation::GetUniformfv(
3334 GLuint program
, GLint location
, GLfloat
* params
) {
3335 GPU_CLIENT_SINGLE_THREAD_CHECK();
3336 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3337 << program
<< ", " << location
<< ", "
3338 << static_cast<const void*>(params
) << ")");
3339 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3340 typedef cmds::GetUniformfv::Result Result
;
3341 Result
* result
= GetResultAs
<Result
*>();
3345 result
->SetNumResults(0);
3346 helper_
->GetUniformfv(
3347 program
, location
, GetResultShmId(), GetResultShmOffset());
3349 result
->CopyResult(params
);
3350 GPU_CLIENT_LOG_CODE_BLOCK({
3351 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3352 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3358 void GLES2Implementation::GetUniformiv(
3359 GLuint program
, GLint location
, GLint
* params
) {
3360 GPU_CLIENT_SINGLE_THREAD_CHECK();
3361 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3362 << program
<< ", " << location
<< ", "
3363 << static_cast<const void*>(params
) << ")");
3364 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3365 typedef cmds::GetUniformiv::Result Result
;
3366 Result
* result
= GetResultAs
<Result
*>();
3370 result
->SetNumResults(0);
3371 helper_
->GetUniformiv(
3372 program
, location
, GetResultShmId(), GetResultShmOffset());
3374 GetResultAs
<cmds::GetUniformiv::Result
*>()->CopyResult(params
);
3375 GPU_CLIENT_LOG_CODE_BLOCK({
3376 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3377 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3383 void GLES2Implementation::GetUniformuiv(
3384 GLuint program
, GLint location
, GLuint
* params
) {
3385 GPU_CLIENT_SINGLE_THREAD_CHECK();
3386 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv("
3387 << program
<< ", " << location
<< ", "
3388 << static_cast<const void*>(params
) << ")");
3389 TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
3390 typedef cmds::GetUniformuiv::Result Result
;
3391 Result
* result
= GetResultAs
<Result
*>();
3395 result
->SetNumResults(0);
3396 helper_
->GetUniformuiv(
3397 program
, location
, GetResultShmId(), GetResultShmOffset());
3399 GetResultAs
<cmds::GetUniformuiv::Result
*>()->CopyResult(params
);
3400 GPU_CLIENT_LOG_CODE_BLOCK({
3401 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3402 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3408 void GLES2Implementation::ReadPixels(
3409 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3410 GLenum type
, void* pixels
) {
3411 GPU_CLIENT_SINGLE_THREAD_CHECK();
3412 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3413 << xoffset
<< ", " << yoffset
<< ", "
3414 << width
<< ", " << height
<< ", "
3415 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3416 << GLES2Util::GetStringPixelType(type
) << ", "
3417 << static_cast<const void*>(pixels
) << ")");
3418 if (width
< 0 || height
< 0) {
3419 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3422 if (width
== 0 || height
== 0) {
3426 // glReadPixel pads the size of each row of pixels by an amount specified by
3427 // glPixelStorei. So, we have to take that into account both in the fact that
3428 // the pixels returned from the ReadPixel command will include that padding
3429 // and that when we copy the results to the user's buffer we need to not
3430 // write those padding bytes but leave them as they are.
3432 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3433 typedef cmds::ReadPixels::Result Result
;
3435 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3437 uint32 unpadded_row_size
;
3438 uint32 padded_row_size
;
3439 if (!GLES2Util::ComputeImageDataSizes(
3440 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3441 &unpadded_row_size
, &padded_row_size
)) {
3442 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3446 if (bound_pixel_pack_transfer_buffer_id_
) {
3447 GLuint offset
= ToGLuint(pixels
);
3448 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3449 bound_pixel_pack_transfer_buffer_id_
,
3450 "glReadPixels", offset
, padded_row_size
* height
);
3451 if (buffer
&& buffer
->shm_id() != -1) {
3452 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3453 buffer
->shm_id(), buffer
->shm_offset(),
3461 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3465 // Transfer by rows.
3466 // The max rows we can transfer.
3468 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3469 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3470 if (!buffer
.valid()) {
3473 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3474 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3475 num_rows
= std::min(num_rows
, height
);
3476 // NOTE: We must look up the address of the result area AFTER allocation
3477 // of the transfer buffer since the transfer buffer may be reallocated.
3478 Result
* result
= GetResultAs
<Result
*>();
3482 *result
= 0; // mark as failed.
3483 helper_
->ReadPixels(
3484 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3485 buffer
.shm_id(), buffer
.offset(),
3486 GetResultShmId(), GetResultShmOffset(),
3490 // when doing a y-flip we have to iterate through top-to-bottom chunks
3491 // of the dst. The service side handles reversing the rows within a
3494 if (pack_reverse_row_order_
) {
3495 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3499 // We have to copy 1 row at a time to avoid writing pad bytes.
3500 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3501 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3502 memcpy(rows_dst
, src
, unpadded_row_size
);
3503 rows_dst
+= padded_row_size
;
3504 src
+= padded_row_size
;
3506 if (!pack_reverse_row_order_
) {
3510 // If it was not marked as successful exit.
3514 yoffset
+= num_rows
;
3520 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3521 GPU_CLIENT_SINGLE_THREAD_CHECK();
3522 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3523 << GLES2Util::GetStringEnum(texture
) << ")");
3524 GLuint texture_index
= texture
- GL_TEXTURE0
;
3525 if (texture_index
>=
3526 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3527 SetGLErrorInvalidEnum(
3528 "glActiveTexture", texture
, "texture");
3532 active_texture_unit_
= texture_index
;
3533 helper_
->ActiveTexture(texture
);
3537 void GLES2Implementation::GenBuffersHelper(
3538 GLsizei
/* n */, const GLuint
* /* buffers */) {
3541 void GLES2Implementation::GenFramebuffersHelper(
3542 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3545 void GLES2Implementation::GenRenderbuffersHelper(
3546 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3549 void GLES2Implementation::GenTexturesHelper(
3550 GLsizei
/* n */, const GLuint
* /* textures */) {
3553 void GLES2Implementation::GenVertexArraysOESHelper(
3554 GLsizei n
, const GLuint
* arrays
) {
3555 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3558 void GLES2Implementation::GenQueriesEXTHelper(
3559 GLsizei
/* n */, const GLuint
* /* queries */) {
3562 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3564 const GLuint
* /* valuebuffers */) {
3567 void GLES2Implementation::GenSamplersHelper(
3568 GLsizei
/* n */, const GLuint
* /* samplers */) {
3571 void GLES2Implementation::GenTransformFeedbacksHelper(
3572 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3575 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3576 // generates a new resource. On newer versions of OpenGL they don't. The code
3577 // related to binding below will need to change if we switch to the new OpenGL
3578 // model. Specifically it assumes a bind will succeed which is always true in
3579 // the old model but possibly not true in the new model if another context has
3580 // deleted the resource.
3582 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3583 // used even when Bind has failed. However, the bug is minor compared to the
3584 // overhead & duplicated checking in client side.
3586 void GLES2Implementation::BindBufferHelper(
3587 GLenum target
, GLuint buffer_id
) {
3588 // TODO(gman): See note #1 above.
3589 bool changed
= false;
3591 case GL_ARRAY_BUFFER
:
3592 if (bound_array_buffer_
!= buffer_id
) {
3593 bound_array_buffer_
= buffer_id
;
3597 case GL_COPY_READ_BUFFER
:
3598 if (bound_copy_read_buffer_
!= buffer_id
) {
3599 bound_copy_read_buffer_
= buffer_id
;
3603 case GL_COPY_WRITE_BUFFER
:
3604 if (bound_copy_write_buffer_
!= buffer_id
) {
3605 bound_copy_write_buffer_
= buffer_id
;
3609 case GL_ELEMENT_ARRAY_BUFFER
:
3610 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3612 case GL_PIXEL_PACK_BUFFER
:
3613 if (bound_pixel_pack_buffer_
!= buffer_id
) {
3614 bound_pixel_pack_buffer_
= buffer_id
;
3618 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3619 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3621 case GL_PIXEL_UNPACK_BUFFER
:
3622 if (bound_pixel_unpack_buffer_
!= buffer_id
) {
3623 bound_pixel_unpack_buffer_
= buffer_id
;
3627 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3628 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3630 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3631 if (bound_transform_feedback_buffer_
!= buffer_id
) {
3632 bound_transform_feedback_buffer_
= buffer_id
;
3636 case GL_UNIFORM_BUFFER
:
3637 if (bound_uniform_buffer_
!= buffer_id
) {
3638 bound_uniform_buffer_
= buffer_id
;
3646 // TODO(gman): See note #2 above.
3648 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3649 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3653 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3654 helper_
->BindBuffer(target
, buffer
);
3655 if (share_group_
->bind_generates_resource())
3656 helper_
->CommandBufferHelper::OrderingBarrier();
3659 void GLES2Implementation::BindBufferBaseHelper(
3660 GLenum target
, GLuint index
, GLuint buffer_id
) {
3661 // TODO(zmo): See note #1 above.
3662 // TODO(zmo): See note #2 above.
3663 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3664 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3667 void GLES2Implementation::BindBufferBaseStub(
3668 GLenum target
, GLuint index
, GLuint buffer
) {
3669 helper_
->BindBufferBase(target
, index
, buffer
);
3670 if (share_group_
->bind_generates_resource())
3671 helper_
->CommandBufferHelper::Flush();
3674 void GLES2Implementation::BindBufferRangeHelper(
3675 GLenum target
, GLuint index
, GLuint buffer_id
,
3676 GLintptr offset
, GLsizeiptr size
) {
3677 // TODO(zmo): See note #1 above.
3678 // TODO(zmo): See note #2 above.
3679 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3680 this, target
, index
, buffer_id
, offset
, size
,
3681 &GLES2Implementation::BindBufferRangeStub
);
3684 void GLES2Implementation::BindBufferRangeStub(
3685 GLenum target
, GLuint index
, GLuint buffer
,
3686 GLintptr offset
, GLsizeiptr size
) {
3687 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3688 if (share_group_
->bind_generates_resource())
3689 helper_
->CommandBufferHelper::Flush();
3692 void GLES2Implementation::BindFramebufferHelper(
3693 GLenum target
, GLuint framebuffer
) {
3694 // TODO(gman): See note #1 above.
3695 bool changed
= false;
3697 case GL_FRAMEBUFFER
:
3698 if (bound_framebuffer_
!= framebuffer
||
3699 bound_read_framebuffer_
!= framebuffer
) {
3700 bound_framebuffer_
= framebuffer
;
3701 bound_read_framebuffer_
= framebuffer
;
3705 case GL_READ_FRAMEBUFFER
:
3706 if (!IsChromiumFramebufferMultisampleAvailable()) {
3707 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3710 if (bound_read_framebuffer_
!= framebuffer
) {
3711 bound_read_framebuffer_
= framebuffer
;
3715 case GL_DRAW_FRAMEBUFFER
:
3716 if (!IsChromiumFramebufferMultisampleAvailable()) {
3717 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3720 if (bound_framebuffer_
!= framebuffer
) {
3721 bound_framebuffer_
= framebuffer
;
3726 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3731 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3732 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3736 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3737 GLuint framebuffer
) {
3738 helper_
->BindFramebuffer(target
, framebuffer
);
3739 if (share_group_
->bind_generates_resource())
3740 helper_
->CommandBufferHelper::OrderingBarrier();
3743 void GLES2Implementation::BindRenderbufferHelper(
3744 GLenum target
, GLuint renderbuffer
) {
3745 // TODO(gman): See note #1 above.
3746 bool changed
= false;
3748 case GL_RENDERBUFFER
:
3749 if (bound_renderbuffer_
!= renderbuffer
) {
3750 bound_renderbuffer_
= renderbuffer
;
3758 // TODO(zmo): See note #2 above.
3760 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3761 this, target
, renderbuffer
,
3762 &GLES2Implementation::BindRenderbufferStub
);
3766 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3767 GLuint renderbuffer
) {
3768 helper_
->BindRenderbuffer(target
, renderbuffer
);
3769 if (share_group_
->bind_generates_resource())
3770 helper_
->CommandBufferHelper::OrderingBarrier();
3773 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3775 helper_
->BindSampler(unit
, sampler
);
3778 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3779 // TODO(gman): See note #1 above.
3780 // TODO(gman): Change this to false once we figure out why it's failing
3782 bool changed
= true;
3783 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3786 if (unit
.bound_texture_2d
!= texture
) {
3787 unit
.bound_texture_2d
= texture
;
3791 case GL_TEXTURE_CUBE_MAP
:
3792 if (unit
.bound_texture_cube_map
!= texture
) {
3793 unit
.bound_texture_cube_map
= texture
;
3797 case GL_TEXTURE_EXTERNAL_OES
:
3798 if (unit
.bound_texture_external_oes
!= texture
) {
3799 unit
.bound_texture_external_oes
= texture
;
3807 // TODO(gman): See note #2 above.
3809 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3810 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3814 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3815 helper_
->BindTexture(target
, texture
);
3816 if (share_group_
->bind_generates_resource())
3817 helper_
->CommandBufferHelper::OrderingBarrier();
3820 void GLES2Implementation::BindTransformFeedbackHelper(
3821 GLenum target
, GLuint transformfeedback
) {
3822 helper_
->BindTransformFeedback(target
, transformfeedback
);
3825 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3826 bool changed
= false;
3827 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3829 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3830 // because unlike other resources VertexArrayObject ids must
3831 // be generated by GenVertexArrays. A random id to Bind will not
3832 // generate a new object.
3833 helper_
->BindVertexArrayOES(array
);
3837 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3838 "id was not generated with glGenVertexArrayOES");
3842 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3843 GLuint valuebuffer
) {
3844 bool changed
= false;
3846 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3847 if (bound_valuebuffer_
!= valuebuffer
) {
3848 bound_valuebuffer_
= valuebuffer
;
3856 // TODO(gman): See note #2 above.
3858 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3859 this, target
, valuebuffer
,
3860 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3864 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3865 GLuint valuebuffer
) {
3866 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3867 if (share_group_
->bind_generates_resource())
3868 helper_
->CommandBufferHelper::OrderingBarrier();
3871 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3872 if (current_program_
!= program
) {
3873 current_program_
= program
;
3874 helper_
->UseProgram(program
);
3878 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3879 return vertex_array_object_manager_
->IsReservedId(id
);
3882 void GLES2Implementation::DeleteBuffersHelper(
3883 GLsizei n
, const GLuint
* buffers
) {
3884 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3885 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3888 "glDeleteBuffers", "id not created by this context.");
3891 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3892 if (buffers
[ii
] == bound_array_buffer_
) {
3893 bound_array_buffer_
= 0;
3895 if (buffers
[ii
] == bound_copy_read_buffer_
) {
3896 bound_copy_read_buffer_
= 0;
3898 if (buffers
[ii
] == bound_copy_write_buffer_
) {
3899 bound_copy_write_buffer_
= 0;
3901 if (buffers
[ii
] == bound_pixel_pack_buffer_
) {
3902 bound_pixel_pack_buffer_
= 0;
3904 if (buffers
[ii
] == bound_pixel_unpack_buffer_
) {
3905 bound_pixel_unpack_buffer_
= 0;
3907 if (buffers
[ii
] == bound_transform_feedback_buffer_
) {
3908 bound_transform_feedback_buffer_
= 0;
3910 if (buffers
[ii
] == bound_uniform_buffer_
) {
3911 bound_uniform_buffer_
= 0;
3913 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3915 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3917 RemoveTransferBuffer(buffer
);
3919 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3920 bound_pixel_unpack_transfer_buffer_id_
= 0;
3923 RemoveMappedBufferRangeById(buffers
[ii
]);
3927 void GLES2Implementation::DeleteBuffersStub(
3928 GLsizei n
, const GLuint
* buffers
) {
3929 helper_
->DeleteBuffersImmediate(n
, buffers
);
3933 void GLES2Implementation::DeleteFramebuffersHelper(
3934 GLsizei n
, const GLuint
* framebuffers
) {
3935 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3936 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3939 "glDeleteFramebuffers", "id not created by this context.");
3942 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3943 if (framebuffers
[ii
] == bound_framebuffer_
) {
3944 bound_framebuffer_
= 0;
3946 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3947 bound_read_framebuffer_
= 0;
3952 void GLES2Implementation::DeleteFramebuffersStub(
3953 GLsizei n
, const GLuint
* framebuffers
) {
3954 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3957 void GLES2Implementation::DeleteRenderbuffersHelper(
3958 GLsizei n
, const GLuint
* renderbuffers
) {
3959 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3960 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3963 "glDeleteRenderbuffers", "id not created by this context.");
3966 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3967 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3968 bound_renderbuffer_
= 0;
3973 void GLES2Implementation::DeleteRenderbuffersStub(
3974 GLsizei n
, const GLuint
* renderbuffers
) {
3975 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3978 void GLES2Implementation::DeleteTexturesHelper(
3979 GLsizei n
, const GLuint
* textures
) {
3980 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3981 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3984 "glDeleteTextures", "id not created by this context.");
3987 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3988 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3990 TextureUnit
& unit
= texture_units_
[tt
];
3991 if (textures
[ii
] == unit
.bound_texture_2d
) {
3992 unit
.bound_texture_2d
= 0;
3994 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3995 unit
.bound_texture_cube_map
= 0;
3997 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3998 unit
.bound_texture_external_oes
= 0;
4004 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
4005 const GLuint
* textures
) {
4006 helper_
->DeleteTexturesImmediate(n
, textures
);
4009 void GLES2Implementation::DeleteVertexArraysOESHelper(
4010 GLsizei n
, const GLuint
* arrays
) {
4011 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
4012 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
4013 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
4016 "glDeleteVertexArraysOES", "id not created by this context.");
4021 void GLES2Implementation::DeleteVertexArraysOESStub(
4022 GLsizei n
, const GLuint
* arrays
) {
4023 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
4026 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
4028 const GLuint
* valuebuffers
) {
4029 if (!GetIdHandler(id_namespaces::kValuebuffers
)
4030 ->FreeIds(this, n
, valuebuffers
,
4031 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
4032 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
4033 "id not created by this context.");
4036 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4037 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
4038 bound_valuebuffer_
= 0;
4043 void GLES2Implementation::DeleteSamplersStub(
4044 GLsizei n
, const GLuint
* samplers
) {
4045 helper_
->DeleteSamplersImmediate(n
, samplers
);
4048 void GLES2Implementation::DeleteSamplersHelper(
4049 GLsizei n
, const GLuint
* samplers
) {
4050 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
4051 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
4054 "glDeleteSamplers", "id not created by this context.");
4059 void GLES2Implementation::DeleteTransformFeedbacksStub(
4060 GLsizei n
, const GLuint
* transformfeedbacks
) {
4061 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
4064 void GLES2Implementation::DeleteTransformFeedbacksHelper(
4065 GLsizei n
, const GLuint
* transformfeedbacks
) {
4066 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
4067 this, n
, transformfeedbacks
,
4068 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
4071 "glDeleteTransformFeedbacks", "id not created by this context.");
4076 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
4078 const GLuint
* valuebuffers
) {
4079 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
4082 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
4083 GPU_CLIENT_SINGLE_THREAD_CHECK();
4085 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
4086 vertex_array_object_manager_
->SetAttribEnable(index
, false);
4087 helper_
->DisableVertexAttribArray(index
);
4091 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
4092 GPU_CLIENT_SINGLE_THREAD_CHECK();
4093 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
4095 vertex_array_object_manager_
->SetAttribEnable(index
, true);
4096 helper_
->EnableVertexAttribArray(index
);
4100 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
4101 GPU_CLIENT_SINGLE_THREAD_CHECK();
4102 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
4103 << GLES2Util::GetStringDrawMode(mode
) << ", "
4104 << first
<< ", " << count
<< ")");
4106 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
4109 bool simulated
= false;
4110 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4111 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
4114 helper_
->DrawArrays(mode
, first
, count
);
4115 RestoreArrayBuffer(simulated
);
4119 void GLES2Implementation::GetVertexAttribfv(
4120 GLuint index
, GLenum pname
, GLfloat
* params
) {
4121 GPU_CLIENT_SINGLE_THREAD_CHECK();
4122 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
4124 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4125 << static_cast<const void*>(params
) << ")");
4127 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4128 *params
= static_cast<GLfloat
>(value
);
4131 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
4132 typedef cmds::GetVertexAttribfv::Result Result
;
4133 Result
* result
= GetResultAs
<Result
*>();
4137 result
->SetNumResults(0);
4138 helper_
->GetVertexAttribfv(
4139 index
, pname
, GetResultShmId(), GetResultShmOffset());
4141 result
->CopyResult(params
);
4142 GPU_CLIENT_LOG_CODE_BLOCK({
4143 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4144 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4150 void GLES2Implementation::GetVertexAttribiv(
4151 GLuint index
, GLenum pname
, GLint
* params
) {
4152 GPU_CLIENT_SINGLE_THREAD_CHECK();
4153 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
4155 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4156 << static_cast<const void*>(params
) << ")");
4158 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4159 *params
= static_cast<GLint
>(value
);
4162 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
4163 typedef cmds::GetVertexAttribiv::Result Result
;
4164 Result
* result
= GetResultAs
<Result
*>();
4168 result
->SetNumResults(0);
4169 helper_
->GetVertexAttribiv(
4170 index
, pname
, GetResultShmId(), GetResultShmOffset());
4172 result
->CopyResult(params
);
4173 GPU_CLIENT_LOG_CODE_BLOCK({
4174 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4175 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4181 void GLES2Implementation::GetVertexAttribIiv(
4182 GLuint index
, GLenum pname
, GLint
* params
) {
4183 GPU_CLIENT_SINGLE_THREAD_CHECK();
4184 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv("
4186 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4187 << static_cast<const void*>(params
) << ")");
4189 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4190 *params
= static_cast<GLint
>(value
);
4193 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
4194 typedef cmds::GetVertexAttribiv::Result Result
;
4195 Result
* result
= GetResultAs
<Result
*>();
4199 result
->SetNumResults(0);
4200 helper_
->GetVertexAttribIiv(
4201 index
, pname
, GetResultShmId(), GetResultShmOffset());
4203 result
->CopyResult(params
);
4204 GPU_CLIENT_LOG_CODE_BLOCK({
4205 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4206 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4212 void GLES2Implementation::GetVertexAttribIuiv(
4213 GLuint index
, GLenum pname
, GLuint
* params
) {
4214 GPU_CLIENT_SINGLE_THREAD_CHECK();
4215 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv("
4217 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4218 << static_cast<const void*>(params
) << ")");
4220 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4221 *params
= static_cast<GLuint
>(value
);
4224 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
4225 typedef cmds::GetVertexAttribiv::Result Result
;
4226 Result
* result
= GetResultAs
<Result
*>();
4230 result
->SetNumResults(0);
4231 helper_
->GetVertexAttribIuiv(
4232 index
, pname
, GetResultShmId(), GetResultShmOffset());
4234 result
->CopyResult(params
);
4235 GPU_CLIENT_LOG_CODE_BLOCK({
4236 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4237 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4243 GLenum
GLES2Implementation::GetGraphicsResetStatusKHR() {
4244 GPU_CLIENT_SINGLE_THREAD_CHECK();
4245 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");
4246 // If we can't make command buffers then the context is lost.
4247 if (gpu_control_
->IsGpuChannelLost())
4248 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4249 // Otherwise, check the command buffer if it is lost.
4250 if (helper_
->IsContextLost()) {
4251 // TODO(danakj): We could GetLastState() off the CommandBuffer and return
4252 // the actual reason here if we cared to.
4253 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4258 void GLES2Implementation::Swap() {
4262 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
4263 PostSubBufferCHROMIUM(
4264 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
4267 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
4268 switch (plane_transform
) {
4269 case gfx::OVERLAY_TRANSFORM_INVALID
:
4271 case gfx::OVERLAY_TRANSFORM_NONE
:
4272 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4273 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
4274 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
4275 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
4276 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
4277 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
4278 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
4279 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
4280 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
4281 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
4282 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
4285 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4288 void GLES2Implementation::ScheduleOverlayPlane(
4290 gfx::OverlayTransform plane_transform
,
4291 unsigned overlay_texture_id
,
4292 const gfx::Rect
& display_bounds
,
4293 const gfx::RectF
& uv_rect
) {
4294 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
4295 GetGLESOverlayTransform(plane_transform
),
4299 display_bounds
.width(),
4300 display_bounds
.height(),
4307 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
4308 const char* feature
) {
4309 GPU_CLIENT_SINGLE_THREAD_CHECK();
4310 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
4312 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
4313 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
4314 Result
* result
= GetResultAs
<Result
*>();
4319 SetBucketAsCString(kResultBucketId
, feature
);
4320 helper_
->EnableFeatureCHROMIUM(
4321 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
4323 helper_
->SetBucketSize(kResultBucketId
, 0);
4324 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
4325 return *result
!= 0;
4328 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
4329 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
4330 GPU_CLIENT_SINGLE_THREAD_CHECK();
4331 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
4332 << target
<< ", " << offset
<< ", " << size
<< ", "
4333 << GLES2Util::GetStringEnum(access
) << ")");
4334 // NOTE: target is NOT checked because the service will check it
4335 // and we don't know what targets are valid.
4336 if (access
!= GL_WRITE_ONLY
) {
4337 SetGLErrorInvalidEnum(
4338 "glMapBufferSubDataCHROMIUM", access
, "access");
4341 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
4342 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
4347 unsigned int shm_offset
;
4348 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4350 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
4354 std::pair
<MappedBufferMap::iterator
, bool> result
=
4355 mapped_buffers_
.insert(std::make_pair(
4358 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4359 DCHECK(result
.second
);
4360 GPU_CLIENT_LOG(" returned " << mem
);
4364 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
4365 GPU_CLIENT_SINGLE_THREAD_CHECK();
4367 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
4368 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
4369 if (it
== mapped_buffers_
.end()) {
4371 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
4374 const MappedBuffer
& mb
= it
->second
;
4375 helper_
->BufferSubData(
4376 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
4377 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
4378 mapped_buffers_
.erase(it
);
4382 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
4383 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
4385 bool cached
= GetHelper(binding
, &id
);
4387 return static_cast<GLuint
>(id
);
4390 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
4391 GLuint buffer
= GetBoundBufferHelper(target
);
4392 RemoveMappedBufferRangeById(buffer
);
4395 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4397 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4398 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4399 mapped_memory_
->FreePendingToken(
4400 iter
->second
.shm_memory
, helper_
->InsertToken());
4401 mapped_buffer_range_map_
.erase(iter
);
4406 void GLES2Implementation::ClearMappedBufferRangeMap() {
4407 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4408 if (buffer_range
.second
.shm_memory
) {
4409 mapped_memory_
->FreePendingToken(
4410 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4413 mapped_buffer_range_map_
.clear();
4416 void* GLES2Implementation::MapBufferRange(
4417 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4418 GPU_CLIENT_SINGLE_THREAD_CHECK();
4419 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4420 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4421 << size
<< ", " << access
<< ")");
4422 if (!ValidateSize("glMapBufferRange", size
) ||
4423 !ValidateOffset("glMapBufferRange", offset
)) {
4428 unsigned int shm_offset
;
4429 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4431 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4435 typedef cmds::MapBufferRange::Result Result
;
4436 Result
* result
= GetResultAs
<Result
*>();
4438 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4439 GetResultShmId(), GetResultShmOffset());
4440 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4441 // consider an early return without WaitForCmd(). crbug.com/465804.
4444 const GLbitfield kInvalidateBits
=
4445 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4446 if ((access
& kInvalidateBits
) != 0) {
4447 // We do not read back from the buffer, therefore, we set the client
4448 // side memory to zero to avoid uninitialized data.
4449 memset(mem
, 0, size
);
4451 GLuint buffer
= GetBoundBufferHelper(target
);
4452 DCHECK_NE(0u, buffer
);
4453 // glMapBufferRange fails on an already mapped buffer.
4454 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4455 mapped_buffer_range_map_
.end());
4456 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4458 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4459 DCHECK(iter
.second
);
4461 mapped_memory_
->Free(mem
);
4465 GPU_CLIENT_LOG(" returned " << mem
);
4470 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4471 GPU_CLIENT_SINGLE_THREAD_CHECK();
4472 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4473 << GLES2Util::GetStringEnum(target
) << ")");
4475 case GL_ARRAY_BUFFER
:
4476 case GL_ELEMENT_ARRAY_BUFFER
:
4477 case GL_COPY_READ_BUFFER
:
4478 case GL_COPY_WRITE_BUFFER
:
4479 case GL_PIXEL_PACK_BUFFER
:
4480 case GL_PIXEL_UNPACK_BUFFER
:
4481 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4482 case GL_UNIFORM_BUFFER
:
4485 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4488 GLuint buffer
= GetBoundBufferHelper(target
);
4490 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4493 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4494 if (iter
== mapped_buffer_range_map_
.end()) {
4495 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4499 helper_
->UnmapBuffer(target
);
4500 RemoveMappedBufferRangeById(buffer
);
4501 // TODO(zmo): There is a rare situation that data might be corrupted and
4502 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4503 // don't have to WaitForCmd().
4504 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4509 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4519 GPU_CLIENT_SINGLE_THREAD_CHECK();
4520 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4521 << target
<< ", " << level
<< ", "
4522 << xoffset
<< ", " << yoffset
<< ", "
4523 << width
<< ", " << height
<< ", "
4524 << GLES2Util::GetStringTextureFormat(format
) << ", "
4525 << GLES2Util::GetStringPixelType(type
) << ", "
4526 << GLES2Util::GetStringEnum(access
) << ")");
4527 if (access
!= GL_WRITE_ONLY
) {
4528 SetGLErrorInvalidEnum(
4529 "glMapTexSubImage2DCHROMIUM", access
, "access");
4532 // NOTE: target is NOT checked because the service will check it
4533 // and we don't know what targets are valid.
4534 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4536 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4540 if (!GLES2Util::ComputeImageDataSizes(
4541 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4543 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4547 unsigned int shm_offset
;
4548 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4550 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4554 std::pair
<MappedTextureMap::iterator
, bool> result
=
4555 mapped_textures_
.insert(std::make_pair(
4558 access
, shm_id
, mem
, shm_offset
,
4559 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4560 DCHECK(result
.second
);
4561 GPU_CLIENT_LOG(" returned " << mem
);
4565 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4566 GPU_CLIENT_SINGLE_THREAD_CHECK();
4568 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4569 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4570 if (it
== mapped_textures_
.end()) {
4572 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4575 const MappedTexture
& mt
= it
->second
;
4576 helper_
->TexSubImage2D(
4577 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4578 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4579 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4580 mapped_textures_
.erase(it
);
4584 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4585 float scale_factor
) {
4586 GPU_CLIENT_SINGLE_THREAD_CHECK();
4587 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4588 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4589 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4593 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4594 GPU_CLIENT_SINGLE_THREAD_CHECK();
4595 GPU_CLIENT_LOG("[" << GetLogPrefix()
4596 << "] glGetRequestableExtensionsCHROMIUM()");
4598 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4599 const char* result
= NULL
;
4600 // Clear the bucket so if the command fails nothing will be in it.
4601 helper_
->SetBucketSize(kResultBucketId
, 0);
4602 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4604 if (GetBucketAsString(kResultBucketId
, &str
)) {
4605 // The set of requestable extensions shrinks as we enable
4606 // them. Because we don't know when the client will stop referring
4607 // to a previous one it queries (see GetString) we need to cache
4608 // the unique results.
4609 std::set
<std::string
>::const_iterator sit
=
4610 requestable_extensions_set_
.find(str
);
4611 if (sit
!= requestable_extensions_set_
.end()) {
4612 result
= sit
->c_str();
4614 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4615 requestable_extensions_set_
.insert(str
);
4616 DCHECK(insert_result
.second
);
4617 result
= insert_result
.first
->c_str();
4620 GPU_CLIENT_LOG(" returned " << result
);
4621 return reinterpret_cast<const GLchar
*>(result
);
4624 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4625 // with VirtualGL contexts.
4626 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4627 GPU_CLIENT_SINGLE_THREAD_CHECK();
4628 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4629 << extension
<< ")");
4630 SetBucketAsCString(kResultBucketId
, extension
);
4631 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4632 helper_
->SetBucketSize(kResultBucketId
, 0);
4634 struct ExtensionCheck
{
4635 const char* extension
;
4636 ExtensionStatus
* status
;
4638 const ExtensionCheck checks
[] = {
4640 "GL_ANGLE_pack_reverse_row_order",
4641 &angle_pack_reverse_row_order_status_
,
4644 "GL_CHROMIUM_framebuffer_multisample",
4645 &chromium_framebuffer_multisample_
,
4648 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4649 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4650 const ExtensionCheck
& check
= checks
[ii
];
4651 if (*check
.status
== kUnavailableExtensionStatus
&&
4652 !strcmp(extension
, check
.extension
)) {
4653 *check
.status
= kUnknownExtensionStatus
;
4658 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4659 GPU_CLIENT_SINGLE_THREAD_CHECK();
4660 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4661 // Wait if this would add too many rate limit tokens.
4662 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4663 helper_
->WaitForToken(rate_limit_tokens_
.front());
4664 rate_limit_tokens_
.pop();
4666 rate_limit_tokens_
.push(helper_
->InsertToken());
4669 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4670 GLuint program
, std::vector
<int8
>* result
) {
4672 // Clear the bucket so if the command fails nothing will be in it.
4673 helper_
->SetBucketSize(kResultBucketId
, 0);
4674 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4675 GetBucketContents(kResultBucketId
, result
);
4678 void GLES2Implementation::GetProgramInfoCHROMIUM(
4679 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4680 GPU_CLIENT_SINGLE_THREAD_CHECK();
4683 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4687 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4690 // Make sure they've set size to 0 else the value will be undefined on
4692 DCHECK_EQ(0, *size
);
4693 std::vector
<int8
> result
;
4694 GetProgramInfoCHROMIUMHelper(program
, &result
);
4695 if (result
.empty()) {
4698 *size
= result
.size();
4702 if (static_cast<size_t>(bufsize
) < result
.size()) {
4703 SetGLError(GL_INVALID_OPERATION
,
4704 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4707 memcpy(info
, &result
[0], result
.size());
4710 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4711 GLuint program
, std::vector
<int8
>* result
) {
4713 // Clear the bucket so if the command fails nothing will be in it.
4714 helper_
->SetBucketSize(kResultBucketId
, 0);
4715 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4716 GetBucketContents(kResultBucketId
, result
);
4719 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4720 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4721 GPU_CLIENT_SINGLE_THREAD_CHECK();
4724 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4728 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4731 // Make sure they've set size to 0 else the value will be undefined on
4733 DCHECK_EQ(0, *size
);
4734 std::vector
<int8
> result
;
4735 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4736 if (result
.empty()) {
4739 *size
= result
.size();
4743 if (static_cast<size_t>(bufsize
) < result
.size()) {
4744 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4745 "bufsize is too small for result.");
4748 memcpy(info
, &result
[0], result
.size());
4751 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4752 GLuint program
, std::vector
<int8
>* result
) {
4754 // Clear the bucket so if the command fails nothing will be in it.
4755 helper_
->SetBucketSize(kResultBucketId
, 0);
4756 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4757 GetBucketContents(kResultBucketId
, result
);
4760 void GLES2Implementation::GetUniformsES3CHROMIUM(
4761 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4762 GPU_CLIENT_SINGLE_THREAD_CHECK();
4765 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4769 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4772 // Make sure they've set size to 0 else the value will be undefined on
4774 DCHECK_EQ(0, *size
);
4775 std::vector
<int8
> result
;
4776 GetUniformsES3CHROMIUMHelper(program
, &result
);
4777 if (result
.empty()) {
4780 *size
= result
.size();
4784 if (static_cast<size_t>(bufsize
) < result
.size()) {
4785 SetGLError(GL_INVALID_OPERATION
,
4786 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4789 memcpy(info
, &result
[0], result
.size());
4792 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4793 GLuint program
, std::vector
<int8
>* result
) {
4795 // Clear the bucket so if the command fails nothing will be in it.
4796 helper_
->SetBucketSize(kResultBucketId
, 0);
4797 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4798 GetBucketContents(kResultBucketId
, result
);
4801 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4802 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4803 GPU_CLIENT_SINGLE_THREAD_CHECK();
4805 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4806 "bufsize less than 0.");
4810 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4814 // Make sure they've set size to 0 else the value will be undefined on
4816 DCHECK_EQ(0, *size
);
4817 std::vector
<int8
> result
;
4818 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4819 if (result
.empty()) {
4822 *size
= result
.size();
4826 if (static_cast<size_t>(bufsize
) < result
.size()) {
4827 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4828 "bufsize is too small for result.");
4831 memcpy(info
, &result
[0], result
.size());
4834 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4835 GPU_CLIENT_SINGLE_THREAD_CHECK();
4836 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4838 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4839 helper_
->CommandBufferHelper::Flush();
4840 return gpu_control_
->CreateStreamTexture(texture
);
4843 void GLES2Implementation::PostSubBufferCHROMIUM(
4844 GLint x
, GLint y
, GLint width
, GLint height
) {
4845 GPU_CLIENT_SINGLE_THREAD_CHECK();
4846 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4847 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4848 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4849 "width", width
, "height", height
);
4851 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4852 swap_buffers_tokens_
.push(helper_
->InsertToken());
4853 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4854 helper_
->CommandBufferHelper::Flush();
4855 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4856 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4857 swap_buffers_tokens_
.pop();
4861 void GLES2Implementation::DeleteQueriesEXTHelper(
4862 GLsizei n
, const GLuint
* queries
) {
4863 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4864 query_tracker_
->RemoveQuery(queries
[ii
]);
4865 query_id_allocator_
->FreeID(queries
[ii
]);
4868 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4871 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4872 GPU_CLIENT_SINGLE_THREAD_CHECK();
4873 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4875 // TODO(gman): To be spec compliant IDs from other contexts sharing
4876 // resources need to return true here even though you can't share
4877 // queries across contexts?
4878 return query_tracker_
->GetQuery(id
) != NULL
;
4881 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4882 GPU_CLIENT_SINGLE_THREAD_CHECK();
4883 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4884 << GLES2Util::GetStringQueryTarget(target
)
4885 << ", " << id
<< ")");
4888 case GL_COMMANDS_ISSUED_CHROMIUM
:
4889 case GL_LATENCY_QUERY_CHROMIUM
:
4890 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
4891 case GL_GET_ERROR_QUERY_CHROMIUM
:
4893 case GL_COMMANDS_COMPLETED_CHROMIUM
:
4894 if (!capabilities_
.sync_query
) {
4896 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4897 "not enabled for commands completed queries");
4901 case GL_ANY_SAMPLES_PASSED
:
4902 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
4903 if (!capabilities_
.occlusion_query_boolean
) {
4905 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4906 "not enabled for occlusion queries");
4910 case GL_TIME_ELAPSED_EXT
:
4911 if (!capabilities_
.timer_queries
) {
4913 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4914 "not enabled for timing queries");
4918 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
4919 if (capabilities_
.major_version
>= 3)
4924 GL_INVALID_ENUM
, "glBeginQueryEXT", "unknown query target");
4928 // if any outstanding queries INV_OP
4929 if (query_tracker_
->GetCurrentQuery(target
)) {
4931 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4936 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4940 if (!query_id_allocator_
->InUse(id
)) {
4941 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4945 // Extra setups some targets might need.
4947 case GL_TIME_ELAPSED_EXT
:
4948 if (!query_tracker_
->SetDisjointSync(this)) {
4949 SetGLError(GL_OUT_OF_MEMORY
,
4951 "buffer allocation failed");
4959 if (query_tracker_
->BeginQuery(id
, target
, this))
4963 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4964 GPU_CLIENT_SINGLE_THREAD_CHECK();
4965 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4966 << GLES2Util::GetStringQueryTarget(target
) << ")");
4967 // Don't do anything if the context is lost.
4968 if (helper_
->IsContextLost()) {
4972 if (query_tracker_
->EndQuery(target
, this))
4976 void GLES2Implementation::QueryCounterEXT(GLuint id
, GLenum target
) {
4977 GPU_CLIENT_SINGLE_THREAD_CHECK();
4978 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] QueryCounterEXT("
4980 << ", " << GLES2Util::GetStringQueryTarget(target
) << ")");
4983 case GL_TIMESTAMP_EXT
:
4984 if (!capabilities_
.timer_queries
) {
4986 GL_INVALID_OPERATION
, "glQueryCounterEXT",
4987 "not enabled for timing queries");
4993 GL_INVALID_ENUM
, "glQueryCounterEXT", "unknown query target");
4998 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "id is 0");
5002 if (!query_id_allocator_
->InUse(id
)) {
5003 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "invalid id");
5007 // Extra setups some targets might need.
5009 case GL_TIMESTAMP_EXT
:
5010 if (!query_tracker_
->SetDisjointSync(this)) {
5011 SetGLError(GL_OUT_OF_MEMORY
,
5012 "glQueryCounterEXT",
5013 "buffer allocation failed");
5021 if (query_tracker_
->QueryCounter(id
, target
, this))
5025 void GLES2Implementation::GetQueryivEXT(
5026 GLenum target
, GLenum pname
, GLint
* params
) {
5027 GPU_CLIENT_SINGLE_THREAD_CHECK();
5028 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
5029 << GLES2Util::GetStringQueryTarget(target
) << ", "
5030 << GLES2Util::GetStringQueryParameter(pname
) << ", "
5031 << static_cast<const void*>(params
) << ")");
5032 if (pname
== GL_QUERY_COUNTER_BITS_EXT
) {
5033 // We convert all queries to CPU time so we support 64 bits.
5036 } else if (pname
!= GL_CURRENT_QUERY_EXT
) {
5037 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
5040 QueryTracker::Query
* query
= query_tracker_
->GetCurrentQuery(target
);
5041 *params
= query
? query
->id() : 0;
5042 GPU_CLIENT_LOG(" " << *params
);
5046 void GLES2Implementation::GetQueryObjectivEXT(
5047 GLuint id
, GLenum pname
, GLint
* params
) {
5048 GLuint64 result
= 0;
5049 if (GetQueryObjectValueHelper("glGetQueryObjectivEXT", id
, pname
, &result
))
5050 *params
= base::saturated_cast
<GLint
>(result
);
5053 void GLES2Implementation::GetQueryObjectuivEXT(
5054 GLuint id
, GLenum pname
, GLuint
* params
) {
5055 GLuint64 result
= 0;
5056 if (GetQueryObjectValueHelper("glGetQueryObjectuivEXT", id
, pname
, &result
))
5057 *params
= base::saturated_cast
<GLuint
>(result
);
5060 void GLES2Implementation::GetQueryObjecti64vEXT(
5061 GLuint id
, GLenum pname
, GLint64
* params
) {
5062 GLuint64 result
= 0;
5063 if (GetQueryObjectValueHelper("glGetQueryObjectiv64vEXT", id
, pname
, &result
))
5064 *params
= base::saturated_cast
<GLint64
>(result
);
5067 void GLES2Implementation::GetQueryObjectui64vEXT(
5068 GLuint id
, GLenum pname
, GLuint64
* params
) {
5069 GLuint64 result
= 0;
5070 if (GetQueryObjectValueHelper("glGetQueryObjectui64vEXT", id
, pname
, &result
))
5074 void GLES2Implementation::SetDisjointValueSyncCHROMIUM() {
5075 query_tracker_
->SetDisjointSync(this);
5078 void GLES2Implementation::DrawArraysInstancedANGLE(
5079 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
5080 GPU_CLIENT_SINGLE_THREAD_CHECK();
5081 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
5082 << GLES2Util::GetStringDrawMode(mode
) << ", "
5083 << first
<< ", " << count
<< ", " << primcount
<< ")");
5085 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
5088 if (primcount
< 0) {
5089 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
5092 if (primcount
== 0) {
5095 bool simulated
= false;
5096 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
5097 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
5101 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
5102 RestoreArrayBuffer(simulated
);
5106 void GLES2Implementation::DrawElementsInstancedANGLE(
5107 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
5108 GLsizei primcount
) {
5109 GPU_CLIENT_SINGLE_THREAD_CHECK();
5110 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
5111 << GLES2Util::GetStringDrawMode(mode
) << ", "
5113 << GLES2Util::GetStringIndexType(type
) << ", "
5114 << static_cast<const void*>(indices
) << ", "
5115 << primcount
<< ")");
5117 SetGLError(GL_INVALID_VALUE
,
5118 "glDrawElementsInstancedANGLE", "count less than 0.");
5124 if (primcount
< 0) {
5125 SetGLError(GL_INVALID_VALUE
,
5126 "glDrawElementsInstancedANGLE", "primcount < 0");
5129 if (primcount
== 0) {
5132 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
5133 !ValidateOffset("glDrawElementsInstancedANGLE",
5134 reinterpret_cast<GLintptr
>(indices
))) {
5138 bool simulated
= false;
5139 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
5140 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
5141 indices
, &offset
, &simulated
)) {
5144 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
5145 RestoreElementAndArrayBuffers(simulated
);
5149 void GLES2Implementation::GenMailboxCHROMIUM(
5151 GPU_CLIENT_SINGLE_THREAD_CHECK();
5152 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
5153 << static_cast<const void*>(mailbox
) << ")");
5154 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
5156 gpu::Mailbox result
= gpu::Mailbox::Generate();
5157 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
5160 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
5161 const GLbyte
* data
) {
5162 GPU_CLIENT_SINGLE_THREAD_CHECK();
5163 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
5164 << static_cast<const void*>(data
) << ")");
5165 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5166 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
5167 "mailbox that was not generated by "
5168 "GenMailboxCHROMIUM.";
5169 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
5173 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
5174 GLuint texture
, GLenum target
, const GLbyte
* data
) {
5175 GPU_CLIENT_SINGLE_THREAD_CHECK();
5176 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
5177 << static_cast<const void*>(data
) << ")");
5178 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5179 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
5180 "mailbox that was not generated by "
5181 "GenMailboxCHROMIUM.";
5182 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
5186 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
5187 const GLbyte
* data
) {
5188 GPU_CLIENT_SINGLE_THREAD_CHECK();
5189 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
5190 << static_cast<const void*>(data
) << ")");
5191 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5192 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
5193 "mailbox that was not generated by "
5194 "GenMailboxCHROMIUM.";
5195 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
5199 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
5200 GLenum target
, const GLbyte
* data
) {
5201 GPU_CLIENT_SINGLE_THREAD_CHECK();
5202 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
5203 << static_cast<const void*>(data
) << ")");
5204 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5205 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
5206 "mailbox that was not generated by "
5207 "GenMailboxCHROMIUM.";
5209 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
5210 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
5212 if (share_group_
->bind_generates_resource())
5213 helper_
->CommandBufferHelper::Flush();
5218 void GLES2Implementation::PushGroupMarkerEXT(
5219 GLsizei length
, const GLchar
* marker
) {
5220 GPU_CLIENT_SINGLE_THREAD_CHECK();
5221 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
5222 << length
<< ", " << marker
<< ")");
5228 (length
? std::string(marker
, length
) : std::string(marker
)));
5229 helper_
->PushGroupMarkerEXT(kResultBucketId
);
5230 helper_
->SetBucketSize(kResultBucketId
, 0);
5231 debug_marker_manager_
.PushGroup(
5232 length
? std::string(marker
, length
) : std::string(marker
));
5235 void GLES2Implementation::InsertEventMarkerEXT(
5236 GLsizei length
, const GLchar
* marker
) {
5237 GPU_CLIENT_SINGLE_THREAD_CHECK();
5238 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
5239 << length
<< ", " << marker
<< ")");
5245 (length
? std::string(marker
, length
) : std::string(marker
)));
5246 helper_
->InsertEventMarkerEXT(kResultBucketId
);
5247 helper_
->SetBucketSize(kResultBucketId
, 0);
5248 debug_marker_manager_
.SetMarker(
5249 length
? std::string(marker
, length
) : std::string(marker
));
5252 void GLES2Implementation::PopGroupMarkerEXT() {
5253 GPU_CLIENT_SINGLE_THREAD_CHECK();
5254 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
5255 helper_
->PopGroupMarkerEXT();
5256 debug_marker_manager_
.PopGroup();
5259 void GLES2Implementation::TraceBeginCHROMIUM(
5260 const char* category_name
, const char* trace_name
) {
5261 GPU_CLIENT_SINGLE_THREAD_CHECK();
5262 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
5263 << category_name
<< ", " << trace_name
<< ")");
5264 SetBucketAsCString(kResultBucketId
, category_name
);
5265 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
5266 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
5267 helper_
->SetBucketSize(kResultBucketId
, 0);
5268 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
5269 current_trace_stack_
++;
5272 void GLES2Implementation::TraceEndCHROMIUM() {
5273 GPU_CLIENT_SINGLE_THREAD_CHECK();
5274 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
5275 if (current_trace_stack_
== 0) {
5276 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
5277 "missing begin trace");
5280 helper_
->TraceEndCHROMIUM();
5281 current_trace_stack_
--;
5284 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
5285 GPU_CLIENT_SINGLE_THREAD_CHECK();
5286 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
5287 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
5289 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
5290 if (access
!= GL_READ_ONLY
) {
5291 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5297 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
5301 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
5305 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5307 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
5310 if (buffer
->mapped()) {
5311 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
5314 // Here we wait for previous transfer operations to be finished.
5315 if (buffer
->last_usage_token()) {
5316 helper_
->WaitForToken(buffer
->last_usage_token());
5317 buffer
->set_last_usage_token(0);
5319 buffer
->set_mapped(true);
5321 GPU_CLIENT_LOG(" returned " << buffer
->address());
5323 return buffer
->address();
5326 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
5327 GPU_CLIENT_SINGLE_THREAD_CHECK();
5329 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
5331 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
5332 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
5337 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5339 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
5342 if (!buffer
->mapped()) {
5343 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
5346 buffer
->set_mapped(false);
5351 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5352 GPU_CLIENT_SINGLE_THREAD_CHECK();
5353 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5354 helper_
->CommandBufferHelper::Flush();
5355 return gpu_control_
->InsertSyncPoint();
5358 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5359 GPU_CLIENT_SINGLE_THREAD_CHECK();
5360 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5361 DCHECK(capabilities_
.future_sync_points
);
5362 return gpu_control_
->InsertFutureSyncPoint();
5365 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5366 GPU_CLIENT_SINGLE_THREAD_CHECK();
5367 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5368 << sync_point
<< ")");
5369 DCHECK(capabilities_
.future_sync_points
);
5370 helper_
->CommandBufferHelper::Flush();
5371 gpu_control_
->RetireSyncPoint(sync_point
);
5374 uint64_t GLES2Implementation::ShareGroupTracingGUID() const {
5375 return share_group_
->TracingGUID();
5380 bool ValidImageFormat(GLenum internalformat
,
5381 const Capabilities
& capabilities
) {
5382 switch (internalformat
) {
5383 case GL_ATC_RGB_AMD
:
5384 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
5385 return capabilities
.texture_format_atc
;
5386 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
5387 return capabilities
.texture_format_dxt1
;
5388 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
5389 return capabilities
.texture_format_dxt5
;
5390 case GL_ETC1_RGB8_OES
:
5391 return capabilities
.texture_format_etc1
;
5395 case GL_RGB_YCBCR_422_CHROMIUM
:
5403 bool ValidImageUsage(GLenum usage
) {
5405 case GL_MAP_CHROMIUM
:
5406 case GL_SCANOUT_CHROMIUM
:
5415 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5418 GLenum internalformat
) {
5420 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5425 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5429 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5430 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5435 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5437 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5443 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5446 GLenum internalformat
) {
5447 GPU_CLIENT_SINGLE_THREAD_CHECK();
5448 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5449 << ", " << height
<< ", "
5450 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5453 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5458 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5459 // Flush the command stream to make sure all pending commands
5460 // that may refer to the image_id are executed on the service side.
5461 helper_
->CommandBufferHelper::Flush();
5462 gpu_control_
->DestroyImage(image_id
);
5465 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5466 GPU_CLIENT_SINGLE_THREAD_CHECK();
5467 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5468 << image_id
<< ")");
5469 DestroyImageCHROMIUMHelper(image_id
);
5473 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5476 GLenum internalformat
,
5480 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5485 SetGLError(GL_INVALID_VALUE
,
5486 "glCreateGpuMemoryBufferImageCHROMIUM",
5491 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5492 SetGLError(GL_INVALID_VALUE
,
5493 "glCreateGpuMemoryBufferImageCHROMIUM",
5498 if (!ValidImageUsage(usage
)) {
5499 SetGLError(GL_INVALID_VALUE
,
5500 "glCreateGpuMemoryBufferImageCHROMIUM",
5505 // Flush the command stream to ensure ordering in case the newly
5506 // returned image_id has recently been in use with a different buffer.
5507 helper_
->CommandBufferHelper::Flush();
5508 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5509 width
, height
, internalformat
, usage
);
5511 SetGLError(GL_OUT_OF_MEMORY
,
5512 "glCreateGpuMemoryBufferImageCHROMIUM",
5519 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5522 GLenum internalformat
,
5524 GPU_CLIENT_SINGLE_THREAD_CHECK();
5525 GPU_CLIENT_LOG("[" << GetLogPrefix()
5526 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5527 << ", " << height
<< ", "
5528 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5529 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5530 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5531 width
, height
, internalformat
, usage
);
5536 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5538 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5541 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5542 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5548 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5550 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5553 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5554 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5560 bool GLES2Implementation::GetSamplerParameterfvHelper(
5561 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5562 // TODO(zmo): Implement client side caching.
5566 bool GLES2Implementation::GetSamplerParameterivHelper(
5567 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5568 // TODO(zmo): Implement client side caching.
5572 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5573 const char* const* str
,
5574 const GLint
* length
,
5575 const char* func_name
) {
5576 DCHECK_LE(0, count
);
5577 // Compute the total size.
5578 base::CheckedNumeric
<size_t> total_size
= count
;
5580 total_size
*= sizeof(GLint
);
5581 if (!total_size
.IsValid()) {
5582 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5585 size_t header_size
= total_size
.ValueOrDefault(0);
5586 std::vector
<GLint
> header(count
+ 1);
5587 header
[0] = static_cast<GLint
>(count
);
5588 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5591 len
= (length
&& length
[ii
] >= 0)
5593 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5596 total_size
+= 1; // NULL at the end of each char array.
5597 if (!total_size
.IsValid()) {
5598 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5601 header
[ii
+ 1] = len
;
5603 // Pack data into a bucket on the service.
5604 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5606 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5608 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5609 base::CheckedNumeric
<size_t> checked_size
=
5610 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5612 checked_size
+= 1; // NULL in the end.
5614 if (!checked_size
.IsValid()) {
5615 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5618 size_t size
= checked_size
.ValueOrDefault(0);
5620 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5621 if (!buffer
.valid() || buffer
.size() == 0) {
5622 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5625 size_t copy_size
= buffer
.size();
5626 if (ii
> 0 && buffer
.size() == size
)
5629 memcpy(buffer
.address(), src
, copy_size
);
5630 if (copy_size
< buffer
.size()) {
5631 // Append NULL in the end.
5632 DCHECK(copy_size
+ 1 == buffer
.size());
5633 char* str
= reinterpret_cast<char*>(buffer
.address());
5636 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5637 buffer
.shm_id(), buffer
.offset());
5638 offset
+= buffer
.size();
5639 src
+= buffer
.size();
5640 size
-= buffer
.size();
5643 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5647 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5650 GPU_CLIENT_SINGLE_THREAD_CHECK();
5651 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5652 << ", " << index
<< ", " << binding
<< ")");
5653 share_group_
->program_info_manager()->UniformBlockBinding(
5654 this, program
, index
, binding
);
5655 helper_
->UniformBlockBinding(program
, index
, binding
);
5659 GLenum
GLES2Implementation::ClientWaitSync(
5660 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5661 GPU_CLIENT_SINGLE_THREAD_CHECK();
5662 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5663 << ", " << flags
<< ", " << timeout
<< ")");
5664 typedef cmds::ClientWaitSync::Result Result
;
5665 Result
* result
= GetResultAs
<Result
*>();
5667 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5668 return GL_WAIT_FAILED
;
5670 *result
= GL_WAIT_FAILED
;
5671 uint32_t v32_0
= 0, v32_1
= 0;
5672 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5673 helper_
->ClientWaitSync(
5674 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5675 GetResultShmId(), GetResultShmOffset());
5677 GPU_CLIENT_LOG("returned " << *result
);
5682 void GLES2Implementation::WaitSync(
5683 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5684 GPU_CLIENT_SINGLE_THREAD_CHECK();
5685 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5686 << flags
<< ", " << timeout
<< ")");
5687 uint32_t v32_0
= 0, v32_1
= 0;
5688 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5689 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5693 void GLES2Implementation::GetInternalformativ(
5694 GLenum target
, GLenum format
, GLenum pname
,
5695 GLsizei buf_size
, GLint
* params
) {
5696 GPU_CLIENT_SINGLE_THREAD_CHECK();
5697 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
5698 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ("
5699 << GLES2Util::GetStringRenderBufferTarget(target
) << ", "
5700 << GLES2Util::GetStringRenderBufferFormat(format
) << ", "
5701 << GLES2Util::GetStringInternalFormatParameter(pname
)
5702 << ", " << buf_size
<< ", "
5703 << static_cast<const void*>(params
) << ")");
5705 SetGLError(GL_INVALID_VALUE
, "glGetInternalformativ", "bufSize < 0");
5708 TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ");
5709 if (GetInternalformativHelper(target
, format
, pname
, buf_size
, params
)) {
5712 typedef cmds::GetInternalformativ::Result Result
;
5713 Result
* result
= GetResultAs
<Result
*>();
5717 result
->SetNumResults(0);
5718 helper_
->GetInternalformativ(target
, format
, pname
,
5719 GetResultShmId(), GetResultShmOffset());
5721 GPU_CLIENT_LOG_CODE_BLOCK({
5722 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
5723 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
5726 if (buf_size
> 0 && params
) {
5727 GLint
* data
= result
->GetData();
5728 if (buf_size
>= result
->GetNumResults()) {
5729 buf_size
= result
->GetNumResults();
5731 for (GLsizei ii
= 0; ii
< buf_size
; ++ii
) {
5732 params
[ii
] = data
[ii
];
5738 GLuint
GLES2Implementation::GenPathsCHROMIUM(GLsizei range
) {
5739 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenPathsCHROMIUM(" << range
5741 GPU_CLIENT_SINGLE_THREAD_CHECK();
5742 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
5744 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5747 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5748 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5754 GLuint first_client_id
= 0;
5755 GetRangeIdHandler(id_namespaces::kPaths
)
5756 ->MakeIdRange(this, range
, &first_client_id
);
5758 if (first_client_id
== 0) {
5759 // Ran out of id space. Is not specified to raise any gl errors.
5763 helper_
->GenPathsCHROMIUM(first_client_id
, range
);
5765 GPU_CLIENT_LOG_CODE_BLOCK({
5766 for (GLsizei i
= 0; i
< range
; ++i
) {
5767 GPU_CLIENT_LOG(" " << i
<< ": " << (first_client_id
+ i
));
5771 return first_client_id
;
5774 void GLES2Implementation::DeletePathsCHROMIUM(GLuint first_client_id
,
5776 GPU_CLIENT_SINGLE_THREAD_CHECK();
5777 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeletePathsCHROMIUM("
5778 << first_client_id
<< ", " << range
<< ")");
5779 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
5782 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5785 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5786 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5792 GLuint last_client_id
;
5793 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
)) {
5794 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5798 GetRangeIdHandler(id_namespaces::kPaths
)
5799 ->FreeIdRange(this, first_client_id
, range
,
5800 &GLES2Implementation::DeletePathsCHROMIUMStub
);
5804 void GLES2Implementation::DeletePathsCHROMIUMStub(GLuint first_client_id
,
5806 helper_
->DeletePathsCHROMIUM(first_client_id
, range
);
5809 void GLES2Implementation::PathCommandsCHROMIUM(GLuint path
,
5810 GLsizei num_commands
,
5811 const GLubyte
* commands
,
5814 const void* coords
) {
5815 GPU_CLIENT_SINGLE_THREAD_CHECK();
5816 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathCommandsCHROMIUM(" << path
5817 << ", " << num_commands
<< ", " << commands
<< ", "
5818 << num_coords
<< ", " << coords
<< ")");
5819 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
5821 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "invalid path object");
5824 if (num_commands
< 0) {
5825 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
5828 if (num_commands
!= 0 && !commands
) {
5829 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing commands");
5832 if (num_coords
< 0) {
5833 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
5836 if (num_coords
!= 0 && !coords
) {
5837 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing coords");
5840 uint32 coord_type_size
= GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
5841 if (coord_type_size
== 0) {
5842 SetGLError(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
5845 if (num_commands
== 0) {
5846 // No commands must mean no coords, thus nothing to memcpy. Let
5847 // the service validate the call. Validate coord_type above, so
5848 // that the parameters will be checked the in the same order
5849 // regardless of num_commands.
5850 helper_
->PathCommandsCHROMIUM(path
, num_commands
, 0, 0, num_coords
,
5857 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
)) {
5858 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5862 uint32 required_buffer_size
;
5863 if (!SafeAddUint32(coords_size
, num_commands
, &required_buffer_size
)) {
5864 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5868 ScopedTransferBufferPtr
buffer(required_buffer_size
, helper_
,
5870 if (!buffer
.valid() || buffer
.size() < required_buffer_size
) {
5871 SetGLError(GL_OUT_OF_MEMORY
, kFunctionName
, "too large");
5875 uint32 coords_shm_id
= 0;
5876 uint32 coords_shm_offset
= 0;
5877 // Copy coords first because they need more strict alignment.
5878 if (coords_size
> 0) {
5879 unsigned char* coords_addr
= static_cast<unsigned char*>(buffer
.address());
5880 memcpy(coords_addr
, coords
, coords_size
);
5881 coords_shm_id
= buffer
.shm_id();
5882 coords_shm_offset
= buffer
.offset();
5885 DCHECK(num_commands
> 0);
5886 unsigned char* commands_addr
=
5887 static_cast<unsigned char*>(buffer
.address()) + coords_size
;
5888 memcpy(commands_addr
, commands
, num_commands
);
5890 helper_
->PathCommandsCHROMIUM(path
, num_commands
, buffer
.shm_id(),
5891 buffer
.offset() + coords_size
, num_coords
,
5892 coord_type
, coords_shm_id
, coords_shm_offset
);
5896 // Include the auto-generated part of this file. We split this because it means
5897 // we can easily edit the non-auto generated parts right here in this file
5898 // instead of having to edit some template or the code generator.
5899 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5901 } // namespace gles2