1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // A class to emulate GLES2 over command buffers.
7 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include <GLES2/gl2ext.h>
10 #include <GLES2/gl2extchromium.h>
11 #include <GLES3/gl3.h>
19 #include "base/bind.h"
20 #include "base/compiler_specific.h"
21 #include "base/numerics/safe_math.h"
22 #include "gpu/command_buffer/client/buffer_tracker.h"
23 #include "gpu/command_buffer/client/gpu_control.h"
24 #include "gpu/command_buffer/client/program_info_manager.h"
25 #include "gpu/command_buffer/client/query_tracker.h"
26 #include "gpu/command_buffer/client/transfer_buffer.h"
27 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
28 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
29 #include "gpu/command_buffer/common/trace_event.h"
31 #if defined(GPU_CLIENT_DEBUG)
32 #include "base/command_line.h"
33 #include "gpu/command_buffer/client/gpu_switches.h"
39 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
40 static GLuint
ToGLuint(const void* ptr
) {
41 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
44 #if !defined(_MSC_VER)
45 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
46 const unsigned int GLES2Implementation::kStartingOffset
;
49 GLES2Implementation::GLStaticState::GLStaticState() {
52 GLES2Implementation::GLStaticState::~GLStaticState() {
55 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
56 GLES2Implementation
* gles2_implementation
)
57 : gles2_implementation_(gles2_implementation
) {
58 CHECK_EQ(0, gles2_implementation_
->use_count_
);
59 ++gles2_implementation_
->use_count_
;
62 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
63 --gles2_implementation_
->use_count_
;
64 CHECK_EQ(0, gles2_implementation_
->use_count_
);
67 GLES2Implementation::GLES2Implementation(
68 GLES2CmdHelper
* helper
,
69 ShareGroup
* share_group
,
70 TransferBufferInterface
* transfer_buffer
,
71 bool bind_generates_resource
,
72 bool lose_context_when_out_of_memory
,
73 bool support_client_side_arrays
,
74 GpuControl
* gpu_control
)
76 transfer_buffer_(transfer_buffer
),
77 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
78 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
81 unpack_flip_y_(false),
82 unpack_row_length_(0),
83 unpack_image_height_(0),
85 unpack_skip_pixels_(0),
86 unpack_skip_images_(0),
87 pack_reverse_row_order_(false),
88 active_texture_unit_(0),
89 bound_framebuffer_(0),
90 bound_read_framebuffer_(0),
91 bound_renderbuffer_(0),
92 bound_valuebuffer_(0),
94 bound_array_buffer_id_(0),
95 bound_pixel_pack_transfer_buffer_id_(0),
96 bound_pixel_unpack_transfer_buffer_id_(0),
97 async_upload_token_(0),
98 async_upload_sync_(NULL
),
99 async_upload_sync_shm_id_(0),
100 async_upload_sync_shm_offset_(0),
103 lose_context_when_out_of_memory_(lose_context_when_out_of_memory
),
104 support_client_side_arrays_(support_client_side_arrays
),
106 error_message_callback_(NULL
),
107 current_trace_stack_(0),
108 gpu_control_(gpu_control
),
109 capabilities_(gpu_control
->GetCapabilities()),
110 weak_ptr_factory_(this) {
112 DCHECK(transfer_buffer
);
115 std::stringstream ss
;
116 ss
<< std::hex
<< this;
117 this_in_hex_
= ss
.str();
119 GPU_CLIENT_LOG_CODE_BLOCK({
120 debug_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
121 switches::kEnableGPUClientLogging
);
125 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
126 DCHECK(share_group_
->bind_generates_resource() == bind_generates_resource
);
128 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
131 bool GLES2Implementation::Initialize(
132 unsigned int starting_transfer_buffer_size
,
133 unsigned int min_transfer_buffer_size
,
134 unsigned int max_transfer_buffer_size
,
135 unsigned int mapped_memory_limit
) {
136 TRACE_EVENT0("gpu", "GLES2Implementation::Initialize");
137 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
138 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
139 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
141 if (!transfer_buffer_
->Initialize(
142 starting_transfer_buffer_size
,
144 min_transfer_buffer_size
,
145 max_transfer_buffer_size
,
151 mapped_memory_
.reset(
152 new MappedMemoryManager(
154 base::Bind(&GLES2Implementation::PollAsyncUploads
,
155 // The mapped memory manager is owned by |this| here, and
156 // since its destroyed before before we destroy ourselves
157 // we don't need extra safety measures for this closure.
158 base::Unretained(this)),
159 mapped_memory_limit
));
161 unsigned chunk_size
= 2 * 1024 * 1024;
162 if (mapped_memory_limit
!= kNoLimit
) {
163 // Use smaller chunks if the client is very memory conscientious.
164 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
166 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
168 GLStaticState::ShaderPrecisionMap
* shader_precisions
=
169 &static_state_
.shader_precisions
;
170 capabilities_
.VisitPrecisions([shader_precisions
](
171 GLenum shader
, GLenum type
, Capabilities::ShaderPrecision
* result
) {
172 const GLStaticState::ShaderPrecisionKey
key(shader
, type
);
173 cmds::GetShaderPrecisionFormat::Result cached_result
= {
174 true, result
->min_range
, result
->max_range
, result
->precision
};
175 shader_precisions
->insert(std::make_pair(key
, cached_result
));
178 util_
.set_num_compressed_texture_formats(
179 capabilities_
.num_compressed_texture_formats
);
180 util_
.set_num_shader_binary_formats(capabilities_
.num_shader_binary_formats
);
182 texture_units_
.reset(
183 new TextureUnit
[capabilities_
.max_combined_texture_image_units
]);
185 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
186 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
188 query_id_allocator_
.reset(new IdAllocator());
189 if (support_client_side_arrays_
) {
190 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
191 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
194 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
195 capabilities_
.max_vertex_attribs
, reserved_ids_
[0], reserved_ids_
[1],
196 support_client_side_arrays_
));
198 // GL_BIND_GENERATES_RESOURCE_CHROMIUM state must be the same
199 // on Client & Service.
200 if (capabilities_
.bind_generates_resource_chromium
!=
201 (share_group_
->bind_generates_resource() ? 1 : 0)) {
202 SetGLError(GL_INVALID_OPERATION
,
204 "Service bind_generates_resource mismatch.");
211 GLES2Implementation::~GLES2Implementation() {
212 // Make sure the queries are finished otherwise we'll delete the
213 // shared memory (mapped_memory_) which will free the memory used
214 // by the queries. The GPU process when validating that memory is still
215 // shared will fail and abort (ie, it will stop running).
217 query_tracker_
.reset();
219 // GLES2Implementation::Initialize() could fail before allocating
220 // reserved_ids_, so we need delete them carefully.
221 if (support_client_side_arrays_
&& reserved_ids_
[0]) {
222 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
225 // Release remaining BufferRange mem; This is when a MapBufferRange() is
226 // called but not the UnmapBuffer() pair.
227 ClearMappedBufferRangeMap();
229 // Release any per-context data in share group.
230 share_group_
->FreeContext(this);
232 buffer_tracker_
.reset();
234 FreeAllAsyncUploadBuffers();
236 if (async_upload_sync_
) {
237 mapped_memory_
->Free(async_upload_sync_
);
238 async_upload_sync_
= NULL
;
241 // Make sure the commands make it the service.
245 GLES2CmdHelper
* GLES2Implementation::helper() const {
249 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
250 return share_group_
->GetIdHandler(namespace_id
);
253 IdAllocator
* GLES2Implementation::GetIdAllocator(int namespace_id
) const {
254 if (namespace_id
== id_namespaces::kQueries
)
255 return query_id_allocator_
.get();
260 void* GLES2Implementation::GetResultBuffer() {
261 return transfer_buffer_
->GetResultBuffer();
264 int32
GLES2Implementation::GetResultShmId() {
265 return transfer_buffer_
->GetShmId();
268 uint32
GLES2Implementation::GetResultShmOffset() {
269 return transfer_buffer_
->GetResultOffset();
272 void GLES2Implementation::FreeUnusedSharedMemory() {
273 mapped_memory_
->FreeUnused();
276 void GLES2Implementation::FreeEverything() {
277 FreeAllAsyncUploadBuffers();
279 query_tracker_
->Shrink();
280 FreeUnusedSharedMemory();
281 transfer_buffer_
->Free();
282 helper_
->FreeRingBuffer();
285 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
286 if (!helper_
->IsContextLost())
290 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
291 const base::Closure
& callback
) {
292 gpu_control_
->SignalSyncPoint(
294 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
295 weak_ptr_factory_
.GetWeakPtr(),
299 void GLES2Implementation::SignalQuery(uint32 query
,
300 const base::Closure
& callback
) {
301 // Flush previously entered commands to ensure ordering with any
302 // glBeginQueryEXT() calls that may have been put into the context.
303 ShallowFlushCHROMIUM();
304 gpu_control_
->SignalQuery(
306 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
307 weak_ptr_factory_
.GetWeakPtr(),
311 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
313 "gpu", "GLES2Implementation::SetSurfaceVisible", "visible", visible
);
314 // TODO(piman): This probably should be ShallowFlushCHROMIUM().
316 gpu_control_
->SetSurfaceVisible(visible
);
321 void GLES2Implementation::WaitForCmd() {
322 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
323 helper_
->CommandBufferHelper::Finish();
326 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
327 const char* extensions
=
328 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
332 int length
= strlen(ext
);
334 int n
= strcspn(extensions
, " ");
335 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
338 if ('\0' == extensions
[n
]) {
345 bool GLES2Implementation::IsExtensionAvailableHelper(
346 const char* extension
, ExtensionStatus
* status
) {
348 case kAvailableExtensionStatus
:
350 case kUnavailableExtensionStatus
:
353 bool available
= IsExtensionAvailable(extension
);
354 *status
= available
? kAvailableExtensionStatus
:
355 kUnavailableExtensionStatus
;
361 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
362 return IsExtensionAvailableHelper(
363 "GL_ANGLE_pack_reverse_row_order",
364 &angle_pack_reverse_row_order_status_
);
367 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
368 return IsExtensionAvailableHelper(
369 "GL_CHROMIUM_framebuffer_multisample",
370 &chromium_framebuffer_multisample_
);
373 const std::string
& GLES2Implementation::GetLogPrefix() const {
374 const std::string
& prefix(debug_marker_manager_
.GetMarker());
375 return prefix
.empty() ? this_in_hex_
: prefix
;
378 GLenum
GLES2Implementation::GetError() {
379 GPU_CLIENT_SINGLE_THREAD_CHECK();
380 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
381 GLenum err
= GetGLError();
382 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
386 GLenum
GLES2Implementation::GetClientSideGLError() {
387 if (error_bits_
== 0) {
391 GLenum error
= GL_NO_ERROR
;
392 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
393 if ((error_bits_
& mask
) != 0) {
394 error
= GLES2Util::GLErrorBitToGLError(mask
);
398 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
402 GLenum
GLES2Implementation::GetGLError() {
403 TRACE_EVENT0("gpu", "GLES2::GetGLError");
404 // Check the GL error first, then our wrapped error.
405 typedef cmds::GetError::Result Result
;
406 Result
* result
= GetResultAs
<Result
*>();
407 // If we couldn't allocate a result the context is lost.
411 *result
= GL_NO_ERROR
;
412 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
414 GLenum error
= *result
;
415 if (error
== GL_NO_ERROR
) {
416 error
= GetClientSideGLError();
418 // There was an error, clear the corresponding wrapped error.
419 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
424 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
425 void GLES2Implementation::FailGLError(GLenum error
) {
426 if (error
!= GL_NO_ERROR
) {
427 NOTREACHED() << "Error";
430 // NOTE: Calling GetGLError overwrites data in the result buffer.
431 void GLES2Implementation::CheckGLError() {
432 FailGLError(GetGLError());
434 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
436 void GLES2Implementation::SetGLError(
437 GLenum error
, const char* function_name
, const char* msg
) {
438 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
439 << GLES2Util::GetStringError(error
) << ": "
440 << function_name
<< ": " << msg
);
445 if (error_message_callback_
) {
446 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
447 function_name
+ ": " + (msg
? msg
: ""));
448 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
450 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
452 if (error
== GL_OUT_OF_MEMORY
&& lose_context_when_out_of_memory_
) {
453 helper_
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
454 GL_UNKNOWN_CONTEXT_RESET_ARB
);
458 void GLES2Implementation::SetGLErrorInvalidEnum(
459 const char* function_name
, GLenum value
, const char* label
) {
460 SetGLError(GL_INVALID_ENUM
, function_name
,
461 (std::string(label
) + " was " +
462 GLES2Util::GetStringEnum(value
)).c_str());
465 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
466 std::vector
<int8
>* data
) {
467 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
469 const uint32 kStartSize
= 32 * 1024;
470 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
471 if (!buffer
.valid()) {
474 typedef cmd::GetBucketStart::Result Result
;
475 Result
* result
= GetResultAs
<Result
*>();
480 helper_
->GetBucketStart(
481 bucket_id
, GetResultShmId(), GetResultShmOffset(),
482 buffer
.size(), buffer
.shm_id(), buffer
.offset());
484 uint32 size
= *result
;
489 if (!buffer
.valid()) {
491 if (!buffer
.valid()) {
494 helper_
->GetBucketData(
495 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
498 uint32 size_to_copy
= std::min(size
, buffer
.size());
499 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
500 offset
+= size_to_copy
;
501 size
-= size_to_copy
;
504 // Free the bucket. This is not required but it does free up the memory.
505 // and we don't have to wait for the result so from the client's perspective
507 helper_
->SetBucketSize(bucket_id
, 0);
512 void GLES2Implementation::SetBucketContents(
513 uint32 bucket_id
, const void* data
, size_t size
) {
515 helper_
->SetBucketSize(bucket_id
, size
);
519 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
520 if (!buffer
.valid()) {
523 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
525 helper_
->SetBucketData(
526 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
527 offset
+= buffer
.size();
528 size
-= buffer
.size();
533 void GLES2Implementation::SetBucketAsCString(
534 uint32 bucket_id
, const char* str
) {
535 // NOTE: strings are passed NULL terminated. That means the empty
536 // string will have a size of 1 and no-string will have a size of 0
538 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
540 helper_
->SetBucketSize(bucket_id
, 0);
544 bool GLES2Implementation::GetBucketAsString(
545 uint32 bucket_id
, std::string
* str
) {
547 std::vector
<int8
> data
;
548 // NOTE: strings are passed NULL terminated. That means the empty
549 // string will have a size of 1 and no-string will have a size of 0
550 if (!GetBucketContents(bucket_id
, &data
)) {
556 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
560 void GLES2Implementation::SetBucketAsString(
561 uint32 bucket_id
, const std::string
& str
) {
562 // NOTE: strings are passed NULL terminated. That means the empty
563 // string will have a size of 1 and no-string will have a size of 0
564 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
567 void GLES2Implementation::Disable(GLenum cap
) {
568 GPU_CLIENT_SINGLE_THREAD_CHECK();
569 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
570 << GLES2Util::GetStringCapability(cap
) << ")");
571 bool changed
= false;
572 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
573 helper_
->Disable(cap
);
578 void GLES2Implementation::Enable(GLenum cap
) {
579 GPU_CLIENT_SINGLE_THREAD_CHECK();
580 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
581 << GLES2Util::GetStringCapability(cap
) << ")");
582 bool changed
= false;
583 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
584 helper_
->Enable(cap
);
589 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
590 GPU_CLIENT_SINGLE_THREAD_CHECK();
591 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
592 << GLES2Util::GetStringCapability(cap
) << ")");
594 if (!state_
.GetEnabled(cap
, &state
)) {
595 typedef cmds::IsEnabled::Result Result
;
596 Result
* result
= GetResultAs
<Result
*>();
601 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
603 state
= (*result
) != 0;
606 GPU_CLIENT_LOG("returned " << state
);
611 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
612 // TODO(zmo): For all the BINDING points, there is a possibility where
613 // resources are shared among multiple contexts, that the cached points
614 // are invalid. It is not a problem for now, but once we allow resource
615 // sharing in WebGL, we need to implement a mechanism to allow correct
616 // client side binding points tracking. crbug.com/465562.
620 case GL_ACTIVE_TEXTURE
:
621 *params
= active_texture_unit_
+ GL_TEXTURE0
;
623 case GL_ARRAY_BUFFER_BINDING
:
624 *params
= bound_array_buffer_id_
;
626 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
628 vertex_array_object_manager_
->bound_element_array_buffer();
630 case GL_FRAMEBUFFER_BINDING
:
631 *params
= bound_framebuffer_
;
633 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
634 *params
= capabilities_
.max_combined_texture_image_units
;
636 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
637 *params
= capabilities_
.max_cube_map_texture_size
;
639 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
640 *params
= capabilities_
.max_fragment_uniform_vectors
;
642 case GL_MAX_RENDERBUFFER_SIZE
:
643 *params
= capabilities_
.max_renderbuffer_size
;
645 case GL_MAX_TEXTURE_IMAGE_UNITS
:
646 *params
= capabilities_
.max_texture_image_units
;
648 case GL_MAX_TEXTURE_SIZE
:
649 *params
= capabilities_
.max_texture_size
;
651 case GL_MAX_VARYING_VECTORS
:
652 *params
= capabilities_
.max_varying_vectors
;
654 case GL_MAX_VERTEX_ATTRIBS
:
655 *params
= capabilities_
.max_vertex_attribs
;
657 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
658 *params
= capabilities_
.max_vertex_texture_image_units
;
660 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
661 *params
= capabilities_
.max_vertex_uniform_vectors
;
663 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
664 *params
= capabilities_
.num_compressed_texture_formats
;
666 case GL_NUM_SHADER_BINARY_FORMATS
:
667 *params
= capabilities_
.num_shader_binary_formats
;
669 case GL_RENDERBUFFER_BINDING
:
670 *params
= bound_renderbuffer_
;
672 case GL_TEXTURE_BINDING_2D
:
673 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
675 case GL_TEXTURE_BINDING_CUBE_MAP
:
676 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
679 // Non-standard parameters.
680 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
682 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
684 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
685 *params
= bound_pixel_pack_transfer_buffer_id_
;
687 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
688 *params
= bound_pixel_unpack_transfer_buffer_id_
;
690 case GL_READ_FRAMEBUFFER_BINDING
:
691 if (IsChromiumFramebufferMultisampleAvailable()) {
692 *params
= bound_read_framebuffer_
;
697 // Non-cached parameters.
698 case GL_ALIASED_LINE_WIDTH_RANGE
:
699 case GL_ALIASED_POINT_SIZE_RANGE
:
703 case GL_BLEND_DST_ALPHA
:
704 case GL_BLEND_DST_RGB
:
705 case GL_BLEND_EQUATION_ALPHA
:
706 case GL_BLEND_EQUATION_RGB
:
707 case GL_BLEND_SRC_ALPHA
:
708 case GL_BLEND_SRC_RGB
:
710 case GL_COLOR_CLEAR_VALUE
:
711 case GL_COLOR_WRITEMASK
:
712 case GL_COMPRESSED_TEXTURE_FORMATS
:
714 case GL_CULL_FACE_MODE
:
715 case GL_CURRENT_PROGRAM
:
717 case GL_DEPTH_CLEAR_VALUE
:
721 case GL_DEPTH_WRITEMASK
:
724 case GL_GENERATE_MIPMAP_HINT
:
726 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
727 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
729 case GL_MAX_VIEWPORT_DIMS
:
730 case GL_PACK_ALIGNMENT
:
731 case GL_POLYGON_OFFSET_FACTOR
:
732 case GL_POLYGON_OFFSET_FILL
:
733 case GL_POLYGON_OFFSET_UNITS
:
735 case GL_SAMPLE_ALPHA_TO_COVERAGE
:
736 case GL_SAMPLE_BUFFERS
:
737 case GL_SAMPLE_COVERAGE
:
738 case GL_SAMPLE_COVERAGE_INVERT
:
739 case GL_SAMPLE_COVERAGE_VALUE
:
742 case GL_SCISSOR_TEST
:
743 case GL_SHADER_BINARY_FORMATS
:
744 case GL_SHADER_COMPILER
:
745 case GL_STENCIL_BACK_FAIL
:
746 case GL_STENCIL_BACK_FUNC
:
747 case GL_STENCIL_BACK_PASS_DEPTH_FAIL
:
748 case GL_STENCIL_BACK_PASS_DEPTH_PASS
:
749 case GL_STENCIL_BACK_REF
:
750 case GL_STENCIL_BACK_VALUE_MASK
:
751 case GL_STENCIL_BACK_WRITEMASK
:
752 case GL_STENCIL_BITS
:
753 case GL_STENCIL_CLEAR_VALUE
:
754 case GL_STENCIL_FAIL
:
755 case GL_STENCIL_FUNC
:
756 case GL_STENCIL_PASS_DEPTH_FAIL
:
757 case GL_STENCIL_PASS_DEPTH_PASS
:
759 case GL_STENCIL_TEST
:
760 case GL_STENCIL_VALUE_MASK
:
761 case GL_STENCIL_WRITEMASK
:
762 case GL_SUBPIXEL_BITS
:
763 case GL_UNPACK_ALIGNMENT
:
770 if (capabilities_
.major_version
< 3) {
776 case GL_MAJOR_VERSION
:
777 *params
= capabilities_
.major_version
;
779 case GL_MAX_3D_TEXTURE_SIZE
:
780 *params
= capabilities_
.max_3d_texture_size
;
782 case GL_MAX_ARRAY_TEXTURE_LAYERS
:
783 *params
= capabilities_
.max_array_texture_layers
;
785 case GL_MAX_COLOR_ATTACHMENTS
:
786 *params
= capabilities_
.max_color_attachments
;
788 case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
:
789 *params
= capabilities_
.max_combined_fragment_uniform_components
;
791 case GL_MAX_COMBINED_UNIFORM_BLOCKS
:
792 *params
= capabilities_
.max_combined_uniform_blocks
;
794 case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
:
795 *params
= capabilities_
.max_combined_vertex_uniform_components
;
797 case GL_MAX_DRAW_BUFFERS
:
798 *params
= capabilities_
.max_draw_buffers
;
800 case GL_MAX_ELEMENT_INDEX
:
801 *params
= capabilities_
.max_element_index
;
803 case GL_MAX_ELEMENTS_INDICES
:
804 *params
= capabilities_
.max_elements_indices
;
806 case GL_MAX_ELEMENTS_VERTICES
:
807 *params
= capabilities_
.max_elements_vertices
;
809 case GL_MAX_FRAGMENT_INPUT_COMPONENTS
:
810 *params
= capabilities_
.max_fragment_input_components
;
812 case GL_MAX_FRAGMENT_UNIFORM_BLOCKS
:
813 *params
= capabilities_
.max_fragment_uniform_blocks
;
815 case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
:
816 *params
= capabilities_
.max_fragment_uniform_components
;
818 case GL_MAX_PROGRAM_TEXEL_OFFSET
:
819 *params
= capabilities_
.max_program_texel_offset
;
822 *params
= capabilities_
.max_samples
;
824 case GL_MAX_SERVER_WAIT_TIMEOUT
:
825 *params
= capabilities_
.max_server_wait_timeout
;
827 case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
:
828 *params
= capabilities_
.max_transform_feedback_interleaved_components
;
830 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
:
831 *params
= capabilities_
.max_transform_feedback_separate_attribs
;
833 case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
:
834 *params
= capabilities_
.max_transform_feedback_separate_components
;
836 case GL_MAX_UNIFORM_BLOCK_SIZE
:
837 *params
= capabilities_
.max_uniform_block_size
;
839 case GL_MAX_UNIFORM_BUFFER_BINDINGS
:
840 *params
= capabilities_
.max_uniform_buffer_bindings
;
842 case GL_MAX_VARYING_COMPONENTS
:
843 *params
= capabilities_
.max_varying_components
;
845 case GL_MAX_VERTEX_OUTPUT_COMPONENTS
:
846 *params
= capabilities_
.max_vertex_output_components
;
848 case GL_MAX_VERTEX_UNIFORM_BLOCKS
:
849 *params
= capabilities_
.max_vertex_uniform_blocks
;
851 case GL_MAX_VERTEX_UNIFORM_COMPONENTS
:
852 *params
= capabilities_
.max_vertex_uniform_components
;
854 case GL_MIN_PROGRAM_TEXEL_OFFSET
:
855 *params
= capabilities_
.min_program_texel_offset
;
857 case GL_MINOR_VERSION
:
858 *params
= capabilities_
.minor_version
;
860 case GL_NUM_EXTENSIONS
:
861 *params
= capabilities_
.num_extensions
;
863 case GL_NUM_PROGRAM_BINARY_FORMATS
:
864 *params
= capabilities_
.num_program_binary_formats
;
866 case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
:
867 *params
= capabilities_
.uniform_buffer_offset_alignment
;
870 // Non-cached ES3 parameters.
871 case GL_COPY_READ_BUFFER_BINDING
:
872 case GL_COPY_WRITE_BUFFER_BINDING
:
873 case GL_DRAW_BUFFER0
:
874 case GL_DRAW_BUFFER1
:
875 case GL_DRAW_BUFFER2
:
876 case GL_DRAW_BUFFER3
:
877 case GL_DRAW_BUFFER4
:
878 case GL_DRAW_BUFFER5
:
879 case GL_DRAW_BUFFER6
:
880 case GL_DRAW_BUFFER7
:
881 case GL_DRAW_BUFFER8
:
882 case GL_DRAW_BUFFER9
:
883 case GL_DRAW_BUFFER10
:
884 case GL_DRAW_BUFFER11
:
885 case GL_DRAW_BUFFER12
:
886 case GL_DRAW_BUFFER13
:
887 case GL_DRAW_BUFFER14
:
888 case GL_DRAW_BUFFER15
:
889 case GL_DRAW_FRAMEBUFFER_BINDING
:
890 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT
:
891 case GL_MAX_TEXTURE_LOD_BIAS
:
892 case GL_PACK_ROW_LENGTH
:
893 case GL_PACK_SKIP_PIXELS
:
894 case GL_PACK_SKIP_ROWS
:
895 case GL_PIXEL_PACK_BUFFER_BINDING
:
896 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
897 case GL_PRIMITIVE_RESTART_FIXED_INDEX
:
898 case GL_PROGRAM_BINARY_FORMATS
:
899 case GL_RASTERIZER_DISCARD
:
901 case GL_READ_FRAMEBUFFER_BINDING
:
902 case GL_SAMPLER_BINDING
:
903 case GL_TEXTURE_BINDING_2D_ARRAY
:
904 case GL_TEXTURE_BINDING_3D
:
905 case GL_TRANSFORM_FEEDBACK_BINDING
:
906 case GL_TRANSFORM_FEEDBACK_ACTIVE
:
907 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
908 case GL_TRANSFORM_FEEDBACK_PAUSED
:
909 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE
:
910 case GL_TRANSFORM_FEEDBACK_BUFFER_START
:
911 case GL_UNIFORM_BUFFER_BINDING
:
912 case GL_UNIFORM_BUFFER_SIZE
:
913 case GL_UNIFORM_BUFFER_START
:
914 case GL_UNPACK_IMAGE_HEIGHT
:
915 case GL_UNPACK_ROW_LENGTH
:
916 case GL_UNPACK_SKIP_IMAGES
:
917 case GL_UNPACK_SKIP_PIXELS
:
918 case GL_UNPACK_SKIP_ROWS
:
919 case GL_VERTEX_ARRAY_BINDING
:
926 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
927 // TODO(gman): Make this handle pnames that return more than 1 value.
929 if (!GetHelper(pname
, &value
)) {
932 *params
= static_cast<GLboolean
>(value
);
936 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
937 // TODO(gman): Make this handle pnames that return more than 1 value.
939 if (!GetHelper(pname
, &value
)) {
942 *params
= static_cast<GLfloat
>(value
);
946 bool GLES2Implementation::GetInteger64vHelper(GLenum pname
, GLint64
* params
) {
947 // TODO(zmo): we limit values to 32-bit, which is OK for now.
949 if (!GetHelper(pname
, &value
)) {
956 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
957 return GetHelper(pname
, params
);
960 bool GLES2Implementation::GetIntegeri_vHelper(
961 GLenum pname
, GLuint index
, GLint
* data
) {
962 // TODO(zmo): Implement client side caching.
966 bool GLES2Implementation::GetInteger64i_vHelper(
967 GLenum pname
, GLuint index
, GLint64
* data
) {
968 // TODO(zmo): Implement client side caching.
972 bool GLES2Implementation::GetInternalformativHelper(
973 GLenum target
, GLenum format
, GLenum pname
, GLsizei bufSize
,
975 // TODO(zmo): Implement the client side caching.
979 bool GLES2Implementation::GetSyncivHelper(
980 GLsync sync
, GLenum pname
, GLsizei bufsize
, GLsizei
* length
,
985 value
= GL_SYNC_FENCE
;
987 case GL_SYNC_CONDITION
:
988 value
= GL_SYNC_GPU_COMMANDS_COMPLETE
;
1006 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
1007 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1008 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
1009 Result
* result
= GetResultAs
<Result
*>();
1014 helper_
->GetMaxValueInBufferCHROMIUM(
1015 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
1020 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
1021 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
1022 GPU_CLIENT_SINGLE_THREAD_CHECK();
1023 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
1024 << buffer_id
<< ", " << count
<< ", "
1025 << GLES2Util::GetStringGetMaxIndexType(type
)
1026 << ", " << offset
<< ")");
1027 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
1028 buffer_id
, count
, type
, offset
);
1029 GPU_CLIENT_LOG("returned " << result
);
1034 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
1036 RestoreArrayBuffer(restore
);
1037 // Restore the element array binding.
1038 // We only need to restore it if it wasn't a client side array.
1039 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
1040 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
1045 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
1047 // Restore the user's current binding.
1048 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_id_
);
1052 void GLES2Implementation::DrawElements(
1053 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
1054 GPU_CLIENT_SINGLE_THREAD_CHECK();
1055 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
1056 << GLES2Util::GetStringDrawMode(mode
) << ", "
1058 << GLES2Util::GetStringIndexType(type
) << ", "
1059 << static_cast<const void*>(indices
) << ")");
1060 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1063 void GLES2Implementation::DrawRangeElements(
1064 GLenum mode
, GLuint start
, GLuint end
,
1065 GLsizei count
, GLenum type
, const void* indices
) {
1066 GPU_CLIENT_SINGLE_THREAD_CHECK();
1067 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements("
1068 << GLES2Util::GetStringDrawMode(mode
) << ", "
1069 << start
<< ", " << end
<< ", " << count
<< ", "
1070 << GLES2Util::GetStringIndexType(type
) << ", "
1071 << static_cast<const void*>(indices
) << ")");
1073 SetGLError(GL_INVALID_VALUE
, "glDrawRangeElements", "end < start");
1076 DrawElementsImpl(mode
, count
, type
, indices
, "glDrawRangeElements");
1079 void GLES2Implementation::DrawElementsImpl(
1080 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
1081 const char* func_name
) {
1083 SetGLError(GL_INVALID_VALUE
, func_name
, "count < 0");
1086 bool simulated
= false;
1087 GLuint offset
= ToGLuint(indices
);
1089 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
1090 !ValidateOffset(func_name
, reinterpret_cast<GLintptr
>(indices
))) {
1093 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
1094 func_name
, this, helper_
, count
, type
, 0, indices
,
1095 &offset
, &simulated
)) {
1099 helper_
->DrawElements(mode
, count
, type
, offset
);
1100 RestoreElementAndArrayBuffers(simulated
);
1104 void GLES2Implementation::Flush() {
1105 GPU_CLIENT_SINGLE_THREAD_CHECK();
1106 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
1107 // Insert the cmd to call glFlush
1109 // Flush our command buffer
1110 // (tell the service to execute up to the flush cmd.)
1111 helper_
->CommandBufferHelper::Flush();
1114 void GLES2Implementation::ShallowFlushCHROMIUM() {
1115 GPU_CLIENT_SINGLE_THREAD_CHECK();
1116 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
1117 // Flush our command buffer
1118 // (tell the service to execute up to the flush cmd.)
1119 helper_
->CommandBufferHelper::Flush();
1120 // TODO(piman): Add the FreeEverything() logic here.
1123 void GLES2Implementation::OrderingBarrierCHROMIUM() {
1124 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glOrderingBarrierCHROMIUM");
1125 // Flush command buffer at the GPU channel level. May be implemented as
1127 helper_
->CommandBufferHelper::OrderingBarrier();
1130 void GLES2Implementation::Finish() {
1131 GPU_CLIENT_SINGLE_THREAD_CHECK();
1135 void GLES2Implementation::ShallowFinishCHROMIUM() {
1136 GPU_CLIENT_SINGLE_THREAD_CHECK();
1137 TRACE_EVENT0("gpu", "GLES2::ShallowFinishCHROMIUM");
1138 // Flush our command buffer (tell the service to execute up to the flush cmd
1139 // and don't return until it completes).
1140 helper_
->CommandBufferHelper::Finish();
1143 void GLES2Implementation::FinishHelper() {
1144 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
1145 TRACE_EVENT0("gpu", "GLES2::Finish");
1146 // Insert the cmd to call glFinish
1148 // Finish our command buffer
1149 // (tell the service to execute up to the Finish cmd and wait for it to
1151 helper_
->CommandBufferHelper::Finish();
1154 void GLES2Implementation::SwapBuffers() {
1155 GPU_CLIENT_SINGLE_THREAD_CHECK();
1156 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
1157 // TODO(piman): Strictly speaking we'd want to insert the token after the
1158 // swap, but the state update with the updated token might not have happened
1159 // by the time the SwapBuffer callback gets called, forcing us to synchronize
1160 // with the GPU process more than needed. So instead, make it happen before.
1161 // All it means is that we could be slightly looser on the kMaxSwapBuffers
1162 // semantics if the client doesn't use the callback mechanism, and by chance
1163 // the scheduler yields between the InsertToken and the SwapBuffers.
1164 swap_buffers_tokens_
.push(helper_
->InsertToken());
1165 helper_
->SwapBuffers();
1166 helper_
->CommandBufferHelper::Flush();
1167 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
1168 // compensate for TODO above.
1169 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
1170 helper_
->WaitForToken(swap_buffers_tokens_
.front());
1171 swap_buffers_tokens_
.pop();
1175 void GLES2Implementation::SwapInterval(int interval
) {
1176 GPU_CLIENT_SINGLE_THREAD_CHECK();
1177 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapInterval("
1178 << interval
<< ")");
1179 helper_
->SwapInterval(interval
);
1182 void GLES2Implementation::BindAttribLocation(
1183 GLuint program
, GLuint index
, const char* name
) {
1184 GPU_CLIENT_SINGLE_THREAD_CHECK();
1185 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1186 << program
<< ", " << index
<< ", " << name
<< ")");
1187 SetBucketAsString(kResultBucketId
, name
);
1188 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1189 helper_
->SetBucketSize(kResultBucketId
, 0);
1193 void GLES2Implementation::BindUniformLocationCHROMIUM(
1194 GLuint program
, GLint location
, const char* name
) {
1195 GPU_CLIENT_SINGLE_THREAD_CHECK();
1196 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1197 << program
<< ", " << location
<< ", " << name
<< ")");
1198 SetBucketAsString(kResultBucketId
, name
);
1199 helper_
->BindUniformLocationCHROMIUMBucket(
1200 program
, location
, kResultBucketId
);
1201 helper_
->SetBucketSize(kResultBucketId
, 0);
1205 void GLES2Implementation::GetVertexAttribPointerv(
1206 GLuint index
, GLenum pname
, void** ptr
) {
1207 GPU_CLIENT_SINGLE_THREAD_CHECK();
1208 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1209 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1210 << static_cast<void*>(ptr
) << ")");
1211 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1212 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1213 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1214 typedef cmds::GetVertexAttribPointerv::Result Result
;
1215 Result
* result
= GetResultAs
<Result
*>();
1219 result
->SetNumResults(0);
1220 helper_
->GetVertexAttribPointerv(
1221 index
, pname
, GetResultShmId(), GetResultShmOffset());
1223 result
->CopyResult(ptr
);
1224 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1226 GPU_CLIENT_LOG_CODE_BLOCK({
1227 for (int32 i
= 0; i
< num_results
; ++i
) {
1228 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1234 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1235 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1236 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1239 "glDeleteProgram", "id not created by this context.");
1242 if (program
== current_program_
) {
1243 current_program_
= 0;
1248 void GLES2Implementation::DeleteProgramStub(
1249 GLsizei n
, const GLuint
* programs
) {
1251 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1252 helper_
->DeleteProgram(programs
[0]);
1255 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1256 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1257 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1260 "glDeleteShader", "id not created by this context.");
1266 void GLES2Implementation::DeleteShaderStub(
1267 GLsizei n
, const GLuint
* shaders
) {
1269 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1270 helper_
->DeleteShader(shaders
[0]);
1273 void GLES2Implementation::DeleteSyncHelper(GLsync sync
) {
1274 GLuint sync_uint
= ToGLuint(sync
);
1275 if (!GetIdHandler(id_namespaces::kSyncs
)->FreeIds(
1276 this, 1, &sync_uint
, &GLES2Implementation::DeleteSyncStub
)) {
1279 "glDeleteSync", "id not created by this context.");
1283 void GLES2Implementation::DeleteSyncStub(GLsizei n
, const GLuint
* syncs
) {
1285 helper_
->DeleteSync(syncs
[0]);
1288 GLint
GLES2Implementation::GetAttribLocationHelper(
1289 GLuint program
, const char* name
) {
1290 typedef cmds::GetAttribLocation::Result Result
;
1291 Result
* result
= GetResultAs
<Result
*>();
1296 SetBucketAsCString(kResultBucketId
, name
);
1297 helper_
->GetAttribLocation(
1298 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1300 helper_
->SetBucketSize(kResultBucketId
, 0);
1304 GLint
GLES2Implementation::GetAttribLocation(
1305 GLuint program
, const char* name
) {
1306 GPU_CLIENT_SINGLE_THREAD_CHECK();
1307 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1308 << ", " << name
<< ")");
1309 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1310 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1311 this, program
, name
);
1312 GPU_CLIENT_LOG("returned " << loc
);
1317 GLint
GLES2Implementation::GetUniformLocationHelper(
1318 GLuint program
, const char* name
) {
1319 typedef cmds::GetUniformLocation::Result Result
;
1320 Result
* result
= GetResultAs
<Result
*>();
1325 SetBucketAsCString(kResultBucketId
, name
);
1326 helper_
->GetUniformLocation(program
, kResultBucketId
,
1327 GetResultShmId(), GetResultShmOffset());
1329 helper_
->SetBucketSize(kResultBucketId
, 0);
1333 GLint
GLES2Implementation::GetUniformLocation(
1334 GLuint program
, const char* name
) {
1335 GPU_CLIENT_SINGLE_THREAD_CHECK();
1336 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1337 << ", " << name
<< ")");
1338 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1339 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1340 this, program
, name
);
1341 GPU_CLIENT_LOG("returned " << loc
);
1346 bool GLES2Implementation::GetUniformIndicesHelper(
1347 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1348 typedef cmds::GetUniformIndices::Result Result
;
1349 Result
* result
= GetResultAs
<Result
*>();
1353 result
->SetNumResults(0);
1354 if (!PackStringsToBucket(count
, names
, NULL
, "glGetUniformIndices")) {
1357 helper_
->GetUniformIndices(program
, kResultBucketId
,
1358 GetResultShmId(), GetResultShmOffset());
1360 if (result
->GetNumResults() != count
) {
1363 result
->CopyResult(indices
);
1367 void GLES2Implementation::GetUniformIndices(
1368 GLuint program
, GLsizei count
, const char* const* names
, GLuint
* indices
) {
1369 GPU_CLIENT_SINGLE_THREAD_CHECK();
1370 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
1371 << ", " << count
<< ", " << names
<< ", " << indices
<< ")");
1372 TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
1374 SetGLError(GL_INVALID_VALUE
, "glGetUniformIndices", "count < 0");
1380 bool success
= share_group_
->program_info_manager()->GetUniformIndices(
1381 this, program
, count
, names
, indices
);
1383 GPU_CLIENT_LOG_CODE_BLOCK({
1384 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1385 GPU_CLIENT_LOG(" " << ii
<< ": " << indices
[ii
]);
1392 bool GLES2Implementation::GetProgramivHelper(
1393 GLuint program
, GLenum pname
, GLint
* params
) {
1394 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1395 this, program
, pname
, params
);
1396 GPU_CLIENT_LOG_CODE_BLOCK({
1398 GPU_CLIENT_LOG(" 0: " << *params
);
1404 GLint
GLES2Implementation::GetFragDataLocationHelper(
1405 GLuint program
, const char* name
) {
1406 typedef cmds::GetFragDataLocation::Result Result
;
1407 Result
* result
= GetResultAs
<Result
*>();
1412 SetBucketAsCString(kResultBucketId
, name
);
1413 helper_
->GetFragDataLocation(
1414 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1416 helper_
->SetBucketSize(kResultBucketId
, 0);
1420 GLint
GLES2Implementation::GetFragDataLocation(
1421 GLuint program
, const char* name
) {
1422 GPU_CLIENT_SINGLE_THREAD_CHECK();
1423 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation("
1424 << program
<< ", " << name
<< ")");
1425 TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation");
1426 GLint loc
= share_group_
->program_info_manager()->GetFragDataLocation(
1427 this, program
, name
);
1428 GPU_CLIENT_LOG("returned " << loc
);
1433 GLuint
GLES2Implementation::GetUniformBlockIndexHelper(
1434 GLuint program
, const char* name
) {
1435 typedef cmds::GetUniformBlockIndex::Result Result
;
1436 Result
* result
= GetResultAs
<Result
*>();
1438 return GL_INVALID_INDEX
;
1440 *result
= GL_INVALID_INDEX
;
1441 SetBucketAsCString(kResultBucketId
, name
);
1442 helper_
->GetUniformBlockIndex(
1443 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1445 helper_
->SetBucketSize(kResultBucketId
, 0);
1449 GLuint
GLES2Implementation::GetUniformBlockIndex(
1450 GLuint program
, const char* name
) {
1451 GPU_CLIENT_SINGLE_THREAD_CHECK();
1452 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformBlockIndex("
1453 << program
<< ", " << name
<< ")");
1454 TRACE_EVENT0("gpu", "GLES2::GetUniformBlockIndex");
1455 GLuint index
= share_group_
->program_info_manager()->GetUniformBlockIndex(
1456 this, program
, name
);
1457 GPU_CLIENT_LOG("returned " << index
);
1462 void GLES2Implementation::LinkProgram(GLuint program
) {
1463 GPU_CLIENT_SINGLE_THREAD_CHECK();
1464 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1465 helper_
->LinkProgram(program
);
1466 share_group_
->program_info_manager()->CreateInfo(program
);
1470 void GLES2Implementation::ShaderBinary(
1471 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1473 GPU_CLIENT_SINGLE_THREAD_CHECK();
1474 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1475 << static_cast<const void*>(shaders
) << ", "
1476 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1477 << static_cast<const void*>(binary
) << ", "
1480 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1484 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1487 // TODO(gman): ShaderBinary should use buckets.
1488 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1489 ScopedTransferBufferArray
<GLint
> buffer(
1490 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1491 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1492 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1495 void* shader_ids
= buffer
.elements();
1496 void* shader_data
= buffer
.elements() + shader_id_size
;
1497 memcpy(shader_ids
, shaders
, shader_id_size
);
1498 memcpy(shader_data
, binary
, length
);
1499 helper_
->ShaderBinary(
1505 buffer
.offset() + shader_id_size
,
1510 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1511 GPU_CLIENT_SINGLE_THREAD_CHECK();
1512 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1513 << GLES2Util::GetStringPixelStore(pname
) << ", "
1516 case GL_PACK_ALIGNMENT
:
1517 pack_alignment_
= param
;
1519 case GL_UNPACK_ALIGNMENT
:
1520 unpack_alignment_
= param
;
1522 case GL_UNPACK_ROW_LENGTH_EXT
:
1523 unpack_row_length_
= param
;
1525 case GL_UNPACK_IMAGE_HEIGHT
:
1526 unpack_image_height_
= param
;
1528 case GL_UNPACK_SKIP_ROWS_EXT
:
1529 unpack_skip_rows_
= param
;
1531 case GL_UNPACK_SKIP_PIXELS_EXT
:
1532 unpack_skip_pixels_
= param
;
1534 case GL_UNPACK_SKIP_IMAGES
:
1535 unpack_skip_images_
= param
;
1537 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1538 unpack_flip_y_
= (param
!= 0);
1540 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1541 pack_reverse_row_order_
=
1542 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1547 helper_
->PixelStorei(pname
, param
);
1551 void GLES2Implementation::VertexAttribIPointer(
1552 GLuint index
, GLint size
, GLenum type
, GLsizei stride
, const void* ptr
) {
1553 GPU_CLIENT_SINGLE_THREAD_CHECK();
1554 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer("
1557 << GLES2Util::GetStringVertexAttribIType(type
) << ", "
1560 // Record the info on the client side.
1561 if (!vertex_array_object_manager_
->SetAttribPointer(
1562 bound_array_buffer_id_
, index
, size
, type
, GL_FALSE
, stride
, ptr
)) {
1563 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribIPointer",
1564 "client side arrays are not allowed in vertex array objects.");
1567 if (!support_client_side_arrays_
|| bound_array_buffer_id_
!= 0) {
1568 // Only report NON client side buffers to the service.
1569 if (!ValidateOffset("glVertexAttribIPointer",
1570 reinterpret_cast<GLintptr
>(ptr
))) {
1573 helper_
->VertexAttribIPointer(index
, size
, type
, stride
, ToGLuint(ptr
));
1578 void GLES2Implementation::VertexAttribPointer(
1579 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1581 GPU_CLIENT_SINGLE_THREAD_CHECK();
1582 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1585 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1586 << GLES2Util::GetStringBool(normalized
) << ", "
1589 // Record the info on the client side.
1590 if (!vertex_array_object_manager_
->SetAttribPointer(
1591 bound_array_buffer_id_
, index
, size
, type
, normalized
, stride
, ptr
)) {
1592 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1593 "client side arrays are not allowed in vertex array objects.");
1596 if (!support_client_side_arrays_
|| bound_array_buffer_id_
!= 0) {
1597 // Only report NON client side buffers to the service.
1598 if (!ValidateOffset("glVertexAttribPointer",
1599 reinterpret_cast<GLintptr
>(ptr
))) {
1602 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1608 void GLES2Implementation::VertexAttribDivisorANGLE(
1609 GLuint index
, GLuint divisor
) {
1610 GPU_CLIENT_SINGLE_THREAD_CHECK();
1611 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1613 << divisor
<< ") ");
1614 // Record the info on the client side.
1615 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1616 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1620 void GLES2Implementation::BufferDataHelper(
1621 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1622 if (!ValidateSize("glBufferData", size
))
1625 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
1626 // Do not upload uninitialized data. Even if it's not a bug, it can cause a
1627 // bogus MSan report during a readback later. This is because MSan doesn't
1628 // understand shared memory and would assume we were reading back the same
1629 // unintialized data.
1630 if (data
) __msan_check_mem_is_initialized(data
, size
);
1634 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1639 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1641 RemoveTransferBuffer(buffer
);
1643 // Create new buffer.
1644 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1646 if (buffer
->address() && data
)
1647 memcpy(buffer
->address(), data
, size
);
1651 RemoveMappedBufferRangeByTarget(target
);
1653 // If there is no data just send BufferData
1654 if (size
== 0 || !data
) {
1655 helper_
->BufferData(target
, size
, 0, 0, usage
);
1659 // See if we can send all at once.
1660 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1661 if (!buffer
.valid()) {
1665 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1666 memcpy(buffer
.address(), data
, size
);
1667 helper_
->BufferData(
1676 // Make the buffer with BufferData then send via BufferSubData
1677 helper_
->BufferData(target
, size
, 0, 0, usage
);
1678 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1682 void GLES2Implementation::BufferData(
1683 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1684 GPU_CLIENT_SINGLE_THREAD_CHECK();
1685 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1686 << GLES2Util::GetStringBufferTarget(target
) << ", "
1688 << static_cast<const void*>(data
) << ", "
1689 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1690 BufferDataHelper(target
, size
, data
, usage
);
1694 void GLES2Implementation::BufferSubDataHelper(
1695 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1700 if (!ValidateSize("glBufferSubData", size
) ||
1701 !ValidateOffset("glBufferSubData", offset
)) {
1706 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1710 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1712 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1717 int32 buffer_size
= buffer
->size();
1718 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1719 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1723 if (buffer
->address() && data
)
1724 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1728 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1729 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1732 void GLES2Implementation::BufferSubDataHelperImpl(
1733 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1734 ScopedTransferBufferPtr
* buffer
) {
1738 const int8
* source
= static_cast<const int8
*>(data
);
1740 if (!buffer
->valid() || buffer
->size() == 0) {
1741 buffer
->Reset(size
);
1742 if (!buffer
->valid()) {
1746 memcpy(buffer
->address(), source
, buffer
->size());
1747 helper_
->BufferSubData(
1748 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1749 offset
+= buffer
->size();
1750 source
+= buffer
->size();
1751 size
-= buffer
->size();
1756 void GLES2Implementation::BufferSubData(
1757 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1758 GPU_CLIENT_SINGLE_THREAD_CHECK();
1759 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1760 << GLES2Util::GetStringBufferTarget(target
) << ", "
1761 << offset
<< ", " << size
<< ", "
1762 << static_cast<const void*>(data
) << ")");
1763 BufferSubDataHelper(target
, offset
, size
, data
);
1767 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer
* buffer
) {
1768 int32 token
= buffer
->last_usage_token();
1769 uint32 async_token
= buffer
->last_async_upload_token();
1772 if (HasAsyncUploadTokenPassed(async_token
)) {
1773 buffer_tracker_
->Free(buffer
);
1775 detached_async_upload_memory_
.push_back(
1776 std::make_pair(buffer
->address(), async_token
));
1777 buffer_tracker_
->Unmanage(buffer
);
1780 if (helper_
->HasTokenPassed(token
))
1781 buffer_tracker_
->Free(buffer
);
1783 buffer_tracker_
->FreePendingToken(buffer
, token
);
1785 buffer_tracker_
->Free(buffer
);
1788 buffer_tracker_
->RemoveBuffer(buffer
->id());
1791 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1793 const char* function_name
,
1794 GLuint
* buffer_id
) {
1798 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1799 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1801 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1802 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1809 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1814 BufferTracker::Buffer
*
1815 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1817 const char* function_name
,
1818 GLuint offset
, GLsizei size
) {
1820 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1822 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1825 if (buffer
->mapped()) {
1826 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1829 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1830 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1836 void GLES2Implementation::CompressedTexImage2D(
1837 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1838 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1839 GPU_CLIENT_SINGLE_THREAD_CHECK();
1840 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1841 << GLES2Util::GetStringTextureTarget(target
) << ", "
1843 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1844 << width
<< ", " << height
<< ", " << border
<< ", "
1845 << image_size
<< ", "
1846 << static_cast<const void*>(data
) << ")");
1847 if (width
< 0 || height
< 0 || level
< 0) {
1848 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1852 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "border != 0");
1855 if (height
== 0 || width
== 0) {
1858 // If there's a pixel unpack buffer bound use it when issuing
1859 // CompressedTexImage2D.
1860 if (bound_pixel_unpack_transfer_buffer_id_
) {
1861 GLuint offset
= ToGLuint(data
);
1862 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1863 bound_pixel_unpack_transfer_buffer_id_
,
1864 "glCompressedTexImage2D", offset
, image_size
);
1865 if (buffer
&& buffer
->shm_id() != -1) {
1866 helper_
->CompressedTexImage2D(
1867 target
, level
, internalformat
, width
, height
, image_size
,
1868 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1869 buffer
->set_last_usage_token(helper_
->InsertToken());
1873 SetBucketContents(kResultBucketId
, data
, image_size
);
1874 helper_
->CompressedTexImage2DBucket(
1875 target
, level
, internalformat
, width
, height
, kResultBucketId
);
1876 // Free the bucket. This is not required but it does free up the memory.
1877 // and we don't have to wait for the result so from the client's perspective
1879 helper_
->SetBucketSize(kResultBucketId
, 0);
1883 void GLES2Implementation::CompressedTexSubImage2D(
1884 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1885 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1886 GPU_CLIENT_SINGLE_THREAD_CHECK();
1887 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1888 << GLES2Util::GetStringTextureTarget(target
) << ", "
1890 << xoffset
<< ", " << yoffset
<< ", "
1891 << width
<< ", " << height
<< ", "
1892 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1893 << image_size
<< ", "
1894 << static_cast<const void*>(data
) << ")");
1895 if (width
< 0 || height
< 0 || level
< 0) {
1896 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1899 // If there's a pixel unpack buffer bound use it when issuing
1900 // CompressedTexSubImage2D.
1901 if (bound_pixel_unpack_transfer_buffer_id_
) {
1902 GLuint offset
= ToGLuint(data
);
1903 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1904 bound_pixel_unpack_transfer_buffer_id_
,
1905 "glCompressedTexSubImage2D", offset
, image_size
);
1906 if (buffer
&& buffer
->shm_id() != -1) {
1907 helper_
->CompressedTexSubImage2D(
1908 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1909 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1910 buffer
->set_last_usage_token(helper_
->InsertToken());
1915 SetBucketContents(kResultBucketId
, data
, image_size
);
1916 helper_
->CompressedTexSubImage2DBucket(
1917 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1918 // Free the bucket. This is not required but it does free up the memory.
1919 // and we don't have to wait for the result so from the client's perspective
1921 helper_
->SetBucketSize(kResultBucketId
, 0);
1925 void GLES2Implementation::CompressedTexImage3D(
1926 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1927 GLsizei height
, GLsizei depth
, GLint border
, GLsizei image_size
,
1929 GPU_CLIENT_SINGLE_THREAD_CHECK();
1930 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage3D("
1931 << GLES2Util::GetStringTexture3DTarget(target
) << ", " << level
<< ", "
1932 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1933 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
1934 << image_size
<< ", " << static_cast<const void*>(data
) << ")");
1935 if (width
< 0 || height
< 0 || depth
< 0 || level
< 0) {
1936 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "dimension < 0");
1940 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage3D", "border != 0");
1943 if (height
== 0 || width
== 0 || depth
== 0) {
1946 // If there's a pixel unpack buffer bound use it when issuing
1947 // CompressedTexImage3D.
1948 if (bound_pixel_unpack_transfer_buffer_id_
) {
1949 GLuint offset
= ToGLuint(data
);
1950 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1951 bound_pixel_unpack_transfer_buffer_id_
,
1952 "glCompressedTexImage3D", offset
, image_size
);
1953 if (buffer
&& buffer
->shm_id() != -1) {
1954 helper_
->CompressedTexImage3D(
1955 target
, level
, internalformat
, width
, height
, depth
, image_size
,
1956 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1957 buffer
->set_last_usage_token(helper_
->InsertToken());
1961 SetBucketContents(kResultBucketId
, data
, image_size
);
1962 helper_
->CompressedTexImage3DBucket(
1963 target
, level
, internalformat
, width
, height
, depth
, kResultBucketId
);
1964 // Free the bucket. This is not required but it does free up the memory.
1965 // and we don't have to wait for the result so from the client's perspective
1967 helper_
->SetBucketSize(kResultBucketId
, 0);
1973 void CopyRectToBuffer(
1976 uint32 unpadded_row_size
,
1977 uint32 pixels_padded_row_size
,
1980 uint32 buffer_padded_row_size
) {
1981 const int8
* source
= static_cast<const int8
*>(pixels
);
1982 int8
* dest
= static_cast<int8
*>(buffer
);
1983 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
1985 dest
+= buffer_padded_row_size
* (height
- 1);
1987 // the last row is copied unpadded at the end
1988 for (; height
> 1; --height
) {
1989 memcpy(dest
, source
, buffer_padded_row_size
);
1991 dest
-= buffer_padded_row_size
;
1993 dest
+= buffer_padded_row_size
;
1995 source
+= pixels_padded_row_size
;
1997 memcpy(dest
, source
, unpadded_row_size
);
1999 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
2000 memcpy(dest
, source
, size
);
2004 } // anonymous namespace
2006 void GLES2Implementation::TexImage2D(
2007 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2008 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
2009 const void* pixels
) {
2010 GPU_CLIENT_SINGLE_THREAD_CHECK();
2011 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
2012 << GLES2Util::GetStringTextureTarget(target
) << ", "
2014 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2015 << width
<< ", " << height
<< ", " << border
<< ", "
2016 << GLES2Util::GetStringTextureFormat(format
) << ", "
2017 << GLES2Util::GetStringPixelType(type
) << ", "
2018 << static_cast<const void*>(pixels
) << ")");
2019 if (level
< 0 || height
< 0 || width
< 0) {
2020 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
2024 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
2028 uint32 unpadded_row_size
;
2029 uint32 padded_row_size
;
2030 if (!GLES2Util::ComputeImageDataSizes(
2031 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
2032 &unpadded_row_size
, &padded_row_size
)) {
2033 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
2037 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
2038 if (bound_pixel_unpack_transfer_buffer_id_
) {
2039 GLuint offset
= ToGLuint(pixels
);
2040 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2041 bound_pixel_unpack_transfer_buffer_id_
,
2042 "glTexImage2D", offset
, size
);
2043 if (buffer
&& buffer
->shm_id() != -1) {
2044 helper_
->TexImage2D(
2045 target
, level
, internalformat
, width
, height
, format
, type
,
2046 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2047 buffer
->set_last_usage_token(helper_
->InsertToken());
2053 // If there's no data just issue TexImage2D
2055 helper_
->TexImage2D(
2056 target
, level
, internalformat
, width
, height
, format
, type
,
2062 // compute the advance bytes per row for the src pixels
2063 uint32 src_padded_row_size
;
2064 if (unpack_row_length_
> 0) {
2065 if (!GLES2Util::ComputeImagePaddedRowSize(
2066 unpack_row_length_
, format
, type
, unpack_alignment_
,
2067 &src_padded_row_size
)) {
2069 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2073 src_padded_row_size
= padded_row_size
;
2076 // advance pixels pointer past the skip rows and skip pixels
2077 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2078 unpack_skip_rows_
* src_padded_row_size
;
2079 if (unpack_skip_pixels_
) {
2080 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2081 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2082 unpack_skip_pixels_
* group_size
;
2085 // Check if we can send it all at once.
2086 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
2087 if (!buffer
.valid()) {
2091 if (buffer
.size() >= size
) {
2093 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
2094 buffer
.address(), padded_row_size
);
2095 helper_
->TexImage2D(
2096 target
, level
, internalformat
, width
, height
, format
, type
,
2097 buffer
.shm_id(), buffer
.offset());
2102 // No, so send it using TexSubImage2D.
2103 helper_
->TexImage2D(
2104 target
, level
, internalformat
, width
, height
, format
, type
,
2107 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
2108 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
2112 void GLES2Implementation::TexImage3D(
2113 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
2114 GLsizei height
, GLsizei depth
, GLint border
, GLenum format
, GLenum type
,
2115 const void* pixels
) {
2116 GPU_CLIENT_SINGLE_THREAD_CHECK();
2117 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
2118 << GLES2Util::GetStringTextureTarget(target
) << ", "
2120 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
2121 << width
<< ", " << height
<< ", " << depth
<< ", " << border
<< ", "
2122 << GLES2Util::GetStringTextureFormat(format
) << ", "
2123 << GLES2Util::GetStringPixelType(type
) << ", "
2124 << static_cast<const void*>(pixels
) << ")");
2125 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2126 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "dimension < 0");
2130 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "border != 0");
2134 uint32 unpadded_row_size
;
2135 uint32 padded_row_size
;
2136 if (!GLES2Util::ComputeImageDataSizes(
2137 width
, height
, depth
, format
, type
, unpack_alignment_
, &size
,
2138 &unpadded_row_size
, &padded_row_size
)) {
2139 SetGLError(GL_INVALID_VALUE
, "glTexImage3D", "image size too large");
2143 // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
2144 if (bound_pixel_unpack_transfer_buffer_id_
) {
2145 GLuint offset
= ToGLuint(pixels
);
2146 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2147 bound_pixel_unpack_transfer_buffer_id_
,
2148 "glTexImage3D", offset
, size
);
2149 if (buffer
&& buffer
->shm_id() != -1) {
2150 helper_
->TexImage3D(
2151 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2152 buffer
->shm_id(), buffer
->shm_offset() + offset
);
2153 buffer
->set_last_usage_token(helper_
->InsertToken());
2159 // If there's no data just issue TexImage3D
2161 helper_
->TexImage3D(
2162 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2168 // compute the advance bytes per row for the src pixels
2169 uint32 src_padded_row_size
;
2170 if (unpack_row_length_
> 0) {
2171 if (!GLES2Util::ComputeImagePaddedRowSize(
2172 unpack_row_length_
, format
, type
, unpack_alignment_
,
2173 &src_padded_row_size
)) {
2175 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2179 src_padded_row_size
= padded_row_size
;
2181 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2183 // advance pixels pointer past the skip images/rows/pixels
2184 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2185 unpack_skip_images_
* src_padded_row_size
* src_height
+
2186 unpack_skip_rows_
* src_padded_row_size
;
2187 if (unpack_skip_pixels_
) {
2188 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2189 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2190 unpack_skip_pixels_
* group_size
;
2193 // Check if we can send it all at once.
2194 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
2195 if (!buffer
.valid()) {
2199 if (buffer
.size() >= size
) {
2200 void* buffer_pointer
= buffer
.address();
2201 for (GLsizei z
= 0; z
< depth
; ++z
) {
2202 // Only the last row of the last image is unpadded.
2203 uint32 src_unpadded_row_size
=
2204 (z
== depth
- 1) ? unpadded_row_size
: src_padded_row_size
;
2205 // TODO(zmo): Ignore flip_y flag for now.
2207 pixels
, height
, src_unpadded_row_size
, src_padded_row_size
, false,
2208 buffer_pointer
, padded_row_size
);
2209 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2210 src_padded_row_size
* src_height
;
2211 buffer_pointer
= reinterpret_cast<int8
*>(buffer_pointer
) +
2212 padded_row_size
* height
;
2214 helper_
->TexImage3D(
2215 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2216 buffer
.shm_id(), buffer
.offset());
2221 // No, so send it using TexSubImage3D.
2222 helper_
->TexImage3D(
2223 target
, level
, internalformat
, width
, height
, depth
, format
, type
,
2226 target
, level
, 0, 0, 0, width
, height
, depth
, format
, type
,
2227 unpadded_row_size
, pixels
, src_padded_row_size
, GL_TRUE
, &buffer
,
2232 void GLES2Implementation::TexSubImage2D(
2233 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2234 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
2235 GPU_CLIENT_SINGLE_THREAD_CHECK();
2236 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
2237 << GLES2Util::GetStringTextureTarget(target
) << ", "
2239 << xoffset
<< ", " << yoffset
<< ", "
2240 << width
<< ", " << height
<< ", "
2241 << GLES2Util::GetStringTextureFormat(format
) << ", "
2242 << GLES2Util::GetStringPixelType(type
) << ", "
2243 << static_cast<const void*>(pixels
) << ")");
2245 if (level
< 0 || height
< 0 || width
< 0) {
2246 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
2249 if (height
== 0 || width
== 0) {
2254 uint32 unpadded_row_size
;
2255 uint32 padded_row_size
;
2256 if (!GLES2Util::ComputeImageDataSizes(
2257 width
, height
, 1, format
, type
, unpack_alignment_
, &temp_size
,
2258 &unpadded_row_size
, &padded_row_size
)) {
2259 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
2263 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2264 if (bound_pixel_unpack_transfer_buffer_id_
) {
2265 GLuint offset
= ToGLuint(pixels
);
2266 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2267 bound_pixel_unpack_transfer_buffer_id_
,
2268 "glTexSubImage2D", offset
, temp_size
);
2269 if (buffer
&& buffer
->shm_id() != -1) {
2270 helper_
->TexSubImage2D(
2271 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2272 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2273 buffer
->set_last_usage_token(helper_
->InsertToken());
2279 // compute the advance bytes per row for the src pixels
2280 uint32 src_padded_row_size
;
2281 if (unpack_row_length_
> 0) {
2282 if (!GLES2Util::ComputeImagePaddedRowSize(
2283 unpack_row_length_
, format
, type
, unpack_alignment_
,
2284 &src_padded_row_size
)) {
2286 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
2290 src_padded_row_size
= padded_row_size
;
2293 // advance pixels pointer past the skip rows and skip pixels
2294 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2295 unpack_skip_rows_
* src_padded_row_size
;
2296 if (unpack_skip_pixels_
) {
2297 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2298 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2299 unpack_skip_pixels_
* group_size
;
2302 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2304 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
2305 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
2310 void GLES2Implementation::TexSubImage3D(
2311 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
2312 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2313 const void* pixels
) {
2314 GPU_CLIENT_SINGLE_THREAD_CHECK();
2315 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
2316 << GLES2Util::GetStringTextureTarget(target
) << ", "
2318 << xoffset
<< ", " << yoffset
<< ", " << zoffset
<< ", "
2319 << width
<< ", " << height
<< ", " << depth
<< ", "
2320 << GLES2Util::GetStringTextureFormat(format
) << ", "
2321 << GLES2Util::GetStringPixelType(type
) << ", "
2322 << static_cast<const void*>(pixels
) << ")");
2324 if (level
< 0 || height
< 0 || width
< 0 || depth
< 0) {
2325 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "dimension < 0");
2328 if (height
== 0 || width
== 0 || depth
== 0) {
2333 uint32 unpadded_row_size
;
2334 uint32 padded_row_size
;
2335 if (!GLES2Util::ComputeImageDataSizes(
2336 width
, height
, depth
, format
, type
, unpack_alignment_
, &temp_size
,
2337 &unpadded_row_size
, &padded_row_size
)) {
2338 SetGLError(GL_INVALID_VALUE
, "glTexSubImage3D", "size to large");
2342 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
2343 if (bound_pixel_unpack_transfer_buffer_id_
) {
2344 GLuint offset
= ToGLuint(pixels
);
2345 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2346 bound_pixel_unpack_transfer_buffer_id_
,
2347 "glTexSubImage3D", offset
, temp_size
);
2348 if (buffer
&& buffer
->shm_id() != -1) {
2349 helper_
->TexSubImage3D(
2350 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2351 format
, type
, buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
2352 buffer
->set_last_usage_token(helper_
->InsertToken());
2358 // compute the advance bytes per row for the src pixels
2359 uint32 src_padded_row_size
;
2360 if (unpack_row_length_
> 0) {
2361 if (!GLES2Util::ComputeImagePaddedRowSize(
2362 unpack_row_length_
, format
, type
, unpack_alignment_
,
2363 &src_padded_row_size
)) {
2365 GL_INVALID_VALUE
, "glTexImage3D", "unpack row length too large");
2369 src_padded_row_size
= padded_row_size
;
2371 uint32 src_height
= unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2373 // advance pixels pointer past the skip images/rows/pixels
2374 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2375 unpack_skip_images_
* src_padded_row_size
* src_height
+
2376 unpack_skip_rows_
* src_padded_row_size
;
2377 if (unpack_skip_pixels_
) {
2378 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
2379 pixels
= reinterpret_cast<const int8
*>(pixels
) +
2380 unpack_skip_pixels_
* group_size
;
2383 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
2385 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
,
2386 format
, type
, unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
,
2387 &buffer
, padded_row_size
);
2391 static GLint
ComputeNumRowsThatFitInBuffer(
2392 uint32 padded_row_size
, uint32 unpadded_row_size
,
2393 unsigned int size
, GLsizei remaining_rows
) {
2394 DCHECK_GE(unpadded_row_size
, 0u);
2395 if (padded_row_size
== 0) {
2398 GLint num_rows
= size
/ padded_row_size
;
2399 if (num_rows
+ 1 == remaining_rows
&&
2400 size
- num_rows
* padded_row_size
>= unpadded_row_size
) {
2406 void GLES2Implementation::TexSubImage2DImpl(
2407 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
2408 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
2409 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
2410 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
2412 DCHECK_GE(level
, 0);
2413 DCHECK_GT(height
, 0);
2414 DCHECK_GT(width
, 0);
2416 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2417 GLint original_yoffset
= yoffset
;
2418 // Transfer by rows.
2420 unsigned int desired_size
=
2421 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
2422 if (!buffer
->valid() || buffer
->size() == 0) {
2423 buffer
->Reset(desired_size
);
2424 if (!buffer
->valid()) {
2429 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2430 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), height
);
2431 num_rows
= std::min(num_rows
, height
);
2433 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
2434 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
2435 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
2436 helper_
->TexSubImage2D(
2437 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
2438 buffer
->shm_id(), buffer
->offset(), internal
);
2440 yoffset
+= num_rows
;
2441 source
+= num_rows
* pixels_padded_row_size
;
2446 void GLES2Implementation::TexSubImage3DImpl(
2447 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei zoffset
,
2448 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
, GLenum type
,
2449 uint32 unpadded_row_size
, const void* pixels
, uint32 pixels_padded_row_size
,
2450 GLboolean internal
, ScopedTransferBufferPtr
* buffer
,
2451 uint32 buffer_padded_row_size
) {
2453 DCHECK_GE(level
, 0);
2454 DCHECK_GT(height
, 0);
2455 DCHECK_GT(width
, 0);
2456 DCHECK_GT(depth
, 0);
2457 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
2458 GLsizei total_rows
= height
* depth
;
2459 GLint row_index
= 0, depth_index
= 0;
2460 while (total_rows
) {
2461 // Each time, we either copy one or more images, or copy one or more rows
2462 // within a single image, depending on the buffer size limit.
2464 unsigned int desired_size
;
2465 if (row_index
> 0) {
2466 // We are in the middle of an image. Send the remaining of the image.
2467 max_rows
= height
- row_index
;
2468 if (total_rows
<= height
) {
2469 // Last image, so last row is unpadded.
2470 desired_size
= buffer_padded_row_size
* (max_rows
- 1) +
2473 desired_size
= buffer_padded_row_size
* max_rows
;
2476 // Send all the remaining data if possible.
2477 max_rows
= total_rows
;
2479 buffer_padded_row_size
* (max_rows
- 1) + unpadded_row_size
;
2481 if (!buffer
->valid() || buffer
->size() == 0) {
2482 buffer
->Reset(desired_size
);
2483 if (!buffer
->valid()) {
2487 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2488 buffer_padded_row_size
, unpadded_row_size
, buffer
->size(), total_rows
);
2489 num_rows
= std::min(num_rows
, max_rows
);
2490 GLint num_images
= num_rows
/ height
;
2491 GLsizei my_height
, my_depth
;
2492 if (num_images
> 0) {
2493 num_rows
= num_images
* height
;
2495 my_depth
= num_images
;
2497 my_height
= num_rows
;
2501 // TODO(zmo): Ignore flip_y flag for now.
2502 if (num_images
> 0) {
2503 int8
* buffer_pointer
= reinterpret_cast<int8
*>(buffer
->address());
2505 unpack_image_height_
> 0 ? unpack_image_height_
: height
;
2506 uint32 image_size_dst
= buffer_padded_row_size
* height
;
2507 uint32 image_size_src
= pixels_padded_row_size
* src_height
;
2508 for (GLint ii
= 0; ii
< num_images
; ++ii
) {
2509 uint32 my_unpadded_row_size
;
2510 if (total_rows
== num_rows
&& ii
+ 1 == num_images
)
2511 my_unpadded_row_size
= unpadded_row_size
;
2513 my_unpadded_row_size
= pixels_padded_row_size
;
2515 source
+ ii
* image_size_src
, my_height
, my_unpadded_row_size
,
2516 pixels_padded_row_size
, false, buffer_pointer
+ ii
* image_size_dst
,
2517 buffer_padded_row_size
);
2520 uint32 my_unpadded_row_size
;
2521 if (total_rows
== num_rows
)
2522 my_unpadded_row_size
= unpadded_row_size
;
2524 my_unpadded_row_size
= pixels_padded_row_size
;
2526 source
, my_height
, my_unpadded_row_size
, pixels_padded_row_size
,
2527 false, buffer
->address(), buffer_padded_row_size
);
2529 helper_
->TexSubImage3D(
2530 target
, level
, xoffset
, yoffset
+ row_index
, zoffset
+ depth_index
,
2531 width
, my_height
, my_depth
,
2532 format
, type
, buffer
->shm_id(), buffer
->offset(), internal
);
2535 total_rows
-= num_rows
;
2536 if (total_rows
> 0) {
2537 GLint num_image_paddings
;
2538 if (num_images
> 0) {
2539 DCHECK_EQ(row_index
, 0);
2540 depth_index
+= num_images
;
2541 num_image_paddings
= num_images
;
2543 row_index
= (row_index
+ my_height
) % height
;
2544 num_image_paddings
= 0;
2545 if (my_height
> 0 && row_index
== 0) {
2547 num_image_paddings
++;
2550 source
+= num_rows
* pixels_padded_row_size
;
2551 if (unpack_image_height_
> height
&& num_image_paddings
> 0) {
2552 source
+= num_image_paddings
* (unpack_image_height_
- height
) *
2553 pixels_padded_row_size
;
2559 bool GLES2Implementation::GetActiveAttribHelper(
2560 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2561 GLenum
* type
, char* name
) {
2562 // Clear the bucket so if the command fails nothing will be in it.
2563 helper_
->SetBucketSize(kResultBucketId
, 0);
2564 typedef cmds::GetActiveAttrib::Result Result
;
2565 Result
* result
= GetResultAs
<Result
*>();
2569 // Set as failed so if the command fails we'll recover.
2570 result
->success
= false;
2571 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
2572 GetResultShmId(), GetResultShmOffset());
2574 if (result
->success
) {
2576 *size
= result
->size
;
2579 *type
= result
->type
;
2581 if (length
|| name
) {
2582 std::vector
<int8
> str
;
2583 GetBucketContents(kResultBucketId
, &str
);
2584 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2585 std::max(static_cast<size_t>(0),
2590 if (name
&& bufsize
> 0) {
2591 memcpy(name
, &str
[0], max_size
);
2592 name
[max_size
] = '\0';
2596 return result
->success
!= 0;
2599 void GLES2Implementation::GetActiveAttrib(
2600 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2601 GLenum
* type
, char* name
) {
2602 GPU_CLIENT_SINGLE_THREAD_CHECK();
2603 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
2604 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2605 << static_cast<const void*>(length
) << ", "
2606 << static_cast<const void*>(size
) << ", "
2607 << static_cast<const void*>(type
) << ", "
2608 << static_cast<const void*>(name
) << ", ");
2610 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
2613 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
2614 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
2615 this, program
, index
, bufsize
, length
, size
, type
, name
);
2618 GPU_CLIENT_LOG(" size: " << *size
);
2621 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2624 GPU_CLIENT_LOG(" name: " << name
);
2630 bool GLES2Implementation::GetActiveUniformHelper(
2631 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2632 GLenum
* type
, char* name
) {
2633 // Clear the bucket so if the command fails nothing will be in it.
2634 helper_
->SetBucketSize(kResultBucketId
, 0);
2635 typedef cmds::GetActiveUniform::Result Result
;
2636 Result
* result
= GetResultAs
<Result
*>();
2640 // Set as failed so if the command fails we'll recover.
2641 result
->success
= false;
2642 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
2643 GetResultShmId(), GetResultShmOffset());
2645 if (result
->success
) {
2647 *size
= result
->size
;
2650 *type
= result
->type
;
2652 if (length
|| name
) {
2653 std::vector
<int8
> str
;
2654 GetBucketContents(kResultBucketId
, &str
);
2655 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2656 std::max(static_cast<size_t>(0),
2661 if (name
&& bufsize
> 0) {
2662 memcpy(name
, &str
[0], max_size
);
2663 name
[max_size
] = '\0';
2667 return result
->success
!= 0;
2670 void GLES2Implementation::GetActiveUniform(
2671 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2672 GLenum
* type
, char* name
) {
2673 GPU_CLIENT_SINGLE_THREAD_CHECK();
2674 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2675 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2676 << static_cast<const void*>(length
) << ", "
2677 << static_cast<const void*>(size
) << ", "
2678 << static_cast<const void*>(type
) << ", "
2679 << static_cast<const void*>(name
) << ", ");
2681 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2684 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2685 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2686 this, program
, index
, bufsize
, length
, size
, type
, name
);
2689 GPU_CLIENT_LOG(" size: " << *size
);
2692 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2695 GPU_CLIENT_LOG(" name: " << name
);
2701 bool GLES2Implementation::GetActiveUniformBlockNameHelper(
2702 GLuint program
, GLuint index
, GLsizei bufsize
,
2703 GLsizei
* length
, char* name
) {
2704 DCHECK_LE(0, bufsize
);
2705 // Clear the bucket so if the command fails nothing will be in it.
2706 helper_
->SetBucketSize(kResultBucketId
, 0);
2707 typedef cmds::GetActiveUniformBlockName::Result Result
;
2708 Result
* result
= GetResultAs
<Result
*>();
2712 // Set as failed so if the command fails we'll recover.
2714 helper_
->GetActiveUniformBlockName(program
, index
, kResultBucketId
,
2715 GetResultShmId(), GetResultShmOffset());
2722 } else if (length
|| name
) {
2723 std::vector
<int8
> str
;
2724 GetBucketContents(kResultBucketId
, &str
);
2725 DCHECK_GT(str
.size(), 0u);
2727 std::min(bufsize
, static_cast<GLsizei
>(str
.size())) - 1;
2732 memcpy(name
, &str
[0], max_size
);
2733 name
[max_size
] = '\0';
2737 return *result
!= 0;
2740 void GLES2Implementation::GetActiveUniformBlockName(
2741 GLuint program
, GLuint index
, GLsizei bufsize
,
2742 GLsizei
* length
, char* name
) {
2743 GPU_CLIENT_SINGLE_THREAD_CHECK();
2744 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
2745 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2746 << static_cast<const void*>(length
) << ", "
2747 << static_cast<const void*>(name
) << ")");
2749 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformBlockName", "bufsize < 0");
2752 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockName");
2754 share_group_
->program_info_manager()->GetActiveUniformBlockName(
2755 this, program
, index
, bufsize
, length
, name
);
2758 GPU_CLIENT_LOG(" name: " << name
);
2764 bool GLES2Implementation::GetActiveUniformBlockivHelper(
2765 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2766 typedef cmds::GetActiveUniformBlockiv::Result Result
;
2767 Result
* result
= GetResultAs
<Result
*>();
2771 result
->SetNumResults(0);
2772 helper_
->GetActiveUniformBlockiv(
2773 program
, index
, pname
, GetResultShmId(), GetResultShmOffset());
2775 if (result
->GetNumResults() > 0) {
2777 result
->CopyResult(params
);
2779 GPU_CLIENT_LOG_CODE_BLOCK({
2780 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2781 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2789 void GLES2Implementation::GetActiveUniformBlockiv(
2790 GLuint program
, GLuint index
, GLenum pname
, GLint
* params
) {
2791 GPU_CLIENT_SINGLE_THREAD_CHECK();
2792 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
2793 << program
<< ", " << index
<< ", "
2794 << GLES2Util::GetStringUniformBlockParameter(pname
) << ", "
2795 << static_cast<const void*>(params
) << ")");
2796 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
2798 share_group_
->program_info_manager()->GetActiveUniformBlockiv(
2799 this, program
, index
, pname
, params
);
2802 // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
2803 // be more than one value returned in params.
2804 GPU_CLIENT_LOG(" params: " << params
[0]);
2810 bool GLES2Implementation::GetActiveUniformsivHelper(
2811 GLuint program
, GLsizei count
, const GLuint
* indices
,
2812 GLenum pname
, GLint
* params
) {
2813 typedef cmds::GetActiveUniformsiv::Result Result
;
2814 Result
* result
= GetResultAs
<Result
*>();
2818 result
->SetNumResults(0);
2819 base::CheckedNumeric
<size_t> bytes
= static_cast<size_t>(count
);
2820 bytes
*= sizeof(GLuint
);
2821 if (!bytes
.IsValid()) {
2822 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count overflow");
2825 SetBucketContents(kResultBucketId
, indices
, bytes
.ValueOrDefault(0));
2826 helper_
->GetActiveUniformsiv(
2827 program
, kResultBucketId
, pname
, GetResultShmId(), GetResultShmOffset());
2829 bool success
= result
->GetNumResults() == count
;
2832 result
->CopyResult(params
);
2834 GPU_CLIENT_LOG_CODE_BLOCK({
2835 for (int32_t i
= 0; i
< result
->GetNumResults(); ++i
) {
2836 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2840 helper_
->SetBucketSize(kResultBucketId
, 0);
2844 void GLES2Implementation::GetActiveUniformsiv(
2845 GLuint program
, GLsizei count
, const GLuint
* indices
,
2846 GLenum pname
, GLint
* params
) {
2847 GPU_CLIENT_SINGLE_THREAD_CHECK();
2848 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
2849 << program
<< ", " << count
<< ", "
2850 << static_cast<const void*>(indices
) << ", "
2851 << GLES2Util::GetStringUniformParameter(pname
) << ", "
2852 << static_cast<const void*>(params
) << ")");
2853 TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
2855 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniformsiv", "count < 0");
2858 bool success
= share_group_
->program_info_manager()->GetActiveUniformsiv(
2859 this, program
, count
, indices
, pname
, params
);
2862 GPU_CLIENT_LOG_CODE_BLOCK({
2863 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
2864 GPU_CLIENT_LOG(" " << ii
<< ": " << params
[ii
]);
2872 void GLES2Implementation::GetAttachedShaders(
2873 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
2874 GPU_CLIENT_SINGLE_THREAD_CHECK();
2875 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
2876 << program
<< ", " << maxcount
<< ", "
2877 << static_cast<const void*>(count
) << ", "
2878 << static_cast<const void*>(shaders
) << ", ");
2880 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2883 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2884 typedef cmds::GetAttachedShaders::Result Result
;
2885 uint32 size
= Result::ComputeSize(maxcount
);
2886 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2890 result
->SetNumResults(0);
2891 helper_
->GetAttachedShaders(
2893 transfer_buffer_
->GetShmId(),
2894 transfer_buffer_
->GetOffset(result
),
2896 int32 token
= helper_
->InsertToken();
2899 *count
= result
->GetNumResults();
2901 result
->CopyResult(shaders
);
2902 GPU_CLIENT_LOG_CODE_BLOCK({
2903 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2904 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2907 transfer_buffer_
->FreePendingToken(result
, token
);
2911 void GLES2Implementation::GetShaderPrecisionFormat(
2912 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2913 GPU_CLIENT_SINGLE_THREAD_CHECK();
2914 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
2915 << GLES2Util::GetStringShaderType(shadertype
) << ", "
2916 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
2917 << static_cast<const void*>(range
) << ", "
2918 << static_cast<const void*>(precision
) << ", ");
2919 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
2920 typedef cmds::GetShaderPrecisionFormat::Result Result
;
2921 Result
* result
= GetResultAs
<Result
*>();
2926 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
2927 GLStaticState::ShaderPrecisionMap::iterator i
=
2928 static_state_
.shader_precisions
.find(key
);
2929 if (i
!= static_state_
.shader_precisions
.end()) {
2930 *result
= i
->second
;
2932 result
->success
= false;
2933 helper_
->GetShaderPrecisionFormat(
2934 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
2936 if (result
->success
)
2937 static_state_
.shader_precisions
[key
] = *result
;
2940 if (result
->success
) {
2942 range
[0] = result
->min_range
;
2943 range
[1] = result
->max_range
;
2944 GPU_CLIENT_LOG(" min_range: " << range
[0]);
2945 GPU_CLIENT_LOG(" min_range: " << range
[1]);
2948 precision
[0] = result
->precision
;
2949 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
2955 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
2956 const char* result
= NULL
;
2957 // Clears the bucket so if the command fails nothing will be in it.
2958 helper_
->SetBucketSize(kResultBucketId
, 0);
2959 helper_
->GetString(name
, kResultBucketId
);
2961 if (GetBucketAsString(kResultBucketId
, &str
)) {
2962 // Adds extensions implemented on client side only.
2965 str
+= std::string(str
.empty() ? "" : " ") +
2966 "GL_CHROMIUM_flipy "
2967 "GL_EXT_unpack_subimage "
2968 "GL_CHROMIUM_map_sub";
2969 if (capabilities_
.image
)
2970 str
+= " GL_CHROMIUM_image GL_CHROMIUM_gpu_memory_buffer_image";
2971 if (capabilities_
.future_sync_points
)
2972 str
+= " GL_CHROMIUM_future_sync_point";
2978 // Because of WebGL the extensions can change. We have to cache each unique
2979 // result since we don't know when the client will stop referring to a
2980 // previous one it queries.
2981 GLStringMap::iterator it
= gl_strings_
.find(name
);
2982 if (it
== gl_strings_
.end()) {
2983 std::set
<std::string
> strings
;
2984 std::pair
<GLStringMap::iterator
, bool> insert_result
=
2985 gl_strings_
.insert(std::make_pair(name
, strings
));
2986 DCHECK(insert_result
.second
);
2987 it
= insert_result
.first
;
2989 std::set
<std::string
>& string_set
= it
->second
;
2990 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
2991 if (sit
!= string_set
.end()) {
2992 result
= sit
->c_str();
2994 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2995 string_set
.insert(str
);
2996 DCHECK(insert_result
.second
);
2997 result
= insert_result
.first
->c_str();
3000 return reinterpret_cast<const GLubyte
*>(result
);
3003 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
3004 GPU_CLIENT_SINGLE_THREAD_CHECK();
3005 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
3006 << GLES2Util::GetStringStringType(name
) << ")");
3007 TRACE_EVENT0("gpu", "GLES2::GetString");
3008 const GLubyte
* result
= GetStringHelper(name
);
3009 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
3014 bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
3015 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3016 GLenum
* type
, char* name
) {
3017 // Clear the bucket so if the command fails nothing will be in it.
3018 helper_
->SetBucketSize(kResultBucketId
, 0);
3019 typedef cmds::GetTransformFeedbackVarying::Result Result
;
3020 Result
* result
= GetResultAs
<Result
*>();
3024 // Set as failed so if the command fails we'll recover.
3025 result
->success
= false;
3026 helper_
->GetTransformFeedbackVarying(
3027 program
, index
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3029 if (result
->success
) {
3031 *size
= result
->size
;
3034 *type
= result
->type
;
3036 if (length
|| name
) {
3037 std::vector
<int8
> str
;
3038 GetBucketContents(kResultBucketId
, &str
);
3039 GLsizei max_size
= std::min(bufsize
, static_cast<GLsizei
>(str
.size()));
3048 memcpy(name
, &str
[0], max_size
);
3049 name
[max_size
] = '\0';
3050 } else if (bufsize
> 0) {
3056 return result
->success
!= 0;
3059 void GLES2Implementation::GetTransformFeedbackVarying(
3060 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
3061 GLenum
* type
, char* name
) {
3062 GPU_CLIENT_SINGLE_THREAD_CHECK();
3063 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
3064 << program
<< ", " << index
<< ", " << bufsize
<< ", "
3065 << static_cast<const void*>(length
) << ", "
3066 << static_cast<const void*>(size
) << ", "
3067 << static_cast<const void*>(type
) << ", "
3068 << static_cast<const void*>(name
) << ", ");
3070 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVarying",
3074 TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
3076 share_group_
->program_info_manager()->GetTransformFeedbackVarying(
3077 this, program
, index
, bufsize
, length
, size
, type
, name
);
3080 GPU_CLIENT_LOG(" size: " << *size
);
3083 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
3086 GPU_CLIENT_LOG(" name: " << name
);
3092 void GLES2Implementation::GetUniformfv(
3093 GLuint program
, GLint location
, GLfloat
* params
) {
3094 GPU_CLIENT_SINGLE_THREAD_CHECK();
3095 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
3096 << program
<< ", " << location
<< ", "
3097 << static_cast<const void*>(params
) << ")");
3098 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
3099 typedef cmds::GetUniformfv::Result Result
;
3100 Result
* result
= GetResultAs
<Result
*>();
3104 result
->SetNumResults(0);
3105 helper_
->GetUniformfv(
3106 program
, location
, GetResultShmId(), GetResultShmOffset());
3108 result
->CopyResult(params
);
3109 GPU_CLIENT_LOG_CODE_BLOCK({
3110 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3111 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3117 void GLES2Implementation::GetUniformiv(
3118 GLuint program
, GLint location
, GLint
* params
) {
3119 GPU_CLIENT_SINGLE_THREAD_CHECK();
3120 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
3121 << program
<< ", " << location
<< ", "
3122 << static_cast<const void*>(params
) << ")");
3123 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
3124 typedef cmds::GetUniformiv::Result Result
;
3125 Result
* result
= GetResultAs
<Result
*>();
3129 result
->SetNumResults(0);
3130 helper_
->GetUniformiv(
3131 program
, location
, GetResultShmId(), GetResultShmOffset());
3133 GetResultAs
<cmds::GetUniformfv::Result
*>()->CopyResult(params
);
3134 GPU_CLIENT_LOG_CODE_BLOCK({
3135 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3136 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3142 void GLES2Implementation::ReadPixels(
3143 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
3144 GLenum type
, void* pixels
) {
3145 GPU_CLIENT_SINGLE_THREAD_CHECK();
3146 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
3147 << xoffset
<< ", " << yoffset
<< ", "
3148 << width
<< ", " << height
<< ", "
3149 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
3150 << GLES2Util::GetStringPixelType(type
) << ", "
3151 << static_cast<const void*>(pixels
) << ")");
3152 if (width
< 0 || height
< 0) {
3153 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
3156 if (width
== 0 || height
== 0) {
3160 // glReadPixel pads the size of each row of pixels by an amount specified by
3161 // glPixelStorei. So, we have to take that into account both in the fact that
3162 // the pixels returned from the ReadPixel command will include that padding
3163 // and that when we copy the results to the user's buffer we need to not
3164 // write those padding bytes but leave them as they are.
3166 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
3167 typedef cmds::ReadPixels::Result Result
;
3169 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
3171 uint32 unpadded_row_size
;
3172 uint32 padded_row_size
;
3173 if (!GLES2Util::ComputeImageDataSizes(
3174 width
, 2, 1, format
, type
, pack_alignment_
, &temp_size
,
3175 &unpadded_row_size
, &padded_row_size
)) {
3176 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
3180 if (bound_pixel_pack_transfer_buffer_id_
) {
3181 GLuint offset
= ToGLuint(pixels
);
3182 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3183 bound_pixel_pack_transfer_buffer_id_
,
3184 "glReadPixels", offset
, padded_row_size
* height
);
3185 if (buffer
&& buffer
->shm_id() != -1) {
3186 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
3187 buffer
->shm_id(), buffer
->shm_offset(),
3195 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
3199 // Transfer by rows.
3200 // The max rows we can transfer.
3202 GLsizei desired_size
= padded_row_size
* (height
- 1) + unpadded_row_size
;
3203 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
3204 if (!buffer
.valid()) {
3207 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
3208 padded_row_size
, unpadded_row_size
, buffer
.size(), height
);
3209 num_rows
= std::min(num_rows
, height
);
3210 // NOTE: We must look up the address of the result area AFTER allocation
3211 // of the transfer buffer since the transfer buffer may be reallocated.
3212 Result
* result
= GetResultAs
<Result
*>();
3216 *result
= 0; // mark as failed.
3217 helper_
->ReadPixels(
3218 xoffset
, yoffset
, width
, num_rows
, format
, type
,
3219 buffer
.shm_id(), buffer
.offset(),
3220 GetResultShmId(), GetResultShmOffset(),
3224 // when doing a y-flip we have to iterate through top-to-bottom chunks
3225 // of the dst. The service side handles reversing the rows within a
3228 if (pack_reverse_row_order_
) {
3229 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
3233 // We have to copy 1 row at a time to avoid writing pad bytes.
3234 const int8
* src
= static_cast<const int8
*>(buffer
.address());
3235 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
3236 memcpy(rows_dst
, src
, unpadded_row_size
);
3237 rows_dst
+= padded_row_size
;
3238 src
+= padded_row_size
;
3240 if (!pack_reverse_row_order_
) {
3244 // If it was not marked as successful exit.
3248 yoffset
+= num_rows
;
3254 void GLES2Implementation::ActiveTexture(GLenum texture
) {
3255 GPU_CLIENT_SINGLE_THREAD_CHECK();
3256 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
3257 << GLES2Util::GetStringEnum(texture
) << ")");
3258 GLuint texture_index
= texture
- GL_TEXTURE0
;
3259 if (texture_index
>=
3260 static_cast<GLuint
>(capabilities_
.max_combined_texture_image_units
)) {
3261 SetGLErrorInvalidEnum(
3262 "glActiveTexture", texture
, "texture");
3266 active_texture_unit_
= texture_index
;
3267 helper_
->ActiveTexture(texture
);
3271 void GLES2Implementation::GenBuffersHelper(
3272 GLsizei
/* n */, const GLuint
* /* buffers */) {
3275 void GLES2Implementation::GenFramebuffersHelper(
3276 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
3279 void GLES2Implementation::GenRenderbuffersHelper(
3280 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
3283 void GLES2Implementation::GenTexturesHelper(
3284 GLsizei
/* n */, const GLuint
* /* textures */) {
3287 void GLES2Implementation::GenVertexArraysOESHelper(
3288 GLsizei n
, const GLuint
* arrays
) {
3289 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
3292 void GLES2Implementation::GenQueriesEXTHelper(
3293 GLsizei
/* n */, const GLuint
* /* queries */) {
3296 void GLES2Implementation::GenValuebuffersCHROMIUMHelper(
3298 const GLuint
* /* valuebuffers */) {
3301 void GLES2Implementation::GenSamplersHelper(
3302 GLsizei
/* n */, const GLuint
* /* samplers */) {
3305 void GLES2Implementation::GenTransformFeedbacksHelper(
3306 GLsizei
/* n */, const GLuint
* /* transformfeedbacks */) {
3309 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
3310 // generates a new resource. On newer versions of OpenGL they don't. The code
3311 // related to binding below will need to change if we switch to the new OpenGL
3312 // model. Specifically it assumes a bind will succeed which is always true in
3313 // the old model but possibly not true in the new model if another context has
3314 // deleted the resource.
3316 // NOTE #2: There is a bug in some BindXXXHelpers, that IDs might be marked as
3317 // used even when Bind has failed. However, the bug is minor compared to the
3318 // overhead & duplicated checking in client side.
3320 void GLES2Implementation::BindBufferHelper(
3321 GLenum target
, GLuint buffer_id
) {
3322 // TODO(gman): See note #1 above.
3323 bool changed
= false;
3325 case GL_ARRAY_BUFFER
:
3326 if (bound_array_buffer_id_
!= buffer_id
) {
3327 bound_array_buffer_id_
= buffer_id
;
3331 case GL_ELEMENT_ARRAY_BUFFER
:
3332 changed
= vertex_array_object_manager_
->BindElementArray(buffer_id
);
3334 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3335 bound_pixel_pack_transfer_buffer_id_
= buffer_id
;
3337 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3338 bound_pixel_unpack_transfer_buffer_id_
= buffer_id
;
3344 // TODO(gman): See note #2 above.
3346 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3347 this, target
, buffer_id
, &GLES2Implementation::BindBufferStub
);
3351 void GLES2Implementation::BindBufferStub(GLenum target
, GLuint buffer
) {
3352 helper_
->BindBuffer(target
, buffer
);
3353 if (share_group_
->bind_generates_resource())
3354 helper_
->CommandBufferHelper::Flush();
3357 void GLES2Implementation::BindBufferBaseHelper(
3358 GLenum target
, GLuint index
, GLuint buffer_id
) {
3359 // TODO(zmo): See note #1 above.
3360 // TODO(zmo): See note #2 above.
3361 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3362 this, target
, index
, buffer_id
, &GLES2Implementation::BindBufferBaseStub
);
3365 void GLES2Implementation::BindBufferBaseStub(
3366 GLenum target
, GLuint index
, GLuint buffer
) {
3367 helper_
->BindBufferBase(target
, index
, buffer
);
3368 if (share_group_
->bind_generates_resource())
3369 helper_
->CommandBufferHelper::Flush();
3372 void GLES2Implementation::BindBufferRangeHelper(
3373 GLenum target
, GLuint index
, GLuint buffer_id
,
3374 GLintptr offset
, GLsizeiptr size
) {
3375 // TODO(zmo): See note #1 above.
3376 // TODO(zmo): See note #2 above.
3377 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(
3378 this, target
, index
, buffer_id
, offset
, size
,
3379 &GLES2Implementation::BindBufferRangeStub
);
3382 void GLES2Implementation::BindBufferRangeStub(
3383 GLenum target
, GLuint index
, GLuint buffer
,
3384 GLintptr offset
, GLsizeiptr size
) {
3385 helper_
->BindBufferRange(target
, index
, buffer
, offset
, size
);
3386 if (share_group_
->bind_generates_resource())
3387 helper_
->CommandBufferHelper::Flush();
3390 void GLES2Implementation::BindFramebufferHelper(
3391 GLenum target
, GLuint framebuffer
) {
3392 // TODO(gman): See note #1 above.
3393 bool changed
= false;
3395 case GL_FRAMEBUFFER
:
3396 if (bound_framebuffer_
!= framebuffer
||
3397 bound_read_framebuffer_
!= framebuffer
) {
3398 bound_framebuffer_
= framebuffer
;
3399 bound_read_framebuffer_
= framebuffer
;
3403 case GL_READ_FRAMEBUFFER
:
3404 if (!IsChromiumFramebufferMultisampleAvailable()) {
3405 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3408 if (bound_read_framebuffer_
!= framebuffer
) {
3409 bound_read_framebuffer_
= framebuffer
;
3413 case GL_DRAW_FRAMEBUFFER
:
3414 if (!IsChromiumFramebufferMultisampleAvailable()) {
3415 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3418 if (bound_framebuffer_
!= framebuffer
) {
3419 bound_framebuffer_
= framebuffer
;
3424 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
3429 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(
3430 this, target
, framebuffer
, &GLES2Implementation::BindFramebufferStub
);
3434 void GLES2Implementation::BindFramebufferStub(GLenum target
,
3435 GLuint framebuffer
) {
3436 helper_
->BindFramebuffer(target
, framebuffer
);
3437 if (share_group_
->bind_generates_resource())
3438 helper_
->CommandBufferHelper::Flush();
3441 void GLES2Implementation::BindRenderbufferHelper(
3442 GLenum target
, GLuint renderbuffer
) {
3443 // TODO(gman): See note #1 above.
3444 bool changed
= false;
3446 case GL_RENDERBUFFER
:
3447 if (bound_renderbuffer_
!= renderbuffer
) {
3448 bound_renderbuffer_
= renderbuffer
;
3456 // TODO(zmo): See note #2 above.
3458 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(
3459 this, target
, renderbuffer
,
3460 &GLES2Implementation::BindRenderbufferStub
);
3464 void GLES2Implementation::BindRenderbufferStub(GLenum target
,
3465 GLuint renderbuffer
) {
3466 helper_
->BindRenderbuffer(target
, renderbuffer
);
3467 if (share_group_
->bind_generates_resource())
3468 helper_
->CommandBufferHelper::Flush();
3471 void GLES2Implementation::BindSamplerHelper(GLuint unit
,
3473 helper_
->BindSampler(unit
, sampler
);
3476 void GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
3477 // TODO(gman): See note #1 above.
3478 // TODO(gman): Change this to false once we figure out why it's failing
3480 bool changed
= true;
3481 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
3484 if (unit
.bound_texture_2d
!= texture
) {
3485 unit
.bound_texture_2d
= texture
;
3489 case GL_TEXTURE_CUBE_MAP
:
3490 if (unit
.bound_texture_cube_map
!= texture
) {
3491 unit
.bound_texture_cube_map
= texture
;
3495 case GL_TEXTURE_EXTERNAL_OES
:
3496 if (unit
.bound_texture_external_oes
!= texture
) {
3497 unit
.bound_texture_external_oes
= texture
;
3505 // TODO(gman): See note #2 above.
3507 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(
3508 this, target
, texture
, &GLES2Implementation::BindTextureStub
);
3512 void GLES2Implementation::BindTextureStub(GLenum target
, GLuint texture
) {
3513 helper_
->BindTexture(target
, texture
);
3514 if (share_group_
->bind_generates_resource())
3515 helper_
->CommandBufferHelper::Flush();
3518 void GLES2Implementation::BindTransformFeedbackHelper(
3519 GLenum target
, GLuint transformfeedback
) {
3520 helper_
->BindTransformFeedback(target
, transformfeedback
);
3523 void GLES2Implementation::BindVertexArrayOESHelper(GLuint array
) {
3524 bool changed
= false;
3525 if (vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
3527 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
3528 // because unlike other resources VertexArrayObject ids must
3529 // be generated by GenVertexArrays. A random id to Bind will not
3530 // generate a new object.
3531 helper_
->BindVertexArrayOES(array
);
3535 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
3536 "id was not generated with glGenVertexArrayOES");
3540 void GLES2Implementation::BindValuebufferCHROMIUMHelper(GLenum target
,
3541 GLuint valuebuffer
) {
3542 bool changed
= false;
3544 case GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
:
3545 if (bound_valuebuffer_
!= valuebuffer
) {
3546 bound_valuebuffer_
= valuebuffer
;
3554 // TODO(gman): See note #2 above.
3556 GetIdHandler(id_namespaces::kValuebuffers
)->MarkAsUsedForBind(
3557 this, target
, valuebuffer
,
3558 &GLES2Implementation::BindValuebufferCHROMIUMStub
);
3562 void GLES2Implementation::BindValuebufferCHROMIUMStub(GLenum target
,
3563 GLuint valuebuffer
) {
3564 helper_
->BindValuebufferCHROMIUM(target
, valuebuffer
);
3565 if (share_group_
->bind_generates_resource())
3566 helper_
->CommandBufferHelper::Flush();
3569 void GLES2Implementation::UseProgramHelper(GLuint program
) {
3570 if (current_program_
!= program
) {
3571 current_program_
= program
;
3572 helper_
->UseProgram(program
);
3576 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
3577 return vertex_array_object_manager_
->IsReservedId(id
);
3580 void GLES2Implementation::DeleteBuffersHelper(
3581 GLsizei n
, const GLuint
* buffers
) {
3582 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
3583 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
3586 "glDeleteBuffers", "id not created by this context.");
3589 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3590 if (buffers
[ii
] == bound_array_buffer_id_
) {
3591 bound_array_buffer_id_
= 0;
3593 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
3595 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
3597 RemoveTransferBuffer(buffer
);
3599 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
3600 bound_pixel_unpack_transfer_buffer_id_
= 0;
3603 RemoveMappedBufferRangeById(buffers
[ii
]);
3607 void GLES2Implementation::DeleteBuffersStub(
3608 GLsizei n
, const GLuint
* buffers
) {
3609 helper_
->DeleteBuffersImmediate(n
, buffers
);
3613 void GLES2Implementation::DeleteFramebuffersHelper(
3614 GLsizei n
, const GLuint
* framebuffers
) {
3615 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
3616 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
3619 "glDeleteFramebuffers", "id not created by this context.");
3622 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3623 if (framebuffers
[ii
] == bound_framebuffer_
) {
3624 bound_framebuffer_
= 0;
3626 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
3627 bound_read_framebuffer_
= 0;
3632 void GLES2Implementation::DeleteFramebuffersStub(
3633 GLsizei n
, const GLuint
* framebuffers
) {
3634 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
3637 void GLES2Implementation::DeleteRenderbuffersHelper(
3638 GLsizei n
, const GLuint
* renderbuffers
) {
3639 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
3640 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
3643 "glDeleteRenderbuffers", "id not created by this context.");
3646 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3647 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
3648 bound_renderbuffer_
= 0;
3653 void GLES2Implementation::DeleteRenderbuffersStub(
3654 GLsizei n
, const GLuint
* renderbuffers
) {
3655 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
3658 void GLES2Implementation::DeleteTexturesHelper(
3659 GLsizei n
, const GLuint
* textures
) {
3660 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
3661 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
3664 "glDeleteTextures", "id not created by this context.");
3667 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3668 for (GLint tt
= 0; tt
< capabilities_
.max_combined_texture_image_units
;
3670 TextureUnit
& unit
= texture_units_
[tt
];
3671 if (textures
[ii
] == unit
.bound_texture_2d
) {
3672 unit
.bound_texture_2d
= 0;
3674 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
3675 unit
.bound_texture_cube_map
= 0;
3677 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
3678 unit
.bound_texture_external_oes
= 0;
3684 void GLES2Implementation::DeleteTexturesStub(GLsizei n
,
3685 const GLuint
* textures
) {
3686 helper_
->DeleteTexturesImmediate(n
, textures
);
3689 void GLES2Implementation::DeleteVertexArraysOESHelper(
3690 GLsizei n
, const GLuint
* arrays
) {
3691 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
3692 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
3693 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
3696 "glDeleteVertexArraysOES", "id not created by this context.");
3701 void GLES2Implementation::DeleteVertexArraysOESStub(
3702 GLsizei n
, const GLuint
* arrays
) {
3703 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
3706 void GLES2Implementation::DeleteValuebuffersCHROMIUMHelper(
3708 const GLuint
* valuebuffers
) {
3709 if (!GetIdHandler(id_namespaces::kValuebuffers
)
3710 ->FreeIds(this, n
, valuebuffers
,
3711 &GLES2Implementation::DeleteValuebuffersCHROMIUMStub
)) {
3712 SetGLError(GL_INVALID_VALUE
, "glDeleteValuebuffersCHROMIUM",
3713 "id not created by this context.");
3716 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3717 if (valuebuffers
[ii
] == bound_valuebuffer_
) {
3718 bound_valuebuffer_
= 0;
3723 void GLES2Implementation::DeleteSamplersStub(
3724 GLsizei n
, const GLuint
* samplers
) {
3725 helper_
->DeleteSamplersImmediate(n
, samplers
);
3728 void GLES2Implementation::DeleteSamplersHelper(
3729 GLsizei n
, const GLuint
* samplers
) {
3730 if (!GetIdHandler(id_namespaces::kSamplers
)->FreeIds(
3731 this, n
, samplers
, &GLES2Implementation::DeleteSamplersStub
)) {
3734 "glDeleteSamplers", "id not created by this context.");
3739 void GLES2Implementation::DeleteTransformFeedbacksStub(
3740 GLsizei n
, const GLuint
* transformfeedbacks
) {
3741 helper_
->DeleteTransformFeedbacksImmediate(n
, transformfeedbacks
);
3744 void GLES2Implementation::DeleteTransformFeedbacksHelper(
3745 GLsizei n
, const GLuint
* transformfeedbacks
) {
3746 if (!GetIdHandler(id_namespaces::kTransformFeedbacks
)->FreeIds(
3747 this, n
, transformfeedbacks
,
3748 &GLES2Implementation::DeleteTransformFeedbacksStub
)) {
3751 "glDeleteTransformFeedbacks", "id not created by this context.");
3756 void GLES2Implementation::DeleteValuebuffersCHROMIUMStub(
3758 const GLuint
* valuebuffers
) {
3759 helper_
->DeleteValuebuffersCHROMIUMImmediate(n
, valuebuffers
);
3762 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
3763 GPU_CLIENT_SINGLE_THREAD_CHECK();
3765 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
3766 vertex_array_object_manager_
->SetAttribEnable(index
, false);
3767 helper_
->DisableVertexAttribArray(index
);
3771 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
3772 GPU_CLIENT_SINGLE_THREAD_CHECK();
3773 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
3775 vertex_array_object_manager_
->SetAttribEnable(index
, true);
3776 helper_
->EnableVertexAttribArray(index
);
3780 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
3781 GPU_CLIENT_SINGLE_THREAD_CHECK();
3782 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
3783 << GLES2Util::GetStringDrawMode(mode
) << ", "
3784 << first
<< ", " << count
<< ")");
3786 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
3789 bool simulated
= false;
3790 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3791 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
3794 helper_
->DrawArrays(mode
, first
, count
);
3795 RestoreArrayBuffer(simulated
);
3799 void GLES2Implementation::GetVertexAttribfv(
3800 GLuint index
, GLenum pname
, GLfloat
* params
) {
3801 GPU_CLIENT_SINGLE_THREAD_CHECK();
3802 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
3804 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
3805 << static_cast<const void*>(params
) << ")");
3807 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
3808 *params
= static_cast<float>(value
);
3811 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
3812 typedef cmds::GetVertexAttribfv::Result Result
;
3813 Result
* result
= GetResultAs
<Result
*>();
3817 result
->SetNumResults(0);
3818 helper_
->GetVertexAttribfv(
3819 index
, pname
, GetResultShmId(), GetResultShmOffset());
3821 result
->CopyResult(params
);
3822 GPU_CLIENT_LOG_CODE_BLOCK({
3823 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3824 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3830 void GLES2Implementation::GetVertexAttribiv(
3831 GLuint index
, GLenum pname
, GLint
* params
) {
3832 GPU_CLIENT_SINGLE_THREAD_CHECK();
3833 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
3835 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
3836 << static_cast<const void*>(params
) << ")");
3838 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
3842 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
3843 typedef cmds::GetVertexAttribiv::Result Result
;
3844 Result
* result
= GetResultAs
<Result
*>();
3848 result
->SetNumResults(0);
3849 helper_
->GetVertexAttribiv(
3850 index
, pname
, GetResultShmId(), GetResultShmOffset());
3852 result
->CopyResult(params
);
3853 GPU_CLIENT_LOG_CODE_BLOCK({
3854 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
3855 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
3861 void GLES2Implementation::Swap() {
3865 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
3866 PostSubBufferCHROMIUM(
3867 sub_buffer
.x(), sub_buffer
.y(), sub_buffer
.width(), sub_buffer
.height());
3870 static GLenum
GetGLESOverlayTransform(gfx::OverlayTransform plane_transform
) {
3871 switch (plane_transform
) {
3872 case gfx::OVERLAY_TRANSFORM_INVALID
:
3874 case gfx::OVERLAY_TRANSFORM_NONE
:
3875 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
3876 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
:
3877 return GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
;
3878 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
:
3879 return GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
;
3880 case gfx::OVERLAY_TRANSFORM_ROTATE_90
:
3881 return GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
;
3882 case gfx::OVERLAY_TRANSFORM_ROTATE_180
:
3883 return GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
;
3884 case gfx::OVERLAY_TRANSFORM_ROTATE_270
:
3885 return GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
;
3888 return GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
;
3891 void GLES2Implementation::ScheduleOverlayPlane(
3893 gfx::OverlayTransform plane_transform
,
3894 unsigned overlay_texture_id
,
3895 const gfx::Rect
& display_bounds
,
3896 const gfx::RectF
& uv_rect
) {
3897 ScheduleOverlayPlaneCHROMIUM(plane_z_order
,
3898 GetGLESOverlayTransform(plane_transform
),
3902 display_bounds
.width(),
3903 display_bounds
.height(),
3910 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
3911 const char* feature
) {
3912 GPU_CLIENT_SINGLE_THREAD_CHECK();
3913 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
3915 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
3916 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
3917 Result
* result
= GetResultAs
<Result
*>();
3922 SetBucketAsCString(kResultBucketId
, feature
);
3923 helper_
->EnableFeatureCHROMIUM(
3924 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
3926 helper_
->SetBucketSize(kResultBucketId
, 0);
3927 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
3928 return *result
!= 0;
3931 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
3932 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
3933 GPU_CLIENT_SINGLE_THREAD_CHECK();
3934 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
3935 << target
<< ", " << offset
<< ", " << size
<< ", "
3936 << GLES2Util::GetStringEnum(access
) << ")");
3937 // NOTE: target is NOT checked because the service will check it
3938 // and we don't know what targets are valid.
3939 if (access
!= GL_WRITE_ONLY
) {
3940 SetGLErrorInvalidEnum(
3941 "glMapBufferSubDataCHROMIUM", access
, "access");
3944 if (!ValidateSize("glMapBufferSubDataCHROMIUM", size
) ||
3945 !ValidateOffset("glMapBufferSubDataCHROMIUM", offset
)) {
3950 unsigned int shm_offset
;
3951 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
3953 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
3957 std::pair
<MappedBufferMap::iterator
, bool> result
=
3958 mapped_buffers_
.insert(std::make_pair(
3961 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
3962 DCHECK(result
.second
);
3963 GPU_CLIENT_LOG(" returned " << mem
);
3967 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
3968 GPU_CLIENT_SINGLE_THREAD_CHECK();
3970 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
3971 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
3972 if (it
== mapped_buffers_
.end()) {
3974 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
3977 const MappedBuffer
& mb
= it
->second
;
3978 helper_
->BufferSubData(
3979 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
3980 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
3981 mapped_buffers_
.erase(it
);
3985 GLuint
GLES2Implementation::GetBoundBufferHelper(GLenum target
) {
3986 GLenum binding
= GLES2Util::MapBufferTargetToBindingEnum(target
);
3988 bool cached
= GetHelper(binding
, &id
);
3990 return static_cast<GLuint
>(id
);
3993 void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target
) {
3994 GLuint buffer
= GetBoundBufferHelper(target
);
3995 RemoveMappedBufferRangeById(buffer
);
3998 void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer
) {
4000 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4001 if (iter
!= mapped_buffer_range_map_
.end() && iter
->second
.shm_memory
) {
4002 mapped_memory_
->FreePendingToken(
4003 iter
->second
.shm_memory
, helper_
->InsertToken());
4004 mapped_buffer_range_map_
.erase(iter
);
4009 void GLES2Implementation::ClearMappedBufferRangeMap() {
4010 for (auto& buffer_range
: mapped_buffer_range_map_
) {
4011 if (buffer_range
.second
.shm_memory
) {
4012 mapped_memory_
->FreePendingToken(
4013 buffer_range
.second
.shm_memory
, helper_
->InsertToken());
4016 mapped_buffer_range_map_
.clear();
4019 void* GLES2Implementation::MapBufferRange(
4020 GLenum target
, GLintptr offset
, GLsizeiptr size
, GLbitfield access
) {
4021 GPU_CLIENT_SINGLE_THREAD_CHECK();
4022 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange("
4023 << GLES2Util::GetStringEnum(target
) << ", " << offset
<< ", "
4024 << size
<< ", " << access
<< ")");
4025 if (!ValidateSize("glMapBufferRange", size
) ||
4026 !ValidateOffset("glMapBufferRange", offset
)) {
4031 unsigned int shm_offset
;
4032 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4034 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferRange", "out of memory");
4038 typedef cmds::MapBufferRange::Result Result
;
4039 Result
* result
= GetResultAs
<Result
*>();
4041 helper_
->MapBufferRange(target
, offset
, size
, access
, shm_id
, shm_offset
,
4042 GetResultShmId(), GetResultShmOffset());
4043 // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should
4044 // consider an early return without WaitForCmd(). crbug.com/465804.
4047 const GLbitfield kInvalidateBits
=
4048 GL_MAP_INVALIDATE_BUFFER_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
4049 if ((access
& kInvalidateBits
) != 0) {
4050 // We do not read back from the buffer, therefore, we set the client
4051 // side memory to zero to avoid uninitialized data.
4052 memset(mem
, 0, size
);
4054 GLuint buffer
= GetBoundBufferHelper(target
);
4055 DCHECK_NE(0u, buffer
);
4056 // glMapBufferRange fails on an already mapped buffer.
4057 DCHECK(mapped_buffer_range_map_
.find(buffer
) ==
4058 mapped_buffer_range_map_
.end());
4059 auto iter
= mapped_buffer_range_map_
.insert(std::make_pair(
4061 MappedBuffer(access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
4062 DCHECK(iter
.second
);
4064 mapped_memory_
->Free(mem
);
4068 GPU_CLIENT_LOG(" returned " << mem
);
4073 GLboolean
GLES2Implementation::UnmapBuffer(GLenum target
) {
4074 GPU_CLIENT_SINGLE_THREAD_CHECK();
4075 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer("
4076 << GLES2Util::GetStringEnum(target
) << ")");
4078 case GL_ARRAY_BUFFER
:
4079 case GL_ELEMENT_ARRAY_BUFFER
:
4080 case GL_COPY_READ_BUFFER
:
4081 case GL_COPY_WRITE_BUFFER
:
4082 case GL_PIXEL_PACK_BUFFER
:
4083 case GL_PIXEL_UNPACK_BUFFER
:
4084 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4085 case GL_UNIFORM_BUFFER
:
4088 SetGLError(GL_INVALID_ENUM
, "glUnmapBuffer", "invalid target");
4091 GLuint buffer
= GetBoundBufferHelper(target
);
4093 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "no buffer bound");
4096 auto iter
= mapped_buffer_range_map_
.find(buffer
);
4097 if (iter
== mapped_buffer_range_map_
.end()) {
4098 SetGLError(GL_INVALID_OPERATION
, "glUnmapBuffer", "buffer is unmapped");
4102 helper_
->UnmapBuffer(target
);
4103 RemoveMappedBufferRangeById(buffer
);
4104 // TODO(zmo): There is a rare situation that data might be corrupted and
4105 // GL_FALSE should be returned. We lose context on that sitatuon, so we
4106 // don't have to WaitForCmd().
4107 GPU_CLIENT_LOG(" returned " << GL_TRUE
);
4112 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
4122 GPU_CLIENT_SINGLE_THREAD_CHECK();
4123 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
4124 << target
<< ", " << level
<< ", "
4125 << xoffset
<< ", " << yoffset
<< ", "
4126 << width
<< ", " << height
<< ", "
4127 << GLES2Util::GetStringTextureFormat(format
) << ", "
4128 << GLES2Util::GetStringPixelType(type
) << ", "
4129 << GLES2Util::GetStringEnum(access
) << ")");
4130 if (access
!= GL_WRITE_ONLY
) {
4131 SetGLErrorInvalidEnum(
4132 "glMapTexSubImage2DCHROMIUM", access
, "access");
4135 // NOTE: target is NOT checked because the service will check it
4136 // and we don't know what targets are valid.
4137 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
4139 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
4143 if (!GLES2Util::ComputeImageDataSizes(
4144 width
, height
, 1, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
4146 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
4150 unsigned int shm_offset
;
4151 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
4153 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
4157 std::pair
<MappedTextureMap::iterator
, bool> result
=
4158 mapped_textures_
.insert(std::make_pair(
4161 access
, shm_id
, mem
, shm_offset
,
4162 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
4163 DCHECK(result
.second
);
4164 GPU_CLIENT_LOG(" returned " << mem
);
4168 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
4169 GPU_CLIENT_SINGLE_THREAD_CHECK();
4171 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
4172 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
4173 if (it
== mapped_textures_
.end()) {
4175 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
4178 const MappedTexture
& mt
= it
->second
;
4179 helper_
->TexSubImage2D(
4180 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
4181 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
4182 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
4183 mapped_textures_
.erase(it
);
4187 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
4188 float scale_factor
) {
4189 GPU_CLIENT_SINGLE_THREAD_CHECK();
4190 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
4191 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
4192 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
4196 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
4197 GPU_CLIENT_SINGLE_THREAD_CHECK();
4198 GPU_CLIENT_LOG("[" << GetLogPrefix()
4199 << "] glGetRequestableExtensionsCHROMIUM()");
4201 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
4202 const char* result
= NULL
;
4203 // Clear the bucket so if the command fails nothing will be in it.
4204 helper_
->SetBucketSize(kResultBucketId
, 0);
4205 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
4207 if (GetBucketAsString(kResultBucketId
, &str
)) {
4208 // The set of requestable extensions shrinks as we enable
4209 // them. Because we don't know when the client will stop referring
4210 // to a previous one it queries (see GetString) we need to cache
4211 // the unique results.
4212 std::set
<std::string
>::const_iterator sit
=
4213 requestable_extensions_set_
.find(str
);
4214 if (sit
!= requestable_extensions_set_
.end()) {
4215 result
= sit
->c_str();
4217 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
4218 requestable_extensions_set_
.insert(str
);
4219 DCHECK(insert_result
.second
);
4220 result
= insert_result
.first
->c_str();
4223 GPU_CLIENT_LOG(" returned " << result
);
4224 return reinterpret_cast<const GLchar
*>(result
);
4227 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
4228 // with VirtualGL contexts.
4229 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
4230 GPU_CLIENT_SINGLE_THREAD_CHECK();
4231 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
4232 << extension
<< ")");
4233 SetBucketAsCString(kResultBucketId
, extension
);
4234 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
4235 helper_
->SetBucketSize(kResultBucketId
, 0);
4237 struct ExtensionCheck
{
4238 const char* extension
;
4239 ExtensionStatus
* status
;
4241 const ExtensionCheck checks
[] = {
4243 "GL_ANGLE_pack_reverse_row_order",
4244 &angle_pack_reverse_row_order_status_
,
4247 "GL_CHROMIUM_framebuffer_multisample",
4248 &chromium_framebuffer_multisample_
,
4251 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
4252 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
4253 const ExtensionCheck
& check
= checks
[ii
];
4254 if (*check
.status
== kUnavailableExtensionStatus
&&
4255 !strcmp(extension
, check
.extension
)) {
4256 *check
.status
= kUnknownExtensionStatus
;
4261 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
4262 GPU_CLIENT_SINGLE_THREAD_CHECK();
4263 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
4264 // Wait if this would add too many rate limit tokens.
4265 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
4266 helper_
->WaitForToken(rate_limit_tokens_
.front());
4267 rate_limit_tokens_
.pop();
4269 rate_limit_tokens_
.push(helper_
->InsertToken());
4272 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
4273 GLuint program
, std::vector
<int8
>* result
) {
4275 // Clear the bucket so if the command fails nothing will be in it.
4276 helper_
->SetBucketSize(kResultBucketId
, 0);
4277 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
4278 GetBucketContents(kResultBucketId
, result
);
4281 void GLES2Implementation::GetProgramInfoCHROMIUM(
4282 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4283 GPU_CLIENT_SINGLE_THREAD_CHECK();
4286 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
4290 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
4293 // Make sure they've set size to 0 else the value will be undefined on
4295 DCHECK_EQ(0, *size
);
4296 std::vector
<int8
> result
;
4297 GetProgramInfoCHROMIUMHelper(program
, &result
);
4298 if (result
.empty()) {
4301 *size
= result
.size();
4305 if (static_cast<size_t>(bufsize
) < result
.size()) {
4306 SetGLError(GL_INVALID_OPERATION
,
4307 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
4310 memcpy(info
, &result
[0], result
.size());
4313 void GLES2Implementation::GetUniformBlocksCHROMIUMHelper(
4314 GLuint program
, std::vector
<int8
>* result
) {
4316 // Clear the bucket so if the command fails nothing will be in it.
4317 helper_
->SetBucketSize(kResultBucketId
, 0);
4318 helper_
->GetUniformBlocksCHROMIUM(program
, kResultBucketId
);
4319 GetBucketContents(kResultBucketId
, result
);
4322 void GLES2Implementation::GetUniformBlocksCHROMIUM(
4323 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4324 GPU_CLIENT_SINGLE_THREAD_CHECK();
4327 GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
4331 SetGLError(GL_INVALID_VALUE
, "glGetUniformBlocksCHROMIUM", "size is null.");
4334 // Make sure they've set size to 0 else the value will be undefined on
4336 DCHECK_EQ(0, *size
);
4337 std::vector
<int8
> result
;
4338 GetUniformBlocksCHROMIUMHelper(program
, &result
);
4339 if (result
.empty()) {
4342 *size
= result
.size();
4346 if (static_cast<size_t>(bufsize
) < result
.size()) {
4347 SetGLError(GL_INVALID_OPERATION
, "glGetUniformBlocksCHROMIUM",
4348 "bufsize is too small for result.");
4351 memcpy(info
, &result
[0], result
.size());
4354 void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
4355 GLuint program
, std::vector
<int8
>* result
) {
4357 // Clear the bucket so if the command fails nothing will be in it.
4358 helper_
->SetBucketSize(kResultBucketId
, 0);
4359 helper_
->GetUniformsES3CHROMIUM(program
, kResultBucketId
);
4360 GetBucketContents(kResultBucketId
, result
);
4363 void GLES2Implementation::GetUniformsES3CHROMIUM(
4364 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4365 GPU_CLIENT_SINGLE_THREAD_CHECK();
4368 GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
4372 SetGLError(GL_INVALID_VALUE
, "glGetUniformsES3CHROMIUM", "size is null.");
4375 // Make sure they've set size to 0 else the value will be undefined on
4377 DCHECK_EQ(0, *size
);
4378 std::vector
<int8
> result
;
4379 GetUniformsES3CHROMIUMHelper(program
, &result
);
4380 if (result
.empty()) {
4383 *size
= result
.size();
4387 if (static_cast<size_t>(bufsize
) < result
.size()) {
4388 SetGLError(GL_INVALID_OPERATION
,
4389 "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
4392 memcpy(info
, &result
[0], result
.size());
4395 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
4396 GLuint program
, std::vector
<int8
>* result
) {
4398 // Clear the bucket so if the command fails nothing will be in it.
4399 helper_
->SetBucketSize(kResultBucketId
, 0);
4400 helper_
->GetTransformFeedbackVaryingsCHROMIUM(program
, kResultBucketId
);
4401 GetBucketContents(kResultBucketId
, result
);
4404 void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
4405 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
4406 GPU_CLIENT_SINGLE_THREAD_CHECK();
4408 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4409 "bufsize less than 0.");
4413 SetGLError(GL_INVALID_VALUE
, "glGetTransformFeedbackVaryingsCHROMIUM",
4417 // Make sure they've set size to 0 else the value will be undefined on
4419 DCHECK_EQ(0, *size
);
4420 std::vector
<int8
> result
;
4421 GetTransformFeedbackVaryingsCHROMIUMHelper(program
, &result
);
4422 if (result
.empty()) {
4425 *size
= result
.size();
4429 if (static_cast<size_t>(bufsize
) < result
.size()) {
4430 SetGLError(GL_INVALID_OPERATION
, "glGetTransformFeedbackVaryingsCHROMIUM",
4431 "bufsize is too small for result.");
4434 memcpy(info
, &result
[0], result
.size());
4437 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
4438 GPU_CLIENT_SINGLE_THREAD_CHECK();
4439 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
4441 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
4442 helper_
->CommandBufferHelper::Flush();
4443 return gpu_control_
->CreateStreamTexture(texture
);
4446 void GLES2Implementation::PostSubBufferCHROMIUM(
4447 GLint x
, GLint y
, GLint width
, GLint height
) {
4448 GPU_CLIENT_SINGLE_THREAD_CHECK();
4449 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
4450 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
4451 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
4452 "width", width
, "height", height
);
4454 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
4455 swap_buffers_tokens_
.push(helper_
->InsertToken());
4456 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
4457 helper_
->CommandBufferHelper::Flush();
4458 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
4459 helper_
->WaitForToken(swap_buffers_tokens_
.front());
4460 swap_buffers_tokens_
.pop();
4464 void GLES2Implementation::DeleteQueriesEXTHelper(
4465 GLsizei n
, const GLuint
* queries
) {
4466 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4467 query_tracker_
->RemoveQuery(queries
[ii
]);
4468 query_id_allocator_
->FreeID(queries
[ii
]);
4471 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
4474 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
4475 GPU_CLIENT_SINGLE_THREAD_CHECK();
4476 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
4478 // TODO(gman): To be spec compliant IDs from other contexts sharing
4479 // resources need to return true here even though you can't share
4480 // queries across contexts?
4481 return query_tracker_
->GetQuery(id
) != NULL
;
4484 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
4485 GPU_CLIENT_SINGLE_THREAD_CHECK();
4486 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
4487 << GLES2Util::GetStringQueryTarget(target
)
4488 << ", " << id
<< ")");
4490 // if any outstanding queries INV_OP
4491 QueryMap::iterator it
= current_queries_
.find(target
);
4492 if (it
!= current_queries_
.end()) {
4494 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
4500 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
4504 // if not GENned INV_OPERATION
4505 if (!query_id_allocator_
->InUse(id
)) {
4506 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "invalid id");
4510 // if id does not have an object
4511 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4513 query
= query_tracker_
->CreateQuery(id
, target
);
4515 SetGLError(GL_OUT_OF_MEMORY
,
4517 "transfer buffer allocation failed");
4520 } else if (query
->target() != target
) {
4522 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
4526 current_queries_
[target
] = query
;
4532 void GLES2Implementation::EndQueryEXT(GLenum target
) {
4533 GPU_CLIENT_SINGLE_THREAD_CHECK();
4534 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
4535 << GLES2Util::GetStringQueryTarget(target
) << ")");
4536 // Don't do anything if the context is lost.
4537 if (helper_
->IsContextLost()) {
4541 QueryMap::iterator it
= current_queries_
.find(target
);
4542 if (it
== current_queries_
.end()) {
4543 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
4547 QueryTracker::Query
* query
= it
->second
;
4549 current_queries_
.erase(it
);
4553 void GLES2Implementation::GetQueryivEXT(
4554 GLenum target
, GLenum pname
, GLint
* params
) {
4555 GPU_CLIENT_SINGLE_THREAD_CHECK();
4556 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
4557 << GLES2Util::GetStringQueryTarget(target
) << ", "
4558 << GLES2Util::GetStringQueryParameter(pname
) << ", "
4559 << static_cast<const void*>(params
) << ")");
4561 if (pname
!= GL_CURRENT_QUERY_EXT
) {
4562 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
4565 QueryMap::iterator it
= current_queries_
.find(target
);
4566 if (it
!= current_queries_
.end()) {
4567 QueryTracker::Query
* query
= it
->second
;
4568 *params
= query
->id();
4572 GPU_CLIENT_LOG(" " << *params
);
4576 void GLES2Implementation::GetQueryObjectuivEXT(
4577 GLuint id
, GLenum pname
, GLuint
* params
) {
4578 GPU_CLIENT_SINGLE_THREAD_CHECK();
4579 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
4580 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
4581 << static_cast<const void*>(params
) << ")");
4583 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
4585 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
4589 QueryMap::iterator it
= current_queries_
.find(query
->target());
4590 if (it
!= current_queries_
.end()) {
4592 GL_INVALID_OPERATION
,
4593 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
4597 if (query
->NeverUsed()) {
4599 GL_INVALID_OPERATION
,
4600 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
4605 case GL_QUERY_RESULT_EXT
:
4606 if (!query
->CheckResultsAvailable(helper_
)) {
4607 helper_
->WaitForToken(query
->token());
4608 if (!query
->CheckResultsAvailable(helper_
)) {
4610 CHECK(query
->CheckResultsAvailable(helper_
));
4613 *params
= query
->GetResult();
4615 case GL_QUERY_RESULT_AVAILABLE_EXT
:
4616 *params
= query
->CheckResultsAvailable(helper_
);
4619 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
4622 GPU_CLIENT_LOG(" " << *params
);
4626 void GLES2Implementation::DrawArraysInstancedANGLE(
4627 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
4628 GPU_CLIENT_SINGLE_THREAD_CHECK();
4629 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
4630 << GLES2Util::GetStringDrawMode(mode
) << ", "
4631 << first
<< ", " << count
<< ", " << primcount
<< ")");
4633 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
4636 if (primcount
< 0) {
4637 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
4640 if (primcount
== 0) {
4643 bool simulated
= false;
4644 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
4645 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
4649 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
4650 RestoreArrayBuffer(simulated
);
4654 void GLES2Implementation::DrawElementsInstancedANGLE(
4655 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
4656 GLsizei primcount
) {
4657 GPU_CLIENT_SINGLE_THREAD_CHECK();
4658 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
4659 << GLES2Util::GetStringDrawMode(mode
) << ", "
4661 << GLES2Util::GetStringIndexType(type
) << ", "
4662 << static_cast<const void*>(indices
) << ", "
4663 << primcount
<< ")");
4665 SetGLError(GL_INVALID_VALUE
,
4666 "glDrawElementsInstancedANGLE", "count less than 0.");
4672 if (primcount
< 0) {
4673 SetGLError(GL_INVALID_VALUE
,
4674 "glDrawElementsInstancedANGLE", "primcount < 0");
4677 if (primcount
== 0) {
4680 if (vertex_array_object_manager_
->bound_element_array_buffer() != 0 &&
4681 !ValidateOffset("glDrawElementsInstancedANGLE",
4682 reinterpret_cast<GLintptr
>(indices
))) {
4686 bool simulated
= false;
4687 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
4688 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
4689 indices
, &offset
, &simulated
)) {
4692 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
4693 RestoreElementAndArrayBuffers(simulated
);
4697 void GLES2Implementation::GenMailboxCHROMIUM(
4699 GPU_CLIENT_SINGLE_THREAD_CHECK();
4700 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
4701 << static_cast<const void*>(mailbox
) << ")");
4702 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
4704 gpu::Mailbox result
= gpu::Mailbox::Generate();
4705 memcpy(mailbox
, result
.name
, sizeof(result
.name
));
4708 void GLES2Implementation::ProduceTextureCHROMIUM(GLenum target
,
4709 const GLbyte
* data
) {
4710 GPU_CLIENT_SINGLE_THREAD_CHECK();
4711 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureCHROMIUM("
4712 << static_cast<const void*>(data
) << ")");
4713 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4714 DCHECK(mailbox
.Verify()) << "ProduceTextureCHROMIUM was passed a "
4715 "mailbox that was not generated by "
4716 "GenMailboxCHROMIUM.";
4717 helper_
->ProduceTextureCHROMIUMImmediate(target
, data
);
4721 void GLES2Implementation::ProduceTextureDirectCHROMIUM(
4722 GLuint texture
, GLenum target
, const GLbyte
* data
) {
4723 GPU_CLIENT_SINGLE_THREAD_CHECK();
4724 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glProduceTextureDirectCHROMIUM("
4725 << static_cast<const void*>(data
) << ")");
4726 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4727 DCHECK(mailbox
.Verify()) << "ProduceTextureDirectCHROMIUM was passed a "
4728 "mailbox that was not generated by "
4729 "GenMailboxCHROMIUM.";
4730 helper_
->ProduceTextureDirectCHROMIUMImmediate(texture
, target
, data
);
4734 void GLES2Implementation::ConsumeTextureCHROMIUM(GLenum target
,
4735 const GLbyte
* data
) {
4736 GPU_CLIENT_SINGLE_THREAD_CHECK();
4737 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glConsumeTextureCHROMIUM("
4738 << static_cast<const void*>(data
) << ")");
4739 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4740 DCHECK(mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
4741 "mailbox that was not generated by "
4742 "GenMailboxCHROMIUM.";
4743 helper_
->ConsumeTextureCHROMIUMImmediate(target
, data
);
4747 GLuint
GLES2Implementation::CreateAndConsumeTextureCHROMIUM(
4748 GLenum target
, const GLbyte
* data
) {
4749 GPU_CLIENT_SINGLE_THREAD_CHECK();
4750 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateAndConsumeTextureCHROMIUM("
4751 << static_cast<const void*>(data
) << ")");
4752 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
4753 DCHECK(mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was passed a "
4754 "mailbox that was not generated by "
4755 "GenMailboxCHROMIUM.";
4757 GetIdHandler(id_namespaces::kTextures
)->MakeIds(this, 0, 1, &client_id
);
4758 helper_
->CreateAndConsumeTextureCHROMIUMImmediate(target
,
4760 if (share_group_
->bind_generates_resource())
4761 helper_
->CommandBufferHelper::Flush();
4766 void GLES2Implementation::PushGroupMarkerEXT(
4767 GLsizei length
, const GLchar
* marker
) {
4768 GPU_CLIENT_SINGLE_THREAD_CHECK();
4769 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
4770 << length
<< ", " << marker
<< ")");
4776 (length
? std::string(marker
, length
) : std::string(marker
)));
4777 helper_
->PushGroupMarkerEXT(kResultBucketId
);
4778 helper_
->SetBucketSize(kResultBucketId
, 0);
4779 debug_marker_manager_
.PushGroup(
4780 length
? std::string(marker
, length
) : std::string(marker
));
4783 void GLES2Implementation::InsertEventMarkerEXT(
4784 GLsizei length
, const GLchar
* marker
) {
4785 GPU_CLIENT_SINGLE_THREAD_CHECK();
4786 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
4787 << length
<< ", " << marker
<< ")");
4793 (length
? std::string(marker
, length
) : std::string(marker
)));
4794 helper_
->InsertEventMarkerEXT(kResultBucketId
);
4795 helper_
->SetBucketSize(kResultBucketId
, 0);
4796 debug_marker_manager_
.SetMarker(
4797 length
? std::string(marker
, length
) : std::string(marker
));
4800 void GLES2Implementation::PopGroupMarkerEXT() {
4801 GPU_CLIENT_SINGLE_THREAD_CHECK();
4802 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
4803 helper_
->PopGroupMarkerEXT();
4804 debug_marker_manager_
.PopGroup();
4807 void GLES2Implementation::TraceBeginCHROMIUM(
4808 const char* category_name
, const char* trace_name
) {
4809 GPU_CLIENT_SINGLE_THREAD_CHECK();
4810 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
4811 << category_name
<< ", " << trace_name
<< ")");
4812 SetBucketAsCString(kResultBucketId
, category_name
);
4813 SetBucketAsCString(kResultBucketId
+ 1, trace_name
);
4814 helper_
->TraceBeginCHROMIUM(kResultBucketId
, kResultBucketId
+ 1);
4815 helper_
->SetBucketSize(kResultBucketId
, 0);
4816 helper_
->SetBucketSize(kResultBucketId
+ 1, 0);
4817 current_trace_stack_
++;
4820 void GLES2Implementation::TraceEndCHROMIUM() {
4821 GPU_CLIENT_SINGLE_THREAD_CHECK();
4822 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
4823 if (current_trace_stack_
== 0) {
4824 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
4825 "missing begin trace");
4828 helper_
->TraceEndCHROMIUM();
4829 current_trace_stack_
--;
4832 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
4833 GPU_CLIENT_SINGLE_THREAD_CHECK();
4834 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
4835 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
4837 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
4838 if (access
!= GL_READ_ONLY
) {
4839 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
4843 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
4844 if (access
!= GL_WRITE_ONLY
) {
4845 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
4851 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
4855 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
4859 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
4861 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
4864 if (buffer
->mapped()) {
4865 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
4868 // Here we wait for previous transfer operations to be finished.
4869 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
4870 // with this method of synchronization. Until this is fixed,
4871 // MapBufferCHROMIUM will not block even if the transfer is not ready
4873 if (buffer
->last_usage_token()) {
4874 helper_
->WaitForToken(buffer
->last_usage_token());
4875 buffer
->set_last_usage_token(0);
4877 buffer
->set_mapped(true);
4879 GPU_CLIENT_LOG(" returned " << buffer
->address());
4881 return buffer
->address();
4884 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
4885 GPU_CLIENT_SINGLE_THREAD_CHECK();
4887 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
4889 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
4890 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
4895 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
4897 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
4900 if (!buffer
->mapped()) {
4901 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
4904 buffer
->set_mapped(false);
4909 bool GLES2Implementation::EnsureAsyncUploadSync() {
4910 if (async_upload_sync_
)
4914 unsigned int shm_offset
;
4915 void* mem
= mapped_memory_
->Alloc(sizeof(AsyncUploadSync
),
4921 async_upload_sync_shm_id_
= shm_id
;
4922 async_upload_sync_shm_offset_
= shm_offset
;
4923 async_upload_sync_
= static_cast<AsyncUploadSync
*>(mem
);
4924 async_upload_sync_
->Reset();
4929 uint32
GLES2Implementation::NextAsyncUploadToken() {
4930 async_upload_token_
++;
4931 if (async_upload_token_
== 0)
4932 async_upload_token_
++;
4933 return async_upload_token_
;
4936 void GLES2Implementation::PollAsyncUploads() {
4937 if (!async_upload_sync_
)
4940 if (helper_
->IsContextLost()) {
4941 DetachedAsyncUploadMemoryList::iterator it
=
4942 detached_async_upload_memory_
.begin();
4943 while (it
!= detached_async_upload_memory_
.end()) {
4944 mapped_memory_
->Free(it
->first
);
4945 it
= detached_async_upload_memory_
.erase(it
);
4950 DetachedAsyncUploadMemoryList::iterator it
=
4951 detached_async_upload_memory_
.begin();
4952 while (it
!= detached_async_upload_memory_
.end()) {
4953 if (HasAsyncUploadTokenPassed(it
->second
)) {
4954 mapped_memory_
->Free(it
->first
);
4955 it
= detached_async_upload_memory_
.erase(it
);
4962 void GLES2Implementation::FreeAllAsyncUploadBuffers() {
4963 // Free all completed unmanaged async uploads buffers.
4966 // Synchronously free rest of the unmanaged async upload buffers.
4967 if (!detached_async_upload_memory_
.empty()) {
4968 WaitAllAsyncTexImage2DCHROMIUM();
4974 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
4975 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
4976 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
4977 const void* pixels
) {
4978 GPU_CLIENT_SINGLE_THREAD_CHECK();
4979 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
4980 << GLES2Util::GetStringTextureTarget(target
) << ", "
4982 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
4983 << width
<< ", " << height
<< ", " << border
<< ", "
4984 << GLES2Util::GetStringTextureFormat(format
) << ", "
4985 << GLES2Util::GetStringPixelType(type
) << ", "
4986 << static_cast<const void*>(pixels
) << ")");
4987 if (level
< 0 || height
< 0 || width
< 0) {
4988 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
4992 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "border != 0");
4996 uint32 unpadded_row_size
;
4997 uint32 padded_row_size
;
4998 if (!GLES2Util::ComputeImageDataSizes(
4999 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5000 &unpadded_row_size
, &padded_row_size
)) {
5001 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
5005 // If there's no data/buffer just issue the AsyncTexImage2D
5006 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
5007 helper_
->AsyncTexImage2DCHROMIUM(
5008 target
, level
, internalformat
, width
, height
, format
, type
,
5013 if (!EnsureAsyncUploadSync()) {
5014 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5018 // Otherwise, async uploads require a transfer buffer to be bound.
5019 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5020 // the buffer before the transfer is finished. (Currently such
5021 // synchronization has to be handled manually.)
5022 GLuint offset
= ToGLuint(pixels
);
5023 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5024 bound_pixel_unpack_transfer_buffer_id_
,
5025 "glAsyncTexImage2DCHROMIUM", offset
, size
);
5026 if (buffer
&& buffer
->shm_id() != -1) {
5027 uint32 async_token
= NextAsyncUploadToken();
5028 buffer
->set_last_async_upload_token(async_token
);
5029 helper_
->AsyncTexImage2DCHROMIUM(
5030 target
, level
, internalformat
, width
, height
, format
, type
,
5031 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5033 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5037 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
5038 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
5039 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
5040 GPU_CLIENT_SINGLE_THREAD_CHECK();
5041 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
5042 << GLES2Util::GetStringTextureTarget(target
) << ", "
5044 << xoffset
<< ", " << yoffset
<< ", "
5045 << width
<< ", " << height
<< ", "
5046 << GLES2Util::GetStringTextureFormat(format
) << ", "
5047 << GLES2Util::GetStringPixelType(type
) << ", "
5048 << static_cast<const void*>(pixels
) << ")");
5049 if (level
< 0 || height
< 0 || width
< 0) {
5051 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
5056 uint32 unpadded_row_size
;
5057 uint32 padded_row_size
;
5058 if (!GLES2Util::ComputeImageDataSizes(
5059 width
, height
, 1, format
, type
, unpack_alignment_
, &size
,
5060 &unpadded_row_size
, &padded_row_size
)) {
5062 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
5066 if (!EnsureAsyncUploadSync()) {
5067 SetGLError(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
5071 // Async uploads require a transfer buffer to be bound.
5072 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
5073 // the buffer before the transfer is finished. (Currently such
5074 // synchronization has to be handled manually.)
5075 GLuint offset
= ToGLuint(pixels
);
5076 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
5077 bound_pixel_unpack_transfer_buffer_id_
,
5078 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
5079 if (buffer
&& buffer
->shm_id() != -1) {
5080 uint32 async_token
= NextAsyncUploadToken();
5081 buffer
->set_last_async_upload_token(async_token
);
5082 helper_
->AsyncTexSubImage2DCHROMIUM(
5083 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
5084 buffer
->shm_id(), buffer
->shm_offset() + offset
,
5086 async_upload_sync_shm_id_
, async_upload_sync_shm_offset_
);
5090 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
5091 GPU_CLIENT_SINGLE_THREAD_CHECK();
5092 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
5093 << GLES2Util::GetStringTextureTarget(target
) << ")");
5094 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
5098 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() {
5099 GPU_CLIENT_SINGLE_THREAD_CHECK();
5100 GPU_CLIENT_LOG("[" << GetLogPrefix()
5101 << "] glWaitAllAsyncTexImage2DCHROMIUM()");
5102 helper_
->WaitAllAsyncTexImage2DCHROMIUM();
5106 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
5107 GPU_CLIENT_SINGLE_THREAD_CHECK();
5108 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
5109 helper_
->CommandBufferHelper::Flush();
5110 return gpu_control_
->InsertSyncPoint();
5113 GLuint
GLES2Implementation::InsertFutureSyncPointCHROMIUM() {
5114 GPU_CLIENT_SINGLE_THREAD_CHECK();
5115 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertFutureSyncPointCHROMIUM");
5116 DCHECK(capabilities_
.future_sync_points
);
5117 return gpu_control_
->InsertFutureSyncPoint();
5120 void GLES2Implementation::RetireSyncPointCHROMIUM(GLuint sync_point
) {
5121 GPU_CLIENT_SINGLE_THREAD_CHECK();
5122 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRetireSyncPointCHROMIUM("
5123 << sync_point
<< ")");
5124 DCHECK(capabilities_
.future_sync_points
);
5125 helper_
->CommandBufferHelper::Flush();
5126 gpu_control_
->RetireSyncPoint(sync_point
);
5131 bool ValidImageFormat(GLenum internalformat
) {
5132 switch (internalformat
) {
5143 bool ValidImageUsage(GLenum usage
) {
5145 case GL_MAP_CHROMIUM
:
5146 case GL_SCANOUT_CHROMIUM
:
5155 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(ClientBuffer buffer
,
5158 GLenum internalformat
) {
5160 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
5165 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
5169 if (!ValidImageFormat(internalformat
)) {
5170 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "invalid format");
5175 gpu_control_
->CreateImage(buffer
, width
, height
, internalformat
);
5177 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "image_id < 0");
5183 GLuint
GLES2Implementation::CreateImageCHROMIUM(ClientBuffer buffer
,
5186 GLenum internalformat
) {
5187 GPU_CLIENT_SINGLE_THREAD_CHECK();
5188 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" << width
5189 << ", " << height
<< ", "
5190 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5193 CreateImageCHROMIUMHelper(buffer
, width
, height
, internalformat
);
5198 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
5199 // Flush the command stream to make sure all pending commands
5200 // that may refer to the image_id are executed on the service side.
5201 helper_
->CommandBufferHelper::Flush();
5202 gpu_control_
->DestroyImage(image_id
);
5205 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
5206 GPU_CLIENT_SINGLE_THREAD_CHECK();
5207 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
5208 << image_id
<< ")");
5209 DestroyImageCHROMIUMHelper(image_id
);
5213 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUMHelper(
5216 GLenum internalformat
,
5220 GL_INVALID_VALUE
, "glCreateGpuMemoryBufferImageCHROMIUM", "width <= 0");
5225 SetGLError(GL_INVALID_VALUE
,
5226 "glCreateGpuMemoryBufferImageCHROMIUM",
5231 if (!ValidImageFormat(internalformat
)) {
5232 SetGLError(GL_INVALID_VALUE
,
5233 "glCreateGpuMemoryBufferImageCHROMIUM",
5238 if (!ValidImageUsage(usage
)) {
5239 SetGLError(GL_INVALID_VALUE
,
5240 "glCreateGpuMemoryBufferImageCHROMIUM",
5245 // Flush the command stream to ensure ordering in case the newly
5246 // returned image_id has recently been in use with a different buffer.
5247 helper_
->CommandBufferHelper::Flush();
5248 int32_t image_id
= gpu_control_
->CreateGpuMemoryBufferImage(
5249 width
, height
, internalformat
, usage
);
5251 SetGLError(GL_OUT_OF_MEMORY
,
5252 "glCreateGpuMemoryBufferImageCHROMIUM",
5259 GLuint
GLES2Implementation::CreateGpuMemoryBufferImageCHROMIUM(
5262 GLenum internalformat
,
5264 GPU_CLIENT_SINGLE_THREAD_CHECK();
5265 GPU_CLIENT_LOG("[" << GetLogPrefix()
5266 << "] glCreateGpuMemoryBufferImageCHROMIUM(" << width
5267 << ", " << height
<< ", "
5268 << GLES2Util::GetStringImageInternalFormat(internalformat
)
5269 << ", " << GLES2Util::GetStringImageUsage(usage
) << ")");
5270 GLuint image_id
= CreateGpuMemoryBufferImageCHROMIUMHelper(
5271 width
, height
, internalformat
, usage
);
5276 bool GLES2Implementation::ValidateSize(const char* func
, GLsizeiptr size
) {
5278 SetGLError(GL_INVALID_VALUE
, func
, "size < 0");
5281 if (!base::IsValueInRangeForNumericType
<int32_t>(size
)) {
5282 SetGLError(GL_INVALID_OPERATION
, func
, "size more than 32-bit");
5288 bool GLES2Implementation::ValidateOffset(const char* func
, GLintptr offset
) {
5290 SetGLError(GL_INVALID_VALUE
, func
, "offset < 0");
5293 if (!base::IsValueInRangeForNumericType
<int32_t>(offset
)) {
5294 SetGLError(GL_INVALID_OPERATION
, func
, "offset more than 32-bit");
5300 bool GLES2Implementation::GetSamplerParameterfvHelper(
5301 GLuint
/* sampler */, GLenum
/* pname */, GLfloat
* /* params */) {
5302 // TODO(zmo): Implement client side caching.
5306 bool GLES2Implementation::GetSamplerParameterivHelper(
5307 GLuint
/* sampler */, GLenum
/* pname */, GLint
* /* params */) {
5308 // TODO(zmo): Implement client side caching.
5312 bool GLES2Implementation::PackStringsToBucket(GLsizei count
,
5313 const char* const* str
,
5314 const GLint
* length
,
5315 const char* func_name
) {
5316 DCHECK_LE(0, count
);
5317 // Compute the total size.
5318 base::CheckedNumeric
<size_t> total_size
= count
;
5320 total_size
*= sizeof(GLint
);
5321 if (!total_size
.IsValid()) {
5322 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5325 size_t header_size
= total_size
.ValueOrDefault(0);
5326 std::vector
<GLint
> header(count
+ 1);
5327 header
[0] = static_cast<GLint
>(count
);
5328 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5331 len
= (length
&& length
[ii
] >= 0)
5333 : base::checked_cast
<GLint
>(strlen(str
[ii
]));
5336 total_size
+= 1; // NULL at the end of each char array.
5337 if (!total_size
.IsValid()) {
5338 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5341 header
[ii
+ 1] = len
;
5343 // Pack data into a bucket on the service.
5344 helper_
->SetBucketSize(kResultBucketId
, total_size
.ValueOrDefault(0));
5346 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
5348 (ii
== 0) ? reinterpret_cast<const char*>(&header
[0]) : str
[ii
- 1];
5349 base::CheckedNumeric
<size_t> checked_size
=
5350 (ii
== 0) ? header_size
: static_cast<size_t>(header
[ii
]);
5352 checked_size
+= 1; // NULL in the end.
5354 if (!checked_size
.IsValid()) {
5355 SetGLError(GL_INVALID_VALUE
, func_name
, "overflow");
5358 size_t size
= checked_size
.ValueOrDefault(0);
5360 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
5361 if (!buffer
.valid() || buffer
.size() == 0) {
5362 SetGLError(GL_OUT_OF_MEMORY
, func_name
, "too large");
5365 size_t copy_size
= buffer
.size();
5366 if (ii
> 0 && buffer
.size() == size
)
5369 memcpy(buffer
.address(), src
, copy_size
);
5370 if (copy_size
< buffer
.size()) {
5371 // Append NULL in the end.
5372 DCHECK(copy_size
+ 1 == buffer
.size());
5373 char* str
= reinterpret_cast<char*>(buffer
.address());
5376 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
5377 buffer
.shm_id(), buffer
.offset());
5378 offset
+= buffer
.size();
5379 src
+= buffer
.size();
5380 size
-= buffer
.size();
5383 DCHECK_EQ(total_size
.ValueOrDefault(0), offset
);
5387 void GLES2Implementation::UniformBlockBinding(GLuint program
,
5390 GPU_CLIENT_SINGLE_THREAD_CHECK();
5391 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
5392 << ", " << index
<< ", " << binding
<< ")");
5393 share_group_
->program_info_manager()->UniformBlockBinding(
5394 this, program
, index
, binding
);
5395 helper_
->UniformBlockBinding(program
, index
, binding
);
5399 GLenum
GLES2Implementation::ClientWaitSync(
5400 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5401 GPU_CLIENT_SINGLE_THREAD_CHECK();
5402 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync
5403 << ", " << flags
<< ", " << timeout
<< ")");
5404 typedef cmds::ClientWaitSync::Result Result
;
5405 Result
* result
= GetResultAs
<Result
*>();
5407 SetGLError(GL_OUT_OF_MEMORY
, "ClientWaitSync", "");
5408 return GL_WAIT_FAILED
;
5410 *result
= GL_WAIT_FAILED
;
5411 uint32_t v32_0
= 0, v32_1
= 0;
5412 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5413 helper_
->ClientWaitSync(
5414 ToGLuint(sync
), flags
, v32_0
, v32_1
,
5415 GetResultShmId(), GetResultShmOffset());
5417 GPU_CLIENT_LOG("returned " << *result
);
5422 void GLES2Implementation::WaitSync(
5423 GLsync sync
, GLbitfield flags
, GLuint64 timeout
) {
5424 GPU_CLIENT_SINGLE_THREAD_CHECK();
5425 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitSync(" << sync
<< ", "
5426 << flags
<< ", " << timeout
<< ")");
5427 uint32_t v32_0
= 0, v32_1
= 0;
5428 GLES2Util::MapUint64ToTwoUint32(timeout
, &v32_0
, &v32_1
);
5429 helper_
->WaitSync(ToGLuint(sync
), flags
, v32_0
, v32_1
);
5433 // Include the auto-generated part of this file. We split this because it means
5434 // we can easily edit the non-auto generated parts right here in this file
5435 // instead of having to edit some template or the code generator.
5436 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
5438 } // namespace gles2