1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // A class to emulate GLES2 over command buffers.
7 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include <GLES2/gl2ext.h>
10 #include <GLES2/gl2extchromium.h>
11 #include <GLES3/gl3.h>
19 #include "base/bind.h"
20 #include "base/compiler_specific.h"
21 #include "base/numerics/safe_math.h"
22 #include "gpu/command_buffer/client/buffer_tracker.h"
23 #include "gpu/command_buffer/client/gpu_control.h"
24 #include "gpu/command_buffer/client/program_info_manager.h"
25 #include "gpu/command_buffer/client/query_tracker.h"
26 #include "gpu/command_buffer/client/transfer_buffer.h"
27 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
28 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
29 #include "gpu/command_buffer/common/trace_event.h"
31 #if defined(GPU_CLIENT_DEBUG)
32 #include "base/command_line.h"
33 #include "gpu/command_buffer/client/gpu_switches.h"
39 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
40 static GLuint
ToGLuint(const void* ptr
) {
41 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
44 #if !defined(_MSC_VER)
45 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
46 const unsigned int GLES2Implementation::kStartingOffset
;
49 GLES2Implementation::GLStaticState::GLStaticState() {
52 GLES2Implementation::GLStaticState::~GLStaticState() {
55 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
56 GLES2Implementation
* gles2_implementation
)
57 : gles2_implementation_(gles2_implementation
) {
58 CHECK_EQ(0, gles2_implementation_
->use_count_
);
59 ++gles2_implementation_
->use_count_
;
62 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
63 --gles2_implementation_
->use_count_
;
64 CHECK_EQ(0, gles2_implementation_
->use_count_
);
67 GLES2Implementation::GLES2Implementation(
68 GLES2CmdHelper
* helper
,
69 ShareGroup
* share_group
,
70 TransferBufferInterface
* transfer_buffer
,
71 bool bind_generates_resource
,
72 bool lose_context_when_out_of_memory
,
73 bool support_client_side_arrays
,
74 GpuControl
* gpu_control
)
76 transfer_buffer_(transfer_buffer
),
77 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
78 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
81 unpack_flip_y_(false),
82 unpack_row_length_(0),
83 unpack_image_height_(0),
85 unpack_skip_pixels_(0),
86 unpack_skip_images_(0),
87 pack_reverse_row_order_(false),
88 active_texture_unit_(0),
89 bound_framebuffer_(0),
90 bound_read_framebuffer_(0),
91 bound_renderbuffer_(0),
92 bound_valuebuffer_(0),
94 bound_array_buffer_(0),
95 bound_copy_read_buffer_(0),
96 bound_copy_write_buffer_(0),
97 bound_pixel_pack_buffer_(0),
98 bound_pixel_unpack_buffer_(0),
99 bound_transform_feedback_buffer_(0),
100 bound_uniform_buffer_(0),
101 bound_pixel_pack_transfer_buffer_id_(0),
102 bound_pixel_unpack_transfer_buffer_id_(0),
103 async_upload_token_(0),
104 async_upload_sync_(NULL
),
105 async_upload_sync_shm_id_(0),
106 async_upload_sync_shm_offset_(0),
109 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
110 support_client_side_arrays_(support_client_side_arrays
),
112 error_message_callback_(NULL
),
113 current_trace_stack_(0),
114 gpu_control_(gpu_control
),
115 capabilities_(gpu_control
->GetCapabilities()),
116 aggressively_free_resources_(false),
117 weak_ptr_factory_(this) {
119 DCHECK(transfer_buffer
);
122 std::stringstream ss
;
123 ss
<< std::hex
<< this;
124 this_in_hex_
= ss
.str();
126 GPU_CLIENT_LOG_CODE_BLOCK({
127 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
128 switches::kEnableGPUClientLogging
);
132 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
133 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
135 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
138 bool GLES2Implementation::Initialize(
139 unsigned int starting_transfer_buffer_size
,
140 unsigned int min_transfer_buffer_size
,
141 unsigned int max_transfer_buffer_size
,
142 unsigned int mapped_memory_limit
) {
143 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
144 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
145 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
146 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
148 if (!transfer_buffer_
->Initialize(
149 starting_transfer_buffer_size
,
151 min_transfer_buffer_size
,
152 max_transfer_buffer_size
,
158 mapped_memory_
.reset(
159 new MappedMemoryManager(
161 base::Bind(&GLES2Implementation::PollAsyncUploads
,
162 // The mapped memory manager is owned by |this| here, and
163 // since its destroyed before before we destroy ourselves
164 // we don't need extra safety measures for this closure.
165 base::Unretained(this)),
166 mapped_memory_limit
));
168 unsigned chunk_size
= 2 * 1024 * 1024;
169 if (mapped_memory_limit
!= kNoLimit
) {
170 // Use smaller chunks if the client is very memory conscientious.
171 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
173 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
175 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
176 &static_state_
.shader_precisions
;
177 capabilities_
.VisitPrecisions([shader_precisions
](
178 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
179 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
180 cmds::GetShaderPrecisionFormat::Result cached_result
= {
181 true, result
->min_range
, result
->max_range
, result
->precision
};
182 shader_precisions
->insert(std::make_pair(key
, cached_result
));
185 util_
.set_num_compressed_texture_formats(
186 capabilities_
.num_compressed_texture_formats
);
187 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
189 texture_units_
.reset(
190 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
192 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
193 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
195 query_id_allocator_
.reset(new IdAllocator());
196 if (support_client_side_arrays_
) {
197 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
198 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
201 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
202 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
203 support_client_side_arrays_
));
205 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
206 // on Client & Service.
207 if (capabilities_
.bind_generates_resource_chromium
!=
208 (share_group_
->bind_generates_resource() ? 1 : 0)) {
209 SetGLError(GL_INVALID_OPERATION
,
211 "Service bind_generates_resource mismatch.");
218 GLES2Implementation::~GLES2Implementation() {
219 // Make sure the queries are finished otherwise we'll delete the
220 // shared memory (mapped_memory_) which will free the memory used
221 // by the queries. The GPU process when validating that memory is still
222 // shared will fail and abort (ie, it will stop running).
224 query_tracker_
.reset();
226 // GLES2Implementation::Initialize() could fail before allocating
227 // reserved_ids_, so we need delete them carefully.
228 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
229 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
232 // Release remaining BufferRange mem; This is when a MapBufferRange() is
233 // called but not the UnmapBuffer() pair.
234 ClearMappedBufferRangeMap();
236 // Release any per-context data in share group.
237 share_group_
->FreeContext(this);
239 buffer_tracker_
.reset();
241 FreeAllAsyncUploadBuffers();
243 if (async_upload_sync_
) {
244 mapped_memory_
->Free(async_upload_sync_
);
245 async_upload_sync_
= NULL
;
248 // Make sure the commands make it the service.
252 GLES2CmdHelper
* GLES2Implementation::helper() const {
256 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
257 return share_group_
->GetIdHandler(namespace_id
);
260 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
261 if (namespace_id
== id_namespaces::kQueries
)
262 return query_id_allocator_
.get();
267 void* GLES2Implementation::GetResultBuffer() {
268 return transfer_buffer_
->GetResultBuffer();
271 int32
GLES2Implementation::GetResultShmId() {
272 return transfer_buffer_
->GetShmId();
275 uint32
GLES2Implementation::GetResultShmOffset() {
276 return transfer_buffer_
->GetResultOffset();
279 void GLES2Implementation::FreeUnusedSharedMemory() {
280 mapped_memory_
->FreeUnused();
283 void GLES2Implementation::FreeEverything() {
284 FreeAllAsyncUploadBuffers();
286 query_tracker_
->Shrink();
287 FreeUnusedSharedMemory();
288 transfer_buffer_
->Free();
289 helper_
->FreeRingBuffer();
292 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
293 if (!helper_
->IsContextLost())
297 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
298 const base::Closure
& callback
) {
299 gpu_control_
->SignalSyncPoint(
301 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
302 weak_ptr_factory_
.GetWeakPtr(),
306 void GLES2Implementation::SignalQuery(uint32 query
,
307 const base::Closure
& callback
) {
308 // Flush previously entered commands to ensure ordering with any
309 // glBeginQueryEXT() calls that may have been put into the context.
310 ShallowFlushCHROMIUM();
311 gpu_control_
->SignalQuery(
313 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
314 weak_ptr_factory_
.GetWeakPtr(),
318 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
320 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
321 ShallowFlushCHROMIUM();
322 gpu_control_
->SetSurfaceVisible(visible
);
325 void GLES2Implementation::SetAggressivelyFreeResources(
326 bool aggressively_free_resources
) {
327 TRACE_EVENT1("gpu", "GLES2Implementation::SetAggressivelyFreeResources",
328 "aggressively_free_resources", aggressively_free_resources
);
329 aggressively_free_resources_
= aggressively_free_resources
;
331 // ShallowFlushCHROMIUM will free resources if |aggressively_free_resources_|
333 ShallowFlushCHROMIUM();
336 void GLES2Implementation::WaitForCmd() {
337 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
338 helper_
->CommandBufferHelper::Finish();
341 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
342 const char* extensions
=
343 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
347 int length
= strlen(ext
);
349 int n
= strcspn(extensions
, " ");
350 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
353 if ('\0' == extensions
[n
]) {
360 bool GLES2Implementation::IsExtensionAvailableHelper(
361 const char* extension
, ExtensionStatus
* status
) {
363 case kAvailableExtensionStatus
:
365 case kUnavailableExtensionStatus
:
368 bool available
= IsExtensionAvailable(extension
);
369 *status
= available
? kAvailableExtensionStatus
:
370 kUnavailableExtensionStatus
;
376 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
377 return IsExtensionAvailableHelper(
378 "GL_ANGLE_pack_reverse_row_order",
379 &angle_pack_reverse_row_order_status_
);
382 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
383 return IsExtensionAvailableHelper(
384 "GL_CHROMIUM_framebuffer_multisample",
385 &chromium_framebuffer_multisample_
);
388 const std::string
& GLES2Implementation::GetLogPrefix() const {
389 const std::string
& prefix(debug_marker_manager_
.GetMarker());
390 return prefix
.empty() ? this_in_hex_
: prefix
;
393 GLenum
GLES2Implementation::GetError() {
394 GPU_CLIENT_SINGLE_THREAD_CHECK();
395 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
396 GLenum err
= GetGLError();
397 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
401 GLenum
GLES2Implementation::GetClientSideGLError() {
402 if (error_bits_
== 0) {
406 GLenum error
= GL_NO_ERROR
;
407 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
408 if ((error_bits_
& mask
) != 0) {
409 error
= GLES2Util::GLErrorBitToGLError(mask
);
413 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
417 GLenum
GLES2Implementation::GetGLError() {
418 TRACE_EVENT0("gpu", "GLES2::GetGLError");
419 // Check the GL error first, then our wrapped error.
420 typedef cmds::GetError::Result Result
;
421 Result
* result
= GetResultAs
<Result
*>();
422 // If we couldn't allocate a result the context is lost.
426 *result
= GL_NO_ERROR
;
427 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
429 GLenum error
= *result
;
430 if (error
== GL_NO_ERROR
) {
431 error
= GetClientSideGLError();
433 // There was an error, clear the corresponding wrapped error.
434 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
439 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
440 void GLES2Implementation::FailGLError(GLenum error
) {
441 if (error
!= GL_NO_ERROR
) {
442 NOTREACHED() << "Error";
445 // NOTE: Calling GetGLError overwrites data in the result buffer.
446 void GLES2Implementation::CheckGLError() {
447 FailGLError(GetGLError());
449 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
451 void GLES2Implementation::SetGLError(
452 GLenum error
, const char* function_name
, const char* msg
) {
453 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
454 << GLES2Util::GetStringError(error
) << ": "
455 << function_name
<< ": " << msg
);
460 if (error_message_callback_
) {
461 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
462 function_name
+ ": " + (msg
? msg
: ""));
463 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
465 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
467 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
468 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
469 GL_UNKNOWN_CONTEXT_RESET_ARB
);
473 void GLES2Implementation::SetGLErrorInvalidEnum(
474 const char* function_name
, GLenum value
, const char* label
) {
475 SetGLError(GL_INVALID_ENUM
, function_name
,
476 (std::string(label
) + " was " +
477 GLES2Util::GetStringEnum(value
)).c_str());
480 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
481 std::vector
<int8
>* data
) {
482 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
484 const uint32 kStartSize
= 32 * 1024;
485 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
486 if (!buffer
.valid()) {
489 typedef cmd::GetBucketStart::Result Result
;
490 Result
* result
= GetResultAs
<Result
*>();
495 helper_
->GetBucketStart(
496 bucket_id
, GetResultShmId(), GetResultShmOffset(),
497 buffer
.size(), buffer
.shm_id(), buffer
.offset());
499 uint32 size
= *result
;
504 if (!buffer
.valid()) {
506 if (!buffer
.valid()) {
509 helper_
->GetBucketData(
510 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
513 uint32 size_to_copy
= std::min(size
, buffer
.size());
514 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
515 offset
+= size_to_copy
;
516 size
-= size_to_copy
;
519 // Free the bucket. This is not required but it does free up the memory.
520 // and we don't have to wait for the result so from the client's perspective
522 helper_
->SetBucketSize(bucket_id
, 0);
527 void GLES2Implementation::SetBucketContents(
528 uint32 bucket_id
, const void* data
, size_t size
) {
530 helper_
->SetBucketSize(bucket_id
, size
);
534 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
535 if (!buffer
.valid()) {
538 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
540 helper_
->SetBucketData(
541 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
542 offset
+= buffer
.size();
543 size
-= buffer
.size();
548 void GLES2Implementation::SetBucketAsCString(
549 uint32 bucket_id
, const char* str
) {
550 // NOTE: strings are passed NULL terminated. That means the empty
551 // string will have a size of 1 and no-string will have a size of 0
553 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
555 helper_
->SetBucketSize(bucket_id
, 0);
559 bool GLES2Implementation::GetBucketAsString(
560 uint32 bucket_id
, std::string
* str
) {
562 std::vector
<int8
> data
;
563 // NOTE: strings are passed NULL terminated. That means the empty
564 // string will have a size of 1 and no-string will have a size of 0
565 if (!GetBucketContents(bucket_id
, &data
)) {
571 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
575 void GLES2Implementation::SetBucketAsString(
576 uint32 bucket_id
, const std::string
& str
) {
577 // NOTE: strings are passed NULL terminated. That means the empty
578 // string will have a size of 1 and no-string will have a size of 0
579 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
582 void GLES2Implementation::Disable(GLenum cap
) {
583 GPU_CLIENT_SINGLE_THREAD_CHECK();
584 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
585 << GLES2Util::GetStringCapability(cap
) << ")");
586 bool changed
= false;
587 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
588 helper_
->Disable(cap
);
593 void GLES2Implementation::Enable(GLenum cap
) {
594 GPU_CLIENT_SINGLE_THREAD_CHECK();
595 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
596 << GLES2Util::GetStringCapability(cap
) << ")");
597 bool changed
= false;
598 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
599 helper_
->Enable(cap
);
604 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
605 GPU_CLIENT_SINGLE_THREAD_CHECK();
606 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
607 << GLES2Util::GetStringCapability(cap
) << ")");
609 if (!state_
.GetEnabled(cap
, &state
)) {
610 typedef cmds::IsEnabled::Result Result
;
611 Result
* result
= GetResultAs
<Result
*>();
616 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
618 state
= (*result
) != 0;
621 GPU_CLIENT_LOG("returned " << state
);
626 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
627 // TODO(zmo): For all the BINDING points, there is a possibility where
628 // resources are shared among multiple contexts, that the cached points
629 // are invalid. It is not a problem for now, but once we allow resource
630 // sharing in WebGL, we need to implement a mechanism to allow correct
631 // client side binding points tracking. crbug.com/465562.
635 case GL_ACTIVE_TEXTURE
:
636 *params
= active_texture_unit_
+ GL_TEXTURE0
;
638 case GL_ARRAY_BUFFER_BINDING
:
639 *params
= bound_array_buffer_
;
641 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
643 vertex_array_object_manager_
->bound_element_array_buffer();
645 case GL_FRAMEBUFFER_BINDING
:
646 *params
= bound_framebuffer_
;
648 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
649 *params
= capabilities_
.max_combined_texture_image_units
;
651 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
652 *params
= capabilities_
.max_cube_map_texture_size
;
654 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
655 *params
= capabilities_
.max_fragment_uniform_vectors
;
657 case GL_MAX_RENDERBUFFER_SIZE
:
658 *params
= capabilities_
.max_renderbuffer_size
;
660 case GL_MAX_TEXTURE_IMAGE_UNITS
:
661 *params
= capabilities_
.max_texture_image_units
;
663 case GL_MAX_TEXTURE_SIZE
:
664 *params
= capabilities_
.max_texture_size
;
666 case GL_MAX_VARYING_VECTORS
:
667 *params
= capabilities_
.max_varying_vectors
;
669 case GL_MAX_VERTEX_ATTRIBS
:
670 *params
= capabilities_
.max_vertex_attribs
;
672 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
673 *params
= capabilities_
.max_vertex_texture_image_units
;
675 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
676 *params
= capabilities_
.max_vertex_uniform_vectors
;
678 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
679 *params
= capabilities_
.num_compressed_texture_formats
;
681 case GL_NUM_SHADER_BINARY_FORMATS
:
682 *params
= capabilities_
.num_shader_binary_formats
;
684 case GL_RENDERBUFFER_BINDING
:
685 *params
= bound_renderbuffer_
;
687 case GL_TEXTURE_BINDING_2D
:
688 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
690 case GL_TEXTURE_BINDING_CUBE_MAP
:
691 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
694 // Non-standard parameters.
695 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
697 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
699 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
700 *params
= bound_pixel_pack_transfer_buffer_id_
;
702 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
703 *params
= bound_pixel_unpack_transfer_buffer_id_
;
705 case GL_READ_FRAMEBUFFER_BINDING
:
706 if (IsChromiumFramebufferMultisampleAvailable()) {
707 *params
= bound_read_framebuffer_
;
712 // Non-cached parameters.
713 case GL_ALIASED_LINE_WIDTH_RANGE
:
714 case GL_ALIASED_POINT_SIZE_RANGE
:
718 case GL_BLEND_DST_ALPHA
:
719 case GL_BLEND_DST_RGB
:
720 case GL_BLEND_EQUATION_ALPHA
:
721 case GL_BLEND_EQUATION_RGB
:
722 case GL_BLEND_SRC_ALPHA
:
723 case GL_BLEND_SRC_RGB
:
725 case GL_COLOR_CLEAR_VALUE
:
726 case GL_COLOR_WRITEMASK
:
727 case GL_COMPRESSED_TEXTURE_FORMATS
:
729 case GL_CULL_FACE_MODE
:
730 case GL_CURRENT_PROGRAM
:
732 case GL_DEPTH_CLEAR_VALUE
:
736 case GL_DEPTH_WRITEMASK
:
739 case GL_GENERATE_MIPMAP_HINT
:
741 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
742 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
744 case GL_MAX_VIEWPORT_DIMS
:
745 case GL_PACK_ALIGNMENT
:
746 case GL_POLYGON_OFFSET_FACTOR
:
747 case GL_POLYGON_OFFSET_FILL
:
748 case GL_POLYGON_OFFSET_UNITS
:
750 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
751 case GL_SAMPLE_BUFFERS
:
752 case GL_SAMPLE_COVERAGE
:
753 case GL_SAMPLE_COVERAGE_INVERT
:
754 case GL_SAMPLE_COVERAGE_VALUE
:
757 case GL_SCISSOR_TEST
:
758 case GL_SHADER_BINARY_FORMATS
:
759 case GL_SHADER_COMPILER
:
760 case GL_STENCIL_BACK_FAIL
:
761 case GL_STENCIL_BACK_FUNC
:
762 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
763 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
764 case GL_STENCIL_BACK_REF
:
765 case GL_STENCIL_BACK_VALUE_MASK
:
766 case GL_STENCIL_BACK_WRITEMASK
:
767 case GL_STENCIL_BITS
:
768 case GL_STENCIL_CLEAR_VALUE
:
769 case GL_STENCIL_FAIL
:
770 case GL_STENCIL_FUNC
:
771 case GL_STENCIL_PASS_DEPTH_FAIL
:
772 case GL_STENCIL_PASS_DEPTH_PASS
:
774 case GL_STENCIL_TEST
:
775 case GL_STENCIL_VALUE_MASK
:
776 case GL_STENCIL_WRITEMASK
:
777 case GL_SUBPIXEL_BITS
:
778 case GL_UNPACK_ALIGNMENT
:
785 if (capabilities_
.major_version
< 3) {
791 case GL_COPY_READ_BUFFER_BINDING
:
792 *params
= bound_copy_read_buffer_
;
794 case GL_COPY_WRITE_BUFFER_BINDING
:
795 *params
= bound_copy_write_buffer_
;
797 case GL_MAJOR_VERSION
:
798 *params
= capabilities_
.major_version
;
800 case GL_MAX_3D_TEXTURE_SIZE
:
801 *params
= capabilities_
.max_3d_texture_size
;
803 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
804 *params
= capabilities_
.max_array_texture_layers
;
806 case GL_MAX_COLOR_ATTACHMENTS
:
807 *params
= capabilities_
.max_color_attachments
;
809 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
810 *params
= static_cast<GLint
>(
811 capabilities_
.max_combined_fragment_uniform_components
);
813 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
814 *params
= capabilities_
.max_combined_uniform_blocks
;
816 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
817 *params
= static_cast<GLint
>(
818 capabilities_
.max_combined_vertex_uniform_components
);
820 case GL_MAX_DRAW_BUFFERS
:
821 *params
= capabilities_
.max_draw_buffers
;
823 case GL_MAX_ELEMENT_INDEX
:
824 *params
= static_cast<GLint
>(capabilities_
.max_element_index
);
826 case GL_MAX_ELEMENTS_INDICES
:
827 *params
= capabilities_
.max_elements_indices
;
829 case GL_MAX_ELEMENTS_VERTICES
:
830 *params
= capabilities_
.max_elements_vertices
;
832 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
833 *params
= capabilities_
.max_fragment_input_components
;
835 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
836 *params
= capabilities_
.max_fragment_uniform_blocks
;
838 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
839 *params
= capabilities_
.max_fragment_uniform_components
;
841 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
842 *params
= capabilities_
.max_program_texel_offset
;
845 *params
= capabilities_
.max_samples
;
847 case GL_MAX_SERVER_WAIT_TIMEOUT
:
848 *params
= static_cast<GLint
>(capabilities_
.max_server_wait_timeout
);
850 case GL_MAX_TEXTURE_LOD_BIAS
:
851 *params
= static_cast<GLint
>(capabilities_
.max_texture_lod_bias
);
853 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
854 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
856 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
857 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
859 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
860 *params
= capabilities_
.max_transform_feedback_separate_components
;
862 case GL_MAX_UNIFORM_BLOCK_SIZE
:
863 *params
= static_cast<GLint
>(capabilities_
.max_uniform_block_size
);
865 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
866 *params
= capabilities_
.max_uniform_buffer_bindings
;
868 case GL_MAX_VARYING_COMPONENTS
:
869 *params
= capabilities_
.max_varying_components
;
871 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
872 *params
= capabilities_
.max_vertex_output_components
;
874 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
875 *params
= capabilities_
.max_vertex_uniform_blocks
;
877 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
878 *params
= capabilities_
.max_vertex_uniform_components
;
880 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
881 *params
= capabilities_
.min_program_texel_offset
;
883 case GL_MINOR_VERSION
:
884 *params
= capabilities_
.minor_version
;
886 case GL_NUM_EXTENSIONS
:
887 *params
= capabilities_
.num_extensions
;
889 case GL_NUM_PROGRAM_BINARY_FORMATS
:
890 *params
= capabilities_
.num_program_binary_formats
;
892 case GL_PIXEL_PACK_BUFFER_BINDING
:
893 *params
= bound_pixel_pack_buffer_
;
895 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
896 *params
= bound_pixel_unpack_buffer_
;
898 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
899 *params
= bound_transform_feedback_buffer_
;
901 case GL_UNIFORM_BUFFER_BINDING
:
902 *params
= bound_uniform_buffer_
;
904 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
905 *params
= capabilities_
.uniform_buffer_offset_alignment
;
908 // Non-cached ES3 parameters.
909 case GL_DRAW_BUFFER0
:
910 case GL_DRAW_BUFFER1
:
911 case GL_DRAW_BUFFER2
:
912 case GL_DRAW_BUFFER3
:
913 case GL_DRAW_BUFFER4
:
914 case GL_DRAW_BUFFER5
:
915 case GL_DRAW_BUFFER6
:
916 case GL_DRAW_BUFFER7
:
917 case GL_DRAW_BUFFER8
:
918 case GL_DRAW_BUFFER9
:
919 case GL_DRAW_BUFFER10
:
920 case GL_DRAW_BUFFER11
:
921 case GL_DRAW_BUFFER12
:
922 case GL_DRAW_BUFFER13
:
923 case GL_DRAW_BUFFER14
:
924 case GL_DRAW_BUFFER15
:
925 case GL_DRAW_FRAMEBUFFER_BINDING
:
926 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
927 case GL_PACK_ROW_LENGTH
:
928 case GL_PACK_SKIP_PIXELS
:
929 case GL_PACK_SKIP_ROWS
:
930 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
931 case GL_PROGRAM_BINARY_FORMATS
:
932 case GL_RASTERIZER_DISCARD
:
934 case GL_READ_FRAMEBUFFER_BINDING
:
935 case GL_SAMPLER_BINDING
:
936 case GL_TEXTURE_BINDING_2D_ARRAY
:
937 case GL_TEXTURE_BINDING_3D
:
938 case GL_TRANSFORM_FEEDBACK_BINDING
:
939 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
940 case GL_TRANSFORM_FEEDBACK_PAUSED
:
941 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
942 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
943 case GL_UNIFORM_BUFFER_SIZE
:
944 case GL_UNIFORM_BUFFER_START
:
945 case GL_UNPACK_IMAGE_HEIGHT
:
946 case GL_UNPACK_ROW_LENGTH
:
947 case GL_UNPACK_SKIP_IMAGES
:
948 case GL_UNPACK_SKIP_PIXELS
:
949 case GL_UNPACK_SKIP_ROWS
:
950 case GL_VERTEX_ARRAY_BINDING
:
957 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
958 // TODO(gman): Make this handle pnames that return more than 1 value.
960 if (!GetHelper(pname
, &value
)) {
963 *params
= static_cast<GLboolean
>(value
);
967 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
968 // TODO(gman): Make this handle pnames that return more than 1 value.
970 case GL_MAX_TEXTURE_LOD_BIAS
:
971 *params
= capabilities_
.max_texture_lod_bias
;
977 if (!GetHelper(pname
, &value
)) {
980 *params
= static_cast<GLfloat
>(value
);
984 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
986 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
987 *params
= capabilities_
.max_combined_fragment_uniform_components
;
989 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
990 *params
= capabilities_
.max_combined_vertex_uniform_components
;
992 case GL_MAX_ELEMENT_INDEX
:
993 *params
= capabilities_
.max_element_index
;
995 case GL_MAX_SERVER_WAIT_TIMEOUT
:
996 *params
= capabilities_
.max_server_wait_timeout
;
998 case GL_MAX_UNIFORM_BLOCK_SIZE
:
999 *params
= capabilities_
.max_uniform_block_size
;
1005 if (!GetHelper(pname
, &value
)) {
1008 *params
= static_cast<GLint64
>(value
);
1012 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
1013 return GetHelper(pname
, params
);
1016 bool GLES2Implementation::GetIntegeri_vHelper(
1017 GLenum pname
, GLuint index
, GLint
* data
) {
1018 // TODO(zmo): Implement client side caching.
1022 bool GLES2Implementation::GetInteger64i_vHelper(
1023 GLenum pname
, GLuint index
, GLint64
* data
) {
1024 // TODO(zmo): Implement client side caching.
1028 bool GLES2Implementation::GetInternalformativHelper(
1029 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
1031 // TODO(zmo): Implement the client side caching.
1035 bool GLES2Implementation::GetSyncivHelper(
1036 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
1040 case GL_OBJECT_TYPE
:
1041 value
= GL_SYNC_FENCE
;
1043 case GL_SYNC_CONDITION
:
1044 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1062 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1063 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1064 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1065 Result
* result
= GetResultAs
<Result
*>();
1070 helper_
->GetMaxValueInBufferCHROMIUM(
1071 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1076 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1077 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1078 GPU_CLIENT_SINGLE_THREAD_CHECK();
1079 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1080 << buffer_id
<< ", " << count
<< ", "
1081 << GLES2Util::GetStringGetMaxIndexType(type
)
1082 << ", " << offset
<< ")");
1083 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1084 buffer_id
, count
, type
, offset
);
1085 GPU_CLIENT_LOG("returned " << result
);
1090 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1092 RestoreArrayBuffer(restore
);
1093 // Restore the element array binding.
1094 // We only need to restore it if it wasn't a client side array.
1095 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1096 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1101 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1103 // Restore the user's current binding.
1104 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_
);
1108 void GLES2Implementation::DrawElements(
1109 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1110 GPU_CLIENT_SINGLE_THREAD_CHECK();
1111 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1112 << GLES2Util::GetStringDrawMode(mode
) << ", "
1114 << GLES2Util::GetStringIndexType(type
) << ", "
1115 << static_cast<const void*>(indices
) << ")");
1116 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1119 void GLES2Implementation::DrawRangeElements(
1120 GLenum mode
, GLuint start
, GLuint end
,
1121 GLsizei count
, GLenum type
, const void* indices
) {
1122 GPU_CLIENT_SINGLE_THREAD_CHECK();
1123 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1124 << GLES2Util::GetStringDrawMode(mode
) << ", "
1125 << start
<< ", " << end
<< ", " << count
<< ", "
1126 << GLES2Util::GetStringIndexType(type
) << ", "
1127 << static_cast<const void*>(indices
) << ")");
1129 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1132 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1135 void GLES2Implementation::DrawElementsImpl(
1136 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1137 const char* func_name
) {
1139 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1142 bool simulated
= false;
1143 GLuint offset
= ToGLuint(indices
);
1145 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1146 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1149 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1150 func_name
, this, helper_
, count
, type
, 0, indices
,
1151 &offset
, &simulated
)) {
1155 helper_
->DrawElements(mode
, count
, type
, offset
);
1156 RestoreElementAndArrayBuffers(simulated
);
1160 void GLES2Implementation::Flush() {
1161 GPU_CLIENT_SINGLE_THREAD_CHECK();
1162 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1163 // Insert the cmd to call glFlush
1168 void GLES2Implementation::ShallowFlushCHROMIUM() {
1169 GPU_CLIENT_SINGLE_THREAD_CHECK();
1170 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1174 void GLES2Implementation::FlushHelper() {
1175 // Flush our command buffer
1176 // (tell the service to execute up to the flush cmd.)
1177 helper_
->CommandBufferHelper::Flush();
1179 if (aggressively_free_resources_
)
1183 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1184 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1185 // Flush command buffer at the GPU channel level. May be implemented as
1187 helper_
->CommandBufferHelper::OrderingBarrier();
1190 void GLES2Implementation::Finish() {
1191 GPU_CLIENT_SINGLE_THREAD_CHECK();
1195 void GLES2Implementation::ShallowFinishCHROMIUM() {
1196 GPU_CLIENT_SINGLE_THREAD_CHECK();
1197 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1198 // Flush our command buffer (tell the service to execute up to the flush cmd
1199 // and don't return until it completes).
1200 helper_
->CommandBufferHelper::Finish();
1202 if (aggressively_free_resources_
)
1206 void GLES2Implementation::FinishHelper() {
1207 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1208 TRACE_EVENT0("gpu", "GLES2::Finish");
1209 // Insert the cmd to call glFinish
1211 // Finish our command buffer
1212 // (tell the service to execute up to the Finish cmd and wait for it to
1214 helper_
->CommandBufferHelper::Finish();
1216 if (aggressively_free_resources_
)
1220 void GLES2Implementation::SwapBuffers() {
1221 GPU_CLIENT_SINGLE_THREAD_CHECK();
1222 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1223 // TODO(piman): Strictly speaking we'd want to insert the token after the
1224 // swap, but the state update with the updated token might not have happened
1225 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1226 // with the GPU process more than needed. So instead, make it happen before.
1227 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1228 // semantics if the client doesn't use the callback mechanism, and by chance
1229 // the scheduler yields between the InsertToken and the SwapBuffers.
1230 swap_buffers_tokens_
.push(helper_
->InsertToken());
1231 helper_
->SwapBuffers();
1232 helper_
->CommandBufferHelper::Flush();
1233 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1234 // compensate for TODO above.
1235 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1236 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1237 swap_buffers_tokens_
.pop();
1241 void GLES2Implementation::SwapInterval(int interval
) {
1242 GPU_CLIENT_SINGLE_THREAD_CHECK();
1243 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1244 << interval
<< ")");
1245 helper_
->SwapInterval(interval
);
1248 void GLES2Implementation::BindAttribLocation(
1249 GLuint program
, GLuint index
, const char* name
) {
1250 GPU_CLIENT_SINGLE_THREAD_CHECK();
1251 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1252 << program
<< ", " << index
<< ", " << name
<< ")");
1253 SetBucketAsString(kResultBucketId
, name
);
1254 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1255 helper_
->SetBucketSize(kResultBucketId
, 0);
1259 void GLES2Implementation::BindUniformLocationCHROMIUM(
1260 GLuint program
, GLint location
, const char* name
) {
1261 GPU_CLIENT_SINGLE_THREAD_CHECK();
1262 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1263 << program
<< ", " << location
<< ", " << name
<< ")");
1264 SetBucketAsString(kResultBucketId
, name
);
1265 helper_
->BindUniformLocationCHROMIUMBucket(
1266 program
, location
, kResultBucketId
);
1267 helper_
->SetBucketSize(kResultBucketId
, 0);
1271 void GLES2Implementation::GetVertexAttribPointerv(
1272 GLuint index
, GLenum pname
, void** ptr
) {
1273 GPU_CLIENT_SINGLE_THREAD_CHECK();
1274 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1275 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1276 << static_cast<void*>(ptr
) << ")");
1277 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1278 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1279 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1280 typedef cmds::GetVertexAttribPointerv::Result Result
;
1281 Result
* result
= GetResultAs
<Result
*>();
1285 result
->SetNumResults(0);
1286 helper_
->GetVertexAttribPointerv(
1287 index
, pname
, GetResultShmId(), GetResultShmOffset());
1289 result
->CopyResult(ptr
);
1290 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1292 GPU_CLIENT_LOG_CODE_BLOCK({
1293 for (int32 i
= 0; i
< num_results
; ++i
) {
1294 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1300 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1301 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1302 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1305 "glDeleteProgram", "id not created by this context.");
1308 if (program
== current_program_
) {
1309 current_program_
= 0;
1314 void GLES2Implementation::DeleteProgramStub(
1315 GLsizei n
, const GLuint
* programs
) {
1317 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1318 helper_
->DeleteProgram(programs
[0]);
1321 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1322 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1323 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1326 "glDeleteShader", "id not created by this context.");
1332 void GLES2Implementation::DeleteShaderStub(
1333 GLsizei n
, const GLuint
* shaders
) {
1335 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1336 helper_
->DeleteShader(shaders
[0]);
1339 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1340 GLuint sync_uint
= ToGLuint(sync
);
1341 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1342 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1345 "glDeleteSync", "id not created by this context.");
1349 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1351 helper_
->DeleteSync(syncs
[0]);
1354 GLint
GLES2Implementation::GetAttribLocationHelper(
1355 GLuint program
, const char* name
) {
1356 typedef cmds::GetAttribLocation::Result Result
;
1357 Result
* result
= GetResultAs
<Result
*>();
1362 SetBucketAsCString(kResultBucketId
, name
);
1363 helper_
->GetAttribLocation(
1364 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1366 helper_
->SetBucketSize(kResultBucketId
, 0);
1370 GLint
GLES2Implementation::GetAttribLocation(
1371 GLuint program
, const char* name
) {
1372 GPU_CLIENT_SINGLE_THREAD_CHECK();
1373 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1374 << ", " << name
<< ")");
1375 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1376 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1377 this, program
, name
);
1378 GPU_CLIENT_LOG("returned " << loc
);
1383 GLint
GLES2Implementation::GetUniformLocationHelper(
1384 GLuint program
, const char* name
) {
1385 typedef cmds::GetUniformLocation::Result Result
;
1386 Result
* result
= GetResultAs
<Result
*>();
1391 SetBucketAsCString(kResultBucketId
, name
);
1392 helper_
->GetUniformLocation(program
, kResultBucketId
,
1393 GetResultShmId(), GetResultShmOffset());
1395 helper_
->SetBucketSize(kResultBucketId
, 0);
1399 GLint
GLES2Implementation::GetUniformLocation(
1400 GLuint program
, const char* name
) {
1401 GPU_CLIENT_SINGLE_THREAD_CHECK();
1402 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1403 << ", " << name
<< ")");
1404 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1405 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1406 this, program
, name
);
1407 GPU_CLIENT_LOG("returned " << loc
);
1412 bool GLES2Implementation::GetUniformIndicesHelper(
1413 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1414 typedef cmds::GetUniformIndices::Result Result
;
1415 Result
* result
= GetResultAs
<Result
*>();
1419 result
->SetNumResults(0);
1420 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1423 helper_
->GetUniformIndices(program
, kResultBucketId
,
1424 GetResultShmId(), GetResultShmOffset());
1426 if (result
->GetNumResults() != count
) {
1429 result
->CopyResult(indices
);
1433 void GLES2Implementation::GetUniformIndices(
1434 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1435 GPU_CLIENT_SINGLE_THREAD_CHECK();
1436 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1437 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1438 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1440 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1446 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1447 this, program
, count
, names
, indices
);
1449 GPU_CLIENT_LOG_CODE_BLOCK({
1450 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1451 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1458 bool GLES2Implementation::GetProgramivHelper(
1459 GLuint program
, GLenum pname
, GLint
* params
) {
1460 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1461 this, program
, pname
, params
);
1462 GPU_CLIENT_LOG_CODE_BLOCK({
1464 GPU_CLIENT_LOG(" 0: " << *params
);
1470 GLint
GLES2Implementation::GetFragDataLocationHelper(
1471 GLuint program
, const char* name
) {
1472 typedef cmds::GetFragDataLocation::Result Result
;
1473 Result
* result
= GetResultAs
<Result
*>();
1478 SetBucketAsCString(kResultBucketId
, name
);
1479 helper_
->GetFragDataLocation(
1480 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1482 helper_
->SetBucketSize(kResultBucketId
, 0);
1486 GLint
GLES2Implementation::GetFragDataLocation(
1487 GLuint program
, const char* name
) {
1488 GPU_CLIENT_SINGLE_THREAD_CHECK();
1489 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1490 << program
<< ", " << name
<< ")");
1491 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1492 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1493 this, program
, name
);
1494 GPU_CLIENT_LOG("returned " << loc
);
1499 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1500 GLuint program
, const char* name
) {
1501 typedef cmds::GetUniformBlockIndex::Result Result
;
1502 Result
* result
= GetResultAs
<Result
*>();
1504 return GL_INVALID_INDEX
;
1506 *result
= GL_INVALID_INDEX
;
1507 SetBucketAsCString(kResultBucketId
, name
);
1508 helper_
->GetUniformBlockIndex(
1509 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1511 helper_
->SetBucketSize(kResultBucketId
, 0);
1515 GLuint
GLES2Implementation::GetUniformBlockIndex(
1516 GLuint program
, const char* name
) {
1517 GPU_CLIENT_SINGLE_THREAD_CHECK();
1518 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1519 << program
<< ", " << name
<< ")");
1520 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1521 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1522 this, program
, name
);
1523 GPU_CLIENT_LOG("returned " << index
);
1528 void GLES2Implementation::LinkProgram(GLuint program
) {
1529 GPU_CLIENT_SINGLE_THREAD_CHECK();
1530 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1531 helper_
->LinkProgram(program
);
1532 share_group_
->program_info_manager()->CreateInfo(program
);
1536 void GLES2Implementation::ShaderBinary(
1537 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1539 GPU_CLIENT_SINGLE_THREAD_CHECK();
1540 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1541 << static_cast<const void*>(shaders
) << ", "
1542 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1543 << static_cast<const void*>(binary
) << ", "
1546 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1550 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1553 // TODO(gman): ShaderBinary should use buckets.
1554 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1555 ScopedTransferBufferArray
<GLint
> buffer(
1556 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1557 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1558 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1561 void* shader_ids
= buffer
.elements();
1562 void* shader_data
= buffer
.elements() + shader_id_size
;
1563 memcpy(shader_ids
, shaders
, shader_id_size
);
1564 memcpy(shader_data
, binary
, length
);
1565 helper_
->ShaderBinary(
1571 buffer
.offset() + shader_id_size
,
1576 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1577 GPU_CLIENT_SINGLE_THREAD_CHECK();
1578 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1579 << GLES2Util::GetStringPixelStore(pname
) << ", "
1582 case GL_PACK_ALIGNMENT
:
1583 pack_alignment_
= param
;
1585 case GL_UNPACK_ALIGNMENT
:
1586 unpack_alignment_
= param
;
1588 case GL_UNPACK_ROW_LENGTH_EXT
:
1589 unpack_row_length_
= param
;
1591 case GL_UNPACK_IMAGE_HEIGHT
:
1592 unpack_image_height_
= param
;
1594 case GL_UNPACK_SKIP_ROWS_EXT
:
1595 unpack_skip_rows_
= param
;
1597 case GL_UNPACK_SKIP_PIXELS_EXT
:
1598 unpack_skip_pixels_
= param
;
1600 case GL_UNPACK_SKIP_IMAGES
:
1601 unpack_skip_images_
= param
;
1603 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1604 unpack_flip_y_
= (param
!= 0);
1606 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1607 pack_reverse_row_order_
=
1608 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1613 helper_
->PixelStorei(pname
, param
);
1617 void GLES2Implementation::VertexAttribIPointer(
1618 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1619 GPU_CLIENT_SINGLE_THREAD_CHECK();
1620 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1623 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1626 // Record the info on the client side.
1627 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1635 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1636 "client side arrays are not allowed in vertex array objects.");
1639 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1640 // Only report NON client side buffers to the service.
1641 if (!ValidateOffset("glVertexAttribIPointer",
1642 reinterpret_cast<GLintptr
>(ptr
))) {
1645 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1650 void GLES2Implementation::VertexAttribPointer(
1651 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1653 GPU_CLIENT_SINGLE_THREAD_CHECK();
1654 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1657 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1658 << GLES2Util::GetStringBool(normalized
) << ", "
1661 // Record the info on the client side.
1662 if (!vertex_array_object_manager_
->SetAttribPointer(bound_array_buffer_
,
1670 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1671 "client side arrays are not allowed in vertex array objects.");
1674 if (!support_client_side_arrays_
|| bound_array_buffer_
!= 0) {
1675 // Only report NON client side buffers to the service.
1676 if (!ValidateOffset("glVertexAttribPointer",
1677 reinterpret_cast<GLintptr
>(ptr
))) {
1680 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1686 void GLES2Implementation::VertexAttribDivisorANGLE(
1687 GLuint index
, GLuint divisor
) {
1688 GPU_CLIENT_SINGLE_THREAD_CHECK();
1689 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1691 << divisor
<< ") ");
1692 // Record the info on the client side.
1693 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1694 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1698 void GLES2Implementation::BufferDataHelper(
1699 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1700 if (!ValidateSize("glBufferData", size
))
1703 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1704 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1705 // bogus MSan report during a readback later. This is because MSan doesn't
1706 // understand shared memory and would assume we were reading back the same
1707 // unintialized data.
1708 if (data
) __msan_check_mem_is_initialized(data
, size
);
1712 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1717 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1719 RemoveTransferBuffer(buffer
);
1721 // Create new buffer.
1722 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1724 if (buffer
->address() && data
)
1725 memcpy(buffer
->address(), data
, size
);
1729 RemoveMappedBufferRangeByTarget(target
);
1731 // If there is no data just send BufferData
1732 if (size
== 0 || !data
) {
1733 helper_
->BufferData(target
, size
, 0, 0, usage
);
1737 // See if we can send all at once.
1738 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1739 if (!buffer
.valid()) {
1743 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1744 memcpy(buffer
.address(), data
, size
);
1745 helper_
->BufferData(
1754 // Make the buffer with BufferData then send via BufferSubData
1755 helper_
->BufferData(target
, size
, 0, 0, usage
);
1756 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1760 void GLES2Implementation::BufferData(
1761 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1762 GPU_CLIENT_SINGLE_THREAD_CHECK();
1763 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1764 << GLES2Util::GetStringBufferTarget(target
) << ", "
1766 << static_cast<const void*>(data
) << ", "
1767 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1768 BufferDataHelper(target
, size
, data
, usage
);
1772 void GLES2Implementation::BufferSubDataHelper(
1773 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1778 if (!ValidateSize("glBufferSubData", size
) ||
1779 !ValidateOffset("glBufferSubData", offset
)) {
1784 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1788 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1790 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1795 int32 buffer_size
= buffer
->size();
1796 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1797 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1801 if (buffer
->address() && data
)
1802 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1806 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1807 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1810 void GLES2Implementation::BufferSubDataHelperImpl(
1811 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1812 ScopedTransferBufferPtr
* buffer
) {
1816 const int8
* source
= static_cast<const int8
*>(data
);
1818 if (!buffer
->valid() || buffer
->size() == 0) {
1819 buffer
->Reset(size
);
1820 if (!buffer
->valid()) {
1824 memcpy(buffer
->address(), source
, buffer
->size());
1825 helper_
->BufferSubData(
1826 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1827 offset
+= buffer
->size();
1828 source
+= buffer
->size();
1829 size
-= buffer
->size();
1834 void GLES2Implementation::BufferSubData(
1835 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1836 GPU_CLIENT_SINGLE_THREAD_CHECK();
1837 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1838 << GLES2Util::GetStringBufferTarget(target
) << ", "
1839 << offset
<< ", " << size
<< ", "
1840 << static_cast<const void*>(data
) << ")");
1841 BufferSubDataHelper(target
, offset
, size
, data
);
1845 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1846 int32 token
= buffer
->last_usage_token();
1847 uint32 async_token
= buffer
->last_async_upload_token();
1850 if (HasAsyncUploadTokenPassed(async_token
)) {
1851 buffer_tracker_
->Free(buffer
);
1853 detached_async_upload_memory_
.push_back(
1854 std::make_pair(buffer
->address(), async_token
));
1855 buffer_tracker_
->Unmanage(buffer
);
1858 if (helper_
->HasTokenPassed(token
))
1859 buffer_tracker_
->Free(buffer
);
1861 buffer_tracker_
->FreePendingToken(buffer
, token
);
1863 buffer_tracker_
->Free(buffer
);
1866 buffer_tracker_
->RemoveBuffer(buffer
->id());
1869 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1871 const char* function_name
,
1872 GLuint
* buffer_id
) {
1876 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1877 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1879 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1880 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1887 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1892 BufferTracker::Buffer
*
1893 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1895 const char* function_name
,
1896 GLuint offset
, GLsizei size
) {
1898 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1900 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1903 if (buffer
->mapped()) {
1904 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1907 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1908 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1914 void GLES2Implementation::CompressedTexImage2D(
1915 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1916 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1917 GPU_CLIENT_SINGLE_THREAD_CHECK();
1918 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1919 << GLES2Util::GetStringTextureTarget(target
) << ", "
1921 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1922 << width
<< ", " << height
<< ", " << border
<< ", "
1923 << image_size
<< ", "
1924 << static_cast<const void*>(data
) << ")");
1925 if (width
< 0 || height
< 0 || level
< 0) {
1926 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1930 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
1933 if (height
== 0 || width
== 0) {
1936 // If there's a pixel unpack buffer bound use it when issuing
1937 // CompressedTexImage2D.
1938 if (bound_pixel_unpack_transfer_buffer_id_
) {
1939 GLuint offset
= ToGLuint(data
);
1940 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1941 bound_pixel_unpack_transfer_buffer_id_
,
1942 "glCompressedTexImage2D", offset
, image_size
);
1943 if (buffer
&& buffer
->shm_id() != -1) {
1944 helper_
->CompressedTexImage2D(
1945 target
, level
, internalformat
, width
, height
, image_size
,
1946 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1947 buffer
->set_last_usage_token(helper_
->InsertToken());
1951 SetBucketContents(kResultBucketId
, data
, image_size
);
1952 helper_
->CompressedTexImage2DBucket(
1953 target
, level
, internalformat
, width
, height
, kResultBucketId
);
1954 // Free the bucket. This is not required but it does free up the memory.
1955 // and we don't have to wait for the result so from the client's perspective
1957 helper_
->SetBucketSize(kResultBucketId
, 0);
1961 void GLES2Implementation::CompressedTexSubImage2D(
1962 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1963 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1964 GPU_CLIENT_SINGLE_THREAD_CHECK();
1965 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1966 << GLES2Util::GetStringTextureTarget(target
) << ", "
1968 << xoffset
<< ", " << yoffset
<< ", "
1969 << width
<< ", " << height
<< ", "
1970 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1971 << image_size
<< ", "
1972 << static_cast<const void*>(data
) << ")");
1973 if (width
< 0 || height
< 0 || level
< 0) {
1974 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1977 // If there's a pixel unpack buffer bound use it when issuing
1978 // CompressedTexSubImage2D.
1979 if (bound_pixel_unpack_transfer_buffer_id_
) {
1980 GLuint offset
= ToGLuint(data
);
1981 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1982 bound_pixel_unpack_transfer_buffer_id_
,
1983 "glCompressedTexSubImage2D", offset
, image_size
);
1984 if (buffer
&& buffer
->shm_id() != -1) {
1985 helper_
->CompressedTexSubImage2D(
1986 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1987 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1988 buffer
->set_last_usage_token(helper_
->InsertToken());
1993 SetBucketContents(kResultBucketId
, data
, image_size
);
1994 helper_
->CompressedTexSubImage2DBucket(
1995 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1996 // Free the bucket. This is not required but it does free up the memory.
1997 // and we don't have to wait for the result so from the client's perspective
1999 helper_
->SetBucketSize(kResultBucketId
, 0);
2003 void GLES2Implementation::CompressedTexImage3D(
2004 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
2005 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
2007 GPU_CLIENT_SINGLE_THREAD_CHECK();
2008 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
2009 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
2010 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
2011 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2012 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
2013 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2014 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
2018 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
2021 if (height
== 0 || width
== 0 || depth
== 0) {
2024 // If there's a pixel unpack buffer bound use it when issuing
2025 // CompressedTexImage3D.
2026 if (bound_pixel_unpack_transfer_buffer_id_
) {
2027 GLuint offset
= ToGLuint(data
);
2028 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2029 bound_pixel_unpack_transfer_buffer_id_
,
2030 "glCompressedTexImage3D", offset
, image_size
);
2031 if (buffer
&& buffer
->shm_id() != -1) {
2032 helper_
->CompressedTexImage3D(
2033 target
, level
, internalformat
, width
, height
, depth
, image_size
,
2034 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2035 buffer
->set_last_usage_token(helper_
->InsertToken());
2039 SetBucketContents(kResultBucketId
, data
, image_size
);
2040 helper_
->CompressedTexImage3DBucket(
2041 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
2042 // Free the bucket. This is not required but it does free up the memory.
2043 // and we don't have to wait for the result so from the client's perspective
2045 helper_
->SetBucketSize(kResultBucketId
, 0);
2049 void GLES2Implementation::CompressedTexSubImage3D(
2050 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2051 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
2052 GLsizei image_size
, const void* data
) {
2053 GPU_CLIENT_SINGLE_THREAD_CHECK();
2054 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage3D("
2055 << GLES2Util::GetStringTextureTarget(target
) << ", "
2057 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2058 << width
<< ", " << height
<< ", " << depth
<< ", "
2059 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
2060 << image_size
<< ", "
2061 << static_cast<const void*>(data
) << ")");
2062 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
2063 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "dimension < 0");
2066 // If there's a pixel unpack buffer bound use it when issuing
2067 // CompressedTexSubImage3D.
2068 if (bound_pixel_unpack_transfer_buffer_id_
) {
2069 GLuint offset
= ToGLuint(data
);
2070 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2071 bound_pixel_unpack_transfer_buffer_id_
,
2072 "glCompressedTexSubImage3D", offset
, image_size
);
2073 if (buffer
&& buffer
->shm_id() != -1) {
2074 helper_
->CompressedTexSubImage3D(
2075 target
, level
, xoffset
, yoffset
, zoffset
,
2076 width
, height
, depth
, format
, image_size
,
2077 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2078 buffer
->set_last_usage_token(helper_
->InsertToken());
2083 SetBucketContents(kResultBucketId
, data
, image_size
);
2084 helper_
->CompressedTexSubImage3DBucket(
2085 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
2087 // Free the bucket. This is not required but it does free up the memory.
2088 // and we don't have to wait for the result so from the client's perspective
2090 helper_
->SetBucketSize(kResultBucketId
, 0);
2096 void CopyRectToBuffer(
2099 uint32 unpadded_row_size
,
2100 uint32 pixels_padded_row_size
,
2103 uint32 buffer_padded_row_size
) {
2104 const int8
* source
= static_cast<const int8
*>(pixels
);
2105 int8
* dest
= static_cast<int8
*>(buffer
);
2106 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
2108 dest
+= buffer_padded_row_size
* (height
- 1);
2110 // the last row is copied unpadded at the end
2111 for (; height
> 1; --height
) {
2112 memcpy(dest
, source
, buffer_padded_row_size
);
2114 dest
-= buffer_padded_row_size
;
2116 dest
+= buffer_padded_row_size
;
2118 source
+= pixels_padded_row_size
;
2120 memcpy(dest
, source
, unpadded_row_size
);
2122 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2123 memcpy(dest
, source
, size
);
2127 } // anonymous namespace
2129 void GLES2Implementation::TexImage2D(
2130 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2131 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2132 const void* pixels
) {
2133 GPU_CLIENT_SINGLE_THREAD_CHECK();
2134 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2135 << GLES2Util::GetStringTextureTarget(target
) << ", "
2137 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2138 << width
<< ", " << height
<< ", " << border
<< ", "
2139 << GLES2Util::GetStringTextureFormat(format
) << ", "
2140 << GLES2Util::GetStringPixelType(type
) << ", "
2141 << static_cast<const void*>(pixels
) << ")");
2142 if (level
< 0 || height
< 0 || width
< 0) {
2143 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2147 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2151 uint32 unpadded_row_size
;
2152 uint32 padded_row_size
;
2153 if (!GLES2Util::ComputeImageDataSizes(
2154 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2155 &unpadded_row_size
, &padded_row_size
)) {
2156 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2160 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2161 if (bound_pixel_unpack_transfer_buffer_id_
) {
2162 GLuint offset
= ToGLuint(pixels
);
2163 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2164 bound_pixel_unpack_transfer_buffer_id_
,
2165 "glTexImage2D", offset
, size
);
2166 if (buffer
&& buffer
->shm_id() != -1) {
2167 helper_
->TexImage2D(
2168 target
, level
, internalformat
, width
, height
, format
, type
,
2169 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2170 buffer
->set_last_usage_token(helper_
->InsertToken());
2176 // If there's no data just issue TexImage2D
2178 helper_
->TexImage2D(
2179 target
, level
, internalformat
, width
, height
, format
, type
,
2185 // compute the advance bytes per row for the src pixels
2186 uint32 src_padded_row_size
;
2187 if (unpack_row_length_
> 0) {
2188 if (!GLES2Util::ComputeImagePaddedRowSize(
2189 unpack_row_length_
, format
, type
, unpack_alignment_
,
2190 &src_padded_row_size
)) {
2192 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2196 src_padded_row_size
= padded_row_size
;
2199 // advance pixels pointer past the skip rows and skip pixels
2200 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2201 unpack_skip_rows_
* src_padded_row_size
;
2202 if (unpack_skip_pixels_
) {
2203 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2204 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2205 unpack_skip_pixels_
* group_size
;
2208 // Check if we can send it all at once.
2210 uint32_t shm_offset
= 0;
2211 void* buffer_pointer
= nullptr;
2213 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2214 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2216 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2217 shm_id
= transfer_alloc
.shm_id();
2218 shm_offset
= transfer_alloc
.offset();
2219 buffer_pointer
= transfer_alloc
.address();
2221 mapped_alloc
.Reset(size
);
2222 if (mapped_alloc
.valid()) {
2223 transfer_alloc
.Discard();
2225 mapped_alloc
.SetFlushAfterRelease(true);
2226 shm_id
= mapped_alloc
.shm_id();
2227 shm_offset
= mapped_alloc
.offset();
2228 buffer_pointer
= mapped_alloc
.address();
2232 if (buffer_pointer
) {
2234 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
2235 buffer_pointer
, padded_row_size
);
2236 helper_
->TexImage2D(
2237 target
, level
, internalformat
, width
, height
, format
, type
,
2238 shm_id
, shm_offset
);
2243 // No, so send it using TexSubImage2D.
2244 helper_
->TexImage2D(
2245 target
, level
, internalformat
, width
, height
, format
, type
,
2248 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2249 pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
, padded_row_size
);
2253 void GLES2Implementation::TexImage3D(
2254 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2255 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2256 const void* pixels
) {
2257 GPU_CLIENT_SINGLE_THREAD_CHECK();
2258 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2259 << GLES2Util::GetStringTextureTarget(target
) << ", "
2261 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2262 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2263 << GLES2Util::GetStringTextureFormat(format
) << ", "
2264 << GLES2Util::GetStringPixelType(type
) << ", "
2265 << static_cast<const void*>(pixels
) << ")");
2266 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2267 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2271 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2275 uint32 unpadded_row_size
;
2276 uint32 padded_row_size
;
2277 if (!GLES2Util::ComputeImageDataSizes(
2278 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2279 &unpadded_row_size
, &padded_row_size
)) {
2280 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2284 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2285 if (bound_pixel_unpack_transfer_buffer_id_
) {
2286 GLuint offset
= ToGLuint(pixels
);
2287 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2288 bound_pixel_unpack_transfer_buffer_id_
,
2289 "glTexImage3D", offset
, size
);
2290 if (buffer
&& buffer
->shm_id() != -1) {
2291 helper_
->TexImage3D(
2292 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2293 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2294 buffer
->set_last_usage_token(helper_
->InsertToken());
2300 // If there's no data just issue TexImage3D
2302 helper_
->TexImage3D(
2303 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2309 // compute the advance bytes per row for the src pixels
2310 uint32 src_padded_row_size
;
2311 if (unpack_row_length_
> 0) {
2312 if (!GLES2Util::ComputeImagePaddedRowSize(
2313 unpack_row_length_
, format
, type
, unpack_alignment_
,
2314 &src_padded_row_size
)) {
2316 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2320 src_padded_row_size
= padded_row_size
;
2322 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2324 // advance pixels pointer past the skip images/rows/pixels
2325 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2326 unpack_skip_images_
* src_padded_row_size
* src_height
+
2327 unpack_skip_rows_
* src_padded_row_size
;
2328 if (unpack_skip_pixels_
) {
2329 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2330 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2331 unpack_skip_pixels_
* group_size
;
2334 // Check if we can send it all at once.
2336 uint32_t shm_offset
= 0;
2337 void* buffer_pointer
= nullptr;
2339 ScopedTransferBufferPtr
transfer_alloc(size
, helper_
, transfer_buffer_
);
2340 ScopedMappedMemoryPtr
mapped_alloc(0, helper_
, mapped_memory_
.get());
2342 if (transfer_alloc
.valid() && transfer_alloc
.size() >= size
) {
2343 shm_id
= transfer_alloc
.shm_id();
2344 shm_offset
= transfer_alloc
.offset();
2345 buffer_pointer
= transfer_alloc
.address();
2347 mapped_alloc
.Reset(size
);
2348 if (mapped_alloc
.valid()) {
2349 transfer_alloc
.Discard();
2351 mapped_alloc
.SetFlushAfterRelease(true);
2352 shm_id
= mapped_alloc
.shm_id();
2353 shm_offset
= mapped_alloc
.offset();
2354 buffer_pointer
= mapped_alloc
.address();
2358 if (buffer_pointer
) {
2359 for (GLsizei z
= 0; z
< depth
; ++z
) {
2360 // Only the last row of the last image is unpadded.
2361 uint32 src_unpadded_row_size
=
2362 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2363 // TODO(zmo): Ignore flip_y flag for now.
2365 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
, false,
2366 buffer_pointer
, padded_row_size
);
2367 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2368 src_padded_row_size
* src_height
;
2369 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2370 padded_row_size
* height
;
2372 helper_
->TexImage3D(
2373 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2374 shm_id
, shm_offset
);
2379 // No, so send it using TexSubImage3D.
2380 helper_
->TexImage3D(
2381 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2384 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2385 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &transfer_alloc
,
2390 void GLES2Implementation::TexSubImage2D(
2391 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2392 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2393 GPU_CLIENT_SINGLE_THREAD_CHECK();
2394 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2395 << GLES2Util::GetStringTextureTarget(target
) << ", "
2397 << xoffset
<< ", " << yoffset
<< ", "
2398 << width
<< ", " << height
<< ", "
2399 << GLES2Util::GetStringTextureFormat(format
) << ", "
2400 << GLES2Util::GetStringPixelType(type
) << ", "
2401 << static_cast<const void*>(pixels
) << ")");
2403 if (level
< 0 || height
< 0 || width
< 0) {
2404 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2407 if (height
== 0 || width
== 0) {
2412 uint32 unpadded_row_size
;
2413 uint32 padded_row_size
;
2414 if (!GLES2Util::ComputeImageDataSizes(
2415 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2416 &unpadded_row_size
, &padded_row_size
)) {
2417 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2421 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2422 if (bound_pixel_unpack_transfer_buffer_id_
) {
2423 GLuint offset
= ToGLuint(pixels
);
2424 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2425 bound_pixel_unpack_transfer_buffer_id_
,
2426 "glTexSubImage2D", offset
, temp_size
);
2427 if (buffer
&& buffer
->shm_id() != -1) {
2428 helper_
->TexSubImage2D(
2429 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2430 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2431 buffer
->set_last_usage_token(helper_
->InsertToken());
2437 // compute the advance bytes per row for the src pixels
2438 uint32 src_padded_row_size
;
2439 if (unpack_row_length_
> 0) {
2440 if (!GLES2Util::ComputeImagePaddedRowSize(
2441 unpack_row_length_
, format
, type
, unpack_alignment_
,
2442 &src_padded_row_size
)) {
2444 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2448 src_padded_row_size
= padded_row_size
;
2451 // advance pixels pointer past the skip rows and skip pixels
2452 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2453 unpack_skip_rows_
* src_padded_row_size
;
2454 if (unpack_skip_pixels_
) {
2455 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2456 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2457 unpack_skip_pixels_
* group_size
;
2460 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2462 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2463 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2468 void GLES2Implementation::TexSubImage3D(
2469 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2470 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2471 const void* pixels
) {
2472 GPU_CLIENT_SINGLE_THREAD_CHECK();
2473 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2474 << GLES2Util::GetStringTextureTarget(target
) << ", "
2476 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2477 << width
<< ", " << height
<< ", " << depth
<< ", "
2478 << GLES2Util::GetStringTextureFormat(format
) << ", "
2479 << GLES2Util::GetStringPixelType(type
) << ", "
2480 << static_cast<const void*>(pixels
) << ")");
2482 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2483 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2486 if (height
== 0 || width
== 0 || depth
== 0) {
2491 uint32 unpadded_row_size
;
2492 uint32 padded_row_size
;
2493 if (!GLES2Util::ComputeImageDataSizes(
2494 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2495 &unpadded_row_size
, &padded_row_size
)) {
2496 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2500 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2501 if (bound_pixel_unpack_transfer_buffer_id_
) {
2502 GLuint offset
= ToGLuint(pixels
);
2503 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2504 bound_pixel_unpack_transfer_buffer_id_
,
2505 "glTexSubImage3D", offset
, temp_size
);
2506 if (buffer
&& buffer
->shm_id() != -1) {
2507 helper_
->TexSubImage3D(
2508 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2509 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2510 buffer
->set_last_usage_token(helper_
->InsertToken());
2516 // compute the advance bytes per row for the src pixels
2517 uint32 src_padded_row_size
;
2518 if (unpack_row_length_
> 0) {
2519 if (!GLES2Util::ComputeImagePaddedRowSize(
2520 unpack_row_length_
, format
, type
, unpack_alignment_
,
2521 &src_padded_row_size
)) {
2523 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2527 src_padded_row_size
= padded_row_size
;
2529 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2531 // advance pixels pointer past the skip images/rows/pixels
2532 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2533 unpack_skip_images_
* src_padded_row_size
* src_height
+
2534 unpack_skip_rows_
* src_padded_row_size
;
2535 if (unpack_skip_pixels_
) {
2536 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2537 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2538 unpack_skip_pixels_
* group_size
;
2541 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2543 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2544 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2545 &buffer
, padded_row_size
);
2549 static GLint
ComputeNumRowsThatFitInBuffer(
2550 uint32 padded_row_size
, uint32 unpadded_row_size
,
2551 unsigned int size
, GLsizei remaining_rows
) {
2552 DCHECK_GE(unpadded_row_size
, 0u);
2553 if (padded_row_size
== 0) {
2556 GLint num_rows
= size
/ padded_row_size
;
2557 if (num_rows
+ 1 == remaining_rows
&&
2558 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2564 void GLES2Implementation::TexSubImage2DImpl(
2565 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2566 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2567 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2568 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2570 DCHECK_GE(level
, 0);
2571 DCHECK_GT(height
, 0);
2572 DCHECK_GT(width
, 0);
2574 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2575 GLint original_yoffset
= yoffset
;
2576 // Transfer by rows.
2578 unsigned int desired_size
=
2579 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2580 if (!buffer
->valid() || buffer
->size() == 0) {
2581 buffer
->Reset(desired_size
);
2582 if (!buffer
->valid()) {
2587 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2588 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2589 num_rows
= std::min(num_rows
, height
);
2591 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2592 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
2593 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
2594 helper_
->TexSubImage2D(
2595 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
2596 buffer
->shm_id(), buffer
->offset(), internal
);
2598 yoffset
+= num_rows
;
2599 source
+= num_rows
* pixels_padded_row_size
;
2604 void GLES2Implementation::TexSubImage3DImpl(
2605 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2606 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2607 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2608 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2609 uint32 buffer_padded_row_size
) {
2611 DCHECK_GE(level
, 0);
2612 DCHECK_GT(height
, 0);
2613 DCHECK_GT(width
, 0);
2614 DCHECK_GT(depth
, 0);
2615 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2616 GLsizei total_rows
= height
* depth
;
2617 GLint row_index
= 0, depth_index
= 0;
2618 while (total_rows
) {
2619 // Each time, we either copy one or more images, or copy one or more rows
2620 // within a single image, depending on the buffer size limit.
2622 unsigned int desired_size
;
2623 if (row_index
> 0) {
2624 // We are in the middle of an image. Send the remaining of the image.
2625 max_rows
= height
- row_index
;
2626 if (total_rows
<= height
) {
2627 // Last image, so last row is unpadded.
2628 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2631 desired_size
= buffer_padded_row_size
* max_rows
;
2634 // Send all the remaining data if possible.
2635 max_rows
= total_rows
;
2637 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2639 if (!buffer
->valid() || buffer
->size() == 0) {
2640 buffer
->Reset(desired_size
);
2641 if (!buffer
->valid()) {
2645 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2646 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2647 num_rows
= std::min(num_rows
, max_rows
);
2648 GLint num_images
= num_rows
/ height
;
2649 GLsizei my_height
, my_depth
;
2650 if (num_images
> 0) {
2651 num_rows
= num_images
* height
;
2653 my_depth
= num_images
;
2655 my_height
= num_rows
;
2659 // TODO(zmo): Ignore flip_y flag for now.
2660 if (num_images
> 0) {
2661 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2663 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2664 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2665 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2666 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2667 uint32 my_unpadded_row_size
;
2668 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2669 my_unpadded_row_size
= unpadded_row_size
;
2671 my_unpadded_row_size
= pixels_padded_row_size
;
2673 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2674 pixels_padded_row_size
, false, buffer_pointer
+ ii
* image_size_dst
,
2675 buffer_padded_row_size
);
2678 uint32 my_unpadded_row_size
;
2679 if (total_rows
== num_rows
)
2680 my_unpadded_row_size
= unpadded_row_size
;
2682 my_unpadded_row_size
= pixels_padded_row_size
;
2684 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2685 false, buffer
->address(), buffer_padded_row_size
);
2687 helper_
->TexSubImage3D(
2688 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2689 width
, my_height
, my_depth
,
2690 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2693 total_rows
-= num_rows
;
2694 if (total_rows
> 0) {
2695 GLint num_image_paddings
;
2696 if (num_images
> 0) {
2697 DCHECK_EQ(row_index
, 0);
2698 depth_index
+= num_images
;
2699 num_image_paddings
= num_images
;
2701 row_index
= (row_index
+ my_height
) % height
;
2702 num_image_paddings
= 0;
2703 if (my_height
> 0 && row_index
== 0) {
2705 num_image_paddings
++;
2708 source
+= num_rows
* pixels_padded_row_size
;
2709 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2710 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2711 pixels_padded_row_size
;
2717 bool GLES2Implementation::GetActiveAttribHelper(
2718 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2719 GLenum
* type
, char* name
) {
2720 // Clear the bucket so if the command fails nothing will be in it.
2721 helper_
->SetBucketSize(kResultBucketId
, 0);
2722 typedef cmds::GetActiveAttrib::Result Result
;
2723 Result
* result
= GetResultAs
<Result
*>();
2727 // Set as failed so if the command fails we'll recover.
2728 result
->success
= false;
2729 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2730 GetResultShmId(), GetResultShmOffset());
2732 if (result
->success
) {
2734 *size
= result
->size
;
2737 *type
= result
->type
;
2739 if (length
|| name
) {
2740 std::vector
<int8
> str
;
2741 GetBucketContents(kResultBucketId
, &str
);
2742 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2743 std::max(static_cast<size_t>(0),
2748 if (name
&& bufsize
> 0) {
2749 memcpy(name
, &str
[0], max_size
);
2750 name
[max_size
] = '\0';
2754 return result
->success
!= 0;
2757 void GLES2Implementation::GetActiveAttrib(
2758 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2759 GLenum
* type
, char* name
) {
2760 GPU_CLIENT_SINGLE_THREAD_CHECK();
2761 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2762 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2763 << static_cast<const void*>(length
) << ", "
2764 << static_cast<const void*>(size
) << ", "
2765 << static_cast<const void*>(type
) << ", "
2766 << static_cast<const void*>(name
) << ", ");
2768 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2771 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2772 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2773 this, program
, index
, bufsize
, length
, size
, type
, name
);
2776 GPU_CLIENT_LOG(" size: " << *size
);
2779 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2782 GPU_CLIENT_LOG(" name: " << name
);
2788 bool GLES2Implementation::GetActiveUniformHelper(
2789 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2790 GLenum
* type
, char* name
) {
2791 // Clear the bucket so if the command fails nothing will be in it.
2792 helper_
->SetBucketSize(kResultBucketId
, 0);
2793 typedef cmds::GetActiveUniform::Result Result
;
2794 Result
* result
= GetResultAs
<Result
*>();
2798 // Set as failed so if the command fails we'll recover.
2799 result
->success
= false;
2800 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2801 GetResultShmId(), GetResultShmOffset());
2803 if (result
->success
) {
2805 *size
= result
->size
;
2808 *type
= result
->type
;
2810 if (length
|| name
) {
2811 std::vector
<int8
> str
;
2812 GetBucketContents(kResultBucketId
, &str
);
2813 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2814 std::max(static_cast<size_t>(0),
2819 if (name
&& bufsize
> 0) {
2820 memcpy(name
, &str
[0], max_size
);
2821 name
[max_size
] = '\0';
2825 return result
->success
!= 0;
2828 void GLES2Implementation::GetActiveUniform(
2829 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2830 GLenum
* type
, char* name
) {
2831 GPU_CLIENT_SINGLE_THREAD_CHECK();
2832 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2833 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2834 << static_cast<const void*>(length
) << ", "
2835 << static_cast<const void*>(size
) << ", "
2836 << static_cast<const void*>(type
) << ", "
2837 << static_cast<const void*>(name
) << ", ");
2839 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2842 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2843 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2844 this, program
, index
, bufsize
, length
, size
, type
, name
);
2847 GPU_CLIENT_LOG(" size: " << *size
);
2850 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2853 GPU_CLIENT_LOG(" name: " << name
);
2859 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2860 GLuint program
, GLuint index
, GLsizei bufsize
,
2861 GLsizei
* length
, char* name
) {
2862 DCHECK_LE(0, bufsize
);
2863 // Clear the bucket so if the command fails nothing will be in it.
2864 helper_
->SetBucketSize(kResultBucketId
, 0);
2865 typedef cmds::GetActiveUniformBlockName::Result Result
;
2866 Result
* result
= GetResultAs
<Result
*>();
2870 // Set as failed so if the command fails we'll recover.
2872 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2873 GetResultShmId(), GetResultShmOffset());
2880 } else if (length
|| name
) {
2881 std::vector
<int8
> str
;
2882 GetBucketContents(kResultBucketId
, &str
);
2883 DCHECK_GT(str
.size(), 0u);
2885 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2890 memcpy(name
, &str
[0], max_size
);
2891 name
[max_size
] = '\0';
2895 return *result
!= 0;
2898 void GLES2Implementation::GetActiveUniformBlockName(
2899 GLuint program
, GLuint index
, GLsizei bufsize
,
2900 GLsizei
* length
, char* name
) {
2901 GPU_CLIENT_SINGLE_THREAD_CHECK();
2902 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2903 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2904 << static_cast<const void*>(length
) << ", "
2905 << static_cast<const void*>(name
) << ")");
2907 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2910 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2912 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2913 this, program
, index
, bufsize
, length
, name
);
2916 GPU_CLIENT_LOG(" name: " << name
);
2922 bool GLES2Implementation::GetActiveUniformBlockivHelper(
2923 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2924 typedef cmds::GetActiveUniformBlockiv::Result Result
;
2925 Result
* result
= GetResultAs
<Result
*>();
2929 result
->SetNumResults(0);
2930 helper_
->GetActiveUniformBlockiv(
2931 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
2933 if (result
->GetNumResults() > 0) {
2935 result
->CopyResult(params
);
2937 GPU_CLIENT_LOG_CODE_BLOCK({
2938 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2939 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2947 void GLES2Implementation::GetActiveUniformBlockiv(
2948 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2949 GPU_CLIENT_SINGLE_THREAD_CHECK();
2950 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
2951 << program
<< ", " << index
<< ", "
2952 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
2953 << static_cast<const void*>(params
) << ")");
2954 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
2956 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
2957 this, program
, index
, pname
, params
);
2960 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
2961 // be more than one value returned in params.
2962 GPU_CLIENT_LOG(" params: " << params
[0]);
2968 bool GLES2Implementation::GetActiveUniformsivHelper(
2969 GLuint program
, GLsizei count
, const GLuint
* indices
,
2970 GLenum pname
, GLint
* params
) {
2971 typedef cmds::GetActiveUniformsiv::Result Result
;
2972 Result
* result
= GetResultAs
<Result
*>();
2976 result
->SetNumResults(0);
2977 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
2978 bytes
*= sizeof(GLuint
);
2979 if (!bytes
.IsValid()) {
2980 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
2983 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
2984 helper_
->GetActiveUniformsiv(
2985 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
2987 bool success
= result
->GetNumResults() == count
;
2990 result
->CopyResult(params
);
2992 GPU_CLIENT_LOG_CODE_BLOCK({
2993 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2994 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2998 helper_
->SetBucketSize(kResultBucketId
, 0);
3002 void GLES2Implementation::GetActiveUniformsiv(
3003 GLuint program
, GLsizei count
, const GLuint
* indices
,
3004 GLenum pname
, GLint
* params
) {
3005 GPU_CLIENT_SINGLE_THREAD_CHECK();
3006 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
3007 << program
<< ", " << count
<< ", "
3008 << static_cast<const void*>(indices
) << ", "
3009 << GLES2Util::GetStringUniformParameter(pname
) << ", "
3010 << static_cast<const void*>(params
) << ")");
3011 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
3013 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
3016 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
3017 this, program
, count
, indices
, pname
, params
);
3020 GPU_CLIENT_LOG_CODE_BLOCK({
3021 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
3022 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
3030 void GLES2Implementation::GetAttachedShaders(
3031 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
3032 GPU_CLIENT_SINGLE_THREAD_CHECK();
3033 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
3034 << program
<< ", " << maxcount
<< ", "
3035 << static_cast<const void*>(count
) << ", "
3036 << static_cast<const void*>(shaders
) << ", ");
3038 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
3041 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
3042 typedef cmds::GetAttachedShaders::Result Result
;
3043 uint32 size
= Result::ComputeSize(maxcount
);
3044 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
3048 result
->SetNumResults(0);
3049 helper_
->GetAttachedShaders(
3051 transfer_buffer_
->GetShmId(),
3052 transfer_buffer_
->GetOffset(result
),
3054 int32 token
= helper_
->InsertToken();
3057 *count
= result
->GetNumResults();
3059 result
->CopyResult(shaders
);
3060 GPU_CLIENT_LOG_CODE_BLOCK({
3061 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3062 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3065 transfer_buffer_
->FreePendingToken(result
, token
);
3069 void GLES2Implementation::GetShaderPrecisionFormat(
3070 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
3071 GPU_CLIENT_SINGLE_THREAD_CHECK();
3072 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
3073 << GLES2Util::GetStringShaderType(shadertype
) << ", "
3074 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
3075 << static_cast<const void*>(range
) << ", "
3076 << static_cast<const void*>(precision
) << ", ");
3077 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
3078 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3079 Result
* result
= GetResultAs
<Result
*>();
3084 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
3085 GLStaticState::ShaderPrecisionMap::iterator i
=
3086 static_state_
.shader_precisions
.find(key
);
3087 if (i
!= static_state_
.shader_precisions
.end()) {
3088 *result
= i
->second
;
3090 result
->success
= false;
3091 helper_
->GetShaderPrecisionFormat(
3092 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
3094 if (result
->success
)
3095 static_state_
.shader_precisions
[key
] = *result
;
3098 if (result
->success
) {
3100 range
[0] = result
->min_range
;
3101 range
[1] = result
->max_range
;
3102 GPU_CLIENT_LOG(" min_range: " << range
[0]);
3103 GPU_CLIENT_LOG(" min_range: " << range
[1]);
3106 precision
[0] = result
->precision
;
3107 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
3113 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
3114 const char* result
= NULL
;
3115 // Clears the bucket so if the command fails nothing will be in it.
3116 helper_
->SetBucketSize(kResultBucketId
, 0);
3117 helper_
->GetString(name
, kResultBucketId
);
3119 if (GetBucketAsString(kResultBucketId
, &str
)) {
3120 // Adds extensions implemented on client side only.
3123 str
+= std::string(str
.empty() ? "" : " ") +
3124 "GL_CHROMIUM_flipy "
3125 "GL_EXT_unpack_subimage "
3126 "GL_CHROMIUM_map_sub";
3127 if (capabilities_
.image
)
3128 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
3129 if (capabilities_
.future_sync_points
)
3130 str
+= " GL_CHROMIUM_future_sync_point";
3136 // Because of WebGL the extensions can change. We have to cache each unique
3137 // result since we don't know when the client will stop referring to a
3138 // previous one it queries.
3139 GLStringMap::iterator it
= gl_strings_
.find(name
);
3140 if (it
== gl_strings_
.end()) {
3141 std::set
<std::string
> strings
;
3142 std::pair
<GLStringMap::iterator
, bool> insert_result
=
3143 gl_strings_
.insert(std::make_pair(name
, strings
));
3144 DCHECK(insert_result
.second
);
3145 it
= insert_result
.first
;
3147 std::set
<std::string
>& string_set
= it
->second
;
3148 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
3149 if (sit
!= string_set
.end()) {
3150 result
= sit
->c_str();
3152 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
3153 string_set
.insert(str
);
3154 DCHECK(insert_result
.second
);
3155 result
= insert_result
.first
->c_str();
3158 return reinterpret_cast<const GLubyte
*>(result
);
3161 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3162 GPU_CLIENT_SINGLE_THREAD_CHECK();
3163 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3164 << GLES2Util::GetStringStringType(name
) << ")");
3165 TRACE_EVENT0("gpu", "GLES2::GetString");
3166 const GLubyte
* result
= GetStringHelper(name
);
3167 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3172 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3173 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3174 GLenum
* type
, char* name
) {
3175 // Clear the bucket so if the command fails nothing will be in it.
3176 helper_
->SetBucketSize(kResultBucketId
, 0);
3177 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3178 Result
* result
= GetResultAs
<Result
*>();
3182 // Set as failed so if the command fails we'll recover.
3183 result
->success
= false;
3184 helper_
->GetTransformFeedbackVarying(
3185 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3187 if (result
->success
) {
3189 *size
= result
->size
;
3192 *type
= result
->type
;
3194 if (length
|| name
) {
3195 std::vector
<int8
> str
;
3196 GetBucketContents(kResultBucketId
, &str
);
3197 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3206 memcpy(name
, &str
[0], max_size
);
3207 name
[max_size
] = '\0';
3208 } else if (bufsize
> 0) {
3214 return result
->success
!= 0;
3217 void GLES2Implementation::GetTransformFeedbackVarying(
3218 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3219 GLenum
* type
, char* name
) {
3220 GPU_CLIENT_SINGLE_THREAD_CHECK();
3221 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3222 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3223 << static_cast<const void*>(length
) << ", "
3224 << static_cast<const void*>(size
) << ", "
3225 << static_cast<const void*>(type
) << ", "
3226 << static_cast<const void*>(name
) << ", ");
3228 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3232 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3234 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3235 this, program
, index
, bufsize
, length
, size
, type
, name
);
3238 GPU_CLIENT_LOG(" size: " << *size
);
3241 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3244 GPU_CLIENT_LOG(" name: " << name
);
3250 void GLES2Implementation::GetUniformfv(
3251 GLuint program
, GLint location
, GLfloat
* params
) {
3252 GPU_CLIENT_SINGLE_THREAD_CHECK();
3253 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3254 << program
<< ", " << location
<< ", "
3255 << static_cast<const void*>(params
) << ")");
3256 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3257 typedef cmds::GetUniformfv::Result Result
;
3258 Result
* result
= GetResultAs
<Result
*>();
3262 result
->SetNumResults(0);
3263 helper_
->GetUniformfv(
3264 program
, location
, GetResultShmId(), GetResultShmOffset());
3266 result
->CopyResult(params
);
3267 GPU_CLIENT_LOG_CODE_BLOCK({
3268 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3269 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3275 void GLES2Implementation::GetUniformiv(
3276 GLuint program
, GLint location
, GLint
* params
) {
3277 GPU_CLIENT_SINGLE_THREAD_CHECK();
3278 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3279 << program
<< ", " << location
<< ", "
3280 << static_cast<const void*>(params
) << ")");
3281 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3282 typedef cmds::GetUniformiv::Result Result
;
3283 Result
* result
= GetResultAs
<Result
*>();
3287 result
->SetNumResults(0);
3288 helper_
->GetUniformiv(
3289 program
, location
, GetResultShmId(), GetResultShmOffset());
3291 GetResultAs
<cmds::GetUniformiv::Result
*>()->CopyResult(params
);
3292 GPU_CLIENT_LOG_CODE_BLOCK({
3293 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3294 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3300 void GLES2Implementation::GetUniformuiv(
3301 GLuint program
, GLint location
, GLuint
* params
) {
3302 GPU_CLIENT_SINGLE_THREAD_CHECK();
3303 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformuiv("
3304 << program
<< ", " << location
<< ", "
3305 << static_cast<const void*>(params
) << ")");
3306 TRACE_EVENT0("gpu", "GLES2::GetUniformuiv");
3307 typedef cmds::GetUniformuiv::Result Result
;
3308 Result
* result
= GetResultAs
<Result
*>();
3312 result
->SetNumResults(0);
3313 helper_
->GetUniformuiv(
3314 program
, location
, GetResultShmId(), GetResultShmOffset());
3316 GetResultAs
<cmds::GetUniformuiv::Result
*>()->CopyResult(params
);
3317 GPU_CLIENT_LOG_CODE_BLOCK({
3318 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3319 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3325 void GLES2Implementation::ReadPixels(
3326 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3327 GLenum type
, void* pixels
) {
3328 GPU_CLIENT_SINGLE_THREAD_CHECK();
3329 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3330 << xoffset
<< ", " << yoffset
<< ", "
3331 << width
<< ", " << height
<< ", "
3332 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3333 << GLES2Util::GetStringPixelType(type
) << ", "
3334 << static_cast<const void*>(pixels
) << ")");
3335 if (width
< 0 || height
< 0) {
3336 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3339 if (width
== 0 || height
== 0) {
3343 // glReadPixel pads the size of each row of pixels by an amount specified by
3344 // glPixelStorei. So, we have to take that into account both in the fact that
3345 // the pixels returned from the ReadPixel command will include that padding
3346 // and that when we copy the results to the user's buffer we need to not
3347 // write those padding bytes but leave them as they are.
3349 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3350 typedef cmds::ReadPixels::Result Result
;
3352 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3354 uint32 unpadded_row_size
;
3355 uint32 padded_row_size
;
3356 if (!GLES2Util::ComputeImageDataSizes(
3357 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3358 &unpadded_row_size
, &padded_row_size
)) {
3359 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3363 if (bound_pixel_pack_transfer_buffer_id_
) {
3364 GLuint offset
= ToGLuint(pixels
);
3365 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3366 bound_pixel_pack_transfer_buffer_id_
,
3367 "glReadPixels", offset
, padded_row_size
* height
);
3368 if (buffer
&& buffer
->shm_id() != -1) {
3369 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3370 buffer
->shm_id(), buffer
->shm_offset(),
3378 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3382 // Transfer by rows.
3383 // The max rows we can transfer.
3385 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3386 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3387 if (!buffer
.valid()) {
3390 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3391 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3392 num_rows
= std::min(num_rows
, height
);
3393 // NOTE: We must look up the address of the result area AFTER allocation
3394 // of the transfer buffer since the transfer buffer may be reallocated.
3395 Result
* result
= GetResultAs
<Result
*>();
3399 *result
= 0; // mark as failed.
3400 helper_
->ReadPixels(
3401 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3402 buffer
.shm_id(), buffer
.offset(),
3403 GetResultShmId(), GetResultShmOffset(),
3407 // when doing a y-flip we have to iterate through top-to-bottom chunks
3408 // of the dst. The service side handles reversing the rows within a
3411 if (pack_reverse_row_order_
) {
3412 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3416 // We have to copy 1 row at a time to avoid writing pad bytes.
3417 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3418 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3419 memcpy(rows_dst
, src
, unpadded_row_size
);
3420 rows_dst
+= padded_row_size
;
3421 src
+= padded_row_size
;
3423 if (!pack_reverse_row_order_
) {
3427 // If it was not marked as successful exit.
3431 yoffset
+= num_rows
;
3437 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3438 GPU_CLIENT_SINGLE_THREAD_CHECK();
3439 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3440 << GLES2Util::GetStringEnum(texture
) << ")");
3441 GLuint texture_index
= texture
- GL_TEXTURE0
;
3442 if (texture_index
>=
3443 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3444 SetGLErrorInvalidEnum(
3445 "glActiveTexture", texture
, "texture");
3449 active_texture_unit_
= texture_index
;
3450 helper_
->ActiveTexture(texture
);
3454 void GLES2Implementation::GenBuffersHelper(
3455 GLsizei
/* n */, const GLuint
* /* buffers */) {
3458 void GLES2Implementation::GenFramebuffersHelper(
3459 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3462 void GLES2Implementation::GenRenderbuffersHelper(
3463 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3466 void GLES2Implementation::GenTexturesHelper(
3467 GLsizei
/* n */, const GLuint
* /* textures */) {
3470 void GLES2Implementation::GenVertexArraysOESHelper(
3471 GLsizei n
, const GLuint
* arrays
) {
3472 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3475 void GLES2Implementation::GenQueriesEXTHelper(
3476 GLsizei
/* n */, const GLuint
* /* queries */) {
3479 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3481 const GLuint
* /* valuebuffers */) {
3484 void GLES2Implementation::GenSamplersHelper(
3485 GLsizei
/* n */, const GLuint
* /* samplers */) {
3488 void GLES2Implementation::GenTransformFeedbacksHelper(
3489 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3492 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3493 // generates a new resource. On newer versions of OpenGL they don't. The code
3494 // related to binding below will need to change if we switch to the new OpenGL
3495 // model. Specifically it assumes a bind will succeed which is always true in
3496 // the old model but possibly not true in the new model if another context has
3497 // deleted the resource.
3499 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3500 // used even when Bind has failed. However, the bug is minor compared to the
3501 // overhead & duplicated checking in client side.
3503 void GLES2Implementation::BindBufferHelper(
3504 GLenum target
, GLuint buffer_id
) {
3505 // TODO(gman): See note #1 above.
3506 bool changed
= false;
3508 case GL_ARRAY_BUFFER
:
3509 if (bound_array_buffer_
!= buffer_id
) {
3510 bound_array_buffer_
= buffer_id
;
3514 case GL_COPY_READ_BUFFER
:
3515 if (bound_copy_read_buffer_
!= buffer_id
) {
3516 bound_copy_read_buffer_
= buffer_id
;
3520 case GL_COPY_WRITE_BUFFER
:
3521 if (bound_copy_write_buffer_
!= buffer_id
) {
3522 bound_copy_write_buffer_
= buffer_id
;
3526 case GL_ELEMENT_ARRAY_BUFFER
:
3527 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3529 case GL_PIXEL_PACK_BUFFER
:
3530 if (bound_pixel_pack_buffer_
!= buffer_id
) {
3531 bound_pixel_pack_buffer_
= buffer_id
;
3535 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3536 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3538 case GL_PIXEL_UNPACK_BUFFER
:
3539 if (bound_pixel_unpack_buffer_
!= buffer_id
) {
3540 bound_pixel_unpack_buffer_
= buffer_id
;
3544 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3545 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3547 case GL_TRANSFORM_FEEDBACK_BUFFER
:
3548 if (bound_transform_feedback_buffer_
!= buffer_id
) {
3549 bound_transform_feedback_buffer_
= buffer_id
;
3553 case GL_UNIFORM_BUFFER
:
3554 if (bound_uniform_buffer_
!= buffer_id
) {
3555 bound_uniform_buffer_
= buffer_id
;
3563 // TODO(gman): See note #2 above.
3565 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3566 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3570 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3571 helper_
->BindBuffer(target
, buffer
);
3572 if (share_group_
->bind_generates_resource())
3573 helper_
->CommandBufferHelper::OrderingBarrier();
3576 void GLES2Implementation::BindBufferBaseHelper(
3577 GLenum target
, GLuint index
, GLuint buffer_id
) {
3578 // TODO(zmo): See note #1 above.
3579 // TODO(zmo): See note #2 above.
3580 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3581 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3584 void GLES2Implementation::BindBufferBaseStub(
3585 GLenum target
, GLuint index
, GLuint buffer
) {
3586 helper_
->BindBufferBase(target
, index
, buffer
);
3587 if (share_group_
->bind_generates_resource())
3588 helper_
->CommandBufferHelper::Flush();
3591 void GLES2Implementation::BindBufferRangeHelper(
3592 GLenum target
, GLuint index
, GLuint buffer_id
,
3593 GLintptr offset
, GLsizeiptr size
) {
3594 // TODO(zmo): See note #1 above.
3595 // TODO(zmo): See note #2 above.
3596 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3597 this, target
, index
, buffer_id
, offset
, size
,
3598 &GLES2Implementation::BindBufferRangeStub
);
3601 void GLES2Implementation::BindBufferRangeStub(
3602 GLenum target
, GLuint index
, GLuint buffer
,
3603 GLintptr offset
, GLsizeiptr size
) {
3604 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3605 if (share_group_
->bind_generates_resource())
3606 helper_
->CommandBufferHelper::Flush();
3609 void GLES2Implementation::BindFramebufferHelper(
3610 GLenum target
, GLuint framebuffer
) {
3611 // TODO(gman): See note #1 above.
3612 bool changed
= false;
3614 case GL_FRAMEBUFFER
:
3615 if (bound_framebuffer_
!= framebuffer
||
3616 bound_read_framebuffer_
!= framebuffer
) {
3617 bound_framebuffer_
= framebuffer
;
3618 bound_read_framebuffer_
= framebuffer
;
3622 case GL_READ_FRAMEBUFFER
:
3623 if (!IsChromiumFramebufferMultisampleAvailable()) {
3624 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3627 if (bound_read_framebuffer_
!= framebuffer
) {
3628 bound_read_framebuffer_
= framebuffer
;
3632 case GL_DRAW_FRAMEBUFFER
:
3633 if (!IsChromiumFramebufferMultisampleAvailable()) {
3634 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3637 if (bound_framebuffer_
!= framebuffer
) {
3638 bound_framebuffer_
= framebuffer
;
3643 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3648 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3649 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3653 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3654 GLuint framebuffer
) {
3655 helper_
->BindFramebuffer(target
, framebuffer
);
3656 if (share_group_
->bind_generates_resource())
3657 helper_
->CommandBufferHelper::OrderingBarrier();
3660 void GLES2Implementation::BindRenderbufferHelper(
3661 GLenum target
, GLuint renderbuffer
) {
3662 // TODO(gman): See note #1 above.
3663 bool changed
= false;
3665 case GL_RENDERBUFFER
:
3666 if (bound_renderbuffer_
!= renderbuffer
) {
3667 bound_renderbuffer_
= renderbuffer
;
3675 // TODO(zmo): See note #2 above.
3677 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3678 this, target
, renderbuffer
,
3679 &GLES2Implementation::BindRenderbufferStub
);
3683 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3684 GLuint renderbuffer
) {
3685 helper_
->BindRenderbuffer(target
, renderbuffer
);
3686 if (share_group_
->bind_generates_resource())
3687 helper_
->CommandBufferHelper::OrderingBarrier();
3690 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3692 helper_
->BindSampler(unit
, sampler
);
3695 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3696 // TODO(gman): See note #1 above.
3697 // TODO(gman): Change this to false once we figure out why it's failing
3699 bool changed
= true;
3700 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3703 if (unit
.bound_texture_2d
!= texture
) {
3704 unit
.bound_texture_2d
= texture
;
3708 case GL_TEXTURE_CUBE_MAP
:
3709 if (unit
.bound_texture_cube_map
!= texture
) {
3710 unit
.bound_texture_cube_map
= texture
;
3714 case GL_TEXTURE_EXTERNAL_OES
:
3715 if (unit
.bound_texture_external_oes
!= texture
) {
3716 unit
.bound_texture_external_oes
= texture
;
3724 // TODO(gman): See note #2 above.
3726 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3727 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3731 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3732 helper_
->BindTexture(target
, texture
);
3733 if (share_group_
->bind_generates_resource())
3734 helper_
->CommandBufferHelper::OrderingBarrier();
3737 void GLES2Implementation::BindTransformFeedbackHelper(
3738 GLenum target
, GLuint transformfeedback
) {
3739 helper_
->BindTransformFeedback(target
, transformfeedback
);
3742 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3743 bool changed
= false;
3744 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3746 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3747 // because unlike other resources VertexArrayObject ids must
3748 // be generated by GenVertexArrays. A random id to Bind will not
3749 // generate a new object.
3750 helper_
->BindVertexArrayOES(array
);
3754 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3755 "id was not generated with glGenVertexArrayOES");
3759 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3760 GLuint valuebuffer
) {
3761 bool changed
= false;
3763 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3764 if (bound_valuebuffer_
!= valuebuffer
) {
3765 bound_valuebuffer_
= valuebuffer
;
3773 // TODO(gman): See note #2 above.
3775 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3776 this, target
, valuebuffer
,
3777 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3781 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3782 GLuint valuebuffer
) {
3783 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3784 if (share_group_
->bind_generates_resource())
3785 helper_
->CommandBufferHelper::OrderingBarrier();
3788 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3789 if (current_program_
!= program
) {
3790 current_program_
= program
;
3791 helper_
->UseProgram(program
);
3795 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3796 return vertex_array_object_manager_
->IsReservedId(id
);
3799 void GLES2Implementation::DeleteBuffersHelper(
3800 GLsizei n
, const GLuint
* buffers
) {
3801 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3802 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3805 "glDeleteBuffers", "id not created by this context.");
3808 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3809 if (buffers
[ii
] == bound_array_buffer_
) {
3810 bound_array_buffer_
= 0;
3812 if (buffers
[ii
] == bound_copy_read_buffer_
) {
3813 bound_copy_read_buffer_
= 0;
3815 if (buffers
[ii
] == bound_copy_write_buffer_
) {
3816 bound_copy_write_buffer_
= 0;
3818 if (buffers
[ii
] == bound_pixel_pack_buffer_
) {
3819 bound_pixel_pack_buffer_
= 0;
3821 if (buffers
[ii
] == bound_pixel_unpack_buffer_
) {
3822 bound_pixel_unpack_buffer_
= 0;
3824 if (buffers
[ii
] == bound_transform_feedback_buffer_
) {
3825 bound_transform_feedback_buffer_
= 0;
3827 if (buffers
[ii
] == bound_uniform_buffer_
) {
3828 bound_uniform_buffer_
= 0;
3830 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3832 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3834 RemoveTransferBuffer(buffer
);
3836 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3837 bound_pixel_unpack_transfer_buffer_id_
= 0;
3840 RemoveMappedBufferRangeById(buffers
[ii
]);
3844 void GLES2Implementation::DeleteBuffersStub(
3845 GLsizei n
, const GLuint
* buffers
) {
3846 helper_
->DeleteBuffersImmediate(n
, buffers
);
3850 void GLES2Implementation::DeleteFramebuffersHelper(
3851 GLsizei n
, const GLuint
* framebuffers
) {
3852 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3853 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3856 "glDeleteFramebuffers", "id not created by this context.");
3859 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3860 if (framebuffers
[ii
] == bound_framebuffer_
) {
3861 bound_framebuffer_
= 0;
3863 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3864 bound_read_framebuffer_
= 0;
3869 void GLES2Implementation::DeleteFramebuffersStub(
3870 GLsizei n
, const GLuint
* framebuffers
) {
3871 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3874 void GLES2Implementation::DeleteRenderbuffersHelper(
3875 GLsizei n
, const GLuint
* renderbuffers
) {
3876 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3877 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3880 "glDeleteRenderbuffers", "id not created by this context.");
3883 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3884 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3885 bound_renderbuffer_
= 0;
3890 void GLES2Implementation::DeleteRenderbuffersStub(
3891 GLsizei n
, const GLuint
* renderbuffers
) {
3892 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3895 void GLES2Implementation::DeleteTexturesHelper(
3896 GLsizei n
, const GLuint
* textures
) {
3897 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3898 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3901 "glDeleteTextures", "id not created by this context.");
3904 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3905 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3907 TextureUnit
& unit
= texture_units_
[tt
];
3908 if (textures
[ii
] == unit
.bound_texture_2d
) {
3909 unit
.bound_texture_2d
= 0;
3911 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3912 unit
.bound_texture_cube_map
= 0;
3914 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3915 unit
.bound_texture_external_oes
= 0;
3921 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
3922 const GLuint
* textures
) {
3923 helper_
->DeleteTexturesImmediate(n
, textures
);
3926 void GLES2Implementation::DeleteVertexArraysOESHelper(
3927 GLsizei n
, const GLuint
* arrays
) {
3928 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
3929 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
3930 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
3933 "glDeleteVertexArraysOES", "id not created by this context.");
3938 void GLES2Implementation::DeleteVertexArraysOESStub(
3939 GLsizei n
, const GLuint
* arrays
) {
3940 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
3943 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
3945 const GLuint
* valuebuffers
) {
3946 if (!GetIdHandler(id_namespaces::kValuebuffers
)
3947 ->FreeIds(this, n
, valuebuffers
,
3948 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
3949 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
3950 "id not created by this context.");
3953 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3954 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
3955 bound_valuebuffer_
= 0;
3960 void GLES2Implementation::DeleteSamplersStub(
3961 GLsizei n
, const GLuint
* samplers
) {
3962 helper_
->DeleteSamplersImmediate(n
, samplers
);
3965 void GLES2Implementation::DeleteSamplersHelper(
3966 GLsizei n
, const GLuint
* samplers
) {
3967 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
3968 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
3971 "glDeleteSamplers", "id not created by this context.");
3976 void GLES2Implementation::DeleteTransformFeedbacksStub(
3977 GLsizei n
, const GLuint
* transformfeedbacks
) {
3978 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
3981 void GLES2Implementation::DeleteTransformFeedbacksHelper(
3982 GLsizei n
, const GLuint
* transformfeedbacks
) {
3983 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
3984 this, n
, transformfeedbacks
,
3985 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
3988 "glDeleteTransformFeedbacks", "id not created by this context.");
3993 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
3995 const GLuint
* valuebuffers
) {
3996 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
3999 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
4000 GPU_CLIENT_SINGLE_THREAD_CHECK();
4002 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
4003 vertex_array_object_manager_
->SetAttribEnable(index
, false);
4004 helper_
->DisableVertexAttribArray(index
);
4008 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
4009 GPU_CLIENT_SINGLE_THREAD_CHECK();
4010 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
4012 vertex_array_object_manager_
->SetAttribEnable(index
, true);
4013 helper_
->EnableVertexAttribArray(index
);
4017 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
4018 GPU_CLIENT_SINGLE_THREAD_CHECK();
4019 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
4020 << GLES2Util::GetStringDrawMode(mode
) << ", "
4021 << first
<< ", " << count
<< ")");
4023 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
4026 bool simulated
= false;
4027 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4028 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
4031 helper_
->DrawArrays(mode
, first
, count
);
4032 RestoreArrayBuffer(simulated
);
4036 void GLES2Implementation::GetVertexAttribfv(
4037 GLuint index
, GLenum pname
, GLfloat
* params
) {
4038 GPU_CLIENT_SINGLE_THREAD_CHECK();
4039 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
4041 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4042 << static_cast<const void*>(params
) << ")");
4044 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4045 *params
= static_cast<GLfloat
>(value
);
4048 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
4049 typedef cmds::GetVertexAttribfv::Result Result
;
4050 Result
* result
= GetResultAs
<Result
*>();
4054 result
->SetNumResults(0);
4055 helper_
->GetVertexAttribfv(
4056 index
, pname
, GetResultShmId(), GetResultShmOffset());
4058 result
->CopyResult(params
);
4059 GPU_CLIENT_LOG_CODE_BLOCK({
4060 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4061 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4067 void GLES2Implementation::GetVertexAttribiv(
4068 GLuint index
, GLenum pname
, GLint
* params
) {
4069 GPU_CLIENT_SINGLE_THREAD_CHECK();
4070 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
4072 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4073 << static_cast<const void*>(params
) << ")");
4075 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4076 *params
= static_cast<GLint
>(value
);
4079 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
4080 typedef cmds::GetVertexAttribiv::Result Result
;
4081 Result
* result
= GetResultAs
<Result
*>();
4085 result
->SetNumResults(0);
4086 helper_
->GetVertexAttribiv(
4087 index
, pname
, GetResultShmId(), GetResultShmOffset());
4089 result
->CopyResult(params
);
4090 GPU_CLIENT_LOG_CODE_BLOCK({
4091 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4092 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4098 void GLES2Implementation::GetVertexAttribIiv(
4099 GLuint index
, GLenum pname
, GLint
* params
) {
4100 GPU_CLIENT_SINGLE_THREAD_CHECK();
4101 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIiv("
4103 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4104 << static_cast<const void*>(params
) << ")");
4106 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4107 *params
= static_cast<GLint
>(value
);
4110 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv");
4111 typedef cmds::GetVertexAttribiv::Result Result
;
4112 Result
* result
= GetResultAs
<Result
*>();
4116 result
->SetNumResults(0);
4117 helper_
->GetVertexAttribIiv(
4118 index
, pname
, GetResultShmId(), GetResultShmOffset());
4120 result
->CopyResult(params
);
4121 GPU_CLIENT_LOG_CODE_BLOCK({
4122 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4123 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4129 void GLES2Implementation::GetVertexAttribIuiv(
4130 GLuint index
, GLenum pname
, GLuint
* params
) {
4131 GPU_CLIENT_SINGLE_THREAD_CHECK();
4132 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribIuiv("
4134 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
4135 << static_cast<const void*>(params
) << ")");
4137 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
4138 *params
= static_cast<GLuint
>(value
);
4141 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv");
4142 typedef cmds::GetVertexAttribiv::Result Result
;
4143 Result
* result
= GetResultAs
<Result
*>();
4147 result
->SetNumResults(0);
4148 helper_
->GetVertexAttribIuiv(
4149 index
, pname
, GetResultShmId(), GetResultShmOffset());
4151 result
->CopyResult(params
);
4152 GPU_CLIENT_LOG_CODE_BLOCK({
4153 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
4154 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
4160 GLenum
GLES2Implementation::GetGraphicsResetStatusKHR() {
4161 GPU_CLIENT_SINGLE_THREAD_CHECK();
4162 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetGraphicsResetStatusKHR()");
4163 // If we can't make command buffers then the context is lost.
4164 if (gpu_control_
->IsGpuChannelLost())
4165 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4166 // Otherwise, check the command buffer if it is lost.
4167 if (helper_
->IsContextLost()) {
4168 // TODO(danakj): We could GetLastState() off the CommandBuffer and return
4169 // the actual reason here if we cared to.
4170 return GL_UNKNOWN_CONTEXT_RESET_KHR
;
4175 void GLES2Implementation::Swap() {
4179 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
4180 PostSubBufferCHROMIUM(
4181 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
4184 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
4185 switch (plane_transform
) {
4186 case gfx::OVERLAY_TRANSFORM_INVALID
:
4188 case gfx::OVERLAY_TRANSFORM_NONE
:
4189 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4190 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
4191 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
4192 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
4193 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
4194 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
4195 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
4196 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
4197 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
4198 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
4199 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
4202 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
4205 void GLES2Implementation::ScheduleOverlayPlane(
4207 gfx::OverlayTransform plane_transform
,
4208 unsigned overlay_texture_id
,
4209 const gfx::Rect
& display_bounds
,
4210 const gfx::RectF
& uv_rect
) {
4211 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
4212 GetGLESOverlayTransform(plane_transform
),
4216 display_bounds
.width(),
4217 display_bounds
.height(),
4224 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
4225 const char* feature
) {
4226 GPU_CLIENT_SINGLE_THREAD_CHECK();
4227 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
4229 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
4230 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
4231 Result
* result
= GetResultAs
<Result
*>();
4236 SetBucketAsCString(kResultBucketId
, feature
);
4237 helper_
->EnableFeatureCHROMIUM(
4238 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
4240 helper_
->SetBucketSize(kResultBucketId
, 0);
4241 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
4242 return *result
!= 0;
4245 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
4246 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
4247 GPU_CLIENT_SINGLE_THREAD_CHECK();
4248 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
4249 << target
<< ", " << offset
<< ", " << size
<< ", "
4250 << GLES2Util::GetStringEnum(access
) << ")");
4251 // NOTE: target is NOT checked because the service will check it
4252 // and we don't know what targets are valid.
4253 if (access
!= GL_WRITE_ONLY
) {
4254 SetGLErrorInvalidEnum(
4255 "glMapBufferSubDataCHROMIUM", access
, "access");
4258 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
4259 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
4264 unsigned int shm_offset
;
4265 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4267 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
4271 std::pair
<MappedBufferMap::iterator
, bool> result
=
4272 mapped_buffers_
.insert(std::make_pair(
4275 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4276 DCHECK(result
.second
);
4277 GPU_CLIENT_LOG(" returned " << mem
);
4281 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
4282 GPU_CLIENT_SINGLE_THREAD_CHECK();
4284 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
4285 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
4286 if (it
== mapped_buffers_
.end()) {
4288 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
4291 const MappedBuffer
& mb
= it
->second
;
4292 helper_
->BufferSubData(
4293 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
4294 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
4295 mapped_buffers_
.erase(it
);
4299 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
4300 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
4302 bool cached
= GetHelper(binding
, &id
);
4304 return static_cast<GLuint
>(id
);
4307 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
4308 GLuint buffer
= GetBoundBufferHelper(target
);
4309 RemoveMappedBufferRangeById(buffer
);
4312 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4314 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4315 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4316 mapped_memory_
->FreePendingToken(
4317 iter
->second
.shm_memory
, helper_
->InsertToken());
4318 mapped_buffer_range_map_
.erase(iter
);
4323 void GLES2Implementation::ClearMappedBufferRangeMap() {
4324 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4325 if (buffer_range
.second
.shm_memory
) {
4326 mapped_memory_
->FreePendingToken(
4327 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4330 mapped_buffer_range_map_
.clear();
4333 void* GLES2Implementation::MapBufferRange(
4334 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4335 GPU_CLIENT_SINGLE_THREAD_CHECK();
4336 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4337 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4338 << size
<< ", " << access
<< ")");
4339 if (!ValidateSize("glMapBufferRange", size
) ||
4340 !ValidateOffset("glMapBufferRange", offset
)) {
4345 unsigned int shm_offset
;
4346 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4348 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4352 typedef cmds::MapBufferRange::Result Result
;
4353 Result
* result
= GetResultAs
<Result
*>();
4355 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4356 GetResultShmId(), GetResultShmOffset());
4357 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4358 // consider an early return without WaitForCmd(). crbug.com/465804.
4361 const GLbitfield kInvalidateBits
=
4362 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4363 if ((access
& kInvalidateBits
) != 0) {
4364 // We do not read back from the buffer, therefore, we set the client
4365 // side memory to zero to avoid uninitialized data.
4366 memset(mem
, 0, size
);
4368 GLuint buffer
= GetBoundBufferHelper(target
);
4369 DCHECK_NE(0u, buffer
);
4370 // glMapBufferRange fails on an already mapped buffer.
4371 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4372 mapped_buffer_range_map_
.end());
4373 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4375 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4376 DCHECK(iter
.second
);
4378 mapped_memory_
->Free(mem
);
4382 GPU_CLIENT_LOG(" returned " << mem
);
4387 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4388 GPU_CLIENT_SINGLE_THREAD_CHECK();
4389 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4390 << GLES2Util::GetStringEnum(target
) << ")");
4392 case GL_ARRAY_BUFFER
:
4393 case GL_ELEMENT_ARRAY_BUFFER
:
4394 case GL_COPY_READ_BUFFER
:
4395 case GL_COPY_WRITE_BUFFER
:
4396 case GL_PIXEL_PACK_BUFFER
:
4397 case GL_PIXEL_UNPACK_BUFFER
:
4398 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4399 case GL_UNIFORM_BUFFER
:
4402 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4405 GLuint buffer
= GetBoundBufferHelper(target
);
4407 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4410 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4411 if (iter
== mapped_buffer_range_map_
.end()) {
4412 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4416 helper_
->UnmapBuffer(target
);
4417 RemoveMappedBufferRangeById(buffer
);
4418 // TODO(zmo): There is a rare situation that data might be corrupted and
4419 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4420 // don't have to WaitForCmd().
4421 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4426 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4436 GPU_CLIENT_SINGLE_THREAD_CHECK();
4437 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4438 << target
<< ", " << level
<< ", "
4439 << xoffset
<< ", " << yoffset
<< ", "
4440 << width
<< ", " << height
<< ", "
4441 << GLES2Util::GetStringTextureFormat(format
) << ", "
4442 << GLES2Util::GetStringPixelType(type
) << ", "
4443 << GLES2Util::GetStringEnum(access
) << ")");
4444 if (access
!= GL_WRITE_ONLY
) {
4445 SetGLErrorInvalidEnum(
4446 "glMapTexSubImage2DCHROMIUM", access
, "access");
4449 // NOTE: target is NOT checked because the service will check it
4450 // and we don't know what targets are valid.
4451 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4453 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4457 if (!GLES2Util::ComputeImageDataSizes(
4458 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4460 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4464 unsigned int shm_offset
;
4465 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4467 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4471 std::pair
<MappedTextureMap::iterator
, bool> result
=
4472 mapped_textures_
.insert(std::make_pair(
4475 access
, shm_id
, mem
, shm_offset
,
4476 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4477 DCHECK(result
.second
);
4478 GPU_CLIENT_LOG(" returned " << mem
);
4482 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4483 GPU_CLIENT_SINGLE_THREAD_CHECK();
4485 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4486 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4487 if (it
== mapped_textures_
.end()) {
4489 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4492 const MappedTexture
& mt
= it
->second
;
4493 helper_
->TexSubImage2D(
4494 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4495 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4496 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4497 mapped_textures_
.erase(it
);
4501 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4502 float scale_factor
) {
4503 GPU_CLIENT_SINGLE_THREAD_CHECK();
4504 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4505 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4506 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4510 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4511 GPU_CLIENT_SINGLE_THREAD_CHECK();
4512 GPU_CLIENT_LOG("[" << GetLogPrefix()
4513 << "] glGetRequestableExtensionsCHROMIUM()");
4515 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4516 const char* result
= NULL
;
4517 // Clear the bucket so if the command fails nothing will be in it.
4518 helper_
->SetBucketSize(kResultBucketId
, 0);
4519 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4521 if (GetBucketAsString(kResultBucketId
, &str
)) {
4522 // The set of requestable extensions shrinks as we enable
4523 // them. Because we don't know when the client will stop referring
4524 // to a previous one it queries (see GetString) we need to cache
4525 // the unique results.
4526 std::set
<std::string
>::const_iterator sit
=
4527 requestable_extensions_set_
.find(str
);
4528 if (sit
!= requestable_extensions_set_
.end()) {
4529 result
= sit
->c_str();
4531 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4532 requestable_extensions_set_
.insert(str
);
4533 DCHECK(insert_result
.second
);
4534 result
= insert_result
.first
->c_str();
4537 GPU_CLIENT_LOG(" returned " << result
);
4538 return reinterpret_cast<const GLchar
*>(result
);
4541 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4542 // with VirtualGL contexts.
4543 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4544 GPU_CLIENT_SINGLE_THREAD_CHECK();
4545 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4546 << extension
<< ")");
4547 SetBucketAsCString(kResultBucketId
, extension
);
4548 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4549 helper_
->SetBucketSize(kResultBucketId
, 0);
4551 struct ExtensionCheck
{
4552 const char* extension
;
4553 ExtensionStatus
* status
;
4555 const ExtensionCheck checks
[] = {
4557 "GL_ANGLE_pack_reverse_row_order",
4558 &angle_pack_reverse_row_order_status_
,
4561 "GL_CHROMIUM_framebuffer_multisample",
4562 &chromium_framebuffer_multisample_
,
4565 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4566 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4567 const ExtensionCheck
& check
= checks
[ii
];
4568 if (*check
.status
== kUnavailableExtensionStatus
&&
4569 !strcmp(extension
, check
.extension
)) {
4570 *check
.status
= kUnknownExtensionStatus
;
4575 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4576 GPU_CLIENT_SINGLE_THREAD_CHECK();
4577 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4578 // Wait if this would add too many rate limit tokens.
4579 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4580 helper_
->WaitForToken(rate_limit_tokens_
.front());
4581 rate_limit_tokens_
.pop();
4583 rate_limit_tokens_
.push(helper_
->InsertToken());
4586 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4587 GLuint program
, std::vector
<int8
>* result
) {
4589 // Clear the bucket so if the command fails nothing will be in it.
4590 helper_
->SetBucketSize(kResultBucketId
, 0);
4591 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4592 GetBucketContents(kResultBucketId
, result
);
4595 void GLES2Implementation::GetProgramInfoCHROMIUM(
4596 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4597 GPU_CLIENT_SINGLE_THREAD_CHECK();
4600 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4604 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4607 // Make sure they've set size to 0 else the value will be undefined on
4609 DCHECK_EQ(0, *size
);
4610 std::vector
<int8
> result
;
4611 GetProgramInfoCHROMIUMHelper(program
, &result
);
4612 if (result
.empty()) {
4615 *size
= result
.size();
4619 if (static_cast<size_t>(bufsize
) < result
.size()) {
4620 SetGLError(GL_INVALID_OPERATION
,
4621 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4624 memcpy(info
, &result
[0], result
.size());
4627 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4628 GLuint program
, std::vector
<int8
>* result
) {
4630 // Clear the bucket so if the command fails nothing will be in it.
4631 helper_
->SetBucketSize(kResultBucketId
, 0);
4632 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4633 GetBucketContents(kResultBucketId
, result
);
4636 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4637 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4638 GPU_CLIENT_SINGLE_THREAD_CHECK();
4641 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4645 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4648 // Make sure they've set size to 0 else the value will be undefined on
4650 DCHECK_EQ(0, *size
);
4651 std::vector
<int8
> result
;
4652 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4653 if (result
.empty()) {
4656 *size
= result
.size();
4660 if (static_cast<size_t>(bufsize
) < result
.size()) {
4661 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4662 "bufsize is too small for result.");
4665 memcpy(info
, &result
[0], result
.size());
4668 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4669 GLuint program
, std::vector
<int8
>* result
) {
4671 // Clear the bucket so if the command fails nothing will be in it.
4672 helper_
->SetBucketSize(kResultBucketId
, 0);
4673 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4674 GetBucketContents(kResultBucketId
, result
);
4677 void GLES2Implementation::GetUniformsES3CHROMIUM(
4678 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4679 GPU_CLIENT_SINGLE_THREAD_CHECK();
4682 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4686 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4689 // Make sure they've set size to 0 else the value will be undefined on
4691 DCHECK_EQ(0, *size
);
4692 std::vector
<int8
> result
;
4693 GetUniformsES3CHROMIUMHelper(program
, &result
);
4694 if (result
.empty()) {
4697 *size
= result
.size();
4701 if (static_cast<size_t>(bufsize
) < result
.size()) {
4702 SetGLError(GL_INVALID_OPERATION
,
4703 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4706 memcpy(info
, &result
[0], result
.size());
4709 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4710 GLuint program
, std::vector
<int8
>* result
) {
4712 // Clear the bucket so if the command fails nothing will be in it.
4713 helper_
->SetBucketSize(kResultBucketId
, 0);
4714 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4715 GetBucketContents(kResultBucketId
, result
);
4718 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4719 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4720 GPU_CLIENT_SINGLE_THREAD_CHECK();
4722 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4723 "bufsize less than 0.");
4727 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4731 // Make sure they've set size to 0 else the value will be undefined on
4733 DCHECK_EQ(0, *size
);
4734 std::vector
<int8
> result
;
4735 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4736 if (result
.empty()) {
4739 *size
= result
.size();
4743 if (static_cast<size_t>(bufsize
) < result
.size()) {
4744 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4745 "bufsize is too small for result.");
4748 memcpy(info
, &result
[0], result
.size());
4751 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4752 GPU_CLIENT_SINGLE_THREAD_CHECK();
4753 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4755 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4756 helper_
->CommandBufferHelper::Flush();
4757 return gpu_control_
->CreateStreamTexture(texture
);
4760 void GLES2Implementation::PostSubBufferCHROMIUM(
4761 GLint x
, GLint y
, GLint width
, GLint height
) {
4762 GPU_CLIENT_SINGLE_THREAD_CHECK();
4763 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4764 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4765 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4766 "width", width
, "height", height
);
4768 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4769 swap_buffers_tokens_
.push(helper_
->InsertToken());
4770 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4771 helper_
->CommandBufferHelper::Flush();
4772 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4773 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4774 swap_buffers_tokens_
.pop();
4778 void GLES2Implementation::DeleteQueriesEXTHelper(
4779 GLsizei n
, const GLuint
* queries
) {
4780 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4781 query_tracker_
->RemoveQuery(queries
[ii
]);
4782 query_id_allocator_
->FreeID(queries
[ii
]);
4785 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4788 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4789 GPU_CLIENT_SINGLE_THREAD_CHECK();
4790 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4792 // TODO(gman): To be spec compliant IDs from other contexts sharing
4793 // resources need to return true here even though you can't share
4794 // queries across contexts?
4795 return query_tracker_
->GetQuery(id
) != NULL
;
4798 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4799 GPU_CLIENT_SINGLE_THREAD_CHECK();
4800 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4801 << GLES2Util::GetStringQueryTarget(target
)
4802 << ", " << id
<< ")");
4804 // if any outstanding queries INV_OP
4805 QueryMap::iterator it
= current_queries_
.find(target
);
4806 if (it
!= current_queries_
.end()) {
4808 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4814 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4818 // if not GENned INV_OPERATION
4819 if (!query_id_allocator_
->InUse(id
)) {
4820 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4824 // if id does not have an object
4825 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4827 query
= query_tracker_
->CreateQuery(id
, target
);
4829 SetGLError(GL_OUT_OF_MEMORY
,
4831 "transfer buffer allocation failed");
4834 } else if (query
->target() != target
) {
4836 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
4840 current_queries_
[target
] = query
;
4846 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4847 GPU_CLIENT_SINGLE_THREAD_CHECK();
4848 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4849 << GLES2Util::GetStringQueryTarget(target
) << ")");
4850 // Don't do anything if the context is lost.
4851 if (helper_
->IsContextLost()) {
4855 QueryMap::iterator it
= current_queries_
.find(target
);
4856 if (it
== current_queries_
.end()) {
4857 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
4861 QueryTracker::Query
* query
= it
->second
;
4863 current_queries_
.erase(it
);
4867 void GLES2Implementation::GetQueryivEXT(
4868 GLenum target
, GLenum pname
, GLint
* params
) {
4869 GPU_CLIENT_SINGLE_THREAD_CHECK();
4870 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
4871 << GLES2Util::GetStringQueryTarget(target
) << ", "
4872 << GLES2Util::GetStringQueryParameter(pname
) << ", "
4873 << static_cast<const void*>(params
) << ")");
4875 if (pname
!= GL_CURRENT_QUERY_EXT
) {
4876 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
4879 QueryMap::iterator it
= current_queries_
.find(target
);
4880 if (it
!= current_queries_
.end()) {
4881 QueryTracker::Query
* query
= it
->second
;
4882 *params
= query
->id();
4886 GPU_CLIENT_LOG(" " << *params
);
4890 void GLES2Implementation::GetQueryObjectuivEXT(
4891 GLuint id
, GLenum pname
, GLuint
* params
) {
4892 GPU_CLIENT_SINGLE_THREAD_CHECK();
4893 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
4894 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
4895 << static_cast<const void*>(params
) << ")");
4897 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4899 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
4903 QueryMap::iterator it
= current_queries_
.find(query
->target());
4904 if (it
!= current_queries_
.end()) {
4906 GL_INVALID_OPERATION
,
4907 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
4911 if (query
->NeverUsed()) {
4913 GL_INVALID_OPERATION
,
4914 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
4919 case GL_QUERY_RESULT_EXT
:
4920 if (!query
->CheckResultsAvailable(helper_
)) {
4921 helper_
->WaitForToken(query
->token());
4922 if (!query
->CheckResultsAvailable(helper_
)) {
4924 CHECK(query
->CheckResultsAvailable(helper_
));
4927 *params
= query
->GetResult();
4929 case GL_QUERY_RESULT_AVAILABLE_EXT
:
4930 *params
= query
->CheckResultsAvailable(helper_
);
4933 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
4936 GPU_CLIENT_LOG(" " << *params
);
4940 void GLES2Implementation::DrawArraysInstancedANGLE(
4941 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
4942 GPU_CLIENT_SINGLE_THREAD_CHECK();
4943 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
4944 << GLES2Util::GetStringDrawMode(mode
) << ", "
4945 << first
<< ", " << count
<< ", " << primcount
<< ")");
4947 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
4950 if (primcount
< 0) {
4951 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
4954 if (primcount
== 0) {
4957 bool simulated
= false;
4958 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4959 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
4963 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
4964 RestoreArrayBuffer(simulated
);
4968 void GLES2Implementation::DrawElementsInstancedANGLE(
4969 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
4970 GLsizei primcount
) {
4971 GPU_CLIENT_SINGLE_THREAD_CHECK();
4972 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
4973 << GLES2Util::GetStringDrawMode(mode
) << ", "
4975 << GLES2Util::GetStringIndexType(type
) << ", "
4976 << static_cast<const void*>(indices
) << ", "
4977 << primcount
<< ")");
4979 SetGLError(GL_INVALID_VALUE
,
4980 "glDrawElementsInstancedANGLE", "count less than 0.");
4986 if (primcount
< 0) {
4987 SetGLError(GL_INVALID_VALUE
,
4988 "glDrawElementsInstancedANGLE", "primcount < 0");
4991 if (primcount
== 0) {
4994 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
4995 !ValidateOffset("glDrawElementsInstancedANGLE",
4996 reinterpret_cast<GLintptr
>(indices
))) {
5000 bool simulated
= false;
5001 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
5002 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
5003 indices
, &offset
, &simulated
)) {
5006 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
5007 RestoreElementAndArrayBuffers(simulated
);
5011 void GLES2Implementation::GenMailboxCHROMIUM(
5013 GPU_CLIENT_SINGLE_THREAD_CHECK();
5014 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
5015 << static_cast<const void*>(mailbox
) << ")");
5016 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
5018 gpu::Mailbox result
= gpu::Mailbox::Generate();
5019 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
5022 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
5023 const GLbyte
* data
) {
5024 GPU_CLIENT_SINGLE_THREAD_CHECK();
5025 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
5026 << static_cast<const void*>(data
) << ")");
5027 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5028 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
5029 "mailbox that was not generated by "
5030 "GenMailboxCHROMIUM.";
5031 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
5035 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
5036 GLuint texture
, GLenum target
, const GLbyte
* data
) {
5037 GPU_CLIENT_SINGLE_THREAD_CHECK();
5038 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
5039 << static_cast<const void*>(data
) << ")");
5040 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5041 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
5042 "mailbox that was not generated by "
5043 "GenMailboxCHROMIUM.";
5044 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
5048 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
5049 const GLbyte
* data
) {
5050 GPU_CLIENT_SINGLE_THREAD_CHECK();
5051 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
5052 << static_cast<const void*>(data
) << ")");
5053 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5054 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
5055 "mailbox that was not generated by "
5056 "GenMailboxCHROMIUM.";
5057 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
5061 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
5062 GLenum target
, const GLbyte
* data
) {
5063 GPU_CLIENT_SINGLE_THREAD_CHECK();
5064 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
5065 << static_cast<const void*>(data
) << ")");
5066 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
5067 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
5068 "mailbox that was not generated by "
5069 "GenMailboxCHROMIUM.";
5071 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
5072 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
5074 if (share_group_
->bind_generates_resource())
5075 helper_
->CommandBufferHelper::Flush();
5080 void GLES2Implementation::PushGroupMarkerEXT(
5081 GLsizei length
, const GLchar
* marker
) {
5082 GPU_CLIENT_SINGLE_THREAD_CHECK();
5083 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
5084 << length
<< ", " << marker
<< ")");
5090 (length
? std::string(marker
, length
) : std::string(marker
)));
5091 helper_
->PushGroupMarkerEXT(kResultBucketId
);
5092 helper_
->SetBucketSize(kResultBucketId
, 0);
5093 debug_marker_manager_
.PushGroup(
5094 length
? std::string(marker
, length
) : std::string(marker
));
5097 void GLES2Implementation::InsertEventMarkerEXT(
5098 GLsizei length
, const GLchar
* marker
) {
5099 GPU_CLIENT_SINGLE_THREAD_CHECK();
5100 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
5101 << length
<< ", " << marker
<< ")");
5107 (length
? std::string(marker
, length
) : std::string(marker
)));
5108 helper_
->InsertEventMarkerEXT(kResultBucketId
);
5109 helper_
->SetBucketSize(kResultBucketId
, 0);
5110 debug_marker_manager_
.SetMarker(
5111 length
? std::string(marker
, length
) : std::string(marker
));
5114 void GLES2Implementation::PopGroupMarkerEXT() {
5115 GPU_CLIENT_SINGLE_THREAD_CHECK();
5116 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
5117 helper_
->PopGroupMarkerEXT();
5118 debug_marker_manager_
.PopGroup();
5121 void GLES2Implementation::TraceBeginCHROMIUM(
5122 const char* category_name
, const char* trace_name
) {
5123 GPU_CLIENT_SINGLE_THREAD_CHECK();
5124 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
5125 << category_name
<< ", " << trace_name
<< ")");
5126 SetBucketAsCString(kResultBucketId
, category_name
);
5127 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
5128 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
5129 helper_
->SetBucketSize(kResultBucketId
, 0);
5130 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
5131 current_trace_stack_
++;
5134 void GLES2Implementation::TraceEndCHROMIUM() {
5135 GPU_CLIENT_SINGLE_THREAD_CHECK();
5136 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
5137 if (current_trace_stack_
== 0) {
5138 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
5139 "missing begin trace");
5142 helper_
->TraceEndCHROMIUM();
5143 current_trace_stack_
--;
5146 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
5147 GPU_CLIENT_SINGLE_THREAD_CHECK();
5148 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
5149 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
5151 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
5152 if (access
!= GL_READ_ONLY
) {
5153 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5157 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
5158 if (access
!= GL_WRITE_ONLY
) {
5159 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
5165 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
5169 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
5173 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5175 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
5178 if (buffer
->mapped()) {
5179 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
5182 // Here we wait for previous transfer operations to be finished.
5183 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
5184 // with this method of synchronization. Until this is fixed,
5185 // MapBufferCHROMIUM will not block even if the transfer is not ready
5187 if (buffer
->last_usage_token()) {
5188 helper_
->WaitForToken(buffer
->last_usage_token());
5189 buffer
->set_last_usage_token(0);
5191 buffer
->set_mapped(true);
5193 GPU_CLIENT_LOG(" returned " << buffer
->address());
5195 return buffer
->address();
5198 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
5199 GPU_CLIENT_SINGLE_THREAD_CHECK();
5201 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
5203 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
5204 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
5209 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
5211 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
5214 if (!buffer
->mapped()) {
5215 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
5218 buffer
->set_mapped(false);
5223 bool GLES2Implementation::EnsureAsyncUploadSync() {
5224 if (async_upload_sync_
)
5228 unsigned int shm_offset
;
5229 void* mem
= mapped_memory_
->Alloc(sizeof(AsyncUploadSync
),
5235 async_upload_sync_shm_id_
= shm_id
;
5236 async_upload_sync_shm_offset_
= shm_offset
;
5237 async_upload_sync_
= static_cast<AsyncUploadSync
*>(mem
);
5238 async_upload_sync_
->Reset();
5243 uint32
GLES2Implementation::NextAsyncUploadToken() {
5244 async_upload_token_
++;
5245 if (async_upload_token_
== 0)
5246 async_upload_token_
++;
5247 return async_upload_token_
;
5250 void GLES2Implementation::PollAsyncUploads() {
5251 if (!async_upload_sync_
)
5254 if (helper_
->IsContextLost()) {
5255 DetachedAsyncUploadMemoryList::iterator it
=
5256 detached_async_upload_memory_
.begin();
5257 while (it
!= detached_async_upload_memory_
.end()) {
5258 mapped_memory_
->Free(it
->first
);
5259 it
= detached_async_upload_memory_
.erase(it
);
5264 DetachedAsyncUploadMemoryList::iterator it
=
5265 detached_async_upload_memory_
.begin();
5266 while (it
!= detached_async_upload_memory_
.end()) {
5267 if (HasAsyncUploadTokenPassed(it
->second
)) {
5268 mapped_memory_
->Free(it
->first
);
5269 it
= detached_async_upload_memory_
.erase(it
);
5276 void GLES2Implementation::FreeAllAsyncUploadBuffers() {
5277 // Free all completed unmanaged async uploads buffers.
5280 // Synchronously free rest of the unmanaged async upload buffers.
5281 if (!detached_async_upload_memory_
.empty()) {
5282 WaitAllAsyncTexImage2DCHROMIUM();
5288 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
5289 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
5290 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
5291 const void* pixels
) {
5292 GPU_CLIENT_SINGLE_THREAD_CHECK();
5293 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
5294 << GLES2Util::GetStringTextureTarget(target
) << ", "
5296 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
5297 << width
<< ", " << height
<< ", " << border
<< ", "
5298 << GLES2Util::GetStringTextureFormat(format
) << ", "
5299 << GLES2Util::GetStringPixelType(type
) << ", "
5300 << static_cast<const void*>(pixels
) << ")");
5301 if (level
< 0 || height
< 0 || width
< 0) {
5302 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
5306 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
5310 uint32 unpadded_row_size
;
5311 uint32 padded_row_size
;
5312 if (!GLES2Util::ComputeImageDataSizes(
5313 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5314 &unpadded_row_size
, &padded_row_size
)) {
5315 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
5319 // If there's no data/buffer just issue the AsyncTexImage2D
5320 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
5321 helper_
->AsyncTexImage2DCHROMIUM(
5322 target
, level
, internalformat
, width
, height
, format
, type
,
5327 if (!EnsureAsyncUploadSync()) {
5328 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5332 // Otherwise, async uploads require a transfer buffer to be bound.
5333 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5334 // the buffer before the transfer is finished. (Currently such
5335 // synchronization has to be handled manually.)
5336 GLuint offset
= ToGLuint(pixels
);
5337 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5338 bound_pixel_unpack_transfer_buffer_id_
,
5339 "glAsyncTexImage2DCHROMIUM", offset
, size
);
5340 if (buffer
&& buffer
->shm_id() != -1) {
5341 uint32 async_token
= NextAsyncUploadToken();
5342 buffer
->set_last_async_upload_token(async_token
);
5343 helper_
->AsyncTexImage2DCHROMIUM(
5344 target
, level
, internalformat
, width
, height
, format
, type
,
5345 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5347 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5351 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
5352 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
5353 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
5354 GPU_CLIENT_SINGLE_THREAD_CHECK();
5355 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
5356 << GLES2Util::GetStringTextureTarget(target
) << ", "
5358 << xoffset
<< ", " << yoffset
<< ", "
5359 << width
<< ", " << height
<< ", "
5360 << GLES2Util::GetStringTextureFormat(format
) << ", "
5361 << GLES2Util::GetStringPixelType(type
) << ", "
5362 << static_cast<const void*>(pixels
) << ")");
5363 if (level
< 0 || height
< 0 || width
< 0) {
5365 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
5370 uint32 unpadded_row_size
;
5371 uint32 padded_row_size
;
5372 if (!GLES2Util::ComputeImageDataSizes(
5373 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5374 &unpadded_row_size
, &padded_row_size
)) {
5376 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
5380 if (!EnsureAsyncUploadSync()) {
5381 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5385 // Async uploads require a transfer buffer to be bound.
5386 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5387 // the buffer before the transfer is finished. (Currently such
5388 // synchronization has to be handled manually.)
5389 GLuint offset
= ToGLuint(pixels
);
5390 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5391 bound_pixel_unpack_transfer_buffer_id_
,
5392 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
5393 if (buffer
&& buffer
->shm_id() != -1) {
5394 uint32 async_token
= NextAsyncUploadToken();
5395 buffer
->set_last_async_upload_token(async_token
);
5396 helper_
->AsyncTexSubImage2DCHROMIUM(
5397 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
5398 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5400 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5404 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
5405 GPU_CLIENT_SINGLE_THREAD_CHECK();
5406 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
5407 << GLES2Util::GetStringTextureTarget(target
) << ")");
5408 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
5412 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() {
5413 GPU_CLIENT_SINGLE_THREAD_CHECK();
5414 GPU_CLIENT_LOG("[" << GetLogPrefix()
5415 << "] glWaitAllAsyncTexImage2DCHROMIUM()");
5416 helper_
->WaitAllAsyncTexImage2DCHROMIUM();
5420 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5421 GPU_CLIENT_SINGLE_THREAD_CHECK();
5422 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5423 helper_
->CommandBufferHelper::Flush();
5424 return gpu_control_
->InsertSyncPoint();
5427 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5428 GPU_CLIENT_SINGLE_THREAD_CHECK();
5429 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5430 DCHECK(capabilities_
.future_sync_points
);
5431 return gpu_control_
->InsertFutureSyncPoint();
5434 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5435 GPU_CLIENT_SINGLE_THREAD_CHECK();
5436 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5437 << sync_point
<< ")");
5438 DCHECK(capabilities_
.future_sync_points
);
5439 helper_
->CommandBufferHelper::Flush();
5440 gpu_control_
->RetireSyncPoint(sync_point
);
5445 bool ValidImageFormat(GLenum internalformat
,
5446 const Capabilities
& capabilities
) {
5447 switch (internalformat
) {
5448 case GL_ATC_RGB_AMD
:
5449 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
5450 return capabilities
.texture_format_atc
;
5451 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
5452 return capabilities
.texture_format_dxt1
;
5453 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
5454 return capabilities
.texture_format_dxt5
;
5455 case GL_ETC1_RGB8_OES
:
5456 return capabilities
.texture_format_etc1
;
5467 bool ValidImageUsage(GLenum usage
) {
5469 case GL_MAP_CHROMIUM
:
5470 case GL_SCANOUT_CHROMIUM
:
5479 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5482 GLenum internalformat
) {
5484 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5489 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5493 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5494 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5499 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5501 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5507 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5510 GLenum internalformat
) {
5511 GPU_CLIENT_SINGLE_THREAD_CHECK();
5512 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5513 << ", " << height
<< ", "
5514 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5517 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5522 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5523 // Flush the command stream to make sure all pending commands
5524 // that may refer to the image_id are executed on the service side.
5525 helper_
->CommandBufferHelper::Flush();
5526 gpu_control_
->DestroyImage(image_id
);
5529 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5530 GPU_CLIENT_SINGLE_THREAD_CHECK();
5531 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5532 << image_id
<< ")");
5533 DestroyImageCHROMIUMHelper(image_id
);
5537 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5540 GLenum internalformat
,
5544 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5549 SetGLError(GL_INVALID_VALUE
,
5550 "glCreateGpuMemoryBufferImageCHROMIUM",
5555 if (!ValidImageFormat(internalformat
, capabilities_
)) {
5556 SetGLError(GL_INVALID_VALUE
,
5557 "glCreateGpuMemoryBufferImageCHROMIUM",
5562 if (!ValidImageUsage(usage
)) {
5563 SetGLError(GL_INVALID_VALUE
,
5564 "glCreateGpuMemoryBufferImageCHROMIUM",
5569 // Flush the command stream to ensure ordering in case the newly
5570 // returned image_id has recently been in use with a different buffer.
5571 helper_
->CommandBufferHelper::Flush();
5572 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5573 width
, height
, internalformat
, usage
);
5575 SetGLError(GL_OUT_OF_MEMORY
,
5576 "glCreateGpuMemoryBufferImageCHROMIUM",
5583 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5586 GLenum internalformat
,
5588 GPU_CLIENT_SINGLE_THREAD_CHECK();
5589 GPU_CLIENT_LOG("[" << GetLogPrefix()
5590 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5591 << ", " << height
<< ", "
5592 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5593 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5594 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5595 width
, height
, internalformat
, usage
);
5600 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5602 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5605 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5606 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5612 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5614 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5617 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5618 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5624 bool GLES2Implementation::GetSamplerParameterfvHelper(
5625 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5626 // TODO(zmo): Implement client side caching.
5630 bool GLES2Implementation::GetSamplerParameterivHelper(
5631 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5632 // TODO(zmo): Implement client side caching.
5636 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5637 const char* const* str
,
5638 const GLint
* length
,
5639 const char* func_name
) {
5640 DCHECK_LE(0, count
);
5641 // Compute the total size.
5642 base::CheckedNumeric
<size_t> total_size
= count
;
5644 total_size
*= sizeof(GLint
);
5645 if (!total_size
.IsValid()) {
5646 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5649 size_t header_size
= total_size
.ValueOrDefault(0);
5650 std::vector
<GLint
> header(count
+ 1);
5651 header
[0] = static_cast<GLint
>(count
);
5652 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5655 len
= (length
&& length
[ii
] >= 0)
5657 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5660 total_size
+= 1; // NULL at the end of each char array.
5661 if (!total_size
.IsValid()) {
5662 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5665 header
[ii
+ 1] = len
;
5667 // Pack data into a bucket on the service.
5668 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5670 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5672 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5673 base::CheckedNumeric
<size_t> checked_size
=
5674 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5676 checked_size
+= 1; // NULL in the end.
5678 if (!checked_size
.IsValid()) {
5679 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5682 size_t size
= checked_size
.ValueOrDefault(0);
5684 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5685 if (!buffer
.valid() || buffer
.size() == 0) {
5686 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5689 size_t copy_size
= buffer
.size();
5690 if (ii
> 0 && buffer
.size() == size
)
5693 memcpy(buffer
.address(), src
, copy_size
);
5694 if (copy_size
< buffer
.size()) {
5695 // Append NULL in the end.
5696 DCHECK(copy_size
+ 1 == buffer
.size());
5697 char* str
= reinterpret_cast<char*>(buffer
.address());
5700 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5701 buffer
.shm_id(), buffer
.offset());
5702 offset
+= buffer
.size();
5703 src
+= buffer
.size();
5704 size
-= buffer
.size();
5707 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5711 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5714 GPU_CLIENT_SINGLE_THREAD_CHECK();
5715 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5716 << ", " << index
<< ", " << binding
<< ")");
5717 share_group_
->program_info_manager()->UniformBlockBinding(
5718 this, program
, index
, binding
);
5719 helper_
->UniformBlockBinding(program
, index
, binding
);
5723 GLenum
GLES2Implementation::ClientWaitSync(
5724 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5725 GPU_CLIENT_SINGLE_THREAD_CHECK();
5726 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5727 << ", " << flags
<< ", " << timeout
<< ")");
5728 typedef cmds::ClientWaitSync::Result Result
;
5729 Result
* result
= GetResultAs
<Result
*>();
5731 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5732 return GL_WAIT_FAILED
;
5734 *result
= GL_WAIT_FAILED
;
5735 uint32_t v32_0
= 0, v32_1
= 0;
5736 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5737 helper_
->ClientWaitSync(
5738 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5739 GetResultShmId(), GetResultShmOffset());
5741 GPU_CLIENT_LOG("returned " << *result
);
5746 void GLES2Implementation::WaitSync(
5747 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5748 GPU_CLIENT_SINGLE_THREAD_CHECK();
5749 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5750 << flags
<< ", " << timeout
<< ")");
5751 uint32_t v32_0
= 0, v32_1
= 0;
5752 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5753 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5757 void GLES2Implementation::GetInternalformativ(
5758 GLenum target
, GLenum format
, GLenum pname
,
5759 GLsizei buf_size
, GLint
* params
) {
5760 GPU_CLIENT_SINGLE_THREAD_CHECK();
5761 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
5762 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInternalformativ("
5763 << GLES2Util::GetStringRenderBufferTarget(target
) << ", "
5764 << GLES2Util::GetStringRenderBufferFormat(format
) << ", "
5765 << GLES2Util::GetStringInternalFormatParameter(pname
)
5766 << ", " << buf_size
<< ", "
5767 << static_cast<const void*>(params
) << ")");
5769 SetGLError(GL_INVALID_VALUE
, "glGetInternalformativ", "bufSize < 0");
5772 TRACE_EVENT0("gpu", "GLES2Implementation::GetInternalformativ");
5773 if (GetInternalformativHelper(target
, format
, pname
, buf_size
, params
)) {
5776 typedef cmds::GetInternalformativ::Result Result
;
5777 Result
* result
= GetResultAs
<Result
*>();
5781 result
->SetNumResults(0);
5782 helper_
->GetInternalformativ(target
, format
, pname
,
5783 GetResultShmId(), GetResultShmOffset());
5785 GPU_CLIENT_LOG_CODE_BLOCK({
5786 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
5787 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
5790 if (buf_size
> 0 && params
) {
5791 GLint
* data
= result
->GetData();
5792 if (buf_size
>= result
->GetNumResults()) {
5793 buf_size
= result
->GetNumResults();
5795 for (GLsizei ii
= 0; ii
< buf_size
; ++ii
) {
5796 params
[ii
] = data
[ii
];
5802 // Include the auto-generated part of this file. We split this because it means
5803 // we can easily edit the non-auto generated parts right here in this file
5804 // instead of having to edit some template or the code generator.
5805 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5807 } // namespace gles2