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"
16 #include <GLES2/gl2ext.h>
17 #include <GLES2/gl2extchromium.h>
18 #include "gpu/command_buffer/client/buffer_tracker.h"
19 #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
20 #include "gpu/command_buffer/client/program_info_manager.h"
21 #include "gpu/command_buffer/client/query_tracker.h"
22 #include "gpu/command_buffer/client/transfer_buffer.h"
23 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
24 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
25 #include "gpu/command_buffer/common/trace_event.h"
26 #include "ui/gfx/gpu_memory_buffer.h"
28 #if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
29 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
32 #if defined(GPU_CLIENT_DEBUG)
33 #include "ui/gl/gl_switches.h"
34 #include "base/command_line.h"
40 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
41 static GLuint
ToGLuint(const void* ptr
) {
42 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
45 #if !defined(_MSC_VER)
46 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
47 const unsigned int GLES2Implementation::kStartingOffset
;
50 GLES2Implementation::GLStaticState::GLStaticState() {
53 GLES2Implementation::GLStaticState::~GLStaticState() {
56 GLES2Implementation::GLStaticState::IntState::IntState()
57 : max_combined_texture_image_units(0),
58 max_cube_map_texture_size(0),
59 max_fragment_uniform_vectors(0),
60 max_renderbuffer_size(0),
61 max_texture_image_units(0),
63 max_varying_vectors(0),
64 max_vertex_attribs(0),
65 max_vertex_texture_image_units(0),
66 max_vertex_uniform_vectors(0),
67 num_compressed_texture_formats(0),
68 num_shader_binary_formats(0) {
71 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
72 GLES2Implementation
* gles2_implementation
)
73 : gles2_implementation_(gles2_implementation
) {
74 GPU_CHECK_EQ(0, gles2_implementation_
->use_count_
);
75 ++gles2_implementation_
->use_count_
;
78 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
79 --gles2_implementation_
->use_count_
;
80 GPU_CHECK_EQ(0, gles2_implementation_
->use_count_
);
83 GLES2Implementation::GLES2Implementation(
84 GLES2CmdHelper
* helper
,
85 ShareGroup
* share_group
,
86 TransferBufferInterface
* transfer_buffer
,
87 bool bind_generates_resource
,
88 GpuControl
* gpu_control
)
90 transfer_buffer_(transfer_buffer
),
91 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
92 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
95 unpack_flip_y_(false),
96 unpack_row_length_(0),
98 unpack_skip_pixels_(0),
99 pack_reverse_row_order_(false),
100 active_texture_unit_(0),
101 bound_framebuffer_(0),
102 bound_read_framebuffer_(0),
103 bound_renderbuffer_(0),
105 bound_array_buffer_id_(0),
106 bound_pixel_pack_transfer_buffer_id_(0),
107 bound_pixel_unpack_transfer_buffer_id_(0),
111 current_query_(NULL
),
112 error_message_callback_(NULL
),
113 gpu_control_(gpu_control
) {
115 GPU_DCHECK(transfer_buffer
);
118 sprintf(temp
, "%p", static_cast<void*>(this));
119 this_in_hex_
= std::string(temp
);
121 GPU_CLIENT_LOG_CODE_BLOCK({
122 debug_
= CommandLine::ForCurrentProcess()->HasSwitch(
123 switches::kEnableGPUClientLogging
);
127 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
129 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
132 bool GLES2Implementation::Initialize(
133 unsigned int starting_transfer_buffer_size
,
134 unsigned int min_transfer_buffer_size
,
135 unsigned int max_transfer_buffer_size
,
136 unsigned int mapped_memory_limit
) {
137 GPU_DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
138 GPU_DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
139 GPU_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(new MappedMemoryManager(helper_
, mapped_memory_limit
));
152 mapped_memory_
->set_chunk_size_multiple(2 * 1024 * 1024);
154 if (!QueryAndCacheStaticState())
157 util_
.set_num_compressed_texture_formats(
158 static_state_
.int_state
.num_compressed_texture_formats
);
159 util_
.set_num_shader_binary_formats(
160 static_state_
.int_state
.num_shader_binary_formats
);
162 texture_units_
.reset(
164 static_state_
.int_state
.max_combined_texture_image_units
]);
166 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
167 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
168 gpu_memory_buffer_tracker_
.reset(new GpuMemoryBufferTracker(gpu_control_
));
170 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
171 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
172 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
175 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
176 static_state_
.int_state
.max_vertex_attribs
,
183 bool GLES2Implementation::QueryAndCacheStaticState() {
184 // Setup query for multiple GetIntegerv's
185 static const GLenum pnames
[] = {
186 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
187 GL_MAX_CUBE_MAP_TEXTURE_SIZE
,
188 GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
189 GL_MAX_RENDERBUFFER_SIZE
,
190 GL_MAX_TEXTURE_IMAGE_UNITS
,
192 GL_MAX_VARYING_VECTORS
,
193 GL_MAX_VERTEX_ATTRIBS
,
194 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
195 GL_MAX_VERTEX_UNIFORM_VECTORS
,
196 GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
197 GL_NUM_SHADER_BINARY_FORMATS
,
200 GetMultipleIntegervState
integerv_state(
201 pnames
, arraysize(pnames
),
202 &static_state_
.int_state
.max_combined_texture_image_units
,
203 sizeof(static_state_
.int_state
));
204 if (!GetMultipleIntegervSetup(&integerv_state
)) {
208 // Setup query for multiple GetShaderPrecisionFormat's
209 static const GLenum precision_params
[][2] = {
210 { GL_VERTEX_SHADER
, GL_LOW_INT
},
211 { GL_VERTEX_SHADER
, GL_MEDIUM_INT
},
212 { GL_VERTEX_SHADER
, GL_HIGH_INT
},
213 { GL_VERTEX_SHADER
, GL_LOW_FLOAT
},
214 { GL_VERTEX_SHADER
, GL_MEDIUM_FLOAT
},
215 { GL_VERTEX_SHADER
, GL_HIGH_FLOAT
},
216 { GL_FRAGMENT_SHADER
, GL_LOW_INT
},
217 { GL_FRAGMENT_SHADER
, GL_MEDIUM_INT
},
218 { GL_FRAGMENT_SHADER
, GL_HIGH_INT
},
219 { GL_FRAGMENT_SHADER
, GL_LOW_FLOAT
},
220 { GL_FRAGMENT_SHADER
, GL_MEDIUM_FLOAT
},
221 { GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
},
224 GetAllShaderPrecisionFormatsState
precision_state(
225 precision_params
, arraysize(precision_params
));
226 GetAllShaderPrecisionFormatsSetup(&precision_state
);
228 // Allocate and partition transfer buffer for all requests
229 void* buffer
= transfer_buffer_
->Alloc(
230 integerv_state
.transfer_buffer_size_needed
+
231 precision_state
.transfer_buffer_size_needed
);
233 SetGLError(GL_OUT_OF_MEMORY
, "QueryAndCacheStaticState",
234 "Transfer buffer allocation failed.");
237 integerv_state
.buffer
= buffer
;
238 precision_state
.results_buffer
=
239 static_cast<char*>(buffer
) + integerv_state
.transfer_buffer_size_needed
;
241 // Make all the requests and wait once for all the results.
242 GetMultipleIntegervRequest(&integerv_state
);
243 GetAllShaderPrecisionFormatsRequest(&precision_state
);
245 GetMultipleIntegervOnCompleted(&integerv_state
);
246 GetAllShaderPrecisionFormatsOnCompleted(&precision_state
);
248 // TODO(gman): We should be able to free without a token.
249 transfer_buffer_
->FreePendingToken(buffer
, helper_
->InsertToken());
255 GLES2Implementation::~GLES2Implementation() {
256 // Make sure the queries are finished otherwise we'll delete the
257 // shared memory (mapped_memory_) which will free the memory used
258 // by the queries. The GPU process when validating that memory is still
259 // shared will fail and abort (ie, it will stop running).
261 query_tracker_
.reset();
263 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
264 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
266 buffer_tracker_
.reset();
268 // Make sure the commands make it the service.
272 GLES2CmdHelper
* GLES2Implementation::helper() const {
276 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
277 return share_group_
->GetIdHandler(namespace_id
);
280 void* GLES2Implementation::GetResultBuffer() {
281 return transfer_buffer_
->GetResultBuffer();
284 int32
GLES2Implementation::GetResultShmId() {
285 return transfer_buffer_
->GetShmId();
288 uint32
GLES2Implementation::GetResultShmOffset() {
289 return transfer_buffer_
->GetResultOffset();
292 void GLES2Implementation::FreeUnusedSharedMemory() {
293 mapped_memory_
->FreeUnused();
296 void GLES2Implementation::FreeEverything() {
298 query_tracker_
->Shrink();
299 FreeUnusedSharedMemory();
300 transfer_buffer_
->Free();
301 helper_
->FreeRingBuffer();
304 void GLES2Implementation::WaitForCmd() {
305 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
306 helper_
->CommandBufferHelper::Finish();
309 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
310 const char* extensions
=
311 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
315 int length
= strlen(ext
);
317 int n
= strcspn(extensions
, " ");
318 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
321 if ('\0' == extensions
[n
]) {
328 bool GLES2Implementation::IsExtensionAvailableHelper(
329 const char* extension
, ExtensionStatus
* status
) {
331 case kAvailableExtensionStatus
:
333 case kUnavailableExtensionStatus
:
336 bool available
= IsExtensionAvailable(extension
);
337 *status
= available
? kAvailableExtensionStatus
:
338 kUnavailableExtensionStatus
;
344 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
345 return IsExtensionAvailableHelper(
346 "GL_ANGLE_pack_reverse_row_order",
347 &angle_pack_reverse_row_order_status_
);
350 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
351 return IsExtensionAvailableHelper(
352 "GL_CHROMIUM_framebuffer_multisample",
353 &chromium_framebuffer_multisample_
);
356 const std::string
& GLES2Implementation::GetLogPrefix() const {
357 const std::string
& prefix(debug_marker_manager_
.GetMarker());
358 return prefix
.empty() ? this_in_hex_
: prefix
;
361 GLenum
GLES2Implementation::GetError() {
362 GPU_CLIENT_SINGLE_THREAD_CHECK();
363 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
364 GLenum err
= GetGLError();
365 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
369 GLenum
GLES2Implementation::GetClientSideGLError() {
370 if (error_bits_
== 0) {
374 GLenum error
= GL_NO_ERROR
;
375 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
376 if ((error_bits_
& mask
) != 0) {
377 error
= GLES2Util::GLErrorBitToGLError(mask
);
381 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
385 GLenum
GLES2Implementation::GetGLError() {
386 TRACE_EVENT0("gpu", "GLES2::GetGLError");
387 // Check the GL error first, then our wrapped error.
388 typedef cmds::GetError::Result Result
;
389 Result
* result
= GetResultAs
<Result
*>();
390 // If we couldn't allocate a result the context is lost.
394 *result
= GL_NO_ERROR
;
395 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
397 GLenum error
= *result
;
398 if (error
== GL_NO_ERROR
) {
399 error
= GetClientSideGLError();
401 // There was an error, clear the corresponding wrapped error.
402 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
407 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
408 void GLES2Implementation::FailGLError(GLenum error
) {
409 if (error
!= GL_NO_ERROR
) {
410 GPU_NOTREACHED() << "Error";
413 // NOTE: Calling GetGLError overwrites data in the result buffer.
414 void GLES2Implementation::CheckGLError() {
415 FailGLError(GetGLError());
417 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
419 void GLES2Implementation::SetGLError(
420 GLenum error
, const char* function_name
, const char* msg
) {
421 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
422 << GLES2Util::GetStringError(error
) << ": "
423 << function_name
<< ": " << msg
);
428 if (error_message_callback_
) {
429 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
430 function_name
+ ": " + (msg
? msg
: ""));
431 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
433 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
436 void GLES2Implementation::SetGLErrorInvalidEnum(
437 const char* function_name
, GLenum value
, const char* label
) {
438 SetGLError(GL_INVALID_ENUM
, function_name
,
439 (std::string(label
) + " was " +
440 GLES2Util::GetStringEnum(value
)).c_str());
443 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
444 std::vector
<int8
>* data
) {
445 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
447 const uint32 kStartSize
= 32 * 1024;
448 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
449 if (!buffer
.valid()) {
452 typedef cmd::GetBucketStart::Result Result
;
453 Result
* result
= GetResultAs
<Result
*>();
458 helper_
->GetBucketStart(
459 bucket_id
, GetResultShmId(), GetResultShmOffset(),
460 buffer
.size(), buffer
.shm_id(), buffer
.offset());
462 uint32 size
= *result
;
467 if (!buffer
.valid()) {
469 if (!buffer
.valid()) {
472 helper_
->GetBucketData(
473 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
476 uint32 size_to_copy
= std::min(size
, buffer
.size());
477 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
478 offset
+= size_to_copy
;
479 size
-= size_to_copy
;
482 // Free the bucket. This is not required but it does free up the memory.
483 // and we don't have to wait for the result so from the client's perspective
485 helper_
->SetBucketSize(bucket_id
, 0);
490 void GLES2Implementation::SetBucketContents(
491 uint32 bucket_id
, const void* data
, size_t size
) {
493 helper_
->SetBucketSize(bucket_id
, size
);
497 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
498 if (!buffer
.valid()) {
501 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
503 helper_
->SetBucketData(
504 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
505 offset
+= buffer
.size();
506 size
-= buffer
.size();
511 void GLES2Implementation::SetBucketAsCString(
512 uint32 bucket_id
, const char* str
) {
513 // NOTE: strings are passed NULL terminated. That means the empty
514 // string will have a size of 1 and no-string will have a size of 0
516 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
518 helper_
->SetBucketSize(bucket_id
, 0);
522 bool GLES2Implementation::GetBucketAsString(
523 uint32 bucket_id
, std::string
* str
) {
525 std::vector
<int8
> data
;
526 // NOTE: strings are passed NULL terminated. That means the empty
527 // string will have a size of 1 and no-string will have a size of 0
528 if (!GetBucketContents(bucket_id
, &data
)) {
534 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
538 void GLES2Implementation::SetBucketAsString(
539 uint32 bucket_id
, const std::string
& str
) {
540 // NOTE: strings are passed NULL terminated. That means the empty
541 // string will have a size of 1 and no-string will have a size of 0
542 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
545 void GLES2Implementation::Disable(GLenum cap
) {
546 GPU_CLIENT_SINGLE_THREAD_CHECK();
547 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
548 << GLES2Util::GetStringCapability(cap
) << ")");
549 bool changed
= false;
550 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
551 helper_
->Disable(cap
);
556 void GLES2Implementation::Enable(GLenum cap
) {
557 GPU_CLIENT_SINGLE_THREAD_CHECK();
558 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
559 << GLES2Util::GetStringCapability(cap
) << ")");
560 bool changed
= false;
561 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
562 helper_
->Enable(cap
);
567 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
568 GPU_CLIENT_SINGLE_THREAD_CHECK();
569 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
570 << GLES2Util::GetStringCapability(cap
) << ")");
572 if (!state_
.GetEnabled(cap
, &state
)) {
573 typedef cmds::IsEnabled::Result Result
;
574 Result
* result
= GetResultAs
<Result
*>();
579 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
581 state
= (*result
) != 0;
584 GPU_CLIENT_LOG("returned " << state
);
589 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
591 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
592 *params
= static_state_
.int_state
.max_combined_texture_image_units
;
594 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
595 *params
= static_state_
.int_state
.max_cube_map_texture_size
;
597 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
598 *params
= static_state_
.int_state
.max_fragment_uniform_vectors
;
600 case GL_MAX_RENDERBUFFER_SIZE
:
601 *params
= static_state_
.int_state
.max_renderbuffer_size
;
603 case GL_MAX_TEXTURE_IMAGE_UNITS
:
604 *params
= static_state_
.int_state
.max_texture_image_units
;
606 case GL_MAX_TEXTURE_SIZE
:
607 *params
= static_state_
.int_state
.max_texture_size
;
609 case GL_MAX_VARYING_VECTORS
:
610 *params
= static_state_
.int_state
.max_varying_vectors
;
612 case GL_MAX_VERTEX_ATTRIBS
:
613 *params
= static_state_
.int_state
.max_vertex_attribs
;
615 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
616 *params
= static_state_
.int_state
.max_vertex_texture_image_units
;
618 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
619 *params
= static_state_
.int_state
.max_vertex_uniform_vectors
;
621 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
622 *params
= static_state_
.int_state
.num_compressed_texture_formats
;
624 case GL_NUM_SHADER_BINARY_FORMATS
:
625 *params
= static_state_
.int_state
.num_shader_binary_formats
;
627 case GL_ARRAY_BUFFER_BINDING
:
628 if (share_group_
->bind_generates_resource()) {
629 *params
= bound_array_buffer_id_
;
633 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
634 if (share_group_
->bind_generates_resource()) {
636 vertex_array_object_manager_
->bound_element_array_buffer();
640 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
641 *params
= bound_pixel_pack_transfer_buffer_id_
;
643 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
644 *params
= bound_pixel_unpack_transfer_buffer_id_
;
646 case GL_ACTIVE_TEXTURE
:
647 *params
= active_texture_unit_
+ GL_TEXTURE0
;
649 case GL_TEXTURE_BINDING_2D
:
650 if (share_group_
->bind_generates_resource()) {
651 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
655 case GL_TEXTURE_BINDING_CUBE_MAP
:
656 if (share_group_
->bind_generates_resource()) {
657 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
661 case GL_FRAMEBUFFER_BINDING
:
662 if (share_group_
->bind_generates_resource()) {
663 *params
= bound_framebuffer_
;
667 case GL_READ_FRAMEBUFFER_BINDING
:
668 if (IsChromiumFramebufferMultisampleAvailable() &&
669 share_group_
->bind_generates_resource()) {
670 *params
= bound_read_framebuffer_
;
674 case GL_RENDERBUFFER_BINDING
:
675 if (share_group_
->bind_generates_resource()) {
676 *params
= bound_renderbuffer_
;
685 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
686 // TODO(gman): Make this handle pnames that return more than 1 value.
688 if (!GetHelper(pname
, &value
)) {
691 *params
= static_cast<GLboolean
>(value
);
695 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
696 // TODO(gman): Make this handle pnames that return more than 1 value.
698 if (!GetHelper(pname
, &value
)) {
701 *params
= static_cast<GLfloat
>(value
);
705 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
706 return GetHelper(pname
, params
);
709 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
710 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
711 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
712 Result
* result
= GetResultAs
<Result
*>();
717 helper_
->GetMaxValueInBufferCHROMIUM(
718 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
723 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
724 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
725 GPU_CLIENT_SINGLE_THREAD_CHECK();
726 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
727 << buffer_id
<< ", " << count
<< ", "
728 << GLES2Util::GetStringGetMaxIndexType(type
)
729 << ", " << offset
<< ")");
730 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
731 buffer_id
, count
, type
, offset
);
732 GPU_CLIENT_LOG("returned " << result
);
737 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
739 RestoreArrayBuffer(restore
);
740 // Restore the element array binding.
741 // We only need to restore it if it wasn't a client side array.
742 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
743 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
748 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
750 // Restore the user's current binding.
751 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_id_
);
755 void GLES2Implementation::DrawElements(
756 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
757 GPU_CLIENT_SINGLE_THREAD_CHECK();
758 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
759 << GLES2Util::GetStringDrawMode(mode
) << ", "
761 << GLES2Util::GetStringIndexType(type
) << ", "
762 << static_cast<const void*>(indices
) << ")");
764 SetGLError(GL_INVALID_VALUE
, "glDrawElements", "count less than 0.");
771 bool simulated
= false;
772 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
773 "glDrawElements", this, helper_
, count
, type
, 0, indices
,
774 &offset
, &simulated
)) {
777 helper_
->DrawElements(mode
, count
, type
, offset
);
778 RestoreElementAndArrayBuffers(simulated
);
782 void GLES2Implementation::Flush() {
783 GPU_CLIENT_SINGLE_THREAD_CHECK();
784 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
785 // Insert the cmd to call glFlush
787 // Flush our command buffer
788 // (tell the service to execute up to the flush cmd.)
789 helper_
->CommandBufferHelper::Flush();
792 void GLES2Implementation::ShallowFlushCHROMIUM() {
793 GPU_CLIENT_SINGLE_THREAD_CHECK();
794 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
795 // Flush our command buffer
796 // (tell the service to execute up to the flush cmd.)
797 helper_
->CommandBufferHelper::Flush();
800 void GLES2Implementation::Finish() {
801 GPU_CLIENT_SINGLE_THREAD_CHECK();
805 void GLES2Implementation::ShallowFinishCHROMIUM() {
806 GPU_CLIENT_SINGLE_THREAD_CHECK();
807 // Flush our command buffer (tell the service to execute up to the flush cmd
808 // and don't return until it completes).
809 helper_
->CommandBufferHelper::Finish();
812 bool GLES2Implementation::MustBeContextLost() {
813 bool context_lost
= helper_
->IsContextLost();
816 context_lost
= helper_
->IsContextLost();
818 GPU_CHECK(context_lost
);
822 void GLES2Implementation::FinishHelper() {
823 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
824 TRACE_EVENT0("gpu", "GLES2::Finish");
825 // Insert the cmd to call glFinish
827 // Finish our command buffer
828 // (tell the service to execute up to the Finish cmd and wait for it to
830 helper_
->CommandBufferHelper::Finish();
833 void GLES2Implementation::SwapBuffers() {
834 GPU_CLIENT_SINGLE_THREAD_CHECK();
835 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
836 // TODO(piman): Strictly speaking we'd want to insert the token after the
837 // swap, but the state update with the updated token might not have happened
838 // by the time the SwapBuffer callback gets called, forcing us to synchronize
839 // with the GPU process more than needed. So instead, make it happen before.
840 // All it means is that we could be slightly looser on the kMaxSwapBuffers
841 // semantics if the client doesn't use the callback mechanism, and by chance
842 // the scheduler yields between the InsertToken and the SwapBuffers.
843 swap_buffers_tokens_
.push(helper_
->InsertToken());
844 helper_
->SwapBuffers();
845 helper_
->CommandBufferHelper::Flush();
846 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
847 // compensate for TODO above.
848 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
849 helper_
->WaitForToken(swap_buffers_tokens_
.front());
850 swap_buffers_tokens_
.pop();
854 void GLES2Implementation::GenSharedIdsCHROMIUM(
855 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
856 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSharedIdsCHROMIUM("
857 << namespace_id
<< ", " << id_offset
<< ", " << n
<< ", " <<
858 static_cast<void*>(ids
) << ")");
859 TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM");
863 ScopedTransferBufferArray
<GLint
> id_buffer(num
, helper_
, transfer_buffer_
);
864 if (!id_buffer
.valid()) {
867 helper_
->GenSharedIdsCHROMIUM(
868 namespace_id
, id_offset
, id_buffer
.num_elements(),
869 id_buffer
.shm_id(), id_buffer
.offset());
871 memcpy(dst
, id_buffer
.address(), sizeof(*dst
) * id_buffer
.num_elements());
872 num
-= id_buffer
.num_elements();
873 dst
+= id_buffer
.num_elements();
875 GPU_CLIENT_LOG_CODE_BLOCK({
876 for (GLsizei i
= 0; i
< n
; ++i
) {
877 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
882 void GLES2Implementation::DeleteSharedIdsCHROMIUM(
883 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
884 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedIdsCHROMIUM("
885 << namespace_id
<< ", " << n
<< ", "
886 << static_cast<const void*>(ids
) << ")");
887 GPU_CLIENT_LOG_CODE_BLOCK({
888 for (GLsizei i
= 0; i
< n
; ++i
) {
889 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
892 TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM");
894 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
895 if (!id_buffer
.valid()) {
898 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
899 helper_
->DeleteSharedIdsCHROMIUM(
900 namespace_id
, id_buffer
.num_elements(),
901 id_buffer
.shm_id(), id_buffer
.offset());
903 n
-= id_buffer
.num_elements();
904 ids
+= id_buffer
.num_elements();
908 void GLES2Implementation::RegisterSharedIdsCHROMIUM(
909 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
910 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRegisterSharedIdsCHROMIUM("
911 << namespace_id
<< ", " << n
<< ", "
912 << static_cast<const void*>(ids
) << ")");
913 GPU_CLIENT_LOG_CODE_BLOCK({
914 for (GLsizei i
= 0; i
< n
; ++i
) {
915 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
918 TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM");
920 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
921 if (!id_buffer
.valid()) {
924 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
925 helper_
->RegisterSharedIdsCHROMIUM(
926 namespace_id
, id_buffer
.num_elements(),
927 id_buffer
.shm_id(), id_buffer
.offset());
929 n
-= id_buffer
.num_elements();
930 ids
+= id_buffer
.num_elements();
934 void GLES2Implementation::BindAttribLocation(
935 GLuint program
, GLuint index
, const char* name
) {
936 GPU_CLIENT_SINGLE_THREAD_CHECK();
937 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
938 << program
<< ", " << index
<< ", " << name
<< ")");
939 SetBucketAsString(kResultBucketId
, name
);
940 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
941 helper_
->SetBucketSize(kResultBucketId
, 0);
945 void GLES2Implementation::BindUniformLocationCHROMIUM(
946 GLuint program
, GLint location
, const char* name
) {
947 GPU_CLIENT_SINGLE_THREAD_CHECK();
948 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
949 << program
<< ", " << location
<< ", " << name
<< ")");
950 SetBucketAsString(kResultBucketId
, name
);
951 helper_
->BindUniformLocationCHROMIUMBucket(
952 program
, location
, kResultBucketId
);
953 helper_
->SetBucketSize(kResultBucketId
, 0);
957 void GLES2Implementation::GetVertexAttribPointerv(
958 GLuint index
, GLenum pname
, void** ptr
) {
959 GPU_CLIENT_SINGLE_THREAD_CHECK();
960 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
961 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
962 << static_cast<void*>(ptr
) << ")");
963 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
964 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
965 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
966 typedef cmds::GetVertexAttribPointerv::Result Result
;
967 Result
* result
= GetResultAs
<Result
*>();
971 result
->SetNumResults(0);
972 helper_
->GetVertexAttribPointerv(
973 index
, pname
, GetResultShmId(), GetResultShmOffset());
975 result
->CopyResult(ptr
);
976 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
978 GPU_CLIENT_LOG_CODE_BLOCK({
979 for (int32 i
= 0; i
< num_results
; ++i
) {
980 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
986 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
987 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
988 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
991 "glDeleteProgram", "id not created by this context.");
994 if (program
== current_program_
) {
995 current_program_
= 0;
1000 void GLES2Implementation::DeleteProgramStub(
1001 GLsizei n
, const GLuint
* programs
) {
1002 GPU_DCHECK_EQ(1, n
);
1003 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1004 helper_
->DeleteProgram(programs
[0]);
1007 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1008 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1009 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1012 "glDeleteShader", "id not created by this context.");
1018 void GLES2Implementation::DeleteShaderStub(
1019 GLsizei n
, const GLuint
* shaders
) {
1020 GPU_DCHECK_EQ(1, n
);
1021 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1022 helper_
->DeleteShader(shaders
[0]);
1026 GLint
GLES2Implementation::GetAttribLocationHelper(
1027 GLuint program
, const char* name
) {
1028 typedef cmds::GetAttribLocationBucket::Result Result
;
1029 Result
* result
= GetResultAs
<Result
*>();
1034 SetBucketAsCString(kResultBucketId
, name
);
1035 helper_
->GetAttribLocationBucket(
1036 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1038 helper_
->SetBucketSize(kResultBucketId
, 0);
1042 GLint
GLES2Implementation::GetAttribLocation(
1043 GLuint program
, const char* name
) {
1044 GPU_CLIENT_SINGLE_THREAD_CHECK();
1045 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1046 << ", " << name
<< ")");
1047 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1048 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1049 this, program
, name
);
1050 GPU_CLIENT_LOG("returned " << loc
);
1055 GLint
GLES2Implementation::GetUniformLocationHelper(
1056 GLuint program
, const char* name
) {
1057 typedef cmds::GetUniformLocationBucket::Result Result
;
1058 Result
* result
= GetResultAs
<Result
*>();
1063 SetBucketAsCString(kResultBucketId
, name
);
1064 helper_
->GetUniformLocationBucket(program
, kResultBucketId
,
1065 GetResultShmId(), GetResultShmOffset());
1067 helper_
->SetBucketSize(kResultBucketId
, 0);
1071 GLint
GLES2Implementation::GetUniformLocation(
1072 GLuint program
, const char* name
) {
1073 GPU_CLIENT_SINGLE_THREAD_CHECK();
1074 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1075 << ", " << name
<< ")");
1076 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1077 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1078 this, program
, name
);
1079 GPU_CLIENT_LOG("returned " << loc
);
1084 void GLES2Implementation::UseProgram(GLuint program
) {
1085 GPU_CLIENT_SINGLE_THREAD_CHECK();
1086 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program
<< ")");
1087 if (current_program_
!= program
) {
1088 current_program_
= program
;
1089 helper_
->UseProgram(program
);
1094 bool GLES2Implementation::GetProgramivHelper(
1095 GLuint program
, GLenum pname
, GLint
* params
) {
1096 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1097 this, program
, pname
, params
);
1098 GPU_CLIENT_LOG_CODE_BLOCK({
1100 GPU_CLIENT_LOG(" 0: " << *params
);
1106 void GLES2Implementation::LinkProgram(GLuint program
) {
1107 GPU_CLIENT_SINGLE_THREAD_CHECK();
1108 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1109 helper_
->LinkProgram(program
);
1110 share_group_
->program_info_manager()->CreateInfo(program
);
1114 void GLES2Implementation::ShaderBinary(
1115 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1117 GPU_CLIENT_SINGLE_THREAD_CHECK();
1118 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1119 << static_cast<const void*>(shaders
) << ", "
1120 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1121 << static_cast<const void*>(binary
) << ", "
1124 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1128 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1131 // TODO(gman): ShaderBinary should use buckets.
1132 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1133 ScopedTransferBufferArray
<GLint
> buffer(
1134 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1135 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1136 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1139 void* shader_ids
= buffer
.elements();
1140 void* shader_data
= buffer
.elements() + shader_id_size
;
1141 memcpy(shader_ids
, shaders
, shader_id_size
);
1142 memcpy(shader_data
, binary
, length
);
1143 helper_
->ShaderBinary(
1149 buffer
.offset() + shader_id_size
,
1154 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1155 GPU_CLIENT_SINGLE_THREAD_CHECK();
1156 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1157 << GLES2Util::GetStringPixelStore(pname
) << ", "
1160 case GL_PACK_ALIGNMENT
:
1161 pack_alignment_
= param
;
1163 case GL_UNPACK_ALIGNMENT
:
1164 unpack_alignment_
= param
;
1166 case GL_UNPACK_ROW_LENGTH
:
1167 unpack_row_length_
= param
;
1169 case GL_UNPACK_SKIP_ROWS
:
1170 unpack_skip_rows_
= param
;
1172 case GL_UNPACK_SKIP_PIXELS
:
1173 unpack_skip_pixels_
= param
;
1175 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1176 unpack_flip_y_
= (param
!= 0);
1178 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1179 pack_reverse_row_order_
=
1180 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1185 helper_
->PixelStorei(pname
, param
);
1190 void GLES2Implementation::VertexAttribPointer(
1191 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1193 GPU_CLIENT_SINGLE_THREAD_CHECK();
1194 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1197 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1198 << GLES2Util::GetStringBool(normalized
) << ", "
1200 << static_cast<const void*>(ptr
) << ")");
1201 // Record the info on the client side.
1202 if (!vertex_array_object_manager_
->SetAttribPointer(
1203 bound_array_buffer_id_
, index
, size
, type
, normalized
, stride
, ptr
)) {
1204 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1205 "client side arrays are not allowed in vertex array objects.");
1208 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1209 if (bound_array_buffer_id_
!= 0) {
1210 // Only report NON client side buffers to the service.
1211 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1214 #else // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1215 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1217 #endif // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1221 void GLES2Implementation::VertexAttribDivisorANGLE(
1222 GLuint index
, GLuint divisor
) {
1223 GPU_CLIENT_SINGLE_THREAD_CHECK();
1224 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1226 << divisor
<< ") ");
1227 // Record the info on the client side.
1228 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1229 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1233 void GLES2Implementation::ShaderSource(
1234 GLuint shader
, GLsizei count
, const GLchar
* const* source
, const GLint
* length
) {
1235 GPU_CLIENT_SINGLE_THREAD_CHECK();
1236 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderSource("
1237 << shader
<< ", " << count
<< ", "
1238 << static_cast<const void*>(source
) << ", "
1239 << static_cast<const void*>(length
) << ")");
1240 GPU_CLIENT_LOG_CODE_BLOCK({
1241 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1243 if (length
&& length
[ii
] >= 0) {
1244 std::string
str(source
[ii
], length
[ii
]);
1245 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << str
<< "\n---");
1247 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << source
[ii
] << "\n---");
1250 GPU_CLIENT_LOG(" " << ii
<< ": NULL");
1255 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "count < 0");
1259 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "shader == 0");
1263 // Compute the total size.
1264 uint32 total_size
= 1;
1265 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1267 total_size
+= (length
&& length
[ii
] >= 0) ?
1268 static_cast<size_t>(length
[ii
]) : strlen(source
[ii
]);
1272 // Concatenate all the strings in to a bucket on the service.
1273 helper_
->SetBucketSize(kResultBucketId
, total_size
);
1275 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
1276 const char* src
= ii
< count
? source
[ii
] : "";
1278 uint32 size
= ii
< count
?
1279 (length
? static_cast<size_t>(length
[ii
]) : strlen(src
)) : 1;
1281 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1282 if (!buffer
.valid()) {
1285 memcpy(buffer
.address(), src
, buffer
.size());
1286 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
1287 buffer
.shm_id(), buffer
.offset());
1288 offset
+= buffer
.size();
1289 src
+= buffer
.size();
1290 size
-= buffer
.size();
1295 GPU_DCHECK_EQ(total_size
, offset
);
1297 helper_
->ShaderSourceBucket(shader
, kResultBucketId
);
1298 helper_
->SetBucketSize(kResultBucketId
, 0);
1302 void GLES2Implementation::BufferDataHelper(
1303 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1305 SetGLError(GL_INVALID_VALUE
, "glBufferData", "size < 0");
1310 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1315 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1317 // Free buffer memory, pending the passage of a token.
1318 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
1320 // Remove old buffer.
1321 buffer_tracker_
->RemoveBuffer(buffer_id
);
1324 // Create new buffer.
1325 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1327 if (buffer
->address() && data
)
1328 memcpy(buffer
->address(), data
, size
);
1336 // If there is no data just send BufferData
1338 helper_
->BufferData(target
, size
, 0, 0, usage
);
1342 // See if we can send all at once.
1343 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1344 if (!buffer
.valid()) {
1348 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1349 memcpy(buffer
.address(), data
, size
);
1350 helper_
->BufferData(
1359 // Make the buffer with BufferData then send via BufferSubData
1360 helper_
->BufferData(target
, size
, 0, 0, usage
);
1361 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1365 void GLES2Implementation::BufferData(
1366 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1367 GPU_CLIENT_SINGLE_THREAD_CHECK();
1368 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1369 << GLES2Util::GetStringBufferTarget(target
) << ", "
1371 << static_cast<const void*>(data
) << ", "
1372 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1373 BufferDataHelper(target
, size
, data
, usage
);
1377 void GLES2Implementation::BufferSubDataHelper(
1378 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1384 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "size < 0");
1389 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1393 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1395 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1400 int32 buffer_size
= buffer
->size();
1401 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1402 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1406 if (buffer
->address() && data
)
1407 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1411 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1412 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1415 void GLES2Implementation::BufferSubDataHelperImpl(
1416 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1417 ScopedTransferBufferPtr
* buffer
) {
1419 GPU_DCHECK_GT(size
, 0);
1421 const int8
* source
= static_cast<const int8
*>(data
);
1423 if (!buffer
->valid() || buffer
->size() == 0) {
1424 buffer
->Reset(size
);
1425 if (!buffer
->valid()) {
1429 memcpy(buffer
->address(), source
, buffer
->size());
1430 helper_
->BufferSubData(
1431 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1432 offset
+= buffer
->size();
1433 source
+= buffer
->size();
1434 size
-= buffer
->size();
1439 void GLES2Implementation::BufferSubData(
1440 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1441 GPU_CLIENT_SINGLE_THREAD_CHECK();
1442 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1443 << GLES2Util::GetStringBufferTarget(target
) << ", "
1444 << offset
<< ", " << size
<< ", "
1445 << static_cast<const void*>(data
) << ")");
1446 BufferSubDataHelper(target
, offset
, size
, data
);
1450 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1452 const char* function_name
,
1453 GLuint
* buffer_id
) {
1457 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1458 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1460 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1461 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1468 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1473 BufferTracker::Buffer
*
1474 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1476 const char* function_name
,
1477 GLuint offset
, GLsizei size
)
1480 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1482 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1485 if (buffer
->mapped()) {
1486 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1489 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1490 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1496 void GLES2Implementation::CompressedTexImage2D(
1497 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1498 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1499 GPU_CLIENT_SINGLE_THREAD_CHECK();
1500 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1501 << GLES2Util::GetStringTextureTarget(target
) << ", "
1503 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1504 << width
<< ", " << height
<< ", " << border
<< ", "
1505 << image_size
<< ", "
1506 << static_cast<const void*>(data
) << ")");
1507 if (width
< 0 || height
< 0 || level
< 0) {
1508 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1511 if (height
== 0 || width
== 0) {
1514 // If there's a pixel unpack buffer bound use it when issuing
1515 // CompressedTexImage2D.
1516 if (bound_pixel_unpack_transfer_buffer_id_
) {
1517 GLuint offset
= ToGLuint(data
);
1518 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1519 bound_pixel_unpack_transfer_buffer_id_
,
1520 "glCompressedTexImage2D", offset
, image_size
);
1521 if (buffer
&& buffer
->shm_id() != -1) {
1522 helper_
->CompressedTexImage2D(
1523 target
, level
, internalformat
, width
, height
, border
, image_size
,
1524 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1525 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1529 SetBucketContents(kResultBucketId
, data
, image_size
);
1530 helper_
->CompressedTexImage2DBucket(
1531 target
, level
, internalformat
, width
, height
, border
, kResultBucketId
);
1532 // Free the bucket. This is not required but it does free up the memory.
1533 // and we don't have to wait for the result so from the client's perspective
1535 helper_
->SetBucketSize(kResultBucketId
, 0);
1539 void GLES2Implementation::CompressedTexSubImage2D(
1540 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1541 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1542 GPU_CLIENT_SINGLE_THREAD_CHECK();
1543 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1544 << GLES2Util::GetStringTextureTarget(target
) << ", "
1546 << xoffset
<< ", " << yoffset
<< ", "
1547 << width
<< ", " << height
<< ", "
1548 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1549 << image_size
<< ", "
1550 << static_cast<const void*>(data
) << ")");
1551 if (width
< 0 || height
< 0 || level
< 0) {
1552 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1555 // If there's a pixel unpack buffer bound use it when issuing
1556 // CompressedTexSubImage2D.
1557 if (bound_pixel_unpack_transfer_buffer_id_
) {
1558 GLuint offset
= ToGLuint(data
);
1559 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1560 bound_pixel_unpack_transfer_buffer_id_
,
1561 "glCompressedTexSubImage2D", offset
, image_size
);
1562 if (buffer
&& buffer
->shm_id() != -1) {
1563 helper_
->CompressedTexSubImage2D(
1564 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1565 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1566 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1571 SetBucketContents(kResultBucketId
, data
, image_size
);
1572 helper_
->CompressedTexSubImage2DBucket(
1573 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1574 // Free the bucket. This is not required but it does free up the memory.
1575 // and we don't have to wait for the result so from the client's perspective
1577 helper_
->SetBucketSize(kResultBucketId
, 0);
1583 void CopyRectToBuffer(
1586 uint32 unpadded_row_size
,
1587 uint32 pixels_padded_row_size
,
1590 uint32 buffer_padded_row_size
) {
1591 const int8
* source
= static_cast<const int8
*>(pixels
);
1592 int8
* dest
= static_cast<int8
*>(buffer
);
1593 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
1595 dest
+= buffer_padded_row_size
* (height
- 1);
1597 // the last row is copied unpadded at the end
1598 for (; height
> 1; --height
) {
1599 memcpy(dest
, source
, buffer_padded_row_size
);
1601 dest
-= buffer_padded_row_size
;
1603 dest
+= buffer_padded_row_size
;
1605 source
+= pixels_padded_row_size
;
1607 memcpy(dest
, source
, unpadded_row_size
);
1609 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
1610 memcpy(dest
, source
, size
);
1614 } // anonymous namespace
1616 void GLES2Implementation::TexImage2D(
1617 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
1618 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
1619 const void* pixels
) {
1620 GPU_CLIENT_SINGLE_THREAD_CHECK();
1621 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
1622 << GLES2Util::GetStringTextureTarget(target
) << ", "
1624 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
1625 << width
<< ", " << height
<< ", " << border
<< ", "
1626 << GLES2Util::GetStringTextureFormat(format
) << ", "
1627 << GLES2Util::GetStringPixelType(type
) << ", "
1628 << static_cast<const void*>(pixels
) << ")");
1629 if (level
< 0 || height
< 0 || width
< 0) {
1630 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
1634 uint32 unpadded_row_size
;
1635 uint32 padded_row_size
;
1636 if (!GLES2Util::ComputeImageDataSizes(
1637 width
, height
, format
, type
, unpack_alignment_
, &size
,
1638 &unpadded_row_size
, &padded_row_size
)) {
1639 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
1643 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
1644 if (bound_pixel_unpack_transfer_buffer_id_
) {
1645 GLuint offset
= ToGLuint(pixels
);
1646 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1647 bound_pixel_unpack_transfer_buffer_id_
,
1648 "glTexImage2D", offset
, size
);
1649 if (buffer
&& buffer
->shm_id() != -1) {
1650 helper_
->TexImage2D(
1651 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1652 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1653 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1659 // If there's no data just issue TexImage2D
1661 helper_
->TexImage2D(
1662 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1668 // compute the advance bytes per row for the src pixels
1669 uint32 src_padded_row_size
;
1670 if (unpack_row_length_
> 0) {
1671 if (!GLES2Util::ComputeImagePaddedRowSize(
1672 unpack_row_length_
, format
, type
, unpack_alignment_
,
1673 &src_padded_row_size
)) {
1675 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1679 src_padded_row_size
= padded_row_size
;
1682 // advance pixels pointer past the skip rows and skip pixels
1683 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1684 unpack_skip_rows_
* src_padded_row_size
;
1685 if (unpack_skip_pixels_
) {
1686 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1687 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1688 unpack_skip_pixels_
* group_size
;
1691 // Check if we can send it all at once.
1692 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1693 if (!buffer
.valid()) {
1697 if (buffer
.size() >= size
) {
1699 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
1700 buffer
.address(), padded_row_size
);
1701 helper_
->TexImage2D(
1702 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1703 buffer
.shm_id(), buffer
.offset());
1708 // No, so send it using TexSubImage2D.
1709 helper_
->TexImage2D(
1710 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1713 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
1714 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
1718 void GLES2Implementation::TexSubImage2D(
1719 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1720 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
1721 GPU_CLIENT_SINGLE_THREAD_CHECK();
1722 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
1723 << GLES2Util::GetStringTextureTarget(target
) << ", "
1725 << xoffset
<< ", " << yoffset
<< ", "
1726 << width
<< ", " << height
<< ", "
1727 << GLES2Util::GetStringTextureFormat(format
) << ", "
1728 << GLES2Util::GetStringPixelType(type
) << ", "
1729 << static_cast<const void*>(pixels
) << ")");
1731 if (level
< 0 || height
< 0 || width
< 0) {
1732 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
1735 if (height
== 0 || width
== 0) {
1740 uint32 unpadded_row_size
;
1741 uint32 padded_row_size
;
1742 if (!GLES2Util::ComputeImageDataSizes(
1743 width
, height
, format
, type
, unpack_alignment_
, &temp_size
,
1744 &unpadded_row_size
, &padded_row_size
)) {
1745 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
1749 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
1750 if (bound_pixel_unpack_transfer_buffer_id_
) {
1751 GLuint offset
= ToGLuint(pixels
);
1752 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1753 bound_pixel_unpack_transfer_buffer_id_
,
1754 "glTexSubImage2D", offset
, temp_size
);
1755 if (buffer
&& buffer
->shm_id() != -1) {
1756 helper_
->TexSubImage2D(
1757 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1758 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
1759 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1765 // compute the advance bytes per row for the src pixels
1766 uint32 src_padded_row_size
;
1767 if (unpack_row_length_
> 0) {
1768 if (!GLES2Util::ComputeImagePaddedRowSize(
1769 unpack_row_length_
, format
, type
, unpack_alignment_
,
1770 &src_padded_row_size
)) {
1772 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1776 src_padded_row_size
= padded_row_size
;
1779 // advance pixels pointer past the skip rows and skip pixels
1780 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1781 unpack_skip_rows_
* src_padded_row_size
;
1782 if (unpack_skip_pixels_
) {
1783 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1784 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1785 unpack_skip_pixels_
* group_size
;
1788 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
1790 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1791 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
1796 static GLint
ComputeNumRowsThatFitInBuffer(
1797 GLsizeiptr padded_row_size
, GLsizeiptr unpadded_row_size
,
1798 unsigned int size
) {
1799 GPU_DCHECK_GE(unpadded_row_size
, 0);
1800 if (padded_row_size
== 0) {
1803 GLint num_rows
= size
/ padded_row_size
;
1804 return num_rows
+ (size
- num_rows
* padded_row_size
) / unpadded_row_size
;
1807 void GLES2Implementation::TexSubImage2DImpl(
1808 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1809 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
1810 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
1811 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
1813 GPU_DCHECK_GE(level
, 0);
1814 GPU_DCHECK_GT(height
, 0);
1815 GPU_DCHECK_GT(width
, 0);
1817 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
1818 GLint original_yoffset
= yoffset
;
1819 // Transfer by rows.
1821 unsigned int desired_size
=
1822 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
1823 if (!buffer
->valid() || buffer
->size() == 0) {
1824 buffer
->Reset(desired_size
);
1825 if (!buffer
->valid()) {
1830 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
1831 buffer_padded_row_size
, unpadded_row_size
, buffer
->size());
1832 num_rows
= std::min(num_rows
, height
);
1834 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
1835 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
1836 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
1837 helper_
->TexSubImage2D(
1838 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
1839 buffer
->shm_id(), buffer
->offset(), internal
);
1841 yoffset
+= num_rows
;
1842 source
+= num_rows
* pixels_padded_row_size
;
1847 bool GLES2Implementation::GetActiveAttribHelper(
1848 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1849 GLenum
* type
, char* name
) {
1850 // Clear the bucket so if the command fails nothing will be in it.
1851 helper_
->SetBucketSize(kResultBucketId
, 0);
1852 typedef cmds::GetActiveAttrib::Result Result
;
1853 Result
* result
= GetResultAs
<Result
*>();
1857 // Set as failed so if the command fails we'll recover.
1858 result
->success
= false;
1859 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
1860 GetResultShmId(), GetResultShmOffset());
1862 if (result
->success
) {
1864 *size
= result
->size
;
1867 *type
= result
->type
;
1869 if (length
|| name
) {
1870 std::vector
<int8
> str
;
1871 GetBucketContents(kResultBucketId
, &str
);
1872 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
1873 std::max(static_cast<size_t>(0),
1878 if (name
&& bufsize
> 0) {
1879 memcpy(name
, &str
[0], max_size
);
1880 name
[max_size
] = '\0';
1884 return result
->success
!= 0;
1887 void GLES2Implementation::GetActiveAttrib(
1888 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1889 GLenum
* type
, char* name
) {
1890 GPU_CLIENT_SINGLE_THREAD_CHECK();
1891 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
1892 << program
<< ", " << index
<< ", " << bufsize
<< ", "
1893 << static_cast<const void*>(length
) << ", "
1894 << static_cast<const void*>(size
) << ", "
1895 << static_cast<const void*>(type
) << ", "
1896 << static_cast<const void*>(name
) << ", ");
1898 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
1901 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
1902 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
1903 this, program
, index
, bufsize
, length
, size
, type
, name
);
1906 GPU_CLIENT_LOG(" size: " << *size
);
1909 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
1912 GPU_CLIENT_LOG(" name: " << name
);
1918 bool GLES2Implementation::GetActiveUniformHelper(
1919 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1920 GLenum
* type
, char* name
) {
1921 // Clear the bucket so if the command fails nothing will be in it.
1922 helper_
->SetBucketSize(kResultBucketId
, 0);
1923 typedef cmds::GetActiveUniform::Result Result
;
1924 Result
* result
= GetResultAs
<Result
*>();
1928 // Set as failed so if the command fails we'll recover.
1929 result
->success
= false;
1930 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
1931 GetResultShmId(), GetResultShmOffset());
1933 if (result
->success
) {
1935 *size
= result
->size
;
1938 *type
= result
->type
;
1940 if (length
|| name
) {
1941 std::vector
<int8
> str
;
1942 GetBucketContents(kResultBucketId
, &str
);
1943 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
1944 std::max(static_cast<size_t>(0),
1949 if (name
&& bufsize
> 0) {
1950 memcpy(name
, &str
[0], max_size
);
1951 name
[max_size
] = '\0';
1955 return result
->success
!= 0;
1958 void GLES2Implementation::GetActiveUniform(
1959 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1960 GLenum
* type
, char* name
) {
1961 GPU_CLIENT_SINGLE_THREAD_CHECK();
1962 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
1963 << program
<< ", " << index
<< ", " << bufsize
<< ", "
1964 << static_cast<const void*>(length
) << ", "
1965 << static_cast<const void*>(size
) << ", "
1966 << static_cast<const void*>(type
) << ", "
1967 << static_cast<const void*>(name
) << ", ");
1969 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
1972 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
1973 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
1974 this, program
, index
, bufsize
, length
, size
, type
, name
);
1977 GPU_CLIENT_LOG(" size: " << *size
);
1980 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
1983 GPU_CLIENT_LOG(" name: " << name
);
1989 void GLES2Implementation::GetAttachedShaders(
1990 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
1991 GPU_CLIENT_SINGLE_THREAD_CHECK();
1992 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
1993 << program
<< ", " << maxcount
<< ", "
1994 << static_cast<const void*>(count
) << ", "
1995 << static_cast<const void*>(shaders
) << ", ");
1997 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2000 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2001 typedef cmds::GetAttachedShaders::Result Result
;
2002 uint32 size
= Result::ComputeSize(maxcount
);
2003 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2007 result
->SetNumResults(0);
2008 helper_
->GetAttachedShaders(
2010 transfer_buffer_
->GetShmId(),
2011 transfer_buffer_
->GetOffset(result
),
2013 int32 token
= helper_
->InsertToken();
2016 *count
= result
->GetNumResults();
2018 result
->CopyResult(shaders
);
2019 GPU_CLIENT_LOG_CODE_BLOCK({
2020 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2021 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2024 transfer_buffer_
->FreePendingToken(result
, token
);
2028 void GLES2Implementation::GetShaderPrecisionFormat(
2029 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2030 GPU_CLIENT_SINGLE_THREAD_CHECK();
2031 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
2032 << GLES2Util::GetStringShaderType(shadertype
) << ", "
2033 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
2034 << static_cast<const void*>(range
) << ", "
2035 << static_cast<const void*>(precision
) << ", ");
2036 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
2037 typedef cmds::GetShaderPrecisionFormat::Result Result
;
2038 Result
* result
= GetResultAs
<Result
*>();
2043 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
2044 GLStaticState::ShaderPrecisionMap::iterator i
=
2045 static_state_
.shader_precisions
.find(key
);
2046 if (i
!= static_state_
.shader_precisions
.end()) {
2047 *result
= i
->second
;
2049 result
->success
= false;
2050 helper_
->GetShaderPrecisionFormat(
2051 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
2053 if (result
->success
)
2054 static_state_
.shader_precisions
[key
] = *result
;
2057 if (result
->success
) {
2059 range
[0] = result
->min_range
;
2060 range
[1] = result
->max_range
;
2061 GPU_CLIENT_LOG(" min_range: " << range
[0]);
2062 GPU_CLIENT_LOG(" min_range: " << range
[1]);
2065 precision
[0] = result
->precision
;
2066 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
2072 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
2073 const char* result
= NULL
;
2074 // Clears the bucket so if the command fails nothing will be in it.
2075 helper_
->SetBucketSize(kResultBucketId
, 0);
2076 helper_
->GetString(name
, kResultBucketId
);
2078 if (GetBucketAsString(kResultBucketId
, &str
)) {
2079 // Adds extensions implemented on client side only.
2082 str
+= std::string(str
.empty() ? "" : " ") +
2083 "GL_CHROMIUM_flipy "
2084 "GL_CHROMIUM_map_sub "
2085 "GL_CHROMIUM_shallow_flush "
2086 "GL_EXT_unpack_subimage";
2087 if (gpu_control_
!= NULL
) {
2088 // The first space character is intentional.
2089 str
+= " GL_CHROMIUM_map_image";
2096 // Because of WebGL the extensions can change. We have to cache each unique
2097 // result since we don't know when the client will stop referring to a
2098 // previous one it queries.
2099 GLStringMap::iterator it
= gl_strings_
.find(name
);
2100 if (it
== gl_strings_
.end()) {
2101 std::set
<std::string
> strings
;
2102 std::pair
<GLStringMap::iterator
, bool> insert_result
=
2103 gl_strings_
.insert(std::make_pair(name
, strings
));
2104 GPU_DCHECK(insert_result
.second
);
2105 it
= insert_result
.first
;
2107 std::set
<std::string
>& string_set
= it
->second
;
2108 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
2109 if (sit
!= string_set
.end()) {
2110 result
= sit
->c_str();
2112 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2113 string_set
.insert(str
);
2114 GPU_DCHECK(insert_result
.second
);
2115 result
= insert_result
.first
->c_str();
2118 return reinterpret_cast<const GLubyte
*>(result
);
2121 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
2122 GPU_CLIENT_SINGLE_THREAD_CHECK();
2123 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
2124 << GLES2Util::GetStringStringType(name
) << ")");
2125 TRACE_EVENT0("gpu", "GLES2::GetString");
2126 const GLubyte
* result
= GetStringHelper(name
);
2127 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
2132 void GLES2Implementation::GetUniformfv(
2133 GLuint program
, GLint location
, GLfloat
* params
) {
2134 GPU_CLIENT_SINGLE_THREAD_CHECK();
2135 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
2136 << program
<< ", " << location
<< ", "
2137 << static_cast<const void*>(params
) << ")");
2138 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
2139 typedef cmds::GetUniformfv::Result Result
;
2140 Result
* result
= GetResultAs
<Result
*>();
2144 result
->SetNumResults(0);
2145 helper_
->GetUniformfv(
2146 program
, location
, GetResultShmId(), GetResultShmOffset());
2148 result
->CopyResult(params
);
2149 GPU_CLIENT_LOG_CODE_BLOCK({
2150 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2151 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2157 void GLES2Implementation::GetUniformiv(
2158 GLuint program
, GLint location
, GLint
* params
) {
2159 GPU_CLIENT_SINGLE_THREAD_CHECK();
2160 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
2161 << program
<< ", " << location
<< ", "
2162 << static_cast<const void*>(params
) << ")");
2163 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
2164 typedef cmds::GetUniformiv::Result Result
;
2165 Result
* result
= GetResultAs
<Result
*>();
2169 result
->SetNumResults(0);
2170 helper_
->GetUniformiv(
2171 program
, location
, GetResultShmId(), GetResultShmOffset());
2173 GetResultAs
<cmds::GetUniformfv::Result
*>()->CopyResult(params
);
2174 GPU_CLIENT_LOG_CODE_BLOCK({
2175 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2176 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2182 void GLES2Implementation::ReadPixels(
2183 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
2184 GLenum type
, void* pixels
) {
2185 GPU_CLIENT_SINGLE_THREAD_CHECK();
2186 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
2187 << xoffset
<< ", " << yoffset
<< ", "
2188 << width
<< ", " << height
<< ", "
2189 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
2190 << GLES2Util::GetStringPixelType(type
) << ", "
2191 << static_cast<const void*>(pixels
) << ")");
2192 if (width
< 0 || height
< 0) {
2193 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
2196 if (width
== 0 || height
== 0) {
2200 // glReadPixel pads the size of each row of pixels by an amount specified by
2201 // glPixelStorei. So, we have to take that into account both in the fact that
2202 // the pixels returned from the ReadPixel command will include that padding
2203 // and that when we copy the results to the user's buffer we need to not
2204 // write those padding bytes but leave them as they are.
2206 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
2207 typedef cmds::ReadPixels::Result Result
;
2209 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
2211 uint32 unpadded_row_size
;
2212 uint32 padded_row_size
;
2213 if (!GLES2Util::ComputeImageDataSizes(
2214 width
, 2, format
, type
, pack_alignment_
, &temp_size
, &unpadded_row_size
,
2215 &padded_row_size
)) {
2216 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
2220 if (bound_pixel_pack_transfer_buffer_id_
) {
2221 GLuint offset
= ToGLuint(pixels
);
2222 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2223 bound_pixel_pack_transfer_buffer_id_
,
2224 "glReadPixels", offset
, padded_row_size
* height
);
2225 if (buffer
&& buffer
->shm_id() != -1) {
2226 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
2227 buffer
->shm_id(), buffer
->shm_offset(),
2235 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
2239 // Transfer by rows.
2240 // The max rows we can transfer.
2242 GLsizei desired_size
= padded_row_size
* height
- 1 + unpadded_row_size
;
2243 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
2244 if (!buffer
.valid()) {
2247 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2248 padded_row_size
, unpadded_row_size
, buffer
.size());
2249 num_rows
= std::min(num_rows
, height
);
2250 // NOTE: We must look up the address of the result area AFTER allocation
2251 // of the transfer buffer since the transfer buffer may be reallocated.
2252 Result
* result
= GetResultAs
<Result
*>();
2256 *result
= 0; // mark as failed.
2257 helper_
->ReadPixels(
2258 xoffset
, yoffset
, width
, num_rows
, format
, type
,
2259 buffer
.shm_id(), buffer
.offset(),
2260 GetResultShmId(), GetResultShmOffset(),
2264 // when doing a y-flip we have to iterate through top-to-bottom chunks
2265 // of the dst. The service side handles reversing the rows within a
2268 if (pack_reverse_row_order_
) {
2269 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
2273 // We have to copy 1 row at a time to avoid writing pad bytes.
2274 const int8
* src
= static_cast<const int8
*>(buffer
.address());
2275 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
2276 memcpy(rows_dst
, src
, unpadded_row_size
);
2277 rows_dst
+= padded_row_size
;
2278 src
+= padded_row_size
;
2280 if (!pack_reverse_row_order_
) {
2284 // If it was not marked as successful exit.
2288 yoffset
+= num_rows
;
2294 void GLES2Implementation::ActiveTexture(GLenum texture
) {
2295 GPU_CLIENT_SINGLE_THREAD_CHECK();
2296 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
2297 << GLES2Util::GetStringEnum(texture
) << ")");
2298 GLuint texture_index
= texture
- GL_TEXTURE0
;
2299 if (texture_index
>= static_cast<GLuint
>(
2300 static_state_
.int_state
.max_combined_texture_image_units
)) {
2301 SetGLErrorInvalidEnum(
2302 "glActiveTexture", texture
, "texture");
2306 active_texture_unit_
= texture_index
;
2307 helper_
->ActiveTexture(texture
);
2311 void GLES2Implementation::GenBuffersHelper(
2312 GLsizei
/* n */, const GLuint
* /* buffers */) {
2315 void GLES2Implementation::GenFramebuffersHelper(
2316 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
2319 void GLES2Implementation::GenRenderbuffersHelper(
2320 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
2323 void GLES2Implementation::GenTexturesHelper(
2324 GLsizei
/* n */, const GLuint
* /* textures */) {
2327 void GLES2Implementation::GenVertexArraysOESHelper(
2328 GLsizei n
, const GLuint
* arrays
) {
2329 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
2332 void GLES2Implementation::GenQueriesEXTHelper(
2333 GLsizei
/* n */, const GLuint
* /* queries */) {
2336 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
2337 // generates a new resource. On newer versions of OpenGL they don't. The code
2338 // related to binding below will need to change if we switch to the new OpenGL
2339 // model. Specifically it assumes a bind will succeed which is always true in
2340 // the old model but possibly not true in the new model if another context has
2341 // deleted the resource.
2343 bool GLES2Implementation::BindBufferHelper(
2344 GLenum target
, GLuint buffer
) {
2345 // TODO(gman): See note #1 above.
2346 bool changed
= false;
2348 case GL_ARRAY_BUFFER
:
2349 if (bound_array_buffer_id_
!= buffer
) {
2350 bound_array_buffer_id_
= buffer
;
2354 case GL_ELEMENT_ARRAY_BUFFER
:
2355 changed
= vertex_array_object_manager_
->BindElementArray(buffer
);
2357 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
2358 bound_pixel_pack_transfer_buffer_id_
= buffer
;
2360 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
2361 bound_pixel_unpack_transfer_buffer_id_
= buffer
;
2367 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2368 // used even though it's marked it as used here.
2369 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(buffer
);
2373 bool GLES2Implementation::BindFramebufferHelper(
2374 GLenum target
, GLuint framebuffer
) {
2375 // TODO(gman): See note #1 above.
2376 bool changed
= false;
2378 case GL_FRAMEBUFFER
:
2379 if (bound_framebuffer_
!= framebuffer
||
2380 bound_read_framebuffer_
!= framebuffer
) {
2381 bound_framebuffer_
= framebuffer
;
2382 bound_read_framebuffer_
= framebuffer
;
2386 case GL_READ_FRAMEBUFFER
:
2387 if (!IsChromiumFramebufferMultisampleAvailable()) {
2388 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2391 if (bound_read_framebuffer_
!= framebuffer
) {
2392 bound_read_framebuffer_
= framebuffer
;
2396 case GL_DRAW_FRAMEBUFFER
:
2397 if (!IsChromiumFramebufferMultisampleAvailable()) {
2398 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2401 if (bound_framebuffer_
!= framebuffer
) {
2402 bound_framebuffer_
= framebuffer
;
2407 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2410 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(framebuffer
);
2414 bool GLES2Implementation::BindRenderbufferHelper(
2415 GLenum target
, GLuint renderbuffer
) {
2416 // TODO(gman): See note #1 above.
2417 bool changed
= false;
2419 case GL_RENDERBUFFER
:
2420 if (bound_renderbuffer_
!= renderbuffer
) {
2421 bound_renderbuffer_
= renderbuffer
;
2429 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2430 // used even though it's marked it as used here.
2431 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(renderbuffer
);
2435 bool GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
2436 // TODO(gman): See note #1 above.
2437 // TODO(gman): Change this to false once we figure out why it's failing
2439 bool changed
= true;
2440 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
2443 if (unit
.bound_texture_2d
!= texture
) {
2444 unit
.bound_texture_2d
= texture
;
2448 case GL_TEXTURE_CUBE_MAP
:
2449 if (unit
.bound_texture_cube_map
!= texture
) {
2450 unit
.bound_texture_cube_map
= texture
;
2458 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2459 // used. even though it's marked it as used here.
2460 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(texture
);
2464 bool GLES2Implementation::BindVertexArrayHelper(GLuint array
) {
2465 // TODO(gman): See note #1 above.
2466 bool changed
= false;
2467 if (!vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
2469 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
2470 "id was not generated with glGenVertexArrayOES");
2472 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
2473 // because unlike other resources VertexArrayObject ids must
2474 // be generated by GenVertexArrays. A random id to Bind will not
2475 // generate a new object.
2479 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
2480 return vertex_array_object_manager_
->IsReservedId(id
);
2483 void GLES2Implementation::DeleteBuffersHelper(
2484 GLsizei n
, const GLuint
* buffers
) {
2485 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
2486 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
2489 "glDeleteBuffers", "id not created by this context.");
2492 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2493 if (buffers
[ii
] == bound_array_buffer_id_
) {
2494 bound_array_buffer_id_
= 0;
2496 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
2497 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
2499 // Free buffer memory, pending the passage of a token.
2500 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
2502 buffer_tracker_
->RemoveBuffer(buffers
[ii
]);
2504 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
2505 bound_pixel_unpack_transfer_buffer_id_
= 0;
2510 void GLES2Implementation::DeleteBuffersStub(
2511 GLsizei n
, const GLuint
* buffers
) {
2512 helper_
->DeleteBuffersImmediate(n
, buffers
);
2516 void GLES2Implementation::DeleteFramebuffersHelper(
2517 GLsizei n
, const GLuint
* framebuffers
) {
2518 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
2519 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
2522 "glDeleteFramebuffers", "id not created by this context.");
2525 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2526 if (framebuffers
[ii
] == bound_framebuffer_
) {
2527 bound_framebuffer_
= 0;
2529 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
2530 bound_read_framebuffer_
= 0;
2535 void GLES2Implementation::DeleteFramebuffersStub(
2536 GLsizei n
, const GLuint
* framebuffers
) {
2537 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
2540 void GLES2Implementation::DeleteRenderbuffersHelper(
2541 GLsizei n
, const GLuint
* renderbuffers
) {
2542 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
2543 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
2546 "glDeleteRenderbuffers", "id not created by this context.");
2549 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2550 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
2551 bound_renderbuffer_
= 0;
2556 void GLES2Implementation::DeleteRenderbuffersStub(
2557 GLsizei n
, const GLuint
* renderbuffers
) {
2558 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
2561 void GLES2Implementation::DeleteTexturesHelper(
2562 GLsizei n
, const GLuint
* textures
) {
2563 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
2564 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
2567 "glDeleteTextures", "id not created by this context.");
2570 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2572 tt
< static_state_
.int_state
.max_combined_texture_image_units
;
2574 TextureUnit
& unit
= texture_units_
[tt
];
2575 if (textures
[ii
] == unit
.bound_texture_2d
) {
2576 unit
.bound_texture_2d
= 0;
2578 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
2579 unit
.bound_texture_cube_map
= 0;
2585 void GLES2Implementation::DeleteVertexArraysOESHelper(
2586 GLsizei n
, const GLuint
* arrays
) {
2587 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
2588 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
2589 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
2592 "glDeleteVertexArraysOES", "id not created by this context.");
2597 void GLES2Implementation::DeleteVertexArraysOESStub(
2598 GLsizei n
, const GLuint
* arrays
) {
2599 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
2602 void GLES2Implementation::DeleteTexturesStub(
2603 GLsizei n
, const GLuint
* textures
) {
2604 helper_
->DeleteTexturesImmediate(n
, textures
);
2607 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
2608 GPU_CLIENT_SINGLE_THREAD_CHECK();
2610 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
2611 vertex_array_object_manager_
->SetAttribEnable(index
, false);
2612 helper_
->DisableVertexAttribArray(index
);
2616 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
2617 GPU_CLIENT_SINGLE_THREAD_CHECK();
2618 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
2620 vertex_array_object_manager_
->SetAttribEnable(index
, true);
2621 helper_
->EnableVertexAttribArray(index
);
2625 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2626 GPU_CLIENT_SINGLE_THREAD_CHECK();
2627 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
2628 << GLES2Util::GetStringDrawMode(mode
) << ", "
2629 << first
<< ", " << count
<< ")");
2631 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
2634 bool simulated
= false;
2635 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
2636 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
2639 helper_
->DrawArrays(mode
, first
, count
);
2640 RestoreArrayBuffer(simulated
);
2644 void GLES2Implementation::GetVertexAttribfv(
2645 GLuint index
, GLenum pname
, GLfloat
* params
) {
2646 GPU_CLIENT_SINGLE_THREAD_CHECK();
2647 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
2649 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2650 << static_cast<const void*>(params
) << ")");
2652 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2653 *params
= static_cast<float>(value
);
2656 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
2657 typedef cmds::GetVertexAttribfv::Result Result
;
2658 Result
* result
= GetResultAs
<Result
*>();
2662 result
->SetNumResults(0);
2663 helper_
->GetVertexAttribfv(
2664 index
, pname
, GetResultShmId(), GetResultShmOffset());
2666 result
->CopyResult(params
);
2667 GPU_CLIENT_LOG_CODE_BLOCK({
2668 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2669 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2675 void GLES2Implementation::GetVertexAttribiv(
2676 GLuint index
, GLenum pname
, GLint
* params
) {
2677 GPU_CLIENT_SINGLE_THREAD_CHECK();
2678 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
2680 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2681 << static_cast<const void*>(params
) << ")");
2683 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2687 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
2688 typedef cmds::GetVertexAttribiv::Result Result
;
2689 Result
* result
= GetResultAs
<Result
*>();
2693 result
->SetNumResults(0);
2694 helper_
->GetVertexAttribiv(
2695 index
, pname
, GetResultShmId(), GetResultShmOffset());
2697 result
->CopyResult(params
);
2698 GPU_CLIENT_LOG_CODE_BLOCK({
2699 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2700 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2706 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
2707 const char* feature
) {
2708 GPU_CLIENT_SINGLE_THREAD_CHECK();
2709 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
2711 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
2712 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
2713 Result
* result
= GetResultAs
<Result
*>();
2718 SetBucketAsCString(kResultBucketId
, feature
);
2719 helper_
->EnableFeatureCHROMIUM(
2720 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
2722 helper_
->SetBucketSize(kResultBucketId
, 0);
2723 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
2727 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
2728 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
2729 GPU_CLIENT_SINGLE_THREAD_CHECK();
2730 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
2731 << target
<< ", " << offset
<< ", " << size
<< ", "
2732 << GLES2Util::GetStringEnum(access
) << ")");
2733 // NOTE: target is NOT checked because the service will check it
2734 // and we don't know what targets are valid.
2735 if (access
!= GL_WRITE_ONLY
) {
2736 SetGLErrorInvalidEnum(
2737 "glMapBufferSubDataCHROMIUM", access
, "access");
2740 if (offset
< 0 || size
< 0) {
2741 SetGLError(GL_INVALID_VALUE
, "glMapBufferSubDataCHROMIUM", "bad range");
2745 unsigned int shm_offset
;
2746 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2748 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
2752 std::pair
<MappedBufferMap::iterator
, bool> result
=
2753 mapped_buffers_
.insert(std::make_pair(
2756 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
2757 GPU_DCHECK(result
.second
);
2758 GPU_CLIENT_LOG(" returned " << mem
);
2762 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
2763 GPU_CLIENT_SINGLE_THREAD_CHECK();
2765 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
2766 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
2767 if (it
== mapped_buffers_
.end()) {
2769 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
2772 const MappedBuffer
& mb
= it
->second
;
2773 helper_
->BufferSubData(
2774 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
2775 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
2776 mapped_buffers_
.erase(it
);
2780 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
2790 GPU_CLIENT_SINGLE_THREAD_CHECK();
2791 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
2792 << target
<< ", " << level
<< ", "
2793 << xoffset
<< ", " << yoffset
<< ", "
2794 << width
<< ", " << height
<< ", "
2795 << GLES2Util::GetStringTextureFormat(format
) << ", "
2796 << GLES2Util::GetStringPixelType(type
) << ", "
2797 << GLES2Util::GetStringEnum(access
) << ")");
2798 if (access
!= GL_WRITE_ONLY
) {
2799 SetGLErrorInvalidEnum(
2800 "glMapTexSubImage2DCHROMIUM", access
, "access");
2803 // NOTE: target is NOT checked because the service will check it
2804 // and we don't know what targets are valid.
2805 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
2807 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
2811 if (!GLES2Util::ComputeImageDataSizes(
2812 width
, height
, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
2814 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
2818 unsigned int shm_offset
;
2819 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2821 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
2825 std::pair
<MappedTextureMap::iterator
, bool> result
=
2826 mapped_textures_
.insert(std::make_pair(
2829 access
, shm_id
, mem
, shm_offset
,
2830 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
2831 GPU_DCHECK(result
.second
);
2832 GPU_CLIENT_LOG(" returned " << mem
);
2836 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
2837 GPU_CLIENT_SINGLE_THREAD_CHECK();
2839 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
2840 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
2841 if (it
== mapped_textures_
.end()) {
2843 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
2846 const MappedTexture
& mt
= it
->second
;
2847 helper_
->TexSubImage2D(
2848 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
2849 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
2850 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
2851 mapped_textures_
.erase(it
);
2855 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
2856 float scale_factor
) {
2857 GPU_CLIENT_SINGLE_THREAD_CHECK();
2858 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
2859 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
2860 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
2864 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
2865 GPU_CLIENT_SINGLE_THREAD_CHECK();
2866 GPU_CLIENT_LOG("[" << GetLogPrefix()
2867 << "] glGetRequestableExtensionsCHROMIUM()");
2869 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
2870 const char* result
= NULL
;
2871 // Clear the bucket so if the command fails nothing will be in it.
2872 helper_
->SetBucketSize(kResultBucketId
, 0);
2873 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
2875 if (GetBucketAsString(kResultBucketId
, &str
)) {
2876 // The set of requestable extensions shrinks as we enable
2877 // them. Because we don't know when the client will stop referring
2878 // to a previous one it queries (see GetString) we need to cache
2879 // the unique results.
2880 std::set
<std::string
>::const_iterator sit
=
2881 requestable_extensions_set_
.find(str
);
2882 if (sit
!= requestable_extensions_set_
.end()) {
2883 result
= sit
->c_str();
2885 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2886 requestable_extensions_set_
.insert(str
);
2887 GPU_DCHECK(insert_result
.second
);
2888 result
= insert_result
.first
->c_str();
2891 GPU_CLIENT_LOG(" returned " << result
);
2892 return reinterpret_cast<const GLchar
*>(result
);
2895 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
2896 // with VirtualGL contexts.
2897 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
2898 GPU_CLIENT_SINGLE_THREAD_CHECK();
2899 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
2900 << extension
<< ")");
2901 SetBucketAsCString(kResultBucketId
, extension
);
2902 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
2903 helper_
->SetBucketSize(kResultBucketId
, 0);
2905 struct ExtensionCheck
{
2906 const char* extension
;
2907 ExtensionStatus
* status
;
2909 const ExtensionCheck checks
[] = {
2911 "GL_ANGLE_pack_reverse_row_order",
2912 &angle_pack_reverse_row_order_status_
,
2915 "GL_CHROMIUM_framebuffer_multisample",
2916 &chromium_framebuffer_multisample_
,
2919 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
2920 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
2921 const ExtensionCheck
& check
= checks
[ii
];
2922 if (*check
.status
== kUnavailableExtensionStatus
&&
2923 !strcmp(extension
, check
.extension
)) {
2924 *check
.status
= kUnknownExtensionStatus
;
2929 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
2930 GPU_CLIENT_SINGLE_THREAD_CHECK();
2931 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
2932 // Wait if this would add too many rate limit tokens.
2933 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
2934 helper_
->WaitForToken(rate_limit_tokens_
.front());
2935 rate_limit_tokens_
.pop();
2937 rate_limit_tokens_
.push(helper_
->InsertToken());
2940 void GLES2Implementation::GetMultipleIntegervCHROMIUM(
2941 const GLenum
* pnames
, GLuint count
, GLint
* results
, GLsizeiptr size
) {
2942 GPU_CLIENT_SINGLE_THREAD_CHECK();
2943 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMultipleIntegervCHROMIUM("
2944 << static_cast<const void*>(pnames
) << ", "
2945 << count
<< ", " << results
<< ", "
2947 GPU_CLIENT_LOG_CODE_BLOCK({
2948 for (GLuint i
= 0; i
< count
; ++i
) {
2950 " " << i
<< ": " << GLES2Util::GetStringGLState(pnames
[i
]));
2954 GetMultipleIntegervState
state(pnames
, count
, results
, size
);
2955 if (!GetMultipleIntegervSetup(&state
)) {
2958 state
.buffer
= transfer_buffer_
->Alloc(state
.transfer_buffer_size_needed
);
2959 if (!state
.buffer
) {
2960 SetGLError(GL_OUT_OF_MEMORY
, "glGetMultipleIntegervCHROMIUM",
2961 "Transfer buffer allocation failed.");
2964 GetMultipleIntegervRequest(&state
);
2966 GetMultipleIntegervOnCompleted(&state
);
2968 GPU_CLIENT_LOG(" returned");
2969 GPU_CLIENT_LOG_CODE_BLOCK({
2970 for (int i
= 0; i
< state
.num_results
; ++i
) {
2971 GPU_CLIENT_LOG(" " << i
<< ": " << (results
[i
]));
2975 // TODO(gman): We should be able to free without a token.
2976 transfer_buffer_
->FreePendingToken(state
.buffer
, helper_
->InsertToken());
2980 bool GLES2Implementation::GetMultipleIntegervSetup(
2981 GetMultipleIntegervState
* state
) {
2982 state
->num_results
= 0;
2983 for (GLuint ii
= 0; ii
< state
->pnames_count
; ++ii
) {
2984 int num
= util_
.GLGetNumValuesReturned(state
->pnames
[ii
]);
2986 SetGLErrorInvalidEnum(
2987 "glGetMultipleIntegervCHROMIUM", state
->pnames
[ii
], "pname");
2990 state
->num_results
+= num
;
2992 if (static_cast<size_t>(state
->results_size
) !=
2993 state
->num_results
* sizeof(GLint
)) {
2994 SetGLError(GL_INVALID_VALUE
, "glGetMultipleIntegervCHROMIUM", "bad size");
2997 for (int ii
= 0; ii
< state
->num_results
; ++ii
) {
2998 if (state
->results
[ii
] != 0) {
2999 SetGLError(GL_INVALID_VALUE
,
3000 "glGetMultipleIntegervCHROMIUM", "results not set to zero.");
3004 state
->transfer_buffer_size_needed
=
3005 state
->pnames_count
* sizeof(state
->pnames
[0]) +
3006 state
->num_results
* sizeof(state
->results
[0]);
3010 void GLES2Implementation::GetMultipleIntegervRequest(
3011 GetMultipleIntegervState
* state
) {
3012 GLenum
* pnames_buffer
= static_cast<GLenum
*>(state
->buffer
);
3013 state
->results_buffer
= pnames_buffer
+ state
->pnames_count
;
3014 memcpy(pnames_buffer
, state
->pnames
, state
->pnames_count
* sizeof(GLenum
));
3015 memset(state
->results_buffer
, 0, state
->num_results
* sizeof(GLint
));
3016 helper_
->GetMultipleIntegervCHROMIUM(
3017 transfer_buffer_
->GetShmId(),
3018 transfer_buffer_
->GetOffset(pnames_buffer
),
3019 state
->pnames_count
,
3020 transfer_buffer_
->GetShmId(),
3021 transfer_buffer_
->GetOffset(state
->results_buffer
),
3022 state
->results_size
);
3025 void GLES2Implementation::GetMultipleIntegervOnCompleted(
3026 GetMultipleIntegervState
* state
) {
3027 memcpy(state
->results
, state
->results_buffer
, state
->results_size
);;
3030 void GLES2Implementation::GetAllShaderPrecisionFormatsSetup(
3031 GetAllShaderPrecisionFormatsState
* state
) {
3032 state
->transfer_buffer_size_needed
=
3033 state
->precision_params_count
*
3034 sizeof(cmds::GetShaderPrecisionFormat::Result
);
3037 void GLES2Implementation::GetAllShaderPrecisionFormatsRequest(
3038 GetAllShaderPrecisionFormatsState
* state
) {
3039 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3040 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3042 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3043 result
->success
= false;
3044 helper_
->GetShaderPrecisionFormat(state
->precision_params
[i
][0],
3045 state
->precision_params
[i
][1],
3046 transfer_buffer_
->GetShmId(),
3047 transfer_buffer_
->GetOffset(result
));
3052 void GLES2Implementation::GetAllShaderPrecisionFormatsOnCompleted(
3053 GetAllShaderPrecisionFormatsState
* state
) {
3054 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3055 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3057 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3058 if (result
->success
) {
3059 const GLStaticState::ShaderPrecisionKey
key(
3060 state
->precision_params
[i
][0], state
->precision_params
[i
][1]);
3061 static_state_
.shader_precisions
[key
] = *result
;
3067 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
3068 GLuint program
, std::vector
<int8
>* result
) {
3070 // Clear the bucket so if the command fails nothing will be in it.
3071 helper_
->SetBucketSize(kResultBucketId
, 0);
3072 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
3073 GetBucketContents(kResultBucketId
, result
);
3076 void GLES2Implementation::GetProgramInfoCHROMIUM(
3077 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
3078 GPU_CLIENT_SINGLE_THREAD_CHECK();
3081 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
3085 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
3088 // Make sure they've set size to 0 else the value will be undefined on
3090 GPU_DCHECK(*size
== 0);
3091 std::vector
<int8
> result
;
3092 GetProgramInfoCHROMIUMHelper(program
, &result
);
3093 if (result
.empty()) {
3096 *size
= result
.size();
3100 if (static_cast<size_t>(bufsize
) < result
.size()) {
3101 SetGLError(GL_INVALID_OPERATION
,
3102 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
3105 memcpy(info
, &result
[0], result
.size());
3108 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
3109 GPU_CLIENT_SINGLE_THREAD_CHECK();
3110 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
3112 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
3113 typedef cmds::CreateStreamTextureCHROMIUM::Result Result
;
3114 Result
* result
= GetResultAs
<Result
*>();
3120 helper_
->CreateStreamTextureCHROMIUM(texture
,
3122 GetResultShmOffset());
3124 GLuint result_value
= *result
;
3126 return result_value
;
3129 void GLES2Implementation::DestroyStreamTextureCHROMIUM(GLuint texture
) {
3130 GPU_CLIENT_SINGLE_THREAD_CHECK();
3131 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] DestroyStreamTextureCHROMIUM("
3133 TRACE_EVENT0("gpu", "GLES2::DestroyStreamTextureCHROMIUM");
3134 helper_
->DestroyStreamTextureCHROMIUM(texture
);
3138 void GLES2Implementation::PostSubBufferCHROMIUM(
3139 GLint x
, GLint y
, GLint width
, GLint height
) {
3140 GPU_CLIENT_SINGLE_THREAD_CHECK();
3141 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
3142 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
3143 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
3144 "width", width
, "height", height
);
3146 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
3147 swap_buffers_tokens_
.push(helper_
->InsertToken());
3148 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
3149 helper_
->CommandBufferHelper::Flush();
3150 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
3151 helper_
->WaitForToken(swap_buffers_tokens_
.front());
3152 swap_buffers_tokens_
.pop();
3156 void GLES2Implementation::DeleteQueriesEXTHelper(
3157 GLsizei n
, const GLuint
* queries
) {
3158 // TODO(gman): Remove this as queries are not shared resources.
3159 if (!GetIdHandler(id_namespaces::kQueries
)->FreeIds(
3160 this, n
, queries
, &GLES2Implementation::DeleteQueriesStub
)) {
3163 "glDeleteTextures", "id not created by this context.");
3167 for (GLsizei ii
= 0; ii
< n
; ++ii
)
3168 query_tracker_
->RemoveQuery(queries
[ii
]);
3170 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
3173 // TODO(gman): Remove this. Queries are not shared resources.
3174 void GLES2Implementation::DeleteQueriesStub(
3175 GLsizei
/* n */, const GLuint
* /* queries */) {
3178 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
3179 GPU_CLIENT_SINGLE_THREAD_CHECK();
3180 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
3182 // TODO(gman): To be spec compliant IDs from other contexts sharing
3183 // resources need to return true here even though you can't share
3184 // queries across contexts?
3185 return query_tracker_
->GetQuery(id
) != NULL
;
3188 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
3189 GPU_CLIENT_SINGLE_THREAD_CHECK();
3190 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
3191 << GLES2Util::GetStringQueryTarget(target
)
3192 << ", " << id
<< ")");
3194 // if any outstanding queries INV_OP
3195 if (current_query_
) {
3197 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
3203 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
3207 // TODO(gman) if id not GENned INV_OPERATION
3209 // if id does not have an object
3210 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
3212 query
= query_tracker_
->CreateQuery(id
, target
);
3214 MustBeContextLost();
3217 } else if (query
->target() != target
) {
3219 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
3223 current_query_
= query
;
3229 void GLES2Implementation::EndQueryEXT(GLenum target
) {
3230 GPU_CLIENT_SINGLE_THREAD_CHECK();
3231 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
3232 << GLES2Util::GetStringQueryTarget(target
) << ")");
3233 // Don't do anything if the context is lost.
3234 if (helper_
->IsContextLost()) {
3238 if (!current_query_
) {
3239 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
3243 if (current_query_
->target() != target
) {
3244 SetGLError(GL_INVALID_OPERATION
,
3245 "glEndQueryEXT", "target does not match active query");
3249 current_query_
->End(this);
3250 current_query_
= NULL
;
3254 void GLES2Implementation::GetQueryivEXT(
3255 GLenum target
, GLenum pname
, GLint
* params
) {
3256 GPU_CLIENT_SINGLE_THREAD_CHECK();
3257 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
3258 << GLES2Util::GetStringQueryTarget(target
) << ", "
3259 << GLES2Util::GetStringQueryParameter(pname
) << ", "
3260 << static_cast<const void*>(params
) << ")");
3262 if (pname
!= GL_CURRENT_QUERY_EXT
) {
3263 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
3266 *params
= (current_query_
&& current_query_
->target() == target
) ?
3267 current_query_
->id() : 0;
3268 GPU_CLIENT_LOG(" " << *params
);
3272 void GLES2Implementation::GetQueryObjectuivEXT(
3273 GLuint id
, GLenum pname
, GLuint
* params
) {
3274 GPU_CLIENT_SINGLE_THREAD_CHECK();
3275 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
3276 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
3277 << static_cast<const void*>(params
) << ")");
3279 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
3281 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
3285 if (query
== current_query_
) {
3287 GL_INVALID_OPERATION
,
3288 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
3292 if (query
->NeverUsed()) {
3294 GL_INVALID_OPERATION
,
3295 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
3300 case GL_QUERY_RESULT_EXT
:
3301 if (!query
->CheckResultsAvailable(helper_
)) {
3302 helper_
->WaitForToken(query
->token());
3303 if (!query
->CheckResultsAvailable(helper_
)) {
3304 // TODO(gman): Speed this up.
3306 GPU_CHECK(query
->CheckResultsAvailable(helper_
));
3309 *params
= query
->GetResult();
3311 case GL_QUERY_RESULT_AVAILABLE_EXT
:
3312 *params
= query
->CheckResultsAvailable(helper_
);
3315 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
3318 GPU_CLIENT_LOG(" " << *params
);
3322 void GLES2Implementation::DrawArraysInstancedANGLE(
3323 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
3324 GPU_CLIENT_SINGLE_THREAD_CHECK();
3325 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
3326 << GLES2Util::GetStringDrawMode(mode
) << ", "
3327 << first
<< ", " << count
<< ", " << primcount
<< ")");
3329 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
3332 if (primcount
< 0) {
3333 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
3336 if (primcount
== 0) {
3339 bool simulated
= false;
3340 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3341 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
3345 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
3346 RestoreArrayBuffer(simulated
);
3350 void GLES2Implementation::DrawElementsInstancedANGLE(
3351 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
3352 GLsizei primcount
) {
3353 GPU_CLIENT_SINGLE_THREAD_CHECK();
3354 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
3355 << GLES2Util::GetStringDrawMode(mode
) << ", "
3357 << GLES2Util::GetStringIndexType(type
) << ", "
3358 << static_cast<const void*>(indices
) << ", "
3359 << primcount
<< ")");
3361 SetGLError(GL_INVALID_VALUE
,
3362 "glDrawElementsInstancedANGLE", "count less than 0.");
3368 if (primcount
< 0) {
3369 SetGLError(GL_INVALID_VALUE
,
3370 "glDrawElementsInstancedANGLE", "primcount < 0");
3373 if (primcount
== 0) {
3377 bool simulated
= false;
3378 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
3379 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
3380 indices
, &offset
, &simulated
)) {
3383 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
3384 RestoreElementAndArrayBuffers(simulated
);
3388 void GLES2Implementation::GenMailboxCHROMIUM(
3390 GPU_CLIENT_SINGLE_THREAD_CHECK();
3391 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
3392 << static_cast<const void*>(mailbox
) << ")");
3393 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
3395 helper_
->GenMailboxCHROMIUM(kResultBucketId
);
3397 std::vector
<GLbyte
> result
;
3398 GetBucketContents(kResultBucketId
, &result
);
3400 std::copy(result
.begin(), result
.end(), mailbox
);
3404 void GLES2Implementation::PushGroupMarkerEXT(
3405 GLsizei length
, const GLchar
* marker
) {
3406 GPU_CLIENT_SINGLE_THREAD_CHECK();
3407 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
3408 << length
<< ", " << marker
<< ")");
3414 (length
? std::string(marker
, length
) : std::string(marker
)));
3415 helper_
->PushGroupMarkerEXT(kResultBucketId
);
3416 helper_
->SetBucketSize(kResultBucketId
, 0);
3417 debug_marker_manager_
.PushGroup(
3418 length
? std::string(marker
, length
) : std::string(marker
));
3421 void GLES2Implementation::InsertEventMarkerEXT(
3422 GLsizei length
, const GLchar
* marker
) {
3423 GPU_CLIENT_SINGLE_THREAD_CHECK();
3424 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
3425 << length
<< ", " << marker
<< ")");
3431 (length
? std::string(marker
, length
) : std::string(marker
)));
3432 helper_
->InsertEventMarkerEXT(kResultBucketId
);
3433 helper_
->SetBucketSize(kResultBucketId
, 0);
3434 debug_marker_manager_
.SetMarker(
3435 length
? std::string(marker
, length
) : std::string(marker
));
3438 void GLES2Implementation::PopGroupMarkerEXT() {
3439 GPU_CLIENT_SINGLE_THREAD_CHECK();
3440 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
3441 helper_
->PopGroupMarkerEXT();
3442 debug_marker_manager_
.PopGroup();
3445 void GLES2Implementation::TraceBeginCHROMIUM(const char* name
) {
3446 GPU_CLIENT_SINGLE_THREAD_CHECK();
3447 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
3449 if (current_trace_name_
.get()) {
3450 SetGLError(GL_INVALID_OPERATION
, "glTraceBeginCHROMIUM",
3451 "trace already running");
3454 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", name
, this);
3455 SetBucketAsCString(kResultBucketId
, name
);
3456 helper_
->TraceBeginCHROMIUM(kResultBucketId
);
3457 helper_
->SetBucketSize(kResultBucketId
, 0);
3458 current_trace_name_
.reset(new std::string(name
));
3461 void GLES2Implementation::TraceEndCHROMIUM() {
3462 GPU_CLIENT_SINGLE_THREAD_CHECK();
3463 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
3464 if (!current_trace_name_
.get()) {
3465 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
3466 "missing begin trace");
3469 helper_
->TraceEndCHROMIUM();
3470 TRACE_EVENT_COPY_ASYNC_END0("gpu", current_trace_name_
->c_str(), this);
3471 current_trace_name_
.reset();
3474 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
3475 GPU_CLIENT_SINGLE_THREAD_CHECK();
3476 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
3477 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
3479 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3480 if (access
!= GL_READ_ONLY
) {
3481 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3485 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3486 if (access
!= GL_WRITE_ONLY
) {
3487 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3493 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
3497 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
3501 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3503 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
3506 if (buffer
->mapped()) {
3507 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
3510 // Here we wait for previous transfer operations to be finished.
3511 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
3512 // with this method of synchronization. Until this is fixed,
3513 // MapBufferCHROMIUM will not block even if the transfer is not ready
3515 if (buffer
->transfer_ready_token()) {
3516 helper_
->WaitForToken(buffer
->transfer_ready_token());
3517 buffer
->set_transfer_ready_token(0);
3519 buffer
->set_mapped(true);
3521 GPU_CLIENT_LOG(" returned " << buffer
->address());
3523 return buffer
->address();
3526 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
3527 GPU_CLIENT_SINGLE_THREAD_CHECK();
3529 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
3531 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
3532 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
3537 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3539 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
3542 if (!buffer
->mapped()) {
3543 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
3546 buffer
->set_mapped(false);
3551 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
3552 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
3553 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
3554 const void* pixels
) {
3555 GPU_CLIENT_SINGLE_THREAD_CHECK();
3556 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
3557 << GLES2Util::GetStringTextureTarget(target
) << ", "
3559 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
3560 << width
<< ", " << height
<< ", " << border
<< ", "
3561 << GLES2Util::GetStringTextureFormat(format
) << ", "
3562 << GLES2Util::GetStringPixelType(type
) << ", "
3563 << static_cast<const void*>(pixels
) << ")");
3564 if (level
< 0 || height
< 0 || width
< 0) {
3565 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
3569 uint32 unpadded_row_size
;
3570 uint32 padded_row_size
;
3571 if (!GLES2Util::ComputeImageDataSizes(
3572 width
, height
, format
, type
, unpack_alignment_
, &size
,
3573 &unpadded_row_size
, &padded_row_size
)) {
3574 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
3578 // If there's no data/buffer just issue the AsyncTexImage2D
3579 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
3580 helper_
->AsyncTexImage2DCHROMIUM(
3581 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3586 // Otherwise, async uploads require a transfer buffer to be bound.
3587 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3588 // the buffer before the transfer is finished. (Currently such
3589 // synchronization has to be handled manually.)
3590 GLuint offset
= ToGLuint(pixels
);
3591 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3592 bound_pixel_unpack_transfer_buffer_id_
,
3593 "glAsyncTexImage2DCHROMIUM", offset
, size
);
3594 if (buffer
&& buffer
->shm_id() != -1) {
3595 helper_
->AsyncTexImage2DCHROMIUM(
3596 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3597 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3601 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
3602 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
3603 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
3604 GPU_CLIENT_SINGLE_THREAD_CHECK();
3605 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
3606 << GLES2Util::GetStringTextureTarget(target
) << ", "
3608 << xoffset
<< ", " << yoffset
<< ", "
3609 << width
<< ", " << height
<< ", "
3610 << GLES2Util::GetStringTextureFormat(format
) << ", "
3611 << GLES2Util::GetStringPixelType(type
) << ", "
3612 << static_cast<const void*>(pixels
) << ")");
3613 if (level
< 0 || height
< 0 || width
< 0) {
3615 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
3620 uint32 unpadded_row_size
;
3621 uint32 padded_row_size
;
3622 if (!GLES2Util::ComputeImageDataSizes(
3623 width
, height
, format
, type
, unpack_alignment_
, &size
,
3624 &unpadded_row_size
, &padded_row_size
)) {
3626 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
3630 // Async uploads require a transfer buffer to be bound.
3631 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3632 // the buffer before the transfer is finished. (Currently such
3633 // synchronization has to be handled manually.)
3634 GLuint offset
= ToGLuint(pixels
);
3635 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3636 bound_pixel_unpack_transfer_buffer_id_
,
3637 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
3638 if (buffer
&& buffer
->shm_id() != -1) {
3639 helper_
->AsyncTexSubImage2DCHROMIUM(
3640 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
3641 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3645 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
3646 GPU_CLIENT_SINGLE_THREAD_CHECK();
3647 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
3648 << GLES2Util::GetStringTextureTarget(target
) << ")");
3649 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
3653 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
3654 GPU_CLIENT_SINGLE_THREAD_CHECK();
3655 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
3656 return helper_
->InsertSyncPointCHROMIUM();
3659 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(
3660 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3662 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
3667 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
3670 // Flush the command stream to ensure ordering in case the newly
3671 // returned image_id has recently been in use with a different buffer.
3672 helper_
->CommandBufferHelper::Flush();
3674 // Create new buffer.
3675 GLuint buffer_id
= gpu_memory_buffer_tracker_
->CreateBuffer(
3676 width
, height
, internalformat
);
3677 if (buffer_id
== 0) {
3678 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "out of GPU memory.");
3684 GLuint
GLES2Implementation::CreateImageCHROMIUM(
3685 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3686 GPU_CLIENT_SINGLE_THREAD_CHECK();
3687 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM("
3690 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ")");
3691 GLuint image_id
= CreateImageCHROMIUMHelper(width
, height
, internalformat
);
3696 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
3697 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3700 SetGLError(GL_INVALID_OPERATION
, "glDestroyImageCHROMIUM", "invalid image");
3704 // Flush the command stream to make sure all pending commands
3705 // that may refer to the image_id are executed on the service side.
3706 helper_
->CommandBufferHelper::Flush();
3707 gpu_memory_buffer_tracker_
->RemoveBuffer(image_id
);
3710 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
3711 GPU_CLIENT_SINGLE_THREAD_CHECK();
3712 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
3713 << image_id
<< ")");
3714 DestroyImageCHROMIUMHelper(image_id
);
3718 void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id
) {
3719 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3722 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "invalid image");
3726 if (!gpu_buffer
->IsMapped()) {
3727 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "not mapped");
3730 gpu_buffer
->Unmap();
3733 void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id
) {
3734 GPU_CLIENT_SINGLE_THREAD_CHECK();
3735 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM("
3736 << image_id
<< ")");
3738 UnmapImageCHROMIUMHelper(image_id
);
3742 void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id
,
3744 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3747 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "invalid image");
3750 gfx::GpuMemoryBuffer::AccessMode mode
;
3753 mode
= gfx::GpuMemoryBuffer::WRITE_ONLY
;
3756 mode
= gfx::GpuMemoryBuffer::READ_ONLY
;
3759 mode
= gfx::GpuMemoryBuffer::READ_WRITE
;
3762 SetGLError(GL_INVALID_ENUM
, "glMapImageCHROMIUM",
3763 "invalid GPU access mode");
3767 if (gpu_buffer
->IsMapped()) {
3768 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "already mapped");
3772 void* mapped_buffer
= NULL
;
3773 gpu_buffer
->Map(mode
, &mapped_buffer
);
3774 return mapped_buffer
;
3777 void* GLES2Implementation::MapImageCHROMIUM(
3778 GLuint image_id
, GLenum access
) {
3779 GPU_CLIENT_SINGLE_THREAD_CHECK();
3780 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
3782 << GLES2Util::GetStringEnum(access
) << ")");
3784 void* mapped
= MapImageCHROMIUMHelper(image_id
, access
);
3789 void GLES2Implementation::GetImageParameterivCHROMIUMHelper(
3790 GLuint image_id
, GLenum pname
, GLint
* params
) {
3791 if (pname
!= GL_IMAGE_ROWBYTES_CHROMIUM
) {
3792 SetGLError(GL_INVALID_ENUM
, "glGetImageParameterivCHROMIUM",
3793 "invalid parameter");
3797 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3800 SetGLError(GL_INVALID_OPERATION
, "glGetImageParameterivCHROMIUM",
3805 *params
= gpu_buffer
->GetStride();
3808 void GLES2Implementation::GetImageParameterivCHROMIUM(
3809 GLuint image_id
, GLenum pname
, GLint
* params
) {
3810 GPU_CLIENT_SINGLE_THREAD_CHECK();
3811 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
3812 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glImageParameterivCHROMIUM("
3814 << GLES2Util::GetStringBufferParameter(pname
) << ", "
3815 << static_cast<const void*>(params
) << ")");
3816 GetImageParameterivCHROMIUMHelper(image_id
, pname
, params
);
3820 // Include the auto-generated part of this file. We split this because it means
3821 // we can easily edit the non-auto generated parts right here in this file
3822 // instead of having to edit some template or the code generator.
3823 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
3825 } // namespace gles2