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/gpu_control.h"
26 #include "gpu/command_buffer/common/trace_event.h"
27 #include "ui/gfx/gpu_memory_buffer.h"
29 #if defined(__native_client__) && !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
30 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
33 #if defined(GPU_CLIENT_DEBUG)
34 #include "ui/gl/gl_switches.h"
35 #include "base/command_line.h"
41 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
42 static GLuint
ToGLuint(const void* ptr
) {
43 return static_cast<GLuint
>(reinterpret_cast<size_t>(ptr
));
46 #if !defined(_MSC_VER)
47 const size_t GLES2Implementation::kMaxSizeOfSimpleResult
;
48 const unsigned int GLES2Implementation::kStartingOffset
;
51 GLES2Implementation::GLStaticState::GLStaticState() {
54 GLES2Implementation::GLStaticState::~GLStaticState() {
57 GLES2Implementation::GLStaticState::IntState::IntState()
58 : max_combined_texture_image_units(0),
59 max_cube_map_texture_size(0),
60 max_fragment_uniform_vectors(0),
61 max_renderbuffer_size(0),
62 max_texture_image_units(0),
64 max_varying_vectors(0),
65 max_vertex_attribs(0),
66 max_vertex_texture_image_units(0),
67 max_vertex_uniform_vectors(0),
68 num_compressed_texture_formats(0),
69 num_shader_binary_formats(0) {
72 GLES2Implementation::SingleThreadChecker::SingleThreadChecker(
73 GLES2Implementation
* gles2_implementation
)
74 : gles2_implementation_(gles2_implementation
) {
75 CHECK_EQ(0, gles2_implementation_
->use_count_
);
76 ++gles2_implementation_
->use_count_
;
79 GLES2Implementation::SingleThreadChecker::~SingleThreadChecker() {
80 --gles2_implementation_
->use_count_
;
81 CHECK_EQ(0, gles2_implementation_
->use_count_
);
84 GLES2Implementation::GLES2Implementation(
85 GLES2CmdHelper
* helper
,
86 ShareGroup
* share_group
,
87 TransferBufferInterface
* transfer_buffer
,
88 bool bind_generates_resource
,
89 bool free_everything_when_invisible
,
90 GpuControl
* gpu_control
)
92 transfer_buffer_(transfer_buffer
),
93 angle_pack_reverse_row_order_status_(kUnknownExtensionStatus
),
94 chromium_framebuffer_multisample_(kUnknownExtensionStatus
),
97 unpack_flip_y_(false),
98 unpack_row_length_(0),
100 unpack_skip_pixels_(0),
101 pack_reverse_row_order_(false),
102 active_texture_unit_(0),
103 bound_framebuffer_(0),
104 bound_read_framebuffer_(0),
105 bound_renderbuffer_(0),
107 bound_array_buffer_id_(0),
108 bound_pixel_pack_transfer_buffer_id_(0),
109 bound_pixel_unpack_transfer_buffer_id_(0),
113 error_message_callback_(NULL
),
114 gpu_control_(gpu_control
),
115 surface_visible_(true),
116 free_everything_when_invisible_(free_everything_when_invisible
),
117 capabilities_(gpu_control
->GetCapabilities()),
118 weak_ptr_factory_(this) {
120 DCHECK(transfer_buffer
);
124 sprintf(temp
, "%p", static_cast<void*>(this));
125 this_in_hex_
= std::string(temp
);
127 GPU_CLIENT_LOG_CODE_BLOCK({
128 debug_
= CommandLine::ForCurrentProcess()->HasSwitch(
129 switches::kEnableGPUClientLogging
);
133 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
135 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
138 bool GLES2Implementation::Initialize(
139 unsigned int starting_transfer_buffer_size
,
140 unsigned int min_transfer_buffer_size
,
141 unsigned int max_transfer_buffer_size
,
142 unsigned int mapped_memory_limit
) {
143 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
144 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
145 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
147 if (!transfer_buffer_
->Initialize(
148 starting_transfer_buffer_size
,
150 min_transfer_buffer_size
,
151 max_transfer_buffer_size
,
157 mapped_memory_
.reset(new MappedMemoryManager(helper_
, mapped_memory_limit
));
159 unsigned chunk_size
= 2 * 1024 * 1024;
160 if (mapped_memory_limit
!= kNoLimit
) {
161 // Use smaller chunks if the client is very memory conscientious.
162 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
164 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
166 if (!QueryAndCacheStaticState())
169 util_
.set_num_compressed_texture_formats(
170 static_state_
.int_state
.num_compressed_texture_formats
);
171 util_
.set_num_shader_binary_formats(
172 static_state_
.int_state
.num_shader_binary_formats
);
174 texture_units_
.reset(
176 static_state_
.int_state
.max_combined_texture_image_units
]);
178 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
179 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
180 gpu_memory_buffer_tracker_
.reset(new GpuMemoryBufferTracker(gpu_control_
));
182 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
183 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
184 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
187 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
188 static_state_
.int_state
.max_vertex_attribs
,
195 bool GLES2Implementation::QueryAndCacheStaticState() {
196 // Setup query for multiple GetIntegerv's
197 static const GLenum pnames
[] = {
198 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
199 GL_MAX_CUBE_MAP_TEXTURE_SIZE
,
200 GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
201 GL_MAX_RENDERBUFFER_SIZE
,
202 GL_MAX_TEXTURE_IMAGE_UNITS
,
204 GL_MAX_VARYING_VECTORS
,
205 GL_MAX_VERTEX_ATTRIBS
,
206 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
207 GL_MAX_VERTEX_UNIFORM_VECTORS
,
208 GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
209 GL_NUM_SHADER_BINARY_FORMATS
,
212 GetMultipleIntegervState
integerv_state(
213 pnames
, arraysize(pnames
),
214 &static_state_
.int_state
.max_combined_texture_image_units
,
215 sizeof(static_state_
.int_state
));
216 if (!GetMultipleIntegervSetup(&integerv_state
)) {
220 // Setup query for multiple GetShaderPrecisionFormat's
221 static const GLenum precision_params
[][2] = {
222 { GL_VERTEX_SHADER
, GL_LOW_INT
},
223 { GL_VERTEX_SHADER
, GL_MEDIUM_INT
},
224 { GL_VERTEX_SHADER
, GL_HIGH_INT
},
225 { GL_VERTEX_SHADER
, GL_LOW_FLOAT
},
226 { GL_VERTEX_SHADER
, GL_MEDIUM_FLOAT
},
227 { GL_VERTEX_SHADER
, GL_HIGH_FLOAT
},
228 { GL_FRAGMENT_SHADER
, GL_LOW_INT
},
229 { GL_FRAGMENT_SHADER
, GL_MEDIUM_INT
},
230 { GL_FRAGMENT_SHADER
, GL_HIGH_INT
},
231 { GL_FRAGMENT_SHADER
, GL_LOW_FLOAT
},
232 { GL_FRAGMENT_SHADER
, GL_MEDIUM_FLOAT
},
233 { GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
},
236 GetAllShaderPrecisionFormatsState
precision_state(
237 precision_params
, arraysize(precision_params
));
238 GetAllShaderPrecisionFormatsSetup(&precision_state
);
240 // Allocate and partition transfer buffer for all requests
241 void* buffer
= transfer_buffer_
->Alloc(
242 integerv_state
.transfer_buffer_size_needed
+
243 precision_state
.transfer_buffer_size_needed
);
245 SetGLError(GL_OUT_OF_MEMORY
, "QueryAndCacheStaticState",
246 "Transfer buffer allocation failed.");
249 integerv_state
.buffer
= buffer
;
250 precision_state
.results_buffer
=
251 static_cast<char*>(buffer
) + integerv_state
.transfer_buffer_size_needed
;
253 // Make all the requests and wait once for all the results.
254 GetMultipleIntegervRequest(&integerv_state
);
255 GetAllShaderPrecisionFormatsRequest(&precision_state
);
257 GetMultipleIntegervOnCompleted(&integerv_state
);
258 GetAllShaderPrecisionFormatsOnCompleted(&precision_state
);
260 // TODO(gman): We should be able to free without a token.
261 transfer_buffer_
->FreePendingToken(buffer
, helper_
->InsertToken());
267 GLES2Implementation::~GLES2Implementation() {
268 // Make sure the queries are finished otherwise we'll delete the
269 // shared memory (mapped_memory_) which will free the memory used
270 // by the queries. The GPU process when validating that memory is still
271 // shared will fail and abort (ie, it will stop running).
273 query_tracker_
.reset();
275 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
276 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
278 buffer_tracker_
.reset();
280 // Make sure the commands make it the service.
284 GLES2CmdHelper
* GLES2Implementation::helper() const {
288 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
289 return share_group_
->GetIdHandler(namespace_id
);
292 void* GLES2Implementation::GetResultBuffer() {
293 return transfer_buffer_
->GetResultBuffer();
296 int32
GLES2Implementation::GetResultShmId() {
297 return transfer_buffer_
->GetShmId();
300 uint32
GLES2Implementation::GetResultShmOffset() {
301 return transfer_buffer_
->GetResultOffset();
304 void GLES2Implementation::FreeUnusedSharedMemory() {
305 mapped_memory_
->FreeUnused();
308 void GLES2Implementation::FreeEverything() {
310 query_tracker_
->Shrink();
311 FreeUnusedSharedMemory();
312 transfer_buffer_
->Free();
313 helper_
->FreeRingBuffer();
316 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
317 if (!helper_
->IsContextLost())
321 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
322 const base::Closure
& callback
) {
323 gpu_control_
->SignalSyncPoint(
325 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
326 weak_ptr_factory_
.GetWeakPtr(),
330 void GLES2Implementation::SignalQuery(uint32 query
,
331 const base::Closure
& callback
) {
332 // Flush previously entered commands to ensure ordering with any
333 // glBeginQueryEXT() calls that may have been put into the context.
334 ShallowFlushCHROMIUM();
335 gpu_control_
->SignalQuery(
337 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
338 weak_ptr_factory_
.GetWeakPtr(),
342 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
343 // TODO(piman): This probably should be ShallowFlushCHROMIUM().
345 surface_visible_
= visible
;
346 gpu_control_
->SetSurfaceVisible(visible
);
351 void GLES2Implementation::SendManagedMemoryStats(
352 const ManagedMemoryStats
& stats
) {
353 gpu_control_
->SendManagedMemoryStats(stats
);
356 void GLES2Implementation::WaitForCmd() {
357 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
358 helper_
->CommandBufferHelper::Finish();
361 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
362 const char* extensions
=
363 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
367 int length
= strlen(ext
);
369 int n
= strcspn(extensions
, " ");
370 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
373 if ('\0' == extensions
[n
]) {
380 bool GLES2Implementation::IsExtensionAvailableHelper(
381 const char* extension
, ExtensionStatus
* status
) {
383 case kAvailableExtensionStatus
:
385 case kUnavailableExtensionStatus
:
388 bool available
= IsExtensionAvailable(extension
);
389 *status
= available
? kAvailableExtensionStatus
:
390 kUnavailableExtensionStatus
;
396 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
397 return IsExtensionAvailableHelper(
398 "GL_ANGLE_pack_reverse_row_order",
399 &angle_pack_reverse_row_order_status_
);
402 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
403 return IsExtensionAvailableHelper(
404 "GL_CHROMIUM_framebuffer_multisample",
405 &chromium_framebuffer_multisample_
);
408 const std::string
& GLES2Implementation::GetLogPrefix() const {
409 const std::string
& prefix(debug_marker_manager_
.GetMarker());
410 return prefix
.empty() ? this_in_hex_
: prefix
;
413 GLenum
GLES2Implementation::GetError() {
414 GPU_CLIENT_SINGLE_THREAD_CHECK();
415 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
416 GLenum err
= GetGLError();
417 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
421 GLenum
GLES2Implementation::GetClientSideGLError() {
422 if (error_bits_
== 0) {
426 GLenum error
= GL_NO_ERROR
;
427 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
428 if ((error_bits_
& mask
) != 0) {
429 error
= GLES2Util::GLErrorBitToGLError(mask
);
433 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
437 GLenum
GLES2Implementation::GetGLError() {
438 TRACE_EVENT0("gpu", "GLES2::GetGLError");
439 // Check the GL error first, then our wrapped error.
440 typedef cmds::GetError::Result Result
;
441 Result
* result
= GetResultAs
<Result
*>();
442 // If we couldn't allocate a result the context is lost.
446 *result
= GL_NO_ERROR
;
447 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
449 GLenum error
= *result
;
450 if (error
== GL_NO_ERROR
) {
451 error
= GetClientSideGLError();
453 // There was an error, clear the corresponding wrapped error.
454 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
459 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
460 void GLES2Implementation::FailGLError(GLenum error
) {
461 if (error
!= GL_NO_ERROR
) {
462 NOTREACHED() << "Error";
465 // NOTE: Calling GetGLError overwrites data in the result buffer.
466 void GLES2Implementation::CheckGLError() {
467 FailGLError(GetGLError());
469 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
471 void GLES2Implementation::SetGLError(
472 GLenum error
, const char* function_name
, const char* msg
) {
473 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
474 << GLES2Util::GetStringError(error
) << ": "
475 << function_name
<< ": " << msg
);
480 if (error_message_callback_
) {
481 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
482 function_name
+ ": " + (msg
? msg
: ""));
483 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
485 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
488 void GLES2Implementation::SetGLErrorInvalidEnum(
489 const char* function_name
, GLenum value
, const char* label
) {
490 SetGLError(GL_INVALID_ENUM
, function_name
,
491 (std::string(label
) + " was " +
492 GLES2Util::GetStringEnum(value
)).c_str());
495 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
496 std::vector
<int8
>* data
) {
497 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
499 const uint32 kStartSize
= 32 * 1024;
500 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
501 if (!buffer
.valid()) {
504 typedef cmd::GetBucketStart::Result Result
;
505 Result
* result
= GetResultAs
<Result
*>();
510 helper_
->GetBucketStart(
511 bucket_id
, GetResultShmId(), GetResultShmOffset(),
512 buffer
.size(), buffer
.shm_id(), buffer
.offset());
514 uint32 size
= *result
;
519 if (!buffer
.valid()) {
521 if (!buffer
.valid()) {
524 helper_
->GetBucketData(
525 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
528 uint32 size_to_copy
= std::min(size
, buffer
.size());
529 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
530 offset
+= size_to_copy
;
531 size
-= size_to_copy
;
534 // Free the bucket. This is not required but it does free up the memory.
535 // and we don't have to wait for the result so from the client's perspective
537 helper_
->SetBucketSize(bucket_id
, 0);
542 void GLES2Implementation::SetBucketContents(
543 uint32 bucket_id
, const void* data
, size_t size
) {
545 helper_
->SetBucketSize(bucket_id
, size
);
549 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
550 if (!buffer
.valid()) {
553 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
555 helper_
->SetBucketData(
556 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
557 offset
+= buffer
.size();
558 size
-= buffer
.size();
563 void GLES2Implementation::SetBucketAsCString(
564 uint32 bucket_id
, const char* str
) {
565 // NOTE: strings are passed NULL terminated. That means the empty
566 // string will have a size of 1 and no-string will have a size of 0
568 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
570 helper_
->SetBucketSize(bucket_id
, 0);
574 bool GLES2Implementation::GetBucketAsString(
575 uint32 bucket_id
, std::string
* str
) {
577 std::vector
<int8
> data
;
578 // NOTE: strings are passed NULL terminated. That means the empty
579 // string will have a size of 1 and no-string will have a size of 0
580 if (!GetBucketContents(bucket_id
, &data
)) {
586 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
590 void GLES2Implementation::SetBucketAsString(
591 uint32 bucket_id
, const std::string
& str
) {
592 // NOTE: strings are passed NULL terminated. That means the empty
593 // string will have a size of 1 and no-string will have a size of 0
594 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
597 void GLES2Implementation::Disable(GLenum cap
) {
598 GPU_CLIENT_SINGLE_THREAD_CHECK();
599 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
600 << GLES2Util::GetStringCapability(cap
) << ")");
601 bool changed
= false;
602 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
603 helper_
->Disable(cap
);
608 void GLES2Implementation::Enable(GLenum cap
) {
609 GPU_CLIENT_SINGLE_THREAD_CHECK();
610 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
611 << GLES2Util::GetStringCapability(cap
) << ")");
612 bool changed
= false;
613 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
614 helper_
->Enable(cap
);
619 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
620 GPU_CLIENT_SINGLE_THREAD_CHECK();
621 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
622 << GLES2Util::GetStringCapability(cap
) << ")");
624 if (!state_
.GetEnabled(cap
, &state
)) {
625 typedef cmds::IsEnabled::Result Result
;
626 Result
* result
= GetResultAs
<Result
*>();
631 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
633 state
= (*result
) != 0;
636 GPU_CLIENT_LOG("returned " << state
);
641 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
643 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
644 *params
= static_state_
.int_state
.max_combined_texture_image_units
;
646 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
647 *params
= static_state_
.int_state
.max_cube_map_texture_size
;
649 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
650 *params
= static_state_
.int_state
.max_fragment_uniform_vectors
;
652 case GL_MAX_RENDERBUFFER_SIZE
:
653 *params
= static_state_
.int_state
.max_renderbuffer_size
;
655 case GL_MAX_TEXTURE_IMAGE_UNITS
:
656 *params
= static_state_
.int_state
.max_texture_image_units
;
658 case GL_MAX_TEXTURE_SIZE
:
659 *params
= static_state_
.int_state
.max_texture_size
;
661 case GL_MAX_VARYING_VECTORS
:
662 *params
= static_state_
.int_state
.max_varying_vectors
;
664 case GL_MAX_VERTEX_ATTRIBS
:
665 *params
= static_state_
.int_state
.max_vertex_attribs
;
667 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
668 *params
= static_state_
.int_state
.max_vertex_texture_image_units
;
670 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
671 *params
= static_state_
.int_state
.max_vertex_uniform_vectors
;
673 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
674 *params
= static_state_
.int_state
.num_compressed_texture_formats
;
676 case GL_NUM_SHADER_BINARY_FORMATS
:
677 *params
= static_state_
.int_state
.num_shader_binary_formats
;
679 case GL_ARRAY_BUFFER_BINDING
:
680 if (share_group_
->bind_generates_resource()) {
681 *params
= bound_array_buffer_id_
;
685 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
686 if (share_group_
->bind_generates_resource()) {
688 vertex_array_object_manager_
->bound_element_array_buffer();
692 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
693 *params
= bound_pixel_pack_transfer_buffer_id_
;
695 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
696 *params
= bound_pixel_unpack_transfer_buffer_id_
;
698 case GL_ACTIVE_TEXTURE
:
699 *params
= active_texture_unit_
+ GL_TEXTURE0
;
701 case GL_TEXTURE_BINDING_2D
:
702 if (share_group_
->bind_generates_resource()) {
703 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
707 case GL_TEXTURE_BINDING_CUBE_MAP
:
708 if (share_group_
->bind_generates_resource()) {
709 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
713 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
714 if (share_group_
->bind_generates_resource()) {
716 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
720 case GL_FRAMEBUFFER_BINDING
:
721 if (share_group_
->bind_generates_resource()) {
722 *params
= bound_framebuffer_
;
726 case GL_READ_FRAMEBUFFER_BINDING
:
727 if (IsChromiumFramebufferMultisampleAvailable() &&
728 share_group_
->bind_generates_resource()) {
729 *params
= bound_read_framebuffer_
;
733 case GL_RENDERBUFFER_BINDING
:
734 if (share_group_
->bind_generates_resource()) {
735 *params
= bound_renderbuffer_
;
744 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
745 // TODO(gman): Make this handle pnames that return more than 1 value.
747 if (!GetHelper(pname
, &value
)) {
750 *params
= static_cast<GLboolean
>(value
);
754 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
755 // TODO(gman): Make this handle pnames that return more than 1 value.
757 if (!GetHelper(pname
, &value
)) {
760 *params
= static_cast<GLfloat
>(value
);
764 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
765 return GetHelper(pname
, params
);
768 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
769 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
770 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
771 Result
* result
= GetResultAs
<Result
*>();
776 helper_
->GetMaxValueInBufferCHROMIUM(
777 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
782 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
783 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
784 GPU_CLIENT_SINGLE_THREAD_CHECK();
785 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
786 << buffer_id
<< ", " << count
<< ", "
787 << GLES2Util::GetStringGetMaxIndexType(type
)
788 << ", " << offset
<< ")");
789 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
790 buffer_id
, count
, type
, offset
);
791 GPU_CLIENT_LOG("returned " << result
);
796 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
798 RestoreArrayBuffer(restore
);
799 // Restore the element array binding.
800 // We only need to restore it if it wasn't a client side array.
801 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
802 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
807 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
809 // Restore the user's current binding.
810 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_id_
);
814 void GLES2Implementation::DrawElements(
815 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
816 GPU_CLIENT_SINGLE_THREAD_CHECK();
817 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
818 << GLES2Util::GetStringDrawMode(mode
) << ", "
820 << GLES2Util::GetStringIndexType(type
) << ", "
821 << static_cast<const void*>(indices
) << ")");
823 SetGLError(GL_INVALID_VALUE
, "glDrawElements", "count less than 0.");
830 bool simulated
= false;
831 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
832 "glDrawElements", this, helper_
, count
, type
, 0, indices
,
833 &offset
, &simulated
)) {
836 helper_
->DrawElements(mode
, count
, type
, offset
);
837 RestoreElementAndArrayBuffers(simulated
);
841 void GLES2Implementation::Flush() {
842 GPU_CLIENT_SINGLE_THREAD_CHECK();
843 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
844 // Insert the cmd to call glFlush
846 // Flush our command buffer
847 // (tell the service to execute up to the flush cmd.)
848 helper_
->CommandBufferHelper::Flush();
849 if (!surface_visible_
&& free_everything_when_invisible_
)
853 void GLES2Implementation::ShallowFlushCHROMIUM() {
854 GPU_CLIENT_SINGLE_THREAD_CHECK();
855 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
856 // Flush our command buffer
857 // (tell the service to execute up to the flush cmd.)
858 helper_
->CommandBufferHelper::Flush();
859 // TODO(piman): Add the FreeEverything() logic here.
862 void GLES2Implementation::Finish() {
863 GPU_CLIENT_SINGLE_THREAD_CHECK();
865 if (!surface_visible_
&& free_everything_when_invisible_
)
869 void GLES2Implementation::ShallowFinishCHROMIUM() {
870 GPU_CLIENT_SINGLE_THREAD_CHECK();
871 // Flush our command buffer (tell the service to execute up to the flush cmd
872 // and don't return until it completes).
873 helper_
->CommandBufferHelper::Finish();
876 bool GLES2Implementation::MustBeContextLost() {
877 bool context_lost
= helper_
->IsContextLost();
880 context_lost
= helper_
->IsContextLost();
886 void GLES2Implementation::FinishHelper() {
887 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
888 TRACE_EVENT0("gpu", "GLES2::Finish");
889 // Insert the cmd to call glFinish
891 // Finish our command buffer
892 // (tell the service to execute up to the Finish cmd and wait for it to
894 helper_
->CommandBufferHelper::Finish();
897 void GLES2Implementation::SwapBuffers() {
898 GPU_CLIENT_SINGLE_THREAD_CHECK();
899 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
900 // TODO(piman): Strictly speaking we'd want to insert the token after the
901 // swap, but the state update with the updated token might not have happened
902 // by the time the SwapBuffer callback gets called, forcing us to synchronize
903 // with the GPU process more than needed. So instead, make it happen before.
904 // All it means is that we could be slightly looser on the kMaxSwapBuffers
905 // semantics if the client doesn't use the callback mechanism, and by chance
906 // the scheduler yields between the InsertToken and the SwapBuffers.
907 swap_buffers_tokens_
.push(helper_
->InsertToken());
908 helper_
->SwapBuffers();
909 helper_
->CommandBufferHelper::Flush();
910 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
911 // compensate for TODO above.
912 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
913 helper_
->WaitForToken(swap_buffers_tokens_
.front());
914 swap_buffers_tokens_
.pop();
918 void GLES2Implementation::GenSharedIdsCHROMIUM(
919 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
920 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSharedIdsCHROMIUM("
921 << namespace_id
<< ", " << id_offset
<< ", " << n
<< ", " <<
922 static_cast<void*>(ids
) << ")");
923 TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM");
927 ScopedTransferBufferArray
<GLint
> id_buffer(num
, helper_
, transfer_buffer_
);
928 if (!id_buffer
.valid()) {
931 helper_
->GenSharedIdsCHROMIUM(
932 namespace_id
, id_offset
, id_buffer
.num_elements(),
933 id_buffer
.shm_id(), id_buffer
.offset());
935 memcpy(dst
, id_buffer
.address(), sizeof(*dst
) * id_buffer
.num_elements());
936 num
-= id_buffer
.num_elements();
937 dst
+= id_buffer
.num_elements();
939 GPU_CLIENT_LOG_CODE_BLOCK({
940 for (GLsizei i
= 0; i
< n
; ++i
) {
941 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
946 void GLES2Implementation::DeleteSharedIdsCHROMIUM(
947 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
948 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedIdsCHROMIUM("
949 << namespace_id
<< ", " << n
<< ", "
950 << static_cast<const void*>(ids
) << ")");
951 GPU_CLIENT_LOG_CODE_BLOCK({
952 for (GLsizei i
= 0; i
< n
; ++i
) {
953 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
956 TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM");
958 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
959 if (!id_buffer
.valid()) {
962 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
963 helper_
->DeleteSharedIdsCHROMIUM(
964 namespace_id
, id_buffer
.num_elements(),
965 id_buffer
.shm_id(), id_buffer
.offset());
967 n
-= id_buffer
.num_elements();
968 ids
+= id_buffer
.num_elements();
972 void GLES2Implementation::RegisterSharedIdsCHROMIUM(
973 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
974 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRegisterSharedIdsCHROMIUM("
975 << namespace_id
<< ", " << n
<< ", "
976 << static_cast<const void*>(ids
) << ")");
977 GPU_CLIENT_LOG_CODE_BLOCK({
978 for (GLsizei i
= 0; i
< n
; ++i
) {
979 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
982 TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM");
984 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
985 if (!id_buffer
.valid()) {
988 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
989 helper_
->RegisterSharedIdsCHROMIUM(
990 namespace_id
, id_buffer
.num_elements(),
991 id_buffer
.shm_id(), id_buffer
.offset());
993 n
-= id_buffer
.num_elements();
994 ids
+= id_buffer
.num_elements();
998 void GLES2Implementation::BindAttribLocation(
999 GLuint program
, GLuint index
, const char* name
) {
1000 GPU_CLIENT_SINGLE_THREAD_CHECK();
1001 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1002 << program
<< ", " << index
<< ", " << name
<< ")");
1003 SetBucketAsString(kResultBucketId
, name
);
1004 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1005 helper_
->SetBucketSize(kResultBucketId
, 0);
1009 void GLES2Implementation::BindUniformLocationCHROMIUM(
1010 GLuint program
, GLint location
, const char* name
) {
1011 GPU_CLIENT_SINGLE_THREAD_CHECK();
1012 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1013 << program
<< ", " << location
<< ", " << name
<< ")");
1014 SetBucketAsString(kResultBucketId
, name
);
1015 helper_
->BindUniformLocationCHROMIUMBucket(
1016 program
, location
, kResultBucketId
);
1017 helper_
->SetBucketSize(kResultBucketId
, 0);
1021 void GLES2Implementation::GetVertexAttribPointerv(
1022 GLuint index
, GLenum pname
, void** ptr
) {
1023 GPU_CLIENT_SINGLE_THREAD_CHECK();
1024 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1025 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1026 << static_cast<void*>(ptr
) << ")");
1027 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1028 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1029 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1030 typedef cmds::GetVertexAttribPointerv::Result Result
;
1031 Result
* result
= GetResultAs
<Result
*>();
1035 result
->SetNumResults(0);
1036 helper_
->GetVertexAttribPointerv(
1037 index
, pname
, GetResultShmId(), GetResultShmOffset());
1039 result
->CopyResult(ptr
);
1040 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1042 GPU_CLIENT_LOG_CODE_BLOCK({
1043 for (int32 i
= 0; i
< num_results
; ++i
) {
1044 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1050 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1051 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1052 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1055 "glDeleteProgram", "id not created by this context.");
1058 if (program
== current_program_
) {
1059 current_program_
= 0;
1064 void GLES2Implementation::DeleteProgramStub(
1065 GLsizei n
, const GLuint
* programs
) {
1067 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1068 helper_
->DeleteProgram(programs
[0]);
1071 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1072 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1073 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1076 "glDeleteShader", "id not created by this context.");
1082 void GLES2Implementation::DeleteShaderStub(
1083 GLsizei n
, const GLuint
* shaders
) {
1085 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1086 helper_
->DeleteShader(shaders
[0]);
1090 GLint
GLES2Implementation::GetAttribLocationHelper(
1091 GLuint program
, const char* name
) {
1092 typedef cmds::GetAttribLocationBucket::Result Result
;
1093 Result
* result
= GetResultAs
<Result
*>();
1098 SetBucketAsCString(kResultBucketId
, name
);
1099 helper_
->GetAttribLocationBucket(
1100 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1102 helper_
->SetBucketSize(kResultBucketId
, 0);
1106 GLint
GLES2Implementation::GetAttribLocation(
1107 GLuint program
, const char* name
) {
1108 GPU_CLIENT_SINGLE_THREAD_CHECK();
1109 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1110 << ", " << name
<< ")");
1111 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1112 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1113 this, program
, name
);
1114 GPU_CLIENT_LOG("returned " << loc
);
1119 GLint
GLES2Implementation::GetUniformLocationHelper(
1120 GLuint program
, const char* name
) {
1121 typedef cmds::GetUniformLocationBucket::Result Result
;
1122 Result
* result
= GetResultAs
<Result
*>();
1127 SetBucketAsCString(kResultBucketId
, name
);
1128 helper_
->GetUniformLocationBucket(program
, kResultBucketId
,
1129 GetResultShmId(), GetResultShmOffset());
1131 helper_
->SetBucketSize(kResultBucketId
, 0);
1135 GLint
GLES2Implementation::GetUniformLocation(
1136 GLuint program
, const char* name
) {
1137 GPU_CLIENT_SINGLE_THREAD_CHECK();
1138 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1139 << ", " << name
<< ")");
1140 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1141 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1142 this, program
, name
);
1143 GPU_CLIENT_LOG("returned " << loc
);
1148 void GLES2Implementation::UseProgram(GLuint program
) {
1149 GPU_CLIENT_SINGLE_THREAD_CHECK();
1150 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program
<< ")");
1151 if (current_program_
!= program
) {
1152 current_program_
= program
;
1153 helper_
->UseProgram(program
);
1158 bool GLES2Implementation::GetProgramivHelper(
1159 GLuint program
, GLenum pname
, GLint
* params
) {
1160 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1161 this, program
, pname
, params
);
1162 GPU_CLIENT_LOG_CODE_BLOCK({
1164 GPU_CLIENT_LOG(" 0: " << *params
);
1170 void GLES2Implementation::LinkProgram(GLuint program
) {
1171 GPU_CLIENT_SINGLE_THREAD_CHECK();
1172 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1173 helper_
->LinkProgram(program
);
1174 share_group_
->program_info_manager()->CreateInfo(program
);
1178 void GLES2Implementation::ShaderBinary(
1179 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1181 GPU_CLIENT_SINGLE_THREAD_CHECK();
1182 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1183 << static_cast<const void*>(shaders
) << ", "
1184 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1185 << static_cast<const void*>(binary
) << ", "
1188 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1192 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1195 // TODO(gman): ShaderBinary should use buckets.
1196 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1197 ScopedTransferBufferArray
<GLint
> buffer(
1198 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1199 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1200 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1203 void* shader_ids
= buffer
.elements();
1204 void* shader_data
= buffer
.elements() + shader_id_size
;
1205 memcpy(shader_ids
, shaders
, shader_id_size
);
1206 memcpy(shader_data
, binary
, length
);
1207 helper_
->ShaderBinary(
1213 buffer
.offset() + shader_id_size
,
1218 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1219 GPU_CLIENT_SINGLE_THREAD_CHECK();
1220 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1221 << GLES2Util::GetStringPixelStore(pname
) << ", "
1224 case GL_PACK_ALIGNMENT
:
1225 pack_alignment_
= param
;
1227 case GL_UNPACK_ALIGNMENT
:
1228 unpack_alignment_
= param
;
1230 case GL_UNPACK_ROW_LENGTH_EXT
:
1231 unpack_row_length_
= param
;
1233 case GL_UNPACK_SKIP_ROWS_EXT
:
1234 unpack_skip_rows_
= param
;
1236 case GL_UNPACK_SKIP_PIXELS_EXT
:
1237 unpack_skip_pixels_
= param
;
1239 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1240 unpack_flip_y_
= (param
!= 0);
1242 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1243 pack_reverse_row_order_
=
1244 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1249 helper_
->PixelStorei(pname
, param
);
1254 void GLES2Implementation::VertexAttribPointer(
1255 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1257 GPU_CLIENT_SINGLE_THREAD_CHECK();
1258 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1261 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1262 << GLES2Util::GetStringBool(normalized
) << ", "
1264 << static_cast<const void*>(ptr
) << ")");
1265 // Record the info on the client side.
1266 if (!vertex_array_object_manager_
->SetAttribPointer(
1267 bound_array_buffer_id_
, index
, size
, type
, normalized
, stride
, ptr
)) {
1268 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1269 "client side arrays are not allowed in vertex array objects.");
1272 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1273 if (bound_array_buffer_id_
!= 0) {
1274 // Only report NON client side buffers to the service.
1275 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1278 #else // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1279 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1281 #endif // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1285 void GLES2Implementation::VertexAttribDivisorANGLE(
1286 GLuint index
, GLuint divisor
) {
1287 GPU_CLIENT_SINGLE_THREAD_CHECK();
1288 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1290 << divisor
<< ") ");
1291 // Record the info on the client side.
1292 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1293 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1297 void GLES2Implementation::ShaderSource(
1298 GLuint shader
, GLsizei count
, const GLchar
* const* source
, const GLint
* length
) {
1299 GPU_CLIENT_SINGLE_THREAD_CHECK();
1300 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderSource("
1301 << shader
<< ", " << count
<< ", "
1302 << static_cast<const void*>(source
) << ", "
1303 << static_cast<const void*>(length
) << ")");
1304 GPU_CLIENT_LOG_CODE_BLOCK({
1305 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1307 if (length
&& length
[ii
] >= 0) {
1308 std::string
str(source
[ii
], length
[ii
]);
1309 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << str
<< "\n---");
1311 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << source
[ii
] << "\n---");
1314 GPU_CLIENT_LOG(" " << ii
<< ": NULL");
1319 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "count < 0");
1323 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "shader == 0");
1327 // Compute the total size.
1328 uint32 total_size
= 1;
1329 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1331 total_size
+= (length
&& length
[ii
] >= 0) ?
1332 static_cast<size_t>(length
[ii
]) : strlen(source
[ii
]);
1336 // Concatenate all the strings in to a bucket on the service.
1337 helper_
->SetBucketSize(kResultBucketId
, total_size
);
1339 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
1340 const char* src
= ii
< count
? source
[ii
] : "";
1342 uint32 size
= ii
< count
?
1343 (length
? static_cast<size_t>(length
[ii
]) : strlen(src
)) : 1;
1345 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1346 if (!buffer
.valid()) {
1349 memcpy(buffer
.address(), src
, buffer
.size());
1350 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
1351 buffer
.shm_id(), buffer
.offset());
1352 offset
+= buffer
.size();
1353 src
+= buffer
.size();
1354 size
-= buffer
.size();
1359 DCHECK_EQ(total_size
, offset
);
1361 helper_
->ShaderSourceBucket(shader
, kResultBucketId
);
1362 helper_
->SetBucketSize(kResultBucketId
, 0);
1366 void GLES2Implementation::BufferDataHelper(
1367 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1369 SetGLError(GL_INVALID_VALUE
, "glBufferData", "size < 0");
1374 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1379 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1381 // Free buffer memory, pending the passage of a token.
1382 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
1384 // Remove old buffer.
1385 buffer_tracker_
->RemoveBuffer(buffer_id
);
1388 // Create new buffer.
1389 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1391 if (buffer
->address() && data
)
1392 memcpy(buffer
->address(), data
, size
);
1400 // If there is no data just send BufferData
1402 helper_
->BufferData(target
, size
, 0, 0, usage
);
1406 // See if we can send all at once.
1407 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1408 if (!buffer
.valid()) {
1412 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1413 memcpy(buffer
.address(), data
, size
);
1414 helper_
->BufferData(
1423 // Make the buffer with BufferData then send via BufferSubData
1424 helper_
->BufferData(target
, size
, 0, 0, usage
);
1425 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1429 void GLES2Implementation::BufferData(
1430 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1431 GPU_CLIENT_SINGLE_THREAD_CHECK();
1432 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1433 << GLES2Util::GetStringBufferTarget(target
) << ", "
1435 << static_cast<const void*>(data
) << ", "
1436 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1437 BufferDataHelper(target
, size
, data
, usage
);
1441 void GLES2Implementation::BufferSubDataHelper(
1442 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1448 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "size < 0");
1453 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1457 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1459 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1464 int32 buffer_size
= buffer
->size();
1465 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1466 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1470 if (buffer
->address() && data
)
1471 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1475 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1476 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1479 void GLES2Implementation::BufferSubDataHelperImpl(
1480 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1481 ScopedTransferBufferPtr
* buffer
) {
1485 const int8
* source
= static_cast<const int8
*>(data
);
1487 if (!buffer
->valid() || buffer
->size() == 0) {
1488 buffer
->Reset(size
);
1489 if (!buffer
->valid()) {
1493 memcpy(buffer
->address(), source
, buffer
->size());
1494 helper_
->BufferSubData(
1495 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1496 offset
+= buffer
->size();
1497 source
+= buffer
->size();
1498 size
-= buffer
->size();
1503 void GLES2Implementation::BufferSubData(
1504 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1505 GPU_CLIENT_SINGLE_THREAD_CHECK();
1506 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1507 << GLES2Util::GetStringBufferTarget(target
) << ", "
1508 << offset
<< ", " << size
<< ", "
1509 << static_cast<const void*>(data
) << ")");
1510 BufferSubDataHelper(target
, offset
, size
, data
);
1514 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1516 const char* function_name
,
1517 GLuint
* buffer_id
) {
1521 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1522 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1524 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1525 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1532 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1537 BufferTracker::Buffer
*
1538 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1540 const char* function_name
,
1541 GLuint offset
, GLsizei size
)
1544 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1546 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1549 if (buffer
->mapped()) {
1550 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1553 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1554 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1560 void GLES2Implementation::CompressedTexImage2D(
1561 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1562 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1563 GPU_CLIENT_SINGLE_THREAD_CHECK();
1564 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1565 << GLES2Util::GetStringTextureTarget(target
) << ", "
1567 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1568 << width
<< ", " << height
<< ", " << border
<< ", "
1569 << image_size
<< ", "
1570 << static_cast<const void*>(data
) << ")");
1571 if (width
< 0 || height
< 0 || level
< 0) {
1572 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1575 if (height
== 0 || width
== 0) {
1578 // If there's a pixel unpack buffer bound use it when issuing
1579 // CompressedTexImage2D.
1580 if (bound_pixel_unpack_transfer_buffer_id_
) {
1581 GLuint offset
= ToGLuint(data
);
1582 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1583 bound_pixel_unpack_transfer_buffer_id_
,
1584 "glCompressedTexImage2D", offset
, image_size
);
1585 if (buffer
&& buffer
->shm_id() != -1) {
1586 helper_
->CompressedTexImage2D(
1587 target
, level
, internalformat
, width
, height
, border
, image_size
,
1588 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1589 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1593 SetBucketContents(kResultBucketId
, data
, image_size
);
1594 helper_
->CompressedTexImage2DBucket(
1595 target
, level
, internalformat
, width
, height
, border
, kResultBucketId
);
1596 // Free the bucket. This is not required but it does free up the memory.
1597 // and we don't have to wait for the result so from the client's perspective
1599 helper_
->SetBucketSize(kResultBucketId
, 0);
1603 void GLES2Implementation::CompressedTexSubImage2D(
1604 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1605 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1606 GPU_CLIENT_SINGLE_THREAD_CHECK();
1607 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1608 << GLES2Util::GetStringTextureTarget(target
) << ", "
1610 << xoffset
<< ", " << yoffset
<< ", "
1611 << width
<< ", " << height
<< ", "
1612 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1613 << image_size
<< ", "
1614 << static_cast<const void*>(data
) << ")");
1615 if (width
< 0 || height
< 0 || level
< 0) {
1616 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1619 // If there's a pixel unpack buffer bound use it when issuing
1620 // CompressedTexSubImage2D.
1621 if (bound_pixel_unpack_transfer_buffer_id_
) {
1622 GLuint offset
= ToGLuint(data
);
1623 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1624 bound_pixel_unpack_transfer_buffer_id_
,
1625 "glCompressedTexSubImage2D", offset
, image_size
);
1626 if (buffer
&& buffer
->shm_id() != -1) {
1627 helper_
->CompressedTexSubImage2D(
1628 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1629 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1630 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1635 SetBucketContents(kResultBucketId
, data
, image_size
);
1636 helper_
->CompressedTexSubImage2DBucket(
1637 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1638 // Free the bucket. This is not required but it does free up the memory.
1639 // and we don't have to wait for the result so from the client's perspective
1641 helper_
->SetBucketSize(kResultBucketId
, 0);
1647 void CopyRectToBuffer(
1650 uint32 unpadded_row_size
,
1651 uint32 pixels_padded_row_size
,
1654 uint32 buffer_padded_row_size
) {
1655 const int8
* source
= static_cast<const int8
*>(pixels
);
1656 int8
* dest
= static_cast<int8
*>(buffer
);
1657 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
1659 dest
+= buffer_padded_row_size
* (height
- 1);
1661 // the last row is copied unpadded at the end
1662 for (; height
> 1; --height
) {
1663 memcpy(dest
, source
, buffer_padded_row_size
);
1665 dest
-= buffer_padded_row_size
;
1667 dest
+= buffer_padded_row_size
;
1669 source
+= pixels_padded_row_size
;
1671 memcpy(dest
, source
, unpadded_row_size
);
1673 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
1674 memcpy(dest
, source
, size
);
1678 } // anonymous namespace
1680 void GLES2Implementation::TexImage2D(
1681 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
1682 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
1683 const void* pixels
) {
1684 GPU_CLIENT_SINGLE_THREAD_CHECK();
1685 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
1686 << GLES2Util::GetStringTextureTarget(target
) << ", "
1688 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
1689 << width
<< ", " << height
<< ", " << border
<< ", "
1690 << GLES2Util::GetStringTextureFormat(format
) << ", "
1691 << GLES2Util::GetStringPixelType(type
) << ", "
1692 << static_cast<const void*>(pixels
) << ")");
1693 if (level
< 0 || height
< 0 || width
< 0) {
1694 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
1698 uint32 unpadded_row_size
;
1699 uint32 padded_row_size
;
1700 if (!GLES2Util::ComputeImageDataSizes(
1701 width
, height
, format
, type
, unpack_alignment_
, &size
,
1702 &unpadded_row_size
, &padded_row_size
)) {
1703 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
1707 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
1708 if (bound_pixel_unpack_transfer_buffer_id_
) {
1709 GLuint offset
= ToGLuint(pixels
);
1710 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1711 bound_pixel_unpack_transfer_buffer_id_
,
1712 "glTexImage2D", offset
, size
);
1713 if (buffer
&& buffer
->shm_id() != -1) {
1714 helper_
->TexImage2D(
1715 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1716 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1717 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1723 // If there's no data just issue TexImage2D
1725 helper_
->TexImage2D(
1726 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1732 // compute the advance bytes per row for the src pixels
1733 uint32 src_padded_row_size
;
1734 if (unpack_row_length_
> 0) {
1735 if (!GLES2Util::ComputeImagePaddedRowSize(
1736 unpack_row_length_
, format
, type
, unpack_alignment_
,
1737 &src_padded_row_size
)) {
1739 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1743 src_padded_row_size
= padded_row_size
;
1746 // advance pixels pointer past the skip rows and skip pixels
1747 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1748 unpack_skip_rows_
* src_padded_row_size
;
1749 if (unpack_skip_pixels_
) {
1750 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1751 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1752 unpack_skip_pixels_
* group_size
;
1755 // Check if we can send it all at once.
1756 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1757 if (!buffer
.valid()) {
1761 if (buffer
.size() >= size
) {
1763 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
1764 buffer
.address(), padded_row_size
);
1765 helper_
->TexImage2D(
1766 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1767 buffer
.shm_id(), buffer
.offset());
1772 // No, so send it using TexSubImage2D.
1773 helper_
->TexImage2D(
1774 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1777 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
1778 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
1782 void GLES2Implementation::TexSubImage2D(
1783 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1784 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
1785 GPU_CLIENT_SINGLE_THREAD_CHECK();
1786 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
1787 << GLES2Util::GetStringTextureTarget(target
) << ", "
1789 << xoffset
<< ", " << yoffset
<< ", "
1790 << width
<< ", " << height
<< ", "
1791 << GLES2Util::GetStringTextureFormat(format
) << ", "
1792 << GLES2Util::GetStringPixelType(type
) << ", "
1793 << static_cast<const void*>(pixels
) << ")");
1795 if (level
< 0 || height
< 0 || width
< 0) {
1796 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
1799 if (height
== 0 || width
== 0) {
1804 uint32 unpadded_row_size
;
1805 uint32 padded_row_size
;
1806 if (!GLES2Util::ComputeImageDataSizes(
1807 width
, height
, format
, type
, unpack_alignment_
, &temp_size
,
1808 &unpadded_row_size
, &padded_row_size
)) {
1809 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
1813 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
1814 if (bound_pixel_unpack_transfer_buffer_id_
) {
1815 GLuint offset
= ToGLuint(pixels
);
1816 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1817 bound_pixel_unpack_transfer_buffer_id_
,
1818 "glTexSubImage2D", offset
, temp_size
);
1819 if (buffer
&& buffer
->shm_id() != -1) {
1820 helper_
->TexSubImage2D(
1821 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1822 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
1823 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1829 // compute the advance bytes per row for the src pixels
1830 uint32 src_padded_row_size
;
1831 if (unpack_row_length_
> 0) {
1832 if (!GLES2Util::ComputeImagePaddedRowSize(
1833 unpack_row_length_
, format
, type
, unpack_alignment_
,
1834 &src_padded_row_size
)) {
1836 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1840 src_padded_row_size
= padded_row_size
;
1843 // advance pixels pointer past the skip rows and skip pixels
1844 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1845 unpack_skip_rows_
* src_padded_row_size
;
1846 if (unpack_skip_pixels_
) {
1847 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1848 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1849 unpack_skip_pixels_
* group_size
;
1852 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
1854 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1855 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
1860 static GLint
ComputeNumRowsThatFitInBuffer(
1861 GLsizeiptr padded_row_size
, GLsizeiptr unpadded_row_size
,
1862 unsigned int size
) {
1863 DCHECK_GE(unpadded_row_size
, 0);
1864 if (padded_row_size
== 0) {
1867 GLint num_rows
= size
/ padded_row_size
;
1868 return num_rows
+ (size
- num_rows
* padded_row_size
) / unpadded_row_size
;
1871 void GLES2Implementation::TexSubImage2DImpl(
1872 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1873 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
1874 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
1875 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
1877 DCHECK_GE(level
, 0);
1878 DCHECK_GT(height
, 0);
1879 DCHECK_GT(width
, 0);
1881 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
1882 GLint original_yoffset
= yoffset
;
1883 // Transfer by rows.
1885 unsigned int desired_size
=
1886 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
1887 if (!buffer
->valid() || buffer
->size() == 0) {
1888 buffer
->Reset(desired_size
);
1889 if (!buffer
->valid()) {
1894 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
1895 buffer_padded_row_size
, unpadded_row_size
, buffer
->size());
1896 num_rows
= std::min(num_rows
, height
);
1898 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
1899 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
1900 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
1901 helper_
->TexSubImage2D(
1902 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
1903 buffer
->shm_id(), buffer
->offset(), internal
);
1905 yoffset
+= num_rows
;
1906 source
+= num_rows
* pixels_padded_row_size
;
1911 bool GLES2Implementation::GetActiveAttribHelper(
1912 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1913 GLenum
* type
, char* name
) {
1914 // Clear the bucket so if the command fails nothing will be in it.
1915 helper_
->SetBucketSize(kResultBucketId
, 0);
1916 typedef cmds::GetActiveAttrib::Result Result
;
1917 Result
* result
= GetResultAs
<Result
*>();
1921 // Set as failed so if the command fails we'll recover.
1922 result
->success
= false;
1923 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
1924 GetResultShmId(), GetResultShmOffset());
1926 if (result
->success
) {
1928 *size
= result
->size
;
1931 *type
= result
->type
;
1933 if (length
|| name
) {
1934 std::vector
<int8
> str
;
1935 GetBucketContents(kResultBucketId
, &str
);
1936 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
1937 std::max(static_cast<size_t>(0),
1942 if (name
&& bufsize
> 0) {
1943 memcpy(name
, &str
[0], max_size
);
1944 name
[max_size
] = '\0';
1948 return result
->success
!= 0;
1951 void GLES2Implementation::GetActiveAttrib(
1952 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1953 GLenum
* type
, char* name
) {
1954 GPU_CLIENT_SINGLE_THREAD_CHECK();
1955 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
1956 << program
<< ", " << index
<< ", " << bufsize
<< ", "
1957 << static_cast<const void*>(length
) << ", "
1958 << static_cast<const void*>(size
) << ", "
1959 << static_cast<const void*>(type
) << ", "
1960 << static_cast<const void*>(name
) << ", ");
1962 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
1965 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
1966 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
1967 this, program
, index
, bufsize
, length
, size
, type
, name
);
1970 GPU_CLIENT_LOG(" size: " << *size
);
1973 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
1976 GPU_CLIENT_LOG(" name: " << name
);
1982 bool GLES2Implementation::GetActiveUniformHelper(
1983 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1984 GLenum
* type
, char* name
) {
1985 // Clear the bucket so if the command fails nothing will be in it.
1986 helper_
->SetBucketSize(kResultBucketId
, 0);
1987 typedef cmds::GetActiveUniform::Result Result
;
1988 Result
* result
= GetResultAs
<Result
*>();
1992 // Set as failed so if the command fails we'll recover.
1993 result
->success
= false;
1994 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
1995 GetResultShmId(), GetResultShmOffset());
1997 if (result
->success
) {
1999 *size
= result
->size
;
2002 *type
= result
->type
;
2004 if (length
|| name
) {
2005 std::vector
<int8
> str
;
2006 GetBucketContents(kResultBucketId
, &str
);
2007 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2008 std::max(static_cast<size_t>(0),
2013 if (name
&& bufsize
> 0) {
2014 memcpy(name
, &str
[0], max_size
);
2015 name
[max_size
] = '\0';
2019 return result
->success
!= 0;
2022 void GLES2Implementation::GetActiveUniform(
2023 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2024 GLenum
* type
, char* name
) {
2025 GPU_CLIENT_SINGLE_THREAD_CHECK();
2026 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2027 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2028 << static_cast<const void*>(length
) << ", "
2029 << static_cast<const void*>(size
) << ", "
2030 << static_cast<const void*>(type
) << ", "
2031 << static_cast<const void*>(name
) << ", ");
2033 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2036 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2037 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2038 this, program
, index
, bufsize
, length
, size
, type
, name
);
2041 GPU_CLIENT_LOG(" size: " << *size
);
2044 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2047 GPU_CLIENT_LOG(" name: " << name
);
2053 void GLES2Implementation::GetAttachedShaders(
2054 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
2055 GPU_CLIENT_SINGLE_THREAD_CHECK();
2056 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
2057 << program
<< ", " << maxcount
<< ", "
2058 << static_cast<const void*>(count
) << ", "
2059 << static_cast<const void*>(shaders
) << ", ");
2061 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2064 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2065 typedef cmds::GetAttachedShaders::Result Result
;
2066 uint32 size
= Result::ComputeSize(maxcount
);
2067 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2071 result
->SetNumResults(0);
2072 helper_
->GetAttachedShaders(
2074 transfer_buffer_
->GetShmId(),
2075 transfer_buffer_
->GetOffset(result
),
2077 int32 token
= helper_
->InsertToken();
2080 *count
= result
->GetNumResults();
2082 result
->CopyResult(shaders
);
2083 GPU_CLIENT_LOG_CODE_BLOCK({
2084 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2085 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2088 transfer_buffer_
->FreePendingToken(result
, token
);
2092 void GLES2Implementation::GetShaderPrecisionFormat(
2093 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2094 GPU_CLIENT_SINGLE_THREAD_CHECK();
2095 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
2096 << GLES2Util::GetStringShaderType(shadertype
) << ", "
2097 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
2098 << static_cast<const void*>(range
) << ", "
2099 << static_cast<const void*>(precision
) << ", ");
2100 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
2101 typedef cmds::GetShaderPrecisionFormat::Result Result
;
2102 Result
* result
= GetResultAs
<Result
*>();
2107 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
2108 GLStaticState::ShaderPrecisionMap::iterator i
=
2109 static_state_
.shader_precisions
.find(key
);
2110 if (i
!= static_state_
.shader_precisions
.end()) {
2111 *result
= i
->second
;
2113 result
->success
= false;
2114 helper_
->GetShaderPrecisionFormat(
2115 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
2117 if (result
->success
)
2118 static_state_
.shader_precisions
[key
] = *result
;
2121 if (result
->success
) {
2123 range
[0] = result
->min_range
;
2124 range
[1] = result
->max_range
;
2125 GPU_CLIENT_LOG(" min_range: " << range
[0]);
2126 GPU_CLIENT_LOG(" min_range: " << range
[1]);
2129 precision
[0] = result
->precision
;
2130 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
2136 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
2137 const char* result
= NULL
;
2138 // Clears the bucket so if the command fails nothing will be in it.
2139 helper_
->SetBucketSize(kResultBucketId
, 0);
2140 helper_
->GetString(name
, kResultBucketId
);
2142 if (GetBucketAsString(kResultBucketId
, &str
)) {
2143 // Adds extensions implemented on client side only.
2146 str
+= std::string(str
.empty() ? "" : " ") +
2147 "GL_CHROMIUM_flipy "
2148 "GL_EXT_unpack_subimage";
2149 if (capabilities_
.map_image
) {
2150 // The first space character is intentional.
2151 str
+= " GL_CHROMIUM_map_image";
2158 // Because of WebGL the extensions can change. We have to cache each unique
2159 // result since we don't know when the client will stop referring to a
2160 // previous one it queries.
2161 GLStringMap::iterator it
= gl_strings_
.find(name
);
2162 if (it
== gl_strings_
.end()) {
2163 std::set
<std::string
> strings
;
2164 std::pair
<GLStringMap::iterator
, bool> insert_result
=
2165 gl_strings_
.insert(std::make_pair(name
, strings
));
2166 DCHECK(insert_result
.second
);
2167 it
= insert_result
.first
;
2169 std::set
<std::string
>& string_set
= it
->second
;
2170 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
2171 if (sit
!= string_set
.end()) {
2172 result
= sit
->c_str();
2174 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2175 string_set
.insert(str
);
2176 DCHECK(insert_result
.second
);
2177 result
= insert_result
.first
->c_str();
2180 return reinterpret_cast<const GLubyte
*>(result
);
2183 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
2184 GPU_CLIENT_SINGLE_THREAD_CHECK();
2185 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
2186 << GLES2Util::GetStringStringType(name
) << ")");
2187 TRACE_EVENT0("gpu", "GLES2::GetString");
2188 const GLubyte
* result
= GetStringHelper(name
);
2189 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
2194 void GLES2Implementation::GetUniformfv(
2195 GLuint program
, GLint location
, GLfloat
* params
) {
2196 GPU_CLIENT_SINGLE_THREAD_CHECK();
2197 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
2198 << program
<< ", " << location
<< ", "
2199 << static_cast<const void*>(params
) << ")");
2200 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
2201 typedef cmds::GetUniformfv::Result Result
;
2202 Result
* result
= GetResultAs
<Result
*>();
2206 result
->SetNumResults(0);
2207 helper_
->GetUniformfv(
2208 program
, location
, GetResultShmId(), GetResultShmOffset());
2210 result
->CopyResult(params
);
2211 GPU_CLIENT_LOG_CODE_BLOCK({
2212 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2213 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2219 void GLES2Implementation::GetUniformiv(
2220 GLuint program
, GLint location
, GLint
* params
) {
2221 GPU_CLIENT_SINGLE_THREAD_CHECK();
2222 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
2223 << program
<< ", " << location
<< ", "
2224 << static_cast<const void*>(params
) << ")");
2225 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
2226 typedef cmds::GetUniformiv::Result Result
;
2227 Result
* result
= GetResultAs
<Result
*>();
2231 result
->SetNumResults(0);
2232 helper_
->GetUniformiv(
2233 program
, location
, GetResultShmId(), GetResultShmOffset());
2235 GetResultAs
<cmds::GetUniformfv::Result
*>()->CopyResult(params
);
2236 GPU_CLIENT_LOG_CODE_BLOCK({
2237 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2238 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2244 void GLES2Implementation::ReadPixels(
2245 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
2246 GLenum type
, void* pixels
) {
2247 GPU_CLIENT_SINGLE_THREAD_CHECK();
2248 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
2249 << xoffset
<< ", " << yoffset
<< ", "
2250 << width
<< ", " << height
<< ", "
2251 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
2252 << GLES2Util::GetStringPixelType(type
) << ", "
2253 << static_cast<const void*>(pixels
) << ")");
2254 if (width
< 0 || height
< 0) {
2255 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
2258 if (width
== 0 || height
== 0) {
2262 // glReadPixel pads the size of each row of pixels by an amount specified by
2263 // glPixelStorei. So, we have to take that into account both in the fact that
2264 // the pixels returned from the ReadPixel command will include that padding
2265 // and that when we copy the results to the user's buffer we need to not
2266 // write those padding bytes but leave them as they are.
2268 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
2269 typedef cmds::ReadPixels::Result Result
;
2271 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
2273 uint32 unpadded_row_size
;
2274 uint32 padded_row_size
;
2275 if (!GLES2Util::ComputeImageDataSizes(
2276 width
, 2, format
, type
, pack_alignment_
, &temp_size
, &unpadded_row_size
,
2277 &padded_row_size
)) {
2278 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
2282 if (bound_pixel_pack_transfer_buffer_id_
) {
2283 GLuint offset
= ToGLuint(pixels
);
2284 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2285 bound_pixel_pack_transfer_buffer_id_
,
2286 "glReadPixels", offset
, padded_row_size
* height
);
2287 if (buffer
&& buffer
->shm_id() != -1) {
2288 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
2289 buffer
->shm_id(), buffer
->shm_offset(),
2297 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
2301 // Transfer by rows.
2302 // The max rows we can transfer.
2304 GLsizei desired_size
= padded_row_size
* height
- 1 + unpadded_row_size
;
2305 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
2306 if (!buffer
.valid()) {
2309 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2310 padded_row_size
, unpadded_row_size
, buffer
.size());
2311 num_rows
= std::min(num_rows
, height
);
2312 // NOTE: We must look up the address of the result area AFTER allocation
2313 // of the transfer buffer since the transfer buffer may be reallocated.
2314 Result
* result
= GetResultAs
<Result
*>();
2318 *result
= 0; // mark as failed.
2319 helper_
->ReadPixels(
2320 xoffset
, yoffset
, width
, num_rows
, format
, type
,
2321 buffer
.shm_id(), buffer
.offset(),
2322 GetResultShmId(), GetResultShmOffset(),
2326 // when doing a y-flip we have to iterate through top-to-bottom chunks
2327 // of the dst. The service side handles reversing the rows within a
2330 if (pack_reverse_row_order_
) {
2331 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
2335 // We have to copy 1 row at a time to avoid writing pad bytes.
2336 const int8
* src
= static_cast<const int8
*>(buffer
.address());
2337 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
2338 memcpy(rows_dst
, src
, unpadded_row_size
);
2339 rows_dst
+= padded_row_size
;
2340 src
+= padded_row_size
;
2342 if (!pack_reverse_row_order_
) {
2346 // If it was not marked as successful exit.
2350 yoffset
+= num_rows
;
2356 void GLES2Implementation::ActiveTexture(GLenum texture
) {
2357 GPU_CLIENT_SINGLE_THREAD_CHECK();
2358 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
2359 << GLES2Util::GetStringEnum(texture
) << ")");
2360 GLuint texture_index
= texture
- GL_TEXTURE0
;
2361 if (texture_index
>= static_cast<GLuint
>(
2362 static_state_
.int_state
.max_combined_texture_image_units
)) {
2363 SetGLErrorInvalidEnum(
2364 "glActiveTexture", texture
, "texture");
2368 active_texture_unit_
= texture_index
;
2369 helper_
->ActiveTexture(texture
);
2373 void GLES2Implementation::GenBuffersHelper(
2374 GLsizei
/* n */, const GLuint
* /* buffers */) {
2377 void GLES2Implementation::GenFramebuffersHelper(
2378 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
2381 void GLES2Implementation::GenRenderbuffersHelper(
2382 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
2385 void GLES2Implementation::GenTexturesHelper(
2386 GLsizei
/* n */, const GLuint
* /* textures */) {
2389 void GLES2Implementation::GenVertexArraysOESHelper(
2390 GLsizei n
, const GLuint
* arrays
) {
2391 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
2394 void GLES2Implementation::GenQueriesEXTHelper(
2395 GLsizei
/* n */, const GLuint
* /* queries */) {
2398 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
2399 // generates a new resource. On newer versions of OpenGL they don't. The code
2400 // related to binding below will need to change if we switch to the new OpenGL
2401 // model. Specifically it assumes a bind will succeed which is always true in
2402 // the old model but possibly not true in the new model if another context has
2403 // deleted the resource.
2405 bool GLES2Implementation::BindBufferHelper(
2406 GLenum target
, GLuint buffer
) {
2407 // TODO(gman): See note #1 above.
2408 bool changed
= false;
2410 case GL_ARRAY_BUFFER
:
2411 if (bound_array_buffer_id_
!= buffer
) {
2412 bound_array_buffer_id_
= buffer
;
2416 case GL_ELEMENT_ARRAY_BUFFER
:
2417 changed
= vertex_array_object_manager_
->BindElementArray(buffer
);
2419 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
2420 bound_pixel_pack_transfer_buffer_id_
= buffer
;
2422 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
2423 bound_pixel_unpack_transfer_buffer_id_
= buffer
;
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::kBuffers
)->MarkAsUsedForBind(buffer
);
2435 bool GLES2Implementation::BindFramebufferHelper(
2436 GLenum target
, GLuint framebuffer
) {
2437 // TODO(gman): See note #1 above.
2438 bool changed
= false;
2440 case GL_FRAMEBUFFER
:
2441 if (bound_framebuffer_
!= framebuffer
||
2442 bound_read_framebuffer_
!= framebuffer
) {
2443 bound_framebuffer_
= framebuffer
;
2444 bound_read_framebuffer_
= framebuffer
;
2448 case GL_READ_FRAMEBUFFER
:
2449 if (!IsChromiumFramebufferMultisampleAvailable()) {
2450 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2453 if (bound_read_framebuffer_
!= framebuffer
) {
2454 bound_read_framebuffer_
= framebuffer
;
2458 case GL_DRAW_FRAMEBUFFER
:
2459 if (!IsChromiumFramebufferMultisampleAvailable()) {
2460 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2463 if (bound_framebuffer_
!= framebuffer
) {
2464 bound_framebuffer_
= framebuffer
;
2469 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2472 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(framebuffer
);
2476 bool GLES2Implementation::BindRenderbufferHelper(
2477 GLenum target
, GLuint renderbuffer
) {
2478 // TODO(gman): See note #1 above.
2479 bool changed
= false;
2481 case GL_RENDERBUFFER
:
2482 if (bound_renderbuffer_
!= renderbuffer
) {
2483 bound_renderbuffer_
= renderbuffer
;
2491 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2492 // used even though it's marked it as used here.
2493 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(renderbuffer
);
2497 bool GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
2498 // TODO(gman): See note #1 above.
2499 // TODO(gman): Change this to false once we figure out why it's failing
2501 bool changed
= true;
2502 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
2505 if (unit
.bound_texture_2d
!= texture
) {
2506 unit
.bound_texture_2d
= texture
;
2510 case GL_TEXTURE_CUBE_MAP
:
2511 if (unit
.bound_texture_cube_map
!= texture
) {
2512 unit
.bound_texture_cube_map
= texture
;
2516 case GL_TEXTURE_EXTERNAL_OES
:
2517 if (unit
.bound_texture_external_oes
!= texture
) {
2518 unit
.bound_texture_external_oes
= texture
;
2526 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2527 // used. even though it's marked it as used here.
2528 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(texture
);
2532 bool GLES2Implementation::BindVertexArrayHelper(GLuint array
) {
2533 // TODO(gman): See note #1 above.
2534 bool changed
= false;
2535 if (!vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
2537 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
2538 "id was not generated with glGenVertexArrayOES");
2540 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
2541 // because unlike other resources VertexArrayObject ids must
2542 // be generated by GenVertexArrays. A random id to Bind will not
2543 // generate a new object.
2547 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
2548 return vertex_array_object_manager_
->IsReservedId(id
);
2551 void GLES2Implementation::DeleteBuffersHelper(
2552 GLsizei n
, const GLuint
* buffers
) {
2553 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
2554 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
2557 "glDeleteBuffers", "id not created by this context.");
2560 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2561 if (buffers
[ii
] == bound_array_buffer_id_
) {
2562 bound_array_buffer_id_
= 0;
2564 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
2565 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
2567 // Free buffer memory, pending the passage of a token.
2568 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
2570 buffer_tracker_
->RemoveBuffer(buffers
[ii
]);
2572 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
2573 bound_pixel_unpack_transfer_buffer_id_
= 0;
2578 void GLES2Implementation::DeleteBuffersStub(
2579 GLsizei n
, const GLuint
* buffers
) {
2580 helper_
->DeleteBuffersImmediate(n
, buffers
);
2584 void GLES2Implementation::DeleteFramebuffersHelper(
2585 GLsizei n
, const GLuint
* framebuffers
) {
2586 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
2587 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
2590 "glDeleteFramebuffers", "id not created by this context.");
2593 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2594 if (framebuffers
[ii
] == bound_framebuffer_
) {
2595 bound_framebuffer_
= 0;
2597 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
2598 bound_read_framebuffer_
= 0;
2603 void GLES2Implementation::DeleteFramebuffersStub(
2604 GLsizei n
, const GLuint
* framebuffers
) {
2605 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
2608 void GLES2Implementation::DeleteRenderbuffersHelper(
2609 GLsizei n
, const GLuint
* renderbuffers
) {
2610 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
2611 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
2614 "glDeleteRenderbuffers", "id not created by this context.");
2617 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2618 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
2619 bound_renderbuffer_
= 0;
2624 void GLES2Implementation::DeleteRenderbuffersStub(
2625 GLsizei n
, const GLuint
* renderbuffers
) {
2626 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
2629 void GLES2Implementation::DeleteTexturesHelper(
2630 GLsizei n
, const GLuint
* textures
) {
2631 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
2632 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
2635 "glDeleteTextures", "id not created by this context.");
2638 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2640 tt
< static_state_
.int_state
.max_combined_texture_image_units
;
2642 TextureUnit
& unit
= texture_units_
[tt
];
2643 if (textures
[ii
] == unit
.bound_texture_2d
) {
2644 unit
.bound_texture_2d
= 0;
2646 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
2647 unit
.bound_texture_cube_map
= 0;
2649 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
2650 unit
.bound_texture_external_oes
= 0;
2656 void GLES2Implementation::DeleteVertexArraysOESHelper(
2657 GLsizei n
, const GLuint
* arrays
) {
2658 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
2659 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
2660 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
2663 "glDeleteVertexArraysOES", "id not created by this context.");
2668 void GLES2Implementation::DeleteVertexArraysOESStub(
2669 GLsizei n
, const GLuint
* arrays
) {
2670 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
2673 void GLES2Implementation::DeleteTexturesStub(
2674 GLsizei n
, const GLuint
* textures
) {
2675 helper_
->DeleteTexturesImmediate(n
, textures
);
2678 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
2679 GPU_CLIENT_SINGLE_THREAD_CHECK();
2681 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
2682 vertex_array_object_manager_
->SetAttribEnable(index
, false);
2683 helper_
->DisableVertexAttribArray(index
);
2687 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
2688 GPU_CLIENT_SINGLE_THREAD_CHECK();
2689 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
2691 vertex_array_object_manager_
->SetAttribEnable(index
, true);
2692 helper_
->EnableVertexAttribArray(index
);
2696 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2697 GPU_CLIENT_SINGLE_THREAD_CHECK();
2698 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
2699 << GLES2Util::GetStringDrawMode(mode
) << ", "
2700 << first
<< ", " << count
<< ")");
2702 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
2705 bool simulated
= false;
2706 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
2707 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
2710 helper_
->DrawArrays(mode
, first
, count
);
2711 RestoreArrayBuffer(simulated
);
2715 void GLES2Implementation::GetVertexAttribfv(
2716 GLuint index
, GLenum pname
, GLfloat
* params
) {
2717 GPU_CLIENT_SINGLE_THREAD_CHECK();
2718 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
2720 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2721 << static_cast<const void*>(params
) << ")");
2723 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2724 *params
= static_cast<float>(value
);
2727 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
2728 typedef cmds::GetVertexAttribfv::Result Result
;
2729 Result
* result
= GetResultAs
<Result
*>();
2733 result
->SetNumResults(0);
2734 helper_
->GetVertexAttribfv(
2735 index
, pname
, GetResultShmId(), GetResultShmOffset());
2737 result
->CopyResult(params
);
2738 GPU_CLIENT_LOG_CODE_BLOCK({
2739 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2740 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2746 void GLES2Implementation::GetVertexAttribiv(
2747 GLuint index
, GLenum pname
, GLint
* params
) {
2748 GPU_CLIENT_SINGLE_THREAD_CHECK();
2749 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
2751 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2752 << static_cast<const void*>(params
) << ")");
2754 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2758 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
2759 typedef cmds::GetVertexAttribiv::Result Result
;
2760 Result
* result
= GetResultAs
<Result
*>();
2764 result
->SetNumResults(0);
2765 helper_
->GetVertexAttribiv(
2766 index
, pname
, GetResultShmId(), GetResultShmOffset());
2768 result
->CopyResult(params
);
2769 GPU_CLIENT_LOG_CODE_BLOCK({
2770 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2771 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2777 void GLES2Implementation::Swap() {
2780 base::Bind(&GLES2Implementation::OnSwapBuffersComplete
,
2781 weak_ptr_factory_
.GetWeakPtr()));
2784 void GLES2Implementation::PartialSwapBuffers(const gfx::Rect
& sub_buffer
) {
2785 PostSubBufferCHROMIUM(sub_buffer
.x(),
2788 sub_buffer
.height());
2789 gpu_control_
->Echo(base::Bind(&GLES2Implementation::OnSwapBuffersComplete
,
2790 weak_ptr_factory_
.GetWeakPtr()));
2793 void GLES2Implementation::SetSwapBuffersCompleteCallback(
2794 const base::Closure
& swap_buffers_complete_callback
) {
2795 swap_buffers_complete_callback_
= swap_buffers_complete_callback
;
2798 void GLES2Implementation::OnSwapBuffersComplete() {
2799 if (!swap_buffers_complete_callback_
.is_null())
2800 swap_buffers_complete_callback_
.Run();
2803 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
2804 const char* feature
) {
2805 GPU_CLIENT_SINGLE_THREAD_CHECK();
2806 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
2808 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
2809 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
2810 Result
* result
= GetResultAs
<Result
*>();
2815 SetBucketAsCString(kResultBucketId
, feature
);
2816 helper_
->EnableFeatureCHROMIUM(
2817 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
2819 helper_
->SetBucketSize(kResultBucketId
, 0);
2820 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
2824 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
2825 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
2826 GPU_CLIENT_SINGLE_THREAD_CHECK();
2827 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
2828 << target
<< ", " << offset
<< ", " << size
<< ", "
2829 << GLES2Util::GetStringEnum(access
) << ")");
2830 // NOTE: target is NOT checked because the service will check it
2831 // and we don't know what targets are valid.
2832 if (access
!= GL_WRITE_ONLY
) {
2833 SetGLErrorInvalidEnum(
2834 "glMapBufferSubDataCHROMIUM", access
, "access");
2837 if (offset
< 0 || size
< 0) {
2838 SetGLError(GL_INVALID_VALUE
, "glMapBufferSubDataCHROMIUM", "bad range");
2842 unsigned int shm_offset
;
2843 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2845 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
2849 std::pair
<MappedBufferMap::iterator
, bool> result
=
2850 mapped_buffers_
.insert(std::make_pair(
2853 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
2854 DCHECK(result
.second
);
2855 GPU_CLIENT_LOG(" returned " << mem
);
2859 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
2860 GPU_CLIENT_SINGLE_THREAD_CHECK();
2862 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
2863 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
2864 if (it
== mapped_buffers_
.end()) {
2866 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
2869 const MappedBuffer
& mb
= it
->second
;
2870 helper_
->BufferSubData(
2871 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
2872 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
2873 mapped_buffers_
.erase(it
);
2877 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
2887 GPU_CLIENT_SINGLE_THREAD_CHECK();
2888 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
2889 << target
<< ", " << level
<< ", "
2890 << xoffset
<< ", " << yoffset
<< ", "
2891 << width
<< ", " << height
<< ", "
2892 << GLES2Util::GetStringTextureFormat(format
) << ", "
2893 << GLES2Util::GetStringPixelType(type
) << ", "
2894 << GLES2Util::GetStringEnum(access
) << ")");
2895 if (access
!= GL_WRITE_ONLY
) {
2896 SetGLErrorInvalidEnum(
2897 "glMapTexSubImage2DCHROMIUM", access
, "access");
2900 // NOTE: target is NOT checked because the service will check it
2901 // and we don't know what targets are valid.
2902 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
2904 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
2908 if (!GLES2Util::ComputeImageDataSizes(
2909 width
, height
, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
2911 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
2915 unsigned int shm_offset
;
2916 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2918 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
2922 std::pair
<MappedTextureMap::iterator
, bool> result
=
2923 mapped_textures_
.insert(std::make_pair(
2926 access
, shm_id
, mem
, shm_offset
,
2927 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
2928 DCHECK(result
.second
);
2929 GPU_CLIENT_LOG(" returned " << mem
);
2933 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
2934 GPU_CLIENT_SINGLE_THREAD_CHECK();
2936 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
2937 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
2938 if (it
== mapped_textures_
.end()) {
2940 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
2943 const MappedTexture
& mt
= it
->second
;
2944 helper_
->TexSubImage2D(
2945 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
2946 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
2947 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
2948 mapped_textures_
.erase(it
);
2952 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
2953 float scale_factor
) {
2954 GPU_CLIENT_SINGLE_THREAD_CHECK();
2955 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
2956 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
2957 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
2961 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
2962 GPU_CLIENT_SINGLE_THREAD_CHECK();
2963 GPU_CLIENT_LOG("[" << GetLogPrefix()
2964 << "] glGetRequestableExtensionsCHROMIUM()");
2966 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
2967 const char* result
= NULL
;
2968 // Clear the bucket so if the command fails nothing will be in it.
2969 helper_
->SetBucketSize(kResultBucketId
, 0);
2970 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
2972 if (GetBucketAsString(kResultBucketId
, &str
)) {
2973 // The set of requestable extensions shrinks as we enable
2974 // them. Because we don't know when the client will stop referring
2975 // to a previous one it queries (see GetString) we need to cache
2976 // the unique results.
2977 std::set
<std::string
>::const_iterator sit
=
2978 requestable_extensions_set_
.find(str
);
2979 if (sit
!= requestable_extensions_set_
.end()) {
2980 result
= sit
->c_str();
2982 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2983 requestable_extensions_set_
.insert(str
);
2984 DCHECK(insert_result
.second
);
2985 result
= insert_result
.first
->c_str();
2988 GPU_CLIENT_LOG(" returned " << result
);
2989 return reinterpret_cast<const GLchar
*>(result
);
2992 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
2993 // with VirtualGL contexts.
2994 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
2995 GPU_CLIENT_SINGLE_THREAD_CHECK();
2996 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
2997 << extension
<< ")");
2998 SetBucketAsCString(kResultBucketId
, extension
);
2999 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
3000 helper_
->SetBucketSize(kResultBucketId
, 0);
3002 struct ExtensionCheck
{
3003 const char* extension
;
3004 ExtensionStatus
* status
;
3006 const ExtensionCheck checks
[] = {
3008 "GL_ANGLE_pack_reverse_row_order",
3009 &angle_pack_reverse_row_order_status_
,
3012 "GL_CHROMIUM_framebuffer_multisample",
3013 &chromium_framebuffer_multisample_
,
3016 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
3017 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
3018 const ExtensionCheck
& check
= checks
[ii
];
3019 if (*check
.status
== kUnavailableExtensionStatus
&&
3020 !strcmp(extension
, check
.extension
)) {
3021 *check
.status
= kUnknownExtensionStatus
;
3026 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
3027 GPU_CLIENT_SINGLE_THREAD_CHECK();
3028 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
3029 // Wait if this would add too many rate limit tokens.
3030 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
3031 helper_
->WaitForToken(rate_limit_tokens_
.front());
3032 rate_limit_tokens_
.pop();
3034 rate_limit_tokens_
.push(helper_
->InsertToken());
3037 void GLES2Implementation::GetMultipleIntegervCHROMIUM(
3038 const GLenum
* pnames
, GLuint count
, GLint
* results
, GLsizeiptr size
) {
3039 GPU_CLIENT_SINGLE_THREAD_CHECK();
3040 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMultipleIntegervCHROMIUM("
3041 << static_cast<const void*>(pnames
) << ", "
3042 << count
<< ", " << results
<< ", "
3044 GPU_CLIENT_LOG_CODE_BLOCK({
3045 for (GLuint i
= 0; i
< count
; ++i
) {
3047 " " << i
<< ": " << GLES2Util::GetStringGLState(pnames
[i
]));
3051 GetMultipleIntegervState
state(pnames
, count
, results
, size
);
3052 if (!GetMultipleIntegervSetup(&state
)) {
3055 state
.buffer
= transfer_buffer_
->Alloc(state
.transfer_buffer_size_needed
);
3056 if (!state
.buffer
) {
3057 SetGLError(GL_OUT_OF_MEMORY
, "glGetMultipleIntegervCHROMIUM",
3058 "Transfer buffer allocation failed.");
3061 GetMultipleIntegervRequest(&state
);
3063 GetMultipleIntegervOnCompleted(&state
);
3065 GPU_CLIENT_LOG(" returned");
3066 GPU_CLIENT_LOG_CODE_BLOCK({
3067 for (int i
= 0; i
< state
.num_results
; ++i
) {
3068 GPU_CLIENT_LOG(" " << i
<< ": " << (results
[i
]));
3072 // TODO(gman): We should be able to free without a token.
3073 transfer_buffer_
->FreePendingToken(state
.buffer
, helper_
->InsertToken());
3077 bool GLES2Implementation::GetMultipleIntegervSetup(
3078 GetMultipleIntegervState
* state
) {
3079 state
->num_results
= 0;
3080 for (GLuint ii
= 0; ii
< state
->pnames_count
; ++ii
) {
3081 int num
= util_
.GLGetNumValuesReturned(state
->pnames
[ii
]);
3083 SetGLErrorInvalidEnum(
3084 "glGetMultipleIntegervCHROMIUM", state
->pnames
[ii
], "pname");
3087 state
->num_results
+= num
;
3089 if (static_cast<size_t>(state
->results_size
) !=
3090 state
->num_results
* sizeof(GLint
)) {
3091 SetGLError(GL_INVALID_VALUE
, "glGetMultipleIntegervCHROMIUM", "bad size");
3094 for (int ii
= 0; ii
< state
->num_results
; ++ii
) {
3095 if (state
->results
[ii
] != 0) {
3096 SetGLError(GL_INVALID_VALUE
,
3097 "glGetMultipleIntegervCHROMIUM", "results not set to zero.");
3101 state
->transfer_buffer_size_needed
=
3102 state
->pnames_count
* sizeof(state
->pnames
[0]) +
3103 state
->num_results
* sizeof(state
->results
[0]);
3107 void GLES2Implementation::GetMultipleIntegervRequest(
3108 GetMultipleIntegervState
* state
) {
3109 GLenum
* pnames_buffer
= static_cast<GLenum
*>(state
->buffer
);
3110 state
->results_buffer
= pnames_buffer
+ state
->pnames_count
;
3111 memcpy(pnames_buffer
, state
->pnames
, state
->pnames_count
* sizeof(GLenum
));
3112 memset(state
->results_buffer
, 0, state
->num_results
* sizeof(GLint
));
3113 helper_
->GetMultipleIntegervCHROMIUM(
3114 transfer_buffer_
->GetShmId(),
3115 transfer_buffer_
->GetOffset(pnames_buffer
),
3116 state
->pnames_count
,
3117 transfer_buffer_
->GetShmId(),
3118 transfer_buffer_
->GetOffset(state
->results_buffer
),
3119 state
->results_size
);
3122 void GLES2Implementation::GetMultipleIntegervOnCompleted(
3123 GetMultipleIntegervState
* state
) {
3124 memcpy(state
->results
, state
->results_buffer
, state
->results_size
);;
3127 void GLES2Implementation::GetAllShaderPrecisionFormatsSetup(
3128 GetAllShaderPrecisionFormatsState
* state
) {
3129 state
->transfer_buffer_size_needed
=
3130 state
->precision_params_count
*
3131 sizeof(cmds::GetShaderPrecisionFormat::Result
);
3134 void GLES2Implementation::GetAllShaderPrecisionFormatsRequest(
3135 GetAllShaderPrecisionFormatsState
* state
) {
3136 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3137 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3139 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3140 result
->success
= false;
3141 helper_
->GetShaderPrecisionFormat(state
->precision_params
[i
][0],
3142 state
->precision_params
[i
][1],
3143 transfer_buffer_
->GetShmId(),
3144 transfer_buffer_
->GetOffset(result
));
3149 void GLES2Implementation::GetAllShaderPrecisionFormatsOnCompleted(
3150 GetAllShaderPrecisionFormatsState
* state
) {
3151 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3152 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3154 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3155 if (result
->success
) {
3156 const GLStaticState::ShaderPrecisionKey
key(
3157 state
->precision_params
[i
][0], state
->precision_params
[i
][1]);
3158 static_state_
.shader_precisions
[key
] = *result
;
3164 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
3165 GLuint program
, std::vector
<int8
>* result
) {
3167 // Clear the bucket so if the command fails nothing will be in it.
3168 helper_
->SetBucketSize(kResultBucketId
, 0);
3169 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
3170 GetBucketContents(kResultBucketId
, result
);
3173 void GLES2Implementation::GetProgramInfoCHROMIUM(
3174 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
3175 GPU_CLIENT_SINGLE_THREAD_CHECK();
3178 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
3182 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
3185 // Make sure they've set size to 0 else the value will be undefined on
3188 std::vector
<int8
> result
;
3189 GetProgramInfoCHROMIUMHelper(program
, &result
);
3190 if (result
.empty()) {
3193 *size
= result
.size();
3197 if (static_cast<size_t>(bufsize
) < result
.size()) {
3198 SetGLError(GL_INVALID_OPERATION
,
3199 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
3202 memcpy(info
, &result
[0], result
.size());
3205 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
3206 GPU_CLIENT_SINGLE_THREAD_CHECK();
3207 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
3209 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
3210 typedef cmds::CreateStreamTextureCHROMIUM::Result Result
;
3211 Result
* result
= GetResultAs
<Result
*>();
3217 helper_
->CreateStreamTextureCHROMIUM(texture
,
3219 GetResultShmOffset());
3221 GLuint result_value
= *result
;
3223 return result_value
;
3226 void GLES2Implementation::DestroyStreamTextureCHROMIUM(GLuint texture
) {
3227 GPU_CLIENT_SINGLE_THREAD_CHECK();
3228 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] DestroyStreamTextureCHROMIUM("
3230 TRACE_EVENT0("gpu", "GLES2::DestroyStreamTextureCHROMIUM");
3231 helper_
->DestroyStreamTextureCHROMIUM(texture
);
3235 void GLES2Implementation::PostSubBufferCHROMIUM(
3236 GLint x
, GLint y
, GLint width
, GLint height
) {
3237 GPU_CLIENT_SINGLE_THREAD_CHECK();
3238 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
3239 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
3240 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
3241 "width", width
, "height", height
);
3243 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
3244 swap_buffers_tokens_
.push(helper_
->InsertToken());
3245 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
3246 helper_
->CommandBufferHelper::Flush();
3247 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
3248 helper_
->WaitForToken(swap_buffers_tokens_
.front());
3249 swap_buffers_tokens_
.pop();
3253 void GLES2Implementation::DeleteQueriesEXTHelper(
3254 GLsizei n
, const GLuint
* queries
) {
3255 // TODO(gman): Remove this as queries are not shared resources.
3256 if (!GetIdHandler(id_namespaces::kQueries
)->FreeIds(
3257 this, n
, queries
, &GLES2Implementation::DeleteQueriesStub
)) {
3260 "glDeleteTextures", "id not created by this context.");
3264 for (GLsizei ii
= 0; ii
< n
; ++ii
)
3265 query_tracker_
->RemoveQuery(queries
[ii
]);
3267 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
3270 // TODO(gman): Remove this. Queries are not shared resources.
3271 void GLES2Implementation::DeleteQueriesStub(
3272 GLsizei
/* n */, const GLuint
* /* queries */) {
3275 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
3276 GPU_CLIENT_SINGLE_THREAD_CHECK();
3277 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
3279 // TODO(gman): To be spec compliant IDs from other contexts sharing
3280 // resources need to return true here even though you can't share
3281 // queries across contexts?
3282 return query_tracker_
->GetQuery(id
) != NULL
;
3285 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
3286 GPU_CLIENT_SINGLE_THREAD_CHECK();
3287 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
3288 << GLES2Util::GetStringQueryTarget(target
)
3289 << ", " << id
<< ")");
3291 // if any outstanding queries INV_OP
3292 QueryMap::iterator it
= current_queries_
.find(target
);
3293 if (it
!= current_queries_
.end()) {
3295 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
3301 SetGLError(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
3305 // TODO(gman) if id not GENned INV_OPERATION
3307 // if id does not have an object
3308 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
3310 query
= query_tracker_
->CreateQuery(id
, target
);
3312 MustBeContextLost();
3315 } else if (query
->target() != target
) {
3317 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
3321 current_queries_
[target
] = query
;
3327 void GLES2Implementation::EndQueryEXT(GLenum target
) {
3328 GPU_CLIENT_SINGLE_THREAD_CHECK();
3329 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] EndQueryEXT("
3330 << GLES2Util::GetStringQueryTarget(target
) << ")");
3331 // Don't do anything if the context is lost.
3332 if (helper_
->IsContextLost()) {
3336 QueryMap::iterator it
= current_queries_
.find(target
);
3337 if (it
== current_queries_
.end()) {
3338 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
3342 QueryTracker::Query
* query
= it
->second
;
3344 current_queries_
.erase(it
);
3348 void GLES2Implementation::GetQueryivEXT(
3349 GLenum target
, GLenum pname
, GLint
* params
) {
3350 GPU_CLIENT_SINGLE_THREAD_CHECK();
3351 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
3352 << GLES2Util::GetStringQueryTarget(target
) << ", "
3353 << GLES2Util::GetStringQueryParameter(pname
) << ", "
3354 << static_cast<const void*>(params
) << ")");
3356 if (pname
!= GL_CURRENT_QUERY_EXT
) {
3357 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
3360 QueryMap::iterator it
= current_queries_
.find(target
);
3361 if (it
!= current_queries_
.end()) {
3362 QueryTracker::Query
* query
= it
->second
;
3363 *params
= query
->id();
3367 GPU_CLIENT_LOG(" " << *params
);
3371 void GLES2Implementation::GetQueryObjectuivEXT(
3372 GLuint id
, GLenum pname
, GLuint
* params
) {
3373 GPU_CLIENT_SINGLE_THREAD_CHECK();
3374 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
3375 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
3376 << static_cast<const void*>(params
) << ")");
3378 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
3380 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
3384 QueryMap::iterator it
= current_queries_
.find(query
->target());
3385 if (it
!= current_queries_
.end()) {
3387 GL_INVALID_OPERATION
,
3388 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
3392 if (query
->NeverUsed()) {
3394 GL_INVALID_OPERATION
,
3395 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
3400 case GL_QUERY_RESULT_EXT
:
3401 if (!query
->CheckResultsAvailable(helper_
)) {
3402 helper_
->WaitForToken(query
->token());
3403 if (!query
->CheckResultsAvailable(helper_
)) {
3404 // TODO(gman): Speed this up.
3406 CHECK(query
->CheckResultsAvailable(helper_
));
3409 *params
= query
->GetResult();
3411 case GL_QUERY_RESULT_AVAILABLE_EXT
:
3412 *params
= query
->CheckResultsAvailable(helper_
);
3415 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
3418 GPU_CLIENT_LOG(" " << *params
);
3422 void GLES2Implementation::DrawArraysInstancedANGLE(
3423 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
3424 GPU_CLIENT_SINGLE_THREAD_CHECK();
3425 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
3426 << GLES2Util::GetStringDrawMode(mode
) << ", "
3427 << first
<< ", " << count
<< ", " << primcount
<< ")");
3429 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
3432 if (primcount
< 0) {
3433 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
3436 if (primcount
== 0) {
3439 bool simulated
= false;
3440 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3441 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
3445 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
3446 RestoreArrayBuffer(simulated
);
3450 void GLES2Implementation::DrawElementsInstancedANGLE(
3451 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
3452 GLsizei primcount
) {
3453 GPU_CLIENT_SINGLE_THREAD_CHECK();
3454 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
3455 << GLES2Util::GetStringDrawMode(mode
) << ", "
3457 << GLES2Util::GetStringIndexType(type
) << ", "
3458 << static_cast<const void*>(indices
) << ", "
3459 << primcount
<< ")");
3461 SetGLError(GL_INVALID_VALUE
,
3462 "glDrawElementsInstancedANGLE", "count less than 0.");
3468 if (primcount
< 0) {
3469 SetGLError(GL_INVALID_VALUE
,
3470 "glDrawElementsInstancedANGLE", "primcount < 0");
3473 if (primcount
== 0) {
3477 bool simulated
= false;
3478 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
3479 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
3480 indices
, &offset
, &simulated
)) {
3483 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
3484 RestoreElementAndArrayBuffers(simulated
);
3488 void GLES2Implementation::GenMailboxCHROMIUM(
3490 GPU_CLIENT_SINGLE_THREAD_CHECK();
3491 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
3492 << static_cast<const void*>(mailbox
) << ")");
3493 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
3495 std::vector
<gpu::Mailbox
> names
;
3496 if (!gpu_control_
->GenerateMailboxNames(1, &names
)) {
3497 SetGLError(GL_OUT_OF_MEMORY
, "glGenMailboxCHROMIUM", "Generate failed.");
3500 memcpy(mailbox
, names
[0].name
, GL_MAILBOX_SIZE_CHROMIUM
);
3503 void GLES2Implementation::PushGroupMarkerEXT(
3504 GLsizei length
, const GLchar
* marker
) {
3505 GPU_CLIENT_SINGLE_THREAD_CHECK();
3506 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
3507 << length
<< ", " << marker
<< ")");
3513 (length
? std::string(marker
, length
) : std::string(marker
)));
3514 helper_
->PushGroupMarkerEXT(kResultBucketId
);
3515 helper_
->SetBucketSize(kResultBucketId
, 0);
3516 debug_marker_manager_
.PushGroup(
3517 length
? std::string(marker
, length
) : std::string(marker
));
3520 void GLES2Implementation::InsertEventMarkerEXT(
3521 GLsizei length
, const GLchar
* marker
) {
3522 GPU_CLIENT_SINGLE_THREAD_CHECK();
3523 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
3524 << length
<< ", " << marker
<< ")");
3530 (length
? std::string(marker
, length
) : std::string(marker
)));
3531 helper_
->InsertEventMarkerEXT(kResultBucketId
);
3532 helper_
->SetBucketSize(kResultBucketId
, 0);
3533 debug_marker_manager_
.SetMarker(
3534 length
? std::string(marker
, length
) : std::string(marker
));
3537 void GLES2Implementation::PopGroupMarkerEXT() {
3538 GPU_CLIENT_SINGLE_THREAD_CHECK();
3539 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
3540 helper_
->PopGroupMarkerEXT();
3541 debug_marker_manager_
.PopGroup();
3544 void GLES2Implementation::TraceBeginCHROMIUM(const char* name
) {
3545 GPU_CLIENT_SINGLE_THREAD_CHECK();
3546 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
3548 if (current_trace_name_
.get()) {
3549 SetGLError(GL_INVALID_OPERATION
, "glTraceBeginCHROMIUM",
3550 "trace already running");
3553 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", name
, this);
3554 SetBucketAsCString(kResultBucketId
, name
);
3555 helper_
->TraceBeginCHROMIUM(kResultBucketId
);
3556 helper_
->SetBucketSize(kResultBucketId
, 0);
3557 current_trace_name_
.reset(new std::string(name
));
3560 void GLES2Implementation::TraceEndCHROMIUM() {
3561 GPU_CLIENT_SINGLE_THREAD_CHECK();
3562 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
3563 if (!current_trace_name_
.get()) {
3564 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
3565 "missing begin trace");
3568 helper_
->TraceEndCHROMIUM();
3569 TRACE_EVENT_COPY_ASYNC_END0("gpu", current_trace_name_
->c_str(), this);
3570 current_trace_name_
.reset();
3573 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
3574 GPU_CLIENT_SINGLE_THREAD_CHECK();
3575 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
3576 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
3578 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3579 if (access
!= GL_READ_ONLY
) {
3580 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3584 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3585 if (access
!= GL_WRITE_ONLY
) {
3586 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3592 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
3596 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
3600 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3602 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
3605 if (buffer
->mapped()) {
3606 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
3609 // Here we wait for previous transfer operations to be finished.
3610 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
3611 // with this method of synchronization. Until this is fixed,
3612 // MapBufferCHROMIUM will not block even if the transfer is not ready
3614 if (buffer
->transfer_ready_token()) {
3615 helper_
->WaitForToken(buffer
->transfer_ready_token());
3616 buffer
->set_transfer_ready_token(0);
3618 buffer
->set_mapped(true);
3620 GPU_CLIENT_LOG(" returned " << buffer
->address());
3622 return buffer
->address();
3625 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
3626 GPU_CLIENT_SINGLE_THREAD_CHECK();
3628 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
3630 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
3631 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
3636 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3638 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
3641 if (!buffer
->mapped()) {
3642 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
3645 buffer
->set_mapped(false);
3650 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
3651 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
3652 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
3653 const void* pixels
) {
3654 GPU_CLIENT_SINGLE_THREAD_CHECK();
3655 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
3656 << GLES2Util::GetStringTextureTarget(target
) << ", "
3658 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
3659 << width
<< ", " << height
<< ", " << border
<< ", "
3660 << GLES2Util::GetStringTextureFormat(format
) << ", "
3661 << GLES2Util::GetStringPixelType(type
) << ", "
3662 << static_cast<const void*>(pixels
) << ")");
3663 if (level
< 0 || height
< 0 || width
< 0) {
3664 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
3668 uint32 unpadded_row_size
;
3669 uint32 padded_row_size
;
3670 if (!GLES2Util::ComputeImageDataSizes(
3671 width
, height
, format
, type
, unpack_alignment_
, &size
,
3672 &unpadded_row_size
, &padded_row_size
)) {
3673 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
3677 // If there's no data/buffer just issue the AsyncTexImage2D
3678 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
3679 helper_
->AsyncTexImage2DCHROMIUM(
3680 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3685 // Otherwise, async uploads require a transfer buffer to be bound.
3686 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3687 // the buffer before the transfer is finished. (Currently such
3688 // synchronization has to be handled manually.)
3689 GLuint offset
= ToGLuint(pixels
);
3690 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3691 bound_pixel_unpack_transfer_buffer_id_
,
3692 "glAsyncTexImage2DCHROMIUM", offset
, size
);
3693 if (buffer
&& buffer
->shm_id() != -1) {
3694 helper_
->AsyncTexImage2DCHROMIUM(
3695 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3696 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3700 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
3701 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
3702 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
3703 GPU_CLIENT_SINGLE_THREAD_CHECK();
3704 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
3705 << GLES2Util::GetStringTextureTarget(target
) << ", "
3707 << xoffset
<< ", " << yoffset
<< ", "
3708 << width
<< ", " << height
<< ", "
3709 << GLES2Util::GetStringTextureFormat(format
) << ", "
3710 << GLES2Util::GetStringPixelType(type
) << ", "
3711 << static_cast<const void*>(pixels
) << ")");
3712 if (level
< 0 || height
< 0 || width
< 0) {
3714 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
3719 uint32 unpadded_row_size
;
3720 uint32 padded_row_size
;
3721 if (!GLES2Util::ComputeImageDataSizes(
3722 width
, height
, format
, type
, unpack_alignment_
, &size
,
3723 &unpadded_row_size
, &padded_row_size
)) {
3725 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
3729 // Async uploads require a transfer buffer to be bound.
3730 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3731 // the buffer before the transfer is finished. (Currently such
3732 // synchronization has to be handled manually.)
3733 GLuint offset
= ToGLuint(pixels
);
3734 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3735 bound_pixel_unpack_transfer_buffer_id_
,
3736 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
3737 if (buffer
&& buffer
->shm_id() != -1) {
3738 helper_
->AsyncTexSubImage2DCHROMIUM(
3739 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
3740 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3744 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
3745 GPU_CLIENT_SINGLE_THREAD_CHECK();
3746 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
3747 << GLES2Util::GetStringTextureTarget(target
) << ")");
3748 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
3752 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
3753 GPU_CLIENT_SINGLE_THREAD_CHECK();
3754 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
3755 helper_
->CommandBufferHelper::Flush();
3756 return gpu_control_
->InsertSyncPoint();
3759 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(
3760 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3762 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
3767 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
3770 // Flush the command stream to ensure ordering in case the newly
3771 // returned image_id has recently been in use with a different buffer.
3772 helper_
->CommandBufferHelper::Flush();
3774 // Create new buffer.
3775 GLuint buffer_id
= gpu_memory_buffer_tracker_
->CreateBuffer(
3776 width
, height
, internalformat
);
3777 if (buffer_id
== 0) {
3778 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "out of GPU memory.");
3784 GLuint
GLES2Implementation::CreateImageCHROMIUM(
3785 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3786 GPU_CLIENT_SINGLE_THREAD_CHECK();
3787 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM("
3790 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ")");
3791 GLuint image_id
= CreateImageCHROMIUMHelper(width
, height
, internalformat
);
3796 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
3797 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3800 SetGLError(GL_INVALID_OPERATION
, "glDestroyImageCHROMIUM", "invalid image");
3804 // Flush the command stream to make sure all pending commands
3805 // that may refer to the image_id are executed on the service side.
3806 helper_
->CommandBufferHelper::Flush();
3807 gpu_memory_buffer_tracker_
->RemoveBuffer(image_id
);
3810 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
3811 GPU_CLIENT_SINGLE_THREAD_CHECK();
3812 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
3813 << image_id
<< ")");
3814 DestroyImageCHROMIUMHelper(image_id
);
3818 void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id
) {
3819 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3822 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "invalid image");
3826 if (!gpu_buffer
->IsMapped()) {
3827 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "not mapped");
3830 gpu_buffer
->Unmap();
3833 void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id
) {
3834 GPU_CLIENT_SINGLE_THREAD_CHECK();
3835 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM("
3836 << image_id
<< ")");
3838 UnmapImageCHROMIUMHelper(image_id
);
3842 void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id
,
3844 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3847 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "invalid image");
3850 gfx::GpuMemoryBuffer::AccessMode mode
;
3853 mode
= gfx::GpuMemoryBuffer::WRITE_ONLY
;
3856 mode
= gfx::GpuMemoryBuffer::READ_ONLY
;
3859 mode
= gfx::GpuMemoryBuffer::READ_WRITE
;
3862 SetGLError(GL_INVALID_ENUM
, "glMapImageCHROMIUM",
3863 "invalid GPU access mode");
3867 if (gpu_buffer
->IsMapped()) {
3868 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "already mapped");
3872 void* mapped_buffer
= NULL
;
3873 gpu_buffer
->Map(mode
, &mapped_buffer
);
3874 return mapped_buffer
;
3877 void* GLES2Implementation::MapImageCHROMIUM(
3878 GLuint image_id
, GLenum access
) {
3879 GPU_CLIENT_SINGLE_THREAD_CHECK();
3880 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
3882 << GLES2Util::GetStringEnum(access
) << ")");
3884 void* mapped
= MapImageCHROMIUMHelper(image_id
, access
);
3889 void GLES2Implementation::GetImageParameterivCHROMIUMHelper(
3890 GLuint image_id
, GLenum pname
, GLint
* params
) {
3891 if (pname
!= GL_IMAGE_ROWBYTES_CHROMIUM
) {
3892 SetGLError(GL_INVALID_ENUM
, "glGetImageParameterivCHROMIUM",
3893 "invalid parameter");
3897 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3900 SetGLError(GL_INVALID_OPERATION
, "glGetImageParameterivCHROMIUM",
3905 *params
= gpu_buffer
->GetStride();
3908 void GLES2Implementation::GetImageParameterivCHROMIUM(
3909 GLuint image_id
, GLenum pname
, GLint
* params
) {
3910 GPU_CLIENT_SINGLE_THREAD_CHECK();
3911 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
3912 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glImageParameterivCHROMIUM("
3914 << GLES2Util::GetStringBufferParameter(pname
) << ", "
3915 << static_cast<const void*>(params
) << ")");
3916 GetImageParameterivCHROMIUMHelper(image_id
, pname
, params
);
3920 // Include the auto-generated part of this file. We split this because it means
3921 // we can easily edit the non-auto generated parts right here in this file
3922 // instead of having to edit some template or the code generator.
3923 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
3925 } // namespace gles2