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 current_query_(NULL
),
114 error_message_callback_(NULL
),
115 gpu_control_(gpu_control
),
116 surface_visible_(true),
117 free_everything_when_invisible_(free_everything_when_invisible
),
118 capabilities_(gpu_control
->GetCapabilities()),
119 weak_ptr_factory_(this) {
121 DCHECK(transfer_buffer
);
125 sprintf(temp
, "%p", static_cast<void*>(this));
126 this_in_hex_
= std::string(temp
);
128 GPU_CLIENT_LOG_CODE_BLOCK({
129 debug_
= CommandLine::ForCurrentProcess()->HasSwitch(
130 switches::kEnableGPUClientLogging
);
134 (share_group
? share_group
: new ShareGroup(bind_generates_resource
));
136 memset(&reserved_ids_
, 0, sizeof(reserved_ids_
));
139 bool GLES2Implementation::Initialize(
140 unsigned int starting_transfer_buffer_size
,
141 unsigned int min_transfer_buffer_size
,
142 unsigned int max_transfer_buffer_size
,
143 unsigned int mapped_memory_limit
) {
144 DCHECK_GE(starting_transfer_buffer_size
, min_transfer_buffer_size
);
145 DCHECK_LE(starting_transfer_buffer_size
, max_transfer_buffer_size
);
146 DCHECK_GE(min_transfer_buffer_size
, kStartingOffset
);
148 if (!transfer_buffer_
->Initialize(
149 starting_transfer_buffer_size
,
151 min_transfer_buffer_size
,
152 max_transfer_buffer_size
,
158 mapped_memory_
.reset(new MappedMemoryManager(helper_
, mapped_memory_limit
));
160 unsigned chunk_size
= 2 * 1024 * 1024;
161 if (mapped_memory_limit
!= kNoLimit
) {
162 // Use smaller chunks if the client is very memory conscientious.
163 chunk_size
= std::min(mapped_memory_limit
/ 4, chunk_size
);
165 mapped_memory_
->set_chunk_size_multiple(chunk_size
);
167 if (!QueryAndCacheStaticState())
170 util_
.set_num_compressed_texture_formats(
171 static_state_
.int_state
.num_compressed_texture_formats
);
172 util_
.set_num_shader_binary_formats(
173 static_state_
.int_state
.num_shader_binary_formats
);
175 texture_units_
.reset(
177 static_state_
.int_state
.max_combined_texture_image_units
]);
179 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
180 buffer_tracker_
.reset(new BufferTracker(mapped_memory_
.get()));
181 gpu_memory_buffer_tracker_
.reset(new GpuMemoryBufferTracker(gpu_control_
));
183 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
184 GetIdHandler(id_namespaces::kBuffers
)->MakeIds(
185 this, kClientSideArrayId
, arraysize(reserved_ids_
), &reserved_ids_
[0]);
188 vertex_array_object_manager_
.reset(new VertexArrayObjectManager(
189 static_state_
.int_state
.max_vertex_attribs
,
196 bool GLES2Implementation::QueryAndCacheStaticState() {
197 // Setup query for multiple GetIntegerv's
198 static const GLenum pnames
[] = {
199 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
200 GL_MAX_CUBE_MAP_TEXTURE_SIZE
,
201 GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
202 GL_MAX_RENDERBUFFER_SIZE
,
203 GL_MAX_TEXTURE_IMAGE_UNITS
,
205 GL_MAX_VARYING_VECTORS
,
206 GL_MAX_VERTEX_ATTRIBS
,
207 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
208 GL_MAX_VERTEX_UNIFORM_VECTORS
,
209 GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
210 GL_NUM_SHADER_BINARY_FORMATS
,
213 GetMultipleIntegervState
integerv_state(
214 pnames
, arraysize(pnames
),
215 &static_state_
.int_state
.max_combined_texture_image_units
,
216 sizeof(static_state_
.int_state
));
217 if (!GetMultipleIntegervSetup(&integerv_state
)) {
221 // Setup query for multiple GetShaderPrecisionFormat's
222 static const GLenum precision_params
[][2] = {
223 { GL_VERTEX_SHADER
, GL_LOW_INT
},
224 { GL_VERTEX_SHADER
, GL_MEDIUM_INT
},
225 { GL_VERTEX_SHADER
, GL_HIGH_INT
},
226 { GL_VERTEX_SHADER
, GL_LOW_FLOAT
},
227 { GL_VERTEX_SHADER
, GL_MEDIUM_FLOAT
},
228 { GL_VERTEX_SHADER
, GL_HIGH_FLOAT
},
229 { GL_FRAGMENT_SHADER
, GL_LOW_INT
},
230 { GL_FRAGMENT_SHADER
, GL_MEDIUM_INT
},
231 { GL_FRAGMENT_SHADER
, GL_HIGH_INT
},
232 { GL_FRAGMENT_SHADER
, GL_LOW_FLOAT
},
233 { GL_FRAGMENT_SHADER
, GL_MEDIUM_FLOAT
},
234 { GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
},
237 GetAllShaderPrecisionFormatsState
precision_state(
238 precision_params
, arraysize(precision_params
));
239 GetAllShaderPrecisionFormatsSetup(&precision_state
);
241 // Allocate and partition transfer buffer for all requests
242 void* buffer
= transfer_buffer_
->Alloc(
243 integerv_state
.transfer_buffer_size_needed
+
244 precision_state
.transfer_buffer_size_needed
);
246 SetGLError(GL_OUT_OF_MEMORY
, "QueryAndCacheStaticState",
247 "Transfer buffer allocation failed.");
250 integerv_state
.buffer
= buffer
;
251 precision_state
.results_buffer
=
252 static_cast<char*>(buffer
) + integerv_state
.transfer_buffer_size_needed
;
254 // Make all the requests and wait once for all the results.
255 GetMultipleIntegervRequest(&integerv_state
);
256 GetAllShaderPrecisionFormatsRequest(&precision_state
);
258 GetMultipleIntegervOnCompleted(&integerv_state
);
259 GetAllShaderPrecisionFormatsOnCompleted(&precision_state
);
261 // TODO(gman): We should be able to free without a token.
262 transfer_buffer_
->FreePendingToken(buffer
, helper_
->InsertToken());
268 GLES2Implementation::~GLES2Implementation() {
269 // Make sure the queries are finished otherwise we'll delete the
270 // shared memory (mapped_memory_) which will free the memory used
271 // by the queries. The GPU process when validating that memory is still
272 // shared will fail and abort (ie, it will stop running).
274 query_tracker_
.reset();
276 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
277 DeleteBuffers(arraysize(reserved_ids_
), &reserved_ids_
[0]);
279 buffer_tracker_
.reset();
281 // Make sure the commands make it the service.
285 GLES2CmdHelper
* GLES2Implementation::helper() const {
289 IdHandlerInterface
* GLES2Implementation::GetIdHandler(int namespace_id
) const {
290 return share_group_
->GetIdHandler(namespace_id
);
293 void* GLES2Implementation::GetResultBuffer() {
294 return transfer_buffer_
->GetResultBuffer();
297 int32
GLES2Implementation::GetResultShmId() {
298 return transfer_buffer_
->GetShmId();
301 uint32
GLES2Implementation::GetResultShmOffset() {
302 return transfer_buffer_
->GetResultOffset();
305 void GLES2Implementation::FreeUnusedSharedMemory() {
306 mapped_memory_
->FreeUnused();
309 void GLES2Implementation::FreeEverything() {
311 query_tracker_
->Shrink();
312 FreeUnusedSharedMemory();
313 transfer_buffer_
->Free();
314 helper_
->FreeRingBuffer();
317 void GLES2Implementation::RunIfContextNotLost(const base::Closure
& callback
) {
318 if (!helper_
->IsContextLost())
322 void GLES2Implementation::SignalSyncPoint(uint32 sync_point
,
323 const base::Closure
& callback
) {
324 gpu_control_
->SignalSyncPoint(
326 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
327 weak_ptr_factory_
.GetWeakPtr(),
331 void GLES2Implementation::SignalQuery(uint32 query
,
332 const base::Closure
& callback
) {
333 // Flush previously entered commands to ensure ordering with any
334 // glBeginQueryEXT() calls that may have been put into the context.
335 ShallowFlushCHROMIUM();
336 gpu_control_
->SignalQuery(
338 base::Bind(&GLES2Implementation::RunIfContextNotLost
,
339 weak_ptr_factory_
.GetWeakPtr(),
343 void GLES2Implementation::SetSurfaceVisible(bool visible
) {
344 // TODO(piman): This probably should be ShallowFlushCHROMIUM().
346 surface_visible_
= visible
;
347 gpu_control_
->SetSurfaceVisible(visible
);
352 void GLES2Implementation::SendManagedMemoryStats(
353 const ManagedMemoryStats
& stats
) {
354 gpu_control_
->SendManagedMemoryStats(stats
);
357 void GLES2Implementation::WaitForCmd() {
358 TRACE_EVENT0("gpu", "GLES2::WaitForCmd");
359 helper_
->CommandBufferHelper::Finish();
362 bool GLES2Implementation::IsExtensionAvailable(const char* ext
) {
363 const char* extensions
=
364 reinterpret_cast<const char*>(GetStringHelper(GL_EXTENSIONS
));
368 int length
= strlen(ext
);
370 int n
= strcspn(extensions
, " ");
371 if (n
== length
&& 0 == strncmp(ext
, extensions
, length
)) {
374 if ('\0' == extensions
[n
]) {
381 bool GLES2Implementation::IsExtensionAvailableHelper(
382 const char* extension
, ExtensionStatus
* status
) {
384 case kAvailableExtensionStatus
:
386 case kUnavailableExtensionStatus
:
389 bool available
= IsExtensionAvailable(extension
);
390 *status
= available
? kAvailableExtensionStatus
:
391 kUnavailableExtensionStatus
;
397 bool GLES2Implementation::IsAnglePackReverseRowOrderAvailable() {
398 return IsExtensionAvailableHelper(
399 "GL_ANGLE_pack_reverse_row_order",
400 &angle_pack_reverse_row_order_status_
);
403 bool GLES2Implementation::IsChromiumFramebufferMultisampleAvailable() {
404 return IsExtensionAvailableHelper(
405 "GL_CHROMIUM_framebuffer_multisample",
406 &chromium_framebuffer_multisample_
);
409 const std::string
& GLES2Implementation::GetLogPrefix() const {
410 const std::string
& prefix(debug_marker_manager_
.GetMarker());
411 return prefix
.empty() ? this_in_hex_
: prefix
;
414 GLenum
GLES2Implementation::GetError() {
415 GPU_CLIENT_SINGLE_THREAD_CHECK();
416 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetError()");
417 GLenum err
= GetGLError();
418 GPU_CLIENT_LOG("returned " << GLES2Util::GetStringError(err
));
422 GLenum
GLES2Implementation::GetClientSideGLError() {
423 if (error_bits_
== 0) {
427 GLenum error
= GL_NO_ERROR
;
428 for (uint32 mask
= 1; mask
!= 0; mask
= mask
<< 1) {
429 if ((error_bits_
& mask
) != 0) {
430 error
= GLES2Util::GLErrorBitToGLError(mask
);
434 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
438 GLenum
GLES2Implementation::GetGLError() {
439 TRACE_EVENT0("gpu", "GLES2::GetGLError");
440 // Check the GL error first, then our wrapped error.
441 typedef cmds::GetError::Result Result
;
442 Result
* result
= GetResultAs
<Result
*>();
443 // If we couldn't allocate a result the context is lost.
447 *result
= GL_NO_ERROR
;
448 helper_
->GetError(GetResultShmId(), GetResultShmOffset());
450 GLenum error
= *result
;
451 if (error
== GL_NO_ERROR
) {
452 error
= GetClientSideGLError();
454 // There was an error, clear the corresponding wrapped error.
455 error_bits_
&= ~GLES2Util::GLErrorToErrorBit(error
);
460 #if defined(GL_CLIENT_FAIL_GL_ERRORS)
461 void GLES2Implementation::FailGLError(GLenum error
) {
462 if (error
!= GL_NO_ERROR
) {
463 NOTREACHED() << "Error";
466 // NOTE: Calling GetGLError overwrites data in the result buffer.
467 void GLES2Implementation::CheckGLError() {
468 FailGLError(GetGLError());
470 #endif // defined(GPU_CLIENT_FAIL_GL_ERRORS)
472 void GLES2Implementation::SetGLError(
473 GLenum error
, const char* function_name
, const char* msg
) {
474 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] Client Synthesized Error: "
475 << GLES2Util::GetStringError(error
) << ": "
476 << function_name
<< ": " << msg
);
481 if (error_message_callback_
) {
482 std::string
temp(GLES2Util::GetStringError(error
) + " : " +
483 function_name
+ ": " + (msg
? msg
: ""));
484 error_message_callback_
->OnErrorMessage(temp
.c_str(), 0);
486 error_bits_
|= GLES2Util::GLErrorToErrorBit(error
);
489 void GLES2Implementation::SetGLErrorInvalidEnum(
490 const char* function_name
, GLenum value
, const char* label
) {
491 SetGLError(GL_INVALID_ENUM
, function_name
,
492 (std::string(label
) + " was " +
493 GLES2Util::GetStringEnum(value
)).c_str());
496 bool GLES2Implementation::GetBucketContents(uint32 bucket_id
,
497 std::vector
<int8
>* data
) {
498 TRACE_EVENT0("gpu", "GLES2::GetBucketContents");
500 const uint32 kStartSize
= 32 * 1024;
501 ScopedTransferBufferPtr
buffer(kStartSize
, helper_
, transfer_buffer_
);
502 if (!buffer
.valid()) {
505 typedef cmd::GetBucketStart::Result Result
;
506 Result
* result
= GetResultAs
<Result
*>();
511 helper_
->GetBucketStart(
512 bucket_id
, GetResultShmId(), GetResultShmOffset(),
513 buffer
.size(), buffer
.shm_id(), buffer
.offset());
515 uint32 size
= *result
;
520 if (!buffer
.valid()) {
522 if (!buffer
.valid()) {
525 helper_
->GetBucketData(
526 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
529 uint32 size_to_copy
= std::min(size
, buffer
.size());
530 memcpy(&(*data
)[offset
], buffer
.address(), size_to_copy
);
531 offset
+= size_to_copy
;
532 size
-= size_to_copy
;
535 // Free the bucket. This is not required but it does free up the memory.
536 // and we don't have to wait for the result so from the client's perspective
538 helper_
->SetBucketSize(bucket_id
, 0);
543 void GLES2Implementation::SetBucketContents(
544 uint32 bucket_id
, const void* data
, size_t size
) {
546 helper_
->SetBucketSize(bucket_id
, size
);
550 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
551 if (!buffer
.valid()) {
554 memcpy(buffer
.address(), static_cast<const int8
*>(data
) + offset
,
556 helper_
->SetBucketData(
557 bucket_id
, offset
, buffer
.size(), buffer
.shm_id(), buffer
.offset());
558 offset
+= buffer
.size();
559 size
-= buffer
.size();
564 void GLES2Implementation::SetBucketAsCString(
565 uint32 bucket_id
, const char* str
) {
566 // NOTE: strings are passed NULL terminated. That means the empty
567 // string will have a size of 1 and no-string will have a size of 0
569 SetBucketContents(bucket_id
, str
, strlen(str
) + 1);
571 helper_
->SetBucketSize(bucket_id
, 0);
575 bool GLES2Implementation::GetBucketAsString(
576 uint32 bucket_id
, std::string
* str
) {
578 std::vector
<int8
> data
;
579 // NOTE: strings are passed NULL terminated. That means the empty
580 // string will have a size of 1 and no-string will have a size of 0
581 if (!GetBucketContents(bucket_id
, &data
)) {
587 str
->assign(&data
[0], &data
[0] + data
.size() - 1);
591 void GLES2Implementation::SetBucketAsString(
592 uint32 bucket_id
, const std::string
& str
) {
593 // NOTE: strings are passed NULL terminated. That means the empty
594 // string will have a size of 1 and no-string will have a size of 0
595 SetBucketContents(bucket_id
, str
.c_str(), str
.size() + 1);
598 void GLES2Implementation::Disable(GLenum cap
) {
599 GPU_CLIENT_SINGLE_THREAD_CHECK();
600 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDisable("
601 << GLES2Util::GetStringCapability(cap
) << ")");
602 bool changed
= false;
603 if (!state_
.SetCapabilityState(cap
, false, &changed
) || changed
) {
604 helper_
->Disable(cap
);
609 void GLES2Implementation::Enable(GLenum cap
) {
610 GPU_CLIENT_SINGLE_THREAD_CHECK();
611 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnable("
612 << GLES2Util::GetStringCapability(cap
) << ")");
613 bool changed
= false;
614 if (!state_
.SetCapabilityState(cap
, true, &changed
) || changed
) {
615 helper_
->Enable(cap
);
620 GLboolean
GLES2Implementation::IsEnabled(GLenum cap
) {
621 GPU_CLIENT_SINGLE_THREAD_CHECK();
622 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsEnabled("
623 << GLES2Util::GetStringCapability(cap
) << ")");
625 if (!state_
.GetEnabled(cap
, &state
)) {
626 typedef cmds::IsEnabled::Result Result
;
627 Result
* result
= GetResultAs
<Result
*>();
632 helper_
->IsEnabled(cap
, GetResultShmId(), GetResultShmOffset());
634 state
= (*result
) != 0;
637 GPU_CLIENT_LOG("returned " << state
);
642 bool GLES2Implementation::GetHelper(GLenum pname
, GLint
* params
) {
644 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
:
645 *params
= static_state_
.int_state
.max_combined_texture_image_units
;
647 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
648 *params
= static_state_
.int_state
.max_cube_map_texture_size
;
650 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
651 *params
= static_state_
.int_state
.max_fragment_uniform_vectors
;
653 case GL_MAX_RENDERBUFFER_SIZE
:
654 *params
= static_state_
.int_state
.max_renderbuffer_size
;
656 case GL_MAX_TEXTURE_IMAGE_UNITS
:
657 *params
= static_state_
.int_state
.max_texture_image_units
;
659 case GL_MAX_TEXTURE_SIZE
:
660 *params
= static_state_
.int_state
.max_texture_size
;
662 case GL_MAX_VARYING_VECTORS
:
663 *params
= static_state_
.int_state
.max_varying_vectors
;
665 case GL_MAX_VERTEX_ATTRIBS
:
666 *params
= static_state_
.int_state
.max_vertex_attribs
;
668 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
:
669 *params
= static_state_
.int_state
.max_vertex_texture_image_units
;
671 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
672 *params
= static_state_
.int_state
.max_vertex_uniform_vectors
;
674 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
675 *params
= static_state_
.int_state
.num_compressed_texture_formats
;
677 case GL_NUM_SHADER_BINARY_FORMATS
:
678 *params
= static_state_
.int_state
.num_shader_binary_formats
;
680 case GL_ARRAY_BUFFER_BINDING
:
681 if (share_group_
->bind_generates_resource()) {
682 *params
= bound_array_buffer_id_
;
686 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
687 if (share_group_
->bind_generates_resource()) {
689 vertex_array_object_manager_
->bound_element_array_buffer();
693 case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
694 *params
= bound_pixel_pack_transfer_buffer_id_
;
696 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM
:
697 *params
= bound_pixel_unpack_transfer_buffer_id_
;
699 case GL_ACTIVE_TEXTURE
:
700 *params
= active_texture_unit_
+ GL_TEXTURE0
;
702 case GL_TEXTURE_BINDING_2D
:
703 if (share_group_
->bind_generates_resource()) {
704 *params
= texture_units_
[active_texture_unit_
].bound_texture_2d
;
708 case GL_TEXTURE_BINDING_CUBE_MAP
:
709 if (share_group_
->bind_generates_resource()) {
710 *params
= texture_units_
[active_texture_unit_
].bound_texture_cube_map
;
714 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
715 if (share_group_
->bind_generates_resource()) {
717 texture_units_
[active_texture_unit_
].bound_texture_external_oes
;
721 case GL_FRAMEBUFFER_BINDING
:
722 if (share_group_
->bind_generates_resource()) {
723 *params
= bound_framebuffer_
;
727 case GL_READ_FRAMEBUFFER_BINDING
:
728 if (IsChromiumFramebufferMultisampleAvailable() &&
729 share_group_
->bind_generates_resource()) {
730 *params
= bound_read_framebuffer_
;
734 case GL_RENDERBUFFER_BINDING
:
735 if (share_group_
->bind_generates_resource()) {
736 *params
= bound_renderbuffer_
;
745 bool GLES2Implementation::GetBooleanvHelper(GLenum pname
, GLboolean
* params
) {
746 // TODO(gman): Make this handle pnames that return more than 1 value.
748 if (!GetHelper(pname
, &value
)) {
751 *params
= static_cast<GLboolean
>(value
);
755 bool GLES2Implementation::GetFloatvHelper(GLenum pname
, GLfloat
* params
) {
756 // TODO(gman): Make this handle pnames that return more than 1 value.
758 if (!GetHelper(pname
, &value
)) {
761 *params
= static_cast<GLfloat
>(value
);
765 bool GLES2Implementation::GetIntegervHelper(GLenum pname
, GLint
* params
) {
766 return GetHelper(pname
, params
);
769 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUMHelper(
770 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
771 typedef cmds::GetMaxValueInBufferCHROMIUM::Result Result
;
772 Result
* result
= GetResultAs
<Result
*>();
777 helper_
->GetMaxValueInBufferCHROMIUM(
778 buffer_id
, count
, type
, offset
, GetResultShmId(), GetResultShmOffset());
783 GLuint
GLES2Implementation::GetMaxValueInBufferCHROMIUM(
784 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
785 GPU_CLIENT_SINGLE_THREAD_CHECK();
786 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMaxValueInBufferCHROMIUM("
787 << buffer_id
<< ", " << count
<< ", "
788 << GLES2Util::GetStringGetMaxIndexType(type
)
789 << ", " << offset
<< ")");
790 GLuint result
= GetMaxValueInBufferCHROMIUMHelper(
791 buffer_id
, count
, type
, offset
);
792 GPU_CLIENT_LOG("returned " << result
);
797 void GLES2Implementation::RestoreElementAndArrayBuffers(bool restore
) {
799 RestoreArrayBuffer(restore
);
800 // Restore the element array binding.
801 // We only need to restore it if it wasn't a client side array.
802 if (vertex_array_object_manager_
->bound_element_array_buffer() == 0) {
803 helper_
->BindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
808 void GLES2Implementation::RestoreArrayBuffer(bool restore
) {
810 // Restore the user's current binding.
811 helper_
->BindBuffer(GL_ARRAY_BUFFER
, bound_array_buffer_id_
);
815 void GLES2Implementation::DrawElements(
816 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
) {
817 GPU_CLIENT_SINGLE_THREAD_CHECK();
818 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElements("
819 << GLES2Util::GetStringDrawMode(mode
) << ", "
821 << GLES2Util::GetStringIndexType(type
) << ", "
822 << static_cast<const void*>(indices
) << ")");
824 SetGLError(GL_INVALID_VALUE
, "glDrawElements", "count less than 0.");
831 bool simulated
= false;
832 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
833 "glDrawElements", this, helper_
, count
, type
, 0, indices
,
834 &offset
, &simulated
)) {
837 helper_
->DrawElements(mode
, count
, type
, offset
);
838 RestoreElementAndArrayBuffers(simulated
);
842 void GLES2Implementation::Flush() {
843 GPU_CLIENT_SINGLE_THREAD_CHECK();
844 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFlush()");
845 // Insert the cmd to call glFlush
847 // Flush our command buffer
848 // (tell the service to execute up to the flush cmd.)
849 helper_
->CommandBufferHelper::Flush();
850 if (!surface_visible_
&& free_everything_when_invisible_
)
854 void GLES2Implementation::ShallowFlushCHROMIUM() {
855 GPU_CLIENT_SINGLE_THREAD_CHECK();
856 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShallowFlushCHROMIUM()");
857 // Flush our command buffer
858 // (tell the service to execute up to the flush cmd.)
859 helper_
->CommandBufferHelper::Flush();
860 // TODO(piman): Add the FreeEverything() logic here.
863 void GLES2Implementation::Finish() {
864 GPU_CLIENT_SINGLE_THREAD_CHECK();
866 if (!surface_visible_
&& free_everything_when_invisible_
)
870 void GLES2Implementation::ShallowFinishCHROMIUM() {
871 GPU_CLIENT_SINGLE_THREAD_CHECK();
872 // Flush our command buffer (tell the service to execute up to the flush cmd
873 // and don't return until it completes).
874 helper_
->CommandBufferHelper::Finish();
877 bool GLES2Implementation::MustBeContextLost() {
878 bool context_lost
= helper_
->IsContextLost();
881 context_lost
= helper_
->IsContextLost();
887 void GLES2Implementation::FinishHelper() {
888 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFinish()");
889 TRACE_EVENT0("gpu", "GLES2::Finish");
890 // Insert the cmd to call glFinish
892 // Finish our command buffer
893 // (tell the service to execute up to the Finish cmd and wait for it to
895 helper_
->CommandBufferHelper::Finish();
898 void GLES2Implementation::SwapBuffers() {
899 GPU_CLIENT_SINGLE_THREAD_CHECK();
900 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSwapBuffers()");
901 // TODO(piman): Strictly speaking we'd want to insert the token after the
902 // swap, but the state update with the updated token might not have happened
903 // by the time the SwapBuffer callback gets called, forcing us to synchronize
904 // with the GPU process more than needed. So instead, make it happen before.
905 // All it means is that we could be slightly looser on the kMaxSwapBuffers
906 // semantics if the client doesn't use the callback mechanism, and by chance
907 // the scheduler yields between the InsertToken and the SwapBuffers.
908 swap_buffers_tokens_
.push(helper_
->InsertToken());
909 helper_
->SwapBuffers();
910 helper_
->CommandBufferHelper::Flush();
911 // Wait if we added too many swap buffers. Add 1 to kMaxSwapBuffers to
912 // compensate for TODO above.
913 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
914 helper_
->WaitForToken(swap_buffers_tokens_
.front());
915 swap_buffers_tokens_
.pop();
919 void GLES2Implementation::GenSharedIdsCHROMIUM(
920 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
921 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSharedIdsCHROMIUM("
922 << namespace_id
<< ", " << id_offset
<< ", " << n
<< ", " <<
923 static_cast<void*>(ids
) << ")");
924 TRACE_EVENT0("gpu", "GLES2::GenSharedIdsCHROMIUM");
928 ScopedTransferBufferArray
<GLint
> id_buffer(num
, helper_
, transfer_buffer_
);
929 if (!id_buffer
.valid()) {
932 helper_
->GenSharedIdsCHROMIUM(
933 namespace_id
, id_offset
, id_buffer
.num_elements(),
934 id_buffer
.shm_id(), id_buffer
.offset());
936 memcpy(dst
, id_buffer
.address(), sizeof(*dst
) * id_buffer
.num_elements());
937 num
-= id_buffer
.num_elements();
938 dst
+= id_buffer
.num_elements();
940 GPU_CLIENT_LOG_CODE_BLOCK({
941 for (GLsizei i
= 0; i
< n
; ++i
) {
942 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
947 void GLES2Implementation::DeleteSharedIdsCHROMIUM(
948 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
949 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSharedIdsCHROMIUM("
950 << namespace_id
<< ", " << n
<< ", "
951 << static_cast<const void*>(ids
) << ")");
952 GPU_CLIENT_LOG_CODE_BLOCK({
953 for (GLsizei i
= 0; i
< n
; ++i
) {
954 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
957 TRACE_EVENT0("gpu", "GLES2::DeleteSharedIdsCHROMIUM");
959 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
960 if (!id_buffer
.valid()) {
963 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
964 helper_
->DeleteSharedIdsCHROMIUM(
965 namespace_id
, id_buffer
.num_elements(),
966 id_buffer
.shm_id(), id_buffer
.offset());
968 n
-= id_buffer
.num_elements();
969 ids
+= id_buffer
.num_elements();
973 void GLES2Implementation::RegisterSharedIdsCHROMIUM(
974 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
975 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRegisterSharedIdsCHROMIUM("
976 << namespace_id
<< ", " << n
<< ", "
977 << static_cast<const void*>(ids
) << ")");
978 GPU_CLIENT_LOG_CODE_BLOCK({
979 for (GLsizei i
= 0; i
< n
; ++i
) {
980 GPU_CLIENT_LOG(" " << i
<< ": " << namespace_id
<< ", " << ids
[i
]);
983 TRACE_EVENT0("gpu", "GLES2::RegisterSharedIdsCHROMIUM");
985 ScopedTransferBufferArray
<GLint
> id_buffer(n
, helper_
, transfer_buffer_
);
986 if (!id_buffer
.valid()) {
989 memcpy(id_buffer
.address(), ids
, sizeof(*ids
) * id_buffer
.num_elements());
990 helper_
->RegisterSharedIdsCHROMIUM(
991 namespace_id
, id_buffer
.num_elements(),
992 id_buffer
.shm_id(), id_buffer
.offset());
994 n
-= id_buffer
.num_elements();
995 ids
+= id_buffer
.num_elements();
999 void GLES2Implementation::BindAttribLocation(
1000 GLuint program
, GLuint index
, const char* name
) {
1001 GPU_CLIENT_SINGLE_THREAD_CHECK();
1002 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindAttribLocation("
1003 << program
<< ", " << index
<< ", " << name
<< ")");
1004 SetBucketAsString(kResultBucketId
, name
);
1005 helper_
->BindAttribLocationBucket(program
, index
, kResultBucketId
);
1006 helper_
->SetBucketSize(kResultBucketId
, 0);
1010 void GLES2Implementation::BindUniformLocationCHROMIUM(
1011 GLuint program
, GLint location
, const char* name
) {
1012 GPU_CLIENT_SINGLE_THREAD_CHECK();
1013 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindUniformLocationCHROMIUM("
1014 << program
<< ", " << location
<< ", " << name
<< ")");
1015 SetBucketAsString(kResultBucketId
, name
);
1016 helper_
->BindUniformLocationCHROMIUMBucket(
1017 program
, location
, kResultBucketId
);
1018 helper_
->SetBucketSize(kResultBucketId
, 0);
1022 void GLES2Implementation::GetVertexAttribPointerv(
1023 GLuint index
, GLenum pname
, void** ptr
) {
1024 GPU_CLIENT_SINGLE_THREAD_CHECK();
1025 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribPointer("
1026 << index
<< ", " << GLES2Util::GetStringVertexPointer(pname
) << ", "
1027 << static_cast<void*>(ptr
) << ")");
1028 GPU_CLIENT_LOG_CODE_BLOCK(int32 num_results
= 1);
1029 if (!vertex_array_object_manager_
->GetAttribPointer(index
, pname
, ptr
)) {
1030 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribPointerv");
1031 typedef cmds::GetVertexAttribPointerv::Result Result
;
1032 Result
* result
= GetResultAs
<Result
*>();
1036 result
->SetNumResults(0);
1037 helper_
->GetVertexAttribPointerv(
1038 index
, pname
, GetResultShmId(), GetResultShmOffset());
1040 result
->CopyResult(ptr
);
1041 GPU_CLIENT_LOG_CODE_BLOCK(num_results
= result
->GetNumResults());
1043 GPU_CLIENT_LOG_CODE_BLOCK({
1044 for (int32 i
= 0; i
< num_results
; ++i
) {
1045 GPU_CLIENT_LOG(" " << i
<< ": " << ptr
[i
]);
1051 bool GLES2Implementation::DeleteProgramHelper(GLuint program
) {
1052 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1053 this, 1, &program
, &GLES2Implementation::DeleteProgramStub
)) {
1056 "glDeleteProgram", "id not created by this context.");
1059 if (program
== current_program_
) {
1060 current_program_
= 0;
1065 void GLES2Implementation::DeleteProgramStub(
1066 GLsizei n
, const GLuint
* programs
) {
1068 share_group_
->program_info_manager()->DeleteInfo(programs
[0]);
1069 helper_
->DeleteProgram(programs
[0]);
1072 bool GLES2Implementation::DeleteShaderHelper(GLuint shader
) {
1073 if (!GetIdHandler(id_namespaces::kProgramsAndShaders
)->FreeIds(
1074 this, 1, &shader
, &GLES2Implementation::DeleteShaderStub
)) {
1077 "glDeleteShader", "id not created by this context.");
1083 void GLES2Implementation::DeleteShaderStub(
1084 GLsizei n
, const GLuint
* shaders
) {
1086 share_group_
->program_info_manager()->DeleteInfo(shaders
[0]);
1087 helper_
->DeleteShader(shaders
[0]);
1091 GLint
GLES2Implementation::GetAttribLocationHelper(
1092 GLuint program
, const char* name
) {
1093 typedef cmds::GetAttribLocationBucket::Result Result
;
1094 Result
* result
= GetResultAs
<Result
*>();
1099 SetBucketAsCString(kResultBucketId
, name
);
1100 helper_
->GetAttribLocationBucket(
1101 program
, kResultBucketId
, GetResultShmId(), GetResultShmOffset());
1103 helper_
->SetBucketSize(kResultBucketId
, 0);
1107 GLint
GLES2Implementation::GetAttribLocation(
1108 GLuint program
, const char* name
) {
1109 GPU_CLIENT_SINGLE_THREAD_CHECK();
1110 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttribLocation(" << program
1111 << ", " << name
<< ")");
1112 TRACE_EVENT0("gpu", "GLES2::GetAttribLocation");
1113 GLint loc
= share_group_
->program_info_manager()->GetAttribLocation(
1114 this, program
, name
);
1115 GPU_CLIENT_LOG("returned " << loc
);
1120 GLint
GLES2Implementation::GetUniformLocationHelper(
1121 GLuint program
, const char* name
) {
1122 typedef cmds::GetUniformLocationBucket::Result Result
;
1123 Result
* result
= GetResultAs
<Result
*>();
1128 SetBucketAsCString(kResultBucketId
, name
);
1129 helper_
->GetUniformLocationBucket(program
, kResultBucketId
,
1130 GetResultShmId(), GetResultShmOffset());
1132 helper_
->SetBucketSize(kResultBucketId
, 0);
1136 GLint
GLES2Implementation::GetUniformLocation(
1137 GLuint program
, const char* name
) {
1138 GPU_CLIENT_SINGLE_THREAD_CHECK();
1139 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformLocation(" << program
1140 << ", " << name
<< ")");
1141 TRACE_EVENT0("gpu", "GLES2::GetUniformLocation");
1142 GLint loc
= share_group_
->program_info_manager()->GetUniformLocation(
1143 this, program
, name
);
1144 GPU_CLIENT_LOG("returned " << loc
);
1149 void GLES2Implementation::UseProgram(GLuint program
) {
1150 GPU_CLIENT_SINGLE_THREAD_CHECK();
1151 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program
<< ")");
1152 if (current_program_
!= program
) {
1153 current_program_
= program
;
1154 helper_
->UseProgram(program
);
1159 bool GLES2Implementation::GetProgramivHelper(
1160 GLuint program
, GLenum pname
, GLint
* params
) {
1161 bool got_value
= share_group_
->program_info_manager()->GetProgramiv(
1162 this, program
, pname
, params
);
1163 GPU_CLIENT_LOG_CODE_BLOCK({
1165 GPU_CLIENT_LOG(" 0: " << *params
);
1171 void GLES2Implementation::LinkProgram(GLuint program
) {
1172 GPU_CLIENT_SINGLE_THREAD_CHECK();
1173 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program
<< ")");
1174 helper_
->LinkProgram(program
);
1175 share_group_
->program_info_manager()->CreateInfo(program
);
1179 void GLES2Implementation::ShaderBinary(
1180 GLsizei n
, const GLuint
* shaders
, GLenum binaryformat
, const void* binary
,
1182 GPU_CLIENT_SINGLE_THREAD_CHECK();
1183 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderBinary(" << n
<< ", "
1184 << static_cast<const void*>(shaders
) << ", "
1185 << GLES2Util::GetStringEnum(binaryformat
) << ", "
1186 << static_cast<const void*>(binary
) << ", "
1189 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "n < 0.");
1193 SetGLError(GL_INVALID_VALUE
, "glShaderBinary", "length < 0.");
1196 // TODO(gman): ShaderBinary should use buckets.
1197 unsigned int shader_id_size
= n
* sizeof(*shaders
);
1198 ScopedTransferBufferArray
<GLint
> buffer(
1199 shader_id_size
+ length
, helper_
, transfer_buffer_
);
1200 if (!buffer
.valid() || buffer
.num_elements() != shader_id_size
+ length
) {
1201 SetGLError(GL_OUT_OF_MEMORY
, "glShaderBinary", "out of memory.");
1204 void* shader_ids
= buffer
.elements();
1205 void* shader_data
= buffer
.elements() + shader_id_size
;
1206 memcpy(shader_ids
, shaders
, shader_id_size
);
1207 memcpy(shader_data
, binary
, length
);
1208 helper_
->ShaderBinary(
1214 buffer
.offset() + shader_id_size
,
1219 void GLES2Implementation::PixelStorei(GLenum pname
, GLint param
) {
1220 GPU_CLIENT_SINGLE_THREAD_CHECK();
1221 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPixelStorei("
1222 << GLES2Util::GetStringPixelStore(pname
) << ", "
1225 case GL_PACK_ALIGNMENT
:
1226 pack_alignment_
= param
;
1228 case GL_UNPACK_ALIGNMENT
:
1229 unpack_alignment_
= param
;
1231 case GL_UNPACK_ROW_LENGTH_EXT
:
1232 unpack_row_length_
= param
;
1234 case GL_UNPACK_SKIP_ROWS_EXT
:
1235 unpack_skip_rows_
= param
;
1237 case GL_UNPACK_SKIP_PIXELS_EXT
:
1238 unpack_skip_pixels_
= param
;
1240 case GL_UNPACK_FLIP_Y_CHROMIUM
:
1241 unpack_flip_y_
= (param
!= 0);
1243 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
1244 pack_reverse_row_order_
=
1245 IsAnglePackReverseRowOrderAvailable() ? (param
!= 0) : false;
1250 helper_
->PixelStorei(pname
, param
);
1255 void GLES2Implementation::VertexAttribPointer(
1256 GLuint index
, GLint size
, GLenum type
, GLboolean normalized
, GLsizei stride
,
1258 GPU_CLIENT_SINGLE_THREAD_CHECK();
1259 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer("
1262 << GLES2Util::GetStringVertexAttribType(type
) << ", "
1263 << GLES2Util::GetStringBool(normalized
) << ", "
1265 << static_cast<const void*>(ptr
) << ")");
1266 // Record the info on the client side.
1267 if (!vertex_array_object_manager_
->SetAttribPointer(
1268 bound_array_buffer_id_
, index
, size
, type
, normalized
, stride
, ptr
)) {
1269 SetGLError(GL_INVALID_OPERATION
, "glVertexAttribPointer",
1270 "client side arrays are not allowed in vertex array objects.");
1273 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1274 if (bound_array_buffer_id_
!= 0) {
1275 // Only report NON client side buffers to the service.
1276 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1279 #else // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1280 helper_
->VertexAttribPointer(index
, size
, type
, normalized
, stride
,
1282 #endif // !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1286 void GLES2Implementation::VertexAttribDivisorANGLE(
1287 GLuint index
, GLuint divisor
) {
1288 GPU_CLIENT_SINGLE_THREAD_CHECK();
1289 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribDivisorANGLE("
1291 << divisor
<< ") ");
1292 // Record the info on the client side.
1293 vertex_array_object_manager_
->SetAttribDivisor(index
, divisor
);
1294 helper_
->VertexAttribDivisorANGLE(index
, divisor
);
1298 void GLES2Implementation::ShaderSource(
1299 GLuint shader
, GLsizei count
, const GLchar
* const* source
, const GLint
* length
) {
1300 GPU_CLIENT_SINGLE_THREAD_CHECK();
1301 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glShaderSource("
1302 << shader
<< ", " << count
<< ", "
1303 << static_cast<const void*>(source
) << ", "
1304 << static_cast<const void*>(length
) << ")");
1305 GPU_CLIENT_LOG_CODE_BLOCK({
1306 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1308 if (length
&& length
[ii
] >= 0) {
1309 std::string
str(source
[ii
], length
[ii
]);
1310 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << str
<< "\n---");
1312 GPU_CLIENT_LOG(" " << ii
<< ": ---\n" << source
[ii
] << "\n---");
1315 GPU_CLIENT_LOG(" " << ii
<< ": NULL");
1320 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "count < 0");
1324 SetGLError(GL_INVALID_VALUE
, "glShaderSource", "shader == 0");
1328 // Compute the total size.
1329 uint32 total_size
= 1;
1330 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
1332 total_size
+= (length
&& length
[ii
] >= 0) ?
1333 static_cast<size_t>(length
[ii
]) : strlen(source
[ii
]);
1337 // Concatenate all the strings in to a bucket on the service.
1338 helper_
->SetBucketSize(kResultBucketId
, total_size
);
1340 for (GLsizei ii
= 0; ii
<= count
; ++ii
) {
1341 const char* src
= ii
< count
? source
[ii
] : "";
1343 uint32 size
= ii
< count
?
1344 (length
? static_cast<size_t>(length
[ii
]) : strlen(src
)) : 1;
1346 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1347 if (!buffer
.valid()) {
1350 memcpy(buffer
.address(), src
, buffer
.size());
1351 helper_
->SetBucketData(kResultBucketId
, offset
, buffer
.size(),
1352 buffer
.shm_id(), buffer
.offset());
1353 offset
+= buffer
.size();
1354 src
+= buffer
.size();
1355 size
-= buffer
.size();
1360 DCHECK_EQ(total_size
, offset
);
1362 helper_
->ShaderSourceBucket(shader
, kResultBucketId
);
1363 helper_
->SetBucketSize(kResultBucketId
, 0);
1367 void GLES2Implementation::BufferDataHelper(
1368 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1370 SetGLError(GL_INVALID_VALUE
, "glBufferData", "size < 0");
1375 if (GetBoundPixelTransferBuffer(target
, "glBufferData", &buffer_id
)) {
1380 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1382 // Free buffer memory, pending the passage of a token.
1383 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
1385 // Remove old buffer.
1386 buffer_tracker_
->RemoveBuffer(buffer_id
);
1389 // Create new buffer.
1390 buffer
= buffer_tracker_
->CreateBuffer(buffer_id
, size
);
1392 if (buffer
->address() && data
)
1393 memcpy(buffer
->address(), data
, size
);
1401 // If there is no data just send BufferData
1403 helper_
->BufferData(target
, size
, 0, 0, usage
);
1407 // See if we can send all at once.
1408 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1409 if (!buffer
.valid()) {
1413 if (buffer
.size() >= static_cast<unsigned int>(size
)) {
1414 memcpy(buffer
.address(), data
, size
);
1415 helper_
->BufferData(
1424 // Make the buffer with BufferData then send via BufferSubData
1425 helper_
->BufferData(target
, size
, 0, 0, usage
);
1426 BufferSubDataHelperImpl(target
, 0, size
, data
, &buffer
);
1430 void GLES2Implementation::BufferData(
1431 GLenum target
, GLsizeiptr size
, const void* data
, GLenum usage
) {
1432 GPU_CLIENT_SINGLE_THREAD_CHECK();
1433 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferData("
1434 << GLES2Util::GetStringBufferTarget(target
) << ", "
1436 << static_cast<const void*>(data
) << ", "
1437 << GLES2Util::GetStringBufferUsage(usage
) << ")");
1438 BufferDataHelper(target
, size
, data
, usage
);
1442 void GLES2Implementation::BufferSubDataHelper(
1443 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1449 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "size < 0");
1454 if (GetBoundPixelTransferBuffer(target
, "glBufferSubData", &buffer_id
)) {
1458 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1460 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
1465 int32 buffer_size
= buffer
->size();
1466 if (!SafeAddInt32(offset
, size
, &end
) || end
> buffer_size
) {
1467 SetGLError(GL_INVALID_VALUE
, "glBufferSubData", "out of range");
1471 if (buffer
->address() && data
)
1472 memcpy(static_cast<uint8
*>(buffer
->address()) + offset
, data
, size
);
1476 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1477 BufferSubDataHelperImpl(target
, offset
, size
, data
, &buffer
);
1480 void GLES2Implementation::BufferSubDataHelperImpl(
1481 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
,
1482 ScopedTransferBufferPtr
* buffer
) {
1486 const int8
* source
= static_cast<const int8
*>(data
);
1488 if (!buffer
->valid() || buffer
->size() == 0) {
1489 buffer
->Reset(size
);
1490 if (!buffer
->valid()) {
1494 memcpy(buffer
->address(), source
, buffer
->size());
1495 helper_
->BufferSubData(
1496 target
, offset
, buffer
->size(), buffer
->shm_id(), buffer
->offset());
1497 offset
+= buffer
->size();
1498 source
+= buffer
->size();
1499 size
-= buffer
->size();
1504 void GLES2Implementation::BufferSubData(
1505 GLenum target
, GLintptr offset
, GLsizeiptr size
, const void* data
) {
1506 GPU_CLIENT_SINGLE_THREAD_CHECK();
1507 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1508 << GLES2Util::GetStringBufferTarget(target
) << ", "
1509 << offset
<< ", " << size
<< ", "
1510 << static_cast<const void*>(data
) << ")");
1511 BufferSubDataHelper(target
, offset
, size
, data
);
1515 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1517 const char* function_name
,
1518 GLuint
* buffer_id
) {
1522 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
1523 *buffer_id
= bound_pixel_pack_transfer_buffer_id_
;
1525 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
1526 *buffer_id
= bound_pixel_unpack_transfer_buffer_id_
;
1533 SetGLError(GL_INVALID_OPERATION
, function_name
, "no buffer bound");
1538 BufferTracker::Buffer
*
1539 GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
1541 const char* function_name
,
1542 GLuint offset
, GLsizei size
)
1545 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
1547 SetGLError(GL_INVALID_OPERATION
, function_name
, "invalid buffer");
1550 if (buffer
->mapped()) {
1551 SetGLError(GL_INVALID_OPERATION
, function_name
, "buffer mapped");
1554 if ((buffer
->size() - offset
) < static_cast<GLuint
>(size
)) {
1555 SetGLError(GL_INVALID_VALUE
, function_name
, "unpack size to large");
1561 void GLES2Implementation::CompressedTexImage2D(
1562 GLenum target
, GLint level
, GLenum internalformat
, GLsizei width
,
1563 GLsizei height
, GLint border
, GLsizei image_size
, const void* data
) {
1564 GPU_CLIENT_SINGLE_THREAD_CHECK();
1565 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexImage2D("
1566 << GLES2Util::GetStringTextureTarget(target
) << ", "
1568 << GLES2Util::GetStringCompressedTextureFormat(internalformat
) << ", "
1569 << width
<< ", " << height
<< ", " << border
<< ", "
1570 << image_size
<< ", "
1571 << static_cast<const void*>(data
) << ")");
1572 if (width
< 0 || height
< 0 || level
< 0) {
1573 SetGLError(GL_INVALID_VALUE
, "glCompressedTexImage2D", "dimension < 0");
1576 if (height
== 0 || width
== 0) {
1579 // If there's a pixel unpack buffer bound use it when issuing
1580 // CompressedTexImage2D.
1581 if (bound_pixel_unpack_transfer_buffer_id_
) {
1582 GLuint offset
= ToGLuint(data
);
1583 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1584 bound_pixel_unpack_transfer_buffer_id_
,
1585 "glCompressedTexImage2D", offset
, image_size
);
1586 if (buffer
&& buffer
->shm_id() != -1) {
1587 helper_
->CompressedTexImage2D(
1588 target
, level
, internalformat
, width
, height
, border
, image_size
,
1589 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1590 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1594 SetBucketContents(kResultBucketId
, data
, image_size
);
1595 helper_
->CompressedTexImage2DBucket(
1596 target
, level
, internalformat
, width
, height
, border
, kResultBucketId
);
1597 // Free the bucket. This is not required but it does free up the memory.
1598 // and we don't have to wait for the result so from the client's perspective
1600 helper_
->SetBucketSize(kResultBucketId
, 0);
1604 void GLES2Implementation::CompressedTexSubImage2D(
1605 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1606 GLsizei height
, GLenum format
, GLsizei image_size
, const void* data
) {
1607 GPU_CLIENT_SINGLE_THREAD_CHECK();
1608 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCompressedTexSubImage2D("
1609 << GLES2Util::GetStringTextureTarget(target
) << ", "
1611 << xoffset
<< ", " << yoffset
<< ", "
1612 << width
<< ", " << height
<< ", "
1613 << GLES2Util::GetStringCompressedTextureFormat(format
) << ", "
1614 << image_size
<< ", "
1615 << static_cast<const void*>(data
) << ")");
1616 if (width
< 0 || height
< 0 || level
< 0) {
1617 SetGLError(GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "dimension < 0");
1620 // If there's a pixel unpack buffer bound use it when issuing
1621 // CompressedTexSubImage2D.
1622 if (bound_pixel_unpack_transfer_buffer_id_
) {
1623 GLuint offset
= ToGLuint(data
);
1624 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1625 bound_pixel_unpack_transfer_buffer_id_
,
1626 "glCompressedTexSubImage2D", offset
, image_size
);
1627 if (buffer
&& buffer
->shm_id() != -1) {
1628 helper_
->CompressedTexSubImage2D(
1629 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
,
1630 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1631 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1636 SetBucketContents(kResultBucketId
, data
, image_size
);
1637 helper_
->CompressedTexSubImage2DBucket(
1638 target
, level
, xoffset
, yoffset
, width
, height
, format
, kResultBucketId
);
1639 // Free the bucket. This is not required but it does free up the memory.
1640 // and we don't have to wait for the result so from the client's perspective
1642 helper_
->SetBucketSize(kResultBucketId
, 0);
1648 void CopyRectToBuffer(
1651 uint32 unpadded_row_size
,
1652 uint32 pixels_padded_row_size
,
1655 uint32 buffer_padded_row_size
) {
1656 const int8
* source
= static_cast<const int8
*>(pixels
);
1657 int8
* dest
= static_cast<int8
*>(buffer
);
1658 if (flip_y
|| pixels_padded_row_size
!= buffer_padded_row_size
) {
1660 dest
+= buffer_padded_row_size
* (height
- 1);
1662 // the last row is copied unpadded at the end
1663 for (; height
> 1; --height
) {
1664 memcpy(dest
, source
, buffer_padded_row_size
);
1666 dest
-= buffer_padded_row_size
;
1668 dest
+= buffer_padded_row_size
;
1670 source
+= pixels_padded_row_size
;
1672 memcpy(dest
, source
, unpadded_row_size
);
1674 uint32 size
= (height
- 1) * pixels_padded_row_size
+ unpadded_row_size
;
1675 memcpy(dest
, source
, size
);
1679 } // anonymous namespace
1681 void GLES2Implementation::TexImage2D(
1682 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
1683 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
1684 const void* pixels
) {
1685 GPU_CLIENT_SINGLE_THREAD_CHECK();
1686 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
1687 << GLES2Util::GetStringTextureTarget(target
) << ", "
1689 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
1690 << width
<< ", " << height
<< ", " << border
<< ", "
1691 << GLES2Util::GetStringTextureFormat(format
) << ", "
1692 << GLES2Util::GetStringPixelType(type
) << ", "
1693 << static_cast<const void*>(pixels
) << ")");
1694 if (level
< 0 || height
< 0 || width
< 0) {
1695 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
1699 uint32 unpadded_row_size
;
1700 uint32 padded_row_size
;
1701 if (!GLES2Util::ComputeImageDataSizes(
1702 width
, height
, format
, type
, unpack_alignment_
, &size
,
1703 &unpadded_row_size
, &padded_row_size
)) {
1704 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
1708 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
1709 if (bound_pixel_unpack_transfer_buffer_id_
) {
1710 GLuint offset
= ToGLuint(pixels
);
1711 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1712 bound_pixel_unpack_transfer_buffer_id_
,
1713 "glTexImage2D", offset
, size
);
1714 if (buffer
&& buffer
->shm_id() != -1) {
1715 helper_
->TexImage2D(
1716 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1717 buffer
->shm_id(), buffer
->shm_offset() + offset
);
1718 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1724 // If there's no data just issue TexImage2D
1726 helper_
->TexImage2D(
1727 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1733 // compute the advance bytes per row for the src pixels
1734 uint32 src_padded_row_size
;
1735 if (unpack_row_length_
> 0) {
1736 if (!GLES2Util::ComputeImagePaddedRowSize(
1737 unpack_row_length_
, format
, type
, unpack_alignment_
,
1738 &src_padded_row_size
)) {
1740 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1744 src_padded_row_size
= padded_row_size
;
1747 // advance pixels pointer past the skip rows and skip pixels
1748 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1749 unpack_skip_rows_
* src_padded_row_size
;
1750 if (unpack_skip_pixels_
) {
1751 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1752 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1753 unpack_skip_pixels_
* group_size
;
1756 // Check if we can send it all at once.
1757 ScopedTransferBufferPtr
buffer(size
, helper_
, transfer_buffer_
);
1758 if (!buffer
.valid()) {
1762 if (buffer
.size() >= size
) {
1764 pixels
, height
, unpadded_row_size
, src_padded_row_size
, unpack_flip_y_
,
1765 buffer
.address(), padded_row_size
);
1766 helper_
->TexImage2D(
1767 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1768 buffer
.shm_id(), buffer
.offset());
1773 // No, so send it using TexSubImage2D.
1774 helper_
->TexImage2D(
1775 target
, level
, internalformat
, width
, height
, border
, format
, type
,
1778 target
, level
, 0, 0, width
, height
, format
, type
, unpadded_row_size
,
1779 pixels
, src_padded_row_size
, GL_TRUE
, &buffer
, padded_row_size
);
1783 void GLES2Implementation::TexSubImage2D(
1784 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1785 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
1786 GPU_CLIENT_SINGLE_THREAD_CHECK();
1787 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage2D("
1788 << GLES2Util::GetStringTextureTarget(target
) << ", "
1790 << xoffset
<< ", " << yoffset
<< ", "
1791 << width
<< ", " << height
<< ", "
1792 << GLES2Util::GetStringTextureFormat(format
) << ", "
1793 << GLES2Util::GetStringPixelType(type
) << ", "
1794 << static_cast<const void*>(pixels
) << ")");
1796 if (level
< 0 || height
< 0 || width
< 0) {
1797 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "dimension < 0");
1800 if (height
== 0 || width
== 0) {
1805 uint32 unpadded_row_size
;
1806 uint32 padded_row_size
;
1807 if (!GLES2Util::ComputeImageDataSizes(
1808 width
, height
, format
, type
, unpack_alignment_
, &temp_size
,
1809 &unpadded_row_size
, &padded_row_size
)) {
1810 SetGLError(GL_INVALID_VALUE
, "glTexSubImage2D", "size to large");
1814 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
1815 if (bound_pixel_unpack_transfer_buffer_id_
) {
1816 GLuint offset
= ToGLuint(pixels
);
1817 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
1818 bound_pixel_unpack_transfer_buffer_id_
,
1819 "glTexSubImage2D", offset
, temp_size
);
1820 if (buffer
&& buffer
->shm_id() != -1) {
1821 helper_
->TexSubImage2D(
1822 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1823 buffer
->shm_id(), buffer
->shm_offset() + offset
, false);
1824 buffer
->set_transfer_ready_token(helper_
->InsertToken());
1830 // compute the advance bytes per row for the src pixels
1831 uint32 src_padded_row_size
;
1832 if (unpack_row_length_
> 0) {
1833 if (!GLES2Util::ComputeImagePaddedRowSize(
1834 unpack_row_length_
, format
, type
, unpack_alignment_
,
1835 &src_padded_row_size
)) {
1837 GL_INVALID_VALUE
, "glTexImage2D", "unpack row length too large");
1841 src_padded_row_size
= padded_row_size
;
1844 // advance pixels pointer past the skip rows and skip pixels
1845 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1846 unpack_skip_rows_
* src_padded_row_size
;
1847 if (unpack_skip_pixels_
) {
1848 uint32 group_size
= GLES2Util::ComputeImageGroupSize(format
, type
);
1849 pixels
= reinterpret_cast<const int8
*>(pixels
) +
1850 unpack_skip_pixels_
* group_size
;
1853 ScopedTransferBufferPtr
buffer(temp_size
, helper_
, transfer_buffer_
);
1855 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
1856 unpadded_row_size
, pixels
, src_padded_row_size
, GL_FALSE
, &buffer
,
1861 static GLint
ComputeNumRowsThatFitInBuffer(
1862 GLsizeiptr padded_row_size
, GLsizeiptr unpadded_row_size
,
1863 unsigned int size
) {
1864 DCHECK_GE(unpadded_row_size
, 0);
1865 if (padded_row_size
== 0) {
1868 GLint num_rows
= size
/ padded_row_size
;
1869 return num_rows
+ (size
- num_rows
* padded_row_size
) / unpadded_row_size
;
1872 void GLES2Implementation::TexSubImage2DImpl(
1873 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
1874 GLsizei height
, GLenum format
, GLenum type
, uint32 unpadded_row_size
,
1875 const void* pixels
, uint32 pixels_padded_row_size
, GLboolean internal
,
1876 ScopedTransferBufferPtr
* buffer
, uint32 buffer_padded_row_size
) {
1878 DCHECK_GE(level
, 0);
1879 DCHECK_GT(height
, 0);
1880 DCHECK_GT(width
, 0);
1882 const int8
* source
= reinterpret_cast<const int8
*>(pixels
);
1883 GLint original_yoffset
= yoffset
;
1884 // Transfer by rows.
1886 unsigned int desired_size
=
1887 buffer_padded_row_size
* (height
- 1) + unpadded_row_size
;
1888 if (!buffer
->valid() || buffer
->size() == 0) {
1889 buffer
->Reset(desired_size
);
1890 if (!buffer
->valid()) {
1895 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
1896 buffer_padded_row_size
, unpadded_row_size
, buffer
->size());
1897 num_rows
= std::min(num_rows
, height
);
1899 source
, num_rows
, unpadded_row_size
, pixels_padded_row_size
,
1900 unpack_flip_y_
, buffer
->address(), buffer_padded_row_size
);
1901 GLint y
= unpack_flip_y_
? original_yoffset
+ height
- num_rows
: yoffset
;
1902 helper_
->TexSubImage2D(
1903 target
, level
, xoffset
, y
, width
, num_rows
, format
, type
,
1904 buffer
->shm_id(), buffer
->offset(), internal
);
1906 yoffset
+= num_rows
;
1907 source
+= num_rows
* pixels_padded_row_size
;
1912 bool GLES2Implementation::GetActiveAttribHelper(
1913 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1914 GLenum
* type
, char* name
) {
1915 // Clear the bucket so if the command fails nothing will be in it.
1916 helper_
->SetBucketSize(kResultBucketId
, 0);
1917 typedef cmds::GetActiveAttrib::Result Result
;
1918 Result
* result
= GetResultAs
<Result
*>();
1922 // Set as failed so if the command fails we'll recover.
1923 result
->success
= false;
1924 helper_
->GetActiveAttrib(program
, index
, kResultBucketId
,
1925 GetResultShmId(), GetResultShmOffset());
1927 if (result
->success
) {
1929 *size
= result
->size
;
1932 *type
= result
->type
;
1934 if (length
|| name
) {
1935 std::vector
<int8
> str
;
1936 GetBucketContents(kResultBucketId
, &str
);
1937 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
1938 std::max(static_cast<size_t>(0),
1943 if (name
&& bufsize
> 0) {
1944 memcpy(name
, &str
[0], max_size
);
1945 name
[max_size
] = '\0';
1949 return result
->success
!= 0;
1952 void GLES2Implementation::GetActiveAttrib(
1953 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1954 GLenum
* type
, char* name
) {
1955 GPU_CLIENT_SINGLE_THREAD_CHECK();
1956 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveAttrib("
1957 << program
<< ", " << index
<< ", " << bufsize
<< ", "
1958 << static_cast<const void*>(length
) << ", "
1959 << static_cast<const void*>(size
) << ", "
1960 << static_cast<const void*>(type
) << ", "
1961 << static_cast<const void*>(name
) << ", ");
1963 SetGLError(GL_INVALID_VALUE
, "glGetActiveAttrib", "bufsize < 0");
1966 TRACE_EVENT0("gpu", "GLES2::GetActiveAttrib");
1967 bool success
= share_group_
->program_info_manager()->GetActiveAttrib(
1968 this, program
, index
, bufsize
, length
, size
, type
, name
);
1971 GPU_CLIENT_LOG(" size: " << *size
);
1974 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
1977 GPU_CLIENT_LOG(" name: " << name
);
1983 bool GLES2Implementation::GetActiveUniformHelper(
1984 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
1985 GLenum
* type
, char* name
) {
1986 // Clear the bucket so if the command fails nothing will be in it.
1987 helper_
->SetBucketSize(kResultBucketId
, 0);
1988 typedef cmds::GetActiveUniform::Result Result
;
1989 Result
* result
= GetResultAs
<Result
*>();
1993 // Set as failed so if the command fails we'll recover.
1994 result
->success
= false;
1995 helper_
->GetActiveUniform(program
, index
, kResultBucketId
,
1996 GetResultShmId(), GetResultShmOffset());
1998 if (result
->success
) {
2000 *size
= result
->size
;
2003 *type
= result
->type
;
2005 if (length
|| name
) {
2006 std::vector
<int8
> str
;
2007 GetBucketContents(kResultBucketId
, &str
);
2008 GLsizei max_size
= std::min(static_cast<size_t>(bufsize
) - 1,
2009 std::max(static_cast<size_t>(0),
2014 if (name
&& bufsize
> 0) {
2015 memcpy(name
, &str
[0], max_size
);
2016 name
[max_size
] = '\0';
2020 return result
->success
!= 0;
2023 void GLES2Implementation::GetActiveUniform(
2024 GLuint program
, GLuint index
, GLsizei bufsize
, GLsizei
* length
, GLint
* size
,
2025 GLenum
* type
, char* name
) {
2026 GPU_CLIENT_SINGLE_THREAD_CHECK();
2027 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniform("
2028 << program
<< ", " << index
<< ", " << bufsize
<< ", "
2029 << static_cast<const void*>(length
) << ", "
2030 << static_cast<const void*>(size
) << ", "
2031 << static_cast<const void*>(type
) << ", "
2032 << static_cast<const void*>(name
) << ", ");
2034 SetGLError(GL_INVALID_VALUE
, "glGetActiveUniform", "bufsize < 0");
2037 TRACE_EVENT0("gpu", "GLES2::GetActiveUniform");
2038 bool success
= share_group_
->program_info_manager()->GetActiveUniform(
2039 this, program
, index
, bufsize
, length
, size
, type
, name
);
2042 GPU_CLIENT_LOG(" size: " << *size
);
2045 GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type
));
2048 GPU_CLIENT_LOG(" name: " << name
);
2054 void GLES2Implementation::GetAttachedShaders(
2055 GLuint program
, GLsizei maxcount
, GLsizei
* count
, GLuint
* shaders
) {
2056 GPU_CLIENT_SINGLE_THREAD_CHECK();
2057 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetAttachedShaders("
2058 << program
<< ", " << maxcount
<< ", "
2059 << static_cast<const void*>(count
) << ", "
2060 << static_cast<const void*>(shaders
) << ", ");
2062 SetGLError(GL_INVALID_VALUE
, "glGetAttachedShaders", "maxcount < 0");
2065 TRACE_EVENT0("gpu", "GLES2::GetAttachedShaders");
2066 typedef cmds::GetAttachedShaders::Result Result
;
2067 uint32 size
= Result::ComputeSize(maxcount
);
2068 Result
* result
= static_cast<Result
*>(transfer_buffer_
->Alloc(size
));
2072 result
->SetNumResults(0);
2073 helper_
->GetAttachedShaders(
2075 transfer_buffer_
->GetShmId(),
2076 transfer_buffer_
->GetOffset(result
),
2078 int32 token
= helper_
->InsertToken();
2081 *count
= result
->GetNumResults();
2083 result
->CopyResult(shaders
);
2084 GPU_CLIENT_LOG_CODE_BLOCK({
2085 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2086 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2089 transfer_buffer_
->FreePendingToken(result
, token
);
2093 void GLES2Implementation::GetShaderPrecisionFormat(
2094 GLenum shadertype
, GLenum precisiontype
, GLint
* range
, GLint
* precision
) {
2095 GPU_CLIENT_SINGLE_THREAD_CHECK();
2096 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetShaderPrecisionFormat("
2097 << GLES2Util::GetStringShaderType(shadertype
) << ", "
2098 << GLES2Util::GetStringShaderPrecision(precisiontype
) << ", "
2099 << static_cast<const void*>(range
) << ", "
2100 << static_cast<const void*>(precision
) << ", ");
2101 TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat");
2102 typedef cmds::GetShaderPrecisionFormat::Result Result
;
2103 Result
* result
= GetResultAs
<Result
*>();
2108 GLStaticState::ShaderPrecisionKey
key(shadertype
, precisiontype
);
2109 GLStaticState::ShaderPrecisionMap::iterator i
=
2110 static_state_
.shader_precisions
.find(key
);
2111 if (i
!= static_state_
.shader_precisions
.end()) {
2112 *result
= i
->second
;
2114 result
->success
= false;
2115 helper_
->GetShaderPrecisionFormat(
2116 shadertype
, precisiontype
, GetResultShmId(), GetResultShmOffset());
2118 if (result
->success
)
2119 static_state_
.shader_precisions
[key
] = *result
;
2122 if (result
->success
) {
2124 range
[0] = result
->min_range
;
2125 range
[1] = result
->max_range
;
2126 GPU_CLIENT_LOG(" min_range: " << range
[0]);
2127 GPU_CLIENT_LOG(" min_range: " << range
[1]);
2130 precision
[0] = result
->precision
;
2131 GPU_CLIENT_LOG(" min_range: " << precision
[0]);
2137 const GLubyte
* GLES2Implementation::GetStringHelper(GLenum name
) {
2138 const char* result
= NULL
;
2139 // Clears the bucket so if the command fails nothing will be in it.
2140 helper_
->SetBucketSize(kResultBucketId
, 0);
2141 helper_
->GetString(name
, kResultBucketId
);
2143 if (GetBucketAsString(kResultBucketId
, &str
)) {
2144 // Adds extensions implemented on client side only.
2147 str
+= std::string(str
.empty() ? "" : " ") +
2148 "GL_CHROMIUM_flipy "
2149 "GL_EXT_unpack_subimage";
2150 if (capabilities_
.map_image
) {
2151 // The first space character is intentional.
2152 str
+= " GL_CHROMIUM_map_image";
2159 // Because of WebGL the extensions can change. We have to cache each unique
2160 // result since we don't know when the client will stop referring to a
2161 // previous one it queries.
2162 GLStringMap::iterator it
= gl_strings_
.find(name
);
2163 if (it
== gl_strings_
.end()) {
2164 std::set
<std::string
> strings
;
2165 std::pair
<GLStringMap::iterator
, bool> insert_result
=
2166 gl_strings_
.insert(std::make_pair(name
, strings
));
2167 DCHECK(insert_result
.second
);
2168 it
= insert_result
.first
;
2170 std::set
<std::string
>& string_set
= it
->second
;
2171 std::set
<std::string
>::const_iterator sit
= string_set
.find(str
);
2172 if (sit
!= string_set
.end()) {
2173 result
= sit
->c_str();
2175 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2176 string_set
.insert(str
);
2177 DCHECK(insert_result
.second
);
2178 result
= insert_result
.first
->c_str();
2181 return reinterpret_cast<const GLubyte
*>(result
);
2184 const GLubyte
* GLES2Implementation::GetString(GLenum name
) {
2185 GPU_CLIENT_SINGLE_THREAD_CHECK();
2186 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetString("
2187 << GLES2Util::GetStringStringType(name
) << ")");
2188 TRACE_EVENT0("gpu", "GLES2::GetString");
2189 const GLubyte
* result
= GetStringHelper(name
);
2190 GPU_CLIENT_LOG(" returned " << reinterpret_cast<const char*>(result
));
2195 void GLES2Implementation::GetUniformfv(
2196 GLuint program
, GLint location
, GLfloat
* params
) {
2197 GPU_CLIENT_SINGLE_THREAD_CHECK();
2198 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformfv("
2199 << program
<< ", " << location
<< ", "
2200 << static_cast<const void*>(params
) << ")");
2201 TRACE_EVENT0("gpu", "GLES2::GetUniformfv");
2202 typedef cmds::GetUniformfv::Result Result
;
2203 Result
* result
= GetResultAs
<Result
*>();
2207 result
->SetNumResults(0);
2208 helper_
->GetUniformfv(
2209 program
, location
, GetResultShmId(), GetResultShmOffset());
2211 result
->CopyResult(params
);
2212 GPU_CLIENT_LOG_CODE_BLOCK({
2213 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2214 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2220 void GLES2Implementation::GetUniformiv(
2221 GLuint program
, GLint location
, GLint
* params
) {
2222 GPU_CLIENT_SINGLE_THREAD_CHECK();
2223 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformiv("
2224 << program
<< ", " << location
<< ", "
2225 << static_cast<const void*>(params
) << ")");
2226 TRACE_EVENT0("gpu", "GLES2::GetUniformiv");
2227 typedef cmds::GetUniformiv::Result Result
;
2228 Result
* result
= GetResultAs
<Result
*>();
2232 result
->SetNumResults(0);
2233 helper_
->GetUniformiv(
2234 program
, location
, GetResultShmId(), GetResultShmOffset());
2236 GetResultAs
<cmds::GetUniformfv::Result
*>()->CopyResult(params
);
2237 GPU_CLIENT_LOG_CODE_BLOCK({
2238 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2239 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2245 void GLES2Implementation::ReadPixels(
2246 GLint xoffset
, GLint yoffset
, GLsizei width
, GLsizei height
, GLenum format
,
2247 GLenum type
, void* pixels
) {
2248 GPU_CLIENT_SINGLE_THREAD_CHECK();
2249 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glReadPixels("
2250 << xoffset
<< ", " << yoffset
<< ", "
2251 << width
<< ", " << height
<< ", "
2252 << GLES2Util::GetStringReadPixelFormat(format
) << ", "
2253 << GLES2Util::GetStringPixelType(type
) << ", "
2254 << static_cast<const void*>(pixels
) << ")");
2255 if (width
< 0 || height
< 0) {
2256 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
2259 if (width
== 0 || height
== 0) {
2263 // glReadPixel pads the size of each row of pixels by an amount specified by
2264 // glPixelStorei. So, we have to take that into account both in the fact that
2265 // the pixels returned from the ReadPixel command will include that padding
2266 // and that when we copy the results to the user's buffer we need to not
2267 // write those padding bytes but leave them as they are.
2269 TRACE_EVENT0("gpu", "GLES2::ReadPixels");
2270 typedef cmds::ReadPixels::Result Result
;
2272 int8
* dest
= reinterpret_cast<int8
*>(pixels
);
2274 uint32 unpadded_row_size
;
2275 uint32 padded_row_size
;
2276 if (!GLES2Util::ComputeImageDataSizes(
2277 width
, 2, format
, type
, pack_alignment_
, &temp_size
, &unpadded_row_size
,
2278 &padded_row_size
)) {
2279 SetGLError(GL_INVALID_VALUE
, "glReadPixels", "size too large.");
2283 if (bound_pixel_pack_transfer_buffer_id_
) {
2284 GLuint offset
= ToGLuint(pixels
);
2285 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
2286 bound_pixel_pack_transfer_buffer_id_
,
2287 "glReadPixels", offset
, padded_row_size
* height
);
2288 if (buffer
&& buffer
->shm_id() != -1) {
2289 helper_
->ReadPixels(xoffset
, yoffset
, width
, height
, format
, type
,
2290 buffer
->shm_id(), buffer
->shm_offset(),
2298 SetGLError(GL_INVALID_OPERATION
, "glReadPixels", "pixels = NULL");
2302 // Transfer by rows.
2303 // The max rows we can transfer.
2305 GLsizei desired_size
= padded_row_size
* height
- 1 + unpadded_row_size
;
2306 ScopedTransferBufferPtr
buffer(desired_size
, helper_
, transfer_buffer_
);
2307 if (!buffer
.valid()) {
2310 GLint num_rows
= ComputeNumRowsThatFitInBuffer(
2311 padded_row_size
, unpadded_row_size
, buffer
.size());
2312 num_rows
= std::min(num_rows
, height
);
2313 // NOTE: We must look up the address of the result area AFTER allocation
2314 // of the transfer buffer since the transfer buffer may be reallocated.
2315 Result
* result
= GetResultAs
<Result
*>();
2319 *result
= 0; // mark as failed.
2320 helper_
->ReadPixels(
2321 xoffset
, yoffset
, width
, num_rows
, format
, type
,
2322 buffer
.shm_id(), buffer
.offset(),
2323 GetResultShmId(), GetResultShmOffset(),
2327 // when doing a y-flip we have to iterate through top-to-bottom chunks
2328 // of the dst. The service side handles reversing the rows within a
2331 if (pack_reverse_row_order_
) {
2332 rows_dst
= dest
+ (height
- num_rows
) * padded_row_size
;
2336 // We have to copy 1 row at a time to avoid writing pad bytes.
2337 const int8
* src
= static_cast<const int8
*>(buffer
.address());
2338 for (GLint yy
= 0; yy
< num_rows
; ++yy
) {
2339 memcpy(rows_dst
, src
, unpadded_row_size
);
2340 rows_dst
+= padded_row_size
;
2341 src
+= padded_row_size
;
2343 if (!pack_reverse_row_order_
) {
2347 // If it was not marked as successful exit.
2351 yoffset
+= num_rows
;
2357 void GLES2Implementation::ActiveTexture(GLenum texture
) {
2358 GPU_CLIENT_SINGLE_THREAD_CHECK();
2359 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture("
2360 << GLES2Util::GetStringEnum(texture
) << ")");
2361 GLuint texture_index
= texture
- GL_TEXTURE0
;
2362 if (texture_index
>= static_cast<GLuint
>(
2363 static_state_
.int_state
.max_combined_texture_image_units
)) {
2364 SetGLErrorInvalidEnum(
2365 "glActiveTexture", texture
, "texture");
2369 active_texture_unit_
= texture_index
;
2370 helper_
->ActiveTexture(texture
);
2374 void GLES2Implementation::GenBuffersHelper(
2375 GLsizei
/* n */, const GLuint
* /* buffers */) {
2378 void GLES2Implementation::GenFramebuffersHelper(
2379 GLsizei
/* n */, const GLuint
* /* framebuffers */) {
2382 void GLES2Implementation::GenRenderbuffersHelper(
2383 GLsizei
/* n */, const GLuint
* /* renderbuffers */) {
2386 void GLES2Implementation::GenTexturesHelper(
2387 GLsizei
/* n */, const GLuint
* /* textures */) {
2390 void GLES2Implementation::GenVertexArraysOESHelper(
2391 GLsizei n
, const GLuint
* arrays
) {
2392 vertex_array_object_manager_
->GenVertexArrays(n
, arrays
);
2395 void GLES2Implementation::GenQueriesEXTHelper(
2396 GLsizei
/* n */, const GLuint
* /* queries */) {
2399 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
2400 // generates a new resource. On newer versions of OpenGL they don't. The code
2401 // related to binding below will need to change if we switch to the new OpenGL
2402 // model. Specifically it assumes a bind will succeed which is always true in
2403 // the old model but possibly not true in the new model if another context has
2404 // deleted the resource.
2406 bool GLES2Implementation::BindBufferHelper(
2407 GLenum target
, GLuint buffer
) {
2408 // TODO(gman): See note #1 above.
2409 bool changed
= false;
2411 case GL_ARRAY_BUFFER
:
2412 if (bound_array_buffer_id_
!= buffer
) {
2413 bound_array_buffer_id_
= buffer
;
2417 case GL_ELEMENT_ARRAY_BUFFER
:
2418 changed
= vertex_array_object_manager_
->BindElementArray(buffer
);
2420 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
2421 bound_pixel_pack_transfer_buffer_id_
= buffer
;
2423 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
2424 bound_pixel_unpack_transfer_buffer_id_
= buffer
;
2430 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2431 // used even though it's marked it as used here.
2432 GetIdHandler(id_namespaces::kBuffers
)->MarkAsUsedForBind(buffer
);
2436 bool GLES2Implementation::BindFramebufferHelper(
2437 GLenum target
, GLuint framebuffer
) {
2438 // TODO(gman): See note #1 above.
2439 bool changed
= false;
2441 case GL_FRAMEBUFFER
:
2442 if (bound_framebuffer_
!= framebuffer
||
2443 bound_read_framebuffer_
!= framebuffer
) {
2444 bound_framebuffer_
= framebuffer
;
2445 bound_read_framebuffer_
= framebuffer
;
2449 case GL_READ_FRAMEBUFFER
:
2450 if (!IsChromiumFramebufferMultisampleAvailable()) {
2451 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2454 if (bound_read_framebuffer_
!= framebuffer
) {
2455 bound_read_framebuffer_
= framebuffer
;
2459 case GL_DRAW_FRAMEBUFFER
:
2460 if (!IsChromiumFramebufferMultisampleAvailable()) {
2461 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2464 if (bound_framebuffer_
!= framebuffer
) {
2465 bound_framebuffer_
= framebuffer
;
2470 SetGLErrorInvalidEnum("glBindFramebuffer", target
, "target");
2473 GetIdHandler(id_namespaces::kFramebuffers
)->MarkAsUsedForBind(framebuffer
);
2477 bool GLES2Implementation::BindRenderbufferHelper(
2478 GLenum target
, GLuint renderbuffer
) {
2479 // TODO(gman): See note #1 above.
2480 bool changed
= false;
2482 case GL_RENDERBUFFER
:
2483 if (bound_renderbuffer_
!= renderbuffer
) {
2484 bound_renderbuffer_
= renderbuffer
;
2492 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2493 // used even though it's marked it as used here.
2494 GetIdHandler(id_namespaces::kRenderbuffers
)->MarkAsUsedForBind(renderbuffer
);
2498 bool GLES2Implementation::BindTextureHelper(GLenum target
, GLuint texture
) {
2499 // TODO(gman): See note #1 above.
2500 // TODO(gman): Change this to false once we figure out why it's failing
2502 bool changed
= true;
2503 TextureUnit
& unit
= texture_units_
[active_texture_unit_
];
2506 if (unit
.bound_texture_2d
!= texture
) {
2507 unit
.bound_texture_2d
= texture
;
2511 case GL_TEXTURE_CUBE_MAP
:
2512 if (unit
.bound_texture_cube_map
!= texture
) {
2513 unit
.bound_texture_cube_map
= texture
;
2517 case GL_TEXTURE_EXTERNAL_OES
:
2518 if (unit
.bound_texture_external_oes
!= texture
) {
2519 unit
.bound_texture_external_oes
= texture
;
2527 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2528 // used. even though it's marked it as used here.
2529 GetIdHandler(id_namespaces::kTextures
)->MarkAsUsedForBind(texture
);
2533 bool GLES2Implementation::BindVertexArrayHelper(GLuint array
) {
2534 // TODO(gman): See note #1 above.
2535 bool changed
= false;
2536 if (!vertex_array_object_manager_
->BindVertexArray(array
, &changed
)) {
2538 GL_INVALID_OPERATION
, "glBindVertexArrayOES",
2539 "id was not generated with glGenVertexArrayOES");
2541 // Unlike other BindXXXHelpers we don't call MarkAsUsedForBind
2542 // because unlike other resources VertexArrayObject ids must
2543 // be generated by GenVertexArrays. A random id to Bind will not
2544 // generate a new object.
2548 bool GLES2Implementation::IsBufferReservedId(GLuint id
) {
2549 return vertex_array_object_manager_
->IsReservedId(id
);
2552 void GLES2Implementation::DeleteBuffersHelper(
2553 GLsizei n
, const GLuint
* buffers
) {
2554 if (!GetIdHandler(id_namespaces::kBuffers
)->FreeIds(
2555 this, n
, buffers
, &GLES2Implementation::DeleteBuffersStub
)) {
2558 "glDeleteBuffers", "id not created by this context.");
2561 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2562 if (buffers
[ii
] == bound_array_buffer_id_
) {
2563 bound_array_buffer_id_
= 0;
2565 vertex_array_object_manager_
->UnbindBuffer(buffers
[ii
]);
2566 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffers
[ii
]);
2568 // Free buffer memory, pending the passage of a token.
2569 buffer_tracker_
->FreePendingToken(buffer
, helper_
->InsertToken());
2571 buffer_tracker_
->RemoveBuffer(buffers
[ii
]);
2573 if (buffers
[ii
] == bound_pixel_unpack_transfer_buffer_id_
) {
2574 bound_pixel_unpack_transfer_buffer_id_
= 0;
2579 void GLES2Implementation::DeleteBuffersStub(
2580 GLsizei n
, const GLuint
* buffers
) {
2581 helper_
->DeleteBuffersImmediate(n
, buffers
);
2585 void GLES2Implementation::DeleteFramebuffersHelper(
2586 GLsizei n
, const GLuint
* framebuffers
) {
2587 if (!GetIdHandler(id_namespaces::kFramebuffers
)->FreeIds(
2588 this, n
, framebuffers
, &GLES2Implementation::DeleteFramebuffersStub
)) {
2591 "glDeleteFramebuffers", "id not created by this context.");
2594 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2595 if (framebuffers
[ii
] == bound_framebuffer_
) {
2596 bound_framebuffer_
= 0;
2598 if (framebuffers
[ii
] == bound_read_framebuffer_
) {
2599 bound_read_framebuffer_
= 0;
2604 void GLES2Implementation::DeleteFramebuffersStub(
2605 GLsizei n
, const GLuint
* framebuffers
) {
2606 helper_
->DeleteFramebuffersImmediate(n
, framebuffers
);
2609 void GLES2Implementation::DeleteRenderbuffersHelper(
2610 GLsizei n
, const GLuint
* renderbuffers
) {
2611 if (!GetIdHandler(id_namespaces::kRenderbuffers
)->FreeIds(
2612 this, n
, renderbuffers
, &GLES2Implementation::DeleteRenderbuffersStub
)) {
2615 "glDeleteRenderbuffers", "id not created by this context.");
2618 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2619 if (renderbuffers
[ii
] == bound_renderbuffer_
) {
2620 bound_renderbuffer_
= 0;
2625 void GLES2Implementation::DeleteRenderbuffersStub(
2626 GLsizei n
, const GLuint
* renderbuffers
) {
2627 helper_
->DeleteRenderbuffersImmediate(n
, renderbuffers
);
2630 void GLES2Implementation::DeleteTexturesHelper(
2631 GLsizei n
, const GLuint
* textures
) {
2632 if (!GetIdHandler(id_namespaces::kTextures
)->FreeIds(
2633 this, n
, textures
, &GLES2Implementation::DeleteTexturesStub
)) {
2636 "glDeleteTextures", "id not created by this context.");
2639 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2641 tt
< static_state_
.int_state
.max_combined_texture_image_units
;
2643 TextureUnit
& unit
= texture_units_
[tt
];
2644 if (textures
[ii
] == unit
.bound_texture_2d
) {
2645 unit
.bound_texture_2d
= 0;
2647 if (textures
[ii
] == unit
.bound_texture_cube_map
) {
2648 unit
.bound_texture_cube_map
= 0;
2650 if (textures
[ii
] == unit
.bound_texture_external_oes
) {
2651 unit
.bound_texture_external_oes
= 0;
2657 void GLES2Implementation::DeleteVertexArraysOESHelper(
2658 GLsizei n
, const GLuint
* arrays
) {
2659 vertex_array_object_manager_
->DeleteVertexArrays(n
, arrays
);
2660 if (!GetIdHandler(id_namespaces::kVertexArrays
)->FreeIds(
2661 this, n
, arrays
, &GLES2Implementation::DeleteVertexArraysOESStub
)) {
2664 "glDeleteVertexArraysOES", "id not created by this context.");
2669 void GLES2Implementation::DeleteVertexArraysOESStub(
2670 GLsizei n
, const GLuint
* arrays
) {
2671 helper_
->DeleteVertexArraysOESImmediate(n
, arrays
);
2674 void GLES2Implementation::DeleteTexturesStub(
2675 GLsizei n
, const GLuint
* textures
) {
2676 helper_
->DeleteTexturesImmediate(n
, textures
);
2679 void GLES2Implementation::DisableVertexAttribArray(GLuint index
) {
2680 GPU_CLIENT_SINGLE_THREAD_CHECK();
2682 "[" << GetLogPrefix() << "] glDisableVertexAttribArray(" << index
<< ")");
2683 vertex_array_object_manager_
->SetAttribEnable(index
, false);
2684 helper_
->DisableVertexAttribArray(index
);
2688 void GLES2Implementation::EnableVertexAttribArray(GLuint index
) {
2689 GPU_CLIENT_SINGLE_THREAD_CHECK();
2690 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableVertexAttribArray("
2692 vertex_array_object_manager_
->SetAttribEnable(index
, true);
2693 helper_
->EnableVertexAttribArray(index
);
2697 void GLES2Implementation::DrawArrays(GLenum mode
, GLint first
, GLsizei count
) {
2698 GPU_CLIENT_SINGLE_THREAD_CHECK();
2699 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArrays("
2700 << GLES2Util::GetStringDrawMode(mode
) << ", "
2701 << first
<< ", " << count
<< ")");
2703 SetGLError(GL_INVALID_VALUE
, "glDrawArrays", "count < 0");
2706 bool simulated
= false;
2707 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
2708 "glDrawArrays", this, helper_
, first
+ count
, 0, &simulated
)) {
2711 helper_
->DrawArrays(mode
, first
, count
);
2712 RestoreArrayBuffer(simulated
);
2716 void GLES2Implementation::GetVertexAttribfv(
2717 GLuint index
, GLenum pname
, GLfloat
* params
) {
2718 GPU_CLIENT_SINGLE_THREAD_CHECK();
2719 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribfv("
2721 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2722 << static_cast<const void*>(params
) << ")");
2724 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2725 *params
= static_cast<float>(value
);
2728 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv");
2729 typedef cmds::GetVertexAttribfv::Result Result
;
2730 Result
* result
= GetResultAs
<Result
*>();
2734 result
->SetNumResults(0);
2735 helper_
->GetVertexAttribfv(
2736 index
, pname
, GetResultShmId(), GetResultShmOffset());
2738 result
->CopyResult(params
);
2739 GPU_CLIENT_LOG_CODE_BLOCK({
2740 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2741 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2747 void GLES2Implementation::GetVertexAttribiv(
2748 GLuint index
, GLenum pname
, GLint
* params
) {
2749 GPU_CLIENT_SINGLE_THREAD_CHECK();
2750 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetVertexAttribiv("
2752 << GLES2Util::GetStringVertexAttribute(pname
) << ", "
2753 << static_cast<const void*>(params
) << ")");
2755 if (vertex_array_object_manager_
->GetVertexAttrib(index
, pname
, &value
)) {
2759 TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv");
2760 typedef cmds::GetVertexAttribiv::Result Result
;
2761 Result
* result
= GetResultAs
<Result
*>();
2765 result
->SetNumResults(0);
2766 helper_
->GetVertexAttribiv(
2767 index
, pname
, GetResultShmId(), GetResultShmOffset());
2769 result
->CopyResult(params
);
2770 GPU_CLIENT_LOG_CODE_BLOCK({
2771 for (int32 i
= 0; i
< result
->GetNumResults(); ++i
) {
2772 GPU_CLIENT_LOG(" " << i
<< ": " << result
->GetData()[i
]);
2778 void GLES2Implementation::Swap() {
2781 base::Bind(&GLES2Implementation::OnSwapBuffersComplete
,
2782 weak_ptr_factory_
.GetWeakPtr()));
2785 void GLES2Implementation::PartialSwapBuffers(gfx::Rect sub_buffer
) {
2786 PostSubBufferCHROMIUM(sub_buffer
.x(),
2789 sub_buffer
.height());
2790 gpu_control_
->Echo(base::Bind(&GLES2Implementation::OnSwapBuffersComplete
,
2791 weak_ptr_factory_
.GetWeakPtr()));
2794 void GLES2Implementation::SetSwapBuffersCompleteCallback(
2795 const base::Closure
& swap_buffers_complete_callback
) {
2796 swap_buffers_complete_callback_
= swap_buffers_complete_callback
;
2799 void GLES2Implementation::OnSwapBuffersComplete() {
2800 if (!swap_buffers_complete_callback_
.is_null())
2801 swap_buffers_complete_callback_
.Run();
2804 GLboolean
GLES2Implementation::EnableFeatureCHROMIUM(
2805 const char* feature
) {
2806 GPU_CLIENT_SINGLE_THREAD_CHECK();
2807 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEnableFeatureCHROMIUM("
2809 TRACE_EVENT0("gpu", "GLES2::EnableFeatureCHROMIUM");
2810 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
2811 Result
* result
= GetResultAs
<Result
*>();
2816 SetBucketAsCString(kResultBucketId
, feature
);
2817 helper_
->EnableFeatureCHROMIUM(
2818 kResultBucketId
, GetResultShmId(), GetResultShmOffset());
2820 helper_
->SetBucketSize(kResultBucketId
, 0);
2821 GPU_CLIENT_LOG(" returned " << GLES2Util::GetStringBool(*result
));
2825 void* GLES2Implementation::MapBufferSubDataCHROMIUM(
2826 GLuint target
, GLintptr offset
, GLsizeiptr size
, GLenum access
) {
2827 GPU_CLIENT_SINGLE_THREAD_CHECK();
2828 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferSubDataCHROMIUM("
2829 << target
<< ", " << offset
<< ", " << size
<< ", "
2830 << GLES2Util::GetStringEnum(access
) << ")");
2831 // NOTE: target is NOT checked because the service will check it
2832 // and we don't know what targets are valid.
2833 if (access
!= GL_WRITE_ONLY
) {
2834 SetGLErrorInvalidEnum(
2835 "glMapBufferSubDataCHROMIUM", access
, "access");
2838 if (offset
< 0 || size
< 0) {
2839 SetGLError(GL_INVALID_VALUE
, "glMapBufferSubDataCHROMIUM", "bad range");
2843 unsigned int shm_offset
;
2844 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2846 SetGLError(GL_OUT_OF_MEMORY
, "glMapBufferSubDataCHROMIUM", "out of memory");
2850 std::pair
<MappedBufferMap::iterator
, bool> result
=
2851 mapped_buffers_
.insert(std::make_pair(
2854 access
, shm_id
, mem
, shm_offset
, target
, offset
, size
)));
2855 DCHECK(result
.second
);
2856 GPU_CLIENT_LOG(" returned " << mem
);
2860 void GLES2Implementation::UnmapBufferSubDataCHROMIUM(const void* mem
) {
2861 GPU_CLIENT_SINGLE_THREAD_CHECK();
2863 "[" << GetLogPrefix() << "] glUnmapBufferSubDataCHROMIUM(" << mem
<< ")");
2864 MappedBufferMap::iterator it
= mapped_buffers_
.find(mem
);
2865 if (it
== mapped_buffers_
.end()) {
2867 GL_INVALID_VALUE
, "UnmapBufferSubDataCHROMIUM", "buffer not mapped");
2870 const MappedBuffer
& mb
= it
->second
;
2871 helper_
->BufferSubData(
2872 mb
.target
, mb
.offset
, mb
.size
, mb
.shm_id
, mb
.shm_offset
);
2873 mapped_memory_
->FreePendingToken(mb
.shm_memory
, helper_
->InsertToken());
2874 mapped_buffers_
.erase(it
);
2878 void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
2888 GPU_CLIENT_SINGLE_THREAD_CHECK();
2889 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapTexSubImage2DCHROMIUM("
2890 << target
<< ", " << level
<< ", "
2891 << xoffset
<< ", " << yoffset
<< ", "
2892 << width
<< ", " << height
<< ", "
2893 << GLES2Util::GetStringTextureFormat(format
) << ", "
2894 << GLES2Util::GetStringPixelType(type
) << ", "
2895 << GLES2Util::GetStringEnum(access
) << ")");
2896 if (access
!= GL_WRITE_ONLY
) {
2897 SetGLErrorInvalidEnum(
2898 "glMapTexSubImage2DCHROMIUM", access
, "access");
2901 // NOTE: target is NOT checked because the service will check it
2902 // and we don't know what targets are valid.
2903 if (level
< 0 || xoffset
< 0 || yoffset
< 0 || width
< 0 || height
< 0) {
2905 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "bad dimensions");
2909 if (!GLES2Util::ComputeImageDataSizes(
2910 width
, height
, format
, type
, unpack_alignment_
, &size
, NULL
, NULL
)) {
2912 GL_INVALID_VALUE
, "glMapTexSubImage2DCHROMIUM", "image size too large");
2916 unsigned int shm_offset
;
2917 void* mem
= mapped_memory_
->Alloc(size
, &shm_id
, &shm_offset
);
2919 SetGLError(GL_OUT_OF_MEMORY
, "glMapTexSubImage2DCHROMIUM", "out of memory");
2923 std::pair
<MappedTextureMap::iterator
, bool> result
=
2924 mapped_textures_
.insert(std::make_pair(
2927 access
, shm_id
, mem
, shm_offset
,
2928 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)));
2929 DCHECK(result
.second
);
2930 GPU_CLIENT_LOG(" returned " << mem
);
2934 void GLES2Implementation::UnmapTexSubImage2DCHROMIUM(const void* mem
) {
2935 GPU_CLIENT_SINGLE_THREAD_CHECK();
2937 "[" << GetLogPrefix() << "] glUnmapTexSubImage2DCHROMIUM(" << mem
<< ")");
2938 MappedTextureMap::iterator it
= mapped_textures_
.find(mem
);
2939 if (it
== mapped_textures_
.end()) {
2941 GL_INVALID_VALUE
, "UnmapTexSubImage2DCHROMIUM", "texture not mapped");
2944 const MappedTexture
& mt
= it
->second
;
2945 helper_
->TexSubImage2D(
2946 mt
.target
, mt
.level
, mt
.xoffset
, mt
.yoffset
, mt
.width
, mt
.height
,
2947 mt
.format
, mt
.type
, mt
.shm_id
, mt
.shm_offset
, GL_FALSE
);
2948 mapped_memory_
->FreePendingToken(mt
.shm_memory
, helper_
->InsertToken());
2949 mapped_textures_
.erase(it
);
2953 void GLES2Implementation::ResizeCHROMIUM(GLuint width
, GLuint height
,
2954 float scale_factor
) {
2955 GPU_CLIENT_SINGLE_THREAD_CHECK();
2956 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResizeCHROMIUM("
2957 << width
<< ", " << height
<< ", " << scale_factor
<< ")");
2958 helper_
->ResizeCHROMIUM(width
, height
, scale_factor
);
2962 const GLchar
* GLES2Implementation::GetRequestableExtensionsCHROMIUM() {
2963 GPU_CLIENT_SINGLE_THREAD_CHECK();
2964 GPU_CLIENT_LOG("[" << GetLogPrefix()
2965 << "] glGetRequestableExtensionsCHROMIUM()");
2967 "GLES2Implementation::GetRequestableExtensionsCHROMIUM()");
2968 const char* result
= NULL
;
2969 // Clear the bucket so if the command fails nothing will be in it.
2970 helper_
->SetBucketSize(kResultBucketId
, 0);
2971 helper_
->GetRequestableExtensionsCHROMIUM(kResultBucketId
);
2973 if (GetBucketAsString(kResultBucketId
, &str
)) {
2974 // The set of requestable extensions shrinks as we enable
2975 // them. Because we don't know when the client will stop referring
2976 // to a previous one it queries (see GetString) we need to cache
2977 // the unique results.
2978 std::set
<std::string
>::const_iterator sit
=
2979 requestable_extensions_set_
.find(str
);
2980 if (sit
!= requestable_extensions_set_
.end()) {
2981 result
= sit
->c_str();
2983 std::pair
<std::set
<std::string
>::const_iterator
, bool> insert_result
=
2984 requestable_extensions_set_
.insert(str
);
2985 DCHECK(insert_result
.second
);
2986 result
= insert_result
.first
->c_str();
2989 GPU_CLIENT_LOG(" returned " << result
);
2990 return reinterpret_cast<const GLchar
*>(result
);
2993 // TODO(gman): Remove this command. It's here for WebGL but is incompatible
2994 // with VirtualGL contexts.
2995 void GLES2Implementation::RequestExtensionCHROMIUM(const char* extension
) {
2996 GPU_CLIENT_SINGLE_THREAD_CHECK();
2997 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRequestExtensionCHROMIUM("
2998 << extension
<< ")");
2999 SetBucketAsCString(kResultBucketId
, extension
);
3000 helper_
->RequestExtensionCHROMIUM(kResultBucketId
);
3001 helper_
->SetBucketSize(kResultBucketId
, 0);
3003 struct ExtensionCheck
{
3004 const char* extension
;
3005 ExtensionStatus
* status
;
3007 const ExtensionCheck checks
[] = {
3009 "GL_ANGLE_pack_reverse_row_order",
3010 &angle_pack_reverse_row_order_status_
,
3013 "GL_CHROMIUM_framebuffer_multisample",
3014 &chromium_framebuffer_multisample_
,
3017 const size_t kNumChecks
= sizeof(checks
)/sizeof(checks
[0]);
3018 for (size_t ii
= 0; ii
< kNumChecks
; ++ii
) {
3019 const ExtensionCheck
& check
= checks
[ii
];
3020 if (*check
.status
== kUnavailableExtensionStatus
&&
3021 !strcmp(extension
, check
.extension
)) {
3022 *check
.status
= kUnknownExtensionStatus
;
3027 void GLES2Implementation::RateLimitOffscreenContextCHROMIUM() {
3028 GPU_CLIENT_SINGLE_THREAD_CHECK();
3029 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glRateLimitOffscreenCHROMIUM()");
3030 // Wait if this would add too many rate limit tokens.
3031 if (rate_limit_tokens_
.size() == kMaxSwapBuffers
) {
3032 helper_
->WaitForToken(rate_limit_tokens_
.front());
3033 rate_limit_tokens_
.pop();
3035 rate_limit_tokens_
.push(helper_
->InsertToken());
3038 void GLES2Implementation::GetMultipleIntegervCHROMIUM(
3039 const GLenum
* pnames
, GLuint count
, GLint
* results
, GLsizeiptr size
) {
3040 GPU_CLIENT_SINGLE_THREAD_CHECK();
3041 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetMultipleIntegervCHROMIUM("
3042 << static_cast<const void*>(pnames
) << ", "
3043 << count
<< ", " << results
<< ", "
3045 GPU_CLIENT_LOG_CODE_BLOCK({
3046 for (GLuint i
= 0; i
< count
; ++i
) {
3048 " " << i
<< ": " << GLES2Util::GetStringGLState(pnames
[i
]));
3052 GetMultipleIntegervState
state(pnames
, count
, results
, size
);
3053 if (!GetMultipleIntegervSetup(&state
)) {
3056 state
.buffer
= transfer_buffer_
->Alloc(state
.transfer_buffer_size_needed
);
3057 if (!state
.buffer
) {
3058 SetGLError(GL_OUT_OF_MEMORY
, "glGetMultipleIntegervCHROMIUM",
3059 "Transfer buffer allocation failed.");
3062 GetMultipleIntegervRequest(&state
);
3064 GetMultipleIntegervOnCompleted(&state
);
3066 GPU_CLIENT_LOG(" returned");
3067 GPU_CLIENT_LOG_CODE_BLOCK({
3068 for (int i
= 0; i
< state
.num_results
; ++i
) {
3069 GPU_CLIENT_LOG(" " << i
<< ": " << (results
[i
]));
3073 // TODO(gman): We should be able to free without a token.
3074 transfer_buffer_
->FreePendingToken(state
.buffer
, helper_
->InsertToken());
3078 bool GLES2Implementation::GetMultipleIntegervSetup(
3079 GetMultipleIntegervState
* state
) {
3080 state
->num_results
= 0;
3081 for (GLuint ii
= 0; ii
< state
->pnames_count
; ++ii
) {
3082 int num
= util_
.GLGetNumValuesReturned(state
->pnames
[ii
]);
3084 SetGLErrorInvalidEnum(
3085 "glGetMultipleIntegervCHROMIUM", state
->pnames
[ii
], "pname");
3088 state
->num_results
+= num
;
3090 if (static_cast<size_t>(state
->results_size
) !=
3091 state
->num_results
* sizeof(GLint
)) {
3092 SetGLError(GL_INVALID_VALUE
, "glGetMultipleIntegervCHROMIUM", "bad size");
3095 for (int ii
= 0; ii
< state
->num_results
; ++ii
) {
3096 if (state
->results
[ii
] != 0) {
3097 SetGLError(GL_INVALID_VALUE
,
3098 "glGetMultipleIntegervCHROMIUM", "results not set to zero.");
3102 state
->transfer_buffer_size_needed
=
3103 state
->pnames_count
* sizeof(state
->pnames
[0]) +
3104 state
->num_results
* sizeof(state
->results
[0]);
3108 void GLES2Implementation::GetMultipleIntegervRequest(
3109 GetMultipleIntegervState
* state
) {
3110 GLenum
* pnames_buffer
= static_cast<GLenum
*>(state
->buffer
);
3111 state
->results_buffer
= pnames_buffer
+ state
->pnames_count
;
3112 memcpy(pnames_buffer
, state
->pnames
, state
->pnames_count
* sizeof(GLenum
));
3113 memset(state
->results_buffer
, 0, state
->num_results
* sizeof(GLint
));
3114 helper_
->GetMultipleIntegervCHROMIUM(
3115 transfer_buffer_
->GetShmId(),
3116 transfer_buffer_
->GetOffset(pnames_buffer
),
3117 state
->pnames_count
,
3118 transfer_buffer_
->GetShmId(),
3119 transfer_buffer_
->GetOffset(state
->results_buffer
),
3120 state
->results_size
);
3123 void GLES2Implementation::GetMultipleIntegervOnCompleted(
3124 GetMultipleIntegervState
* state
) {
3125 memcpy(state
->results
, state
->results_buffer
, state
->results_size
);;
3128 void GLES2Implementation::GetAllShaderPrecisionFormatsSetup(
3129 GetAllShaderPrecisionFormatsState
* state
) {
3130 state
->transfer_buffer_size_needed
=
3131 state
->precision_params_count
*
3132 sizeof(cmds::GetShaderPrecisionFormat::Result
);
3135 void GLES2Implementation::GetAllShaderPrecisionFormatsRequest(
3136 GetAllShaderPrecisionFormatsState
* state
) {
3137 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3138 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3140 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3141 result
->success
= false;
3142 helper_
->GetShaderPrecisionFormat(state
->precision_params
[i
][0],
3143 state
->precision_params
[i
][1],
3144 transfer_buffer_
->GetShmId(),
3145 transfer_buffer_
->GetOffset(result
));
3150 void GLES2Implementation::GetAllShaderPrecisionFormatsOnCompleted(
3151 GetAllShaderPrecisionFormatsState
* state
) {
3152 typedef cmds::GetShaderPrecisionFormat::Result Result
;
3153 Result
* result
= static_cast<Result
*>(state
->results_buffer
);
3155 for (int i
= 0; i
< state
->precision_params_count
; i
++) {
3156 if (result
->success
) {
3157 const GLStaticState::ShaderPrecisionKey
key(
3158 state
->precision_params
[i
][0], state
->precision_params
[i
][1]);
3159 static_state_
.shader_precisions
[key
] = *result
;
3165 void GLES2Implementation::GetProgramInfoCHROMIUMHelper(
3166 GLuint program
, std::vector
<int8
>* result
) {
3168 // Clear the bucket so if the command fails nothing will be in it.
3169 helper_
->SetBucketSize(kResultBucketId
, 0);
3170 helper_
->GetProgramInfoCHROMIUM(program
, kResultBucketId
);
3171 GetBucketContents(kResultBucketId
, result
);
3174 void GLES2Implementation::GetProgramInfoCHROMIUM(
3175 GLuint program
, GLsizei bufsize
, GLsizei
* size
, void* info
) {
3176 GPU_CLIENT_SINGLE_THREAD_CHECK();
3179 GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "bufsize less than 0.");
3183 SetGLError(GL_INVALID_VALUE
, "glProgramInfoCHROMIUM", "size is null.");
3186 // Make sure they've set size to 0 else the value will be undefined on
3189 std::vector
<int8
> result
;
3190 GetProgramInfoCHROMIUMHelper(program
, &result
);
3191 if (result
.empty()) {
3194 *size
= result
.size();
3198 if (static_cast<size_t>(bufsize
) < result
.size()) {
3199 SetGLError(GL_INVALID_OPERATION
,
3200 "glProgramInfoCHROMIUM", "bufsize is too small for result.");
3203 memcpy(info
, &result
[0], result
.size());
3206 GLuint
GLES2Implementation::CreateStreamTextureCHROMIUM(GLuint texture
) {
3207 GPU_CLIENT_SINGLE_THREAD_CHECK();
3208 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] CreateStreamTextureCHROMIUM("
3210 TRACE_EVENT0("gpu", "GLES2::CreateStreamTextureCHROMIUM");
3211 typedef cmds::CreateStreamTextureCHROMIUM::Result Result
;
3212 Result
* result
= GetResultAs
<Result
*>();
3218 helper_
->CreateStreamTextureCHROMIUM(texture
,
3220 GetResultShmOffset());
3222 GLuint result_value
= *result
;
3224 return result_value
;
3227 void GLES2Implementation::DestroyStreamTextureCHROMIUM(GLuint texture
) {
3228 GPU_CLIENT_SINGLE_THREAD_CHECK();
3229 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] DestroyStreamTextureCHROMIUM("
3231 TRACE_EVENT0("gpu", "GLES2::DestroyStreamTextureCHROMIUM");
3232 helper_
->DestroyStreamTextureCHROMIUM(texture
);
3236 void GLES2Implementation::PostSubBufferCHROMIUM(
3237 GLint x
, GLint y
, GLint width
, GLint height
) {
3238 GPU_CLIENT_SINGLE_THREAD_CHECK();
3239 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] PostSubBufferCHROMIUM("
3240 << x
<< ", " << y
<< ", " << width
<< ", " << height
<< ")");
3241 TRACE_EVENT2("gpu", "GLES2::PostSubBufferCHROMIUM",
3242 "width", width
, "height", height
);
3244 // Same flow control as GLES2Implementation::SwapBuffers (see comments there).
3245 swap_buffers_tokens_
.push(helper_
->InsertToken());
3246 helper_
->PostSubBufferCHROMIUM(x
, y
, width
, height
);
3247 helper_
->CommandBufferHelper::Flush();
3248 if (swap_buffers_tokens_
.size() > kMaxSwapBuffers
+ 1) {
3249 helper_
->WaitForToken(swap_buffers_tokens_
.front());
3250 swap_buffers_tokens_
.pop();
3254 void GLES2Implementation::DeleteQueriesEXTHelper(
3255 GLsizei n
, const GLuint
* queries
) {
3256 // TODO(gman): Remove this as queries are not shared resources.
3257 if (!GetIdHandler(id_namespaces::kQueries
)->FreeIds(
3258 this, n
, queries
, &GLES2Implementation::DeleteQueriesStub
)) {
3261 "glDeleteTextures", "id not created by this context.");
3265 for (GLsizei ii
= 0; ii
< n
; ++ii
)
3266 query_tracker_
->RemoveQuery(queries
[ii
]);
3268 helper_
->DeleteQueriesEXTImmediate(n
, queries
);
3271 // TODO(gman): Remove this. Queries are not shared resources.
3272 void GLES2Implementation::DeleteQueriesStub(
3273 GLsizei
/* n */, const GLuint
* /* queries */) {
3276 GLboolean
GLES2Implementation::IsQueryEXT(GLuint id
) {
3277 GPU_CLIENT_SINGLE_THREAD_CHECK();
3278 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] IsQueryEXT(" << id
<< ")");
3280 // TODO(gman): To be spec compliant IDs from other contexts sharing
3281 // resources need to return true here even though you can't share
3282 // queries across contexts?
3283 return query_tracker_
->GetQuery(id
) != NULL
;
3286 void GLES2Implementation::BeginQueryEXT(GLenum target
, GLuint id
) {
3287 GPU_CLIENT_SINGLE_THREAD_CHECK();
3288 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] BeginQueryEXT("
3289 << GLES2Util::GetStringQueryTarget(target
)
3290 << ", " << id
<< ")");
3292 // if any outstanding queries INV_OP
3293 if (current_query_
) {
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_query_
= 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 if (!current_query_
) {
3337 SetGLError(GL_INVALID_OPERATION
, "glEndQueryEXT", "no active query");
3341 if (current_query_
->target() != target
) {
3342 SetGLError(GL_INVALID_OPERATION
,
3343 "glEndQueryEXT", "target does not match active query");
3347 current_query_
->End(this);
3348 current_query_
= NULL
;
3352 void GLES2Implementation::GetQueryivEXT(
3353 GLenum target
, GLenum pname
, GLint
* params
) {
3354 GPU_CLIENT_SINGLE_THREAD_CHECK();
3355 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT("
3356 << GLES2Util::GetStringQueryTarget(target
) << ", "
3357 << GLES2Util::GetStringQueryParameter(pname
) << ", "
3358 << static_cast<const void*>(params
) << ")");
3360 if (pname
!= GL_CURRENT_QUERY_EXT
) {
3361 SetGLErrorInvalidEnum("glGetQueryivEXT", pname
, "pname");
3364 *params
= (current_query_
&& current_query_
->target() == target
) ?
3365 current_query_
->id() : 0;
3366 GPU_CLIENT_LOG(" " << *params
);
3370 void GLES2Implementation::GetQueryObjectuivEXT(
3371 GLuint id
, GLenum pname
, GLuint
* params
) {
3372 GPU_CLIENT_SINGLE_THREAD_CHECK();
3373 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] GetQueryivEXT(" << id
<< ", "
3374 << GLES2Util::GetStringQueryObjectParameter(pname
) << ", "
3375 << static_cast<const void*>(params
) << ")");
3377 QueryTracker::Query
* query
= query_tracker_
->GetQuery(id
);
3379 SetGLError(GL_INVALID_OPERATION
, "glQueryObjectuivEXT", "unknown query id");
3383 if (query
== current_query_
) {
3385 GL_INVALID_OPERATION
,
3386 "glQueryObjectuivEXT", "query active. Did you to call glEndQueryEXT?");
3390 if (query
->NeverUsed()) {
3392 GL_INVALID_OPERATION
,
3393 "glQueryObjectuivEXT", "Never used. Did you call glBeginQueryEXT?");
3398 case GL_QUERY_RESULT_EXT
:
3399 if (!query
->CheckResultsAvailable(helper_
)) {
3400 helper_
->WaitForToken(query
->token());
3401 if (!query
->CheckResultsAvailable(helper_
)) {
3402 // TODO(gman): Speed this up.
3404 CHECK(query
->CheckResultsAvailable(helper_
));
3407 *params
= query
->GetResult();
3409 case GL_QUERY_RESULT_AVAILABLE_EXT
:
3410 *params
= query
->CheckResultsAvailable(helper_
);
3413 SetGLErrorInvalidEnum("glQueryObjectuivEXT", pname
, "pname");
3416 GPU_CLIENT_LOG(" " << *params
);
3420 void GLES2Implementation::DrawArraysInstancedANGLE(
3421 GLenum mode
, GLint first
, GLsizei count
, GLsizei primcount
) {
3422 GPU_CLIENT_SINGLE_THREAD_CHECK();
3423 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawArraysInstancedANGLE("
3424 << GLES2Util::GetStringDrawMode(mode
) << ", "
3425 << first
<< ", " << count
<< ", " << primcount
<< ")");
3427 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "count < 0");
3430 if (primcount
< 0) {
3431 SetGLError(GL_INVALID_VALUE
, "glDrawArraysInstancedANGLE", "primcount < 0");
3434 if (primcount
== 0) {
3437 bool simulated
= false;
3438 if (!vertex_array_object_manager_
->SetupSimulatedClientSideBuffers(
3439 "glDrawArraysInstancedANGLE", this, helper_
, first
+ count
, primcount
,
3443 helper_
->DrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
3444 RestoreArrayBuffer(simulated
);
3448 void GLES2Implementation::DrawElementsInstancedANGLE(
3449 GLenum mode
, GLsizei count
, GLenum type
, const void* indices
,
3450 GLsizei primcount
) {
3451 GPU_CLIENT_SINGLE_THREAD_CHECK();
3452 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawElementsInstancedANGLE("
3453 << GLES2Util::GetStringDrawMode(mode
) << ", "
3455 << GLES2Util::GetStringIndexType(type
) << ", "
3456 << static_cast<const void*>(indices
) << ", "
3457 << primcount
<< ")");
3459 SetGLError(GL_INVALID_VALUE
,
3460 "glDrawElementsInstancedANGLE", "count less than 0.");
3466 if (primcount
< 0) {
3467 SetGLError(GL_INVALID_VALUE
,
3468 "glDrawElementsInstancedANGLE", "primcount < 0");
3471 if (primcount
== 0) {
3475 bool simulated
= false;
3476 if (!vertex_array_object_manager_
->SetupSimulatedIndexAndClientSideBuffers(
3477 "glDrawElementsInstancedANGLE", this, helper_
, count
, type
, primcount
,
3478 indices
, &offset
, &simulated
)) {
3481 helper_
->DrawElementsInstancedANGLE(mode
, count
, type
, offset
, primcount
);
3482 RestoreElementAndArrayBuffers(simulated
);
3486 void GLES2Implementation::GenMailboxCHROMIUM(
3488 GPU_CLIENT_SINGLE_THREAD_CHECK();
3489 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenMailboxCHROMIUM("
3490 << static_cast<const void*>(mailbox
) << ")");
3491 TRACE_EVENT0("gpu", "GLES2::GenMailboxCHROMIUM");
3493 std::vector
<gpu::Mailbox
> names
;
3494 if (!gpu_control_
->GenerateMailboxNames(1, &names
)) {
3495 SetGLError(GL_OUT_OF_MEMORY
, "glGenMailboxCHROMIUM", "Generate failed.");
3498 memcpy(mailbox
, names
[0].name
, GL_MAILBOX_SIZE_CHROMIUM
);
3501 void GLES2Implementation::PushGroupMarkerEXT(
3502 GLsizei length
, const GLchar
* marker
) {
3503 GPU_CLIENT_SINGLE_THREAD_CHECK();
3504 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPushGroupMarkerEXT("
3505 << length
<< ", " << marker
<< ")");
3511 (length
? std::string(marker
, length
) : std::string(marker
)));
3512 helper_
->PushGroupMarkerEXT(kResultBucketId
);
3513 helper_
->SetBucketSize(kResultBucketId
, 0);
3514 debug_marker_manager_
.PushGroup(
3515 length
? std::string(marker
, length
) : std::string(marker
));
3518 void GLES2Implementation::InsertEventMarkerEXT(
3519 GLsizei length
, const GLchar
* marker
) {
3520 GPU_CLIENT_SINGLE_THREAD_CHECK();
3521 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertEventMarkerEXT("
3522 << length
<< ", " << marker
<< ")");
3528 (length
? std::string(marker
, length
) : std::string(marker
)));
3529 helper_
->InsertEventMarkerEXT(kResultBucketId
);
3530 helper_
->SetBucketSize(kResultBucketId
, 0);
3531 debug_marker_manager_
.SetMarker(
3532 length
? std::string(marker
, length
) : std::string(marker
));
3535 void GLES2Implementation::PopGroupMarkerEXT() {
3536 GPU_CLIENT_SINGLE_THREAD_CHECK();
3537 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPopGroupMarkerEXT()");
3538 helper_
->PopGroupMarkerEXT();
3539 debug_marker_manager_
.PopGroup();
3542 void GLES2Implementation::TraceBeginCHROMIUM(const char* name
) {
3543 GPU_CLIENT_SINGLE_THREAD_CHECK();
3544 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
3546 if (current_trace_name_
.get()) {
3547 SetGLError(GL_INVALID_OPERATION
, "glTraceBeginCHROMIUM",
3548 "trace already running");
3551 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", name
, this);
3552 SetBucketAsCString(kResultBucketId
, name
);
3553 helper_
->TraceBeginCHROMIUM(kResultBucketId
);
3554 helper_
->SetBucketSize(kResultBucketId
, 0);
3555 current_trace_name_
.reset(new std::string(name
));
3558 void GLES2Implementation::TraceEndCHROMIUM() {
3559 GPU_CLIENT_SINGLE_THREAD_CHECK();
3560 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
3561 if (!current_trace_name_
.get()) {
3562 SetGLError(GL_INVALID_OPERATION
, "glTraceEndCHROMIUM",
3563 "missing begin trace");
3566 helper_
->TraceEndCHROMIUM();
3567 TRACE_EVENT_COPY_ASYNC_END0("gpu", current_trace_name_
->c_str(), this);
3568 current_trace_name_
.reset();
3571 void* GLES2Implementation::MapBufferCHROMIUM(GLuint target
, GLenum access
) {
3572 GPU_CLIENT_SINGLE_THREAD_CHECK();
3573 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
3574 << target
<< ", " << GLES2Util::GetStringEnum(access
) << ")");
3576 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
:
3577 if (access
!= GL_READ_ONLY
) {
3578 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3582 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
:
3583 if (access
!= GL_WRITE_ONLY
) {
3584 SetGLError(GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "bad access mode");
3590 GL_INVALID_ENUM
, "glMapBufferCHROMIUM", "invalid target");
3594 GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
);
3598 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3600 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "invalid buffer");
3603 if (buffer
->mapped()) {
3604 SetGLError(GL_INVALID_OPERATION
, "glMapBufferCHROMIUM", "already mapped");
3607 // Here we wait for previous transfer operations to be finished.
3608 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
3609 // with this method of synchronization. Until this is fixed,
3610 // MapBufferCHROMIUM will not block even if the transfer is not ready
3612 if (buffer
->transfer_ready_token()) {
3613 helper_
->WaitForToken(buffer
->transfer_ready_token());
3614 buffer
->set_transfer_ready_token(0);
3616 buffer
->set_mapped(true);
3618 GPU_CLIENT_LOG(" returned " << buffer
->address());
3620 return buffer
->address();
3623 GLboolean
GLES2Implementation::UnmapBufferCHROMIUM(GLuint target
) {
3624 GPU_CLIENT_SINGLE_THREAD_CHECK();
3626 "[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target
<< ")");
3628 if (!GetBoundPixelTransferBuffer(target
, "glMapBufferCHROMIUM", &buffer_id
)) {
3629 SetGLError(GL_INVALID_ENUM
, "glUnmapBufferCHROMIUM", "invalid target");
3634 BufferTracker::Buffer
* buffer
= buffer_tracker_
->GetBuffer(buffer_id
);
3636 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "invalid buffer");
3639 if (!buffer
->mapped()) {
3640 SetGLError(GL_INVALID_OPERATION
, "glUnmapBufferCHROMIUM", "not mapped");
3643 buffer
->set_mapped(false);
3648 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
3649 GLenum target
, GLint level
, GLint internalformat
, GLsizei width
,
3650 GLsizei height
, GLint border
, GLenum format
, GLenum type
,
3651 const void* pixels
) {
3652 GPU_CLIENT_SINGLE_THREAD_CHECK();
3653 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
3654 << GLES2Util::GetStringTextureTarget(target
) << ", "
3656 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ", "
3657 << width
<< ", " << height
<< ", " << border
<< ", "
3658 << GLES2Util::GetStringTextureFormat(format
) << ", "
3659 << GLES2Util::GetStringPixelType(type
) << ", "
3660 << static_cast<const void*>(pixels
) << ")");
3661 if (level
< 0 || height
< 0 || width
< 0) {
3662 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "dimension < 0");
3666 uint32 unpadded_row_size
;
3667 uint32 padded_row_size
;
3668 if (!GLES2Util::ComputeImageDataSizes(
3669 width
, height
, format
, type
, unpack_alignment_
, &size
,
3670 &unpadded_row_size
, &padded_row_size
)) {
3671 SetGLError(GL_INVALID_VALUE
, "glTexImage2D", "image size too large");
3675 // If there's no data/buffer just issue the AsyncTexImage2D
3676 if (!pixels
&& !bound_pixel_unpack_transfer_buffer_id_
) {
3677 helper_
->AsyncTexImage2DCHROMIUM(
3678 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3683 // Otherwise, async uploads require a transfer buffer to be bound.
3684 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3685 // the buffer before the transfer is finished. (Currently such
3686 // synchronization has to be handled manually.)
3687 GLuint offset
= ToGLuint(pixels
);
3688 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3689 bound_pixel_unpack_transfer_buffer_id_
,
3690 "glAsyncTexImage2DCHROMIUM", offset
, size
);
3691 if (buffer
&& buffer
->shm_id() != -1) {
3692 helper_
->AsyncTexImage2DCHROMIUM(
3693 target
, level
, internalformat
, width
, height
, border
, format
, type
,
3694 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3698 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
3699 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLsizei width
,
3700 GLsizei height
, GLenum format
, GLenum type
, const void* pixels
) {
3701 GPU_CLIENT_SINGLE_THREAD_CHECK();
3702 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
3703 << GLES2Util::GetStringTextureTarget(target
) << ", "
3705 << xoffset
<< ", " << yoffset
<< ", "
3706 << width
<< ", " << height
<< ", "
3707 << GLES2Util::GetStringTextureFormat(format
) << ", "
3708 << GLES2Util::GetStringPixelType(type
) << ", "
3709 << static_cast<const void*>(pixels
) << ")");
3710 if (level
< 0 || height
< 0 || width
< 0) {
3712 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "dimension < 0");
3717 uint32 unpadded_row_size
;
3718 uint32 padded_row_size
;
3719 if (!GLES2Util::ComputeImageDataSizes(
3720 width
, height
, format
, type
, unpack_alignment_
, &size
,
3721 &unpadded_row_size
, &padded_row_size
)) {
3723 GL_INVALID_VALUE
, "glAsyncTexSubImage2DCHROMIUM", "size to large");
3727 // Async uploads require a transfer buffer to be bound.
3728 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3729 // the buffer before the transfer is finished. (Currently such
3730 // synchronization has to be handled manually.)
3731 GLuint offset
= ToGLuint(pixels
);
3732 BufferTracker::Buffer
* buffer
= GetBoundPixelUnpackTransferBufferIfValid(
3733 bound_pixel_unpack_transfer_buffer_id_
,
3734 "glAsyncTexSubImage2DCHROMIUM", offset
, size
);
3735 if (buffer
&& buffer
->shm_id() != -1) {
3736 helper_
->AsyncTexSubImage2DCHROMIUM(
3737 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
,
3738 buffer
->shm_id(), buffer
->shm_offset() + offset
);
3742 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target
) {
3743 GPU_CLIENT_SINGLE_THREAD_CHECK();
3744 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
3745 << GLES2Util::GetStringTextureTarget(target
) << ")");
3746 helper_
->WaitAsyncTexImage2DCHROMIUM(target
);
3750 GLuint
GLES2Implementation::InsertSyncPointCHROMIUM() {
3751 GPU_CLIENT_SINGLE_THREAD_CHECK();
3752 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM");
3753 helper_
->CommandBufferHelper::Flush();
3754 return gpu_control_
->InsertSyncPoint();
3757 GLuint
GLES2Implementation::CreateImageCHROMIUMHelper(
3758 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3760 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "width <= 0");
3765 SetGLError(GL_INVALID_VALUE
, "glCreateImageCHROMIUM", "height <= 0");
3768 // Flush the command stream to ensure ordering in case the newly
3769 // returned image_id has recently been in use with a different buffer.
3770 helper_
->CommandBufferHelper::Flush();
3772 // Create new buffer.
3773 GLuint buffer_id
= gpu_memory_buffer_tracker_
->CreateBuffer(
3774 width
, height
, internalformat
);
3775 if (buffer_id
== 0) {
3776 SetGLError(GL_OUT_OF_MEMORY
, "glCreateImageCHROMIUM", "out of GPU memory.");
3782 GLuint
GLES2Implementation::CreateImageCHROMIUM(
3783 GLsizei width
, GLsizei height
, GLenum internalformat
) {
3784 GPU_CLIENT_SINGLE_THREAD_CHECK();
3785 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM("
3788 << GLES2Util::GetStringTextureInternalFormat(internalformat
) << ")");
3789 GLuint image_id
= CreateImageCHROMIUMHelper(width
, height
, internalformat
);
3794 void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id
) {
3795 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3798 SetGLError(GL_INVALID_OPERATION
, "glDestroyImageCHROMIUM", "invalid image");
3802 // Flush the command stream to make sure all pending commands
3803 // that may refer to the image_id are executed on the service side.
3804 helper_
->CommandBufferHelper::Flush();
3805 gpu_memory_buffer_tracker_
->RemoveBuffer(image_id
);
3808 void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id
) {
3809 GPU_CLIENT_SINGLE_THREAD_CHECK();
3810 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM("
3811 << image_id
<< ")");
3812 DestroyImageCHROMIUMHelper(image_id
);
3816 void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id
) {
3817 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3820 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "invalid image");
3824 if (!gpu_buffer
->IsMapped()) {
3825 SetGLError(GL_INVALID_OPERATION
, "glUnmapImageCHROMIUM", "not mapped");
3828 gpu_buffer
->Unmap();
3831 void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id
) {
3832 GPU_CLIENT_SINGLE_THREAD_CHECK();
3833 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM("
3834 << image_id
<< ")");
3836 UnmapImageCHROMIUMHelper(image_id
);
3840 void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id
,
3842 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3845 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "invalid image");
3848 gfx::GpuMemoryBuffer::AccessMode mode
;
3851 mode
= gfx::GpuMemoryBuffer::WRITE_ONLY
;
3854 mode
= gfx::GpuMemoryBuffer::READ_ONLY
;
3857 mode
= gfx::GpuMemoryBuffer::READ_WRITE
;
3860 SetGLError(GL_INVALID_ENUM
, "glMapImageCHROMIUM",
3861 "invalid GPU access mode");
3865 if (gpu_buffer
->IsMapped()) {
3866 SetGLError(GL_INVALID_OPERATION
, "glMapImageCHROMIUM", "already mapped");
3870 void* mapped_buffer
= NULL
;
3871 gpu_buffer
->Map(mode
, &mapped_buffer
);
3872 return mapped_buffer
;
3875 void* GLES2Implementation::MapImageCHROMIUM(
3876 GLuint image_id
, GLenum access
) {
3877 GPU_CLIENT_SINGLE_THREAD_CHECK();
3878 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM("
3880 << GLES2Util::GetStringEnum(access
) << ")");
3882 void* mapped
= MapImageCHROMIUMHelper(image_id
, access
);
3887 void GLES2Implementation::GetImageParameterivCHROMIUMHelper(
3888 GLuint image_id
, GLenum pname
, GLint
* params
) {
3889 if (pname
!= GL_IMAGE_ROWBYTES_CHROMIUM
) {
3890 SetGLError(GL_INVALID_ENUM
, "glGetImageParameterivCHROMIUM",
3891 "invalid parameter");
3895 gfx::GpuMemoryBuffer
* gpu_buffer
= gpu_memory_buffer_tracker_
->GetBuffer(
3898 SetGLError(GL_INVALID_OPERATION
, "glGetImageParameterivCHROMIUM",
3903 *params
= gpu_buffer
->GetStride();
3906 void GLES2Implementation::GetImageParameterivCHROMIUM(
3907 GLuint image_id
, GLenum pname
, GLint
* params
) {
3908 GPU_CLIENT_SINGLE_THREAD_CHECK();
3909 GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint
, params
);
3910 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glImageParameterivCHROMIUM("
3912 << GLES2Util::GetStringBufferParameter(pname
) << ", "
3913 << static_cast<const void*>(params
) << ")");
3914 GetImageParameterivCHROMIUMHelper(image_id
, pname
, params
);
3918 // Include the auto-generated part of this file. We split this because it means
3919 // we can easily edit the non-auto generated parts right here in this file
3920 // instead of having to edit some template or the code generator.
3921 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
3923 } // namespace gles2