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
: new ShareGroup(bind_generates_resource
));
134 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
136 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
139 bool GLES2Implementation::Initialize(
140 unsigned int starting_transfer_buffer_size
,
141 unsigned int min_transfer_buffer_size
,
142 unsigned int max_transfer_buffer_size
,
143 unsigned int mapped_memory_limit
) {
144 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
145 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
146 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
147 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
149 if (!transfer_buffer_
->Initialize(
150 starting_transfer_buffer_size
,
152 min_transfer_buffer_size
,
153 max_transfer_buffer_size
,
159 mapped_memory_
.reset(new MappedMemoryManager(helper_
, mapped_memory_limit
));
161 unsigned chunk_size
= 2 * 1024 * 1024;
162 if (mapped_memory_limit
!= kNoLimit
) {
163 // Use smaller chunks if the client is very memory conscientious.
164 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
166 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
168 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
169 &static_state_
.shader_precisions
;
170 capabilities_
.VisitPrecisions([shader_precisions
](
171 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
172 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
173 cmds::GetShaderPrecisionFormat::Result cached_result
= {
174 true, result
->min_range
, result
->max_range
, result
->precision
};
175 shader_precisions
->insert(std::make_pair(key
, cached_result
));
178 util_
.set_num_compressed_texture_formats(
179 capabilities_
.num_compressed_texture_formats
);
180 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
182 texture_units_
.reset(
183 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
185 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
186 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
188 query_id_allocator_
.reset(new IdAllocator());
189 if (support_client_side_arrays_
) {
190 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
191 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
194 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
195 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
196 support_client_side_arrays_
));
198 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
199 // on Client & Service.
200 if (capabilities_
.bind_generates_resource_chromium
!=
201 (share_group_
->bind_generates_resource() ? 1 : 0)) {
202 SetGLError(GL_INVALID_OPERATION
,
204 "Service bind_generates_resource mismatch.");
208 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
209 // Don't register a dump provider in these cases.
210 // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
211 if (base::ThreadTaskRunnerHandle::IsSet()) {
212 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
213 this, base::ThreadTaskRunnerHandle::Get());
219 GLES2Implementation::~GLES2Implementation() {
220 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
223 // Make sure the queries are finished otherwise we'll delete the
224 // shared memory (mapped_memory_) which will free the memory used
225 // by the queries. The GPU process when validating that memory is still
226 // shared will fail and abort (ie, it will stop running).
228 query_tracker_
.reset();
230 // GLES2Implementation::Initialize() could fail before allocating
231 // reserved_ids_, so we need delete them carefully.
232 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
233 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
236 // Release remaining BufferRange mem; This is when a MapBufferRange() is
237 // called but not the UnmapBuffer() pair.
238 ClearMappedBufferRangeMap();
240 // Release any per-context data in share group.
241 share_group_
->FreeContext(this);
243 buffer_tracker_
.reset();
245 // Make sure the commands make it the service.
249 GLES2CmdHelper
* GLES2Implementation::helper() const {
253 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
254 return share_group_
->GetIdHandler(namespace_id
);
257 RangeIdHandlerInterface
* GLES2Implementation::GetRangeIdHandler(
258 int namespace_id
) const {
259 return share_group_
->GetRangeIdHandler(namespace_id
);
262 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
263 if (namespace_id
== id_namespaces::kQueries
)
264 return query_id_allocator_
.get();
269 void* GLES2Implementation::GetResultBuffer() {
270 return transfer_buffer_
->GetResultBuffer();
273 int32
GLES2Implementation::GetResultShmId() {
274 return transfer_buffer_
->GetShmId();
277 uint32
GLES2Implementation::GetResultShmOffset() {
278 return transfer_buffer_
->GetResultOffset();
281 void GLES2Implementation::FreeUnusedSharedMemory() {
282 mapped_memory_
->FreeUnused();
285 void GLES2Implementation::FreeEverything() {
287 query_tracker_
->Shrink();
288 FreeUnusedSharedMemory();
289 transfer_buffer_
->Free();
290 helper_
->FreeRingBuffer();
293 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
294 if (!helper_
->IsContextLost())
298 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
299 const base::Closure
& callback
) {
300 gpu_control_
->SignalSyncPoint(
302 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
303 weak_ptr_factory_
.GetWeakPtr(),
307 void GLES2Implementation::SignalQuery(uint32 query
,
308 const base::Closure
& callback
) {
309 // Flush previously entered commands to ensure ordering with any
310 // glBeginQueryEXT() calls that may have been put into the context.
311 ShallowFlushCHROMIUM();
312 gpu_control_
->SignalQuery(
314 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
315 weak_ptr_factory_
.GetWeakPtr(),
319 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
321 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
322 ShallowFlushCHROMIUM();
323 gpu_control_
->SetSurfaceVisible(visible
);
326 void GLES2Implementation::SetAggressivelyFreeResources(
327 bool aggressively_free_resources
) {
328 TRACE_EVENT1("gpu", "GLES2Implementation::SetAggressivelyFreeResources",
329 "aggressively_free_resources", aggressively_free_resources
);
330 aggressively_free_resources_
= aggressively_free_resources
;
332 if (aggressively_free_resources_
&& helper_
->HaveRingBuffer()) {
333 // Ensure that we clean up as much cache memory as possible and fully flush.
334 FlushDriverCachesCHROMIUM();
336 // Flush will delete transfer buffer resources if
337 // |aggressively_free_resources_| is true.
340 ShallowFlushCHROMIUM();
344 bool GLES2Implementation::OnMemoryDump(
345 const base::trace_event::MemoryDumpArgs
& args
,
346 base::trace_event::ProcessMemoryDump
* pmd
) {
347 if (!transfer_buffer_
->HaveBuffer())
350 const uint64 tracing_process_id
=
351 base::trace_event::MemoryDumpManager::GetInstance()
352 ->GetTracingProcessId();
354 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
355 base::StringPrintf("gpu/transfer_buffer_memory/buffer_%d",
356 transfer_buffer_
->GetShmId()));
357 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
358 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
359 transfer_buffer_
->GetSize());
360 dump
->AddScalar("free_size",
361 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
362 transfer_buffer_
->GetFreeSize());
364 GetBufferGUIDForTracing(tracing_process_id
, transfer_buffer_
->GetShmId());
365 const int kImportance
= 2;
366 pmd
->CreateSharedGlobalAllocatorDump(guid
);
367 pmd
->AddOwnershipEdge(dump
->guid(), guid
, kImportance
);
372 void GLES2Implementation::WaitForCmd() {
373 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
374 helper_
->CommandBufferHelper::Finish();
377 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
378 const char* extensions
=
379 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
383 int length
= strlen(ext
);
385 int n
= strcspn(extensions
, " ");
386 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
389 if ('\0' == extensions
[n
]) {
396 bool GLES2Implementation::IsExtensionAvailableHelper(
397 const char* extension
, ExtensionStatus
* status
) {
399 case kAvailableExtensionStatus
:
401 case kUnavailableExtensionStatus
:
404 bool available
= IsExtensionAvailable(extension
);
405 *status
= available
? kAvailableExtensionStatus
:
406 kUnavailableExtensionStatus
;
412 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
413 return IsExtensionAvailableHelper(
414 "GL_ANGLE_pack_reverse_row_order",
415 &angle_pack_reverse_row_order_status_
);
418 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
419 return IsExtensionAvailableHelper(
420 "GL_CHROMIUM_framebuffer_multisample",
421 &chromium_framebuffer_multisample_
);
424 const std::string
& GLES2Implementation::GetLogPrefix() const {
425 const std::string
& prefix(debug_marker_manager_
.GetMarker());
426 return prefix
.empty() ? this_in_hex_
: prefix
;
429 GLenum
GLES2Implementation::GetError() {
430 GPU_CLIENT_SINGLE_THREAD_CHECK();
431 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
432 GLenum err
= GetGLError();
433 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
437 GLenum
GLES2Implementation::GetClientSideGLError() {
438 if (error_bits_
== 0) {
442 GLenum error
= GL_NO_ERROR
;
443 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
444 if ((error_bits_
& mask
) != 0) {
445 error
= GLES2Util::GLErrorBitToGLError(mask
);
449 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
453 GLenum
GLES2Implementation::GetGLError() {
454 TRACE_EVENT0("gpu", "GLES2::GetGLError");
455 // Check the GL error first, then our wrapped error.
456 typedef cmds::GetError::Result Result
;
457 Result
* result
= GetResultAs
<Result
*>();
458 // If we couldn't allocate a result the context is lost.
462 *result
= GL_NO_ERROR
;
463 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
465 GLenum error
= *result
;
466 if (error
== GL_NO_ERROR
) {
467 error
= GetClientSideGLError();
469 // There was an error, clear the corresponding wrapped error.
470 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
475 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
476 void GLES2Implementation::FailGLError(GLenum error
) {
477 if (error
!= GL_NO_ERROR
) {
478 NOTREACHED() << "Error";
481 // NOTE: Calling GetGLError overwrites data in the result buffer.
482 void GLES2Implementation::CheckGLError() {
483 FailGLError(GetGLError());
485 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
487 void GLES2Implementation::SetGLError(
488 GLenum error
, const char* function_name
, const char* msg
) {
489 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
490 << GLES2Util::GetStringError(error
) << ": "
491 << function_name
<< ": " << msg
);
496 if (error_message_callback_
) {
497 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
498 function_name
+ ": " + (msg
? msg
: ""));
499 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
501 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
503 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
504 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
505 GL_UNKNOWN_CONTEXT_RESET_ARB
);
509 void GLES2Implementation::SetGLErrorInvalidEnum(
510 const char* function_name
, GLenum value
, const char* label
) {
511 SetGLError(GL_INVALID_ENUM
, function_name
,
512 (std::string(label
) + " was " +
513 GLES2Util::GetStringEnum(value
)).c_str());
516 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
517 std::vector
<int8
>* data
) {
518 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
520 const uint32 kStartSize
= 32 * 1024;
521 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
522 if (!buffer
.valid()) {
525 typedef cmd::GetBucketStart::Result Result
;
526 Result
* result
= GetResultAs
<Result
*>();
531 helper_
->GetBucketStart(
532 bucket_id
, GetResultShmId(), GetResultShmOffset(),
533 buffer
.size(), buffer
.shm_id(), buffer
.offset());
535 uint32 size
= *result
;
540 if (!buffer
.valid()) {
542 if (!buffer
.valid()) {
545 helper_
->GetBucketData(
546 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
549 uint32 size_to_copy
= std::min(size
, buffer
.size());
550 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
551 offset
+= size_to_copy
;
552 size
-= size_to_copy
;
555 // Free the bucket. This is not required but it does free up the memory.
556 // and we don't have to wait for the result so from the client's perspective
558 helper_
->SetBucketSize(bucket_id
, 0);
563 void GLES2Implementation::SetBucketContents(
564 uint32 bucket_id
, const void* data
, size_t size
) {
566 helper_
->SetBucketSize(bucket_id
, size
);
570 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
571 if (!buffer
.valid()) {
574 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
576 helper_
->SetBucketData(
577 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
578 offset
+= buffer
.size();
579 size
-= buffer
.size();
584 void GLES2Implementation::SetBucketAsCString(
585 uint32 bucket_id
, const char* str
) {
586 // NOTE: strings are passed NULL terminated. That means the empty
587 // string will have a size of 1 and no-string will have a size of 0
589 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
591 helper_
->SetBucketSize(bucket_id
, 0);
595 bool GLES2Implementation::GetBucketAsString(
596 uint32 bucket_id
, std::string
* str
) {
598 std::vector
<int8
> data
;
599 // NOTE: strings are passed NULL terminated. That means the empty
600 // string will have a size of 1 and no-string will have a size of 0
601 if (!GetBucketContents(bucket_id
, &data
)) {
607 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
611 void GLES2Implementation::SetBucketAsString(
612 uint32 bucket_id
, const std::string
& str
) {
613 // NOTE: strings are passed NULL terminated. That means the empty
614 // string will have a size of 1 and no-string will have a size of 0
615 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
618 void GLES2Implementation::Disable(GLenum cap
) {
619 GPU_CLIENT_SINGLE_THREAD_CHECK();
620 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
621 << GLES2Util::GetStringCapability(cap
) << ")");
622 bool changed
= false;
623 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
624 helper_
->Disable(cap
);
629 void GLES2Implementation::Enable(GLenum cap
) {
630 GPU_CLIENT_SINGLE_THREAD_CHECK();
631 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
632 << GLES2Util::GetStringCapability(cap
) << ")");
633 bool changed
= false;
634 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
635 helper_
->Enable(cap
);
640 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
641 GPU_CLIENT_SINGLE_THREAD_CHECK();
642 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
643 << GLES2Util::GetStringCapability(cap
) << ")");
645 if (!state_
.GetEnabled(cap
, &state
)) {
646 typedef cmds::IsEnabled::Result Result
;
647 Result
* result
= GetResultAs
<Result
*>();
652 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
654 state
= (*result
) != 0;
657 GPU_CLIENT_LOG("returned " << state
);
662 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
663 // TODO(zmo): For all the BINDING points, there is a possibility where
664 // resources are shared among multiple contexts, that the cached points
665 // are invalid. It is not a problem for now, but once we allow resource
666 // sharing in WebGL, we need to implement a mechanism to allow correct
667 // client side binding points tracking. crbug.com/465562.
671 case GL_ACTIVE_TEXTURE
:
672 *params
= active_texture_unit_
+ GL_TEXTURE0
;
674 case GL_ARRAY_BUFFER_BINDING
:
675 *params
= bound_array_buffer_
;
677 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
679 vertex_array_object_manager_
->bound_element_array_buffer();
681 case GL_FRAMEBUFFER_BINDING
:
682 *params
= bound_framebuffer_
;
684 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
685 *params
= capabilities_
.max_combined_texture_image_units
;
687 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
688 *params
= capabilities_
.max_cube_map_texture_size
;
690 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
691 *params
= capabilities_
.max_fragment_uniform_vectors
;
693 case GL_MAX_RENDERBUFFER_SIZE
:
694 *params
= capabilities_
.max_renderbuffer_size
;
696 case GL_MAX_TEXTURE_IMAGE_UNITS
:
697 *params
= capabilities_
.max_texture_image_units
;
699 case GL_MAX_TEXTURE_SIZE
:
700 *params
= capabilities_
.max_texture_size
;
702 case GL_MAX_VARYING_VECTORS
:
703 *params
= capabilities_
.max_varying_vectors
;
705 case GL_MAX_VERTEX_ATTRIBS
:
706 *params
= capabilities_
.max_vertex_attribs
;
708 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
709 *params
= capabilities_
.max_vertex_texture_image_units
;
711 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
712 *params
= capabilities_
.max_vertex_uniform_vectors
;
714 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
715 *params
= capabilities_
.num_compressed_texture_formats
;
717 case GL_NUM_SHADER_BINARY_FORMATS
:
718 *params
= capabilities_
.num_shader_binary_formats
;
720 case GL_RENDERBUFFER_BINDING
:
721 *params
= bound_renderbuffer_
;
723 case GL_TEXTURE_BINDING_2D
:
724 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
726 case GL_TEXTURE_BINDING_CUBE_MAP
:
727 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
730 // Non-standard parameters.
731 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
733 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
735 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
736 *params
= bound_pixel_pack_transfer_buffer_id_
;
738 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
739 *params
= bound_pixel_unpack_transfer_buffer_id_
;
741 case GL_READ_FRAMEBUFFER_BINDING
:
742 if (IsChromiumFramebufferMultisampleAvailable()) {
743 *params
= bound_read_framebuffer_
;
747 case GL_TIMESTAMP_EXT
:
748 // We convert all GPU timestamps to CPU time.
749 *params
= base::saturated_cast
<GLint
>(
750 (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
751 * base::Time::kNanosecondsPerMicrosecond
);
753 case GL_GPU_DISJOINT_EXT
:
754 *params
= static_cast<GLint
>(query_tracker_
->CheckAndResetDisjoint());
757 // Non-cached parameters.
758 case GL_ALIASED_LINE_WIDTH_RANGE
:
759 case GL_ALIASED_POINT_SIZE_RANGE
:
763 case GL_BLEND_DST_ALPHA
:
764 case GL_BLEND_DST_RGB
:
765 case GL_BLEND_EQUATION_ALPHA
:
766 case GL_BLEND_EQUATION_RGB
:
767 case GL_BLEND_SRC_ALPHA
:
768 case GL_BLEND_SRC_RGB
:
770 case GL_COLOR_CLEAR_VALUE
:
771 case GL_COLOR_WRITEMASK
:
772 case GL_COMPRESSED_TEXTURE_FORMATS
:
774 case GL_CULL_FACE_MODE
:
775 case GL_CURRENT_PROGRAM
:
777 case GL_DEPTH_CLEAR_VALUE
:
781 case GL_DEPTH_WRITEMASK
:
784 case GL_GENERATE_MIPMAP_HINT
:
786 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
787 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
789 case GL_MAX_VIEWPORT_DIMS
:
790 case GL_PACK_ALIGNMENT
:
791 case GL_POLYGON_OFFSET_FACTOR
:
792 case GL_POLYGON_OFFSET_FILL
:
793 case GL_POLYGON_OFFSET_UNITS
:
795 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
796 case GL_SAMPLE_BUFFERS
:
797 case GL_SAMPLE_COVERAGE
:
798 case GL_SAMPLE_COVERAGE_INVERT
:
799 case GL_SAMPLE_COVERAGE_VALUE
:
802 case GL_SCISSOR_TEST
:
803 case GL_SHADER_BINARY_FORMATS
:
804 case GL_SHADER_COMPILER
:
805 case GL_STENCIL_BACK_FAIL
:
806 case GL_STENCIL_BACK_FUNC
:
807 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
808 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
809 case GL_STENCIL_BACK_REF
:
810 case GL_STENCIL_BACK_VALUE_MASK
:
811 case GL_STENCIL_BACK_WRITEMASK
:
812 case GL_STENCIL_BITS
:
813 case GL_STENCIL_CLEAR_VALUE
:
814 case GL_STENCIL_FAIL
:
815 case GL_STENCIL_FUNC
:
816 case GL_STENCIL_PASS_DEPTH_FAIL
:
817 case GL_STENCIL_PASS_DEPTH_PASS
:
819 case GL_STENCIL_TEST
:
820 case GL_STENCIL_VALUE_MASK
:
821 case GL_STENCIL_WRITEMASK
:
822 case GL_SUBPIXEL_BITS
:
823 case GL_UNPACK_ALIGNMENT
:
830 if (capabilities_
.major_version
< 3) {
836 case GL_COPY_READ_BUFFER_BINDING
:
837 *params
= bound_copy_read_buffer_
;
839 case GL_COPY_WRITE_BUFFER_BINDING
:
840 *params
= bound_copy_write_buffer_
;
842 case GL_MAJOR_VERSION
:
843 *params
= capabilities_
.major_version
;
845 case GL_MAX_3D_TEXTURE_SIZE
:
846 *params
= capabilities_
.max_3d_texture_size
;
848 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
849 *params
= capabilities_
.max_array_texture_layers
;
851 case GL_MAX_COLOR_ATTACHMENTS
:
852 *params
= capabilities_
.max_color_attachments
;
854 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
855 *params
= static_cast<GLint
>(
856 capabilities_
.max_combined_fragment_uniform_components
);
858 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
859 *params
= capabilities_
.max_combined_uniform_blocks
;
861 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
862 *params
= static_cast<GLint
>(
863 capabilities_
.max_combined_vertex_uniform_components
);
865 case GL_MAX_DRAW_BUFFERS
:
866 *params
= capabilities_
.max_draw_buffers
;
868 case GL_MAX_ELEMENT_INDEX
:
869 *params
= static_cast<GLint
>(capabilities_
.max_element_index
);
871 case GL_MAX_ELEMENTS_INDICES
:
872 *params
= capabilities_
.max_elements_indices
;
874 case GL_MAX_ELEMENTS_VERTICES
:
875 *params
= capabilities_
.max_elements_vertices
;
877 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
878 *params
= capabilities_
.max_fragment_input_components
;
880 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
881 *params
= capabilities_
.max_fragment_uniform_blocks
;
883 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
884 *params
= capabilities_
.max_fragment_uniform_components
;
886 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
887 *params
= capabilities_
.max_program_texel_offset
;
890 *params
= capabilities_
.max_samples
;
892 case GL_MAX_SERVER_WAIT_TIMEOUT
:
893 *params
= static_cast<GLint
>(capabilities_
.max_server_wait_timeout
);
895 case GL_MAX_TEXTURE_LOD_BIAS
:
896 *params
= static_cast<GLint
>(capabilities_
.max_texture_lod_bias
);
898 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
899 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
901 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
902 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
904 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
905 *params
= capabilities_
.max_transform_feedback_separate_components
;
907 case GL_MAX_UNIFORM_BLOCK_SIZE
:
908 *params
= static_cast<GLint
>(capabilities_
.max_uniform_block_size
);
910 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
911 *params
= capabilities_
.max_uniform_buffer_bindings
;
913 case GL_MAX_VARYING_COMPONENTS
:
914 *params
= capabilities_
.max_varying_components
;
916 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
917 *params
= capabilities_
.max_vertex_output_components
;
919 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
920 *params
= capabilities_
.max_vertex_uniform_blocks
;
922 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
923 *params
= capabilities_
.max_vertex_uniform_components
;
925 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
926 *params
= capabilities_
.min_program_texel_offset
;
928 case GL_MINOR_VERSION
:
929 *params
= capabilities_
.minor_version
;
931 case GL_NUM_EXTENSIONS
:
932 *params
= capabilities_
.num_extensions
;
934 case GL_NUM_PROGRAM_BINARY_FORMATS
:
935 *params
= capabilities_
.num_program_binary_formats
;
937 case GL_PIXEL_PACK_BUFFER_BINDING
:
938 *params
= bound_pixel_pack_buffer_
;
940 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
941 *params
= bound_pixel_unpack_buffer_
;
943 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
944 *params
= bound_transform_feedback_buffer_
;
946 case GL_UNIFORM_BUFFER_BINDING
:
947 *params
= bound_uniform_buffer_
;
949 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
950 *params
= capabilities_
.uniform_buffer_offset_alignment
;
953 // Non-cached ES3 parameters.
954 case GL_DRAW_BUFFER0
:
955 case GL_DRAW_BUFFER1
:
956 case GL_DRAW_BUFFER2
:
957 case GL_DRAW_BUFFER3
:
958 case GL_DRAW_BUFFER4
:
959 case GL_DRAW_BUFFER5
:
960 case GL_DRAW_BUFFER6
:
961 case GL_DRAW_BUFFER7
:
962 case GL_DRAW_BUFFER8
:
963 case GL_DRAW_BUFFER9
:
964 case GL_DRAW_BUFFER10
:
965 case GL_DRAW_BUFFER11
:
966 case GL_DRAW_BUFFER12
:
967 case GL_DRAW_BUFFER13
:
968 case GL_DRAW_BUFFER14
:
969 case GL_DRAW_BUFFER15
:
970 case GL_DRAW_FRAMEBUFFER_BINDING
:
971 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
972 case GL_PACK_ROW_LENGTH
:
973 case GL_PACK_SKIP_PIXELS
:
974 case GL_PACK_SKIP_ROWS
:
975 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
976 case GL_PROGRAM_BINARY_FORMATS
:
977 case GL_RASTERIZER_DISCARD
:
979 case GL_READ_FRAMEBUFFER_BINDING
:
980 case GL_SAMPLER_BINDING
:
981 case GL_TEXTURE_BINDING_2D_ARRAY
:
982 case GL_TEXTURE_BINDING_3D
:
983 case GL_TRANSFORM_FEEDBACK_BINDING
:
984 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
985 case GL_TRANSFORM_FEEDBACK_PAUSED
:
986 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
987 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
988 case GL_UNIFORM_BUFFER_SIZE
:
989 case GL_UNIFORM_BUFFER_START
:
990 case GL_UNPACK_IMAGE_HEIGHT
:
991 case GL_UNPACK_ROW_LENGTH
:
992 case GL_UNPACK_SKIP_IMAGES
:
993 case GL_UNPACK_SKIP_PIXELS
:
994 case GL_UNPACK_SKIP_ROWS
:
995 case GL_VERTEX_ARRAY_BINDING
:
1002 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
1003 // TODO(gman): Make this handle pnames that return more than 1 value.
1005 if (!GetHelper(pname
, &value
)) {
1008 *params
= static_cast<GLboolean
>(value
);
1012 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
1013 // TODO(gman): Make this handle pnames that return more than 1 value.
1015 case GL_MAX_TEXTURE_LOD_BIAS
:
1016 *params
= capabilities_
.max_texture_lod_bias
;
1022 if (!GetHelper(pname
, &value
)) {
1025 *params
= static_cast<GLfloat
>(value
);
1029 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
1031 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
1032 *params
= capabilities_
.max_combined_fragment_uniform_components
;
1034 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
1035 *params
= capabilities_
.max_combined_vertex_uniform_components
;
1037 case GL_MAX_ELEMENT_INDEX
:
1038 *params
= capabilities_
.max_element_index
;
1040 case GL_MAX_SERVER_WAIT_TIMEOUT
:
1041 *params
= capabilities_
.max_server_wait_timeout
;
1043 case GL_MAX_UNIFORM_BLOCK_SIZE
:
1044 *params
= capabilities_
.max_uniform_block_size
;
1046 case GL_TIMESTAMP_EXT
:
1047 // We convert all GPU timestamps to CPU time.
1048 *params
= (base::TraceTicks::Now() - base::TraceTicks()).InMicroseconds()
1049 * base::Time::kNanosecondsPerMicrosecond
;
1055 if (!GetHelper(pname
, &value
)) {
1058 *params
= static_cast<GLint64
>(value
);
1062 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
1063 return GetHelper(pname
, params
);
1066 bool GLES2Implementation::GetIntegeri_vHelper(
1067 GLenum pname
, GLuint index
, GLint
* data
) {
1068 // TODO(zmo): Implement client side caching.
1072 bool GLES2Implementation::GetInteger64i_vHelper(
1073 GLenum pname
, GLuint index
, GLint64
* data
) {
1074 // TODO(zmo): Implement client side caching.
1078 bool GLES2Implementation::GetInternalformativHelper(
1079 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
1081 // TODO(zmo): Implement the client side caching.
1085 bool GLES2Implementation::GetSyncivHelper(
1086 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
1090 case GL_OBJECT_TYPE
:
1091 value
= GL_SYNC_FENCE
;
1093 case GL_SYNC_CONDITION
:
1094 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1112 bool GLES2Implementation::GetQueryObjectValueHelper(
1113 const char* function_name
, GLuint id
, GLenum pname
, GLuint64
* params
) {
1114 GPU_CLIENT_SINGLE_THREAD_CHECK();
1115 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryObjectValueHelper("
1117 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
1118 << static_cast<const void*>(params
) << ")");
1120 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
1122 SetGLError(GL_INVALID_OPERATION
,
1123 function_name
, "unknown query id");
1127 if (query
->Active()) {
1129 GL_INVALID_OPERATION
,
1131 "query active. Did you call glEndQueryEXT?");
1135 if (query
->NeverUsed()) {
1137 GL_INVALID_OPERATION
,
1138 function_name
, "Never used. Did you call glBeginQueryEXT?");
1142 bool valid_value
= false;
1144 case GL_QUERY_RESULT_EXT
:
1145 if (!query
->CheckResultsAvailable(helper_
)) {
1146 helper_
->WaitForToken(query
->token());
1147 if (!query
->CheckResultsAvailable(helper_
)) {
1149 CHECK(query
->CheckResultsAvailable(helper_
));
1152 *params
= query
->GetResult();
1155 case GL_QUERY_RESULT_AVAILABLE_EXT
:
1156 *params
= query
->CheckResultsAvailable(helper_
);
1160 SetGLErrorInvalidEnum(function_name
, pname
, "pname");
1163 GPU_CLIENT_LOG(" " << *params
);
1168 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1169 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1170 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1171 Result
* result
= GetResultAs
<Result
*>();
1176 helper_
->GetMaxValueInBufferCHROMIUM(
1177 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1182 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1183 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1184 GPU_CLIENT_SINGLE_THREAD_CHECK();
1185 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1186 << buffer_id
<< ", " << count
<< ", "
1187 << GLES2Util::GetStringGetMaxIndexType(type
)
1188 << ", " << offset
<< ")");
1189 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1190 buffer_id
, count
, type
, offset
);
1191 GPU_CLIENT_LOG("returned " << result
);
1196 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1198 RestoreArrayBuffer(restore
);
1199 // Restore the element array binding.
1200 // We only need to restore it if it wasn't a client side array.
1201 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1202 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1207 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1209 // Restore the user's current binding.
1210 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_
);
1214 void GLES2Implementation::DrawElements(
1215 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1216 GPU_CLIENT_SINGLE_THREAD_CHECK();
1217 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1218 << GLES2Util::GetStringDrawMode(mode
) << ", "
1220 << GLES2Util::GetStringIndexType(type
) << ", "
1221 << static_cast<const void*>(indices
) << ")");
1222 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1225 void GLES2Implementation::DrawRangeElements(
1226 GLenum mode
, GLuint start
, GLuint end
,
1227 GLsizei count
, GLenum type
, const void* indices
) {
1228 GPU_CLIENT_SINGLE_THREAD_CHECK();
1229 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1230 << GLES2Util::GetStringDrawMode(mode
) << ", "
1231 << start
<< ", " << end
<< ", " << count
<< ", "
1232 << GLES2Util::GetStringIndexType(type
) << ", "
1233 << static_cast<const void*>(indices
) << ")");
1235 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1238 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1241 void GLES2Implementation::DrawElementsImpl(
1242 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1243 const char* func_name
) {
1245 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1248 bool simulated
= false;
1249 GLuint offset
= ToGLuint(indices
);
1251 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1252 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1255 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1256 func_name
, this, helper_
, count
, type
, 0, indices
,
1257 &offset
, &simulated
)) {
1261 helper_
->DrawElements(mode
, count
, type
, offset
);
1262 RestoreElementAndArrayBuffers(simulated
);
1266 void GLES2Implementation::Flush() {
1267 GPU_CLIENT_SINGLE_THREAD_CHECK();
1268 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1269 // Insert the cmd to call glFlush
1274 void GLES2Implementation::ShallowFlushCHROMIUM() {
1275 GPU_CLIENT_SINGLE_THREAD_CHECK();
1276 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1280 void GLES2Implementation::FlushHelper() {
1281 // Flush our command buffer
1282 // (tell the service to execute up to the flush cmd.)
1283 helper_
->CommandBufferHelper::Flush();
1285 if (aggressively_free_resources_
)
1289 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1290 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1291 // Flush command buffer at the GPU channel level. May be implemented as
1293 helper_
->CommandBufferHelper::OrderingBarrier();
1296 void GLES2Implementation::Finish() {
1297 GPU_CLIENT_SINGLE_THREAD_CHECK();
1301 void GLES2Implementation::ShallowFinishCHROMIUM() {
1302 GPU_CLIENT_SINGLE_THREAD_CHECK();
1303 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1304 // Flush our command buffer (tell the service to execute up to the flush cmd
1305 // and don't return until it completes).
1306 helper_
->CommandBufferHelper::Finish();
1308 if (aggressively_free_resources_
)
1312 void GLES2Implementation::FinishHelper() {
1313 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1314 TRACE_EVENT0("gpu", "GLES2::Finish");
1315 // Insert the cmd to call glFinish
1317 // Finish our command buffer
1318 // (tell the service to execute up to the Finish cmd and wait for it to
1320 helper_
->CommandBufferHelper::Finish();
1322 if (aggressively_free_resources_
)
1326 void GLES2Implementation::SwapBuffers() {
1327 GPU_CLIENT_SINGLE_THREAD_CHECK();
1328 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1329 // TODO(piman): Strictly speaking we'd want to insert the token after the
1330 // swap, but the state update with the updated token might not have happened
1331 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1332 // with the GPU process more than needed. So instead, make it happen before.
1333 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1334 // semantics if the client doesn't use the callback mechanism, and by chance
1335 // the scheduler yields between the InsertToken and the SwapBuffers.
1336 swap_buffers_tokens_
.push(helper_
->InsertToken());
1337 helper_
->SwapBuffers();
1338 helper_
->CommandBufferHelper::Flush();
1339 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1340 // compensate for TODO above.
1341 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1342 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1343 swap_buffers_tokens_
.pop();
1347 void GLES2Implementation::SwapInterval(int interval
) {
1348 GPU_CLIENT_SINGLE_THREAD_CHECK();
1349 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1350 << interval
<< ")");
1351 helper_
->SwapInterval(interval
);
1354 void GLES2Implementation::BindAttribLocation(
1355 GLuint program
, GLuint index
, const char* name
) {
1356 GPU_CLIENT_SINGLE_THREAD_CHECK();
1357 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1358 << program
<< ", " << index
<< ", " << name
<< ")");
1359 SetBucketAsString(kResultBucketId
, name
);
1360 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1361 helper_
->SetBucketSize(kResultBucketId
, 0);
1365 void GLES2Implementation::BindUniformLocationCHROMIUM(
1366 GLuint program
, GLint location
, const char* name
) {
1367 GPU_CLIENT_SINGLE_THREAD_CHECK();
1368 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1369 << program
<< ", " << location
<< ", " << name
<< ")");
1370 SetBucketAsString(kResultBucketId
, name
);
1371 helper_
->BindUniformLocationCHROMIUMBucket(
1372 program
, location
, kResultBucketId
);
1373 helper_
->SetBucketSize(kResultBucketId
, 0);
1377 void GLES2Implementation::GetVertexAttribPointerv(
1378 GLuint index
, GLenum pname
, void** ptr
) {
1379 GPU_CLIENT_SINGLE_THREAD_CHECK();
1380 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1381 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1382 << static_cast<void*>(ptr
) << ")");
1383 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1384 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1385 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1386 typedef cmds::GetVertexAttribPointerv::Result Result
;
1387 Result
* result
= GetResultAs
<Result
*>();
1391 result
->SetNumResults(0);
1392 helper_
->GetVertexAttribPointerv(
1393 index
, pname
, GetResultShmId(), GetResultShmOffset());
1395 result
->CopyResult(ptr
);
1396 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1398 GPU_CLIENT_LOG_CODE_BLOCK({
1399 for (int32 i
= 0; i
< num_results
; ++i
) {
1400 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1406 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1407 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1408 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1411 "glDeleteProgram", "id not created by this context.");
1414 if (program
== current_program_
) {
1415 current_program_
= 0;
1420 void GLES2Implementation::DeleteProgramStub(
1421 GLsizei n
, const GLuint
* programs
) {
1423 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1424 helper_
->DeleteProgram(programs
[0]);
1427 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1428 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1429 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1432 "glDeleteShader", "id not created by this context.");
1438 void GLES2Implementation::DeleteShaderStub(
1439 GLsizei n
, const GLuint
* shaders
) {
1441 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1442 helper_
->DeleteShader(shaders
[0]);
1445 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1446 GLuint sync_uint
= ToGLuint(sync
);
1447 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1448 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1451 "glDeleteSync", "id not created by this context.");
1455 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1457 helper_
->DeleteSync(syncs
[0]);
1460 GLint
GLES2Implementation::GetAttribLocationHelper(
1461 GLuint program
, const char* name
) {
1462 typedef cmds::GetAttribLocation::Result Result
;
1463 Result
* result
= GetResultAs
<Result
*>();
1468 SetBucketAsCString(kResultBucketId
, name
);
1469 helper_
->GetAttribLocation(
1470 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1472 helper_
->SetBucketSize(kResultBucketId
, 0);
1476 GLint
GLES2Implementation::GetAttribLocation(
1477 GLuint program
, const char* name
) {
1478 GPU_CLIENT_SINGLE_THREAD_CHECK();
1479 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1480 << ", " << name
<< ")");
1481 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1482 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1483 this, program
, name
);
1484 GPU_CLIENT_LOG("returned " << loc
);
1489 GLint
GLES2Implementation::GetUniformLocationHelper(
1490 GLuint program
, const char* name
) {
1491 typedef cmds::GetUniformLocation::Result Result
;
1492 Result
* result
= GetResultAs
<Result
*>();
1497 SetBucketAsCString(kResultBucketId
, name
);
1498 helper_
->GetUniformLocation(program
, kResultBucketId
,
1499 GetResultShmId(), GetResultShmOffset());
1501 helper_
->SetBucketSize(kResultBucketId
, 0);
1505 GLint
GLES2Implementation::GetUniformLocation(
1506 GLuint program
, const char* name
) {
1507 GPU_CLIENT_SINGLE_THREAD_CHECK();
1508 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1509 << ", " << name
<< ")");
1510 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1511 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1512 this, program
, name
);
1513 GPU_CLIENT_LOG("returned " << loc
);
1518 bool GLES2Implementation::GetUniformIndicesHelper(
1519 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1520 typedef cmds::GetUniformIndices::Result Result
;
1521 Result
* result
= GetResultAs
<Result
*>();
1525 result
->SetNumResults(0);
1526 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1529 helper_
->GetUniformIndices(program
, kResultBucketId
,
1530 GetResultShmId(), GetResultShmOffset());
1532 if (result
->GetNumResults() != count
) {
1535 result
->CopyResult(indices
);
1539 void GLES2Implementation::GetUniformIndices(
1540 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1541 GPU_CLIENT_SINGLE_THREAD_CHECK();
1542 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1543 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1544 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1546 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1552 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1553 this, program
, count
, names
, indices
);
1555 GPU_CLIENT_LOG_CODE_BLOCK({
1556 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1557 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1564 bool GLES2Implementation::GetProgramivHelper(
1565 GLuint program
, GLenum pname
, GLint
* params
) {
1566 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1567 this, program
, pname
, params
);
1568 GPU_CLIENT_LOG_CODE_BLOCK({
1570 GPU_CLIENT_LOG(" 0: " << *params
);
1576 GLint
GLES2Implementation::GetFragDataLocationHelper(
1577 GLuint program
, const char* name
) {
1578 typedef cmds::GetFragDataLocation::Result Result
;
1579 Result
* result
= GetResultAs
<Result
*>();
1584 SetBucketAsCString(kResultBucketId
, name
);
1585 helper_
->GetFragDataLocation(
1586 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1588 helper_
->SetBucketSize(kResultBucketId
, 0);
1592 GLint
GLES2Implementation::GetFragDataLocation(
1593 GLuint program
, const char* name
) {
1594 GPU_CLIENT_SINGLE_THREAD_CHECK();
1595 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1596 << program
<< ", " << name
<< ")");
1597 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1598 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1599 this, program
, name
);
1600 GPU_CLIENT_LOG("returned " << loc
);
1605 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1606 GLuint program
, const char* name
) {
1607 typedef cmds::GetUniformBlockIndex::Result Result
;
1608 Result
* result
= GetResultAs
<Result
*>();
1610 return GL_INVALID_INDEX
;
1612 *result
= GL_INVALID_INDEX
;
1613 SetBucketAsCString(kResultBucketId
, name
);
1614 helper_
->GetUniformBlockIndex(
1615 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1617 helper_
->SetBucketSize(kResultBucketId
, 0);
1621 GLuint
GLES2Implementation::GetUniformBlockIndex(
1622 GLuint program
, const char* name
) {
1623 GPU_CLIENT_SINGLE_THREAD_CHECK();
1624 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1625 << program
<< ", " << name
<< ")");
1626 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1627 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1628 this, program
, name
);
1629 GPU_CLIENT_LOG("returned " << index
);
1634 void GLES2Implementation::LinkProgram(GLuint program
) {
1635 GPU_CLIENT_SINGLE_THREAD_CHECK();
1636 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1637 helper_
->LinkProgram(program
);
1638 share_group_
->program_info_manager()->CreateInfo(program
);
1642 void GLES2Implementation::ShaderBinary(
1643 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1645 GPU_CLIENT_SINGLE_THREAD_CHECK();
1646 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1647 << static_cast<const void*>(shaders
) << ", "
1648 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1649 << static_cast<const void*>(binary
) << ", "
1652 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1656 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1659 // TODO(gman): ShaderBinary should use buckets.
1660 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1661 ScopedTransferBufferArray
<GLint
> buffer(
1662 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1663 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1664 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1667 void* shader_ids
= buffer
.elements();
1668 void* shader_data
= buffer
.elements() + shader_id_size
;
1669 memcpy(shader_ids
, shaders
, shader_id_size
);
1670 memcpy(shader_data
, binary
, length
);
1671 helper_
->ShaderBinary(
1677 buffer
.offset() + shader_id_size
,
1682 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1683 GPU_CLIENT_SINGLE_THREAD_CHECK();
1684 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1685 << GLES2Util::GetStringPixelStore(pname
) << ", "
1688 case GL_PACK_ALIGNMENT
:
1689 pack_alignment_
= param
;
1691 case GL_UNPACK_ALIGNMENT
:
1692 unpack_alignment_
= param
;
1694 case GL_UNPACK_ROW_LENGTH_EXT
:
1695 unpack_row_length_
= param
;
1697 case GL_UNPACK_IMAGE_HEIGHT
:
1698 unpack_image_height_
= param
;
1700 case GL_UNPACK_SKIP_ROWS_EXT
:
1701 unpack_skip_rows_
= param
;
1703 case GL_UNPACK_SKIP_PIXELS_EXT
:
1704 unpack_skip_pixels_
= param
;
1706 case GL_UNPACK_SKIP_IMAGES
:
1707 unpack_skip_images_
= param
;
1709 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1710 pack_reverse_row_order_
=
1711 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1716 helper_
->PixelStorei(pname
, param
);
1720 void GLES2Implementation::VertexAttribIPointer(
1721 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1722 GPU_CLIENT_SINGLE_THREAD_CHECK();
1723 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1726 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1729 // Record the info on the client side.
1730 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1738 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1739 "client side arrays are not allowed in vertex array objects.");
1742 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1743 // Only report NON client side buffers to the service.
1744 if (!ValidateOffset("glVertexAttribIPointer",
1745 reinterpret_cast<GLintptr
>(ptr
))) {
1748 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1753 void GLES2Implementation::VertexAttribPointer(
1754 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1756 GPU_CLIENT_SINGLE_THREAD_CHECK();
1757 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1760 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1761 << GLES2Util::GetStringBool(normalized
) << ", "
1764 // Record the info on the client side.
1765 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1773 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1774 "client side arrays are not allowed in vertex array objects.");
1777 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1778 // Only report NON client side buffers to the service.
1779 if (!ValidateOffset("glVertexAttribPointer",
1780 reinterpret_cast<GLintptr
>(ptr
))) {
1783 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1789 void GLES2Implementation::VertexAttribDivisorANGLE(
1790 GLuint index
, GLuint divisor
) {
1791 GPU_CLIENT_SINGLE_THREAD_CHECK();
1792 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1794 << divisor
<< ") ");
1795 // Record the info on the client side.
1796 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1797 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1801 void GLES2Implementation::BufferDataHelper(
1802 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1803 if (!ValidateSize("glBufferData", size
))
1806 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1807 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1808 // bogus MSan report during a readback later. This is because MSan doesn't
1809 // understand shared memory and would assume we were reading back the same
1810 // unintialized data.
1811 if (data
) __msan_check_mem_is_initialized(data
, size
);
1815 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1820 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1822 RemoveTransferBuffer(buffer
);
1824 // Create new buffer.
1825 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1827 if (buffer
->address() && data
)
1828 memcpy(buffer
->address(), data
, size
);
1832 RemoveMappedBufferRangeByTarget(target
);
1834 // If there is no data just send BufferData
1835 if (size
== 0 || !data
) {
1836 helper_
->BufferData(target
, size
, 0, 0, usage
);
1840 // See if we can send all at once.
1841 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1842 if (!buffer
.valid()) {
1846 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1847 memcpy(buffer
.address(), data
, size
);
1848 helper_
->BufferData(
1857 // Make the buffer with BufferData then send via BufferSubData
1858 helper_
->BufferData(target
, size
, 0, 0, usage
);
1859 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1863 void GLES2Implementation::BufferData(
1864 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1865 GPU_CLIENT_SINGLE_THREAD_CHECK();
1866 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1867 << GLES2Util::GetStringBufferTarget(target
) << ", "
1869 << static_cast<const void*>(data
) << ", "
1870 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1871 BufferDataHelper(target
, size
, data
, usage
);
1875 void GLES2Implementation::BufferSubDataHelper(
1876 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1881 if (!ValidateSize("glBufferSubData", size
) ||
1882 !ValidateOffset("glBufferSubData", offset
)) {
1887 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1891 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1893 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1898 int32 buffer_size
= buffer
->size();
1899 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1900 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1904 if (buffer
->address() && data
)
1905 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1909 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1910 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1913 void GLES2Implementation::BufferSubDataHelperImpl(
1914 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1915 ScopedTransferBufferPtr
* buffer
) {
1919 const int8
* source
= static_cast<const int8
*>(data
);
1921 if (!buffer
->valid() || buffer
->size() == 0) {
1922 buffer
->Reset(size
);
1923 if (!buffer
->valid()) {
1927 memcpy(buffer
->address(), source
, buffer
->size());
1928 helper_
->BufferSubData(
1929 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1930 offset
+= buffer
->size();
1931 source
+= buffer
->size();
1932 size
-= buffer
->size();
1937 void GLES2Implementation::BufferSubData(
1938 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1939 GPU_CLIENT_SINGLE_THREAD_CHECK();
1940 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1941 << GLES2Util::GetStringBufferTarget(target
) << ", "
1942 << offset
<< ", " << size
<< ", "
1943 << static_cast<const void*>(data
) << ")");
1944 BufferSubDataHelper(target
, offset
, size
, data
);
1948 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1949 int32 token
= buffer
->last_usage_token();
1952 if (helper_
->HasTokenPassed(token
))
1953 buffer_tracker_
->Free(buffer
);
1955 buffer_tracker_
->FreePendingToken(buffer
, token
);
1957 buffer_tracker_
->Free(buffer
);
1960 buffer_tracker_
->RemoveBuffer(buffer
->id());
1963 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1965 const char* function_name
,
1966 GLuint
* buffer_id
) {
1970 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1971 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1973 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1974 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1981 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1986 BufferTracker::Buffer
*
1987 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1989 const char* function_name
,
1990 GLuint offset
, GLsizei size
) {
1992 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1994 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1997 if (buffer
->mapped()) {
1998 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
2001 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
2002 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
2008 void GLES2Implementation::CompressedTexImage2D(
2009 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2010 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
2011 GPU_CLIENT_SINGLE_THREAD_CHECK();
2012 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
2013 << GLES2Util::GetStringTextureTarget(target
) << ", "
2015 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2016 << width
<< ", " << height
<< ", " << border
<< ", "
2017 << image_size
<< ", "
2018 << static_cast<const void*>(data
) << ")");
2019 if (width
< 0 || height
< 0 || level
< 0) {
2020 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
2024 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
2027 if (height
== 0 || width
== 0) {
2030 // If there's a pixel unpack buffer bound use it when issuing
2031 // CompressedTexImage2D.
2032 if (bound_pixel_unpack_transfer_buffer_id_
) {
2033 GLuint offset
= ToGLuint(data
);
2034 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2035 bound_pixel_unpack_transfer_buffer_id_
,
2036 "glCompressedTexImage2D", offset
, image_size
);
2037 if (buffer
&& buffer
->shm_id() != -1) {
2038 helper_
->CompressedTexImage2D(
2039 target
, level
, internalformat
, width
, height
, image_size
,
2040 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2041 buffer
->set_last_usage_token(helper_
->InsertToken());
2045 SetBucketContents(kResultBucketId
, data
, image_size
);
2046 helper_
->CompressedTexImage2DBucket(
2047 target
, level
, internalformat
, width
, height
, kResultBucketId
);
2048 // Free the bucket. This is not required but it does free up the memory.
2049 // and we don't have to wait for the result so from the client's perspective
2051 helper_
->SetBucketSize(kResultBucketId
, 0);
2055 void GLES2Implementation::CompressedTexSubImage2D(
2056 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2057 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
2058 GPU_CLIENT_SINGLE_THREAD_CHECK();
2059 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
2060 << GLES2Util::GetStringTextureTarget(target
) << ", "
2062 << xoffset
<< ", " << yoffset
<< ", "
2063 << width
<< ", " << height
<< ", "
2064 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2065 << image_size
<< ", "
2066 << static_cast<const void*>(data
) << ")");
2067 if (width
< 0 || height
< 0 || level
< 0) {
2068 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
2071 // If there's a pixel unpack buffer bound use it when issuing
2072 // CompressedTexSubImage2D.
2073 if (bound_pixel_unpack_transfer_buffer_id_
) {
2074 GLuint offset
= ToGLuint(data
);
2075 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2076 bound_pixel_unpack_transfer_buffer_id_
,
2077 "glCompressedTexSubImage2D", offset
, image_size
);
2078 if (buffer
&& buffer
->shm_id() != -1) {
2079 helper_
->CompressedTexSubImage2D(
2080 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
2081 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2082 buffer
->set_last_usage_token(helper_
->InsertToken());
2087 SetBucketContents(kResultBucketId
, data
, image_size
);
2088 helper_
->CompressedTexSubImage2DBucket(
2089 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
2090 // Free the bucket. This is not required but it does free up the memory.
2091 // and we don't have to wait for the result so from the client's perspective
2093 helper_
->SetBucketSize(kResultBucketId
, 0);
2097 void GLES2Implementation::CompressedTexImage3D(
2098 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2099 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
2101 GPU_CLIENT_SINGLE_THREAD_CHECK();
2102 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
2103 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
2104 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2105 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2106 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
2107 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2108 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
2112 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
2115 if (height
== 0 || width
== 0 || depth
== 0) {
2118 // If there's a pixel unpack buffer bound use it when issuing
2119 // CompressedTexImage3D.
2120 if (bound_pixel_unpack_transfer_buffer_id_
) {
2121 GLuint offset
= ToGLuint(data
);
2122 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2123 bound_pixel_unpack_transfer_buffer_id_
,
2124 "glCompressedTexImage3D", offset
, image_size
);
2125 if (buffer
&& buffer
->shm_id() != -1) {
2126 helper_
->CompressedTexImage3D(
2127 target
, level
, internalformat
, width
, height
, depth
, image_size
,
2128 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2129 buffer
->set_last_usage_token(helper_
->InsertToken());
2133 SetBucketContents(kResultBucketId
, data
, image_size
);
2134 helper_
->CompressedTexImage3DBucket(
2135 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
2136 // Free the bucket. This is not required but it does free up the memory.
2137 // and we don't have to wait for the result so from the client's perspective
2139 helper_
->SetBucketSize(kResultBucketId
, 0);
2143 void GLES2Implementation::CompressedTexSubImage3D(
2144 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2145 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
2146 GLsizei image_size
, const void* data
) {
2147 GPU_CLIENT_SINGLE_THREAD_CHECK();
2148 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
2149 << GLES2Util::GetStringTextureTarget(target
) << ", "
2151 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2152 << width
<< ", " << height
<< ", " << depth
<< ", "
2153 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2154 << image_size
<< ", "
2155 << static_cast<const void*>(data
) << ")");
2156 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2157 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "dimension < 0");
2160 // If there's a pixel unpack buffer bound use it when issuing
2161 // CompressedTexSubImage3D.
2162 if (bound_pixel_unpack_transfer_buffer_id_
) {
2163 GLuint offset
= ToGLuint(data
);
2164 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2165 bound_pixel_unpack_transfer_buffer_id_
,
2166 "glCompressedTexSubImage3D", offset
, image_size
);
2167 if (buffer
&& buffer
->shm_id() != -1) {
2168 helper_
->CompressedTexSubImage3D(
2169 target
, level
, xoffset
, yoffset
, zoffset
,
2170 width
, height
, depth
, format
, image_size
,
2171 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2172 buffer
->set_last_usage_token(helper_
->InsertToken());
2177 SetBucketContents(kResultBucketId
, data
, image_size
);
2178 helper_
->CompressedTexSubImage3DBucket(
2179 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
2181 // Free the bucket. This is not required but it does free up the memory.
2182 // and we don't have to wait for the result so from the client's perspective
2184 helper_
->SetBucketSize(kResultBucketId
, 0);
2190 void CopyRectToBuffer(
2193 uint32 unpadded_row_size
,
2194 uint32 pixels_padded_row_size
,
2196 uint32 buffer_padded_row_size
) {
2197 const int8
* source
= static_cast<const int8
*>(pixels
);
2198 int8
* dest
= static_cast<int8
*>(buffer
);
2199 if (pixels_padded_row_size
!= buffer_padded_row_size
) {
2200 // the last row is copied unpadded at the end
2201 for (; height
> 1; --height
) {
2202 memcpy(dest
, source
, buffer_padded_row_size
);
2203 dest
+= buffer_padded_row_size
;
2204 source
+= pixels_padded_row_size
;
2206 memcpy(dest
, source
, unpadded_row_size
);
2208 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2209 memcpy(dest
, source
, size
);
2213 } // anonymous namespace
2215 void GLES2Implementation::TexImage2D(
2216 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2217 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2218 const void* pixels
) {
2219 GPU_CLIENT_SINGLE_THREAD_CHECK();
2220 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2221 << GLES2Util::GetStringTextureTarget(target
) << ", "
2223 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2224 << width
<< ", " << height
<< ", " << border
<< ", "
2225 << GLES2Util::GetStringTextureFormat(format
) << ", "
2226 << GLES2Util::GetStringPixelType(type
) << ", "
2227 << static_cast<const void*>(pixels
) << ")");
2228 if (level
< 0 || height
< 0 || width
< 0) {
2229 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2233 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2237 uint32 unpadded_row_size
;
2238 uint32 padded_row_size
;
2239 if (!GLES2Util::ComputeImageDataSizes(
2240 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2241 &unpadded_row_size
, &padded_row_size
)) {
2242 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2246 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2247 if (bound_pixel_unpack_transfer_buffer_id_
) {
2248 GLuint offset
= ToGLuint(pixels
);
2249 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2250 bound_pixel_unpack_transfer_buffer_id_
,
2251 "glTexImage2D", offset
, size
);
2252 if (buffer
&& buffer
->shm_id() != -1) {
2253 helper_
->TexImage2D(
2254 target
, level
, internalformat
, width
, height
, format
, type
,
2255 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2256 buffer
->set_last_usage_token(helper_
->InsertToken());
2262 // If there's no data just issue TexImage2D
2264 helper_
->TexImage2D(
2265 target
, level
, internalformat
, width
, height
, format
, type
,
2271 // compute the advance bytes per row for the src pixels
2272 uint32 src_padded_row_size
;
2273 if (unpack_row_length_
> 0) {
2274 if (!GLES2Util::ComputeImagePaddedRowSize(
2275 unpack_row_length_
, format
, type
, unpack_alignment_
,
2276 &src_padded_row_size
)) {
2278 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2282 src_padded_row_size
= padded_row_size
;
2285 // advance pixels pointer past the skip rows and skip pixels
2286 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2287 unpack_skip_rows_
* src_padded_row_size
;
2288 if (unpack_skip_pixels_
) {
2289 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2290 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2291 unpack_skip_pixels_
* group_size
;
2294 // Check if we can send it all at once.
2296 uint32_t shm_offset
= 0;
2297 void* buffer_pointer
= nullptr;
2299 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2300 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2302 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2303 shm_id
= transfer_alloc
.shm_id();
2304 shm_offset
= transfer_alloc
.offset();
2305 buffer_pointer
= transfer_alloc
.address();
2307 mapped_alloc
.Reset(size
);
2308 if (mapped_alloc
.valid()) {
2309 transfer_alloc
.Discard();
2311 mapped_alloc
.SetFlushAfterRelease(true);
2312 shm_id
= mapped_alloc
.shm_id();
2313 shm_offset
= mapped_alloc
.offset();
2314 buffer_pointer
= mapped_alloc
.address();
2318 if (buffer_pointer
) {
2320 pixels
, height
, unpadded_row_size
, src_padded_row_size
,
2321 buffer_pointer
, padded_row_size
);
2322 helper_
->TexImage2D(
2323 target
, level
, internalformat
, width
, height
, format
, type
,
2324 shm_id
, shm_offset
);
2329 // No, so send it using TexSubImage2D.
2330 helper_
->TexImage2D(
2331 target
, level
, internalformat
, width
, height
, format
, type
,
2334 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2335 pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
, padded_row_size
);
2339 void GLES2Implementation::TexImage3D(
2340 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2341 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2342 const void* pixels
) {
2343 GPU_CLIENT_SINGLE_THREAD_CHECK();
2344 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2345 << GLES2Util::GetStringTextureTarget(target
) << ", "
2347 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2348 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2349 << GLES2Util::GetStringTextureFormat(format
) << ", "
2350 << GLES2Util::GetStringPixelType(type
) << ", "
2351 << static_cast<const void*>(pixels
) << ")");
2352 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2353 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2357 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2361 uint32 unpadded_row_size
;
2362 uint32 padded_row_size
;
2363 if (!GLES2Util::ComputeImageDataSizes(
2364 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2365 &unpadded_row_size
, &padded_row_size
)) {
2366 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2370 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2371 if (bound_pixel_unpack_transfer_buffer_id_
) {
2372 GLuint offset
= ToGLuint(pixels
);
2373 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2374 bound_pixel_unpack_transfer_buffer_id_
,
2375 "glTexImage3D", offset
, size
);
2376 if (buffer
&& buffer
->shm_id() != -1) {
2377 helper_
->TexImage3D(
2378 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2379 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2380 buffer
->set_last_usage_token(helper_
->InsertToken());
2386 // If there's no data just issue TexImage3D
2388 helper_
->TexImage3D(
2389 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2395 // compute the advance bytes per row for the src pixels
2396 uint32 src_padded_row_size
;
2397 if (unpack_row_length_
> 0) {
2398 if (!GLES2Util::ComputeImagePaddedRowSize(
2399 unpack_row_length_
, format
, type
, unpack_alignment_
,
2400 &src_padded_row_size
)) {
2402 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2406 src_padded_row_size
= padded_row_size
;
2408 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2410 // advance pixels pointer past the skip images/rows/pixels
2411 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2412 unpack_skip_images_
* src_padded_row_size
* src_height
+
2413 unpack_skip_rows_
* src_padded_row_size
;
2414 if (unpack_skip_pixels_
) {
2415 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2416 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2417 unpack_skip_pixels_
* group_size
;
2420 // Check if we can send it all at once.
2422 uint32_t shm_offset
= 0;
2423 void* buffer_pointer
= nullptr;
2425 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2426 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2428 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2429 shm_id
= transfer_alloc
.shm_id();
2430 shm_offset
= transfer_alloc
.offset();
2431 buffer_pointer
= transfer_alloc
.address();
2433 mapped_alloc
.Reset(size
);
2434 if (mapped_alloc
.valid()) {
2435 transfer_alloc
.Discard();
2437 mapped_alloc
.SetFlushAfterRelease(true);
2438 shm_id
= mapped_alloc
.shm_id();
2439 shm_offset
= mapped_alloc
.offset();
2440 buffer_pointer
= mapped_alloc
.address();
2444 if (buffer_pointer
) {
2445 for (GLsizei z
= 0; z
< depth
; ++z
) {
2446 // Only the last row of the last image is unpadded.
2447 uint32 src_unpadded_row_size
=
2448 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2450 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
,
2451 buffer_pointer
, padded_row_size
);
2452 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2453 src_padded_row_size
* src_height
;
2454 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2455 padded_row_size
* height
;
2457 helper_
->TexImage3D(
2458 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2459 shm_id
, shm_offset
);
2464 // No, so send it using TexSubImage3D.
2465 helper_
->TexImage3D(
2466 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2469 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2470 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
,
2475 void GLES2Implementation::TexSubImage2D(
2476 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2477 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2478 GPU_CLIENT_SINGLE_THREAD_CHECK();
2479 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2480 << GLES2Util::GetStringTextureTarget(target
) << ", "
2482 << xoffset
<< ", " << yoffset
<< ", "
2483 << width
<< ", " << height
<< ", "
2484 << GLES2Util::GetStringTextureFormat(format
) << ", "
2485 << GLES2Util::GetStringPixelType(type
) << ", "
2486 << static_cast<const void*>(pixels
) << ")");
2488 if (level
< 0 || height
< 0 || width
< 0) {
2489 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2492 if (height
== 0 || width
== 0) {
2497 uint32 unpadded_row_size
;
2498 uint32 padded_row_size
;
2499 if (!GLES2Util::ComputeImageDataSizes(
2500 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2501 &unpadded_row_size
, &padded_row_size
)) {
2502 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2506 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2507 if (bound_pixel_unpack_transfer_buffer_id_
) {
2508 GLuint offset
= ToGLuint(pixels
);
2509 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2510 bound_pixel_unpack_transfer_buffer_id_
,
2511 "glTexSubImage2D", offset
, temp_size
);
2512 if (buffer
&& buffer
->shm_id() != -1) {
2513 helper_
->TexSubImage2D(
2514 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2515 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2516 buffer
->set_last_usage_token(helper_
->InsertToken());
2522 // compute the advance bytes per row for the src pixels
2523 uint32 src_padded_row_size
;
2524 if (unpack_row_length_
> 0) {
2525 if (!GLES2Util::ComputeImagePaddedRowSize(
2526 unpack_row_length_
, format
, type
, unpack_alignment_
,
2527 &src_padded_row_size
)) {
2529 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2533 src_padded_row_size
= padded_row_size
;
2536 // advance pixels pointer past the skip rows and skip pixels
2537 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2538 unpack_skip_rows_
* src_padded_row_size
;
2539 if (unpack_skip_pixels_
) {
2540 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2541 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2542 unpack_skip_pixels_
* group_size
;
2545 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2547 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2548 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2553 void GLES2Implementation::TexSubImage3D(
2554 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2555 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2556 const void* pixels
) {
2557 GPU_CLIENT_SINGLE_THREAD_CHECK();
2558 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2559 << GLES2Util::GetStringTextureTarget(target
) << ", "
2561 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2562 << width
<< ", " << height
<< ", " << depth
<< ", "
2563 << GLES2Util::GetStringTextureFormat(format
) << ", "
2564 << GLES2Util::GetStringPixelType(type
) << ", "
2565 << static_cast<const void*>(pixels
) << ")");
2567 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2568 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2571 if (height
== 0 || width
== 0 || depth
== 0) {
2576 uint32 unpadded_row_size
;
2577 uint32 padded_row_size
;
2578 if (!GLES2Util::ComputeImageDataSizes(
2579 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2580 &unpadded_row_size
, &padded_row_size
)) {
2581 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2585 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2586 if (bound_pixel_unpack_transfer_buffer_id_
) {
2587 GLuint offset
= ToGLuint(pixels
);
2588 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2589 bound_pixel_unpack_transfer_buffer_id_
,
2590 "glTexSubImage3D", offset
, temp_size
);
2591 if (buffer
&& buffer
->shm_id() != -1) {
2592 helper_
->TexSubImage3D(
2593 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2594 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2595 buffer
->set_last_usage_token(helper_
->InsertToken());
2601 // compute the advance bytes per row for the src pixels
2602 uint32 src_padded_row_size
;
2603 if (unpack_row_length_
> 0) {
2604 if (!GLES2Util::ComputeImagePaddedRowSize(
2605 unpack_row_length_
, format
, type
, unpack_alignment_
,
2606 &src_padded_row_size
)) {
2608 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2612 src_padded_row_size
= padded_row_size
;
2614 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2616 // advance pixels pointer past the skip images/rows/pixels
2617 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2618 unpack_skip_images_
* src_padded_row_size
* src_height
+
2619 unpack_skip_rows_
* src_padded_row_size
;
2620 if (unpack_skip_pixels_
) {
2621 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2622 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2623 unpack_skip_pixels_
* group_size
;
2626 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2628 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2629 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2630 &buffer
, padded_row_size
);
2634 static GLint
ComputeNumRowsThatFitInBuffer(
2635 uint32 padded_row_size
, uint32 unpadded_row_size
,
2636 unsigned int size
, GLsizei remaining_rows
) {
2637 DCHECK_GE(unpadded_row_size
, 0u);
2638 if (padded_row_size
== 0) {
2641 GLint num_rows
= size
/ padded_row_size
;
2642 if (num_rows
+ 1 == remaining_rows
&&
2643 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2649 void GLES2Implementation::TexSubImage2DImpl(
2650 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2651 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2652 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2653 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2655 DCHECK_GE(level
, 0);
2656 DCHECK_GT(height
, 0);
2657 DCHECK_GT(width
, 0);
2659 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2660 // Transfer by rows.
2662 unsigned int desired_size
=
2663 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2664 if (!buffer
->valid() || buffer
->size() == 0) {
2665 buffer
->Reset(desired_size
);
2666 if (!buffer
->valid()) {
2671 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2672 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2673 num_rows
= std::min(num_rows
, height
);
2675 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2676 buffer
->address(), buffer_padded_row_size
);
2677 helper_
->TexSubImage2D(
2678 target
, level
, xoffset
, yoffset
, width
, num_rows
, format
, type
,
2679 buffer
->shm_id(), buffer
->offset(), internal
);
2681 yoffset
+= num_rows
;
2682 source
+= num_rows
* pixels_padded_row_size
;
2687 void GLES2Implementation::TexSubImage3DImpl(
2688 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2689 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2690 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2691 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2692 uint32 buffer_padded_row_size
) {
2694 DCHECK_GE(level
, 0);
2695 DCHECK_GT(height
, 0);
2696 DCHECK_GT(width
, 0);
2697 DCHECK_GT(depth
, 0);
2698 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2699 GLsizei total_rows
= height
* depth
;
2700 GLint row_index
= 0, depth_index
= 0;
2701 while (total_rows
) {
2702 // Each time, we either copy one or more images, or copy one or more rows
2703 // within a single image, depending on the buffer size limit.
2705 unsigned int desired_size
;
2706 if (row_index
> 0) {
2707 // We are in the middle of an image. Send the remaining of the image.
2708 max_rows
= height
- row_index
;
2709 if (total_rows
<= height
) {
2710 // Last image, so last row is unpadded.
2711 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2714 desired_size
= buffer_padded_row_size
* max_rows
;
2717 // Send all the remaining data if possible.
2718 max_rows
= total_rows
;
2720 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2722 if (!buffer
->valid() || buffer
->size() == 0) {
2723 buffer
->Reset(desired_size
);
2724 if (!buffer
->valid()) {
2728 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2729 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2730 num_rows
= std::min(num_rows
, max_rows
);
2731 GLint num_images
= num_rows
/ height
;
2732 GLsizei my_height
, my_depth
;
2733 if (num_images
> 0) {
2734 num_rows
= num_images
* height
;
2736 my_depth
= num_images
;
2738 my_height
= num_rows
;
2742 if (num_images
> 0) {
2743 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2745 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2746 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2747 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2748 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2749 uint32 my_unpadded_row_size
;
2750 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2751 my_unpadded_row_size
= unpadded_row_size
;
2753 my_unpadded_row_size
= pixels_padded_row_size
;
2755 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2756 pixels_padded_row_size
, buffer_pointer
+ ii
* image_size_dst
,
2757 buffer_padded_row_size
);
2760 uint32 my_unpadded_row_size
;
2761 if (total_rows
== num_rows
)
2762 my_unpadded_row_size
= unpadded_row_size
;
2764 my_unpadded_row_size
= pixels_padded_row_size
;
2766 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2767 buffer
->address(), buffer_padded_row_size
);
2769 helper_
->TexSubImage3D(
2770 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2771 width
, my_height
, my_depth
,
2772 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2775 total_rows
-= num_rows
;
2776 if (total_rows
> 0) {
2777 GLint num_image_paddings
;
2778 if (num_images
> 0) {
2779 DCHECK_EQ(row_index
, 0);
2780 depth_index
+= num_images
;
2781 num_image_paddings
= num_images
;
2783 row_index
= (row_index
+ my_height
) % height
;
2784 num_image_paddings
= 0;
2785 if (my_height
> 0 && row_index
== 0) {
2787 num_image_paddings
++;
2790 source
+= num_rows
* pixels_padded_row_size
;
2791 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2792 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2793 pixels_padded_row_size
;
2799 bool GLES2Implementation::GetActiveAttribHelper(
2800 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2801 GLenum
* type
, char* name
) {
2802 // Clear the bucket so if the command fails nothing will be in it.
2803 helper_
->SetBucketSize(kResultBucketId
, 0);
2804 typedef cmds::GetActiveAttrib::Result Result
;
2805 Result
* result
= GetResultAs
<Result
*>();
2809 // Set as failed so if the command fails we'll recover.
2810 result
->success
= false;
2811 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2812 GetResultShmId(), GetResultShmOffset());
2814 if (result
->success
) {
2816 *size
= result
->size
;
2819 *type
= result
->type
;
2821 if (length
|| name
) {
2822 std::vector
<int8
> str
;
2823 GetBucketContents(kResultBucketId
, &str
);
2824 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2825 std::max(static_cast<size_t>(0),
2830 if (name
&& bufsize
> 0) {
2831 memcpy(name
, &str
[0], max_size
);
2832 name
[max_size
] = '\0';
2836 return result
->success
!= 0;
2839 void GLES2Implementation::GetActiveAttrib(
2840 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2841 GLenum
* type
, char* name
) {
2842 GPU_CLIENT_SINGLE_THREAD_CHECK();
2843 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2844 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2845 << static_cast<const void*>(length
) << ", "
2846 << static_cast<const void*>(size
) << ", "
2847 << static_cast<const void*>(type
) << ", "
2848 << static_cast<const void*>(name
) << ", ");
2850 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2853 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2854 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2855 this, program
, index
, bufsize
, length
, size
, type
, name
);
2858 GPU_CLIENT_LOG(" size: " << *size
);
2861 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2864 GPU_CLIENT_LOG(" name: " << name
);
2870 bool GLES2Implementation::GetActiveUniformHelper(
2871 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2872 GLenum
* type
, char* name
) {
2873 // Clear the bucket so if the command fails nothing will be in it.
2874 helper_
->SetBucketSize(kResultBucketId
, 0);
2875 typedef cmds::GetActiveUniform::Result Result
;
2876 Result
* result
= GetResultAs
<Result
*>();
2880 // Set as failed so if the command fails we'll recover.
2881 result
->success
= false;
2882 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2883 GetResultShmId(), GetResultShmOffset());
2885 if (result
->success
) {
2887 *size
= result
->size
;
2890 *type
= result
->type
;
2892 if (length
|| name
) {
2893 std::vector
<int8
> str
;
2894 GetBucketContents(kResultBucketId
, &str
);
2895 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2896 std::max(static_cast<size_t>(0),
2901 if (name
&& bufsize
> 0) {
2902 memcpy(name
, &str
[0], max_size
);
2903 name
[max_size
] = '\0';
2907 return result
->success
!= 0;
2910 void GLES2Implementation::GetActiveUniform(
2911 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2912 GLenum
* type
, char* name
) {
2913 GPU_CLIENT_SINGLE_THREAD_CHECK();
2914 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2915 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2916 << static_cast<const void*>(length
) << ", "
2917 << static_cast<const void*>(size
) << ", "
2918 << static_cast<const void*>(type
) << ", "
2919 << static_cast<const void*>(name
) << ", ");
2921 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2924 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2925 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2926 this, program
, index
, bufsize
, length
, size
, type
, name
);
2929 GPU_CLIENT_LOG(" size: " << *size
);
2932 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2935 GPU_CLIENT_LOG(" name: " << name
);
2941 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2942 GLuint program
, GLuint index
, GLsizei bufsize
,
2943 GLsizei
* length
, char* name
) {
2944 DCHECK_LE(0, bufsize
);
2945 // Clear the bucket so if the command fails nothing will be in it.
2946 helper_
->SetBucketSize(kResultBucketId
, 0);
2947 typedef cmds::GetActiveUniformBlockName::Result Result
;
2948 Result
* result
= GetResultAs
<Result
*>();
2952 // Set as failed so if the command fails we'll recover.
2954 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2955 GetResultShmId(), GetResultShmOffset());
2962 } else if (length
|| name
) {
2963 std::vector
<int8
> str
;
2964 GetBucketContents(kResultBucketId
, &str
);
2965 DCHECK_GT(str
.size(), 0u);
2967 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2972 memcpy(name
, &str
[0], max_size
);
2973 name
[max_size
] = '\0';
2977 return *result
!= 0;
2980 void GLES2Implementation::GetActiveUniformBlockName(
2981 GLuint program
, GLuint index
, GLsizei bufsize
,
2982 GLsizei
* length
, char* name
) {
2983 GPU_CLIENT_SINGLE_THREAD_CHECK();
2984 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2985 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2986 << static_cast<const void*>(length
) << ", "
2987 << static_cast<const void*>(name
) << ")");
2989 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2992 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2994 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2995 this, program
, index
, bufsize
, length
, name
);
2998 GPU_CLIENT_LOG(" name: " << name
);
3004 bool GLES2Implementation::GetActiveUniformBlockivHelper(
3005 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
3006 typedef cmds::GetActiveUniformBlockiv::Result Result
;
3007 Result
* result
= GetResultAs
<Result
*>();
3011 result
->SetNumResults(0);
3012 helper_
->GetActiveUniformBlockiv(
3013 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
3015 if (result
->GetNumResults() > 0) {
3017 result
->CopyResult(params
);
3019 GPU_CLIENT_LOG_CODE_BLOCK({
3020 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3021 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3029 void GLES2Implementation::GetActiveUniformBlockiv(
3030 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
3031 GPU_CLIENT_SINGLE_THREAD_CHECK();
3032 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
3033 << program
<< ", " << index
<< ", "
3034 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
3035 << static_cast<const void*>(params
) << ")");
3036 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
3038 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
3039 this, program
, index
, pname
, params
);
3042 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
3043 // be more than one value returned in params.
3044 GPU_CLIENT_LOG(" params: " << params
[0]);
3050 bool GLES2Implementation::GetActiveUniformsivHelper(
3051 GLuint program
, GLsizei count
, const GLuint
* indices
,
3052 GLenum pname
, GLint
* params
) {
3053 typedef cmds::GetActiveUniformsiv::Result Result
;
3054 Result
* result
= GetResultAs
<Result
*>();
3058 result
->SetNumResults(0);
3059 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
3060 bytes
*= sizeof(GLuint
);
3061 if (!bytes
.IsValid()) {
3062 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
3065 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
3066 helper_
->GetActiveUniformsiv(
3067 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
3069 bool success
= result
->GetNumResults() == count
;
3072 result
->CopyResult(params
);
3074 GPU_CLIENT_LOG_CODE_BLOCK({
3075 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
3076 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3080 helper_
->SetBucketSize(kResultBucketId
, 0);
3084 void GLES2Implementation::GetActiveUniformsiv(
3085 GLuint program
, GLsizei count
, const GLuint
* indices
,
3086 GLenum pname
, GLint
* params
) {
3087 GPU_CLIENT_SINGLE_THREAD_CHECK();
3088 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
3089 << program
<< ", " << count
<< ", "
3090 << static_cast<const void*>(indices
) << ", "
3091 << GLES2Util::GetStringUniformParameter(pname
) << ", "
3092 << static_cast<const void*>(params
) << ")");
3093 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
3095 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
3098 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
3099 this, program
, count
, indices
, pname
, params
);
3102 GPU_CLIENT_LOG_CODE_BLOCK({
3103 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
3104 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
3112 void GLES2Implementation::GetAttachedShaders(
3113 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
3114 GPU_CLIENT_SINGLE_THREAD_CHECK();
3115 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
3116 << program
<< ", " << maxcount
<< ", "
3117 << static_cast<const void*>(count
) << ", "
3118 << static_cast<const void*>(shaders
) << ", ");
3120 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
3123 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
3124 typedef cmds::GetAttachedShaders::Result Result
;
3125 uint32 size
= Result::ComputeSize(maxcount
);
3126 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
3130 result
->SetNumResults(0);
3131 helper_
->GetAttachedShaders(
3133 transfer_buffer_
->GetShmId(),
3134 transfer_buffer_
->GetOffset(result
),
3136 int32 token
= helper_
->InsertToken();
3139 *count
= result
->GetNumResults();
3141 result
->CopyResult(shaders
);
3142 GPU_CLIENT_LOG_CODE_BLOCK({
3143 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3144 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3147 transfer_buffer_
->FreePendingToken(result
, token
);
3151 void GLES2Implementation::GetShaderPrecisionFormat(
3152 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
3153 GPU_CLIENT_SINGLE_THREAD_CHECK();
3154 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
3155 << GLES2Util::GetStringShaderType(shadertype
) << ", "
3156 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
3157 << static_cast<const void*>(range
) << ", "
3158 << static_cast<const void*>(precision
) << ", ");
3159 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
3160 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3161 Result
* result
= GetResultAs
<Result
*>();
3166 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
3167 GLStaticState::ShaderPrecisionMap::iterator i
=
3168 static_state_
.shader_precisions
.find(key
);
3169 if (i
!= static_state_
.shader_precisions
.end()) {
3170 *result
= i
->second
;
3172 result
->success
= false;
3173 helper_
->GetShaderPrecisionFormat(
3174 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
3176 if (result
->success
)
3177 static_state_
.shader_precisions
[key
] = *result
;
3180 if (result
->success
) {
3182 range
[0] = result
->min_range
;
3183 range
[1] = result
->max_range
;
3184 GPU_CLIENT_LOG(" min_range: " << range
[0]);
3185 GPU_CLIENT_LOG(" min_range: " << range
[1]);
3188 precision
[0] = result
->precision
;
3189 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
3195 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
3196 const char* result
= NULL
;
3197 // Clears the bucket so if the command fails nothing will be in it.
3198 helper_
->SetBucketSize(kResultBucketId
, 0);
3199 helper_
->GetString(name
, kResultBucketId
);
3201 if (GetBucketAsString(kResultBucketId
, &str
)) {
3202 // Adds extensions implemented on client side only.
3205 str
+= std::string(str
.empty() ? "" : " ") +
3206 "GL_EXT_unpack_subimage "
3207 "GL_CHROMIUM_map_sub";
3208 if (capabilities_
.image
)
3209 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
3210 if (capabilities_
.future_sync_points
)
3211 str
+= " GL_CHROMIUM_future_sync_point";
3217 // Because of WebGL the extensions can change. We have to cache each unique
3218 // result since we don't know when the client will stop referring to a
3219 // previous one it queries.
3220 GLStringMap::iterator it
= gl_strings_
.find(name
);
3221 if (it
== gl_strings_
.end()) {
3222 std::set
<std::string
> strings
;
3223 std::pair
<GLStringMap::iterator
, bool> insert_result
=
3224 gl_strings_
.insert(std::make_pair(name
, strings
));
3225 DCHECK(insert_result
.second
);
3226 it
= insert_result
.first
;
3228 std::set
<std::string
>& string_set
= it
->second
;
3229 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
3230 if (sit
!= string_set
.end()) {
3231 result
= sit
->c_str();
3233 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3234 string_set
.insert(str
);
3235 DCHECK(insert_result
.second
);
3236 result
= insert_result
.first
->c_str();
3239 return reinterpret_cast<const GLubyte
*>(result
);
3242 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3243 GPU_CLIENT_SINGLE_THREAD_CHECK();
3244 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3245 << GLES2Util::GetStringStringType(name
) << ")");
3246 TRACE_EVENT0("gpu", "GLES2::GetString");
3247 const GLubyte
* result
= GetStringHelper(name
);
3248 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3253 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3254 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3255 GLenum
* type
, char* name
) {
3256 // Clear the bucket so if the command fails nothing will be in it.
3257 helper_
->SetBucketSize(kResultBucketId
, 0);
3258 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3259 Result
* result
= GetResultAs
<Result
*>();
3263 // Set as failed so if the command fails we'll recover.
3264 result
->success
= false;
3265 helper_
->GetTransformFeedbackVarying(
3266 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3268 if (result
->success
) {
3270 *size
= result
->size
;
3273 *type
= result
->type
;
3275 if (length
|| name
) {
3276 std::vector
<int8
> str
;
3277 GetBucketContents(kResultBucketId
, &str
);
3278 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3287 memcpy(name
, &str
[0], max_size
);
3288 name
[max_size
] = '\0';
3289 } else if (bufsize
> 0) {
3295 return result
->success
!= 0;
3298 void GLES2Implementation::GetTransformFeedbackVarying(
3299 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3300 GLenum
* type
, char* name
) {
3301 GPU_CLIENT_SINGLE_THREAD_CHECK();
3302 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3303 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3304 << static_cast<const void*>(length
) << ", "
3305 << static_cast<const void*>(size
) << ", "
3306 << static_cast<const void*>(type
) << ", "
3307 << static_cast<const void*>(name
) << ", ");
3309 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3313 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3315 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3316 this, program
, index
, bufsize
, length
, size
, type
, name
);
3319 GPU_CLIENT_LOG(" size: " << *size
);
3322 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3325 GPU_CLIENT_LOG(" name: " << name
);
3331 void GLES2Implementation::GetUniformfv(
3332 GLuint program
, GLint location
, GLfloat
* params
) {
3333 GPU_CLIENT_SINGLE_THREAD_CHECK();
3334 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3335 << program
<< ", " << location
<< ", "
3336 << static_cast<const void*>(params
) << ")");
3337 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3338 typedef cmds::GetUniformfv::Result Result
;
3339 Result
* result
= GetResultAs
<Result
*>();
3343 result
->SetNumResults(0);
3344 helper_
->GetUniformfv(
3345 program
, location
, GetResultShmId(), GetResultShmOffset());
3347 result
->CopyResult(params
);
3348 GPU_CLIENT_LOG_CODE_BLOCK({
3349 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3350 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3356 void GLES2Implementation::GetUniformiv(
3357 GLuint program
, GLint location
, GLint
* params
) {
3358 GPU_CLIENT_SINGLE_THREAD_CHECK();
3359 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3360 << program
<< ", " << location
<< ", "
3361 << static_cast<const void*>(params
) << ")");
3362 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3363 typedef cmds::GetUniformiv::Result Result
;
3364 Result
* result
= GetResultAs
<Result
*>();
3368 result
->SetNumResults(0);
3369 helper_
->GetUniformiv(
3370 program
, location
, GetResultShmId(), GetResultShmOffset());
3372 GetResultAs
<cmds::GetUniformiv::Result
*>()->CopyResult(params
);
3373 GPU_CLIENT_LOG_CODE_BLOCK({
3374 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3375 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3381 void GLES2Implementation::GetUniformuiv(
3382 GLuint program
, GLint location
, GLuint
* params
) {
3383 GPU_CLIENT_SINGLE_THREAD_CHECK();
3384 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv("
3385 << program
<< ", " << location
<< ", "
3386 << static_cast<const void*>(params
) << ")");
3387 TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
3388 typedef cmds::GetUniformuiv::Result Result
;
3389 Result
* result
= GetResultAs
<Result
*>();
3393 result
->SetNumResults(0);
3394 helper_
->GetUniformuiv(
3395 program
, location
, GetResultShmId(), GetResultShmOffset());
3397 GetResultAs
<cmds::GetUniformuiv::Result
*>()->CopyResult(params
);
3398 GPU_CLIENT_LOG_CODE_BLOCK({
3399 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3400 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3406 void GLES2Implementation::ReadPixels(
3407 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3408 GLenum type
, void* pixels
) {
3409 GPU_CLIENT_SINGLE_THREAD_CHECK();
3410 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3411 << xoffset
<< ", " << yoffset
<< ", "
3412 << width
<< ", " << height
<< ", "
3413 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3414 << GLES2Util::GetStringPixelType(type
) << ", "
3415 << static_cast<const void*>(pixels
) << ")");
3416 if (width
< 0 || height
< 0) {
3417 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3420 if (width
== 0 || height
== 0) {
3424 // glReadPixel pads the size of each row of pixels by an amount specified by
3425 // glPixelStorei. So, we have to take that into account both in the fact that
3426 // the pixels returned from the ReadPixel command will include that padding
3427 // and that when we copy the results to the user's buffer we need to not
3428 // write those padding bytes but leave them as they are.
3430 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3431 typedef cmds::ReadPixels::Result Result
;
3433 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3435 uint32 unpadded_row_size
;
3436 uint32 padded_row_size
;
3437 if (!GLES2Util::ComputeImageDataSizes(
3438 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3439 &unpadded_row_size
, &padded_row_size
)) {
3440 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3444 if (bound_pixel_pack_transfer_buffer_id_
) {
3445 GLuint offset
= ToGLuint(pixels
);
3446 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3447 bound_pixel_pack_transfer_buffer_id_
,
3448 "glReadPixels", offset
, padded_row_size
* height
);
3449 if (buffer
&& buffer
->shm_id() != -1) {
3450 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3451 buffer
->shm_id(), buffer
->shm_offset(),
3459 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3463 // Transfer by rows.
3464 // The max rows we can transfer.
3466 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3467 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3468 if (!buffer
.valid()) {
3471 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3472 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3473 num_rows
= std::min(num_rows
, height
);
3474 // NOTE: We must look up the address of the result area AFTER allocation
3475 // of the transfer buffer since the transfer buffer may be reallocated.
3476 Result
* result
= GetResultAs
<Result
*>();
3480 *result
= 0; // mark as failed.
3481 helper_
->ReadPixels(
3482 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3483 buffer
.shm_id(), buffer
.offset(),
3484 GetResultShmId(), GetResultShmOffset(),
3488 // when doing a y-flip we have to iterate through top-to-bottom chunks
3489 // of the dst. The service side handles reversing the rows within a
3492 if (pack_reverse_row_order_
) {
3493 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3497 // We have to copy 1 row at a time to avoid writing pad bytes.
3498 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3499 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3500 memcpy(rows_dst
, src
, unpadded_row_size
);
3501 rows_dst
+= padded_row_size
;
3502 src
+= padded_row_size
;
3504 if (!pack_reverse_row_order_
) {
3508 // If it was not marked as successful exit.
3512 yoffset
+= num_rows
;
3518 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3519 GPU_CLIENT_SINGLE_THREAD_CHECK();
3520 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3521 << GLES2Util::GetStringEnum(texture
) << ")");
3522 GLuint texture_index
= texture
- GL_TEXTURE0
;
3523 if (texture_index
>=
3524 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3525 SetGLErrorInvalidEnum(
3526 "glActiveTexture", texture
, "texture");
3530 active_texture_unit_
= texture_index
;
3531 helper_
->ActiveTexture(texture
);
3535 void GLES2Implementation::GenBuffersHelper(
3536 GLsizei
/* n */, const GLuint
* /* buffers */) {
3539 void GLES2Implementation::GenFramebuffersHelper(
3540 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3543 void GLES2Implementation::GenRenderbuffersHelper(
3544 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3547 void GLES2Implementation::GenTexturesHelper(
3548 GLsizei
/* n */, const GLuint
* /* textures */) {
3551 void GLES2Implementation::GenVertexArraysOESHelper(
3552 GLsizei n
, const GLuint
* arrays
) {
3553 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3556 void GLES2Implementation::GenQueriesEXTHelper(
3557 GLsizei
/* n */, const GLuint
* /* queries */) {
3560 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3562 const GLuint
* /* valuebuffers */) {
3565 void GLES2Implementation::GenSamplersHelper(
3566 GLsizei
/* n */, const GLuint
* /* samplers */) {
3569 void GLES2Implementation::GenTransformFeedbacksHelper(
3570 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3573 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3574 // generates a new resource. On newer versions of OpenGL they don't. The code
3575 // related to binding below will need to change if we switch to the new OpenGL
3576 // model. Specifically it assumes a bind will succeed which is always true in
3577 // the old model but possibly not true in the new model if another context has
3578 // deleted the resource.
3580 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3581 // used even when Bind has failed. However, the bug is minor compared to the
3582 // overhead & duplicated checking in client side.
3584 void GLES2Implementation::BindBufferHelper(
3585 GLenum target
, GLuint buffer_id
) {
3586 // TODO(gman): See note #1 above.
3587 bool changed
= false;
3589 case GL_ARRAY_BUFFER
:
3590 if (bound_array_buffer_
!= buffer_id
) {
3591 bound_array_buffer_
= buffer_id
;
3595 case GL_COPY_READ_BUFFER
:
3596 if (bound_copy_read_buffer_
!= buffer_id
) {
3597 bound_copy_read_buffer_
= buffer_id
;
3601 case GL_COPY_WRITE_BUFFER
:
3602 if (bound_copy_write_buffer_
!= buffer_id
) {
3603 bound_copy_write_buffer_
= buffer_id
;
3607 case GL_ELEMENT_ARRAY_BUFFER
:
3608 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3610 case GL_PIXEL_PACK_BUFFER
:
3611 if (bound_pixel_pack_buffer_
!= buffer_id
) {
3612 bound_pixel_pack_buffer_
= buffer_id
;
3616 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3617 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3619 case GL_PIXEL_UNPACK_BUFFER
:
3620 if (bound_pixel_unpack_buffer_
!= buffer_id
) {
3621 bound_pixel_unpack_buffer_
= buffer_id
;
3625 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3626 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3628 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3629 if (bound_transform_feedback_buffer_
!= buffer_id
) {
3630 bound_transform_feedback_buffer_
= buffer_id
;
3634 case GL_UNIFORM_BUFFER
:
3635 if (bound_uniform_buffer_
!= buffer_id
) {
3636 bound_uniform_buffer_
= buffer_id
;
3644 // TODO(gman): See note #2 above.
3646 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3647 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3651 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3652 helper_
->BindBuffer(target
, buffer
);
3653 if (share_group_
->bind_generates_resource())
3654 helper_
->CommandBufferHelper::OrderingBarrier();
3657 void GLES2Implementation::BindBufferBaseHelper(
3658 GLenum target
, GLuint index
, GLuint buffer_id
) {
3659 // TODO(zmo): See note #1 above.
3660 // TODO(zmo): See note #2 above.
3661 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3662 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3665 void GLES2Implementation::BindBufferBaseStub(
3666 GLenum target
, GLuint index
, GLuint buffer
) {
3667 helper_
->BindBufferBase(target
, index
, buffer
);
3668 if (share_group_
->bind_generates_resource())
3669 helper_
->CommandBufferHelper::Flush();
3672 void GLES2Implementation::BindBufferRangeHelper(
3673 GLenum target
, GLuint index
, GLuint buffer_id
,
3674 GLintptr offset
, GLsizeiptr size
) {
3675 // TODO(zmo): See note #1 above.
3676 // TODO(zmo): See note #2 above.
3677 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3678 this, target
, index
, buffer_id
, offset
, size
,
3679 &GLES2Implementation::BindBufferRangeStub
);
3682 void GLES2Implementation::BindBufferRangeStub(
3683 GLenum target
, GLuint index
, GLuint buffer
,
3684 GLintptr offset
, GLsizeiptr size
) {
3685 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3686 if (share_group_
->bind_generates_resource())
3687 helper_
->CommandBufferHelper::Flush();
3690 void GLES2Implementation::BindFramebufferHelper(
3691 GLenum target
, GLuint framebuffer
) {
3692 // TODO(gman): See note #1 above.
3693 bool changed
= false;
3695 case GL_FRAMEBUFFER
:
3696 if (bound_framebuffer_
!= framebuffer
||
3697 bound_read_framebuffer_
!= framebuffer
) {
3698 bound_framebuffer_
= framebuffer
;
3699 bound_read_framebuffer_
= framebuffer
;
3703 case GL_READ_FRAMEBUFFER
:
3704 if (!IsChromiumFramebufferMultisampleAvailable()) {
3705 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3708 if (bound_read_framebuffer_
!= framebuffer
) {
3709 bound_read_framebuffer_
= framebuffer
;
3713 case GL_DRAW_FRAMEBUFFER
:
3714 if (!IsChromiumFramebufferMultisampleAvailable()) {
3715 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3718 if (bound_framebuffer_
!= framebuffer
) {
3719 bound_framebuffer_
= framebuffer
;
3724 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3729 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3730 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3734 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3735 GLuint framebuffer
) {
3736 helper_
->BindFramebuffer(target
, framebuffer
);
3737 if (share_group_
->bind_generates_resource())
3738 helper_
->CommandBufferHelper::OrderingBarrier();
3741 void GLES2Implementation::BindRenderbufferHelper(
3742 GLenum target
, GLuint renderbuffer
) {
3743 // TODO(gman): See note #1 above.
3744 bool changed
= false;
3746 case GL_RENDERBUFFER
:
3747 if (bound_renderbuffer_
!= renderbuffer
) {
3748 bound_renderbuffer_
= renderbuffer
;
3756 // TODO(zmo): See note #2 above.
3758 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3759 this, target
, renderbuffer
,
3760 &GLES2Implementation::BindRenderbufferStub
);
3764 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3765 GLuint renderbuffer
) {
3766 helper_
->BindRenderbuffer(target
, renderbuffer
);
3767 if (share_group_
->bind_generates_resource())
3768 helper_
->CommandBufferHelper::OrderingBarrier();
3771 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3773 helper_
->BindSampler(unit
, sampler
);
3776 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3777 // TODO(gman): See note #1 above.
3778 // TODO(gman): Change this to false once we figure out why it's failing
3780 bool changed
= true;
3781 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3784 if (unit
.bound_texture_2d
!= texture
) {
3785 unit
.bound_texture_2d
= texture
;
3789 case GL_TEXTURE_CUBE_MAP
:
3790 if (unit
.bound_texture_cube_map
!= texture
) {
3791 unit
.bound_texture_cube_map
= texture
;
3795 case GL_TEXTURE_EXTERNAL_OES
:
3796 if (unit
.bound_texture_external_oes
!= texture
) {
3797 unit
.bound_texture_external_oes
= texture
;
3805 // TODO(gman): See note #2 above.
3807 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3808 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3812 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3813 helper_
->BindTexture(target
, texture
);
3814 if (share_group_
->bind_generates_resource())
3815 helper_
->CommandBufferHelper::OrderingBarrier();
3818 void GLES2Implementation::BindTransformFeedbackHelper(
3819 GLenum target
, GLuint transformfeedback
) {
3820 helper_
->BindTransformFeedback(target
, transformfeedback
);
3823 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3824 bool changed
= false;
3825 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3827 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3828 // because unlike other resources VertexArrayObject ids must
3829 // be generated by GenVertexArrays. A random id to Bind will not
3830 // generate a new object.
3831 helper_
->BindVertexArrayOES(array
);
3835 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3836 "id was not generated with glGenVertexArrayOES");
3840 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3841 GLuint valuebuffer
) {
3842 bool changed
= false;
3844 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3845 if (bound_valuebuffer_
!= valuebuffer
) {
3846 bound_valuebuffer_
= valuebuffer
;
3854 // TODO(gman): See note #2 above.
3856 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3857 this, target
, valuebuffer
,
3858 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3862 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3863 GLuint valuebuffer
) {
3864 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3865 if (share_group_
->bind_generates_resource())
3866 helper_
->CommandBufferHelper::OrderingBarrier();
3869 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3870 if (current_program_
!= program
) {
3871 current_program_
= program
;
3872 helper_
->UseProgram(program
);
3876 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3877 return vertex_array_object_manager_
->IsReservedId(id
);
3880 void GLES2Implementation::DeleteBuffersHelper(
3881 GLsizei n
, const GLuint
* buffers
) {
3882 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3883 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3886 "glDeleteBuffers", "id not created by this context.");
3889 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3890 if (buffers
[ii
] == bound_array_buffer_
) {
3891 bound_array_buffer_
= 0;
3893 if (buffers
[ii
] == bound_copy_read_buffer_
) {
3894 bound_copy_read_buffer_
= 0;
3896 if (buffers
[ii
] == bound_copy_write_buffer_
) {
3897 bound_copy_write_buffer_
= 0;
3899 if (buffers
[ii
] == bound_pixel_pack_buffer_
) {
3900 bound_pixel_pack_buffer_
= 0;
3902 if (buffers
[ii
] == bound_pixel_unpack_buffer_
) {
3903 bound_pixel_unpack_buffer_
= 0;
3905 if (buffers
[ii
] == bound_transform_feedback_buffer_
) {
3906 bound_transform_feedback_buffer_
= 0;
3908 if (buffers
[ii
] == bound_uniform_buffer_
) {
3909 bound_uniform_buffer_
= 0;
3911 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3913 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3915 RemoveTransferBuffer(buffer
);
3917 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3918 bound_pixel_unpack_transfer_buffer_id_
= 0;
3921 RemoveMappedBufferRangeById(buffers
[ii
]);
3925 void GLES2Implementation::DeleteBuffersStub(
3926 GLsizei n
, const GLuint
* buffers
) {
3927 helper_
->DeleteBuffersImmediate(n
, buffers
);
3931 void GLES2Implementation::DeleteFramebuffersHelper(
3932 GLsizei n
, const GLuint
* framebuffers
) {
3933 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3934 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3937 "glDeleteFramebuffers", "id not created by this context.");
3940 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3941 if (framebuffers
[ii
] == bound_framebuffer_
) {
3942 bound_framebuffer_
= 0;
3944 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3945 bound_read_framebuffer_
= 0;
3950 void GLES2Implementation::DeleteFramebuffersStub(
3951 GLsizei n
, const GLuint
* framebuffers
) {
3952 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3955 void GLES2Implementation::DeleteRenderbuffersHelper(
3956 GLsizei n
, const GLuint
* renderbuffers
) {
3957 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3958 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3961 "glDeleteRenderbuffers", "id not created by this context.");
3964 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3965 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3966 bound_renderbuffer_
= 0;
3971 void GLES2Implementation::DeleteRenderbuffersStub(
3972 GLsizei n
, const GLuint
* renderbuffers
) {
3973 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3976 void GLES2Implementation::DeleteTexturesHelper(
3977 GLsizei n
, const GLuint
* textures
) {
3978 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3979 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3982 "glDeleteTextures", "id not created by this context.");
3985 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3986 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3988 TextureUnit
& unit
= texture_units_
[tt
];
3989 if (textures
[ii
] == unit
.bound_texture_2d
) {
3990 unit
.bound_texture_2d
= 0;
3992 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3993 unit
.bound_texture_cube_map
= 0;
3995 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3996 unit
.bound_texture_external_oes
= 0;
4002 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
4003 const GLuint
* textures
) {
4004 helper_
->DeleteTexturesImmediate(n
, textures
);
4007 void GLES2Implementation::DeleteVertexArraysOESHelper(
4008 GLsizei n
, const GLuint
* arrays
) {
4009 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
4010 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
4011 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
4014 "glDeleteVertexArraysOES", "id not created by this context.");
4019 void GLES2Implementation::DeleteVertexArraysOESStub(
4020 GLsizei n
, const GLuint
* arrays
) {
4021 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
4024 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
4026 const GLuint
* valuebuffers
) {
4027 if (!GetIdHandler(id_namespaces::kValuebuffers
)
4028 ->FreeIds(this, n
, valuebuffers
,
4029 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
4030 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
4031 "id not created by this context.");
4034 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4035 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
4036 bound_valuebuffer_
= 0;
4041 void GLES2Implementation::DeleteSamplersStub(
4042 GLsizei n
, const GLuint
* samplers
) {
4043 helper_
->DeleteSamplersImmediate(n
, samplers
);
4046 void GLES2Implementation::DeleteSamplersHelper(
4047 GLsizei n
, const GLuint
* samplers
) {
4048 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
4049 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
4052 "glDeleteSamplers", "id not created by this context.");
4057 void GLES2Implementation::DeleteTransformFeedbacksStub(
4058 GLsizei n
, const GLuint
* transformfeedbacks
) {
4059 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
4062 void GLES2Implementation::DeleteTransformFeedbacksHelper(
4063 GLsizei n
, const GLuint
* transformfeedbacks
) {
4064 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
4065 this, n
, transformfeedbacks
,
4066 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
4069 "glDeleteTransformFeedbacks", "id not created by this context.");
4074 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
4076 const GLuint
* valuebuffers
) {
4077 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
4080 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
4081 GPU_CLIENT_SINGLE_THREAD_CHECK();
4083 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
4084 vertex_array_object_manager_
->SetAttribEnable(index
, false);
4085 helper_
->DisableVertexAttribArray(index
);
4089 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
4090 GPU_CLIENT_SINGLE_THREAD_CHECK();
4091 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
4093 vertex_array_object_manager_
->SetAttribEnable(index
, true);
4094 helper_
->EnableVertexAttribArray(index
);
4098 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
4099 GPU_CLIENT_SINGLE_THREAD_CHECK();
4100 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
4101 << GLES2Util::GetStringDrawMode(mode
) << ", "
4102 << first
<< ", " << count
<< ")");
4104 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
4107 bool simulated
= false;
4108 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4109 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
4112 helper_
->DrawArrays(mode
, first
, count
);
4113 RestoreArrayBuffer(simulated
);
4117 void GLES2Implementation::GetVertexAttribfv(
4118 GLuint index
, GLenum pname
, GLfloat
* params
) {
4119 GPU_CLIENT_SINGLE_THREAD_CHECK();
4120 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
4122 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4123 << static_cast<const void*>(params
) << ")");
4125 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4126 *params
= static_cast<GLfloat
>(value
);
4129 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
4130 typedef cmds::GetVertexAttribfv::Result Result
;
4131 Result
* result
= GetResultAs
<Result
*>();
4135 result
->SetNumResults(0);
4136 helper_
->GetVertexAttribfv(
4137 index
, pname
, GetResultShmId(), GetResultShmOffset());
4139 result
->CopyResult(params
);
4140 GPU_CLIENT_LOG_CODE_BLOCK({
4141 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4142 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4148 void GLES2Implementation::GetVertexAttribiv(
4149 GLuint index
, GLenum pname
, GLint
* params
) {
4150 GPU_CLIENT_SINGLE_THREAD_CHECK();
4151 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
4153 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4154 << static_cast<const void*>(params
) << ")");
4156 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4157 *params
= static_cast<GLint
>(value
);
4160 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
4161 typedef cmds::GetVertexAttribiv::Result Result
;
4162 Result
* result
= GetResultAs
<Result
*>();
4166 result
->SetNumResults(0);
4167 helper_
->GetVertexAttribiv(
4168 index
, pname
, GetResultShmId(), GetResultShmOffset());
4170 result
->CopyResult(params
);
4171 GPU_CLIENT_LOG_CODE_BLOCK({
4172 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4173 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4179 void GLES2Implementation::GetVertexAttribIiv(
4180 GLuint index
, GLenum pname
, GLint
* params
) {
4181 GPU_CLIENT_SINGLE_THREAD_CHECK();
4182 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv("
4184 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4185 << static_cast<const void*>(params
) << ")");
4187 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4188 *params
= static_cast<GLint
>(value
);
4191 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
4192 typedef cmds::GetVertexAttribiv::Result Result
;
4193 Result
* result
= GetResultAs
<Result
*>();
4197 result
->SetNumResults(0);
4198 helper_
->GetVertexAttribIiv(
4199 index
, pname
, GetResultShmId(), GetResultShmOffset());
4201 result
->CopyResult(params
);
4202 GPU_CLIENT_LOG_CODE_BLOCK({
4203 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4204 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4210 void GLES2Implementation::GetVertexAttribIuiv(
4211 GLuint index
, GLenum pname
, GLuint
* params
) {
4212 GPU_CLIENT_SINGLE_THREAD_CHECK();
4213 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv("
4215 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4216 << static_cast<const void*>(params
) << ")");
4218 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4219 *params
= static_cast<GLuint
>(value
);
4222 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
4223 typedef cmds::GetVertexAttribiv::Result Result
;
4224 Result
* result
= GetResultAs
<Result
*>();
4228 result
->SetNumResults(0);
4229 helper_
->GetVertexAttribIuiv(
4230 index
, pname
, GetResultShmId(), GetResultShmOffset());
4232 result
->CopyResult(params
);
4233 GPU_CLIENT_LOG_CODE_BLOCK({
4234 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4235 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4241 GLenum
GLES2Implementation::GetGraphicsResetStatusKHR() {
4242 GPU_CLIENT_SINGLE_THREAD_CHECK();
4243 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");
4244 // If we can't make command buffers then the context is lost.
4245 if (gpu_control_
->IsGpuChannelLost())
4246 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4247 // Otherwise, check the command buffer if it is lost.
4248 if (helper_
->IsContextLost()) {
4249 // TODO(danakj): We could GetLastState() off the CommandBuffer and return
4250 // the actual reason here if we cared to.
4251 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4256 void GLES2Implementation::Swap() {
4260 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
4261 PostSubBufferCHROMIUM(
4262 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
4265 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
4266 switch (plane_transform
) {
4267 case gfx::OVERLAY_TRANSFORM_INVALID
:
4269 case gfx::OVERLAY_TRANSFORM_NONE
:
4270 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4271 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
4272 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
4273 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
4274 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
4275 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
4276 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
4277 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
4278 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
4279 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
4280 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
4283 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4286 void GLES2Implementation::ScheduleOverlayPlane(
4288 gfx::OverlayTransform plane_transform
,
4289 unsigned overlay_texture_id
,
4290 const gfx::Rect
& display_bounds
,
4291 const gfx::RectF
& uv_rect
) {
4292 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
4293 GetGLESOverlayTransform(plane_transform
),
4297 display_bounds
.width(),
4298 display_bounds
.height(),
4305 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
4306 const char* feature
) {
4307 GPU_CLIENT_SINGLE_THREAD_CHECK();
4308 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
4310 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
4311 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
4312 Result
* result
= GetResultAs
<Result
*>();
4317 SetBucketAsCString(kResultBucketId
, feature
);
4318 helper_
->EnableFeatureCHROMIUM(
4319 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
4321 helper_
->SetBucketSize(kResultBucketId
, 0);
4322 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
4323 return *result
!= 0;
4326 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
4327 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
4328 GPU_CLIENT_SINGLE_THREAD_CHECK();
4329 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
4330 << target
<< ", " << offset
<< ", " << size
<< ", "
4331 << GLES2Util::GetStringEnum(access
) << ")");
4332 // NOTE: target is NOT checked because the service will check it
4333 // and we don't know what targets are valid.
4334 if (access
!= GL_WRITE_ONLY
) {
4335 SetGLErrorInvalidEnum(
4336 "glMapBufferSubDataCHROMIUM", access
, "access");
4339 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
4340 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
4345 unsigned int shm_offset
;
4346 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4348 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
4352 std::pair
<MappedBufferMap::iterator
, bool> result
=
4353 mapped_buffers_
.insert(std::make_pair(
4356 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4357 DCHECK(result
.second
);
4358 GPU_CLIENT_LOG(" returned " << mem
);
4362 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
4363 GPU_CLIENT_SINGLE_THREAD_CHECK();
4365 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
4366 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
4367 if (it
== mapped_buffers_
.end()) {
4369 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
4372 const MappedBuffer
& mb
= it
->second
;
4373 helper_
->BufferSubData(
4374 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
4375 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
4376 mapped_buffers_
.erase(it
);
4380 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
4381 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
4383 bool cached
= GetHelper(binding
, &id
);
4385 return static_cast<GLuint
>(id
);
4388 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
4389 GLuint buffer
= GetBoundBufferHelper(target
);
4390 RemoveMappedBufferRangeById(buffer
);
4393 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4395 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4396 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4397 mapped_memory_
->FreePendingToken(
4398 iter
->second
.shm_memory
, helper_
->InsertToken());
4399 mapped_buffer_range_map_
.erase(iter
);
4404 void GLES2Implementation::ClearMappedBufferRangeMap() {
4405 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4406 if (buffer_range
.second
.shm_memory
) {
4407 mapped_memory_
->FreePendingToken(
4408 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4411 mapped_buffer_range_map_
.clear();
4414 void* GLES2Implementation::MapBufferRange(
4415 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4416 GPU_CLIENT_SINGLE_THREAD_CHECK();
4417 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4418 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4419 << size
<< ", " << access
<< ")");
4420 if (!ValidateSize("glMapBufferRange", size
) ||
4421 !ValidateOffset("glMapBufferRange", offset
)) {
4426 unsigned int shm_offset
;
4427 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4429 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4433 typedef cmds::MapBufferRange::Result Result
;
4434 Result
* result
= GetResultAs
<Result
*>();
4436 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4437 GetResultShmId(), GetResultShmOffset());
4438 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4439 // consider an early return without WaitForCmd(). crbug.com/465804.
4442 const GLbitfield kInvalidateBits
=
4443 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4444 if ((access
& kInvalidateBits
) != 0) {
4445 // We do not read back from the buffer, therefore, we set the client
4446 // side memory to zero to avoid uninitialized data.
4447 memset(mem
, 0, size
);
4449 GLuint buffer
= GetBoundBufferHelper(target
);
4450 DCHECK_NE(0u, buffer
);
4451 // glMapBufferRange fails on an already mapped buffer.
4452 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4453 mapped_buffer_range_map_
.end());
4454 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4456 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4457 DCHECK(iter
.second
);
4459 mapped_memory_
->Free(mem
);
4463 GPU_CLIENT_LOG(" returned " << mem
);
4468 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4469 GPU_CLIENT_SINGLE_THREAD_CHECK();
4470 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4471 << GLES2Util::GetStringEnum(target
) << ")");
4473 case GL_ARRAY_BUFFER
:
4474 case GL_ELEMENT_ARRAY_BUFFER
:
4475 case GL_COPY_READ_BUFFER
:
4476 case GL_COPY_WRITE_BUFFER
:
4477 case GL_PIXEL_PACK_BUFFER
:
4478 case GL_PIXEL_UNPACK_BUFFER
:
4479 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4480 case GL_UNIFORM_BUFFER
:
4483 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4486 GLuint buffer
= GetBoundBufferHelper(target
);
4488 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4491 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4492 if (iter
== mapped_buffer_range_map_
.end()) {
4493 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4497 helper_
->UnmapBuffer(target
);
4498 RemoveMappedBufferRangeById(buffer
);
4499 // TODO(zmo): There is a rare situation that data might be corrupted and
4500 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4501 // don't have to WaitForCmd().
4502 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4507 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4517 GPU_CLIENT_SINGLE_THREAD_CHECK();
4518 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4519 << target
<< ", " << level
<< ", "
4520 << xoffset
<< ", " << yoffset
<< ", "
4521 << width
<< ", " << height
<< ", "
4522 << GLES2Util::GetStringTextureFormat(format
) << ", "
4523 << GLES2Util::GetStringPixelType(type
) << ", "
4524 << GLES2Util::GetStringEnum(access
) << ")");
4525 if (access
!= GL_WRITE_ONLY
) {
4526 SetGLErrorInvalidEnum(
4527 "glMapTexSubImage2DCHROMIUM", access
, "access");
4530 // NOTE: target is NOT checked because the service will check it
4531 // and we don't know what targets are valid.
4532 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4534 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4538 if (!GLES2Util::ComputeImageDataSizes(
4539 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4541 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4545 unsigned int shm_offset
;
4546 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4548 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4552 std::pair
<MappedTextureMap::iterator
, bool> result
=
4553 mapped_textures_
.insert(std::make_pair(
4556 access
, shm_id
, mem
, shm_offset
,
4557 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4558 DCHECK(result
.second
);
4559 GPU_CLIENT_LOG(" returned " << mem
);
4563 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4564 GPU_CLIENT_SINGLE_THREAD_CHECK();
4566 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4567 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4568 if (it
== mapped_textures_
.end()) {
4570 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4573 const MappedTexture
& mt
= it
->second
;
4574 helper_
->TexSubImage2D(
4575 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4576 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4577 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4578 mapped_textures_
.erase(it
);
4582 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4583 float scale_factor
) {
4584 GPU_CLIENT_SINGLE_THREAD_CHECK();
4585 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4586 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4587 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4591 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4592 GPU_CLIENT_SINGLE_THREAD_CHECK();
4593 GPU_CLIENT_LOG("[" << GetLogPrefix()
4594 << "] glGetRequestableExtensionsCHROMIUM()");
4596 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4597 const char* result
= NULL
;
4598 // Clear the bucket so if the command fails nothing will be in it.
4599 helper_
->SetBucketSize(kResultBucketId
, 0);
4600 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4602 if (GetBucketAsString(kResultBucketId
, &str
)) {
4603 // The set of requestable extensions shrinks as we enable
4604 // them. Because we don't know when the client will stop referring
4605 // to a previous one it queries (see GetString) we need to cache
4606 // the unique results.
4607 std::set
<std::string
>::const_iterator sit
=
4608 requestable_extensions_set_
.find(str
);
4609 if (sit
!= requestable_extensions_set_
.end()) {
4610 result
= sit
->c_str();
4612 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4613 requestable_extensions_set_
.insert(str
);
4614 DCHECK(insert_result
.second
);
4615 result
= insert_result
.first
->c_str();
4618 GPU_CLIENT_LOG(" returned " << result
);
4619 return reinterpret_cast<const GLchar
*>(result
);
4622 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4623 // with VirtualGL contexts.
4624 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4625 GPU_CLIENT_SINGLE_THREAD_CHECK();
4626 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4627 << extension
<< ")");
4628 SetBucketAsCString(kResultBucketId
, extension
);
4629 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4630 helper_
->SetBucketSize(kResultBucketId
, 0);
4632 struct ExtensionCheck
{
4633 const char* extension
;
4634 ExtensionStatus
* status
;
4636 const ExtensionCheck checks
[] = {
4638 "GL_ANGLE_pack_reverse_row_order",
4639 &angle_pack_reverse_row_order_status_
,
4642 "GL_CHROMIUM_framebuffer_multisample",
4643 &chromium_framebuffer_multisample_
,
4646 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4647 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4648 const ExtensionCheck
& check
= checks
[ii
];
4649 if (*check
.status
== kUnavailableExtensionStatus
&&
4650 !strcmp(extension
, check
.extension
)) {
4651 *check
.status
= kUnknownExtensionStatus
;
4656 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4657 GPU_CLIENT_SINGLE_THREAD_CHECK();
4658 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4659 // Wait if this would add too many rate limit tokens.
4660 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4661 helper_
->WaitForToken(rate_limit_tokens_
.front());
4662 rate_limit_tokens_
.pop();
4664 rate_limit_tokens_
.push(helper_
->InsertToken());
4667 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4668 GLuint program
, std::vector
<int8
>* result
) {
4670 // Clear the bucket so if the command fails nothing will be in it.
4671 helper_
->SetBucketSize(kResultBucketId
, 0);
4672 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4673 GetBucketContents(kResultBucketId
, result
);
4676 void GLES2Implementation::GetProgramInfoCHROMIUM(
4677 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4678 GPU_CLIENT_SINGLE_THREAD_CHECK();
4681 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4685 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4688 // Make sure they've set size to 0 else the value will be undefined on
4690 DCHECK_EQ(0, *size
);
4691 std::vector
<int8
> result
;
4692 GetProgramInfoCHROMIUMHelper(program
, &result
);
4693 if (result
.empty()) {
4696 *size
= result
.size();
4700 if (static_cast<size_t>(bufsize
) < result
.size()) {
4701 SetGLError(GL_INVALID_OPERATION
,
4702 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4705 memcpy(info
, &result
[0], result
.size());
4708 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4709 GLuint program
, std::vector
<int8
>* result
) {
4711 // Clear the bucket so if the command fails nothing will be in it.
4712 helper_
->SetBucketSize(kResultBucketId
, 0);
4713 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4714 GetBucketContents(kResultBucketId
, result
);
4717 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4718 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4719 GPU_CLIENT_SINGLE_THREAD_CHECK();
4722 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4726 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4729 // Make sure they've set size to 0 else the value will be undefined on
4731 DCHECK_EQ(0, *size
);
4732 std::vector
<int8
> result
;
4733 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4734 if (result
.empty()) {
4737 *size
= result
.size();
4741 if (static_cast<size_t>(bufsize
) < result
.size()) {
4742 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4743 "bufsize is too small for result.");
4746 memcpy(info
, &result
[0], result
.size());
4749 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4750 GLuint program
, std::vector
<int8
>* result
) {
4752 // Clear the bucket so if the command fails nothing will be in it.
4753 helper_
->SetBucketSize(kResultBucketId
, 0);
4754 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4755 GetBucketContents(kResultBucketId
, result
);
4758 void GLES2Implementation::GetUniformsES3CHROMIUM(
4759 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4760 GPU_CLIENT_SINGLE_THREAD_CHECK();
4763 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4767 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4770 // Make sure they've set size to 0 else the value will be undefined on
4772 DCHECK_EQ(0, *size
);
4773 std::vector
<int8
> result
;
4774 GetUniformsES3CHROMIUMHelper(program
, &result
);
4775 if (result
.empty()) {
4778 *size
= result
.size();
4782 if (static_cast<size_t>(bufsize
) < result
.size()) {
4783 SetGLError(GL_INVALID_OPERATION
,
4784 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4787 memcpy(info
, &result
[0], result
.size());
4790 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4791 GLuint program
, std::vector
<int8
>* result
) {
4793 // Clear the bucket so if the command fails nothing will be in it.
4794 helper_
->SetBucketSize(kResultBucketId
, 0);
4795 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4796 GetBucketContents(kResultBucketId
, result
);
4799 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4800 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4801 GPU_CLIENT_SINGLE_THREAD_CHECK();
4803 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4804 "bufsize less than 0.");
4808 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4812 // Make sure they've set size to 0 else the value will be undefined on
4814 DCHECK_EQ(0, *size
);
4815 std::vector
<int8
> result
;
4816 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4817 if (result
.empty()) {
4820 *size
= result
.size();
4824 if (static_cast<size_t>(bufsize
) < result
.size()) {
4825 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4826 "bufsize is too small for result.");
4829 memcpy(info
, &result
[0], result
.size());
4832 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4833 GPU_CLIENT_SINGLE_THREAD_CHECK();
4834 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4836 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4837 helper_
->CommandBufferHelper::Flush();
4838 return gpu_control_
->CreateStreamTexture(texture
);
4841 void GLES2Implementation::PostSubBufferCHROMIUM(
4842 GLint x
, GLint y
, GLint width
, GLint height
) {
4843 GPU_CLIENT_SINGLE_THREAD_CHECK();
4844 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4845 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4846 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4847 "width", width
, "height", height
);
4849 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4850 swap_buffers_tokens_
.push(helper_
->InsertToken());
4851 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4852 helper_
->CommandBufferHelper::Flush();
4853 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4854 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4855 swap_buffers_tokens_
.pop();
4859 void GLES2Implementation::DeleteQueriesEXTHelper(
4860 GLsizei n
, const GLuint
* queries
) {
4861 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4862 query_tracker_
->RemoveQuery(queries
[ii
]);
4863 query_id_allocator_
->FreeID(queries
[ii
]);
4866 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4869 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4870 GPU_CLIENT_SINGLE_THREAD_CHECK();
4871 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4873 // TODO(gman): To be spec compliant IDs from other contexts sharing
4874 // resources need to return true here even though you can't share
4875 // queries across contexts?
4876 return query_tracker_
->GetQuery(id
) != NULL
;
4879 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4880 GPU_CLIENT_SINGLE_THREAD_CHECK();
4881 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4882 << GLES2Util::GetStringQueryTarget(target
)
4883 << ", " << id
<< ")");
4886 case GL_COMMANDS_ISSUED_CHROMIUM
:
4887 case GL_LATENCY_QUERY_CHROMIUM
:
4888 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
4889 case GL_GET_ERROR_QUERY_CHROMIUM
:
4891 case GL_COMMANDS_COMPLETED_CHROMIUM
:
4892 if (!capabilities_
.sync_query
) {
4894 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4895 "not enabled for commands completed queries");
4899 case GL_ANY_SAMPLES_PASSED
:
4900 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
4901 if (!capabilities_
.occlusion_query_boolean
) {
4903 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4904 "not enabled for occlusion queries");
4908 case GL_TIME_ELAPSED_EXT
:
4909 if (!capabilities_
.timer_queries
) {
4911 GL_INVALID_OPERATION
, "glBeginQueryEXT",
4912 "not enabled for timing queries");
4916 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
4917 if (capabilities_
.major_version
>= 3)
4922 GL_INVALID_ENUM
, "glBeginQueryEXT", "unknown query target");
4926 // if any outstanding queries INV_OP
4927 if (query_tracker_
->GetCurrentQuery(target
)) {
4929 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4934 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4938 if (!query_id_allocator_
->InUse(id
)) {
4939 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4943 // Extra setups some targets might need.
4945 case GL_TIME_ELAPSED_EXT
:
4946 if (!query_tracker_
->SetDisjointSync(this)) {
4947 SetGLError(GL_OUT_OF_MEMORY
,
4949 "buffer allocation failed");
4957 if (query_tracker_
->BeginQuery(id
, target
, this))
4961 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4962 GPU_CLIENT_SINGLE_THREAD_CHECK();
4963 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4964 << GLES2Util::GetStringQueryTarget(target
) << ")");
4965 // Don't do anything if the context is lost.
4966 if (helper_
->IsContextLost()) {
4970 if (query_tracker_
->EndQuery(target
, this))
4974 void GLES2Implementation::QueryCounterEXT(GLuint id
, GLenum target
) {
4975 GPU_CLIENT_SINGLE_THREAD_CHECK();
4976 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] QueryCounterEXT("
4978 << ", " << GLES2Util::GetStringQueryTarget(target
) << ")");
4981 case GL_TIMESTAMP_EXT
:
4982 if (!capabilities_
.timer_queries
) {
4984 GL_INVALID_OPERATION
, "glQueryCounterEXT",
4985 "not enabled for timing queries");
4991 GL_INVALID_ENUM
, "glQueryCounterEXT", "unknown query target");
4996 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "id is 0");
5000 if (!query_id_allocator_
->InUse(id
)) {
5001 SetGLError(GL_INVALID_OPERATION
, "glQueryCounterEXT", "invalid id");
5005 // Extra setups some targets might need.
5007 case GL_TIMESTAMP_EXT
:
5008 if (!query_tracker_
->SetDisjointSync(this)) {
5009 SetGLError(GL_OUT_OF_MEMORY
,
5010 "glQueryCounterEXT",
5011 "buffer allocation failed");
5019 if (query_tracker_
->QueryCounter(id
, target
, this))
5023 void GLES2Implementation::GetQueryivEXT(
5024 GLenum target
, GLenum pname
, GLint
* params
) {
5025 GPU_CLIENT_SINGLE_THREAD_CHECK();
5026 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
5027 << GLES2Util::GetStringQueryTarget(target
) << ", "
5028 << GLES2Util::GetStringQueryParameter(pname
) << ", "
5029 << static_cast<const void*>(params
) << ")");
5030 if (pname
== GL_QUERY_COUNTER_BITS_EXT
) {
5031 // We convert all queries to CPU time so we support 64 bits.
5034 } else if (pname
!= GL_CURRENT_QUERY_EXT
) {
5035 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
5038 QueryTracker::Query
* query
= query_tracker_
->GetCurrentQuery(target
);
5039 *params
= query
? query
->id() : 0;
5040 GPU_CLIENT_LOG(" " << *params
);
5044 void GLES2Implementation::GetQueryObjectivEXT(
5045 GLuint id
, GLenum pname
, GLint
* params
) {
5046 GLuint64 result
= 0;
5047 if (GetQueryObjectValueHelper("glGetQueryObjectivEXT", id
, pname
, &result
))
5048 *params
= base::saturated_cast
<GLint
>(result
);
5051 void GLES2Implementation::GetQueryObjectuivEXT(
5052 GLuint id
, GLenum pname
, GLuint
* params
) {
5053 GLuint64 result
= 0;
5054 if (GetQueryObjectValueHelper("glGetQueryObjectuivEXT", id
, pname
, &result
))
5055 *params
= base::saturated_cast
<GLuint
>(result
);
5058 void GLES2Implementation::GetQueryObjecti64vEXT(
5059 GLuint id
, GLenum pname
, GLint64
* params
) {
5060 GLuint64 result
= 0;
5061 if (GetQueryObjectValueHelper("glGetQueryObjectiv64vEXT", id
, pname
, &result
))
5062 *params
= base::saturated_cast
<GLint64
>(result
);
5065 void GLES2Implementation::GetQueryObjectui64vEXT(
5066 GLuint id
, GLenum pname
, GLuint64
* params
) {
5067 GLuint64 result
= 0;
5068 if (GetQueryObjectValueHelper("glGetQueryObjectui64vEXT", id
, pname
, &result
))
5072 void GLES2Implementation::SetDisjointValueSyncCHROMIUM() {
5073 query_tracker_
->SetDisjointSync(this);
5076 void GLES2Implementation::DrawArraysInstancedANGLE(
5077 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
5078 GPU_CLIENT_SINGLE_THREAD_CHECK();
5079 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
5080 << GLES2Util::GetStringDrawMode(mode
) << ", "
5081 << first
<< ", " << count
<< ", " << primcount
<< ")");
5083 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
5086 if (primcount
< 0) {
5087 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
5090 if (primcount
== 0) {
5093 bool simulated
= false;
5094 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
5095 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
5099 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
5100 RestoreArrayBuffer(simulated
);
5104 void GLES2Implementation::DrawElementsInstancedANGLE(
5105 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
5106 GLsizei primcount
) {
5107 GPU_CLIENT_SINGLE_THREAD_CHECK();
5108 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
5109 << GLES2Util::GetStringDrawMode(mode
) << ", "
5111 << GLES2Util::GetStringIndexType(type
) << ", "
5112 << static_cast<const void*>(indices
) << ", "
5113 << primcount
<< ")");
5115 SetGLError(GL_INVALID_VALUE
,
5116 "glDrawElementsInstancedANGLE", "count less than 0.");
5122 if (primcount
< 0) {
5123 SetGLError(GL_INVALID_VALUE
,
5124 "glDrawElementsInstancedANGLE", "primcount < 0");
5127 if (primcount
== 0) {
5130 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
5131 !ValidateOffset("glDrawElementsInstancedANGLE",
5132 reinterpret_cast<GLintptr
>(indices
))) {
5136 bool simulated
= false;
5137 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
5138 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
5139 indices
, &offset
, &simulated
)) {
5142 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
5143 RestoreElementAndArrayBuffers(simulated
);
5147 void GLES2Implementation::GenMailboxCHROMIUM(
5149 GPU_CLIENT_SINGLE_THREAD_CHECK();
5150 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
5151 << static_cast<const void*>(mailbox
) << ")");
5152 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
5154 gpu::Mailbox result
= gpu::Mailbox::Generate();
5155 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
5158 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
5159 const GLbyte
* data
) {
5160 GPU_CLIENT_SINGLE_THREAD_CHECK();
5161 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
5162 << static_cast<const void*>(data
) << ")");
5163 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5164 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
5165 "mailbox that was not generated by "
5166 "GenMailboxCHROMIUM.";
5167 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
5171 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
5172 GLuint texture
, GLenum target
, const GLbyte
* data
) {
5173 GPU_CLIENT_SINGLE_THREAD_CHECK();
5174 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
5175 << static_cast<const void*>(data
) << ")");
5176 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5177 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
5178 "mailbox that was not generated by "
5179 "GenMailboxCHROMIUM.";
5180 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
5184 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
5185 const GLbyte
* data
) {
5186 GPU_CLIENT_SINGLE_THREAD_CHECK();
5187 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
5188 << static_cast<const void*>(data
) << ")");
5189 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5190 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
5191 "mailbox that was not generated by "
5192 "GenMailboxCHROMIUM.";
5193 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
5197 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
5198 GLenum target
, const GLbyte
* data
) {
5199 GPU_CLIENT_SINGLE_THREAD_CHECK();
5200 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
5201 << static_cast<const void*>(data
) << ")");
5202 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5203 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
5204 "mailbox that was not generated by "
5205 "GenMailboxCHROMIUM.";
5207 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
5208 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
5210 if (share_group_
->bind_generates_resource())
5211 helper_
->CommandBufferHelper::Flush();
5216 void GLES2Implementation::PushGroupMarkerEXT(
5217 GLsizei length
, const GLchar
* marker
) {
5218 GPU_CLIENT_SINGLE_THREAD_CHECK();
5219 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
5220 << length
<< ", " << marker
<< ")");
5226 (length
? std::string(marker
, length
) : std::string(marker
)));
5227 helper_
->PushGroupMarkerEXT(kResultBucketId
);
5228 helper_
->SetBucketSize(kResultBucketId
, 0);
5229 debug_marker_manager_
.PushGroup(
5230 length
? std::string(marker
, length
) : std::string(marker
));
5233 void GLES2Implementation::InsertEventMarkerEXT(
5234 GLsizei length
, const GLchar
* marker
) {
5235 GPU_CLIENT_SINGLE_THREAD_CHECK();
5236 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
5237 << length
<< ", " << marker
<< ")");
5243 (length
? std::string(marker
, length
) : std::string(marker
)));
5244 helper_
->InsertEventMarkerEXT(kResultBucketId
);
5245 helper_
->SetBucketSize(kResultBucketId
, 0);
5246 debug_marker_manager_
.SetMarker(
5247 length
? std::string(marker
, length
) : std::string(marker
));
5250 void GLES2Implementation::PopGroupMarkerEXT() {
5251 GPU_CLIENT_SINGLE_THREAD_CHECK();
5252 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
5253 helper_
->PopGroupMarkerEXT();
5254 debug_marker_manager_
.PopGroup();
5257 void GLES2Implementation::TraceBeginCHROMIUM(
5258 const char* category_name
, const char* trace_name
) {
5259 GPU_CLIENT_SINGLE_THREAD_CHECK();
5260 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
5261 << category_name
<< ", " << trace_name
<< ")");
5262 SetBucketAsCString(kResultBucketId
, category_name
);
5263 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
5264 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
5265 helper_
->SetBucketSize(kResultBucketId
, 0);
5266 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
5267 current_trace_stack_
++;
5270 void GLES2Implementation::TraceEndCHROMIUM() {
5271 GPU_CLIENT_SINGLE_THREAD_CHECK();
5272 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
5273 if (current_trace_stack_
== 0) {
5274 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
5275 "missing begin trace");
5278 helper_
->TraceEndCHROMIUM();
5279 current_trace_stack_
--;
5282 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
5283 GPU_CLIENT_SINGLE_THREAD_CHECK();
5284 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
5285 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
5287 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
5288 if (access
!= GL_READ_ONLY
) {
5289 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5295 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
5299 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
5303 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5305 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
5308 if (buffer
->mapped()) {
5309 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
5312 // Here we wait for previous transfer operations to be finished.
5313 if (buffer
->last_usage_token()) {
5314 helper_
->WaitForToken(buffer
->last_usage_token());
5315 buffer
->set_last_usage_token(0);
5317 buffer
->set_mapped(true);
5319 GPU_CLIENT_LOG(" returned " << buffer
->address());
5321 return buffer
->address();
5324 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
5325 GPU_CLIENT_SINGLE_THREAD_CHECK();
5327 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
5329 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
5330 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
5335 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5337 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
5340 if (!buffer
->mapped()) {
5341 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
5344 buffer
->set_mapped(false);
5349 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5350 GPU_CLIENT_SINGLE_THREAD_CHECK();
5351 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5352 helper_
->CommandBufferHelper::Flush();
5353 return gpu_control_
->InsertSyncPoint();
5356 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5357 GPU_CLIENT_SINGLE_THREAD_CHECK();
5358 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5359 DCHECK(capabilities_
.future_sync_points
);
5360 return gpu_control_
->InsertFutureSyncPoint();
5363 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5364 GPU_CLIENT_SINGLE_THREAD_CHECK();
5365 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5366 << sync_point
<< ")");
5367 DCHECK(capabilities_
.future_sync_points
);
5368 helper_
->CommandBufferHelper::Flush();
5369 gpu_control_
->RetireSyncPoint(sync_point
);
5374 bool ValidImageFormat(GLenum internalformat
,
5375 const Capabilities
& capabilities
) {
5376 switch (internalformat
) {
5377 case GL_ATC_RGB_AMD
:
5378 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
5379 return capabilities
.texture_format_atc
;
5380 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
5381 return capabilities
.texture_format_dxt1
;
5382 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
5383 return capabilities
.texture_format_dxt5
;
5384 case GL_ETC1_RGB8_OES
:
5385 return capabilities
.texture_format_etc1
;
5389 case GL_RGB_YCBCR_422_CHROMIUM
:
5397 bool ValidImageUsage(GLenum usage
) {
5399 case GL_MAP_CHROMIUM
:
5400 case GL_SCANOUT_CHROMIUM
:
5409 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5412 GLenum internalformat
) {
5414 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5419 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5423 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5424 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5429 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5431 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5437 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5440 GLenum internalformat
) {
5441 GPU_CLIENT_SINGLE_THREAD_CHECK();
5442 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5443 << ", " << height
<< ", "
5444 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5447 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5452 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5453 // Flush the command stream to make sure all pending commands
5454 // that may refer to the image_id are executed on the service side.
5455 helper_
->CommandBufferHelper::Flush();
5456 gpu_control_
->DestroyImage(image_id
);
5459 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5460 GPU_CLIENT_SINGLE_THREAD_CHECK();
5461 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5462 << image_id
<< ")");
5463 DestroyImageCHROMIUMHelper(image_id
);
5467 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5470 GLenum internalformat
,
5474 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5479 SetGLError(GL_INVALID_VALUE
,
5480 "glCreateGpuMemoryBufferImageCHROMIUM",
5485 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5486 SetGLError(GL_INVALID_VALUE
,
5487 "glCreateGpuMemoryBufferImageCHROMIUM",
5492 if (!ValidImageUsage(usage
)) {
5493 SetGLError(GL_INVALID_VALUE
,
5494 "glCreateGpuMemoryBufferImageCHROMIUM",
5499 // Flush the command stream to ensure ordering in case the newly
5500 // returned image_id has recently been in use with a different buffer.
5501 helper_
->CommandBufferHelper::Flush();
5502 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5503 width
, height
, internalformat
, usage
);
5505 SetGLError(GL_OUT_OF_MEMORY
,
5506 "glCreateGpuMemoryBufferImageCHROMIUM",
5513 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5516 GLenum internalformat
,
5518 GPU_CLIENT_SINGLE_THREAD_CHECK();
5519 GPU_CLIENT_LOG("[" << GetLogPrefix()
5520 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5521 << ", " << height
<< ", "
5522 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5523 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5524 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5525 width
, height
, internalformat
, usage
);
5530 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5532 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5535 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5536 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5542 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5544 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5547 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5548 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5554 bool GLES2Implementation::GetSamplerParameterfvHelper(
5555 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5556 // TODO(zmo): Implement client side caching.
5560 bool GLES2Implementation::GetSamplerParameterivHelper(
5561 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5562 // TODO(zmo): Implement client side caching.
5566 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5567 const char* const* str
,
5568 const GLint
* length
,
5569 const char* func_name
) {
5570 DCHECK_LE(0, count
);
5571 // Compute the total size.
5572 base::CheckedNumeric
<size_t> total_size
= count
;
5574 total_size
*= sizeof(GLint
);
5575 if (!total_size
.IsValid()) {
5576 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5579 size_t header_size
= total_size
.ValueOrDefault(0);
5580 std::vector
<GLint
> header(count
+ 1);
5581 header
[0] = static_cast<GLint
>(count
);
5582 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5585 len
= (length
&& length
[ii
] >= 0)
5587 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5590 total_size
+= 1; // NULL at the end of each char array.
5591 if (!total_size
.IsValid()) {
5592 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5595 header
[ii
+ 1] = len
;
5597 // Pack data into a bucket on the service.
5598 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5600 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5602 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5603 base::CheckedNumeric
<size_t> checked_size
=
5604 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5606 checked_size
+= 1; // NULL in the end.
5608 if (!checked_size
.IsValid()) {
5609 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5612 size_t size
= checked_size
.ValueOrDefault(0);
5614 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5615 if (!buffer
.valid() || buffer
.size() == 0) {
5616 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5619 size_t copy_size
= buffer
.size();
5620 if (ii
> 0 && buffer
.size() == size
)
5623 memcpy(buffer
.address(), src
, copy_size
);
5624 if (copy_size
< buffer
.size()) {
5625 // Append NULL in the end.
5626 DCHECK(copy_size
+ 1 == buffer
.size());
5627 char* str
= reinterpret_cast<char*>(buffer
.address());
5630 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5631 buffer
.shm_id(), buffer
.offset());
5632 offset
+= buffer
.size();
5633 src
+= buffer
.size();
5634 size
-= buffer
.size();
5637 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5641 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5644 GPU_CLIENT_SINGLE_THREAD_CHECK();
5645 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5646 << ", " << index
<< ", " << binding
<< ")");
5647 share_group_
->program_info_manager()->UniformBlockBinding(
5648 this, program
, index
, binding
);
5649 helper_
->UniformBlockBinding(program
, index
, binding
);
5653 GLenum
GLES2Implementation::ClientWaitSync(
5654 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5655 GPU_CLIENT_SINGLE_THREAD_CHECK();
5656 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5657 << ", " << flags
<< ", " << timeout
<< ")");
5658 typedef cmds::ClientWaitSync::Result Result
;
5659 Result
* result
= GetResultAs
<Result
*>();
5661 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5662 return GL_WAIT_FAILED
;
5664 *result
= GL_WAIT_FAILED
;
5665 uint32_t v32_0
= 0, v32_1
= 0;
5666 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5667 helper_
->ClientWaitSync(
5668 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5669 GetResultShmId(), GetResultShmOffset());
5671 GPU_CLIENT_LOG("returned " << *result
);
5676 void GLES2Implementation::WaitSync(
5677 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5678 GPU_CLIENT_SINGLE_THREAD_CHECK();
5679 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5680 << flags
<< ", " << timeout
<< ")");
5681 uint32_t v32_0
= 0, v32_1
= 0;
5682 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5683 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5687 void GLES2Implementation::GetInternalformativ(
5688 GLenum target
, GLenum format
, GLenum pname
,
5689 GLsizei buf_size
, GLint
* params
) {
5690 GPU_CLIENT_SINGLE_THREAD_CHECK();
5691 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
5692 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ("
5693 << GLES2Util::GetStringRenderBufferTarget(target
) << ", "
5694 << GLES2Util::GetStringRenderBufferFormat(format
) << ", "
5695 << GLES2Util::GetStringInternalFormatParameter(pname
)
5696 << ", " << buf_size
<< ", "
5697 << static_cast<const void*>(params
) << ")");
5699 SetGLError(GL_INVALID_VALUE
, "glGetInternalformativ", "bufSize < 0");
5702 TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ");
5703 if (GetInternalformativHelper(target
, format
, pname
, buf_size
, params
)) {
5706 typedef cmds::GetInternalformativ::Result Result
;
5707 Result
* result
= GetResultAs
<Result
*>();
5711 result
->SetNumResults(0);
5712 helper_
->GetInternalformativ(target
, format
, pname
,
5713 GetResultShmId(), GetResultShmOffset());
5715 GPU_CLIENT_LOG_CODE_BLOCK({
5716 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
5717 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
5720 if (buf_size
> 0 && params
) {
5721 GLint
* data
= result
->GetData();
5722 if (buf_size
>= result
->GetNumResults()) {
5723 buf_size
= result
->GetNumResults();
5725 for (GLsizei ii
= 0; ii
< buf_size
; ++ii
) {
5726 params
[ii
] = data
[ii
];
5732 GLuint
GLES2Implementation::GenPathsCHROMIUM(GLsizei range
) {
5733 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenPathsCHROMIUM(" << range
5735 GPU_CLIENT_SINGLE_THREAD_CHECK();
5736 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
5738 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5741 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5742 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5748 GLuint first_client_id
= 0;
5749 GetRangeIdHandler(id_namespaces::kPaths
)
5750 ->MakeIdRange(this, range
, &first_client_id
);
5752 if (first_client_id
== 0) {
5753 // Ran out of id space. Is not specified to raise any gl errors.
5757 helper_
->GenPathsCHROMIUM(first_client_id
, range
);
5759 GPU_CLIENT_LOG_CODE_BLOCK({
5760 for (GLsizei i
= 0; i
< range
; ++i
) {
5761 GPU_CLIENT_LOG(" " << i
<< ": " << (first_client_id
+ i
));
5765 return first_client_id
;
5768 void GLES2Implementation::DeletePathsCHROMIUM(GLuint first_client_id
,
5770 GPU_CLIENT_SINGLE_THREAD_CHECK();
5771 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeletePathsCHROMIUM("
5772 << first_client_id
<< ", " << range
<< ")");
5773 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
5776 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
5779 if (!base::IsValueInRangeForNumericType
<int32_t>(range
)) {
5780 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "range more than 32-bit");
5786 GLuint last_client_id
;
5787 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
)) {
5788 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5792 GetRangeIdHandler(id_namespaces::kPaths
)
5793 ->FreeIdRange(this, first_client_id
, range
,
5794 &GLES2Implementation::DeletePathsCHROMIUMStub
);
5798 void GLES2Implementation::DeletePathsCHROMIUMStub(GLuint first_client_id
,
5800 helper_
->DeletePathsCHROMIUM(first_client_id
, range
);
5803 void GLES2Implementation::PathCommandsCHROMIUM(GLuint path
,
5804 GLsizei num_commands
,
5805 const GLubyte
* commands
,
5808 const void* coords
) {
5809 GPU_CLIENT_SINGLE_THREAD_CHECK();
5810 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPathCommandsCHROMIUM(" << path
5811 << ", " << num_commands
<< ", " << commands
<< ", "
5812 << num_coords
<< ", " << coords
<< ")");
5813 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
5815 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "invalid path object");
5818 if (num_commands
< 0) {
5819 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
5822 if (num_commands
!= 0 && !commands
) {
5823 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing commands");
5826 if (num_coords
< 0) {
5827 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
5830 if (num_coords
!= 0 && !coords
) {
5831 SetGLError(GL_INVALID_VALUE
, kFunctionName
, "missing coords");
5834 uint32 coord_type_size
= GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
5835 if (coord_type_size
== 0) {
5836 SetGLError(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
5839 if (num_commands
== 0) {
5840 // No commands must mean no coords, thus nothing to memcpy. Let
5841 // the service validate the call. Validate coord_type above, so
5842 // that the parameters will be checked the in the same order
5843 // regardless of num_commands.
5844 helper_
->PathCommandsCHROMIUM(path
, num_commands
, 0, 0, num_coords
,
5851 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
)) {
5852 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5856 uint32 required_buffer_size
;
5857 if (!SafeAddUint32(coords_size
, num_commands
, &required_buffer_size
)) {
5858 SetGLError(GL_INVALID_OPERATION
, kFunctionName
, "overflow");
5862 ScopedTransferBufferPtr
buffer(required_buffer_size
, helper_
,
5864 if (!buffer
.valid() || buffer
.size() < required_buffer_size
) {
5865 SetGLError(GL_OUT_OF_MEMORY
, kFunctionName
, "too large");
5869 uint32 coords_shm_id
= 0;
5870 uint32 coords_shm_offset
= 0;
5871 // Copy coords first because they need more strict alignment.
5872 if (coords_size
> 0) {
5873 unsigned char* coords_addr
= static_cast<unsigned char*>(buffer
.address());
5874 memcpy(coords_addr
, coords
, coords_size
);
5875 coords_shm_id
= buffer
.shm_id();
5876 coords_shm_offset
= buffer
.offset();
5879 DCHECK(num_commands
> 0);
5880 unsigned char* commands_addr
=
5881 static_cast<unsigned char*>(buffer
.address()) + coords_size
;
5882 memcpy(commands_addr
, commands
, num_commands
);
5884 helper_
->PathCommandsCHROMIUM(path
, num_commands
, buffer
.shm_id(),
5885 buffer
.offset() + coords_size
, num_coords
,
5886 coord_type
, coords_shm_id
, coords_shm_offset
);
5890 // Include the auto-generated part of this file. We split this because it means
5891 // we can easily edit the non-auto generated parts right here in this file
5892 // instead of having to edit some template or the code generator.
5893 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5895 } // namespace gles2