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 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
16 #include "base/at_exit.h"
17 #include "base/atomicops.h"
18 #include "base/bind.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #if defined(OS_MACOSX)
22 #include "base/mac/scoped_cftyperef.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/mailbox_manager.h"
49 #include "gpu/command_buffer/service/memory_tracking.h"
50 #include "gpu/command_buffer/service/program_manager.h"
51 #include "gpu/command_buffer/service/query_manager.h"
52 #include "gpu/command_buffer/service/renderbuffer_manager.h"
53 #include "gpu/command_buffer/service/shader_manager.h"
54 #include "gpu/command_buffer/service/shader_translator.h"
55 #include "gpu/command_buffer/service/shader_translator_cache.h"
56 #include "gpu/command_buffer/service/stream_texture.h"
57 #include "gpu/command_buffer/service/stream_texture_manager.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "ui/gl/gl_bindings.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include "ui/gl/io_surface_support_mac.h"
71 // TODO(zmo): we can't include "City.h" due to type def conflicts.
72 extern uint64
CityHash64(const char*, size_t);
79 static const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
80 static const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
81 static const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
83 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
84 khronos_uint64_t
CityHashForAngle(const char* name
, unsigned int len
) {
85 return static_cast<khronos_uint64_t
>(
86 CityHash64(name
, static_cast<size_t>(len
)));
90 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
93 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
96 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
97 GLenum precision_type
,
98 GLint
*range
, GLint
*precision
) {
99 switch (precision_type
) {
103 // These values are for a 32-bit twos-complement integer format.
109 case GL_MEDIUM_FLOAT
:
111 // These values are for an IEEE single-precision floating-point format.
121 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
122 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
123 // This function is sometimes defined even though it's really just
124 // a stub, so we need to set range and precision as if it weren't
125 // defined before calling it.
126 // On Mac OS with some GPUs, calling this generates a
127 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
129 glGetShaderPrecisionFormat(shader_type
, precision_type
,
132 // TODO(brianderson): Make the following official workarounds.
134 // Some drivers have bugs where they report the ranges as a negative number.
135 // Taking the absolute value here shouldn't hurt because negative numbers
136 // aren't expected anyway.
137 range
[0] = abs(range
[0]);
138 range
[1] = abs(range
[1]);
140 // If the driver reports a precision for highp float that isn't actually
141 // highp, don't pretend like it's supported because shader compilation will
143 if (precision_type
== GL_HIGH_FLOAT
&&
144 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
154 class GLES2DecoderImpl
;
156 // Local versions of the SET_GL_ERROR macros
157 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
158 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
159 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
160 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
161 function_name, value, label)
162 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
163 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
164 function_name, pname)
165 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
166 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
168 #define LOCAL_PEEK_GL_ERROR(function_name) \
169 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
170 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
171 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
172 #define LOCAL_PERFORMANCE_WARNING(msg) \
173 PerformanceWarning(__FILE__, __LINE__, msg)
174 #define LOCAL_RENDER_WARNING(msg) \
175 RenderWarning(__FILE__, __LINE__, msg)
177 // Check that certain assumptions the code makes are true. There are places in
178 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
179 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
180 // a few others) are 32bits. If they are not 32bits the code will have to change
181 // to call those GL functions with service side memory and then copy the results
182 // to shared memory, converting the sizes.
183 COMPILE_ASSERT(sizeof(GLint
) == sizeof(uint32
), // NOLINT
184 GLint_not_same_size_as_uint32
);
185 COMPILE_ASSERT(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
186 GLint_not_same_size_as_uint32
);
187 COMPILE_ASSERT(sizeof(GLfloat
) == sizeof(float), // NOLINT
188 GLfloat_not_same_size_as_float
);
190 // TODO(kbr): the use of this anonymous namespace core dumps the
191 // linker on Mac OS X 10.6 when the symbol ordering file is used
194 // Returns the address of the first byte after a struct.
195 template <typename T
>
196 const void* AddressAfterStruct(const T
& pod
) {
197 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
200 // Returns the address of the frst byte after the struct or NULL if size >
201 // immediate_data_size.
202 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
203 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
205 uint32 immediate_data_size
) {
206 return (size
<= immediate_data_size
) ?
207 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
211 // Computes the data size for certain gl commands like glUniform.
212 bool ComputeDataSize(
215 unsigned int elements_per_unit
,
218 if (!SafeMultiplyUint32(count
, size
, &value
)) {
221 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
228 // A struct to hold info about each command.
230 int arg_flags
; // How to handle the arguments for this command
231 int arg_count
; // How many arguments are expected for this command.
234 // A table of CommandInfo for all the commands.
235 const CommandInfo g_command_info
[] = {
236 #define GLES2_CMD_OP(name) { \
237 cmds::name::kArgFlags, \
238 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
240 GLES2_COMMAND_LIST(GLES2_CMD_OP)
245 // Return true if a character belongs to the ASCII subset as defined in
246 // GLSL ES 1.0 spec section 3.1.
247 static bool CharacterIsValidForGLES(unsigned char c
) {
248 // Printing characters are valid except " $ ` @ \ ' DEL.
249 if (c
>= 32 && c
<= 126 &&
258 // Horizontal tab, line feed, vertical tab, form feed, carriage return
260 if (c
>= 9 && c
<= 13) {
267 static bool StringIsValidForGLES(const char* str
) {
268 for (; *str
; ++str
) {
269 if (!CharacterIsValidForGLES(*str
)) {
276 // Wrapper for glEnable/glDisable that doesn't suck.
277 static void EnableDisable(GLenum pname
, bool enable
) {
285 // This class prevents any GL errors that occur when it is in scope from
286 // being reported to the client.
287 class ScopedGLErrorSuppressor
{
289 explicit ScopedGLErrorSuppressor(
290 const char* function_name
, GLES2DecoderImpl
* decoder
);
291 ~ScopedGLErrorSuppressor();
293 const char* function_name_
;
294 GLES2DecoderImpl
* decoder_
;
295 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
298 // Temporarily changes a decoder's bound 2D texture and restore it when this
299 // object goes out of scope. Also temporarily switches to using active texture
300 // unit zero in case the client has changed that to something invalid.
301 class ScopedTexture2DBinder
{
303 ScopedTexture2DBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
304 ~ScopedTexture2DBinder();
307 GLES2DecoderImpl
* decoder_
;
308 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder
);
311 // Temporarily changes a decoder's bound render buffer and restore it when this
312 // object goes out of scope.
313 class ScopedRenderBufferBinder
{
315 ScopedRenderBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
316 ~ScopedRenderBufferBinder();
319 GLES2DecoderImpl
* decoder_
;
320 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
323 // Temporarily changes a decoder's bound frame buffer and restore it when this
324 // object goes out of scope.
325 class ScopedFrameBufferBinder
{
327 ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
328 ~ScopedFrameBufferBinder();
331 GLES2DecoderImpl
* decoder_
;
332 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
335 // Temporarily changes a decoder's bound frame buffer to a resolved version of
336 // the multisampled offscreen render buffer if that buffer is multisampled, and,
337 // if it is bound or enforce_internal_framebuffer is true. If internal is
338 // true, the resolved framebuffer is not visible to the parent.
339 class ScopedResolvedFrameBufferBinder
{
341 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
342 bool enforce_internal_framebuffer
,
344 ~ScopedResolvedFrameBufferBinder();
347 GLES2DecoderImpl
* decoder_
;
348 bool resolve_and_bind_
;
349 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
352 // This class records texture upload time when in scope.
353 class ScopedTextureUploadTimer
{
355 explicit ScopedTextureUploadTimer(GLES2DecoderImpl
* decoder
);
356 ~ScopedTextureUploadTimer();
359 GLES2DecoderImpl
* decoder_
;
360 base::TimeTicks begin_time_
;
361 DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer
);
364 // Encapsulates an OpenGL texture.
367 explicit BackTexture(GLES2DecoderImpl
* decoder
);
370 // Create a new render texture.
373 // Set the initial size and format of a render texture or resize it.
374 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
376 // Copy the contents of the currently bound frame buffer.
377 void Copy(const gfx::Size
& size
, GLenum format
);
379 // Destroy the render texture. This must be explicitly called before
380 // destroying this object.
383 // Invalidate the texture. This can be used when a context is lost and it is
384 // not possible to make it current in order to free the resource.
391 gfx::Size
size() const {
395 size_t estimated_size() const {
396 return memory_tracker_
.GetMemRepresented();
400 GLES2DecoderImpl
* decoder_
;
401 MemoryTypeTracker memory_tracker_
;
402 size_t bytes_allocated_
;
405 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
408 // Encapsulates an OpenGL render buffer of any format.
409 class BackRenderbuffer
{
411 explicit BackRenderbuffer(GLES2DecoderImpl
* decoder
);
414 // Create a new render buffer.
417 // Set the initial size and format of a render buffer or resize it.
418 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, GLsizei samples
);
420 // Destroy the render buffer. This must be explicitly called before destroying
424 // Invalidate the render buffer. This can be used when a context is lost and
425 // it is not possible to make it current in order to free the resource.
432 size_t estimated_size() const {
433 return memory_tracker_
.GetMemRepresented();
437 GLES2DecoderImpl
* decoder_
;
438 MemoryTypeTracker memory_tracker_
;
439 size_t bytes_allocated_
;
441 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
444 // Encapsulates an OpenGL frame buffer.
445 class BackFramebuffer
{
447 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
450 // Create a new frame buffer.
453 // Attach a color render buffer to a frame buffer.
454 void AttachRenderTexture(BackTexture
* texture
);
456 // Attach a render buffer to a frame buffer. Note that this unbinds any
457 // currently bound frame buffer.
458 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
460 // Destroy the frame buffer. This must be explicitly called before destroying
464 // Invalidate the frame buffer. This can be used when a context is lost and it
465 // is not possible to make it current in order to free the resource.
468 // See glCheckFramebufferStatusEXT.
469 GLenum
CheckStatus();
476 GLES2DecoderImpl
* decoder_
;
478 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
481 struct FenceCallback
{
482 explicit FenceCallback()
483 : fence(gfx::GLFence::Create()) {
486 void AddCallback(base::Closure cb
) {
487 callbacks
.push_back(cb
);
489 std::vector
<base::Closure
> callbacks
;
490 scoped_ptr
<gfx::GLFence
> fence
;
494 // } // anonymous namespace.
496 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
497 uint32
* service_texture_id
) {
501 GLES2Decoder::GLES2Decoder()
502 : initialized_(false),
504 log_commands_(false) {
507 GLES2Decoder::~GLES2Decoder() {
510 bool GLES2Decoder::testing_force_is_angle_
;
512 void GLES2Decoder::set_testing_force_is_angle(bool force
) {
513 testing_force_is_angle_
= force
;
516 bool GLES2Decoder::IsAngle() {
518 return testing_force_is_angle_
||
519 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
;
521 return testing_force_is_angle_
;
525 // This class implements GLES2Decoder so we don't have to expose all the GLES2
526 // cmd stuff to outside this class.
527 class GLES2DecoderImpl
: public GLES2Decoder
{
529 // Used by PrepForSetUniformByLocation to validate types.
530 struct BaseUniformInfo
{
531 const GLenum
* const valid_types
;
532 size_t num_valid_types
;
535 explicit GLES2DecoderImpl(ContextGroup
* group
);
536 virtual ~GLES2DecoderImpl();
538 // Overridden from AsyncAPIInterface.
539 virtual Error
DoCommand(unsigned int command
,
540 unsigned int arg_count
,
541 const void* args
) OVERRIDE
;
543 // Overridden from AsyncAPIInterface.
544 virtual const char* GetCommandName(unsigned int command_id
) const OVERRIDE
;
546 // Overridden from GLES2Decoder.
547 virtual bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
548 const scoped_refptr
<gfx::GLContext
>& context
,
550 const gfx::Size
& size
,
551 const DisallowedFeatures
& disallowed_features
,
552 const char* allowed_extensions
,
553 const std::vector
<int32
>& attribs
) OVERRIDE
;
554 virtual void Destroy(bool have_context
) OVERRIDE
;
555 virtual void SetSurface(
556 const scoped_refptr
<gfx::GLSurface
>& surface
) OVERRIDE
;
557 virtual bool ProduceFrontBuffer(const Mailbox
& mailbox
) OVERRIDE
;
558 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) OVERRIDE
;
559 void UpdateParentTextureInfo();
560 virtual bool MakeCurrent() OVERRIDE
;
561 virtual void ReleaseCurrent() OVERRIDE
;
562 virtual GLES2Util
* GetGLES2Util() OVERRIDE
{ return &util_
; }
563 virtual gfx::GLContext
* GetGLContext() OVERRIDE
{ return context_
.get(); }
564 virtual ContextGroup
* GetContextGroup() OVERRIDE
{ return group_
.get(); }
565 virtual void RestoreState() const OVERRIDE
;
567 virtual void RestoreActiveTexture() const OVERRIDE
{
568 state_
.RestoreActiveTexture();
570 virtual void RestoreAllTextureUnitBindings() const OVERRIDE
{
571 state_
.RestoreAllTextureUnitBindings();
573 virtual void RestoreAttribute(unsigned index
) const OVERRIDE
{
574 state_
.RestoreAttribute(index
);
576 virtual void RestoreBufferBindings() const OVERRIDE
{
577 state_
.RestoreBufferBindings();
579 virtual void RestoreGlobalState() const OVERRIDE
{
580 state_
.RestoreGlobalState();
582 virtual void RestoreProgramBindings() const OVERRIDE
{
583 state_
.RestoreProgramBindings();
585 virtual void RestoreRenderbufferBindings() const OVERRIDE
{
586 state_
.RestoreRenderbufferBindings();
588 virtual void RestoreTextureUnitBindings(unsigned unit
) const OVERRIDE
{
589 state_
.RestoreTextureUnitBindings(unit
);
591 virtual void RestoreFramebufferBindings() const OVERRIDE
;
592 virtual void RestoreTextureState(unsigned service_id
) const OVERRIDE
;
594 virtual QueryManager
* GetQueryManager() OVERRIDE
{
595 return query_manager_
.get();
597 virtual VertexArrayManager
* GetVertexArrayManager() OVERRIDE
{
598 return vertex_array_manager_
.get();
600 virtual bool ProcessPendingQueries() OVERRIDE
;
601 virtual bool HasMoreIdleWork() OVERRIDE
;
602 virtual void PerformIdleWork() OVERRIDE
;
604 virtual void WaitForReadPixels(base::Closure callback
) OVERRIDE
;
606 virtual void SetResizeCallback(
607 const base::Callback
<void(gfx::Size
, float)>& callback
) OVERRIDE
;
609 virtual Logger
* GetLogger() OVERRIDE
;
610 virtual ErrorState
* GetErrorState() OVERRIDE
;
612 virtual void SetShaderCacheCallback(
613 const ShaderCacheCallback
& callback
) OVERRIDE
;
614 virtual void SetWaitSyncPointCallback(
615 const WaitSyncPointCallback
& callback
) OVERRIDE
;
617 virtual AsyncPixelTransferManager
*
618 GetAsyncPixelTransferManager() OVERRIDE
;
619 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE
;
620 virtual void SetAsyncPixelTransferManagerForTest(
621 AsyncPixelTransferManager
* manager
) OVERRIDE
;
622 void ProcessFinishedAsyncTransfers();
624 virtual bool GetServiceTextureId(uint32 client_texture_id
,
625 uint32
* service_texture_id
) OVERRIDE
;
627 virtual uint32
GetTextureUploadCount() OVERRIDE
;
628 virtual base::TimeDelta
GetTotalTextureUploadTime() OVERRIDE
;
629 virtual base::TimeDelta
GetTotalProcessingCommandsTime() OVERRIDE
;
630 virtual void AddProcessingCommandsTime(base::TimeDelta
) OVERRIDE
;
632 // Restores the current state to the user's settings.
633 void RestoreCurrentFramebufferBindings();
634 void RestoreCurrentRenderbufferBindings();
635 void RestoreCurrentTexture2DBindings();
637 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
638 void ApplyDirtyState();
640 // These check the state of the currently bound framebuffer or the
641 // backbuffer if no framebuffer is bound.
642 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
643 // check with all attached and enabled color attachments.
644 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
645 bool BoundFramebufferHasDepthAttachment();
646 bool BoundFramebufferHasStencilAttachment();
648 virtual error::ContextLostReason
GetContextLostReason() OVERRIDE
;
651 friend class ScopedFrameBufferBinder
;
652 friend class ScopedGLErrorSuppressor
;
653 friend class ScopedResolvedFrameBufferBinder
;
654 friend class ScopedTextureUploadTimer
;
655 friend class BackTexture
;
656 friend class BackRenderbuffer
;
657 friend class BackFramebuffer
;
659 // Initialize or re-initialize the shader translator.
660 bool InitializeShaderTranslator();
662 void UpdateCapabilities();
664 // Helpers for the glGen and glDelete functions.
665 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
666 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
667 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
668 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
669 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
670 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
671 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
672 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
673 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
674 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
675 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
676 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
679 void OnFboChanged() const;
680 void OnUseFramebuffer() const;
682 // TODO(gman): Cache these pointers?
683 BufferManager
* buffer_manager() {
684 return group_
->buffer_manager();
687 RenderbufferManager
* renderbuffer_manager() {
688 return group_
->renderbuffer_manager();
691 FramebufferManager
* framebuffer_manager() {
692 return group_
->framebuffer_manager();
695 ProgramManager
* program_manager() {
696 return group_
->program_manager();
699 ShaderManager
* shader_manager() {
700 return group_
->shader_manager();
703 const TextureManager
* texture_manager() const {
704 return group_
->texture_manager();
707 TextureManager
* texture_manager() {
708 return group_
->texture_manager();
711 MailboxManager
* mailbox_manager() {
712 return group_
->mailbox_manager();
715 ImageManager
* image_manager() {
716 return group_
->image_manager();
719 VertexArrayManager
* vertex_array_manager() {
720 return vertex_array_manager_
.get();
723 MemoryTracker
* memory_tracker() {
724 return group_
->memory_tracker();
727 StreamTextureManager
* stream_texture_manager() const {
728 return group_
->stream_texture_manager();
731 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
732 MemoryTracker
* tracker
= memory_tracker();
734 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
739 bool IsOffscreenBufferMultisampled() const {
740 return offscreen_target_samples_
> 1;
743 // Creates a Texture for the given texture.
744 TextureRef
* CreateTexture(
745 GLuint client_id
, GLuint service_id
) {
746 return texture_manager()->CreateTexture(client_id
, service_id
);
749 // Gets the texture info for the given texture. Returns NULL if none exists.
750 TextureRef
* GetTexture(GLuint client_id
) const {
751 return texture_manager()->GetTexture(client_id
);
754 // Deletes the texture info for the given texture.
755 void RemoveTexture(GLuint client_id
) {
756 texture_manager()->RemoveTexture(client_id
);
759 // Get the size (in pixels) of the currently bound frame buffer (either FBO
760 // or regular back buffer).
761 gfx::Size
GetBoundReadFrameBufferSize();
763 // Get the format of the currently bound frame buffer (either FBO or regular
765 GLenum
GetBoundReadFrameBufferInternalFormat();
766 GLenum
GetBoundDrawFrameBufferInternalFormat();
768 // Wrapper for CompressedTexImage2D commands.
769 error::Error
DoCompressedTexImage2D(
772 GLenum internal_format
,
779 // Wrapper for CompressedTexSubImage2D.
780 void DoCompressedTexSubImage2D(
791 // Wrapper for CopyTexImage2D.
792 void DoCopyTexImage2D(
795 GLenum internal_format
,
802 // Wrapper for SwapBuffers.
803 void DoSwapBuffers();
805 // Wrapper for CopyTexSubImage2D.
806 void DoCopyTexSubImage2D(
816 // Validation for TexImage2D commands.
817 bool ValidateTexImage2D(
818 const char* function_name
,
821 GLenum internal_format
,
830 // Wrapper for TexImage2D commands.
834 GLenum internal_format
,
843 // Validation for TexSubImage2D.
844 bool ValidateTexSubImage2D(
846 const char* function_name
,
857 // Wrapper for TexSubImage2D.
858 error::Error
DoTexSubImage2D(
869 // Extra validation for async tex(Sub)Image2D.
870 bool ValidateAsyncTransfer(
871 const char* function_name
,
872 TextureRef
* texture_ref
,
877 // Wrapper for TexImageIOSurface2DCHROMIUM.
878 void DoTexImageIOSurface2DCHROMIUM(
882 GLuint io_surface_id
,
885 void DoCopyTextureCHROMIUM(
890 GLenum internal_format
,
893 // Wrapper for TexStorage2DEXT.
894 void DoTexStorage2DEXT(
897 GLenum internal_format
,
901 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
902 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
904 void DoBindTexImage2DCHROMIUM(
907 void DoReleaseTexImage2DCHROMIUM(
911 void DoTraceEndCHROMIUM(void);
913 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
915 // Creates a Program for the given program.
916 Program
* CreateProgram(
917 GLuint client_id
, GLuint service_id
) {
918 return program_manager()->CreateProgram(client_id
, service_id
);
921 // Gets the program info for the given program. Returns NULL if none exists.
922 Program
* GetProgram(GLuint client_id
) {
923 return program_manager()->GetProgram(client_id
);
927 void LogClientServiceMapping(
928 const char* /* function_name */,
929 GLuint
/* client_id */,
930 GLuint
/* service_id */) {
933 void LogClientServiceForInfo(
934 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
937 void LogClientServiceMapping(
938 const char* function_name
, GLuint client_id
, GLuint service_id
) {
939 if (service_logging_
) {
940 DLOG(INFO
) << "[" << logger_
.GetLogPrefix() << "] " << function_name
941 << ": client_id = " << client_id
942 << ", service_id = " << service_id
;
946 void LogClientServiceForInfo(
947 T
* info
, GLuint client_id
, const char* function_name
) {
949 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
954 // Gets the program info for the given program. If it's not a program
955 // generates a GL error. Returns NULL if not program.
956 Program
* GetProgramInfoNotShader(
957 GLuint client_id
, const char* function_name
) {
958 Program
* program
= GetProgram(client_id
);
960 if (GetShader(client_id
)) {
962 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
967 LogClientServiceForInfo(program
, client_id
, function_name
);
972 // Creates a Shader for the given shader.
973 Shader
* CreateShader(
976 GLenum shader_type
) {
977 return shader_manager()->CreateShader(
978 client_id
, service_id
, shader_type
);
981 // Gets the shader info for the given shader. Returns NULL if none exists.
982 Shader
* GetShader(GLuint client_id
) {
983 return shader_manager()->GetShader(client_id
);
986 // Gets the shader info for the given shader. If it's not a shader generates a
987 // GL error. Returns NULL if not shader.
988 Shader
* GetShaderInfoNotProgram(
989 GLuint client_id
, const char* function_name
) {
990 Shader
* shader
= GetShader(client_id
);
992 if (GetProgram(client_id
)) {
994 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
997 GL_INVALID_VALUE
, function_name
, "unknown shader");
1000 LogClientServiceForInfo(shader
, client_id
, function_name
);
1004 // Creates a buffer info for the given buffer.
1005 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1006 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1009 // Gets the buffer info for the given buffer.
1010 Buffer
* GetBuffer(GLuint client_id
) {
1011 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1015 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1016 // on glDeleteBuffers so we can make sure the user does not try to render
1017 // with deleted buffers.
1018 void RemoveBuffer(GLuint client_id
);
1020 // Creates a framebuffer info for the given framebuffer.
1021 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1022 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1025 // Gets the framebuffer info for the given framebuffer.
1026 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1027 return framebuffer_manager()->GetFramebuffer(client_id
);
1030 // Removes the framebuffer info for the given framebuffer.
1031 void RemoveFramebuffer(GLuint client_id
) {
1032 framebuffer_manager()->RemoveFramebuffer(client_id
);
1035 // Creates a renderbuffer info for the given renderbuffer.
1036 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1037 return renderbuffer_manager()->CreateRenderbuffer(
1038 client_id
, service_id
);
1041 // Gets the renderbuffer info for the given renderbuffer.
1042 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1043 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1046 // Removes the renderbuffer info for the given renderbuffer.
1047 void RemoveRenderbuffer(GLuint client_id
) {
1048 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1051 // Gets the vertex attrib manager for the given vertex array.
1052 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1053 VertexAttribManager
* info
=
1054 vertex_array_manager()->GetVertexAttribManager(client_id
);
1058 // Removes the vertex attrib manager for the given vertex array.
1059 void RemoveVertexAttribManager(GLuint client_id
) {
1060 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1063 // Creates a vertex attrib manager for the given vertex array.
1064 void CreateVertexAttribManager(GLuint client_id
, GLuint service_id
) {
1065 return vertex_array_manager()->CreateVertexAttribManager(
1066 client_id
, service_id
, group_
->max_vertex_attribs());
1069 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1070 void DoBindUniformLocationCHROMIUM(
1071 GLuint client_id
, GLint location
, const char* name
);
1073 error::Error
GetAttribLocationHelper(
1074 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1075 const std::string
& name_str
);
1077 error::Error
GetUniformLocationHelper(
1078 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1079 const std::string
& name_str
);
1081 // Helper for glShaderSource.
1082 error::Error
ShaderSourceHelper(
1083 GLuint client_id
, const char* data
, uint32 data_size
);
1085 // Clear any textures used by the current program.
1086 bool ClearUnclearedTextures();
1088 // Clear any uncleared level in texture.
1089 // Returns false if there was a generated GL error.
1090 bool ClearTexture(Texture
* texture
);
1092 // Clears any uncleared attachments attached to the given frame buffer.
1093 // Returns false if there was a generated GL error.
1094 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1096 // overridden from GLES2Decoder
1097 virtual bool ClearLevel(unsigned service_id
,
1098 unsigned bind_target
,
1105 bool is_texture_immutable
) OVERRIDE
;
1107 // Restore all GL state that affects clearing.
1108 void RestoreClearState();
1110 // Remembers the state of some capabilities.
1111 // Returns: true if glEnable/glDisable should actually be called.
1112 bool SetCapabilityState(GLenum cap
, bool enabled
);
1114 // Check that the currently bound framebuffers are valid.
1115 // Generates GL error if not.
1116 bool CheckBoundFramebuffersValid(const char* func_name
);
1118 // Check if a framebuffer meets our requirements.
1119 bool CheckFramebufferValid(
1120 Framebuffer
* framebuffer
,
1122 const char* func_name
);
1124 // Checks if the current program exists and is valid. If not generates the
1125 // appropriate GL error. Returns true if the current program is in a usable
1127 bool CheckCurrentProgram(const char* function_name
);
1129 // Checks if the current program exists and is valid and that location is not
1130 // -1. If the current program is not valid generates the appropriate GL
1131 // error. Returns true if the current program is in a usable state and
1132 // location is not -1.
1133 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1135 // Gets the type of a uniform for a location in the current program. Sets GL
1136 // errors if the current program is not valid. Returns true if the current
1137 // program is valid and the location exists. Adjusts count so it
1138 // does not overflow the uniform.
1139 bool PrepForSetUniformByLocation(
1140 GLint fake_location
, const char* function_name
,
1141 const BaseUniformInfo
& base_info
,
1142 GLint
* real_location
, GLenum
* type
, GLsizei
* count
);
1144 // Gets the service id for any simulated backbuffer fbo.
1145 GLuint
GetBackbufferServiceId() const;
1147 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1148 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1150 // Helper for glGetVertexAttrib
1151 void GetVertexAttribHelper(
1152 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1154 // Wrapper for glCreateProgram
1155 bool CreateProgramHelper(GLuint client_id
);
1157 // Wrapper for glCreateShader
1158 bool CreateShaderHelper(GLenum type
, GLuint client_id
);
1160 // Wrapper for glActiveTexture
1161 void DoActiveTexture(GLenum texture_unit
);
1163 // Wrapper for glAttachShader
1164 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1166 // Wrapper for glBindBuffer since we need to track the current targets.
1167 void DoBindBuffer(GLenum target
, GLuint buffer
);
1169 // Wrapper for glBindFramebuffer since we need to track the current targets.
1170 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1172 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1173 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1175 // Wrapper for glBindTexture since we need to track the current targets.
1176 void DoBindTexture(GLenum target
, GLuint texture
);
1178 // Wrapper for glBindVertexArrayOES
1179 void DoBindVertexArrayOES(GLuint array
);
1180 void EmulateVertexArrayState();
1182 // Wrapper for glBlitFramebufferEXT.
1183 void DoBlitFramebufferEXT(
1184 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1185 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1186 GLbitfield mask
, GLenum filter
);
1188 // Wrapper for glBufferData.
1190 GLenum target
, GLsizeiptr size
, const GLvoid
* data
, GLenum usage
);
1192 // Wrapper for glBufferSubData.
1193 void DoBufferSubData(
1194 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1196 // Wrapper for glCheckFramebufferStatus
1197 GLenum
DoCheckFramebufferStatus(GLenum target
);
1199 // Wrapper for glClear
1200 error::Error
DoClear(GLbitfield mask
);
1202 // Wrappers for various state.
1203 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1204 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1206 // Wrapper for glCompileShader.
1207 void DoCompileShader(GLuint shader
);
1209 // Helper for DeleteSharedIdsCHROMIUM commands.
1210 void DoDeleteSharedIdsCHROMIUM(
1211 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1213 // Wrapper for glDetachShader
1214 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1216 // Wrapper for glDisable
1217 void DoDisable(GLenum cap
);
1219 // Wrapper for glDisableVertexAttribArray.
1220 void DoDisableVertexAttribArray(GLuint index
);
1222 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1224 void DoDiscardFramebufferEXT(GLenum target
,
1225 GLsizei numAttachments
,
1226 const GLenum
* attachments
);
1228 // Wrapper for glEnable
1229 void DoEnable(GLenum cap
);
1231 // Wrapper for glEnableVertexAttribArray.
1232 void DoEnableVertexAttribArray(GLuint index
);
1234 // Wrapper for glFinish.
1237 // Wrapper for glFlush.
1240 // Wrapper for glFramebufferRenderbufffer.
1241 void DoFramebufferRenderbuffer(
1242 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1243 GLuint renderbuffer
);
1245 // Wrapper for glFramebufferTexture2D.
1246 void DoFramebufferTexture2D(
1247 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1250 // Wrapper for glGenerateMipmap
1251 void DoGenerateMipmap(GLenum target
);
1253 // Helper for GenSharedIdsCHROMIUM commands.
1254 void DoGenSharedIdsCHROMIUM(
1255 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
);
1257 // Wrapper for DoGetBooleanv.
1258 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1260 // Wrapper for DoGetFloatv.
1261 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1263 // Wrapper for glGetFramebufferAttachmentParameteriv.
1264 void DoGetFramebufferAttachmentParameteriv(
1265 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1267 // Wrapper for glGetIntegerv.
1268 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1270 // Gets the max value in a range in a buffer.
1271 GLuint
DoGetMaxValueInBufferCHROMIUM(
1272 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1274 // Wrapper for glGetBufferParameteriv.
1275 void DoGetBufferParameteriv(
1276 GLenum target
, GLenum pname
, GLint
* params
);
1278 // Wrapper for glGetProgramiv.
1279 void DoGetProgramiv(
1280 GLuint program_id
, GLenum pname
, GLint
* params
);
1282 // Wrapper for glRenderbufferParameteriv.
1283 void DoGetRenderbufferParameteriv(
1284 GLenum target
, GLenum pname
, GLint
* params
);
1286 // Wrapper for glGetShaderiv
1287 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1289 // Wrappers for glGetVertexAttrib.
1290 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1291 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1293 // Wrappers for glIsXXX functions.
1294 bool DoIsEnabled(GLenum cap
);
1295 bool DoIsBuffer(GLuint client_id
);
1296 bool DoIsFramebuffer(GLuint client_id
);
1297 bool DoIsProgram(GLuint client_id
);
1298 bool DoIsRenderbuffer(GLuint client_id
);
1299 bool DoIsShader(GLuint client_id
);
1300 bool DoIsTexture(GLuint client_id
);
1301 bool DoIsVertexArrayOES(GLuint client_id
);
1303 // Wrapper for glLinkProgram
1304 void DoLinkProgram(GLuint program
);
1306 // Helper for RegisterSharedIdsCHROMIUM.
1307 void DoRegisterSharedIdsCHROMIUM(
1308 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1310 // Wrapper for glRenderbufferStorage.
1311 void DoRenderbufferStorage(
1312 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1314 // Wrapper for glRenderbufferStorageMultisampleEXT.
1315 void DoRenderbufferStorageMultisample(
1316 GLenum target
, GLsizei samples
, GLenum internalformat
,
1317 GLsizei width
, GLsizei height
);
1319 // Wrapper for glReleaseShaderCompiler.
1320 void DoReleaseShaderCompiler() { }
1322 // Wrappers for glTexParameter functions.
1323 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1324 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1325 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1326 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1328 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1329 // spec only these 2 functions can be used to set sampler uniforms.
1330 void DoUniform1i(GLint fake_location
, GLint v0
);
1331 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1332 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1333 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1334 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1336 // Wrappers for glUniformfv because some drivers don't correctly accept
1338 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1339 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1340 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1341 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1343 void DoUniformMatrix2fv(
1344 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1345 const GLfloat
* value
);
1346 void DoUniformMatrix3fv(
1347 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1348 const GLfloat
* value
);
1349 void DoUniformMatrix4fv(
1350 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1351 const GLfloat
* value
);
1353 bool SetVertexAttribValue(
1354 const char* function_name
, GLuint index
, const GLfloat
* value
);
1356 // Wrappers for glVertexAttrib??
1357 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1358 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1359 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1360 void DoVertexAttrib4f(
1361 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1362 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1363 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1364 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1365 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1367 // Wrapper for glViewport
1368 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1370 // Wrapper for glUseProgram
1371 void DoUseProgram(GLuint program
);
1373 // Wrapper for glValidateProgram.
1374 void DoValidateProgram(GLuint program_client_id
);
1376 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1377 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1378 void DoPopGroupMarkerEXT(void);
1380 // Gets the number of values that will be returned by glGetXXX. Returns
1381 // false if pname is unknown.
1382 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1384 // Checks if the current program and vertex attributes are valid for drawing.
1386 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
);
1388 // Returns true if successful, simulated will be true if attrib0 was
1390 bool SimulateAttrib0(
1391 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1392 void RestoreStateForAttrib(GLuint attrib
);
1394 // Returns true if textures were set.
1395 bool SetBlackTextureForNonRenderableTextures();
1396 void RestoreStateForNonRenderableTextures();
1398 // Returns true if GL_FIXED attribs were simulated.
1399 bool SimulateFixedAttribs(
1400 const char* function_name
,
1401 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1402 void RestoreStateForSimulatedFixedAttribs();
1404 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1405 // cases (primcount is 0 for non-instanced).
1406 error::Error
DoDrawArrays(
1407 const char* function_name
,
1408 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1410 error::Error
DoDrawElements(
1411 const char* function_name
,
1412 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1413 int32 offset
, GLsizei primcount
);
1415 // Gets the buffer id for a given target.
1416 Buffer
* GetBufferInfoForTarget(GLenum target
) {
1417 DCHECK(target
== GL_ARRAY_BUFFER
|| target
== GL_ELEMENT_ARRAY_BUFFER
);
1418 if (target
== GL_ARRAY_BUFFER
) {
1419 return state_
.bound_array_buffer
.get();
1421 return state_
.vertex_attrib_manager
->element_array_buffer();
1425 // Gets the texture id for a given target.
1426 TextureRef
* GetTextureInfoForTarget(GLenum target
) {
1427 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
1428 TextureRef
* texture
= NULL
;
1431 texture
= unit
.bound_texture_2d
.get();
1433 case GL_TEXTURE_CUBE_MAP
:
1434 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1436 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1437 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1439 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1440 texture
= unit
.bound_texture_cube_map
.get();
1442 case GL_TEXTURE_EXTERNAL_OES
:
1443 texture
= unit
.bound_texture_external_oes
.get();
1445 case GL_TEXTURE_RECTANGLE_ARB
:
1446 texture
= unit
.bound_texture_rectangle_arb
.get();
1455 TextureRef
* GetTextureInfoForTargetUnlessDefault(
1457 TextureRef
* texture
= GetTextureInfoForTarget(target
);
1460 if (texture
== texture_manager()->GetDefaultTextureInfo(target
))
1465 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1466 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1467 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1470 return GL_TEXTURE_2D
;
1471 case GL_SAMPLER_CUBE
:
1472 return GL_TEXTURE_CUBE_MAP
;
1473 case GL_SAMPLER_EXTERNAL_OES
:
1474 return GL_TEXTURE_EXTERNAL_OES
;
1475 case GL_SAMPLER_2D_RECT_ARB
:
1476 return GL_TEXTURE_RECTANGLE_ARB
;
1483 // Gets the framebuffer info for a particular target.
1484 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1485 Framebuffer
* framebuffer
= NULL
;
1487 case GL_FRAMEBUFFER
:
1488 case GL_DRAW_FRAMEBUFFER_EXT
:
1489 framebuffer
= state_
.bound_draw_framebuffer
.get();
1491 case GL_READ_FRAMEBUFFER_EXT
:
1492 framebuffer
= state_
.bound_read_framebuffer
.get();
1501 Renderbuffer
* GetRenderbufferInfoForTarget(
1503 Renderbuffer
* renderbuffer
= NULL
;
1505 case GL_RENDERBUFFER
:
1506 renderbuffer
= state_
.bound_renderbuffer
.get();
1512 return renderbuffer
;
1515 // Validates the program and location for a glGetUniform call and returns
1516 // a SizeResult setup to receive the result. Returns true if glGetUniform
1517 // should be called.
1518 bool GetUniformSetup(
1519 GLuint program
, GLint fake_location
,
1520 uint32 shm_id
, uint32 shm_offset
,
1521 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1522 void** result
, GLenum
* result_type
);
1524 // Computes the estimated memory used for the backbuffer and passes it to
1525 // the tracing system.
1526 size_t GetBackbufferMemoryTotal();
1528 virtual bool WasContextLost() OVERRIDE
;
1529 virtual bool WasContextLostByRobustnessExtension() OVERRIDE
;
1530 virtual void LoseContext(uint32 reset_status
) OVERRIDE
;
1532 #if defined(OS_MACOSX)
1533 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1536 // Validates the combination of texture parameters. For example validates that
1537 // for a given format the specific type, level and targets are valid.
1538 // Synthesizes the correct GL error if invalid. Returns true if valid.
1539 bool ValidateTextureParameters(
1540 const char* function_name
,
1541 GLenum target
, GLenum format
, GLenum type
, GLint level
);
1543 bool ValidateCompressedTexDimensions(
1544 const char* function_name
,
1545 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1546 bool ValidateCompressedTexFuncData(
1547 const char* function_name
,
1548 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1549 bool ValidateCompressedTexSubDimensions(
1550 const char* function_name
,
1551 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1552 GLsizei width
, GLsizei height
, GLenum format
,
1555 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1556 void PerformanceWarning(
1557 const char* filename
, int line
, const std::string
& msg
);
1559 const FeatureInfo::FeatureFlags
& features() const {
1560 return feature_info_
->feature_flags();
1563 const FeatureInfo::Workarounds
& workarounds() const {
1564 return feature_info_
->workarounds();
1567 bool ShouldDeferDraws() {
1568 return !offscreen_target_frame_buffer_
.get() &&
1569 state_
.bound_draw_framebuffer
.get() == NULL
&&
1570 surface_
->DeferDraws();
1573 bool ShouldDeferReads() {
1574 return !offscreen_target_frame_buffer_
.get() &&
1575 state_
.bound_read_framebuffer
.get() == NULL
&&
1576 surface_
->DeferDraws();
1579 void ProcessPendingReadPixels();
1580 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1582 void ForceCompileShaderIfPending(Shader
* shader
);
1584 // Generate a member function prototype for each command in an automated and
1586 #define GLES2_CMD_OP(name) \
1587 Error Handle ## name( \
1588 uint32 immediate_data_size, \
1589 const cmds::name& args); \
1591 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1595 // The GL context this decoder renders to on behalf of the client.
1596 scoped_refptr
<gfx::GLSurface
> surface_
;
1597 scoped_refptr
<gfx::GLContext
> context_
;
1599 // The ContextGroup for this decoder uses to track resources.
1600 scoped_refptr
<ContextGroup
> group_
;
1602 DebugMarkerManager debug_marker_manager_
;
1605 // All the state for this context.
1606 ContextState state_
;
1608 // Current width and height of the offscreen frame buffer.
1609 gfx::Size offscreen_size_
;
1611 // Util to help with GL.
1614 // unpack flip y as last set by glPixelStorei
1615 bool unpack_flip_y_
;
1617 // unpack (un)premultiply alpha as last set by glPixelStorei
1618 bool unpack_premultiply_alpha_
;
1619 bool unpack_unpremultiply_alpha_
;
1621 // Default vertex attribs manager, used when no VAOs are bound.
1622 scoped_refptr
<VertexAttribManager
> default_vertex_attrib_manager_
;
1624 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1625 GLuint attrib_0_buffer_id_
;
1627 // The value currently in attrib_0.
1628 Vec4 attrib_0_value_
;
1630 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1631 bool attrib_0_buffer_matches_value_
;
1633 // The size of attrib 0.
1634 GLsizei attrib_0_size_
;
1636 // The buffer used to simulate GL_FIXED attribs.
1637 GLuint fixed_attrib_buffer_id_
;
1639 // The size of fiixed attrib buffer.
1640 GLsizei fixed_attrib_buffer_size_
;
1642 // state saved for clearing so we can clear render buffers and then
1643 // restore to these values.
1644 bool clear_state_dirty_
;
1646 // The offscreen frame buffer that the client renders to. With EGL, the
1647 // depth and stencil buffers are separate. With regular GL there is a single
1648 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1649 // offscreen_target_stencil_render_buffer_ is unused.
1650 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1651 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1652 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1653 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1654 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1655 GLenum offscreen_target_color_format_
;
1656 GLenum offscreen_target_depth_format_
;
1657 GLenum offscreen_target_stencil_format_
;
1658 GLsizei offscreen_target_samples_
;
1659 GLboolean offscreen_target_buffer_preserved_
;
1661 // The copy that is saved when SwapBuffers is called.
1662 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1663 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1664 scoped_refptr
<TextureRef
>
1665 offscreen_saved_color_texture_info_
;
1667 // The copy that is used as the destination for multi-sample resolves.
1668 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1669 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1670 GLenum offscreen_saved_color_format_
;
1672 scoped_ptr
<QueryManager
> query_manager_
;
1674 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1676 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1678 WaitSyncPointCallback wait_sync_point_callback_
;
1680 ShaderCacheCallback shader_cache_callback_
;
1682 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1684 // The format of the back buffer_
1685 GLenum back_buffer_color_format_
;
1686 bool back_buffer_has_depth_
;
1687 bool back_buffer_has_stencil_
;
1689 // Backbuffer attachments that are currently undefined.
1690 uint32 backbuffer_needs_clear_bits_
;
1692 bool teximage2d_faster_than_texsubimage2d_
;
1694 // The current decoder error.
1695 error::Error current_decoder_error_
;
1697 bool use_shader_translator_
;
1698 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1699 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1701 DisallowedFeatures disallowed_features_
;
1703 // Cached from ContextGroup
1704 const Validators
* validators_
;
1705 scoped_refptr
<FeatureInfo
> feature_info_
;
1707 // This indicates all the following texSubImage2D calls that are part of the
1708 // failed texImage2D call should be ignored.
1709 bool tex_image_2d_failed_
;
1713 bool has_robustness_extension_
;
1714 GLenum reset_status_
;
1715 bool reset_by_robustness_extension_
;
1717 // These flags are used to override the state of the shared feature_info_
1718 // member. Because the same FeatureInfo instance may be shared among many
1719 // contexts, the assumptions on the availablity of extensions in WebGL
1720 // contexts may be broken. These flags override the shared state to preserve
1722 bool force_webgl_glsl_validation_
;
1723 bool derivatives_explicitly_enabled_
;
1724 bool frag_depth_explicitly_enabled_
;
1725 bool draw_buffers_explicitly_enabled_
;
1727 bool compile_shader_always_succeeds_
;
1730 bool service_logging_
;
1732 #if defined(OS_MACOSX)
1733 typedef std::map
<GLuint
, CFTypeRef
> TextureToIOSurfaceMap
;
1734 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1737 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1739 // Cached values of the currently assigned viewport dimensions.
1740 GLsizei viewport_max_width_
;
1741 GLsizei viewport_max_height_
;
1743 // Command buffer stats.
1744 int texture_upload_count_
;
1745 base::TimeDelta total_texture_upload_time_
;
1746 base::TimeDelta total_processing_commands_time_
;
1748 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1750 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1752 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1755 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1756 const char* function_name
, GLES2DecoderImpl
* decoder
)
1757 : function_name_(function_name
),
1759 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_
->GetErrorState(),
1763 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1764 ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_
->GetErrorState(), function_name_
);
1767 ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl
* decoder
,
1769 : decoder_(decoder
) {
1770 ScopedGLErrorSuppressor
suppressor(
1771 "ScopedTexture2DBinder::ctor", decoder_
);
1773 // TODO(apatrick): Check if there are any other states that need to be reset
1774 // before binding a new texture.
1775 glActiveTexture(GL_TEXTURE0
);
1776 glBindTexture(GL_TEXTURE_2D
, id
);
1779 ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1780 ScopedGLErrorSuppressor
suppressor(
1781 "ScopedTexture2DBinder::dtor", decoder_
);
1782 decoder_
->RestoreCurrentTexture2DBindings();
1785 ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl
* decoder
,
1787 : decoder_(decoder
) {
1788 ScopedGLErrorSuppressor
suppressor(
1789 "ScopedRenderBufferBinder::ctor", decoder_
);
1790 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1793 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1794 ScopedGLErrorSuppressor
suppressor(
1795 "ScopedRenderBufferBinder::dtor", decoder_
);
1796 decoder_
->RestoreCurrentRenderbufferBindings();
1799 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
1801 : decoder_(decoder
) {
1802 ScopedGLErrorSuppressor
suppressor(
1803 "ScopedFrameBufferBinder::ctor", decoder_
);
1804 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
1805 decoder
->OnFboChanged();
1808 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1809 ScopedGLErrorSuppressor
suppressor(
1810 "ScopedFrameBufferBinder::dtor", decoder_
);
1811 decoder_
->RestoreCurrentFramebufferBindings();
1814 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1815 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
1816 : decoder_(decoder
) {
1817 resolve_and_bind_
= (decoder_
->offscreen_target_frame_buffer_
.get() &&
1818 decoder_
->IsOffscreenBufferMultisampled() &&
1819 (!decoder_
->state_
.bound_read_framebuffer
.get() ||
1820 enforce_internal_framebuffer
));
1821 if (!resolve_and_bind_
)
1824 ScopedGLErrorSuppressor
suppressor(
1825 "ScopedResolvedFrameBufferBinder::ctor", decoder_
);
1826 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
1827 decoder_
->offscreen_target_frame_buffer_
->id());
1830 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
1831 decoder_
->offscreen_resolved_frame_buffer_
.reset(
1832 new BackFramebuffer(decoder_
));
1833 decoder_
->offscreen_resolved_frame_buffer_
->Create();
1834 decoder_
->offscreen_resolved_color_texture_
.reset(
1835 new BackTexture(decoder_
));
1836 decoder_
->offscreen_resolved_color_texture_
->Create();
1838 DCHECK(decoder_
->offscreen_saved_color_format_
);
1839 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
1840 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
1842 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
1843 decoder_
->offscreen_resolved_color_texture_
.get());
1844 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
1845 GL_FRAMEBUFFER_COMPLETE
) {
1846 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
1847 << "because offscreen resolved FBO was incomplete.";
1851 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
1853 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
1855 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
1856 const int width
= decoder_
->offscreen_size_
.width();
1857 const int height
= decoder_
->offscreen_size_
.height();
1858 glDisable(GL_SCISSOR_TEST
);
1859 if (GLES2Decoder::IsAngle()) {
1860 glBlitFramebufferANGLE(0, 0, width
, height
, 0, 0, width
, height
,
1861 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
1863 glBlitFramebufferEXT(0, 0, width
, height
, 0, 0, width
, height
,
1864 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
1866 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
1869 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1870 if (!resolve_and_bind_
)
1873 ScopedGLErrorSuppressor
suppressor(
1874 "ScopedResolvedFrameBufferBinder::dtor", decoder_
);
1875 decoder_
->RestoreCurrentFramebufferBindings();
1876 if (decoder_
->state_
.enable_flags
.scissor_test
) {
1877 glEnable(GL_SCISSOR_TEST
);
1881 ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl
* decoder
)
1882 : decoder_(decoder
),
1883 begin_time_(base::TimeTicks::HighResNow()) {
1886 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1887 decoder_
->texture_upload_count_
++;
1888 decoder_
->total_texture_upload_time_
+=
1889 base::TimeTicks::HighResNow() - begin_time_
;
1892 BackTexture::BackTexture(GLES2DecoderImpl
* decoder
)
1893 : decoder_(decoder
),
1894 memory_tracker_(decoder
->memory_tracker(), MemoryTracker::kUnmanaged
),
1895 bytes_allocated_(0),
1899 BackTexture::~BackTexture() {
1900 // This does not destroy the render texture because that would require that
1901 // the associated GL context was current. Just check that it was explicitly
1906 void BackTexture::Create() {
1907 ScopedGLErrorSuppressor
suppressor("BackTexture::Create", decoder_
);
1909 glGenTextures(1, &id_
);
1910 ScopedTexture2DBinder
binder(decoder_
, id_
);
1911 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
1912 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1913 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1914 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1916 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1917 // never called on an offscreen context, no data will ever be uploaded to the
1918 // saved offscreen color texture (it is deferred until to when SwapBuffers
1919 // is called). My idea is that some nvidia drivers might have a bug where
1920 // deleting a texture that has never been populated might cause a
1923 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
1925 bytes_allocated_
= 16u * 16u * 4u;
1926 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
1929 bool BackTexture::AllocateStorage(
1930 const gfx::Size
& size
, GLenum format
, bool zero
) {
1932 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage", decoder_
);
1933 ScopedTexture2DBinder
binder(decoder_
, id_
);
1934 uint32 image_size
= 0;
1935 GLES2Util::ComputeImageDataSizes(
1936 size
.width(), size
.height(), format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
1939 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
1943 scoped_ptr
<char[]> zero_data
;
1945 zero_data
.reset(new char[image_size
]);
1946 memset(zero_data
.get(), 0, image_size
);
1949 glTexImage2D(GL_TEXTURE_2D
,
1961 bool success
= glGetError() == GL_NO_ERROR
;
1963 memory_tracker_
.TrackMemFree(bytes_allocated_
);
1964 bytes_allocated_
= image_size
;
1965 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
1970 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
1972 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy", decoder_
);
1973 ScopedTexture2DBinder
binder(decoder_
, id_
);
1974 glCopyTexImage2D(GL_TEXTURE_2D
,
1983 void BackTexture::Destroy() {
1985 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy", decoder_
);
1986 glDeleteTextures(1, &id_
);
1989 memory_tracker_
.TrackMemFree(bytes_allocated_
);
1990 bytes_allocated_
= 0;
1993 void BackTexture::Invalidate() {
1997 BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl
* decoder
)
1998 : decoder_(decoder
),
1999 memory_tracker_(decoder
->memory_tracker(), MemoryTracker::kUnmanaged
),
2000 bytes_allocated_(0),
2004 BackRenderbuffer::~BackRenderbuffer() {
2005 // This does not destroy the render buffer because that would require that
2006 // the associated GL context was current. Just check that it was explicitly
2011 void BackRenderbuffer::Create() {
2012 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create", decoder_
);
2014 glGenRenderbuffersEXT(1, &id_
);
2017 bool BackRenderbuffer::AllocateStorage(const gfx::Size
& size
, GLenum format
,
2019 ScopedGLErrorSuppressor
suppressor(
2020 "BackRenderbuffer::AllocateStorage", decoder_
);
2021 ScopedRenderBufferBinder
binder(decoder_
, id_
);
2023 uint32 estimated_size
= 0;
2024 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
2025 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2029 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2034 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2039 if (GLES2Decoder::IsAngle()) {
2040 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER
,
2046 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER
,
2053 bool success
= glGetError() == GL_NO_ERROR
;
2055 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2056 bytes_allocated_
= estimated_size
;
2057 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2062 void BackRenderbuffer::Destroy() {
2064 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy", decoder_
);
2065 glDeleteRenderbuffersEXT(1, &id_
);
2068 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2069 bytes_allocated_
= 0;
2072 void BackRenderbuffer::Invalidate() {
2076 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2077 : decoder_(decoder
),
2081 BackFramebuffer::~BackFramebuffer() {
2082 // This does not destroy the frame buffer because that would require that
2083 // the associated GL context was current. Just check that it was explicitly
2088 void BackFramebuffer::Create() {
2089 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create", decoder_
);
2091 glGenFramebuffersEXT(1, &id_
);
2094 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2096 ScopedGLErrorSuppressor
suppressor(
2097 "BackFramebuffer::AttachRenderTexture", decoder_
);
2098 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2099 GLuint attach_id
= texture
? texture
->id() : 0;
2100 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2101 GL_COLOR_ATTACHMENT0
,
2107 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2108 BackRenderbuffer
* render_buffer
) {
2110 ScopedGLErrorSuppressor
suppressor(
2111 "BackFramebuffer::AttachRenderBuffer", decoder_
);
2112 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2113 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2114 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2120 void BackFramebuffer::Destroy() {
2122 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy", decoder_
);
2123 glDeleteFramebuffersEXT(1, &id_
);
2128 void BackFramebuffer::Invalidate() {
2132 GLenum
BackFramebuffer::CheckStatus() {
2134 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus", decoder_
);
2135 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2136 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2139 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2140 return new GLES2DecoderImpl(group
);
2143 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2146 logger_(&debug_marker_manager_
),
2147 state_(group_
->feature_info(), &logger_
),
2148 unpack_flip_y_(false),
2149 unpack_premultiply_alpha_(false),
2150 unpack_unpremultiply_alpha_(false),
2151 attrib_0_buffer_id_(0),
2152 attrib_0_buffer_matches_value_(true),
2154 fixed_attrib_buffer_id_(0),
2155 fixed_attrib_buffer_size_(0),
2156 clear_state_dirty_(true),
2157 offscreen_target_color_format_(0),
2158 offscreen_target_depth_format_(0),
2159 offscreen_target_stencil_format_(0),
2160 offscreen_target_samples_(0),
2161 offscreen_target_buffer_preserved_(true),
2162 offscreen_saved_color_format_(0),
2163 back_buffer_color_format_(0),
2164 back_buffer_has_depth_(false),
2165 back_buffer_has_stencil_(false),
2166 backbuffer_needs_clear_bits_(0),
2167 teximage2d_faster_than_texsubimage2d_(true),
2168 current_decoder_error_(error::kNoError
),
2169 use_shader_translator_(true),
2170 validators_(group_
->feature_info()->validators()),
2171 feature_info_(group_
->feature_info()),
2172 tex_image_2d_failed_(false),
2174 has_robustness_extension_(false),
2175 reset_status_(GL_NO_ERROR
),
2176 reset_by_robustness_extension_(false),
2177 force_webgl_glsl_validation_(false),
2178 derivatives_explicitly_enabled_(false),
2179 frag_depth_explicitly_enabled_(false),
2180 draw_buffers_explicitly_enabled_(false),
2181 compile_shader_always_succeeds_(false),
2182 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2183 switches::kEnableGPUServiceLoggingGPU
)),
2184 viewport_max_width_(0),
2185 viewport_max_height_(0),
2186 texture_upload_count_(0) {
2189 attrib_0_value_
.v
[0] = 0.0f
;
2190 attrib_0_value_
.v
[1] = 0.0f
;
2191 attrib_0_value_
.v
[2] = 0.0f
;
2192 attrib_0_value_
.v
[3] = 1.0f
;
2194 // The shader translator is used for WebGL even when running on EGL
2195 // because additional restrictions are needed (like only enabling
2196 // GL_OES_standard_derivatives on demand). It is used for the unit
2197 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2198 // the empty string to CompileShader and this is not a valid shader.
2199 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2200 CommandLine::ForCurrentProcess()->HasSwitch(
2201 switches::kDisableGLSLTranslator
)) {
2202 use_shader_translator_
= false;
2205 // TODO(gman): Consider setting this based on GPU and/or driver.
2207 teximage2d_faster_than_texsubimage2d_
= false;
2211 GLES2DecoderImpl::~GLES2DecoderImpl() {
2214 bool GLES2DecoderImpl::Initialize(
2215 const scoped_refptr
<gfx::GLSurface
>& surface
,
2216 const scoped_refptr
<gfx::GLContext
>& context
,
2218 const gfx::Size
& size
,
2219 const DisallowedFeatures
& disallowed_features
,
2220 const char* allowed_extensions
,
2221 const std::vector
<int32
>& attribs
) {
2222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2223 DCHECK(context
->IsCurrent(surface
.get()));
2224 DCHECK(!context_
.get());
2227 gpu_tracer_
= GPUTracer::Create();
2229 if (CommandLine::ForCurrentProcess()->HasSwitch(
2230 switches::kEnableGPUDebugging
)) {
2234 if (CommandLine::ForCurrentProcess()->HasSwitch(
2235 switches::kEnableGPUCommandLogging
)) {
2236 set_log_commands(true);
2239 compile_shader_always_succeeds_
= CommandLine::ForCurrentProcess()->HasSwitch(
2240 switches::kCompileShaderAlwaysSucceeds
);
2243 // Take ownership of the context and surface. The surface can be replaced with
2248 if (!group_
->Initialize(this, disallowed_features
, allowed_extensions
)) {
2249 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2250 << "failed to initialize.";
2251 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2257 disallowed_features_
= disallowed_features
;
2259 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2260 default_vertex_attrib_manager_
= new VertexAttribManager();
2261 default_vertex_attrib_manager_
->Initialize(group_
->max_vertex_attribs());
2263 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2264 DoBindVertexArrayOES(0);
2266 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2267 vertex_array_manager_
.reset(new VertexArrayManager());
2269 util_
.set_num_compressed_texture_formats(
2270 validators_
->compressed_texture_format
.GetValues().size());
2272 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2273 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2274 // OpenGL ES 2.0 does not have this issue.
2275 glEnableVertexAttribArray(0);
2277 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2278 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2279 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2280 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2281 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2283 state_
.texture_units
.resize(group_
->max_texture_units());
2284 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2285 glActiveTexture(GL_TEXTURE0
+ tt
);
2286 // We want the last bind to be 2D.
2288 if (features().oes_egl_image_external
) {
2289 ref
= texture_manager()->GetDefaultTextureInfo(
2290 GL_TEXTURE_EXTERNAL_OES
);
2291 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2292 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
->service_id());
2294 if (features().arb_texture_rectangle
) {
2295 ref
= texture_manager()->GetDefaultTextureInfo(
2296 GL_TEXTURE_RECTANGLE_ARB
);
2297 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2298 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
->service_id());
2300 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2301 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2302 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
->service_id());
2303 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2304 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2305 glBindTexture(GL_TEXTURE_2D
, ref
->service_id());
2307 glActiveTexture(GL_TEXTURE0
);
2310 ContextCreationAttribParser attrib_parser
;
2311 if (!attrib_parser
.Parse(attribs
))
2315 if (attrib_parser
.samples_
> 0 && attrib_parser
.sample_buffers_
> 0 &&
2316 features().chromium_framebuffer_multisample
) {
2317 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2318 // max_sample_count must be initialized to a sane value. If
2319 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2320 GLint max_sample_count
= 1;
2321 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2322 offscreen_target_samples_
= std::min(attrib_parser
.samples_
,
2325 offscreen_target_samples_
= 1;
2327 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved_
;
2329 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2330 const bool rgb8_supported
=
2331 context_
->HasExtension("GL_OES_rgb8_rgba8");
2332 // The only available default render buffer formats in GLES2 have very
2333 // little precision. Don't enable multisampling unless 8-bit render
2334 // buffer formats are available--instead fall back to 8-bit textures.
2335 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2336 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2339 offscreen_target_samples_
= 1;
2340 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2344 // ANGLE only supports packed depth/stencil formats, so use it if it is
2346 const bool depth24_stencil8_supported
=
2347 context_
->HasExtension("GL_OES_packed_depth_stencil");
2348 VLOG(1) << "GL_OES_packed_depth_stencil "
2349 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2350 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2351 depth24_stencil8_supported
) {
2352 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2353 offscreen_target_stencil_format_
= 0;
2355 // It may be the case that this depth/stencil combination is not
2356 // supported, but this will be checked later by CheckFramebufferStatus.
2357 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2358 GL_DEPTH_COMPONENT16
: 0;
2359 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2360 GL_STENCIL_INDEX8
: 0;
2363 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2366 // If depth is requested at all, use the packed depth stencil format if
2367 // it's available, as some desktop GL drivers don't support any non-packed
2368 // formats for depth attachments.
2369 const bool depth24_stencil8_supported
=
2370 context_
->HasExtension("GL_EXT_packed_depth_stencil");
2371 VLOG(1) << "GL_EXT_packed_depth_stencil "
2372 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2374 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2375 depth24_stencil8_supported
) {
2376 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2377 offscreen_target_stencil_format_
= 0;
2379 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2380 GL_DEPTH_COMPONENT
: 0;
2381 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2382 GL_STENCIL_INDEX
: 0;
2386 offscreen_saved_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2389 // Create the target frame buffer. This is the one that the client renders
2391 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2392 offscreen_target_frame_buffer_
->Create();
2393 // Due to GLES2 format limitations, either the color texture (for
2394 // non-multisampling) or the color render buffer (for multisampling) will be
2395 // attached to the offscreen frame buffer. The render buffer has more
2396 // limited formats available to it, but the texture can't do multisampling.
2397 if (IsOffscreenBufferMultisampled()) {
2398 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(this));
2399 offscreen_target_color_render_buffer_
->Create();
2401 offscreen_target_color_texture_
.reset(new BackTexture(this));
2402 offscreen_target_color_texture_
->Create();
2404 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(this));
2405 offscreen_target_depth_render_buffer_
->Create();
2406 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(this));
2407 offscreen_target_stencil_render_buffer_
->Create();
2409 // Create the saved offscreen texture. The target frame buffer is copied
2410 // here when SwapBuffers is called.
2411 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2412 offscreen_saved_frame_buffer_
->Create();
2414 offscreen_saved_color_texture_
.reset(new BackTexture(this));
2415 offscreen_saved_color_texture_
->Create();
2417 // Allocate the render buffers at their initial size and check the status
2418 // of the frame buffers is okay.
2419 if (!ResizeOffscreenFrameBuffer(size
)) {
2420 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2425 // Allocate the offscreen saved color texture.
2426 DCHECK(offscreen_saved_color_format_
);
2427 offscreen_saved_color_texture_
->AllocateStorage(
2428 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2430 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2431 offscreen_saved_color_texture_
.get());
2432 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2433 GL_FRAMEBUFFER_COMPLETE
) {
2434 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2439 // Bind to the new default frame buffer (the offscreen target frame buffer).
2440 // This should now be associated with ID zero.
2441 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2443 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2444 // These are NOT if the back buffer has these proprorties. They are
2445 // if we want the command buffer to enforce them regardless of what
2446 // the real backbuffer is assuming the real back buffer gives us more than
2447 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2448 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2449 // can't do anything about that.
2452 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2453 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2454 // user requested RGB then RGB. If the user did not specify a preference
2455 // than use whatever we were given. Same for DEPTH and STENCIL.
2456 back_buffer_color_format_
=
2457 (attrib_parser
.alpha_size_
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2458 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2459 back_buffer_has_depth_
= attrib_parser
.depth_size_
!= 0 && v
> 0;
2460 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2461 back_buffer_has_stencil_
= attrib_parser
.stencil_size_
!= 0 && v
> 0;
2464 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2465 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2466 // isn't well documented; it was discovered in the Khronos OpenGL ES
2467 // mailing list archives. It also implicitly enables the desktop GL
2468 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2469 // variable in fragment shaders.
2470 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2471 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2472 glEnable(GL_POINT_SPRITE
);
2475 has_robustness_extension_
=
2476 context
->HasExtension("GL_ARB_robustness") ||
2477 context
->HasExtension("GL_EXT_robustness");
2479 if (!InitializeShaderTranslator()) {
2483 state_
.viewport_width
= size
.width();
2484 state_
.viewport_height
= size
.height();
2486 GLint viewport_params
[4] = { 0 };
2487 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2488 viewport_max_width_
= viewport_params
[0];
2489 viewport_max_height_
= viewport_params
[1];
2491 state_
.scissor_width
= state_
.viewport_width
;
2492 state_
.scissor_height
= state_
.viewport_height
;
2494 // Set all the default state because some GL drivers get it wrong.
2495 state_
.InitCapabilities();
2497 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2499 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2500 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2501 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2502 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2504 // Clear the backbuffer.
2505 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2507 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2508 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2511 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2512 context_
->SetUnbindFboOnMakeCurrent();
2515 // Only compositor contexts are known to use only the subset of GL
2516 // that can be safely migrated between the iGPU and the dGPU. Mark
2517 // those contexts as safe to forcibly transition between the GPUs.
2518 // http://crbug.com/180876, http://crbug.com/227228
2520 context_
->SetSafeToForceGpuSwitch();
2522 async_pixel_transfer_manager_
.reset(
2523 AsyncPixelTransferManager::Create(context
.get()));
2524 async_pixel_transfer_manager_
->Initialize(texture_manager());
2529 void GLES2DecoderImpl::UpdateCapabilities() {
2530 util_
.set_num_compressed_texture_formats(
2531 validators_
->compressed_texture_format
.GetValues().size());
2532 util_
.set_num_shader_binary_formats(
2533 validators_
->shader_binary_format
.GetValues().size());
2536 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2537 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2539 if (!use_shader_translator_
) {
2542 ShBuiltInResources resources
;
2543 ShInitBuiltInResources(&resources
);
2544 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2545 resources
.MaxVertexUniformVectors
=
2546 group_
->max_vertex_uniform_vectors();
2547 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2548 resources
.MaxVertexTextureImageUnits
=
2549 group_
->max_vertex_texture_image_units();
2550 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2551 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2552 resources
.MaxFragmentUniformVectors
=
2553 group_
->max_fragment_uniform_vectors();
2554 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2555 resources
.MaxExpressionComplexity
= 256;
2556 resources
.MaxCallStackDepth
= 256;
2558 #if (ANGLE_SH_VERSION >= 110)
2559 GLint range
[2] = { 0, 0 };
2560 GLint precision
= 0;
2561 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2563 resources
.FragmentPrecisionHigh
=
2564 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2567 if (force_webgl_glsl_validation_
) {
2568 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2569 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2570 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2572 resources
.OES_standard_derivatives
=
2573 features().oes_standard_derivatives
? 1 : 0;
2574 resources
.ARB_texture_rectangle
=
2575 features().arb_texture_rectangle
? 1 : 0;
2576 resources
.OES_EGL_image_external
=
2577 features().oes_egl_image_external
? 1 : 0;
2578 resources
.EXT_draw_buffers
=
2579 features().ext_draw_buffers
? 1 : 0;
2580 resources
.EXT_frag_depth
=
2581 features().ext_frag_depth
? 1 : 0;
2584 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2586 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2587 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2588 resources
.HashFunction
= &CityHashForAngle
;
2590 resources
.HashFunction
= &CityHash64
;
2593 resources
.HashFunction
= NULL
;
2594 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2595 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2596 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2597 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior
=
2598 workarounds().needs_glsl_built_in_function_emulation
?
2599 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated
:
2600 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal
;
2602 ShaderTranslatorCache
* cache
= ShaderTranslatorCache::GetInstance();
2603 vertex_translator_
= cache
->GetTranslator(
2604 SH_VERTEX_SHADER
, shader_spec
, &resources
,
2605 implementation_type
, function_behavior
);
2606 if (!vertex_translator_
.get()) {
2607 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2612 fragment_translator_
= cache
->GetTranslator(
2613 SH_FRAGMENT_SHADER
, shader_spec
, &resources
,
2614 implementation_type
, function_behavior
);
2615 if (!fragment_translator_
.get()) {
2616 LOG(ERROR
) << "Could not initialize fragment shader translator.";
2623 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
2624 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2625 if (GetBuffer(client_ids
[ii
])) {
2629 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2630 glGenBuffersARB(n
, service_ids
.get());
2631 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2632 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
2637 bool GLES2DecoderImpl::GenFramebuffersHelper(
2638 GLsizei n
, const GLuint
* client_ids
) {
2639 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2640 if (GetFramebuffer(client_ids
[ii
])) {
2644 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2645 glGenFramebuffersEXT(n
, service_ids
.get());
2646 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2647 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
2652 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2653 GLsizei n
, const GLuint
* client_ids
) {
2654 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2655 if (GetRenderbuffer(client_ids
[ii
])) {
2659 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2660 glGenRenderbuffersEXT(n
, service_ids
.get());
2661 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2662 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
2667 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
2668 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2669 if (GetTexture(client_ids
[ii
])) {
2673 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2674 glGenTextures(n
, service_ids
.get());
2675 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2676 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
2681 void GLES2DecoderImpl::DeleteBuffersHelper(
2682 GLsizei n
, const GLuint
* client_ids
) {
2683 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2684 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
2685 if (buffer
&& !buffer
->IsDeleted()) {
2686 state_
.vertex_attrib_manager
->Unbind(buffer
);
2687 if (state_
.bound_array_buffer
.get() == buffer
) {
2688 state_
.bound_array_buffer
= NULL
;
2690 RemoveBuffer(client_ids
[ii
]);
2695 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2696 GLsizei n
, const GLuint
* client_ids
) {
2697 bool supports_separate_framebuffer_binds
=
2698 features().chromium_framebuffer_multisample
;
2700 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2701 Framebuffer
* framebuffer
=
2702 GetFramebuffer(client_ids
[ii
]);
2703 if (framebuffer
&& !framebuffer
->IsDeleted()) {
2704 if (framebuffer
== state_
.bound_draw_framebuffer
.get()) {
2705 state_
.bound_draw_framebuffer
= NULL
;
2706 clear_state_dirty_
= true;
2707 GLenum target
= supports_separate_framebuffer_binds
?
2708 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2709 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2711 if (framebuffer
== state_
.bound_read_framebuffer
.get()) {
2712 state_
.bound_read_framebuffer
= NULL
;
2713 GLenum target
= supports_separate_framebuffer_binds
?
2714 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2715 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2718 RemoveFramebuffer(client_ids
[ii
]);
2723 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2724 GLsizei n
, const GLuint
* client_ids
) {
2725 bool supports_separate_framebuffer_binds
=
2726 features().chromium_framebuffer_multisample
;
2727 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2728 Renderbuffer
* renderbuffer
=
2729 GetRenderbuffer(client_ids
[ii
]);
2730 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
2731 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
2732 state_
.bound_renderbuffer
= NULL
;
2734 // Unbind from current framebuffers.
2735 if (supports_separate_framebuffer_binds
) {
2736 if (state_
.bound_read_framebuffer
.get()) {
2737 state_
.bound_read_framebuffer
2738 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
2740 if (state_
.bound_draw_framebuffer
.get()) {
2741 state_
.bound_draw_framebuffer
2742 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
2745 if (state_
.bound_draw_framebuffer
.get()) {
2746 state_
.bound_draw_framebuffer
2747 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
2750 clear_state_dirty_
= true;
2751 RemoveRenderbuffer(client_ids
[ii
]);
2756 void GLES2DecoderImpl::DeleteTexturesHelper(
2757 GLsizei n
, const GLuint
* client_ids
) {
2758 bool supports_separate_framebuffer_binds
=
2759 features().chromium_framebuffer_multisample
;
2760 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2761 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
2763 Texture
* texture
= texture_ref
->texture();
2764 if (texture
->IsAttachedToFramebuffer()) {
2765 clear_state_dirty_
= true;
2767 // Unbind texture_ref from texture_ref units.
2768 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
2769 state_
.texture_units
[jj
].Unbind(texture_ref
);
2771 // Unbind from current framebuffers.
2772 if (supports_separate_framebuffer_binds
) {
2773 if (state_
.bound_read_framebuffer
.get()) {
2774 state_
.bound_read_framebuffer
2775 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
2777 if (state_
.bound_draw_framebuffer
.get()) {
2778 state_
.bound_draw_framebuffer
2779 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
2782 if (state_
.bound_draw_framebuffer
.get()) {
2783 state_
.bound_draw_framebuffer
2784 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
2787 #if defined(OS_MACOSX)
2788 GLuint service_id
= texture
->service_id();
2789 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
2790 ReleaseIOSurfaceForTexture(service_id
);
2793 RemoveTexture(client_ids
[ii
]);
2798 // } // anonymous namespace
2800 bool GLES2DecoderImpl::MakeCurrent() {
2801 if (!context_
.get() || !context_
->MakeCurrent(surface_
.get()))
2804 if (WasContextLost()) {
2805 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2807 // Some D3D drivers cannot recover from device lost in the GPU process
2808 // sandbox. Allow a new GPU process to launch.
2809 if (workarounds().exit_on_context_lost
) {
2810 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
2811 << " a D3D device in the Chrome GPU process sandbox.";
2818 ProcessFinishedAsyncTransfers();
2819 if (workarounds().flush_on_context_switch
)
2822 // Rebind the FBO if it was unbound by the context.
2823 if (workarounds().unbind_fbo_on_context_switch
)
2824 RestoreFramebufferBindings();
2826 clear_state_dirty_
= true;
2831 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
2832 ProcessPendingReadPixels();
2833 if (engine() && query_manager_
.get())
2834 query_manager_
->ProcessPendingTransferQueries();
2836 // TODO(epenner): Is there a better place to do this?
2837 // This needs to occur before we execute any batch of commands
2838 // from the client, as the client may have recieved an async
2839 // completion while issuing those commands.
2840 // "DidFlushStart" would be ideal if we had such a callback.
2841 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
2844 void GLES2DecoderImpl::ReleaseCurrent() {
2846 context_
->ReleaseCurrent(surface_
.get());
2849 void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2850 Renderbuffer
* renderbuffer
=
2851 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
2852 glBindRenderbufferEXT(
2853 GL_RENDERBUFFER
, renderbuffer
? renderbuffer
->service_id() : 0);
2856 static void RebindCurrentFramebuffer(
2858 Framebuffer
* framebuffer
,
2859 GLuint back_buffer_service_id
) {
2860 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
2862 if (framebuffer_id
== 0) {
2863 framebuffer_id
= back_buffer_service_id
;
2866 glBindFramebufferEXT(target
, framebuffer_id
);
2869 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2870 clear_state_dirty_
= true;
2872 if (!features().chromium_framebuffer_multisample
) {
2873 RebindCurrentFramebuffer(
2875 state_
.bound_draw_framebuffer
.get(),
2876 GetBackbufferServiceId());
2878 RebindCurrentFramebuffer(
2879 GL_READ_FRAMEBUFFER_EXT
,
2880 state_
.bound_read_framebuffer
.get(),
2881 GetBackbufferServiceId());
2882 RebindCurrentFramebuffer(
2883 GL_DRAW_FRAMEBUFFER_EXT
,
2884 state_
.bound_draw_framebuffer
.get(),
2885 GetBackbufferServiceId());
2890 void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2891 TextureUnit
& info
= state_
.texture_units
[0];
2893 if (info
.bound_texture_2d
.get()) {
2894 last_id
= info
.bound_texture_2d
->service_id();
2899 glBindTexture(GL_TEXTURE_2D
, last_id
);
2900 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2903 bool GLES2DecoderImpl::CheckFramebufferValid(
2904 Framebuffer
* framebuffer
,
2905 GLenum target
, const char* func_name
) {
2907 if (backbuffer_needs_clear_bits_
) {
2908 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2909 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
2910 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
2915 glDisable(GL_SCISSOR_TEST
);
2916 glClear(backbuffer_needs_clear_bits_
);
2917 backbuffer_needs_clear_bits_
= 0;
2918 RestoreClearState();
2923 if (framebuffer_manager()->IsComplete(framebuffer
)) {
2927 GLenum completeness
= framebuffer
->IsPossiblyComplete();
2928 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
2930 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
2934 // Are all the attachments cleared?
2935 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2936 texture_manager()->HaveUnclearedMips()) {
2937 if (!framebuffer
->IsCleared()) {
2938 // Can we clear them?
2939 if (framebuffer
->GetStatus(texture_manager(), target
) !=
2940 GL_FRAMEBUFFER_COMPLETE
) {
2942 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
2943 "framebuffer incomplete (clear)");
2946 ClearUnclearedAttachments(target
, framebuffer
);
2950 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
2951 if (framebuffer
->GetStatus(texture_manager(), target
) !=
2952 GL_FRAMEBUFFER_COMPLETE
) {
2954 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
2955 "framebuffer incomplete (check)");
2958 framebuffer_manager()->MarkAsComplete(framebuffer
);
2961 // NOTE: At this point we don't know if the framebuffer is complete but
2962 // we DO know that everything that needs to be cleared has been cleared.
2966 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
2967 if (!features().chromium_framebuffer_multisample
) {
2968 bool valid
= CheckFramebufferValid(
2969 state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
, func_name
);
2976 return CheckFramebufferValid(state_
.bound_draw_framebuffer
.get(),
2977 GL_DRAW_FRAMEBUFFER_EXT
,
2979 CheckFramebufferValid(state_
.bound_read_framebuffer
.get(),
2980 GL_READ_FRAMEBUFFER_EXT
,
2984 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2985 Framebuffer
* framebuffer
=
2986 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
2987 if (framebuffer
!= NULL
) {
2988 const Framebuffer::Attachment
* attachment
=
2989 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
2991 return gfx::Size(attachment
->width(), attachment
->height());
2993 return gfx::Size(0, 0);
2994 } else if (offscreen_target_frame_buffer_
.get()) {
2995 return offscreen_size_
;
2997 return surface_
->GetSize();
3001 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3002 Framebuffer
* framebuffer
=
3003 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3004 if (framebuffer
!= NULL
) {
3005 return framebuffer
->GetColorAttachmentFormat();
3006 } else if (offscreen_target_frame_buffer_
.get()) {
3007 return offscreen_target_color_format_
;
3009 return back_buffer_color_format_
;
3013 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3014 Framebuffer
* framebuffer
=
3015 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3016 if (framebuffer
!= NULL
) {
3017 return framebuffer
->GetColorAttachmentFormat();
3018 } else if (offscreen_target_frame_buffer_
.get()) {
3019 return offscreen_target_color_format_
;
3021 return back_buffer_color_format_
;
3025 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3026 if (!offscreen_saved_color_texture_info_
.get())
3028 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3029 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3030 texture_manager()->SetLevelInfo(
3031 offscreen_saved_color_texture_info_
.get(),
3035 offscreen_size_
.width(),
3036 offscreen_size_
.height(),
3042 texture_manager()->SetParameter(
3043 "UpdateParentTextureInfo",
3045 offscreen_saved_color_texture_info_
.get(),
3046 GL_TEXTURE_MAG_FILTER
,
3048 texture_manager()->SetParameter(
3049 "UpdateParentTextureInfo",
3051 offscreen_saved_color_texture_info_
.get(),
3052 GL_TEXTURE_MIN_FILTER
,
3054 texture_manager()->SetParameter(
3055 "UpdateParentTextureInfo",
3057 offscreen_saved_color_texture_info_
.get(),
3060 texture_manager()->SetParameter(
3061 "UpdateParentTextureInfo",
3063 offscreen_saved_color_texture_info_
.get(),
3066 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
3067 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3070 void GLES2DecoderImpl::SetResizeCallback(
3071 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3072 resize_callback_
= callback
;
3075 Logger
* GLES2DecoderImpl::GetLogger() {
3079 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3080 return state_
.GetErrorState();
3083 void GLES2DecoderImpl::SetShaderCacheCallback(
3084 const ShaderCacheCallback
& callback
) {
3085 shader_cache_callback_
= callback
;
3088 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3089 const WaitSyncPointCallback
& callback
) {
3090 wait_sync_point_callback_
= callback
;
3093 AsyncPixelTransferManager
*
3094 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3095 return async_pixel_transfer_manager_
.get();
3098 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3099 async_pixel_transfer_manager_
.reset();
3102 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3103 AsyncPixelTransferManager
* manager
) {
3104 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3107 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3108 uint32
* service_texture_id
) {
3109 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3111 *service_texture_id
= texture_ref
->service_id();
3117 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3118 return texture_upload_count_
+
3119 async_pixel_transfer_manager_
->GetTextureUploadCount();
3122 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3123 return total_texture_upload_time_
+
3124 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3127 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3128 return total_processing_commands_time_
;
3131 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3132 total_processing_commands_time_
+= time
;
3135 void GLES2DecoderImpl::Destroy(bool have_context
) {
3139 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3141 // Unbind everything.
3142 state_
.vertex_attrib_manager
= NULL
;
3143 default_vertex_attrib_manager_
= NULL
;
3144 state_
.texture_units
.clear();
3145 state_
.bound_array_buffer
= NULL
;
3146 state_
.current_query
= NULL
;
3147 state_
.current_program
= NULL
;
3148 state_
.bound_read_framebuffer
= NULL
;
3149 state_
.bound_draw_framebuffer
= NULL
;
3150 state_
.bound_renderbuffer
= NULL
;
3152 if (offscreen_saved_color_texture_info_
.get()) {
3153 DCHECK(offscreen_target_color_texture_
);
3154 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3155 offscreen_saved_color_texture_
->id());
3156 offscreen_saved_color_texture_
->Invalidate();
3157 offscreen_saved_color_texture_info_
= NULL
;
3160 if (copy_texture_CHROMIUM_
.get()) {
3161 copy_texture_CHROMIUM_
->Destroy();
3162 copy_texture_CHROMIUM_
.reset();
3165 if (state_
.current_program
.get()) {
3166 program_manager()->UnuseProgram(shader_manager(),
3167 state_
.current_program
.get());
3168 state_
.current_program
= NULL
;
3171 if (attrib_0_buffer_id_
) {
3172 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3174 if (fixed_attrib_buffer_id_
) {
3175 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3178 if (offscreen_target_frame_buffer_
.get())
3179 offscreen_target_frame_buffer_
->Destroy();
3180 if (offscreen_target_color_texture_
.get())
3181 offscreen_target_color_texture_
->Destroy();
3182 if (offscreen_target_color_render_buffer_
.get())
3183 offscreen_target_color_render_buffer_
->Destroy();
3184 if (offscreen_target_depth_render_buffer_
.get())
3185 offscreen_target_depth_render_buffer_
->Destroy();
3186 if (offscreen_target_stencil_render_buffer_
.get())
3187 offscreen_target_stencil_render_buffer_
->Destroy();
3188 if (offscreen_saved_frame_buffer_
.get())
3189 offscreen_saved_frame_buffer_
->Destroy();
3190 if (offscreen_saved_color_texture_
.get())
3191 offscreen_saved_color_texture_
->Destroy();
3192 if (offscreen_resolved_frame_buffer_
.get())
3193 offscreen_resolved_frame_buffer_
->Destroy();
3194 if (offscreen_resolved_color_texture_
.get())
3195 offscreen_resolved_color_texture_
->Destroy();
3197 if (offscreen_target_frame_buffer_
.get())
3198 offscreen_target_frame_buffer_
->Invalidate();
3199 if (offscreen_target_color_texture_
.get())
3200 offscreen_target_color_texture_
->Invalidate();
3201 if (offscreen_target_color_render_buffer_
.get())
3202 offscreen_target_color_render_buffer_
->Invalidate();
3203 if (offscreen_target_depth_render_buffer_
.get())
3204 offscreen_target_depth_render_buffer_
->Invalidate();
3205 if (offscreen_target_stencil_render_buffer_
.get())
3206 offscreen_target_stencil_render_buffer_
->Invalidate();
3207 if (offscreen_saved_frame_buffer_
.get())
3208 offscreen_saved_frame_buffer_
->Invalidate();
3209 if (offscreen_saved_color_texture_
.get())
3210 offscreen_saved_color_texture_
->Invalidate();
3211 if (offscreen_resolved_frame_buffer_
.get())
3212 offscreen_resolved_frame_buffer_
->Invalidate();
3213 if (offscreen_resolved_color_texture_
.get())
3214 offscreen_resolved_color_texture_
->Invalidate();
3216 copy_texture_CHROMIUM_
.reset();
3218 if (query_manager_
.get()) {
3219 query_manager_
->Destroy(have_context
);
3220 query_manager_
.reset();
3223 if (vertex_array_manager_
.get()) {
3224 vertex_array_manager_
->Destroy(have_context
);
3225 vertex_array_manager_
.reset();
3228 offscreen_target_frame_buffer_
.reset();
3229 offscreen_target_color_texture_
.reset();
3230 offscreen_target_color_render_buffer_
.reset();
3231 offscreen_target_depth_render_buffer_
.reset();
3232 offscreen_target_stencil_render_buffer_
.reset();
3233 offscreen_saved_frame_buffer_
.reset();
3234 offscreen_saved_color_texture_
.reset();
3235 offscreen_resolved_frame_buffer_
.reset();
3236 offscreen_resolved_color_texture_
.reset();
3238 // Should destroy the transfer manager before the texture manager held
3239 // by the context group.
3240 async_pixel_transfer_manager_
.reset();
3243 group_
->Destroy(this, have_context
);
3247 if (context_
.get()) {
3248 context_
->ReleaseCurrent(NULL
);
3252 #if defined(OS_MACOSX)
3253 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3254 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3255 CFRelease(it
->second
);
3257 texture_to_io_surface_map_
.clear();
3261 void GLES2DecoderImpl::SetSurface(
3262 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3263 DCHECK(context_
->IsCurrent(NULL
));
3264 DCHECK(surface_
.get());
3266 RestoreCurrentFramebufferBindings();
3269 bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3270 if (!offscreen_saved_color_texture_
.get())
3272 if (!offscreen_saved_color_texture_info_
.get()) {
3273 GLuint service_id
= offscreen_saved_color_texture_
->id();
3274 offscreen_saved_color_texture_info_
= TextureRef::Create(
3275 texture_manager(), 0, service_id
);
3276 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3278 UpdateParentTextureInfo();
3280 gpu::gles2::MailboxName name
;
3281 memcpy(name
.key
, mailbox
.name
, sizeof(mailbox
.name
));
3282 return mailbox_manager()->ProduceTexture(
3283 GL_TEXTURE_2D
, name
, offscreen_saved_color_texture_info_
->texture());
3286 size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
3288 if (offscreen_target_frame_buffer_
.get()) {
3289 if (offscreen_target_color_texture_
.get()) {
3290 total
+= offscreen_target_color_texture_
->estimated_size();
3292 if (offscreen_target_color_render_buffer_
.get()) {
3293 total
+= offscreen_target_color_render_buffer_
->estimated_size();
3295 if (offscreen_target_depth_render_buffer_
.get()) {
3296 total
+= offscreen_target_depth_render_buffer_
->estimated_size();
3298 if (offscreen_target_stencil_render_buffer_
.get()) {
3299 total
+= offscreen_target_stencil_render_buffer_
->estimated_size();
3301 if (offscreen_saved_color_texture_
.get()) {
3302 total
+= offscreen_saved_color_texture_
->estimated_size();
3304 if (offscreen_resolved_color_texture_
.get()) {
3305 total
+= offscreen_resolved_color_texture_
->estimated_size();
3308 gfx::Size size
= surface_
->GetSize();
3309 total
+= size
.width() * size
.height() *
3310 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_
);
3315 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3316 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3317 if (!is_offscreen
) {
3318 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3319 << " with an onscreen framebuffer.";
3323 if (offscreen_size_
== size
)
3326 offscreen_size_
= size
;
3327 int w
= offscreen_size_
.width();
3328 int h
= offscreen_size_
.height();
3329 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3330 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3331 << "to allocate storage due to excessive dimensions.";
3335 // Reallocate the offscreen target buffers.
3336 DCHECK(offscreen_target_color_format_
);
3337 if (IsOffscreenBufferMultisampled()) {
3338 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3339 offscreen_size_
, offscreen_target_color_format_
,
3340 offscreen_target_samples_
)) {
3341 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3342 << "to allocate storage for offscreen target color buffer.";
3346 if (!offscreen_target_color_texture_
->AllocateStorage(
3347 offscreen_size_
, offscreen_target_color_format_
, false)) {
3348 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3349 << "to allocate storage for offscreen target color texture.";
3353 if (offscreen_target_depth_format_
&&
3354 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3355 offscreen_size_
, offscreen_target_depth_format_
,
3356 offscreen_target_samples_
)) {
3357 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3358 << "to allocate storage for offscreen target depth buffer.";
3361 if (offscreen_target_stencil_format_
&&
3362 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3363 offscreen_size_
, offscreen_target_stencil_format_
,
3364 offscreen_target_samples_
)) {
3365 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3366 << "to allocate storage for offscreen target stencil buffer.";
3370 // Attach the offscreen target buffers to the target frame buffer.
3371 if (IsOffscreenBufferMultisampled()) {
3372 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3373 GL_COLOR_ATTACHMENT0
,
3374 offscreen_target_color_render_buffer_
.get());
3376 offscreen_target_frame_buffer_
->AttachRenderTexture(
3377 offscreen_target_color_texture_
.get());
3379 if (offscreen_target_depth_format_
) {
3380 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3381 GL_DEPTH_ATTACHMENT
,
3382 offscreen_target_depth_render_buffer_
.get());
3384 const bool packed_depth_stencil
=
3385 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3386 if (packed_depth_stencil
) {
3387 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3388 GL_STENCIL_ATTACHMENT
,
3389 offscreen_target_depth_render_buffer_
.get());
3390 } else if (offscreen_target_stencil_format_
) {
3391 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3392 GL_STENCIL_ATTACHMENT
,
3393 offscreen_target_stencil_render_buffer_
.get());
3396 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3397 GL_FRAMEBUFFER_COMPLETE
) {
3398 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3399 << "because offscreen FBO was incomplete.";
3403 // Clear the target frame buffer.
3405 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3406 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3407 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3408 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3410 glStencilMaskSeparate(GL_FRONT
, -1);
3411 glStencilMaskSeparate(GL_BACK
, -1);
3413 glDepthMask(GL_TRUE
);
3414 glDisable(GL_SCISSOR_TEST
);
3415 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3416 RestoreClearState();
3419 // Destroy the offscreen resolved framebuffers.
3420 if (offscreen_resolved_frame_buffer_
.get())
3421 offscreen_resolved_frame_buffer_
->Destroy();
3422 if (offscreen_resolved_color_texture_
.get())
3423 offscreen_resolved_color_texture_
->Destroy();
3424 offscreen_resolved_color_texture_
.reset();
3425 offscreen_resolved_frame_buffer_
.reset();
3430 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(
3431 uint32 immediate_data_size
, const cmds::ResizeCHROMIUM
& c
) {
3432 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3433 return error::kDeferCommandUntilLater
;
3435 GLuint width
= static_cast<GLuint
>(c
.width
);
3436 GLuint height
= static_cast<GLuint
>(c
.height
);
3437 GLfloat scale_factor
= c
.scale_factor
;
3438 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3440 width
= std::max(1U, width
);
3441 height
= std::max(1U, height
);
3443 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3444 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3445 // Make sure that we are done drawing to the back buffer before resizing.
3448 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3450 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3451 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3452 << "ResizeOffscreenFrameBuffer failed.";
3453 return error::kLostContext
;
3457 if (!resize_callback_
.is_null()) {
3458 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3459 DCHECK(context_
->IsCurrent(surface_
.get()));
3460 if (!context_
->IsCurrent(surface_
.get())) {
3461 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3462 << "current after resize callback.";
3463 return error::kLostContext
;
3467 return error::kNoError
;
3470 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3471 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3472 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3474 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3477 // Decode command with its arguments, and call the corresponding GL function.
3478 // Note: args is a pointer to the command buffer. As such, it could be changed
3479 // by a (malicious) client at any time, so if validation has to happen, it
3480 // should operate on a copy of them.
3481 error::Error
GLES2DecoderImpl::DoCommand(
3482 unsigned int command
,
3483 unsigned int arg_count
,
3484 const void* cmd_data
) {
3485 error::Error result
= error::kNoError
;
3486 if (log_commands()) {
3487 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3488 // LOG(INFO), tried VLOG(1), no luck.
3489 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]" << "cmd: "
3490 << GetCommandName(command
);
3492 unsigned int command_index
= command
- kStartPoint
- 1;
3493 if (command_index
< arraysize(g_command_info
)) {
3494 const CommandInfo
& info
= g_command_info
[command_index
];
3495 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3496 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3497 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3498 uint32 immediate_data_size
=
3499 (arg_count
- info_arg_count
) * sizeof(CommandBufferEntry
); // NOLINT
3501 #define GLES2_CMD_OP(name) \
3502 case cmds::name::kCmdId: \
3503 result = Handle ## name( \
3504 immediate_data_size, \
3505 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3508 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3513 while ((error
= glGetError()) != GL_NO_ERROR
) {
3514 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
3515 << "GL ERROR: " << GLES2Util::GetStringEnum(error
) << " : "
3516 << GetCommandName(command
);
3517 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
3521 result
= error::kInvalidArguments
;
3524 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
3526 if (result
== error::kNoError
&& current_decoder_error_
!= error::kNoError
) {
3527 result
= current_decoder_error_
;
3528 current_decoder_error_
= error::kNoError
;
3533 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
3534 buffer_manager()->RemoveBuffer(client_id
);
3537 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id
) {
3538 if (GetProgram(client_id
)) {
3541 GLuint service_id
= glCreateProgram();
3542 if (service_id
!= 0) {
3543 CreateProgram(client_id
, service_id
);
3548 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type
, GLuint client_id
) {
3549 if (GetShader(client_id
)) {
3552 GLuint service_id
= glCreateShader(type
);
3553 if (service_id
!= 0) {
3554 CreateShader(client_id
, service_id
, type
);
3559 void GLES2DecoderImpl::DoFinish() {
3561 ProcessPendingReadPixels();
3562 ProcessPendingQueries();
3565 void GLES2DecoderImpl::DoFlush() {
3567 ProcessPendingQueries();
3570 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
3571 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
3572 if (texture_index
>= state_
.texture_units
.size()) {
3573 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3574 "glActiveTexture", texture_unit
, "texture_unit");
3577 state_
.active_texture_unit
= texture_index
;
3578 glActiveTexture(texture_unit
);
3581 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
3582 Buffer
* buffer
= NULL
;
3583 GLuint service_id
= 0;
3584 if (client_id
!= 0) {
3585 buffer
= GetBuffer(client_id
);
3587 if (!group_
->bind_generates_resource()) {
3588 LOG(ERROR
) << "glBindBuffer: id not generated by glGenBuffers";
3589 current_decoder_error_
= error::kGenericError
;
3593 // It's a new id so make a buffer buffer for it.
3594 glGenBuffersARB(1, &service_id
);
3595 CreateBuffer(client_id
, service_id
);
3596 buffer
= GetBuffer(client_id
);
3597 IdAllocatorInterface
* id_allocator
=
3598 group_
->GetIdAllocator(id_namespaces::kBuffers
);
3599 id_allocator
->MarkAsUsed(client_id
);
3602 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
3604 if (!buffer_manager()->SetTarget(buffer
, target
)) {
3606 GL_INVALID_OPERATION
,
3607 "glBindBuffer", "buffer bound to more than 1 target");
3610 service_id
= buffer
->service_id();
3613 case GL_ARRAY_BUFFER
:
3614 state_
.bound_array_buffer
= buffer
;
3616 case GL_ELEMENT_ARRAY_BUFFER
:
3617 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
3620 NOTREACHED(); // Validation should prevent us getting here.
3623 glBindBuffer(target
, service_id
);
3626 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3627 bool all_draw_buffers
) {
3628 Framebuffer
* framebuffer
=
3629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3630 if (!all_draw_buffers
|| !framebuffer
) {
3631 return (GLES2Util::GetChannelsForFormat(
3632 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3634 return framebuffer
->HasAlphaMRT();
3637 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3638 Framebuffer
* framebuffer
=
3639 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3641 return framebuffer
->HasDepthAttachment();
3643 if (offscreen_target_frame_buffer_
.get()) {
3644 return offscreen_target_depth_format_
!= 0;
3646 return back_buffer_has_depth_
;
3649 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3650 Framebuffer
* framebuffer
=
3651 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3653 return framebuffer
->HasStencilAttachment();
3655 if (offscreen_target_frame_buffer_
.get()) {
3656 return offscreen_target_stencil_format_
!= 0 ||
3657 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3659 return back_buffer_has_stencil_
;
3662 void GLES2DecoderImpl::ApplyDirtyState() {
3663 if (clear_state_dirty_
) {
3665 state_
.color_mask_red
, state_
.color_mask_green
, state_
.color_mask_blue
,
3666 state_
.color_mask_alpha
&&
3667 BoundFramebufferHasColorAttachmentWithAlpha(true));
3668 bool have_depth
= BoundFramebufferHasDepthAttachment();
3669 glDepthMask(state_
.depth_mask
&& have_depth
);
3670 EnableDisable(GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
3671 bool have_stencil
= BoundFramebufferHasStencilAttachment();
3672 glStencilMaskSeparate(
3673 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
3674 glStencilMaskSeparate(
3675 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
3677 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
3678 EnableDisable(GL_CULL_FACE
, state_
.enable_flags
.cull_face
);
3679 EnableDisable(GL_SCISSOR_TEST
, state_
.enable_flags
.scissor_test
);
3680 EnableDisable(GL_BLEND
, state_
.enable_flags
.blend
);
3681 clear_state_dirty_
= false;
3685 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
3686 return (offscreen_target_frame_buffer_
.get())
3687 ? offscreen_target_frame_buffer_
->id()
3688 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
3691 void GLES2DecoderImpl::RestoreState() const {
3692 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3693 "context", logger_
.GetLogPrefix());
3694 // Restore the Framebuffer first because of bugs in Intel drivers.
3695 // Intel drivers incorrectly clip the viewport settings to
3696 // the size of the current framebuffer object.
3697 RestoreFramebufferBindings();
3698 state_
.RestoreState();
3701 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3702 GLuint service_id
= state_
.bound_draw_framebuffer
.get()
3703 ? state_
.bound_draw_framebuffer
->service_id()
3704 : GetBackbufferServiceId();
3705 if (!features().chromium_framebuffer_multisample
) {
3706 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
3708 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
3709 service_id
= state_
.bound_read_framebuffer
.get()
3710 ? state_
.bound_read_framebuffer
->service_id()
3711 : GetBackbufferServiceId();
3712 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
3717 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
3718 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
3720 GLenum target
= texture
->target();
3721 glBindTexture(target
, service_id
);
3723 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
3725 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
3727 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
3729 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
3730 RestoreTextureUnitBindings(state_
.active_texture_unit
);
3734 void GLES2DecoderImpl::OnFboChanged() const {
3735 if (workarounds().restore_scissor_on_fbo_change
)
3736 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
3739 // Called after the FBO is checked for completeness.
3740 void GLES2DecoderImpl::OnUseFramebuffer() const {
3741 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
3742 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
3743 // The driver forgets the correct scissor when modifying the FBO binding.
3744 glScissor(state_
.scissor_x
,
3746 state_
.scissor_width
,
3747 state_
.scissor_height
);
3749 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3750 // it's unclear how this bug works.
3755 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
3756 Framebuffer
* framebuffer
= NULL
;
3757 GLuint service_id
= 0;
3758 if (client_id
!= 0) {
3759 framebuffer
= GetFramebuffer(client_id
);
3761 if (!group_
->bind_generates_resource()) {
3763 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3764 current_decoder_error_
= error::kGenericError
;
3768 // It's a new id so make a framebuffer framebuffer for it.
3769 glGenFramebuffersEXT(1, &service_id
);
3770 CreateFramebuffer(client_id
, service_id
);
3771 framebuffer
= GetFramebuffer(client_id
);
3772 IdAllocatorInterface
* id_allocator
=
3773 group_
->GetIdAllocator(id_namespaces::kFramebuffers
);
3774 id_allocator
->MarkAsUsed(client_id
);
3776 service_id
= framebuffer
->service_id();
3778 framebuffer
->MarkAsValid();
3780 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
3782 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
3783 state_
.bound_draw_framebuffer
= framebuffer
;
3785 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
3786 state_
.bound_read_framebuffer
= framebuffer
;
3789 clear_state_dirty_
= true;
3791 // If we are rendering to the backbuffer get the FBO id for any simulated
3793 if (framebuffer
== NULL
) {
3794 service_id
= GetBackbufferServiceId();
3797 glBindFramebufferEXT(target
, service_id
);
3801 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
3802 Renderbuffer
* renderbuffer
= NULL
;
3803 GLuint service_id
= 0;
3804 if (client_id
!= 0) {
3805 renderbuffer
= GetRenderbuffer(client_id
);
3806 if (!renderbuffer
) {
3807 if (!group_
->bind_generates_resource()) {
3809 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3810 current_decoder_error_
= error::kGenericError
;
3814 // It's a new id so make a renderbuffer renderbuffer for it.
3815 glGenRenderbuffersEXT(1, &service_id
);
3816 CreateRenderbuffer(client_id
, service_id
);
3817 renderbuffer
= GetRenderbuffer(client_id
);
3818 IdAllocatorInterface
* id_allocator
=
3819 group_
->GetIdAllocator(id_namespaces::kRenderbuffers
);
3820 id_allocator
->MarkAsUsed(client_id
);
3822 service_id
= renderbuffer
->service_id();
3824 renderbuffer
->MarkAsValid();
3826 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenerbuffer");
3827 state_
.bound_renderbuffer
= renderbuffer
;
3828 glBindRenderbufferEXT(target
, service_id
);
3831 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
3832 TextureRef
* texture_ref
= NULL
;
3833 GLuint service_id
= 0;
3834 if (client_id
!= 0) {
3835 texture_ref
= GetTexture(client_id
);
3837 if (!group_
->bind_generates_resource()) {
3838 LOG(ERROR
) << "glBindTexture: id not generated by glGenTextures";
3839 current_decoder_error_
= error::kGenericError
;
3843 // It's a new id so make a texture texture for it.
3844 glGenTextures(1, &service_id
);
3845 DCHECK_NE(0u, service_id
);
3846 CreateTexture(client_id
, service_id
);
3847 texture_ref
= GetTexture(client_id
);
3848 IdAllocatorInterface
* id_allocator
=
3849 group_
->GetIdAllocator(id_namespaces::kTextures
);
3850 id_allocator
->MarkAsUsed(client_id
);
3853 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
3855 Texture
* texture
= texture_ref
->texture();
3857 // Check the texture exists
3858 // Check that we are not trying to bind it to a different target.
3859 if (texture
->target() != 0 && texture
->target() != target
) {
3861 GL_INVALID_OPERATION
,
3862 "glBindTexture", "texture bound to more than 1 target.");
3865 if (texture
->IsStreamTexture() && target
!= GL_TEXTURE_EXTERNAL_OES
) {
3867 GL_INVALID_OPERATION
,
3868 "glBindTexture", "illegal target for stream texture.");
3871 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
3872 if (texture
->target() == 0) {
3873 texture_manager()->SetTarget(texture_ref
, target
);
3875 glBindTexture(target
, texture
->service_id());
3877 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
3878 unit
.bind_target
= target
;
3881 unit
.bound_texture_2d
= texture_ref
;
3883 case GL_TEXTURE_CUBE_MAP
:
3884 unit
.bound_texture_cube_map
= texture_ref
;
3886 case GL_TEXTURE_EXTERNAL_OES
:
3887 unit
.bound_texture_external_oes
= texture_ref
;
3888 if (texture
->IsStreamTexture()) {
3889 DCHECK(stream_texture_manager());
3890 StreamTexture
* stream_tex
=
3891 stream_texture_manager()->LookupStreamTexture(
3892 texture
->service_id());
3894 stream_tex
->Update();
3897 case GL_TEXTURE_RECTANGLE_ARB
:
3898 unit
.bound_texture_rectangle_arb
= texture_ref
;
3901 NOTREACHED(); // Validation should prevent us getting here.
3906 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
3907 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
3909 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
3910 glDisableVertexAttribArray(index
);
3915 "glDisableVertexAttribArray", "index out of range");
3919 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
3920 GLsizei numAttachments
,
3921 const GLenum
* attachments
) {
3922 Framebuffer
* framebuffer
=
3923 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
3925 // Validates the attachments. If one of them fails
3926 // the whole command fails.
3927 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
3929 !validators_
->attachment
.IsValid(attachments
[i
])) ||
3931 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
3932 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3933 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
3938 // Marks each one of them as not cleared
3939 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
3941 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
3946 switch (attachments
[i
]) {
3948 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
3951 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
3952 case GL_STENCIL_EXT
:
3953 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
3962 glDiscardFramebufferEXT(target
, numAttachments
, attachments
);
3965 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
3966 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
3967 glEnableVertexAttribArray(index
);
3970 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
3974 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
3975 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
3977 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
3979 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
3983 if (target
== GL_TEXTURE_CUBE_MAP
) {
3984 for (int i
= 0; i
< 6; ++i
) {
3985 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
3986 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
3988 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
3993 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
3995 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4000 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4001 // Workaround for Mac driver bug. In the large scheme of things setting
4002 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4003 // hit so there's probably no need to make this conditional. The bug appears
4004 // to be that if the filtering mode is set to something that doesn't require
4005 // mipmaps for rendering, or is never set to something other than the default,
4006 // then glGenerateMipmap misbehaves.
4007 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4008 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4010 glGenerateMipmapEXT(target
);
4011 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4012 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4013 texture_ref
->texture()->min_filter());
4015 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4016 if (error
== GL_NO_ERROR
) {
4017 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4021 bool GLES2DecoderImpl::GetHelper(
4022 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4023 DCHECK(num_written
);
4024 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4026 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4029 *params
= GL_RGBA
; // We don't support other formats.
4032 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4035 *params
= GL_UNSIGNED_BYTE
; // We don't support other types.
4038 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4041 *params
= group_
->max_fragment_uniform_vectors();
4044 case GL_MAX_VARYING_VECTORS
:
4047 *params
= group_
->max_varying_vectors();
4050 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4053 *params
= group_
->max_vertex_uniform_vectors();
4059 case GL_MAX_VIEWPORT_DIMS
:
4060 if (offscreen_target_frame_buffer_
.get()) {
4063 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4064 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4069 case GL_MAX_SAMPLES
:
4072 params
[0] = renderbuffer_manager()->max_samples();
4075 case GL_MAX_RENDERBUFFER_SIZE
:
4078 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4081 case GL_MAX_TEXTURE_SIZE
:
4084 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4087 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4090 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4093 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4096 params
[0] = group_
->max_color_attachments();
4099 case GL_MAX_DRAW_BUFFERS_ARB
:
4102 params
[0] = group_
->max_draw_buffers();
4109 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4110 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4117 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4118 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4121 case GL_STENCIL_BITS
:
4125 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4126 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4129 case GL_COMPRESSED_TEXTURE_FORMATS
:
4130 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4132 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4133 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4137 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4140 *params
= validators_
->compressed_texture_format
.GetValues().size();
4143 case GL_NUM_SHADER_BINARY_FORMATS
:
4146 *params
= validators_
->shader_binary_format
.GetValues().size();
4149 case GL_SHADER_BINARY_FORMATS
:
4150 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4152 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4153 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4157 case GL_SHADER_COMPILER
:
4163 case GL_ARRAY_BUFFER_BINDING
:
4166 if (state_
.bound_array_buffer
.get()) {
4167 GLuint client_id
= 0;
4168 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4170 *params
= client_id
;
4176 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4179 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4180 GLuint client_id
= 0;
4181 buffer_manager()->GetClientId(
4182 state_
.vertex_attrib_manager
->element_array_buffer()->
4183 service_id(), &client_id
);
4184 *params
= client_id
;
4190 case GL_FRAMEBUFFER_BINDING
:
4191 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4194 Framebuffer
* framebuffer
=
4195 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4197 GLuint client_id
= 0;
4198 framebuffer_manager()->GetClientId(
4199 framebuffer
->service_id(), &client_id
);
4200 *params
= client_id
;
4206 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4209 Framebuffer
* framebuffer
=
4210 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4212 GLuint client_id
= 0;
4213 framebuffer_manager()->GetClientId(
4214 framebuffer
->service_id(), &client_id
);
4215 *params
= client_id
;
4221 case GL_RENDERBUFFER_BINDING
:
4224 Renderbuffer
* renderbuffer
=
4225 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4227 *params
= renderbuffer
->client_id();
4233 case GL_CURRENT_PROGRAM
:
4236 if (state_
.current_program
.get()) {
4237 GLuint client_id
= 0;
4238 program_manager()->GetClientId(
4239 state_
.current_program
->service_id(), &client_id
);
4240 *params
= client_id
;
4246 case GL_VERTEX_ARRAY_BINDING_OES
:
4249 if (state_
.vertex_attrib_manager
.get() !=
4250 default_vertex_attrib_manager_
.get()) {
4251 GLuint client_id
= 0;
4252 vertex_array_manager_
->GetClientId(
4253 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4254 *params
= client_id
;
4260 case GL_TEXTURE_BINDING_2D
:
4263 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4264 if (unit
.bound_texture_2d
.get()) {
4265 *params
= unit
.bound_texture_2d
->client_id();
4271 case GL_TEXTURE_BINDING_CUBE_MAP
:
4274 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4275 if (unit
.bound_texture_cube_map
.get()) {
4276 *params
= unit
.bound_texture_cube_map
->client_id();
4282 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4285 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4286 if (unit
.bound_texture_external_oes
.get()) {
4287 *params
= unit
.bound_texture_external_oes
->client_id();
4293 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4296 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4297 if (unit
.bound_texture_rectangle_arb
.get()) {
4298 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4304 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4307 params
[0] = unpack_flip_y_
;
4310 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4313 params
[0] = unpack_premultiply_alpha_
;
4316 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4319 params
[0] = unpack_unpremultiply_alpha_
;
4323 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4324 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4327 Framebuffer
* framebuffer
=
4328 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4330 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4331 } else { // backbuffer
4332 if (pname
== GL_DRAW_BUFFER0_ARB
)
4333 params
[0] = group_
->draw_buffer();
4335 params
[0] = GL_NONE
;
4340 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4345 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4346 GLenum pname
, GLsizei
* num_values
) {
4347 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4350 return GetHelper(pname
, NULL
, num_values
);
4353 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4355 GLsizei num_written
= 0;
4356 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4357 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4358 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4359 GetHelper(pname
, values
.get(), &num_written
);
4361 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4362 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4365 glGetBooleanv(pname
, params
);
4369 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4371 GLsizei num_written
= 0;
4372 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4373 if (GetHelper(pname
, NULL
, &num_written
)) {
4374 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4375 GetHelper(pname
, values
.get(), &num_written
);
4376 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4377 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4380 glGetFloatv(pname
, params
);
4385 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4387 GLsizei num_written
;
4388 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4389 !GetHelper(pname
, params
, &num_written
)) {
4390 glGetIntegerv(pname
, params
);
4394 void GLES2DecoderImpl::DoGetProgramiv(
4395 GLuint program_id
, GLenum pname
, GLint
* params
) {
4396 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
4400 program
->GetProgramiv(pname
, params
);
4403 void GLES2DecoderImpl::DoGetBufferParameteriv(
4404 GLenum target
, GLenum pname
, GLint
* params
) {
4405 Buffer
* buffer
= GetBufferInfoForTarget(target
);
4408 GL_INVALID_OPERATION
, "glGetBufferParameteriv",
4409 "no buffer bound for target");
4413 case GL_BUFFER_SIZE
:
4414 *params
= buffer
->size();
4416 case GL_BUFFER_USAGE
:
4417 *params
= buffer
->usage();
4424 void GLES2DecoderImpl::DoBindAttribLocation(
4425 GLuint program_id
, GLuint index
, const char* name
) {
4426 if (!StringIsValidForGLES(name
)) {
4428 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
4431 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4433 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
4436 if (index
>= group_
->max_vertex_attribs()) {
4438 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
4441 Program
* program
= GetProgramInfoNotShader(
4442 program_id
, "glBindAttribLocation");
4446 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
4447 glBindAttribLocation(program
->service_id(), index
, name
);
4450 error::Error
GLES2DecoderImpl::HandleBindAttribLocation(
4451 uint32 immediate_data_size
, const cmds::BindAttribLocation
& c
) {
4452 GLuint program
= static_cast<GLuint
>(c
.program
);
4453 GLuint index
= static_cast<GLuint
>(c
.index
);
4454 uint32 name_size
= c
.data_size
;
4455 const char* name
= GetSharedMemoryAs
<const char*>(
4456 c
.name_shm_id
, c
.name_shm_offset
, name_size
);
4458 return error::kOutOfBounds
;
4460 String
name_str(name
, name_size
);
4461 DoBindAttribLocation(program
, index
, name_str
.c_str());
4462 return error::kNoError
;
4465 error::Error
GLES2DecoderImpl::HandleBindAttribLocationImmediate(
4466 uint32 immediate_data_size
, const cmds::BindAttribLocationImmediate
& c
) {
4467 GLuint program
= static_cast<GLuint
>(c
.program
);
4468 GLuint index
= static_cast<GLuint
>(c
.index
);
4469 uint32 name_size
= c
.data_size
;
4470 const char* name
= GetImmediateDataAs
<const char*>(
4471 c
, name_size
, immediate_data_size
);
4473 return error::kOutOfBounds
;
4475 String
name_str(name
, name_size
);
4476 DoBindAttribLocation(program
, index
, name_str
.c_str());
4477 return error::kNoError
;
4480 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
4481 uint32 immediate_data_size
, const cmds::BindAttribLocationBucket
& c
) {
4482 GLuint program
= static_cast<GLuint
>(c
.program
);
4483 GLuint index
= static_cast<GLuint
>(c
.index
);
4484 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4485 if (!bucket
|| bucket
->size() == 0) {
4486 return error::kInvalidArguments
;
4488 std::string name_str
;
4489 if (!bucket
->GetAsString(&name_str
)) {
4490 return error::kInvalidArguments
;
4492 DoBindAttribLocation(program
, index
, name_str
.c_str());
4493 return error::kNoError
;
4496 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4497 GLuint program_id
, GLint location
, const char* name
) {
4498 if (!StringIsValidForGLES(name
)) {
4501 "glBindUniformLocationCHROMIUM", "Invalid character");
4504 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4506 GL_INVALID_OPERATION
,
4507 "glBindUniformLocationCHROMIUM", "reserved prefix");
4510 if (location
< 0 || static_cast<uint32
>(location
) >=
4511 (group_
->max_fragment_uniform_vectors() +
4512 group_
->max_vertex_uniform_vectors()) * 4) {
4515 "glBindUniformLocationCHROMIUM", "location out of range");
4518 Program
* program
= GetProgramInfoNotShader(
4519 program_id
, "glBindUniformLocationCHROMIUM");
4523 if (!program
->SetUniformLocationBinding(name
, location
)) {
4526 "glBindUniformLocationCHROMIUM", "location out of range");
4530 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4531 uint32 immediate_data_size
, const cmds::BindUniformLocationCHROMIUM
& c
) {
4532 GLuint program
= static_cast<GLuint
>(c
.program
);
4533 GLint location
= static_cast<GLint
>(c
.location
);
4534 uint32 name_size
= c
.data_size
;
4535 const char* name
= GetSharedMemoryAs
<const char*>(
4536 c
.name_shm_id
, c
.name_shm_offset
, name_size
);
4538 return error::kOutOfBounds
;
4540 String
name_str(name
, name_size
);
4541 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4542 return error::kNoError
;
4545 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4546 uint32 immediate_data_size
,
4547 const cmds::BindUniformLocationCHROMIUMImmediate
& c
) {
4548 GLuint program
= static_cast<GLuint
>(c
.program
);
4549 GLint location
= static_cast<GLint
>(c
.location
);
4550 uint32 name_size
= c
.data_size
;
4551 const char* name
= GetImmediateDataAs
<const char*>(
4552 c
, name_size
, immediate_data_size
);
4554 return error::kOutOfBounds
;
4556 String
name_str(name
, name_size
);
4557 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4558 return error::kNoError
;
4561 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4562 uint32 immediate_data_size
,
4563 const cmds::BindUniformLocationCHROMIUMBucket
& c
) {
4564 GLuint program
= static_cast<GLuint
>(c
.program
);
4565 GLint location
= static_cast<GLint
>(c
.location
);
4566 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4567 if (!bucket
|| bucket
->size() == 0) {
4568 return error::kInvalidArguments
;
4570 std::string name_str
;
4571 if (!bucket
->GetAsString(&name_str
)) {
4572 return error::kInvalidArguments
;
4574 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4575 return error::kNoError
;
4578 error::Error
GLES2DecoderImpl::HandleDeleteShader(
4579 uint32 immediate_data_size
, const cmds::DeleteShader
& c
) {
4580 GLuint client_id
= c
.shader
;
4582 Shader
* shader
= GetShader(client_id
);
4584 if (!shader
->IsDeleted()) {
4585 glDeleteShader(shader
->service_id());
4586 shader_manager()->MarkAsDeleted(shader
);
4589 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
4592 return error::kNoError
;
4595 error::Error
GLES2DecoderImpl::HandleDeleteProgram(
4596 uint32 immediate_data_size
, const cmds::DeleteProgram
& c
) {
4597 GLuint client_id
= c
.program
;
4599 Program
* program
= GetProgram(client_id
);
4601 if (!program
->IsDeleted()) {
4602 program_manager()->MarkAsDeleted(shader_manager(), program
);
4606 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
4609 return error::kNoError
;
4612 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4613 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4614 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4615 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4616 id_allocator
->FreeID(ids
[ii
]);
4620 error::Error
GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4621 uint32 immediate_data_size
, const cmds::DeleteSharedIdsCHROMIUM
& c
) {
4622 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4623 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4625 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4626 return error::kOutOfBounds
;
4628 const GLuint
* ids
= GetSharedMemoryAs
<const GLuint
*>(
4629 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4631 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "DeleteSharedIdsCHROMIUM", "n < 0");
4632 return error::kNoError
;
4635 return error::kOutOfBounds
;
4637 DoDeleteSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4638 return error::kNoError
;
4641 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4642 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
4643 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4644 if (id_offset
== 0) {
4645 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4646 ids
[ii
] = id_allocator
->AllocateID();
4649 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4650 ids
[ii
] = id_allocator
->AllocateIDAtOrAbove(id_offset
);
4651 id_offset
= ids
[ii
] + 1;
4656 error::Error
GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4657 uint32 immediate_data_size
, const cmds::GenSharedIdsCHROMIUM
& c
) {
4658 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4659 GLuint id_offset
= static_cast<GLuint
>(c
.id_offset
);
4660 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4662 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4663 return error::kOutOfBounds
;
4665 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4666 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4668 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "GenSharedIdsCHROMIUM", "n < 0");
4669 return error::kNoError
;
4672 return error::kOutOfBounds
;
4674 DoGenSharedIdsCHROMIUM(namespace_id
, id_offset
, n
, ids
);
4675 return error::kNoError
;
4678 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4679 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4680 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4681 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4682 if (!id_allocator
->MarkAsUsed(ids
[ii
])) {
4683 for (GLsizei jj
= 0; jj
< ii
; ++jj
) {
4684 id_allocator
->FreeID(ids
[jj
]);
4687 GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM",
4688 "attempt to register id that already exists");
4694 error::Error
GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4695 uint32 immediate_data_size
, const cmds::RegisterSharedIdsCHROMIUM
& c
) {
4696 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4697 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4699 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4700 return error::kOutOfBounds
;
4702 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4703 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4705 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM", "n < 0");
4706 return error::kNoError
;
4709 return error::kOutOfBounds
;
4711 DoRegisterSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4712 return error::kNoError
;
4715 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
4716 DCHECK(!ShouldDeferDraws());
4717 if (CheckBoundFramebuffersValid("glClear")) {
4721 return error::kNoError
;
4724 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4725 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
4726 GLuint client_renderbuffer_id
) {
4727 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
4730 GL_INVALID_OPERATION
,
4731 "glFramebufferRenderbuffer", "no framebuffer bound");
4734 GLuint service_id
= 0;
4735 Renderbuffer
* renderbuffer
= NULL
;
4736 if (client_renderbuffer_id
) {
4737 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
4738 if (!renderbuffer
) {
4740 GL_INVALID_OPERATION
,
4741 "glFramebufferRenderbuffer", "unknown renderbuffer");
4744 service_id
= renderbuffer
->service_id();
4746 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4747 glFramebufferRenderbufferEXT(
4748 target
, attachment
, renderbuffertarget
, service_id
);
4749 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4750 if (error
== GL_NO_ERROR
) {
4751 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
4753 if (framebuffer
== state_
.bound_draw_framebuffer
.get()) {
4754 clear_state_dirty_
= true;
4759 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
4760 if (SetCapabilityState(cap
, false)) {
4765 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
4766 if (SetCapabilityState(cap
, true)) {
4771 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
4772 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
4773 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
4774 glDepthRange(znear
, zfar
);
4777 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
4778 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
4779 state_
.sample_coverage_invert
= (invert
!= 0);
4780 glSampleCoverage(state_
.sample_coverage_value
, invert
);
4783 // Assumes framebuffer is complete.
4784 void GLES2DecoderImpl::ClearUnclearedAttachments(
4785 GLenum target
, Framebuffer
* framebuffer
) {
4786 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
4787 // bind this to the DRAW point, clear then bind back to READ
4788 // TODO(gman): I don't think there is any guarantee that an FBO that
4789 // is complete on the READ attachment will be complete as a DRAW
4791 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
4792 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
4794 GLbitfield clear_bits
= 0;
4795 if (framebuffer
->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0
)) {
4798 (GLES2Util::GetChannelsForFormat(
4799 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
4801 glColorMask(true, true, true, true);
4802 clear_bits
|= GL_COLOR_BUFFER_BIT
;
4805 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
4806 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
4809 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
4812 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
4813 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
4816 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
4819 glDisable(GL_SCISSOR_TEST
);
4820 glClear(clear_bits
);
4822 framebuffer_manager()->MarkAttachmentsAsCleared(
4823 framebuffer
, renderbuffer_manager(), texture_manager());
4825 RestoreClearState();
4827 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
4828 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
4829 Framebuffer
* draw_framebuffer
=
4830 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4831 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
4832 GetBackbufferServiceId();
4833 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
4837 void GLES2DecoderImpl::RestoreClearState() {
4838 clear_state_dirty_
= true;
4840 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
4841 state_
.color_clear_alpha
);
4842 glClearStencil(state_
.stencil_clear
);
4843 glClearDepth(state_
.depth_clear
);
4844 if (state_
.enable_flags
.scissor_test
) {
4845 glEnable(GL_SCISSOR_TEST
);
4849 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
4850 Framebuffer
* framebuffer
=
4851 GetFramebufferInfoForTarget(target
);
4853 return GL_FRAMEBUFFER_COMPLETE
;
4855 GLenum completeness
= framebuffer
->IsPossiblyComplete();
4856 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
4857 return completeness
;
4859 return framebuffer
->GetStatus(texture_manager(), target
);
4862 void GLES2DecoderImpl::DoFramebufferTexture2D(
4863 GLenum target
, GLenum attachment
, GLenum textarget
,
4864 GLuint client_texture_id
, GLint level
) {
4865 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
4868 GL_INVALID_OPERATION
,
4869 "glFramebufferTexture2D", "no framebuffer bound.");
4872 GLuint service_id
= 0;
4873 TextureRef
* texture_ref
= NULL
;
4874 if (client_texture_id
) {
4875 texture_ref
= GetTexture(client_texture_id
);
4878 GL_INVALID_OPERATION
,
4879 "glFramebufferTexture2D", "unknown texture_ref");
4882 service_id
= texture_ref
->service_id();
4885 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
4888 "glFramebufferTexture2D", "level out of range");
4892 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferTexture2D");
4893 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
4894 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferTexture2D");
4895 if (error
== GL_NO_ERROR
) {
4896 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
);
4898 if (framebuffer
== state_
.bound_draw_framebuffer
.get()) {
4899 clear_state_dirty_
= true;
4904 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4905 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
4906 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
4909 GL_INVALID_OPERATION
,
4910 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
4913 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
4914 const Framebuffer::Attachment
* attachment_object
=
4915 framebuffer
->GetAttachment(attachment
);
4916 *params
= attachment_object
? attachment_object
->object_name() : 0;
4918 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
4922 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4923 GLenum target
, GLenum pname
, GLint
* params
) {
4924 Renderbuffer
* renderbuffer
=
4925 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4926 if (!renderbuffer
) {
4928 GL_INVALID_OPERATION
,
4929 "glGetRenderbufferParameteriv", "no renderbuffer bound");
4933 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
4934 *params
= renderbuffer
->internal_format();
4936 case GL_RENDERBUFFER_WIDTH
:
4937 *params
= renderbuffer
->width();
4939 case GL_RENDERBUFFER_HEIGHT
:
4940 *params
= renderbuffer
->height();
4943 glGetRenderbufferParameterivEXT(target
, pname
, params
);
4948 void GLES2DecoderImpl::DoBlitFramebufferEXT(
4949 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
4950 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
4951 GLbitfield mask
, GLenum filter
) {
4952 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
4953 if (!features().chromium_framebuffer_multisample
) {
4955 GL_INVALID_OPERATION
,
4956 "glBlitFramebufferEXT", "function not available");
4959 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
4963 glDisable(GL_SCISSOR_TEST
);
4965 glBlitFramebufferANGLE(
4966 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
4968 glBlitFramebufferEXT(
4969 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
4971 EnableDisable(GL_SCISSOR_TEST
, state_
.enable_flags
.scissor_test
);
4974 void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4975 GLenum target
, GLsizei samples
, GLenum internalformat
,
4976 GLsizei width
, GLsizei height
) {
4977 if (!features().chromium_framebuffer_multisample
) {
4979 GL_INVALID_OPERATION
,
4980 "glRenderbufferStorageMultisample", "function not available");
4984 Renderbuffer
* renderbuffer
=
4985 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4986 if (!renderbuffer
) {
4988 GL_INVALID_OPERATION
,
4989 "glRenderbufferStorageMultisample", "no renderbuffer bound");
4993 if (samples
> renderbuffer_manager()->max_samples()) {
4996 "glRenderbufferStorageMultisample", "samples too large");
5000 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5001 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5004 "glRenderbufferStorageMultisample", "dimensions too large");
5008 uint32 estimated_size
= 0;
5009 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5010 width
, height
, samples
, internalformat
, &estimated_size
)) {
5013 "glRenderbufferStorageMultsample", "dimensions too large");
5017 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5020 "glRenderbufferStorageMultsample", "out of memory");
5024 GLenum impl_format
= RenderbufferManager::
5025 InternalRenderbufferFormatToImplFormat(internalformat
);
5026 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
5028 glRenderbufferStorageMultisampleANGLE(
5029 target
, samples
, impl_format
, width
, height
);
5031 glRenderbufferStorageMultisampleEXT(
5032 target
, samples
, impl_format
, width
, height
);
5034 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
5035 if (error
== GL_NO_ERROR
) {
5036 // TODO(gman): If renderbuffers tracked which framebuffers they were
5037 // attached to we could just mark those framebuffers as not complete.
5038 framebuffer_manager()->IncFramebufferStateChangeCount();
5039 renderbuffer_manager()->SetInfo(
5040 renderbuffer
, samples
, internalformat
, width
, height
);
5044 void GLES2DecoderImpl::DoRenderbufferStorage(
5045 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5046 Renderbuffer
* renderbuffer
=
5047 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5048 if (!renderbuffer
) {
5050 GL_INVALID_OPERATION
,
5051 "glRenderbufferStorage", "no renderbuffer bound");
5055 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5056 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5058 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5062 uint32 estimated_size
= 0;
5063 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5064 width
, height
, 1, internalformat
, &estimated_size
)) {
5066 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5070 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5072 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5076 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5077 glRenderbufferStorageEXT(
5078 target
, RenderbufferManager::
5079 InternalRenderbufferFormatToImplFormat(internalformat
),
5081 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5082 if (error
== GL_NO_ERROR
) {
5083 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5084 // we could just mark those framebuffers as not complete.
5085 framebuffer_manager()->IncFramebufferStateChangeCount();
5086 renderbuffer_manager()->SetInfo(
5087 renderbuffer
, 1, internalformat
, width
, height
);
5091 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5092 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5093 Program
* program
= GetProgramInfoNotShader(
5094 program_id
, "glLinkProgram");
5099 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5100 ShaderTranslator
* vertex_translator
= NULL
;
5101 ShaderTranslator
* fragment_translator
= NULL
;
5102 if (use_shader_translator_
) {
5103 vertex_translator
= vertex_translator_
.get();
5104 fragment_translator
= fragment_translator_
.get();
5106 if (program
->Link(shader_manager(),
5108 fragment_translator
,
5109 feature_info_
.get(),
5110 shader_cache_callback_
)) {
5111 if (program
== state_
.current_program
.get()) {
5112 if (workarounds().use_current_program_after_successful_link
) {
5113 glUseProgram(program
->service_id());
5115 program_manager()->ClearUniforms(program
);
5120 void GLES2DecoderImpl::DoTexParameterf(
5121 GLenum target
, GLenum pname
, GLfloat param
) {
5122 TextureRef
* texture
= GetTextureInfoForTarget(target
);
5124 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5128 texture_manager()->SetParameter(
5129 "glTexParameterf", GetErrorState(), texture
, pname
,
5130 static_cast<GLint
>(param
));
5133 void GLES2DecoderImpl::DoTexParameteri(
5134 GLenum target
, GLenum pname
, GLint param
) {
5135 TextureRef
* texture
= GetTextureInfoForTarget(target
);
5137 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5141 texture_manager()->SetParameter(
5142 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5145 void GLES2DecoderImpl::DoTexParameterfv(
5146 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5147 TextureRef
* texture
= GetTextureInfoForTarget(target
);
5149 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5153 texture_manager()->SetParameter(
5154 "glTexParameterfv", GetErrorState(), texture
, pname
,
5155 static_cast<GLint
>(params
[0]));
5158 void GLES2DecoderImpl::DoTexParameteriv(
5159 GLenum target
, GLenum pname
, const GLint
* params
) {
5160 TextureRef
* texture
= GetTextureInfoForTarget(target
);
5163 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5167 texture_manager()->SetParameter(
5168 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5171 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5172 if (!state_
.current_program
.get()) {
5173 // The program does not exist.
5175 GL_INVALID_OPERATION
, function_name
, "no program in use");
5178 if (!state_
.current_program
->InUse()) {
5180 GL_INVALID_OPERATION
, function_name
, "program not linked");
5186 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5187 GLint location
, const char* function_name
) {
5188 if (!CheckCurrentProgram(function_name
)) {
5191 return location
!= -1;
5196 static const GLenum valid_int_vec1_types_list
[] = {
5200 GL_SAMPLER_2D_RECT_ARB
,
5202 GL_SAMPLER_EXTERNAL_OES
,
5205 static const GLenum valid_int_vec2_types_list
[] = {
5210 static const GLenum valid_int_vec3_types_list
[] = {
5215 static const GLenum valid_int_vec4_types_list
[] = {
5220 static const GLenum valid_float_vec1_types_list
[] = {
5225 static const GLenum valid_float_vec2_types_list
[] = {
5230 static const GLenum valid_float_vec3_types_list
[] = {
5235 static const GLenum valid_float_vec4_types_list
[] = {
5240 static const GLenum valid_float_mat2_types_list
[] = {
5244 static const GLenum valid_float_mat3_types_list
[] = {
5248 static const GLenum valid_float_mat4_types_list
[] = {
5252 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info
= {
5253 valid_int_vec1_types_list
,
5254 arraysize(valid_int_vec1_types_list
),
5257 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info
= {
5258 valid_int_vec2_types_list
,
5259 arraysize(valid_int_vec2_types_list
),
5262 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info
= {
5263 valid_int_vec3_types_list
,
5264 arraysize(valid_int_vec3_types_list
),
5267 static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info
= {
5268 valid_int_vec4_types_list
,
5269 arraysize(valid_int_vec4_types_list
),
5272 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info
= {
5273 valid_float_vec1_types_list
,
5274 arraysize(valid_float_vec1_types_list
),
5277 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info
= {
5278 valid_float_vec2_types_list
,
5279 arraysize(valid_float_vec2_types_list
),
5282 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info
= {
5283 valid_float_vec3_types_list
,
5284 arraysize(valid_float_vec3_types_list
),
5287 static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info
= {
5288 valid_float_vec4_types_list
,
5289 arraysize(valid_float_vec4_types_list
),
5292 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info
= {
5293 valid_float_mat2_types_list
,
5294 arraysize(valid_float_mat2_types_list
),
5297 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info
= {
5298 valid_float_mat3_types_list
,
5299 arraysize(valid_float_mat3_types_list
),
5302 static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info
= {
5303 valid_float_mat4_types_list
,
5304 arraysize(valid_float_mat4_types_list
),
5307 } // anonymous namespace.
5309 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5310 GLint fake_location
, const char* function_name
,
5311 const GLES2DecoderImpl::BaseUniformInfo
& base_info
,
5312 GLint
* real_location
, GLenum
* type
, GLsizei
* count
) {
5315 DCHECK(real_location
);
5317 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
5320 GLint array_index
= -1;
5321 const Program::UniformInfo
* info
=
5322 state_
.current_program
->GetUniformInfoByFakeLocation(
5323 fake_location
, real_location
, &array_index
);
5326 GL_INVALID_OPERATION
, function_name
, "unknown location");
5330 for (size_t ii
= 0; ii
< base_info
.num_valid_types
; ++ii
) {
5331 if (base_info
.valid_types
[ii
] == info
->type
) {
5338 GL_INVALID_OPERATION
, function_name
,
5339 "wrong uniform function for type");
5342 if (*count
> 1 && !info
->is_array
) {
5344 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
5347 *count
= std::min(info
->size
- array_index
, *count
);
5355 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
5358 GLint real_location
= -1;
5359 if (!PrepForSetUniformByLocation(
5360 fake_location
, "glUniform1iv", valid_int_vec1_base_info
,
5361 &real_location
, &type
, &count
)) {
5364 if (!state_
.current_program
->SetSamplers(
5365 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
5367 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
5370 glUniform1i(real_location
, v0
);
5373 void GLES2DecoderImpl::DoUniform1iv(
5374 GLint fake_location
, GLsizei count
, const GLint
*value
) {
5376 GLint real_location
= -1;
5377 if (!PrepForSetUniformByLocation(
5378 fake_location
, "glUniform1iv", valid_int_vec1_base_info
,
5379 &real_location
, &type
, &count
)) {
5382 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
5383 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
5384 if (!state_
.current_program
->SetSamplers(
5385 state_
.texture_units
.size(), fake_location
, count
, value
)) {
5387 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
5391 glUniform1iv(real_location
, count
, value
);
5394 void GLES2DecoderImpl::DoUniform1fv(
5395 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5397 GLint real_location
= -1;
5398 if (!PrepForSetUniformByLocation(
5399 fake_location
, "glUniform1fv", valid_float_vec1_base_info
,
5400 &real_location
, &type
, &count
)) {
5403 if (type
== GL_BOOL
) {
5404 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
5405 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5406 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5408 DoUniform1iv(real_location
, count
, temp
.get());
5410 glUniform1fv(real_location
, count
, value
);
5414 void GLES2DecoderImpl::DoUniform2fv(
5415 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5417 GLint real_location
= -1;
5418 if (!PrepForSetUniformByLocation(
5419 fake_location
, "glUniform2fv", valid_float_vec2_base_info
,
5420 &real_location
, &type
, &count
)) {
5423 if (type
== GL_BOOL_VEC2
) {
5424 GLsizei num_values
= count
* 2;
5425 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5426 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5427 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5429 glUniform2iv(real_location
, count
, temp
.get());
5431 glUniform2fv(real_location
, count
, value
);
5435 void GLES2DecoderImpl::DoUniform3fv(
5436 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5438 GLint real_location
= -1;
5439 if (!PrepForSetUniformByLocation(
5440 fake_location
, "glUniform3fv", valid_float_vec3_base_info
,
5441 &real_location
, &type
, &count
)) {
5444 if (type
== GL_BOOL_VEC3
) {
5445 GLsizei num_values
= count
* 3;
5446 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5447 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5448 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5450 glUniform3iv(real_location
, count
, temp
.get());
5452 glUniform3fv(real_location
, count
, value
);
5456 void GLES2DecoderImpl::DoUniform4fv(
5457 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5459 GLint real_location
= -1;
5460 if (!PrepForSetUniformByLocation(
5461 fake_location
, "glUniform4fv", valid_float_vec4_base_info
,
5462 &real_location
, &type
, &count
)) {
5465 if (type
== GL_BOOL_VEC4
) {
5466 GLsizei num_values
= count
* 4;
5467 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5468 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5469 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5471 glUniform4iv(real_location
, count
, temp
.get());
5473 glUniform4fv(real_location
, count
, value
);
5477 void GLES2DecoderImpl::DoUniform2iv(
5478 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5480 GLint real_location
= -1;
5481 if (!PrepForSetUniformByLocation(
5482 fake_location
, "glUniform2iv", valid_int_vec2_base_info
,
5483 &real_location
, &type
, &count
)) {
5486 glUniform2iv(real_location
, count
, value
);
5489 void GLES2DecoderImpl::DoUniform3iv(
5490 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5492 GLint real_location
= -1;
5493 if (!PrepForSetUniformByLocation(
5494 fake_location
, "glUniform3iv", valid_int_vec3_base_info
,
5495 &real_location
, &type
, &count
)) {
5498 glUniform3iv(real_location
, count
, value
);
5501 void GLES2DecoderImpl::DoUniform4iv(
5502 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5504 GLint real_location
= -1;
5505 if (!PrepForSetUniformByLocation(
5506 fake_location
, "glUniform4iv", valid_int_vec4_base_info
,
5507 &real_location
, &type
, &count
)) {
5510 glUniform4iv(real_location
, count
, value
);
5513 void GLES2DecoderImpl::DoUniformMatrix2fv(
5514 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5515 const GLfloat
* value
) {
5517 GLint real_location
= -1;
5518 if (!PrepForSetUniformByLocation(
5519 fake_location
, "glUniformMatrix2fv", valid_float_mat2_base_info
,
5520 &real_location
, &type
, &count
)) {
5523 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
5526 void GLES2DecoderImpl::DoUniformMatrix3fv(
5527 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5528 const GLfloat
* value
) {
5530 GLint real_location
= -1;
5531 if (!PrepForSetUniformByLocation(
5532 fake_location
, "glUniformMatrix3fv", valid_float_mat3_base_info
,
5533 &real_location
, &type
, &count
)) {
5536 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
5539 void GLES2DecoderImpl::DoUniformMatrix4fv(
5540 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5541 const GLfloat
* value
) {
5543 GLint real_location
= -1;
5544 if (!PrepForSetUniformByLocation(
5545 fake_location
, "glUniformMatrix4fv", valid_float_mat4_base_info
,
5546 &real_location
, &type
, &count
)) {
5549 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
5552 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
5553 GLuint service_id
= 0;
5554 Program
* program
= NULL
;
5556 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
5560 if (!program
->IsValid()) {
5561 // Program was not linked successfully. (ie, glLinkProgram)
5563 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
5566 service_id
= program
->service_id();
5568 if (state_
.current_program
.get()) {
5569 program_manager()->UnuseProgram(shader_manager(),
5570 state_
.current_program
.get());
5572 state_
.current_program
= program
;
5573 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
5574 glUseProgram(service_id
);
5575 if (state_
.current_program
.get()) {
5576 program_manager()->UseProgram(state_
.current_program
.get());
5580 void GLES2DecoderImpl::RenderWarning(
5581 const char* filename
, int line
, const std::string
& msg
) {
5582 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
5585 void GLES2DecoderImpl::PerformanceWarning(
5586 const char* filename
, int line
, const std::string
& msg
) {
5587 logger_
.LogMessage(filename
, line
,
5588 std::string("PERFORMANCE WARNING: ") + msg
);
5591 void GLES2DecoderImpl::ForceCompileShaderIfPending(Shader
* shader
) {
5592 if (shader
->compilation_status() ==
5593 Shader::PENDING_DEFERRED_COMPILE
) {
5594 ShaderTranslator
* translator
= NULL
;
5595 if (use_shader_translator_
) {
5596 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
5597 vertex_translator_
.get() : fragment_translator_
.get();
5599 // We know there will be no errors, because we only defer compilation on
5600 // shaders that were previously compiled successfully.
5601 program_manager()->ForceCompileShader(shader
->deferred_compilation_source(),
5604 feature_info_
.get());
5608 bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
5609 DCHECK(state_
.current_program
.get());
5610 // Only check if there are some unrenderable textures.
5611 if (!texture_manager()->HaveUnrenderableTextures()) {
5615 bool textures_set
= false;
5616 const Program::SamplerIndices
& sampler_indices
=
5617 state_
.current_program
->sampler_indices();
5618 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
5619 const Program::UniformInfo
* uniform_info
=
5620 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
5621 DCHECK(uniform_info
);
5622 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
5623 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
5624 if (texture_unit_index
< state_
.texture_units
.size()) {
5625 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
5626 TextureRef
* texture
=
5627 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
5628 if (!texture
|| !texture_manager()->CanRender(texture
)) {
5629 textures_set
= true;
5630 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
5632 GetBindTargetForSamplerType(uniform_info
->type
),
5633 texture_manager()->black_texture_id(uniform_info
->type
));
5634 LOCAL_RENDER_WARNING(
5635 std::string("texture bound to texture unit ") +
5636 base::IntToString(texture_unit_index
) +
5637 " is not renderable. It maybe non-power-of-2 and have"
5638 " incompatible texture filtering or is not"
5639 " 'texture complete'");
5642 // else: should this be an error?
5645 return textures_set
;
5648 void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
5649 DCHECK(state_
.current_program
.get());
5650 const Program::SamplerIndices
& sampler_indices
=
5651 state_
.current_program
->sampler_indices();
5652 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
5653 const Program::UniformInfo
* uniform_info
=
5654 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
5655 DCHECK(uniform_info
);
5656 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
5657 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
5658 if (texture_unit_index
< state_
.texture_units
.size()) {
5659 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
5660 TextureRef
* texture_ref
=
5661 uniform_info
->type
== GL_SAMPLER_2D
5662 ? texture_unit
.bound_texture_2d
.get()
5663 : texture_unit
.bound_texture_cube_map
.get();
5664 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
5665 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
5666 // Get the texture_ref info that was previously bound here.
5667 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
5668 ? texture_unit
.bound_texture_2d
.get()
5669 : texture_unit
.bound_texture_cube_map
.get();
5670 glBindTexture(texture_unit
.bind_target
,
5671 texture_ref
? texture_ref
->service_id() : 0);
5676 // Set the active texture back to whatever the user had it as.
5677 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
5680 bool GLES2DecoderImpl::ClearUnclearedTextures() {
5681 // Only check if there are some uncleared textures.
5682 if (!texture_manager()->HaveUnsafeTextures()) {
5686 // 1: Check all textures we are about to render with.
5687 if (state_
.current_program
.get()) {
5688 const Program::SamplerIndices
& sampler_indices
=
5689 state_
.current_program
->sampler_indices();
5690 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
5691 const Program::UniformInfo
* uniform_info
=
5692 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
5693 DCHECK(uniform_info
);
5694 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
5695 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
5696 if (texture_unit_index
< state_
.texture_units
.size()) {
5697 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
5698 TextureRef
* texture_ref
=
5699 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
5700 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
5701 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
5712 bool GLES2DecoderImpl::IsDrawValid(
5713 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
) {
5714 // NOTE: We specifically do not check current_program->IsValid() because
5715 // it could never be invalid since glUseProgram would have failed. While
5716 // glLinkProgram could later mark the program as invalid the previous
5717 // valid program will still function if it is still the current program.
5718 if (!state_
.current_program
.get()) {
5719 // The program does not exist.
5720 // But GL says no ERROR.
5721 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
5725 return state_
.vertex_attrib_manager
5726 ->ValidateBindings(function_name
,
5728 feature_info_
.get(),
5729 state_
.current_program
.get(),
5730 max_vertex_accessed
,
5734 bool GLES2DecoderImpl::SimulateAttrib0(
5735 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
5739 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
5742 const VertexAttrib
* attrib
=
5743 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
5744 // If it's enabled or it's not used then we don't need to do anything.
5745 bool attrib_0_used
=
5746 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
5747 if (attrib
->enabled() && attrib_0_used
) {
5751 // Make a buffer with a single repeated vec4 value enough to
5752 // simulate the constant value that is supposed to be here.
5753 // This is required to emulate GLES2 on GL.
5754 GLuint num_vertices
= max_vertex_accessed
+ 1;
5755 uint32 size_needed
= 0;
5757 if (num_vertices
== 0 ||
5758 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
5759 size_needed
> 0x7FFFFFFFU
) {
5760 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
5764 LOCAL_PERFORMANCE_WARNING(
5765 "Attribute 0 is disabled. This has signficant performance penalty");
5767 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
5768 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
5770 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
5772 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
5773 GLenum error
= glGetError();
5774 if (error
!= GL_NO_ERROR
) {
5776 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
5781 const Vec4
& value
= state_
.attrib_values
[0];
5784 (!attrib_0_buffer_matches_value_
||
5785 (value
.v
[0] != attrib_0_value_
.v
[0] ||
5786 value
.v
[1] != attrib_0_value_
.v
[1] ||
5787 value
.v
[2] != attrib_0_value_
.v
[2] ||
5788 value
.v
[3] != attrib_0_value_
.v
[3])))) {
5789 std::vector
<Vec4
> temp(num_vertices
, value
);
5790 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
5791 attrib_0_buffer_matches_value_
= true;
5792 attrib_0_value_
= value
;
5793 attrib_0_size_
= size_needed
;
5796 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
5798 if (attrib
->divisor())
5799 glVertexAttribDivisorANGLE(0, 0);
5805 void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index
) {
5806 const VertexAttrib
* attrib
=
5807 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
5808 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
5809 Buffer
* buffer
= attrib
->buffer();
5810 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
5811 glVertexAttribPointer(
5812 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
5813 attrib
->gl_stride(), ptr
);
5814 if (attrib
->divisor())
5815 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
5818 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
5821 // Never touch vertex attribute 0's state (in particular, never
5822 // disable it) when running on desktop GL because it will never be
5824 if (attrib_index
!= 0 ||
5825 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
5826 if (attrib
->enabled()) {
5827 glEnableVertexAttribArray(attrib_index
);
5829 glDisableVertexAttribArray(attrib_index
);
5834 bool GLES2DecoderImpl::SimulateFixedAttribs(
5835 const char* function_name
,
5836 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
5839 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
5842 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
5846 LOCAL_PERFORMANCE_WARNING(
5847 "GL_FIXED attributes have a signficant performance penalty");
5849 // NOTE: we could be smart and try to check if a buffer is used
5850 // twice in 2 different attribs, find the overlapping parts and therefore
5851 // duplicate the minimum amount of data but this whole code path is not meant
5852 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5853 // tests so we just add to the buffer attrib used.
5855 GLuint elements_needed
= 0;
5856 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
5857 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
5858 for (VertexAttribManager::VertexAttribList::const_iterator it
=
5859 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
5860 const VertexAttrib
* attrib
= *it
;
5861 const Program::VertexAttrib
* attrib_info
=
5862 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
5863 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
5864 max_vertex_accessed
);
5865 GLuint num_vertices
= max_accessed
+ 1;
5866 if (num_vertices
== 0) {
5868 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
5872 attrib
->CanAccess(max_accessed
) &&
5873 attrib
->type() == GL_FIXED
) {
5874 uint32 elements_used
= 0;
5875 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
5876 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
5878 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
5884 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
5885 uint32 size_needed
= 0;
5886 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
5887 size_needed
> 0x7FFFFFFFU
) {
5889 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
5893 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
5895 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
5896 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
5897 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
5898 GLenum error
= glGetError();
5899 if (error
!= GL_NO_ERROR
) {
5901 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
5906 // Copy the elements and convert to float
5907 GLintptr offset
= 0;
5908 for (VertexAttribManager::VertexAttribList::const_iterator it
=
5909 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
5910 const VertexAttrib
* attrib
= *it
;
5911 const Program::VertexAttrib
* attrib_info
=
5912 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
5913 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
5914 max_vertex_accessed
);
5915 GLuint num_vertices
= max_accessed
+ 1;
5916 if (num_vertices
== 0) {
5918 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
5922 attrib
->CanAccess(max_accessed
) &&
5923 attrib
->type() == GL_FIXED
) {
5924 int num_elements
= attrib
->size() * kSizeOfFloat
;
5925 int size
= num_elements
* num_vertices
;
5926 scoped_ptr
<float[]> data(new float[size
]);
5927 const int32
* src
= reinterpret_cast<const int32
*>(
5928 attrib
->buffer()->GetRange(attrib
->offset(), size
));
5929 const int32
* end
= src
+ num_elements
;
5930 float* dst
= data
.get();
5931 while (src
!= end
) {
5932 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
5934 glBufferSubData(GL_ARRAY_BUFFER
, offset
, size
, data
.get());
5935 glVertexAttribPointer(
5936 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
5937 reinterpret_cast<GLvoid
*>(offset
));
5945 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5946 // There's no need to call glVertexAttribPointer because we shadow all the
5947 // settings and passing GL_FIXED to it will not work.
5950 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
5954 error::Error
GLES2DecoderImpl::DoDrawArrays(
5955 const char* function_name
,
5960 GLsizei primcount
) {
5961 if (ShouldDeferDraws())
5962 return error::kDeferCommandUntilLater
;
5963 if (!validators_
->draw_mode
.IsValid(mode
)) {
5964 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
5965 return error::kNoError
;
5968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
5969 return error::kNoError
;
5971 if (primcount
< 0) {
5972 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
5973 return error::kNoError
;
5975 if (!CheckBoundFramebuffersValid(function_name
)) {
5976 return error::kNoError
;
5978 // We have to check this here because the prototype for glDrawArrays
5979 // is GLint not GLsizei.
5981 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
5982 return error::kNoError
;
5985 if (count
== 0 || (instanced
&& primcount
== 0)) {
5986 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
5987 return error::kNoError
;
5990 GLuint max_vertex_accessed
= first
+ count
- 1;
5991 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
5992 if (!ClearUnclearedTextures()) {
5993 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
5994 return error::kNoError
;
5996 bool simulated_attrib_0
= false;
5997 if (!SimulateAttrib0(
5998 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
5999 return error::kNoError
;
6001 bool simulated_fixed_attribs
= false;
6002 if (SimulateFixedAttribs(
6003 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6005 bool textures_set
= SetBlackTextureForNonRenderableTextures();
6008 glDrawArrays(mode
, first
, count
);
6010 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6012 ProcessPendingQueries();
6014 RestoreStateForNonRenderableTextures();
6016 if (simulated_fixed_attribs
) {
6017 RestoreStateForSimulatedFixedAttribs();
6020 if (simulated_attrib_0
) {
6021 RestoreStateForAttrib(0);
6024 return error::kNoError
;
6027 error::Error
GLES2DecoderImpl::HandleDrawArrays(
6028 uint32 immediate_data_size
, const cmds::DrawArrays
& c
) {
6029 return DoDrawArrays("glDrawArrays",
6031 static_cast<GLenum
>(c
.mode
),
6032 static_cast<GLint
>(c
.first
),
6033 static_cast<GLsizei
>(c
.count
),
6037 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6038 uint32 immediate_data_size
, const cmds::DrawArraysInstancedANGLE
& c
) {
6039 if (!features().angle_instanced_arrays
) {
6041 GL_INVALID_OPERATION
,
6042 "glDrawArraysInstancedANGLE", "function not available");
6043 return error::kNoError
;
6045 return DoDrawArrays("glDrawArraysIntancedANGLE",
6047 static_cast<GLenum
>(c
.mode
),
6048 static_cast<GLint
>(c
.first
),
6049 static_cast<GLsizei
>(c
.count
),
6050 static_cast<GLsizei
>(c
.primcount
));
6053 error::Error
GLES2DecoderImpl::DoDrawElements(
6054 const char* function_name
,
6060 GLsizei primcount
) {
6061 if (ShouldDeferDraws())
6062 return error::kDeferCommandUntilLater
;
6063 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6065 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6066 return error::kNoError
;
6070 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6071 return error::kNoError
;
6074 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6075 return error::kNoError
;
6077 if (!validators_
->draw_mode
.IsValid(mode
)) {
6078 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6079 return error::kNoError
;
6081 if (!validators_
->index_type
.IsValid(type
)) {
6082 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6083 return error::kNoError
;
6085 if (primcount
< 0) {
6086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6087 return error::kNoError
;
6090 if (!CheckBoundFramebuffersValid(function_name
)) {
6091 return error::kNoError
;
6094 if (count
== 0 || (instanced
&& primcount
== 0)) {
6095 return error::kNoError
;
6098 GLuint max_vertex_accessed
;
6099 Buffer
* element_array_buffer
=
6100 state_
.vertex_attrib_manager
->element_array_buffer();
6102 if (!element_array_buffer
->GetMaxValueForRange(
6103 offset
, count
, type
, &max_vertex_accessed
)) {
6105 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6106 return error::kNoError
;
6109 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
6110 if (!ClearUnclearedTextures()) {
6111 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6112 return error::kNoError
;
6114 bool simulated_attrib_0
= false;
6115 if (!SimulateAttrib0(
6116 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6117 return error::kNoError
;
6119 bool simulated_fixed_attribs
= false;
6120 if (SimulateFixedAttribs(
6121 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6123 bool textures_set
= SetBlackTextureForNonRenderableTextures();
6125 // TODO(gman): Refactor to hide these details in BufferManager or
6126 // VertexAttribManager.
6127 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6128 bool used_client_side_array
= false;
6129 if (element_array_buffer
->IsClientSideArray()) {
6130 used_client_side_array
= true;
6131 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6132 indices
= element_array_buffer
->GetRange(offset
, 0);
6136 glDrawElements(mode
, count
, type
, indices
);
6138 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6141 if (used_client_side_array
) {
6142 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6143 element_array_buffer
->service_id());
6146 ProcessPendingQueries();
6148 RestoreStateForNonRenderableTextures();
6150 if (simulated_fixed_attribs
) {
6151 RestoreStateForSimulatedFixedAttribs();
6154 if (simulated_attrib_0
) {
6155 RestoreStateForAttrib(0);
6158 return error::kNoError
;
6161 error::Error
GLES2DecoderImpl::HandleDrawElements(
6162 uint32 immediate_data_size
, const cmds::DrawElements
& c
) {
6163 return DoDrawElements("glDrawElements",
6165 static_cast<GLenum
>(c
.mode
),
6166 static_cast<GLsizei
>(c
.count
),
6167 static_cast<GLenum
>(c
.type
),
6168 static_cast<int32
>(c
.index_offset
),
6172 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6173 uint32 immediate_data_size
, const cmds::DrawElementsInstancedANGLE
& c
) {
6174 if (!features().angle_instanced_arrays
) {
6176 GL_INVALID_OPERATION
,
6177 "glDrawElementsInstancedANGLE", "function not available");
6178 return error::kNoError
;
6180 return DoDrawElements("glDrawElementsInstancedANGLE",
6182 static_cast<GLenum
>(c
.mode
),
6183 static_cast<GLsizei
>(c
.count
),
6184 static_cast<GLenum
>(c
.type
),
6185 static_cast<int32
>(c
.index_offset
),
6186 static_cast<GLsizei
>(c
.primcount
));
6189 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6190 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
6191 GLuint max_vertex_accessed
= 0;
6192 Buffer
* buffer
= GetBuffer(buffer_id
);
6194 // TODO(gman): Should this be a GL error or a command buffer error?
6196 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6198 if (!buffer
->GetMaxValueForRange(
6199 offset
, count
, type
, &max_vertex_accessed
)) {
6200 // TODO(gman): Should this be a GL error or a command buffer error?
6202 GL_INVALID_OPERATION
,
6203 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6206 return max_vertex_accessed
;
6209 // Calls glShaderSource for the various versions of the ShaderSource command.
6210 // Assumes that data / data_size points to a piece of memory that is in range
6211 // of whatever context it came from (shared memory, immediate memory, bucket
6213 error::Error
GLES2DecoderImpl::ShaderSourceHelper(
6214 GLuint client_id
, const char* data
, uint32 data_size
) {
6215 std::string
str(data
, data
+ data_size
);
6216 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
6218 return error::kNoError
;
6220 // Note: We don't actually call glShaderSource here. We wait until
6221 // the call to glCompileShader.
6222 shader
->UpdateSource(str
.c_str());
6223 return error::kNoError
;
6226 error::Error
GLES2DecoderImpl::HandleShaderSource(
6227 uint32 immediate_data_size
, const cmds::ShaderSource
& c
) {
6228 uint32 data_size
= c
.data_size
;
6229 const char* data
= GetSharedMemoryAs
<const char*>(
6230 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
6232 return error::kOutOfBounds
;
6234 return ShaderSourceHelper(c
.shader
, data
, data_size
);
6237 error::Error
GLES2DecoderImpl::HandleShaderSourceImmediate(
6238 uint32 immediate_data_size
, const cmds::ShaderSourceImmediate
& c
) {
6239 uint32 data_size
= c
.data_size
;
6240 const char* data
= GetImmediateDataAs
<const char*>(
6241 c
, data_size
, immediate_data_size
);
6243 return error::kOutOfBounds
;
6245 return ShaderSourceHelper(c
.shader
, data
, data_size
);
6248 error::Error
GLES2DecoderImpl::HandleShaderSourceBucket(
6249 uint32 immediate_data_size
, const cmds::ShaderSourceBucket
& c
) {
6250 Bucket
* bucket
= GetBucket(c
.data_bucket_id
);
6251 if (!bucket
|| bucket
->size() == 0) {
6252 return error::kInvalidArguments
;
6254 return ShaderSourceHelper(
6255 c
.shader
, bucket
->GetDataAs
<const char*>(0, bucket
->size() - 1),
6256 bucket
->size() - 1);
6259 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
6260 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6261 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
6265 ShaderTranslator
* translator
= NULL
;
6266 if (use_shader_translator_
) {
6267 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
6268 vertex_translator_
.get() : fragment_translator_
.get();
6271 program_manager()->DoCompileShader(shader
, translator
, feature_info_
.get());
6274 void GLES2DecoderImpl::DoGetShaderiv(
6275 GLuint shader_id
, GLenum pname
, GLint
* params
) {
6276 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
6281 case GL_SHADER_SOURCE_LENGTH
:
6282 *params
= shader
->source() ? shader
->source()->size() + 1 : 0;
6284 case GL_COMPILE_STATUS
:
6285 *params
= compile_shader_always_succeeds_
? true : shader
->IsValid();
6287 case GL_INFO_LOG_LENGTH
:
6288 *params
= shader
->log_info() ? shader
->log_info()->size() + 1 : 0;
6290 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
6291 ForceCompileShaderIfPending(shader
);
6292 *params
= shader
->translated_source() ?
6293 shader
->translated_source()->size() + 1 : 0;
6298 glGetShaderiv(shader
->service_id(), pname
, params
);
6301 error::Error
GLES2DecoderImpl::HandleGetShaderSource(
6302 uint32 immediate_data_size
, const cmds::GetShaderSource
& c
) {
6303 GLuint shader_id
= c
.shader
;
6304 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6305 Bucket
* bucket
= CreateBucket(bucket_id
);
6306 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
6307 if (!shader
|| !shader
->source()) {
6309 return error::kNoError
;
6311 bucket
->SetFromString(shader
->source()->c_str());
6312 return error::kNoError
;
6315 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6316 uint32 immediate_data_size
,
6317 const cmds::GetTranslatedShaderSourceANGLE
& c
) {
6318 GLuint shader_id
= c
.shader
;
6319 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6320 Bucket
* bucket
= CreateBucket(bucket_id
);
6321 Shader
* shader
= GetShaderInfoNotProgram(
6322 shader_id
, "glTranslatedGetShaderSourceANGLE");
6325 return error::kNoError
;
6327 ForceCompileShaderIfPending(shader
);
6329 bucket
->SetFromString(shader
->translated_source() ?
6330 shader
->translated_source()->c_str() : NULL
);
6331 return error::kNoError
;
6334 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
6335 uint32 immediate_data_size
, const cmds::GetProgramInfoLog
& c
) {
6336 GLuint program_id
= c
.program
;
6337 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6338 Bucket
* bucket
= CreateBucket(bucket_id
);
6339 Program
* program
= GetProgramInfoNotShader(
6340 program_id
, "glGetProgramInfoLog");
6341 if (!program
|| !program
->log_info()) {
6342 bucket
->SetFromString("");
6343 return error::kNoError
;
6345 bucket
->SetFromString(program
->log_info()->c_str());
6346 return error::kNoError
;
6349 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
6350 uint32 immediate_data_size
, const cmds::GetShaderInfoLog
& c
) {
6351 GLuint shader_id
= c
.shader
;
6352 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6353 Bucket
* bucket
= CreateBucket(bucket_id
);
6354 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
6355 if (!shader
|| !shader
->log_info()) {
6356 bucket
->SetFromString("");
6357 return error::kNoError
;
6359 bucket
->SetFromString(shader
->log_info()->c_str());
6360 return error::kNoError
;
6363 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
6364 return state_
.GetEnabled(cap
);
6367 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
6368 const Buffer
* buffer
= GetBuffer(client_id
);
6369 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
6372 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
6373 const Framebuffer
* framebuffer
=
6374 GetFramebuffer(client_id
);
6375 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
6378 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
6379 // IsProgram is true for programs as soon as they are created, until they are
6380 // deleted and no longer in use.
6381 const Program
* program
= GetProgram(client_id
);
6382 return program
!= NULL
&& !program
->IsDeleted();
6385 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
6386 const Renderbuffer
* renderbuffer
=
6387 GetRenderbuffer(client_id
);
6388 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
6391 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
6392 // IsShader is true for shaders as soon as they are created, until they
6393 // are deleted and not attached to any programs.
6394 const Shader
* shader
= GetShader(client_id
);
6395 return shader
!= NULL
&& !shader
->IsDeleted();
6398 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
6399 const TextureRef
* texture_ref
= GetTexture(client_id
);
6400 return texture_ref
&& texture_ref
->texture()->IsValid();
6403 void GLES2DecoderImpl::DoAttachShader(
6404 GLuint program_client_id
, GLint shader_client_id
) {
6405 Program
* program
= GetProgramInfoNotShader(
6406 program_client_id
, "glAttachShader");
6410 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
6414 if (!program
->AttachShader(shader_manager(), shader
)) {
6416 GL_INVALID_OPERATION
,
6418 "can not attach more than one shader of the same type.");
6421 glAttachShader(program
->service_id(), shader
->service_id());
6424 void GLES2DecoderImpl::DoDetachShader(
6425 GLuint program_client_id
, GLint shader_client_id
) {
6426 Program
* program
= GetProgramInfoNotShader(
6427 program_client_id
, "glDetachShader");
6431 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
6435 if (!program
->DetachShader(shader_manager(), shader
)) {
6437 GL_INVALID_OPERATION
,
6438 "glDetachShader", "shader not attached to program");
6441 glDetachShader(program
->service_id(), shader
->service_id());
6444 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
6445 Program
* program
= GetProgramInfoNotShader(
6446 program_client_id
, "glValidateProgram");
6450 program
->Validate();
6453 void GLES2DecoderImpl::GetVertexAttribHelper(
6454 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
6456 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
6457 Buffer
* buffer
= attrib
->buffer();
6458 if (buffer
&& !buffer
->IsDeleted()) {
6460 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
6461 *params
= client_id
;
6465 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
6466 *params
= attrib
->enabled();
6468 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
6469 *params
= attrib
->size();
6471 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
6472 *params
= attrib
->gl_stride();
6474 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
6475 *params
= attrib
->type();
6477 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
6478 *params
= attrib
->normalized();
6480 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
6481 *params
= attrib
->divisor();
6489 void GLES2DecoderImpl::DoGetVertexAttribfv(
6490 GLuint index
, GLenum pname
, GLfloat
* params
) {
6491 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
6494 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
6498 case GL_CURRENT_VERTEX_ATTRIB
: {
6499 const Vec4
& value
= state_
.attrib_values
[index
];
6500 params
[0] = value
.v
[0];
6501 params
[1] = value
.v
[1];
6502 params
[2] = value
.v
[2];
6503 params
[3] = value
.v
[3];
6508 GetVertexAttribHelper(attrib
, pname
, &value
);
6509 *params
= static_cast<GLfloat
>(value
);
6515 void GLES2DecoderImpl::DoGetVertexAttribiv(
6516 GLuint index
, GLenum pname
, GLint
* params
) {
6517 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
6520 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
6524 case GL_CURRENT_VERTEX_ATTRIB
: {
6525 const Vec4
& value
= state_
.attrib_values
[index
];
6526 params
[0] = static_cast<GLint
>(value
.v
[0]);
6527 params
[1] = static_cast<GLint
>(value
.v
[1]);
6528 params
[2] = static_cast<GLint
>(value
.v
[2]);
6529 params
[3] = static_cast<GLint
>(value
.v
[3]);
6533 GetVertexAttribHelper(attrib
, pname
, params
);
6538 bool GLES2DecoderImpl::SetVertexAttribValue(
6539 const char* function_name
, GLuint index
, const GLfloat
* value
) {
6540 if (index
>= state_
.attrib_values
.size()) {
6541 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
6544 Vec4
& v
= state_
.attrib_values
[index
];
6552 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
6553 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
6554 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
6555 glVertexAttrib1f(index
, v0
);
6559 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
6560 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
6561 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
6562 glVertexAttrib2f(index
, v0
, v1
);
6566 void GLES2DecoderImpl::DoVertexAttrib3f(
6567 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
6568 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
6569 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
6570 glVertexAttrib3f(index
, v0
, v1
, v2
);
6574 void GLES2DecoderImpl::DoVertexAttrib4f(
6575 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
6576 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
6577 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
6578 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
6582 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
6583 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
6584 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
6585 glVertexAttrib1fv(index
, v
);
6589 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
6590 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
6591 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
6592 glVertexAttrib2fv(index
, v
);
6596 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
6597 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
6598 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
6599 glVertexAttrib3fv(index
, v
);
6603 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
6604 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
6605 glVertexAttrib4fv(index
, v
);
6609 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
6610 uint32 immediate_data_size
, const cmds::VertexAttribPointer
& c
) {
6612 if (!state_
.bound_array_buffer
.get() ||
6613 state_
.bound_array_buffer
->IsDeleted()) {
6614 if (state_
.vertex_attrib_manager
.get() ==
6615 default_vertex_attrib_manager_
.get()) {
6617 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
6618 return error::kNoError
;
6619 } else if (c
.offset
!= 0) {
6622 "glVertexAttribPointer", "client side arrays are not allowed");
6623 return error::kNoError
;
6627 GLuint indx
= c
.indx
;
6628 GLint size
= c
.size
;
6629 GLenum type
= c
.type
;
6630 GLboolean normalized
= c
.normalized
;
6631 GLsizei stride
= c
.stride
;
6632 GLsizei offset
= c
.offset
;
6633 const void* ptr
= reinterpret_cast<const void*>(offset
);
6634 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
6635 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
6636 return error::kNoError
;
6638 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
6640 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
6641 return error::kNoError
;
6643 if (indx
>= group_
->max_vertex_attribs()) {
6645 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
6646 return error::kNoError
;
6650 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
6651 return error::kNoError
;
6655 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
6656 return error::kNoError
;
6660 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
6661 return error::kNoError
;
6663 GLsizei component_size
=
6664 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
6665 if (offset
% component_size
> 0) {
6667 GL_INVALID_OPERATION
,
6668 "glVertexAttribPointer", "offset not valid for type");
6669 return error::kNoError
;
6671 if (stride
% component_size
> 0) {
6673 GL_INVALID_OPERATION
,
6674 "glVertexAttribPointer", "stride not valid for type");
6675 return error::kNoError
;
6677 state_
.vertex_attrib_manager
6678 ->SetAttribInfo(indx
,
6679 state_
.bound_array_buffer
.get(),
6684 stride
!= 0 ? stride
: component_size
* size
,
6686 if (type
!= GL_FIXED
) {
6687 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
6689 return error::kNoError
;
6692 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
6694 state_
.viewport_x
= x
;
6695 state_
.viewport_y
= y
;
6696 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
6697 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
6698 glViewport(x
, y
, width
, height
);
6701 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6702 uint32 immediate_data_size
, const cmds::VertexAttribDivisorANGLE
& c
) {
6703 if (!features().angle_instanced_arrays
) {
6705 GL_INVALID_OPERATION
,
6706 "glVertexAttribDivisorANGLE", "function not available");
6708 GLuint index
= c
.index
;
6709 GLuint divisor
= c
.divisor
;
6710 if (index
>= group_
->max_vertex_attribs()) {
6713 "glVertexAttribDivisorANGLE", "index out of range");
6714 return error::kNoError
;
6717 state_
.vertex_attrib_manager
->SetDivisor(
6720 glVertexAttribDivisorANGLE(index
, divisor
);
6721 return error::kNoError
;
6724 void GLES2DecoderImpl::FinishReadPixels(
6725 const cmds::ReadPixels
& c
,
6727 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6728 GLsizei width
= c
.width
;
6729 GLsizei height
= c
.height
;
6730 GLenum format
= c
.format
;
6731 GLenum type
= c
.type
;
6732 typedef cmds::ReadPixels::Result Result
;
6734 Result
* result
= NULL
;
6735 if (c
.result_shm_id
!= 0) {
6736 result
= GetSharedMemoryAs
<Result
*>(
6737 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
6740 glDeleteBuffersARB(1, &buffer
);
6745 GLES2Util::ComputeImageDataSizes(
6746 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
6748 void* pixels
= GetSharedMemoryAs
<void*>(
6749 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
6752 glDeleteBuffersARB(1, &buffer
);
6758 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
6759 void* data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
6760 memcpy(pixels
, data
, pixels_size
);
6761 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6762 // have to restore the state.
6763 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
6764 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
6765 glDeleteBuffersARB(1, &buffer
);
6768 if (result
!= NULL
) {
6772 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
6773 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
6774 if ((channels_exist
& 0x0008) == 0 &&
6775 workarounds().clear_alpha_in_readpixels
) {
6776 // Set the alpha to 255 because some drivers are buggy in this regard.
6779 uint32 unpadded_row_size
;
6780 uint32 padded_row_size
;
6781 if (!GLES2Util::ComputeImageDataSizes(
6782 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
6783 &unpadded_row_size
, &padded_row_size
)) {
6786 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6787 // of this implementation.
6788 if (type
!= GL_UNSIGNED_BYTE
) {
6795 int offset
= (format
== GL_ALPHA
) ? 0 : 3;
6796 int step
= (format
== GL_ALPHA
) ? 1 : 4;
6797 uint8
* dst
= static_cast<uint8
*>(pixels
) + offset
;
6798 for (GLint yy
= 0; yy
< height
; ++yy
) {
6799 uint8
* end
= dst
+ unpadded_row_size
;
6800 for (uint8
* d
= dst
; d
< end
; d
+= step
) {
6803 dst
+= padded_row_size
;
6814 error::Error
GLES2DecoderImpl::HandleReadPixels(
6815 uint32 immediate_data_size
, const cmds::ReadPixels
& c
) {
6816 if (ShouldDeferReads())
6817 return error::kDeferCommandUntilLater
;
6820 GLsizei width
= c
.width
;
6821 GLsizei height
= c
.height
;
6822 GLenum format
= c
.format
;
6823 GLenum type
= c
.type
;
6824 GLboolean async
= c
.async
;
6825 if (width
< 0 || height
< 0) {
6826 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
6827 return error::kNoError
;
6829 typedef cmds::ReadPixels::Result Result
;
6831 if (!GLES2Util::ComputeImageDataSizes(
6832 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
6834 return error::kOutOfBounds
;
6836 void* pixels
= GetSharedMemoryAs
<void*>(
6837 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
6839 return error::kOutOfBounds
;
6841 Result
* result
= NULL
;
6842 if (c
.result_shm_id
!= 0) {
6843 result
= GetSharedMemoryAs
<Result
*>(
6844 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
6846 return error::kOutOfBounds
;
6850 if (!validators_
->read_pixel_format
.IsValid(format
)) {
6851 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
6852 return error::kNoError
;
6854 if (!validators_
->pixel_type
.IsValid(type
)) {
6855 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
6856 return error::kNoError
;
6858 if (width
== 0 || height
== 0) {
6859 return error::kNoError
;
6862 // Get the size of the current fbo or backbuffer.
6863 gfx::Size max_size
= GetBoundReadFrameBufferSize();
6867 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
6869 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
6870 return error::kNoError
;
6873 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6874 return error::kNoError
;
6877 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
6879 ScopedResolvedFrameBufferBinder
binder(this, false, true);
6881 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
6882 // The user requested an out of range area. Get the results 1 line
6885 uint32 unpadded_row_size
;
6886 uint32 padded_row_size
;
6887 if (!GLES2Util::ComputeImageDataSizes(
6888 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
6889 &unpadded_row_size
, &padded_row_size
)) {
6891 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
6892 return error::kNoError
;
6895 GLint dest_x_offset
= std::max(-x
, 0);
6896 uint32 dest_row_offset
;
6897 if (!GLES2Util::ComputeImageDataSizes(
6898 dest_x_offset
, 1, format
, type
, state_
.pack_alignment
, &dest_row_offset
,
6901 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
6902 return error::kNoError
;
6905 // Copy each row into the larger dest rect.
6906 int8
* dst
= static_cast<int8
*>(pixels
);
6907 GLint read_x
= std::max(0, x
);
6908 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
6909 GLint read_width
= read_end_x
- read_x
;
6910 for (GLint yy
= 0; yy
< height
; ++yy
) {
6914 memset(dst
, 0, unpadded_row_size
);
6916 // If the row is in range, copy it.
6917 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
6919 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
6921 dst
+= padded_row_size
;
6924 if (async
&& features().use_async_readpixels
) {
6926 glGenBuffersARB(1, &buffer
);
6927 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
6928 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, GL_STREAM_READ
);
6929 GLenum error
= glGetError();
6930 if (error
== GL_NO_ERROR
) {
6931 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
6932 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
6933 new FenceCallback()));
6934 WaitForReadPixels(base::Bind(
6935 &GLES2DecoderImpl::FinishReadPixels
,
6936 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
6937 <GLES2DecoderImpl
>(this),
6939 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
6940 return error::kNoError
;
6943 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
6945 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
6946 if (error
== GL_NO_ERROR
) {
6947 if (result
!= NULL
) {
6950 FinishReadPixels(c
, 0);
6953 return error::kNoError
;
6956 error::Error
GLES2DecoderImpl::HandlePixelStorei(
6957 uint32 immediate_data_size
, const cmds::PixelStorei
& c
) {
6958 GLenum pname
= c
.pname
;
6959 GLenum param
= c
.param
;
6960 if (!validators_
->pixel_store
.IsValid(pname
)) {
6961 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
6962 return error::kNoError
;
6965 case GL_PACK_ALIGNMENT
:
6966 case GL_UNPACK_ALIGNMENT
:
6967 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
6969 GL_INVALID_VALUE
, "glPixelStore", "param GL_INVALID_VALUE");
6970 return error::kNoError
;
6973 case GL_UNPACK_FLIP_Y_CHROMIUM
:
6974 unpack_flip_y_
= (param
!= 0);
6975 return error::kNoError
;
6976 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
6977 unpack_premultiply_alpha_
= (param
!= 0);
6978 return error::kNoError
;
6979 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
6980 unpack_unpremultiply_alpha_
= (param
!= 0);
6981 return error::kNoError
;
6985 glPixelStorei(pname
, param
);
6987 case GL_PACK_ALIGNMENT
:
6988 state_
.pack_alignment
= param
;
6990 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
6991 state_
.pack_reverse_row_order
= (param
!= 0);
6993 case GL_UNPACK_ALIGNMENT
:
6994 state_
.unpack_alignment
= param
;
6997 // Validation should have prevented us from getting here.
7001 return error::kNoError
;
7004 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7005 uint32 immediate_data_size
, const cmds::PostSubBufferCHROMIUM
& c
) {
7006 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7007 if (!surface_
->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
7009 GL_INVALID_OPERATION
,
7010 "glPostSubBufferCHROMIUM", "command not supported by surface");
7011 return error::kNoError
;
7013 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
7014 return error::kNoError
;
7016 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
7017 return error::kLostContext
;
7021 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
7022 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7023 const std::string
& name_str
) {
7024 if (!StringIsValidForGLES(name_str
.c_str())) {
7026 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
7027 return error::kNoError
;
7029 Program
* program
= GetProgramInfoNotShader(
7030 client_id
, "glGetAttribLocation");
7032 return error::kNoError
;
7034 if (!program
->IsValid()) {
7036 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
7037 return error::kNoError
;
7039 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7040 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7042 return error::kOutOfBounds
;
7044 // Require the client to init this incase the context is lost and we are no
7045 // longer executing commands.
7046 if (*location
!= -1) {
7047 return error::kGenericError
;
7049 *location
= program
->GetAttribLocation(name_str
);
7050 return error::kNoError
;
7053 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
7054 uint32 immediate_data_size
, const cmds::GetAttribLocation
& c
) {
7055 uint32 name_size
= c
.data_size
;
7056 const char* name
= GetSharedMemoryAs
<const char*>(
7057 c
.name_shm_id
, c
.name_shm_offset
, name_size
);
7059 return error::kOutOfBounds
;
7061 String
name_str(name
, name_size
);
7062 return GetAttribLocationHelper(
7063 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7066 error::Error
GLES2DecoderImpl::HandleGetAttribLocationImmediate(
7067 uint32 immediate_data_size
, const cmds::GetAttribLocationImmediate
& c
) {
7068 uint32 name_size
= c
.data_size
;
7069 const char* name
= GetImmediateDataAs
<const char*>(
7070 c
, name_size
, immediate_data_size
);
7072 return error::kOutOfBounds
;
7074 String
name_str(name
, name_size
);
7075 return GetAttribLocationHelper(
7076 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7079 error::Error
GLES2DecoderImpl::HandleGetAttribLocationBucket(
7080 uint32 immediate_data_size
, const cmds::GetAttribLocationBucket
& c
) {
7081 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7083 return error::kInvalidArguments
;
7085 std::string name_str
;
7086 if (!bucket
->GetAsString(&name_str
)) {
7087 return error::kInvalidArguments
;
7089 return GetAttribLocationHelper(
7090 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7093 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
7094 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7095 const std::string
& name_str
) {
7096 if (!StringIsValidForGLES(name_str
.c_str())) {
7098 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
7099 return error::kNoError
;
7101 Program
* program
= GetProgramInfoNotShader(
7102 client_id
, "glUniformLocation");
7104 return error::kNoError
;
7106 if (!program
->IsValid()) {
7108 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
7109 return error::kNoError
;
7111 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7112 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7114 return error::kOutOfBounds
;
7116 // Require the client to init this incase the context is lost an we are no
7117 // longer executing commands.
7118 if (*location
!= -1) {
7119 return error::kGenericError
;
7121 *location
= program
->GetUniformFakeLocation(name_str
);
7122 return error::kNoError
;
7125 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
7126 uint32 immediate_data_size
, const cmds::GetUniformLocation
& c
) {
7127 uint32 name_size
= c
.data_size
;
7128 const char* name
= GetSharedMemoryAs
<const char*>(
7129 c
.name_shm_id
, c
.name_shm_offset
, name_size
);
7131 return error::kOutOfBounds
;
7133 String
name_str(name
, name_size
);
7134 return GetUniformLocationHelper(
7135 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7138 error::Error
GLES2DecoderImpl::HandleGetUniformLocationImmediate(
7139 uint32 immediate_data_size
, const cmds::GetUniformLocationImmediate
& c
) {
7140 uint32 name_size
= c
.data_size
;
7141 const char* name
= GetImmediateDataAs
<const char*>(
7142 c
, name_size
, immediate_data_size
);
7144 return error::kOutOfBounds
;
7146 String
name_str(name
, name_size
);
7147 return GetUniformLocationHelper(
7148 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7151 error::Error
GLES2DecoderImpl::HandleGetUniformLocationBucket(
7152 uint32 immediate_data_size
, const cmds::GetUniformLocationBucket
& c
) {
7153 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7155 return error::kInvalidArguments
;
7157 std::string name_str
;
7158 if (!bucket
->GetAsString(&name_str
)) {
7159 return error::kInvalidArguments
;
7161 return GetUniformLocationHelper(
7162 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7165 error::Error
GLES2DecoderImpl::HandleGetString(
7166 uint32 immediate_data_size
, const cmds::GetString
& c
) {
7167 GLenum name
= static_cast<GLenum
>(c
.name
);
7168 if (!validators_
->string_type
.IsValid(name
)) {
7169 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
7170 return error::kNoError
;
7172 const char* gl_str
= reinterpret_cast<const char*>(glGetString(name
));
7173 const char* str
= NULL
;
7174 std::string extensions
;
7177 str
= "OpenGL ES 2.0 Chromium";
7179 case GL_SHADING_LANGUAGE_VERSION
:
7180 str
= "OpenGL ES GLSL ES 1.0 Chromium";
7190 // For WebGL contexts, strip out the OES derivatives and
7191 // EXT frag depth extensions if they have not been enabled.
7192 if (force_webgl_glsl_validation_
) {
7193 extensions
= feature_info_
->extensions();
7194 if (!derivatives_explicitly_enabled_
) {
7195 size_t offset
= extensions
.find(kOESDerivativeExtension
);
7196 if (std::string::npos
!= offset
) {
7197 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
7201 if (!frag_depth_explicitly_enabled_
) {
7202 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
7203 if (std::string::npos
!= offset
) {
7204 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
7208 if (!draw_buffers_explicitly_enabled_
) {
7209 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
7210 if (std::string::npos
!= offset
) {
7211 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
7216 extensions
= feature_info_
->extensions().c_str();
7218 std::string surface_extensions
= surface_
->GetExtensions();
7219 if (!surface_extensions
.empty())
7220 extensions
+= " " + surface_extensions
;
7221 str
= extensions
.c_str();
7228 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
7229 bucket
->SetFromString(str
);
7230 return error::kNoError
;
7233 void GLES2DecoderImpl::DoBufferData(
7234 GLenum target
, GLsizeiptr size
, const GLvoid
* data
, GLenum usage
) {
7235 if (!validators_
->buffer_target
.IsValid(target
)) {
7236 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", target
, "target");
7239 if (!validators_
->buffer_usage
.IsValid(usage
)) {
7240 LOCAL_SET_GL_ERROR_INVALID_ENUM("glBufferData", usage
, "usage");
7244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glBufferData", "size < 0");
7247 Buffer
* buffer
= GetBufferInfoForTarget(target
);
7249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glBufferData", "unknown buffer");
7253 if (!EnsureGPUMemoryAvailable(size
)) {
7254 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glBufferData", "out of memory");
7258 buffer_manager()->DoBufferData(GetErrorState(), buffer
, size
, usage
, data
);
7261 error::Error
GLES2DecoderImpl::HandleBufferData(
7262 uint32 immediate_data_size
, const cmds::BufferData
& c
) {
7263 GLenum target
= static_cast<GLenum
>(c
.target
);
7264 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
7265 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
7266 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
7267 GLenum usage
= static_cast<GLenum
>(c
.usage
);
7268 const void* data
= NULL
;
7269 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
7270 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
7272 return error::kOutOfBounds
;
7275 DoBufferData(target
, size
, data
, usage
);
7276 return error::kNoError
;
7279 error::Error
GLES2DecoderImpl::HandleBufferDataImmediate(
7280 uint32 immediate_data_size
, const cmds::BufferDataImmediate
& c
) {
7281 GLenum target
= static_cast<GLenum
>(c
.target
);
7282 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
7283 const void* data
= GetImmediateDataAs
<const void*>(
7284 c
, size
, immediate_data_size
);
7286 return error::kOutOfBounds
;
7288 GLenum usage
= static_cast<GLenum
>(c
.usage
);
7289 DoBufferData(target
, size
, data
, usage
);
7290 return error::kNoError
;
7293 void GLES2DecoderImpl::DoBufferSubData(
7294 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
7295 Buffer
* buffer
= GetBufferInfoForTarget(target
);
7297 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glBufferSubData", "unknown buffer");
7301 buffer_manager()->DoBufferSubData(GetErrorState(), buffer
, offset
, size
,
7305 bool GLES2DecoderImpl::ClearLevel(
7306 unsigned service_id
,
7307 unsigned bind_target
,
7314 bool is_texture_immutable
) {
7315 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
7316 if (IsAngle() && (channels
& GLES2Util::kDepth
) != 0) {
7317 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7318 // on depth formats.
7320 glGenFramebuffersEXT(1, &fb
);
7321 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
7323 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
7324 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
7325 GL_DEPTH_ATTACHMENT
;
7327 glFramebufferTexture2DEXT(
7328 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
7329 // ANGLE promises a depth only attachment ok.
7330 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
7331 GL_FRAMEBUFFER_COMPLETE
) {
7338 glDisable(GL_SCISSOR_TEST
);
7339 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
7341 RestoreClearState();
7343 glDeleteFramebuffersEXT(1, &fb
);
7344 Framebuffer
* framebuffer
=
7345 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
7346 GLuint fb_service_id
=
7347 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
7348 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
7352 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
7355 uint32 padded_row_size
;
7356 if (!GLES2Util::ComputeImageDataSizes(
7357 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
7358 NULL
, &padded_row_size
)) {
7362 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
7366 if (size
> kMaxZeroSize
) {
7367 if (kMaxZeroSize
< padded_row_size
) {
7368 // That'd be an awfully large texture.
7371 // We should never have a large total size with a zero row size.
7372 DCHECK_GT(padded_row_size
, 0U);
7373 tile_height
= kMaxZeroSize
/ padded_row_size
;
7374 if (!GLES2Util::ComputeImageDataSizes(
7375 width
, tile_height
, format
, type
, state_
.unpack_alignment
, &size
,
7380 tile_height
= height
;
7383 // Assumes the size has already been checked.
7384 scoped_ptr
<char[]> zero(new char[size
]);
7385 memset(zero
.get(), 0, size
);
7386 glBindTexture(bind_target
, service_id
);
7389 while (y
< height
) {
7390 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
7391 if (is_texture_immutable
|| h
!= height
) {
7392 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
7395 target
, level
, format
, width
, h
, 0, format
, type
, zero
.get());
7399 TextureRef
* texture
= GetTextureInfoForTarget(bind_target
);
7400 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
7406 const int kS3TCBlockWidth
= 4;
7407 const int kS3TCBlockHeight
= 4;
7408 const int kS3TCDXT1BlockSize
= 8;
7409 const int kS3TCDXT3AndDXT5BlockSize
= 16;
7410 const int kETC1BlockWidth
= 4;
7411 const int kETC1BlockHeight
= 4;
7412 const int kETC1BlockSize
= 8;
7414 bool IsValidDXTSize(GLint level
, GLsizei size
) {
7415 return (size
== 1) ||
7416 (size
== 2) || !(size
% kS3TCBlockWidth
);
7419 } // anonymous namespace.
7421 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7422 const char* function_name
,
7423 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
7424 unsigned int bytes_required
= 0;
7427 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7428 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
: {
7429 int num_blocks_across
=
7430 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7431 int num_blocks_down
=
7432 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7433 int num_blocks
= num_blocks_across
* num_blocks_down
;
7434 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
7437 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7438 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7439 int num_blocks_across
=
7440 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7441 int num_blocks_down
=
7442 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7443 int num_blocks
= num_blocks_across
* num_blocks_down
;
7444 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
7447 case GL_ETC1_RGB8_OES
: {
7448 int num_blocks_across
=
7449 (width
+ kETC1BlockWidth
- 1) / kETC1BlockWidth
;
7450 int num_blocks_down
=
7451 (height
+ kETC1BlockHeight
- 1) / kETC1BlockHeight
;
7452 int num_blocks
= num_blocks_across
* num_blocks_down
;
7453 bytes_required
= num_blocks
* kETC1BlockSize
;
7457 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
7461 if (size
!= bytes_required
) {
7463 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
7470 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7471 const char* function_name
,
7472 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
7474 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7475 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7476 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7477 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7478 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
7480 GL_INVALID_OPERATION
, function_name
,
7481 "width or height invalid for level");
7486 case GL_ETC1_RGB8_OES
:
7487 if (width
<= 0 || height
<= 0) {
7489 GL_INVALID_OPERATION
, function_name
,
7490 "width or height invalid for level");
7499 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7500 const char* function_name
,
7501 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
7502 GLsizei width
, GLsizei height
, GLenum format
,
7504 if (xoffset
< 0 || yoffset
< 0) {
7506 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
7511 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7512 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7513 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7514 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7515 const int kBlockWidth
= 4;
7516 const int kBlockHeight
= 4;
7517 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
7519 GL_INVALID_OPERATION
, function_name
,
7520 "xoffset or yoffset not multiple of 4");
7523 GLsizei tex_width
= 0;
7524 GLsizei tex_height
= 0;
7525 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
7526 width
- xoffset
> tex_width
||
7527 height
- yoffset
> tex_height
) {
7529 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
7532 return ValidateCompressedTexDimensions(
7533 function_name
, level
, width
, height
, format
);
7535 case GL_ETC1_RGB8_OES
: {
7537 GL_INVALID_OPERATION
, function_name
,
7538 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7546 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
7549 GLenum internal_format
,
7555 // TODO(gman): Validate image_size is correct for width, height and format.
7556 if (!validators_
->texture_target
.IsValid(target
)) {
7557 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7558 "glCompressedTexImage2D", target
, "target");
7559 return error::kNoError
;
7561 if (!validators_
->compressed_texture_format
.IsValid(
7563 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7564 "glCompressedTexImage2D", internal_format
, "internal_format");
7565 return error::kNoError
;
7567 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
7571 "glCompressedTexImage2D", "dimensions out of range");
7572 return error::kNoError
;
7574 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
7578 "glCompressedTexImage2D", "unknown texture target");
7579 return error::kNoError
;
7581 Texture
* texture
= texture_ref
->texture();
7582 if (texture
->IsImmutable()) {
7584 GL_INVALID_OPERATION
,
7585 "glCompressedTexImage2D", "texture is immutable");
7586 return error::kNoError
;
7589 if (!ValidateCompressedTexDimensions(
7590 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
7591 !ValidateCompressedTexFuncData(
7592 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
7593 return error::kNoError
;
7596 if (!EnsureGPUMemoryAvailable(image_size
)) {
7598 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
7599 return error::kNoError
;
7602 if (texture
->IsAttachedToFramebuffer()) {
7603 clear_state_dirty_
= true;
7606 scoped_ptr
<int8
[]> zero
;
7608 zero
.reset(new int8
[image_size
]);
7609 memset(zero
.get(), 0, image_size
);
7612 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
7613 glCompressedTexImage2D(
7614 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
7615 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
7616 if (error
== GL_NO_ERROR
) {
7617 texture_manager()->SetLevelInfo(
7618 texture_ref
, target
, level
, internal_format
,
7619 width
, height
, 1, border
, 0, 0, true);
7621 return error::kNoError
;
7624 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
7625 uint32 immediate_data_size
, const cmds::CompressedTexImage2D
& c
) {
7626 GLenum target
= static_cast<GLenum
>(c
.target
);
7627 GLint level
= static_cast<GLint
>(c
.level
);
7628 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
7629 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7630 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7631 GLint border
= static_cast<GLint
>(c
.border
);
7632 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
7633 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
7634 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
7635 const void* data
= NULL
;
7636 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
7637 data
= GetSharedMemoryAs
<const void*>(
7638 data_shm_id
, data_shm_offset
, image_size
);
7640 return error::kOutOfBounds
;
7643 return DoCompressedTexImage2D(
7644 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
7647 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
7648 uint32 immediate_data_size
, const cmds::CompressedTexImage2DImmediate
& c
) {
7649 GLenum target
= static_cast<GLenum
>(c
.target
);
7650 GLint level
= static_cast<GLint
>(c
.level
);
7651 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
7652 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7653 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7654 GLint border
= static_cast<GLint
>(c
.border
);
7655 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
7656 const void* data
= GetImmediateDataAs
<const void*>(
7657 c
, image_size
, immediate_data_size
);
7659 return error::kOutOfBounds
;
7661 return DoCompressedTexImage2D(
7662 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
7665 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7666 uint32 immediate_data_size
, const cmds::CompressedTexImage2DBucket
& c
) {
7667 GLenum target
= static_cast<GLenum
>(c
.target
);
7668 GLint level
= static_cast<GLint
>(c
.level
);
7669 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
7670 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7671 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7672 GLint border
= static_cast<GLint
>(c
.border
);
7673 Bucket
* bucket
= GetBucket(c
.bucket_id
);
7675 return error::kInvalidArguments
;
7677 uint32 data_size
= bucket
->size();
7678 GLsizei imageSize
= data_size
;
7679 const void* data
= bucket
->GetData(0, data_size
);
7681 return error::kInvalidArguments
;
7683 return DoCompressedTexImage2D(
7684 target
, level
, internal_format
, width
, height
, border
,
7688 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7689 uint32 immediate_data_size
,
7690 const cmds::CompressedTexSubImage2DBucket
& c
) {
7691 GLenum target
= static_cast<GLenum
>(c
.target
);
7692 GLint level
= static_cast<GLint
>(c
.level
);
7693 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
7694 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
7695 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7696 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7697 GLenum format
= static_cast<GLenum
>(c
.format
);
7698 Bucket
* bucket
= GetBucket(c
.bucket_id
);
7700 return error::kInvalidArguments
;
7702 uint32 data_size
= bucket
->size();
7703 GLsizei imageSize
= data_size
;
7704 const void* data
= bucket
->GetData(0, data_size
);
7706 return error::kInvalidArguments
;
7708 if (!validators_
->texture_target
.IsValid(target
)) {
7710 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
7711 return error::kNoError
;
7713 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
7714 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7715 "glCompressedTexSubImage2D", format
, "format");
7716 return error::kNoError
;
7720 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
7721 return error::kNoError
;
7725 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
7726 return error::kNoError
;
7728 if (imageSize
< 0) {
7730 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
7731 return error::kNoError
;
7733 DoCompressedTexSubImage2D(
7734 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
7735 return error::kNoError
;
7738 bool GLES2DecoderImpl::ValidateTextureParameters(
7739 const char* function_name
,
7740 GLenum target
, GLenum format
, GLenum type
, GLint level
) {
7741 if (!feature_info_
->GetTextureFormatValidator(format
).IsValid(type
)) {
7743 GL_INVALID_OPERATION
, function_name
,
7744 (std::string("invalid type ") +
7745 GLES2Util::GetStringEnum(type
) + " for format " +
7746 GLES2Util::GetStringEnum(format
)).c_str());
7750 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
7751 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
7753 GL_INVALID_OPERATION
, function_name
,
7754 (std::string("invalid type ") +
7755 GLES2Util::GetStringEnum(type
) + " for format " +
7756 GLES2Util::GetStringEnum(format
)).c_str());
7762 bool GLES2DecoderImpl::ValidateTexImage2D(
7763 const char* function_name
,
7766 GLenum internal_format
,
7773 uint32 pixels_size
) {
7774 if (!validators_
->texture_target
.IsValid(target
)) {
7775 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
7778 if (!validators_
->texture_format
.IsValid(internal_format
)) {
7779 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7780 function_name
, internal_format
, "internal_format");
7783 if (!validators_
->texture_format
.IsValid(format
)) {
7784 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
7787 if (!validators_
->pixel_type
.IsValid(type
)) {
7788 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7791 if (format
!= internal_format
) {
7793 GL_INVALID_OPERATION
, function_name
, "format != internalFormat");
7796 if (!ValidateTextureParameters(function_name
, target
, format
, type
, level
)) {
7799 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
7802 GL_INVALID_VALUE
, function_name
, "dimensions out of range");
7805 if ((GLES2Util::GetChannelsForFormat(format
) &
7806 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && pixels
) {
7808 GL_INVALID_OPERATION
,
7809 function_name
, "can not supply data for depth or stencil textures");
7812 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
7815 GL_INVALID_OPERATION
, function_name
, "unknown texture for target");
7818 if (texture_ref
->texture()->IsImmutable()) {
7820 GL_INVALID_OPERATION
, function_name
, "texture is immutable");
7826 void GLES2DecoderImpl::DoTexImage2D(
7829 GLenum internal_format
,
7836 uint32 pixels_size
) {
7837 if (!ValidateTexImage2D("glTexImage2D", target
, level
, internal_format
,
7838 width
, height
, border
, format
, type
, pixels
, pixels_size
)) {
7842 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
7843 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexImage2D", "out of memory");
7847 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
7848 Texture
* texture
= texture_ref
->texture();
7849 GLsizei tex_width
= 0;
7850 GLsizei tex_height
= 0;
7851 GLenum tex_type
= 0;
7852 GLenum tex_format
= 0;
7853 bool level_is_same
=
7854 texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) &&
7855 texture
->GetLevelType(target
, level
, &tex_type
, &tex_format
) &&
7856 width
== tex_width
&& height
== tex_height
&&
7857 type
== tex_type
&& format
== tex_format
;
7859 if (level_is_same
&& !pixels
) {
7860 // Just set the level texture but mark the texture as uncleared.
7861 texture_manager()->SetLevelInfo(
7863 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
7865 tex_image_2d_failed_
= false;
7869 if (texture
->IsAttachedToFramebuffer()) {
7870 clear_state_dirty_
= true;
7873 if (!teximage2d_faster_than_texsubimage2d_
&& level_is_same
&& pixels
) {
7875 ScopedTextureUploadTimer
timer(this);
7876 glTexSubImage2D(target
, level
, 0, 0, width
, height
, format
, type
, pixels
);
7878 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
7879 tex_image_2d_failed_
= false;
7883 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D");
7885 ScopedTextureUploadTimer
timer(this);
7887 target
, level
, internal_format
, width
, height
, border
, format
, type
,
7890 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexImage2D");
7891 if (error
== GL_NO_ERROR
) {
7892 texture_manager()->SetLevelInfo(
7894 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
7896 tex_image_2d_failed_
= false;
7901 error::Error
GLES2DecoderImpl::HandleTexImage2D(
7902 uint32 immediate_data_size
, const cmds::TexImage2D
& c
) {
7903 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
7904 tex_image_2d_failed_
= true;
7905 GLenum target
= static_cast<GLenum
>(c
.target
);
7906 GLint level
= static_cast<GLint
>(c
.level
);
7907 GLint internal_format
= static_cast<GLint
>(c
.internalformat
);
7908 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7909 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7910 GLint border
= static_cast<GLint
>(c
.border
);
7911 GLenum format
= static_cast<GLenum
>(c
.format
);
7912 GLenum type
= static_cast<GLenum
>(c
.type
);
7913 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
7914 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
7916 if (!GLES2Util::ComputeImageDataSizes(
7917 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
7919 return error::kOutOfBounds
;
7921 const void* pixels
= NULL
;
7922 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
7923 pixels
= GetSharedMemoryAs
<const void*>(
7924 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
7926 return error::kOutOfBounds
;
7931 target
, level
, internal_format
, width
, height
, border
, format
, type
,
7932 pixels
, pixels_size
);
7933 return error::kNoError
;
7936 error::Error
GLES2DecoderImpl::HandleTexImage2DImmediate(
7937 uint32 immediate_data_size
, const cmds::TexImage2DImmediate
& c
) {
7938 GLenum target
= static_cast<GLenum
>(c
.target
);
7939 GLint level
= static_cast<GLint
>(c
.level
);
7940 GLint internal_format
= static_cast<GLint
>(c
.internalformat
);
7941 GLsizei width
= static_cast<GLsizei
>(c
.width
);
7942 GLsizei height
= static_cast<GLsizei
>(c
.height
);
7943 GLint border
= static_cast<GLint
>(c
.border
);
7944 GLenum format
= static_cast<GLenum
>(c
.format
);
7945 GLenum type
= static_cast<GLenum
>(c
.type
);
7947 if (!GLES2Util::ComputeImageDataSizes(
7948 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
7950 return error::kOutOfBounds
;
7952 const void* pixels
= GetImmediateDataAs
<const void*>(
7953 c
, size
, immediate_data_size
);
7955 return error::kOutOfBounds
;
7958 target
, level
, internal_format
, width
, height
, border
, format
, type
,
7960 return error::kNoError
;
7963 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7972 const void * data
) {
7973 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
7976 GL_INVALID_OPERATION
,
7977 "glCompressedTexSubImage2D", "unknown texture for target");
7980 Texture
* texture
= texture_ref
->texture();
7982 GLenum internal_format
= 0;
7983 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
7985 GL_INVALID_OPERATION
,
7986 "glCompressedTexSubImage2D", "level does not exist.");
7989 if (internal_format
!= format
) {
7991 GL_INVALID_OPERATION
,
7992 "glCompressedTexSubImage2D", "format does not match internal format.");
7995 if (!texture
->ValidForTexture(
7996 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)) {
7998 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8002 if (!ValidateCompressedTexFuncData(
8003 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8004 !ValidateCompressedTexSubDimensions(
8005 "glCompressedTexSubImage2D",
8006 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8011 // Note: There is no need to deal with texture cleared tracking here
8012 // because the validation above means you can only get here if the level
8013 // is already a matching compressed format and in that case
8014 // CompressedTexImage2D already cleared the texture.
8015 glCompressedTexSubImage2D(
8016 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8020 GLint start
, GLint range
, GLint sourceRange
,
8021 GLint
* out_start
, GLint
* out_range
) {
8028 GLint end
= start
+ range
;
8029 if (end
> sourceRange
) {
8030 range
-= end
- sourceRange
;
8036 void GLES2DecoderImpl::DoCopyTexImage2D(
8039 GLenum internal_format
,
8045 DCHECK(!ShouldDeferReads());
8046 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
8049 GL_INVALID_OPERATION
,
8050 "glCopyTexImage2D", "unknown texture for target");
8053 Texture
* texture
= texture_ref
->texture();
8054 if (texture
->IsImmutable()) {
8056 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8058 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8061 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8064 if (!ValidateTextureParameters(
8065 "glCopyTexImage2D", target
, internal_format
, GL_UNSIGNED_BYTE
, level
)) {
8069 // Check we have compatible formats.
8070 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8071 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8072 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
8074 if ((channels_needed
& channels_exist
) != channels_needed
) {
8076 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
8080 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8082 GL_INVALID_OPERATION
,
8083 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8087 uint32 estimated_size
= 0;
8088 if (!GLES2Util::ComputeImageDataSizes(
8089 width
, height
, internal_format
, GL_UNSIGNED_BYTE
, state_
.unpack_alignment
,
8090 &estimated_size
, NULL
, NULL
)) {
8092 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
8096 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
8097 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
8101 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8105 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8106 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8107 gfx::Size size
= GetBoundReadFrameBufferSize();
8109 if (texture
->IsAttachedToFramebuffer()) {
8110 clear_state_dirty_
= true;
8113 // Clip to size to source dimensions
8116 GLint copyWidth
= 0;
8117 GLint copyHeight
= 0;
8118 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8119 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8123 copyWidth
!= width
||
8124 copyHeight
!= height
) {
8125 // some part was clipped so clear the texture.
8127 texture
->service_id(), texture
->target(),
8128 target
, level
, internal_format
, GL_UNSIGNED_BYTE
, width
, height
,
8129 texture
->IsImmutable())) {
8131 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
8134 if (copyHeight
> 0 && copyWidth
> 0) {
8135 GLint dx
= copyX
- x
;
8136 GLint dy
= copyY
- y
;
8139 glCopyTexSubImage2D(target
, level
,
8140 destX
, destY
, copyX
, copyY
,
8141 copyWidth
, copyHeight
);
8144 glCopyTexImage2D(target
, level
, internal_format
,
8145 copyX
, copyY
, copyWidth
, copyHeight
, border
);
8147 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8148 if (error
== GL_NO_ERROR
) {
8149 texture_manager()->SetLevelInfo(
8150 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
8151 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
8155 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8164 DCHECK(!ShouldDeferReads());
8165 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
8168 GL_INVALID_OPERATION
,
8169 "glCopyTexSubImage2D", "unknown texture for target");
8172 Texture
* texture
= texture_ref
->texture();
8175 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
8176 !texture
->ValidForTexture(
8177 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)) {
8179 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
8182 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8184 GL_INVALID_OPERATION
,
8185 "glCopyTexSubImage2D", "async upload pending for texture");
8189 // Check we have compatible formats.
8190 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8191 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8192 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
8194 if (!channels_needed
||
8195 (channels_needed
& channels_exist
) != channels_needed
) {
8197 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
8201 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8203 GL_INVALID_OPERATION
,
8204 "glCopySubImage2D", "can not be used with depth or stencil textures");
8208 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8212 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8213 gfx::Size size
= GetBoundReadFrameBufferSize();
8216 GLint copyWidth
= 0;
8217 GLint copyHeight
= 0;
8218 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8219 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8221 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, level
)) {
8223 GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D", "dimensions too big");
8229 copyWidth
!= width
||
8230 copyHeight
!= height
) {
8231 // some part was clipped so clear the sub rect.
8232 uint32 pixels_size
= 0;
8233 if (!GLES2Util::ComputeImageDataSizes(
8234 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8237 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
8240 scoped_ptr
<char[]> zero(new char[pixels_size
]);
8241 memset(zero
.get(), 0, pixels_size
);
8243 target
, level
, xoffset
, yoffset
, width
, height
,
8244 format
, type
, zero
.get());
8247 if (copyHeight
> 0 && copyWidth
> 0) {
8248 GLint dx
= copyX
- x
;
8249 GLint dy
= copyY
- y
;
8250 GLint destX
= xoffset
+ dx
;
8251 GLint destY
= yoffset
+ dy
;
8252 glCopyTexSubImage2D(target
, level
,
8253 destX
, destY
, copyX
, copyY
,
8254 copyWidth
, copyHeight
);
8258 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8259 error::Error
* error
,
8260 const char* function_name
,
8269 const void * data
) {
8270 (*error
) = error::kNoError
;
8271 if (!validators_
->texture_target
.IsValid(target
)) {
8272 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
8276 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
8280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
8283 if (!validators_
->texture_format
.IsValid(format
)) {
8284 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8287 if (!validators_
->pixel_type
.IsValid(type
)) {
8288 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
8291 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
8294 GL_INVALID_OPERATION
,
8295 function_name
, "unknown texture for target");
8298 Texture
* texture
= texture_ref
->texture();
8299 GLenum current_type
= 0;
8300 GLenum internal_format
= 0;
8301 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
8303 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
8306 if (format
!= internal_format
) {
8308 GL_INVALID_OPERATION
,
8309 function_name
, "format does not match internal format.");
8312 if (type
!= current_type
) {
8314 GL_INVALID_OPERATION
,
8315 function_name
, "type does not match type of texture.");
8318 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8320 GL_INVALID_OPERATION
,
8321 function_name
, "async upload pending for texture");
8324 if (!texture
->ValidForTexture(
8325 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
)) {
8326 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
8329 if ((GLES2Util::GetChannelsForFormat(format
) &
8330 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8332 GL_INVALID_OPERATION
,
8333 function_name
, "can not supply data for depth or stencil textures");
8337 (*error
) = error::kOutOfBounds
;
8343 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
8352 const void * data
) {
8353 error::Error error
= error::kNoError
;
8354 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
8355 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
8358 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
8359 Texture
* texture
= texture_ref
->texture();
8360 GLsizei tex_width
= 0;
8361 GLsizei tex_height
= 0;
8362 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
8364 if (xoffset
!= 0 || yoffset
!= 0 ||
8365 width
!= tex_width
|| height
!= tex_height
) {
8366 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
8369 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
8370 return error::kNoError
;
8372 ScopedTextureUploadTimer
timer(this);
8374 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8375 return error::kNoError
;
8378 if (teximage2d_faster_than_texsubimage2d_
&& !texture
->IsImmutable()) {
8379 ScopedTextureUploadTimer
timer(this);
8380 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8381 // same as internal_foramt. If that changes we'll need to look them up.
8383 target
, level
, format
, width
, height
, 0, format
, type
, data
);
8385 ScopedTextureUploadTimer
timer(this);
8387 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8389 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
8390 return error::kNoError
;
8393 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(
8394 uint32 immediate_data_size
, const cmds::TexSubImage2D
& c
) {
8395 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8396 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
8397 if (internal
== GL_TRUE
&& tex_image_2d_failed_
)
8398 return error::kNoError
;
8400 GLenum target
= static_cast<GLenum
>(c
.target
);
8401 GLint level
= static_cast<GLint
>(c
.level
);
8402 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8403 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8404 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8405 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8406 GLenum format
= static_cast<GLenum
>(c
.format
);
8407 GLenum type
= static_cast<GLenum
>(c
.type
);
8409 if (!GLES2Util::ComputeImageDataSizes(
8410 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
8412 return error::kOutOfBounds
;
8414 const void* pixels
= GetSharedMemoryAs
<const void*>(
8415 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
8416 return DoTexSubImage2D(
8417 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
8420 error::Error
GLES2DecoderImpl::HandleTexSubImage2DImmediate(
8421 uint32 immediate_data_size
, const cmds::TexSubImage2DImmediate
& c
) {
8422 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
8423 if (internal
== GL_TRUE
&& tex_image_2d_failed_
)
8424 return error::kNoError
;
8426 GLenum target
= static_cast<GLenum
>(c
.target
);
8427 GLint level
= static_cast<GLint
>(c
.level
);
8428 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8429 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8430 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8431 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8432 GLenum format
= static_cast<GLenum
>(c
.format
);
8433 GLenum type
= static_cast<GLenum
>(c
.type
);
8435 if (!GLES2Util::ComputeImageDataSizes(
8436 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
8438 return error::kOutOfBounds
;
8440 const void* pixels
= GetImmediateDataAs
<const void*>(
8441 c
, data_size
, immediate_data_size
);
8442 return DoTexSubImage2D(
8443 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
8446 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8447 uint32 immediate_data_size
, const cmds::GetVertexAttribPointerv
& c
) {
8448 GLuint index
= static_cast<GLuint
>(c
.index
);
8449 GLenum pname
= static_cast<GLenum
>(c
.pname
);
8450 typedef cmds::GetVertexAttribPointerv::Result Result
;
8451 Result
* result
= GetSharedMemoryAs
<Result
*>(
8452 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
8454 return error::kOutOfBounds
;
8456 // Check that the client initialized the result.
8457 if (result
->size
!= 0) {
8458 return error::kInvalidArguments
;
8460 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
8461 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8462 "glGetVertexAttribPointerv", pname
, "pname");
8463 return error::kNoError
;
8465 if (index
>= group_
->max_vertex_attribs()) {
8467 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
8468 return error::kNoError
;
8470 result
->SetNumResults(1);
8471 *result
->GetData() =
8472 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
8473 return error::kNoError
;
8476 bool GLES2DecoderImpl::GetUniformSetup(
8477 GLuint program_id
, GLint fake_location
,
8478 uint32 shm_id
, uint32 shm_offset
,
8479 error::Error
* error
, GLint
* real_location
,
8480 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
8483 DCHECK(result_pointer
);
8484 DCHECK(result_type
);
8485 DCHECK(real_location
);
8486 *error
= error::kNoError
;
8487 // Make sure we have enough room for the result on failure.
8488 SizedResult
<GLint
>* result
;
8489 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8490 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
8492 *error
= error::kOutOfBounds
;
8495 *result_pointer
= result
;
8496 // Set the result size to 0 so the client does not have to check for success.
8497 result
->SetNumResults(0);
8498 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
8502 if (!program
->IsValid()) {
8503 // Program was not linked successfully. (ie, glLinkProgram)
8505 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
8508 *service_id
= program
->service_id();
8509 GLint array_index
= -1;
8510 const Program::UniformInfo
* uniform_info
=
8511 program
->GetUniformInfoByFakeLocation(
8512 fake_location
, real_location
, &array_index
);
8513 if (!uniform_info
) {
8514 // No such location.
8516 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
8519 GLenum type
= uniform_info
->type
;
8520 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
8522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
8525 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8526 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
8528 *error
= error::kOutOfBounds
;
8531 result
->size
= size
;
8532 *result_type
= type
;
8536 error::Error
GLES2DecoderImpl::HandleGetUniformiv(
8537 uint32 immediate_data_size
, const cmds::GetUniformiv
& c
) {
8538 GLuint program
= c
.program
;
8539 GLint fake_location
= c
.location
;
8542 GLint real_location
= -1;
8545 if (GetUniformSetup(
8546 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8547 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
8549 service_id
, real_location
,
8550 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
8555 error::Error
GLES2DecoderImpl::HandleGetUniformfv(
8556 uint32 immediate_data_size
, const cmds::GetUniformfv
& c
) {
8557 GLuint program
= c
.program
;
8558 GLint fake_location
= c
.location
;
8560 GLint real_location
= -1;
8562 typedef cmds::GetUniformfv::Result Result
;
8565 if (GetUniformSetup(
8566 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8567 &error
, &real_location
, &service_id
,
8568 reinterpret_cast<void**>(&result
), &result_type
)) {
8569 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
8570 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
8571 GLsizei num_values
= result
->GetNumResults();
8572 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
8573 glGetUniformiv(service_id
, real_location
, temp
.get());
8574 GLfloat
* dst
= result
->GetData();
8575 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
8576 dst
[ii
] = (temp
[ii
] != 0);
8579 glGetUniformfv(service_id
, real_location
, result
->GetData());
8585 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8586 uint32 immediate_data_size
, const cmds::GetShaderPrecisionFormat
& c
) {
8587 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
8588 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
8589 typedef cmds::GetShaderPrecisionFormat::Result Result
;
8590 Result
* result
= GetSharedMemoryAs
<Result
*>(
8591 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8593 return error::kOutOfBounds
;
8595 // Check that the client initialized the result.
8596 if (result
->success
!= 0) {
8597 return error::kInvalidArguments
;
8599 if (!validators_
->shader_type
.IsValid(shader_type
)) {
8600 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8601 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
8602 return error::kNoError
;
8604 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
8605 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8606 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
8607 return error::kNoError
;
8610 result
->success
= 1; // true
8612 GLint range
[2] = { 0, 0 };
8613 GLint precision
= 0;
8614 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
8616 result
->min_range
= range
[0];
8617 result
->max_range
= range
[1];
8618 result
->precision
= precision
;
8620 return error::kNoError
;
8623 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
8624 uint32 immediate_data_size
, const cmds::GetAttachedShaders
& c
) {
8625 uint32 result_size
= c
.result_size
;
8626 GLuint program_id
= static_cast<GLuint
>(c
.program
);
8627 Program
* program
= GetProgramInfoNotShader(
8628 program_id
, "glGetAttachedShaders");
8630 return error::kNoError
;
8632 typedef cmds::GetAttachedShaders::Result Result
;
8633 uint32 max_count
= Result::ComputeMaxResults(result_size
);
8634 Result
* result
= GetSharedMemoryAs
<Result
*>(
8635 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
8637 return error::kOutOfBounds
;
8639 // Check that the client initialized the result.
8640 if (result
->size
!= 0) {
8641 return error::kInvalidArguments
;
8644 glGetAttachedShaders(
8645 program
->service_id(), max_count
, &count
, result
->GetData());
8646 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
8647 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
8648 &result
->GetData()[ii
])) {
8650 return error::kGenericError
;
8653 result
->SetNumResults(count
);
8654 return error::kNoError
;
8657 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
8658 uint32 immediate_data_size
, const cmds::GetActiveUniform
& c
) {
8659 GLuint program_id
= c
.program
;
8660 GLuint index
= c
.index
;
8661 uint32 name_bucket_id
= c
.name_bucket_id
;
8662 typedef cmds::GetActiveUniform::Result Result
;
8663 Result
* result
= GetSharedMemoryAs
<Result
*>(
8664 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8666 return error::kOutOfBounds
;
8668 // Check that the client initialized the result.
8669 if (result
->success
!= 0) {
8670 return error::kInvalidArguments
;
8672 Program
* program
= GetProgramInfoNotShader(
8673 program_id
, "glGetActiveUniform");
8675 return error::kNoError
;
8677 const Program::UniformInfo
* uniform_info
=
8678 program
->GetUniformInfo(index
);
8679 if (!uniform_info
) {
8681 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
8682 return error::kNoError
;
8684 result
->success
= 1; // true.
8685 result
->size
= uniform_info
->size
;
8686 result
->type
= uniform_info
->type
;
8687 Bucket
* bucket
= CreateBucket(name_bucket_id
);
8688 bucket
->SetFromString(uniform_info
->name
.c_str());
8689 return error::kNoError
;
8692 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(
8693 uint32 immediate_data_size
, const cmds::GetActiveAttrib
& c
) {
8694 GLuint program_id
= c
.program
;
8695 GLuint index
= c
.index
;
8696 uint32 name_bucket_id
= c
.name_bucket_id
;
8697 typedef cmds::GetActiveAttrib::Result Result
;
8698 Result
* result
= GetSharedMemoryAs
<Result
*>(
8699 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8701 return error::kOutOfBounds
;
8703 // Check that the client initialized the result.
8704 if (result
->success
!= 0) {
8705 return error::kInvalidArguments
;
8707 Program
* program
= GetProgramInfoNotShader(
8708 program_id
, "glGetActiveAttrib");
8710 return error::kNoError
;
8712 const Program::VertexAttrib
* attrib_info
=
8713 program
->GetAttribInfo(index
);
8716 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
8717 return error::kNoError
;
8719 result
->success
= 1; // true.
8720 result
->size
= attrib_info
->size
;
8721 result
->type
= attrib_info
->type
;
8722 Bucket
* bucket
= CreateBucket(name_bucket_id
);
8723 bucket
->SetFromString(attrib_info
->name
.c_str());
8724 return error::kNoError
;
8727 error::Error
GLES2DecoderImpl::HandleShaderBinary(
8728 uint32 immediate_data_size
, const cmds::ShaderBinary
& c
) {
8729 #if 1 // No binary shader support.
8730 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
8731 return error::kNoError
;
8733 GLsizei n
= static_cast<GLsizei
>(c
.n
);
8735 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
8736 return error::kNoError
;
8738 GLsizei length
= static_cast<GLsizei
>(c
.length
);
8740 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
8741 return error::kNoError
;
8744 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
8745 return error::kOutOfBounds
;
8747 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
8748 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
8749 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
8750 const void* binary
= GetSharedMemoryAs
<const void*>(
8751 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
8752 if (shaders
== NULL
|| binary
== NULL
) {
8753 return error::kOutOfBounds
;
8755 scoped_array
<GLuint
> service_ids(new GLuint
[n
]);
8756 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
8757 Shader
* shader
= GetShader(shaders
[ii
]);
8759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
8760 return error::kNoError
;
8762 service_ids
[ii
] = shader
->service_id();
8764 // TODO(gman): call glShaderBinary
8765 return error::kNoError
;
8769 void GLES2DecoderImpl::DoSwapBuffers() {
8770 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8772 int this_frame_number
= frame_number_
++;
8773 // TRACE_EVENT for gpu tests:
8774 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8775 TRACE_EVENT_SCOPE_THREAD
,
8776 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8777 "width", (is_offscreen
? offscreen_size_
.width() :
8778 surface_
->GetSize().width()));
8779 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
8780 "offscreen", is_offscreen
,
8781 "frame", this_frame_number
);
8782 // If offscreen then don't actually SwapBuffers to the display. Just copy
8783 // the rendered frame to another frame buffer.
8785 TRACE_EVENT2("gpu", "Offscreen",
8786 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
8787 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
8788 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8789 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8791 if (workarounds().needs_offscreen_buffer_workaround
) {
8792 offscreen_saved_frame_buffer_
->Create();
8796 // Allocate the offscreen saved color texture.
8797 DCHECK(offscreen_saved_color_format_
);
8798 offscreen_saved_color_texture_
->AllocateStorage(
8799 offscreen_size_
, offscreen_saved_color_format_
, false);
8801 offscreen_saved_frame_buffer_
->AttachRenderTexture(
8802 offscreen_saved_color_texture_
.get());
8803 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
8804 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
8805 GL_FRAMEBUFFER_COMPLETE
) {
8806 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8807 << "because offscreen saved FBO was incomplete.";
8808 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
8812 // Clear the offscreen color texture.
8813 // TODO(piman): Is this still necessary?
8815 ScopedFrameBufferBinder
binder(this,
8816 offscreen_saved_frame_buffer_
->id());
8817 glClearColor(0, 0, 0, 0);
8818 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
8819 glDisable(GL_SCISSOR_TEST
);
8820 glClear(GL_COLOR_BUFFER_BIT
);
8821 RestoreClearState();
8825 UpdateParentTextureInfo();
8828 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
8830 ScopedGLErrorSuppressor
suppressor(
8831 "GLES2DecoderImpl::DoSwapBuffers", this);
8833 if (IsOffscreenBufferMultisampled()) {
8834 // For multisampled buffers, resolve the frame buffer.
8835 ScopedResolvedFrameBufferBinder
binder(this, true, false);
8837 ScopedFrameBufferBinder
binder(this,
8838 offscreen_target_frame_buffer_
->id());
8840 if (offscreen_target_buffer_preserved_
) {
8841 // Copy the target frame buffer to the saved offscreen texture.
8842 offscreen_saved_color_texture_
->Copy(
8843 offscreen_saved_color_texture_
->size(),
8844 offscreen_saved_color_format_
);
8846 // Flip the textures in the parent context via the texture manager.
8847 if (!!offscreen_saved_color_texture_info_
.get())
8848 offscreen_saved_color_texture_info_
->texture()->
8849 SetServiceId(offscreen_target_color_texture_
->id());
8851 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
8852 offscreen_target_frame_buffer_
->AttachRenderTexture(
8853 offscreen_target_color_texture_
.get());
8856 // Ensure the side effects of the copy are visible to the parent
8857 // context. There is no need to do this for ANGLE because it uses a
8858 // single D3D device for all contexts.
8863 TRACE_EVENT2("gpu", "Onscreen",
8864 "width", surface_
->GetSize().width(),
8865 "height", surface_
->GetSize().height());
8866 if (!surface_
->SwapBuffers()) {
8867 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
8868 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
8873 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8874 uint32 immediate_data_size
, const cmds::EnableFeatureCHROMIUM
& c
) {
8875 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8876 if (!bucket
|| bucket
->size() == 0) {
8877 return error::kInvalidArguments
;
8879 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
8880 Result
* result
= GetSharedMemoryAs
<Result
*>(
8881 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8883 return error::kOutOfBounds
;
8885 // Check that the client initialized the result.
8887 return error::kInvalidArguments
;
8889 std::string feature_str
;
8890 if (!bucket
->GetAsString(&feature_str
)) {
8891 return error::kInvalidArguments
;
8894 // TODO(gman): make this some kind of table to function pointer thingy.
8895 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
8896 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8897 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
8898 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8899 // TODO(gman): decide how to remove the need for this const_cast.
8900 // I could make validators_ non const but that seems bad as this is the only
8901 // place it is needed. I could make some special friend class of validators
8902 // just to allow this to set them. That seems silly. I could refactor this
8903 // code to use the extension mechanism or the initialization attributes to
8904 // turn this feature on. Given that the only real point of this is to make
8905 // the conformance tests pass and given that there is lots of real work that
8906 // needs to be done it seems like refactoring for one to one of those
8907 // methods is a very low priority.
8908 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
8909 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
8910 force_webgl_glsl_validation_
= true;
8911 InitializeShaderTranslator();
8913 return error::kNoError
;
8916 *result
= 1; // true.
8917 return error::kNoError
;
8920 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8921 uint32 immediate_data_size
,
8922 const cmds::GetRequestableExtensionsCHROMIUM
& c
) {
8923 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8924 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
8925 info
->Initialize(disallowed_features_
, NULL
);
8926 bucket
->SetFromString(info
->extensions().c_str());
8927 return error::kNoError
;
8930 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8931 uint32 immediate_data_size
, const cmds::RequestExtensionCHROMIUM
& c
) {
8932 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8933 if (!bucket
|| bucket
->size() == 0) {
8934 return error::kInvalidArguments
;
8936 std::string feature_str
;
8937 if (!bucket
->GetAsString(&feature_str
)) {
8938 return error::kInvalidArguments
;
8941 bool desire_webgl_glsl_validation
=
8942 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
8943 bool desire_standard_derivatives
= false;
8944 bool desire_frag_depth
= false;
8945 bool desire_draw_buffers
= false;
8946 if (force_webgl_glsl_validation_
) {
8947 desire_standard_derivatives
=
8948 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
8950 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
8951 desire_draw_buffers
=
8952 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
8955 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
8956 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
8957 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
8958 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
8959 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
8960 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
8961 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
8962 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
8963 InitializeShaderTranslator();
8966 UpdateCapabilities();
8968 return error::kNoError
;
8971 error::Error
GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8972 uint32 immediate_data_size
, const cmds::GetMultipleIntegervCHROMIUM
& c
) {
8973 GLuint count
= c
.count
;
8975 if (!SafeMultiplyUint32(count
, sizeof(GLenum
), &pnames_size
)) {
8976 return error::kOutOfBounds
;
8978 const GLenum
* pnames
= GetSharedMemoryAs
<const GLenum
*>(
8979 c
.pnames_shm_id
, c
.pnames_shm_offset
, pnames_size
);
8980 if (pnames
== NULL
) {
8981 return error::kOutOfBounds
;
8984 // We have to copy them since we use them twice so the client
8985 // can't change them between the time we validate them and the time we use
8987 scoped_ptr
<GLenum
[]> enums(new GLenum
[count
]);
8988 memcpy(enums
.get(), pnames
, pnames_size
);
8990 // Count up the space needed for the result.
8991 uint32 num_results
= 0;
8992 for (GLuint ii
= 0; ii
< count
; ++ii
) {
8993 uint32 num
= util_
.GLGetNumValuesReturned(enums
[ii
]);
8995 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8996 "glGetMulitpleCHROMIUM", enums
[ii
], "pname");
8997 return error::kNoError
;
8999 // Num will never be more than 4.
9001 if (!SafeAddUint32(num_results
, num
, &num_results
)) {
9002 return error::kOutOfBounds
;
9006 uint32 result_size
= 0;
9007 if (!SafeMultiplyUint32(num_results
, sizeof(GLint
), &result_size
)) {
9008 return error::kOutOfBounds
;
9011 if (result_size
!= static_cast<uint32
>(c
.size
)) {
9014 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
9015 return error::kNoError
;
9018 GLint
* results
= GetSharedMemoryAs
<GLint
*>(
9019 c
.results_shm_id
, c
.results_shm_offset
, result_size
);
9020 if (results
== NULL
) {
9021 return error::kOutOfBounds
;
9024 // Check the results have been cleared in case the context was lost.
9025 for (uint32 ii
= 0; ii
< num_results
; ++ii
) {
9027 return error::kInvalidArguments
;
9032 GLint
* start
= results
;
9033 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9034 GLsizei num_written
= 0;
9035 if (!state_
.GetStateAsGLint(enums
[ii
], results
, &num_written
) &&
9036 !GetHelper(enums
[ii
], results
, &num_written
)) {
9037 DoGetIntegerv(enums
[ii
], results
);
9039 results
+= num_written
;
9042 // Just to verify. Should this be a DCHECK?
9043 if (static_cast<uint32
>(results
- start
) != num_results
) {
9044 return error::kOutOfBounds
;
9047 return error::kNoError
;
9050 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9051 uint32 immediate_data_size
, const cmds::GetProgramInfoCHROMIUM
& c
) {
9052 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9053 uint32 bucket_id
= c
.bucket_id
;
9054 Bucket
* bucket
= CreateBucket(bucket_id
);
9055 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
9056 Program
* program
= NULL
;
9057 program
= GetProgram(program_id
);
9058 if (!program
|| !program
->IsValid()) {
9059 return error::kNoError
;
9061 program
->GetProgramInfo(program_manager(), bucket
);
9062 return error::kNoError
;
9065 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
9066 switch (reset_status_
) {
9068 // TODO(kbr): improve the precision of the error code in this case.
9069 // Consider delegating to context for error code if MakeCurrent fails.
9070 return error::kUnknown
;
9071 case GL_GUILTY_CONTEXT_RESET_ARB
:
9072 return error::kGuilty
;
9073 case GL_INNOCENT_CONTEXT_RESET_ARB
:
9074 return error::kInnocent
;
9075 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
9076 return error::kUnknown
;
9080 return error::kUnknown
;
9083 bool GLES2DecoderImpl::WasContextLost() {
9084 if (reset_status_
!= GL_NO_ERROR
) {
9087 if (context_
->WasAllocatedUsingRobustnessExtension()) {
9088 GLenum status
= GL_NO_ERROR
;
9089 if (has_robustness_extension_
)
9090 status
= glGetGraphicsResetStatusARB();
9091 if (status
!= GL_NO_ERROR
) {
9092 // The graphics card was reset. Signal a lost context to the application.
9093 reset_status_
= status
;
9094 reset_by_robustness_extension_
= true;
9095 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
9096 << " context lost via ARB/EXT_robustness. Reset status = "
9097 << GLES2Util::GetStringEnum(status
);
9104 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9105 return WasContextLost() && reset_by_robustness_extension_
;
9108 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
9109 // Only loses the context once.
9110 if (reset_status_
!= GL_NO_ERROR
) {
9114 // Marks this context as lost.
9115 reset_status_
= reset_status
;
9116 current_decoder_error_
= error::kLostContext
;
9119 error::Error
GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9120 uint32 immediate_data_size
, const cmds::LoseContextCHROMIUM
& c
) {
9121 GLenum current
= static_cast<GLenum
>(c
.current
);
9122 GLenum other
= static_cast<GLenum
>(c
.other
);
9123 if (!validators_
->reset_status
.IsValid(current
)) {
9124 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9125 "glLoseContextCHROMIUM", current
, "current");
9127 if (!validators_
->reset_status
.IsValid(other
)) {
9128 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other
, "other");
9130 group_
->LoseContexts(other
);
9131 reset_status_
= current
;
9132 current_decoder_error_
= error::kLostContext
;
9133 return error::kLostContext
;
9136 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9137 uint32 immediate_data_size
, const cmds::InsertSyncPointCHROMIUM
& c
) {
9138 return error::kUnknownCommand
;
9141 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9142 uint32 immediate_data_size
, const cmds::WaitSyncPointCHROMIUM
& c
) {
9143 if (wait_sync_point_callback_
.is_null())
9144 return error::kNoError
;
9146 return wait_sync_point_callback_
.Run(c
.sync_point
) ?
9147 error::kNoError
: error::kDeferCommandUntilLater
;
9150 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9151 GLsizei n
, const GLuint
* client_ids
) {
9152 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9153 if (query_manager_
->GetQuery(client_ids
[ii
])) {
9157 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9161 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9162 GLsizei n
, const GLuint
* client_ids
) {
9163 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9164 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
9165 if (query
&& !query
->IsDeleted()) {
9166 if (query
== state_
.current_query
.get()) {
9167 state_
.current_query
= NULL
;
9169 query
->Destroy(true);
9170 query_manager_
->RemoveQuery(client_ids
[ii
]);
9175 bool GLES2DecoderImpl::ProcessPendingQueries() {
9176 if (query_manager_
.get() == NULL
) {
9179 if (!query_manager_
->ProcessPendingQueries()) {
9180 current_decoder_error_
= error::kOutOfBounds
;
9182 return query_manager_
->HavePendingQueries();
9185 // Note that if there are no pending readpixels right now,
9186 // this function will call the callback immediately.
9187 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
9188 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
9189 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
9195 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9196 while (!pending_readpixel_fences_
.empty() &&
9197 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
9198 std::vector
<base::Closure
> callbacks
=
9199 pending_readpixel_fences_
.front()->callbacks
;
9200 pending_readpixel_fences_
.pop();
9201 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
9207 bool GLES2DecoderImpl::HasMoreIdleWork() {
9208 return !pending_readpixel_fences_
.empty() ||
9209 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
9212 void GLES2DecoderImpl::PerformIdleWork() {
9213 ProcessPendingReadPixels();
9214 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
9216 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
9217 ProcessFinishedAsyncTransfers();
9220 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(
9221 uint32 immediate_data_size
, const cmds::BeginQueryEXT
& c
) {
9222 GLenum target
= static_cast<GLenum
>(c
.target
);
9223 GLuint client_id
= static_cast<GLuint
>(c
.id
);
9224 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
9225 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
9228 case GL_COMMANDS_ISSUED_CHROMIUM
:
9229 case GL_LATENCY_QUERY_CHROMIUM
:
9230 case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM
:
9231 case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM
:
9232 case GL_GET_ERROR_QUERY_CHROMIUM
:
9235 if (!features().occlusion_query_boolean
) {
9237 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9238 "not enabled for occlusion queries");
9239 return error::kNoError
;
9244 // TODO(hubbe): Make it possible to have one query per type running at the
9246 if (state_
.current_query
.get()) {
9248 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
9249 return error::kNoError
;
9252 if (client_id
== 0) {
9253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
9254 return error::kNoError
;
9257 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
9259 // TODO(gman): Decide if we need this check.
9261 // Checks id was made by glGenQueries
9263 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9264 // for all Query ids but from the POV of the command buffer service maybe
9267 // The client can enforce this. I don't think the service cares.
9269 // IdAllocatorInterface* id_allocator =
9270 // group_->GetIdAllocator(id_namespaces::kQueries);
9271 // if (!id_allocator->InUse(client_id)) {
9272 // LOCAL_SET_GL_ERROR(
9273 // GL_INVALID_OPERATION,
9274 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
9275 // return error::kNoError;
9277 query
= query_manager_
->CreateQuery(
9278 target
, client_id
, sync_shm_id
, sync_shm_offset
);
9281 if (query
->target() != target
) {
9283 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
9284 return error::kNoError
;
9285 } else if (query
->shm_id() != sync_shm_id
||
9286 query
->shm_offset() != sync_shm_offset
) {
9287 DLOG(ERROR
) << "Shared memory used by query not the same as before";
9288 return error::kInvalidArguments
;
9291 if (!query_manager_
->BeginQuery(query
)) {
9292 return error::kOutOfBounds
;
9295 state_
.current_query
= query
;
9296 return error::kNoError
;
9299 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(
9300 uint32 immediate_data_size
, const cmds::EndQueryEXT
& c
) {
9301 GLenum target
= static_cast<GLenum
>(c
.target
);
9302 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
9304 if (!state_
.current_query
.get()) {
9306 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
9307 return error::kNoError
;
9309 if (state_
.current_query
->target() != target
) {
9311 GL_INVALID_OPERATION
,
9312 "glEndQueryEXT", "target does not match active query");
9313 return error::kNoError
;
9316 if (!query_manager_
->EndQuery(state_
.current_query
.get(), submit_count
)) {
9317 return error::kOutOfBounds
;
9320 query_manager_
->ProcessPendingTransferQueries();
9322 state_
.current_query
= NULL
;
9323 return error::kNoError
;
9326 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9327 GLsizei n
, const GLuint
* client_ids
) {
9328 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9329 if (GetVertexAttribManager(client_ids
[ii
])) {
9334 if (!features().native_vertex_array_object
) {
9336 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9337 CreateVertexAttribManager(client_ids
[ii
], 0);
9340 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9342 glGenVertexArraysOES(n
, service_ids
.get());
9343 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9344 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
]);
9351 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9352 GLsizei n
, const GLuint
* client_ids
) {
9353 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9354 VertexAttribManager
* vao
=
9355 GetVertexAttribManager(client_ids
[ii
]);
9356 if (vao
&& !vao
->IsDeleted()) {
9357 if (state_
.vertex_attrib_manager
.get() == vao
) {
9358 state_
.vertex_attrib_manager
= default_vertex_attrib_manager_
;
9360 RemoveVertexAttribManager(client_ids
[ii
]);
9365 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
9366 VertexAttribManager
* vao
= NULL
;
9367 GLuint service_id
= 0;
9368 if (client_id
!= 0) {
9369 vao
= GetVertexAttribManager(client_id
);
9371 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9372 // only allows names that have been previously generated. As such, we do
9373 // not generate new names here.
9375 GL_INVALID_OPERATION
,
9376 "glBindVertexArrayOES", "bad vertex array id.");
9377 current_decoder_error_
= error::kNoError
;
9380 service_id
= vao
->service_id();
9383 vao
= default_vertex_attrib_manager_
.get();
9386 // Only set the VAO state if it's changed
9387 if (state_
.vertex_attrib_manager
.get() != vao
) {
9388 state_
.vertex_attrib_manager
= vao
;
9389 if (!features().native_vertex_array_object
) {
9390 EmulateVertexArrayState();
9392 glBindVertexArrayOES(service_id
);
9397 // Used when OES_vertex_array_object isn't natively supported
9398 void GLES2DecoderImpl::EmulateVertexArrayState() {
9399 // Setup the Vertex attribute state
9400 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
9401 RestoreStateForAttrib(vv
);
9404 // Setup the element buffer
9405 Buffer
* element_array_buffer
=
9406 state_
.vertex_attrib_manager
->element_array_buffer();
9407 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
9408 element_array_buffer
? element_array_buffer
->service_id() : 0);
9411 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
9412 const VertexAttribManager
* vao
=
9413 GetVertexAttribManager(client_id
);
9414 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
9417 error::Error
GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9418 uint32 immediate_data_size
,
9419 const cmds::CreateStreamTextureCHROMIUM
& c
) {
9420 if (!features().chromium_stream_texture
) {
9422 GL_INVALID_OPERATION
,
9423 "glOpenStreamTextureCHROMIUM", "not supported.");
9424 return error::kNoError
;
9427 uint32 client_id
= c
.client_id
;
9428 typedef cmds::CreateStreamTextureCHROMIUM::Result Result
;
9429 Result
* result
= GetSharedMemoryAs
<Result
*>(
9430 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9433 return error::kOutOfBounds
;
9435 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_id
);
9439 "glCreateStreamTextureCHROMIUM", "bad texture id.");
9440 return error::kNoError
;
9443 Texture
* texture
= texture_ref
->texture();
9444 if (texture
->IsStreamTexture()) {
9446 GL_INVALID_OPERATION
,
9447 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
9448 return error::kNoError
;
9451 if (texture
->target() && texture
->target() != GL_TEXTURE_EXTERNAL_OES
) {
9453 GL_INVALID_OPERATION
,
9454 "glCreateStreamTextureCHROMIUM",
9455 "is already bound to incompatible target.");
9456 return error::kNoError
;
9459 if (!stream_texture_manager())
9460 return error::kInvalidArguments
;
9462 GLuint object_id
= stream_texture_manager()->CreateStreamTexture(
9463 texture
->service_id(), client_id
);
9466 texture_manager()->SetStreamTexture(texture_ref
, true);
9470 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
9473 *result
= object_id
;
9474 return error::kNoError
;
9477 error::Error
GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9478 uint32 immediate_data_size
,
9479 const cmds::DestroyStreamTextureCHROMIUM
& c
) {
9480 GLuint client_id
= c
.texture
;
9481 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_id
);
9482 if (texture_ref
&& texture_manager()->IsStreamTextureOwner(texture_ref
)) {
9483 if (!stream_texture_manager())
9484 return error::kInvalidArguments
;
9486 stream_texture_manager()->DestroyStreamTexture(texture_ref
->service_id());
9487 texture_manager()->SetStreamTexture(texture_ref
, false);
9491 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
9494 return error::kNoError
;
9497 #if defined(OS_MACOSX)
9498 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
9499 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
9501 if (it
!= texture_to_io_surface_map_
.end()) {
9502 // Found a previous IOSurface bound to this texture; release it.
9503 CFTypeRef surface
= it
->second
;
9505 texture_to_io_surface_map_
.erase(it
);
9510 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9511 GLenum target
, GLsizei width
, GLsizei height
,
9512 GLuint io_surface_id
, GLuint plane
) {
9513 #if defined(OS_MACOSX)
9514 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
9516 GL_INVALID_OPERATION
,
9517 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9521 IOSurfaceSupport
* surface_support
= IOSurfaceSupport::Initialize();
9522 if (!surface_support
) {
9524 GL_INVALID_OPERATION
,
9525 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
9529 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
9530 // This might be supported in the future, and if we could require
9531 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9532 // could delete a lot of code. For now, perform strict validation so we
9533 // know what's going on.
9535 GL_INVALID_OPERATION
,
9536 "glTexImageIOSurface2DCHROMIUM",
9537 "requires TEXTURE_RECTANGLE_ARB target");
9541 // Default target might be conceptually valid, but disallow it to avoid
9543 TextureRef
* texture_ref
= GetTextureInfoForTargetUnlessDefault(target
);
9546 GL_INVALID_OPERATION
,
9547 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9551 // Look up the new IOSurface. Note that because of asynchrony
9552 // between processes this might fail; during live resizing the
9553 // plugin process might allocate and release an IOSurface before
9554 // this process gets a chance to look it up. Hold on to any old
9555 // IOSurface in this case.
9556 CFTypeRef surface
= surface_support
->IOSurfaceLookup(io_surface_id
);
9559 GL_INVALID_OPERATION
,
9560 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9564 // Release any IOSurface previously bound to this texture.
9565 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
9567 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9568 texture_to_io_surface_map_
.insert(
9569 std::make_pair(texture_ref
->service_id(), surface
));
9571 CGLContextObj context
=
9572 static_cast<CGLContextObj
>(context_
->GetHandle());
9574 CGLError err
= surface_support
->CGLTexImageIOSurface2D(
9581 GL_UNSIGNED_INT_8_8_8_8_REV
,
9585 if (err
!= kCGLNoError
) {
9587 GL_INVALID_OPERATION
,
9588 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9592 texture_manager()->SetLevelInfo(
9593 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
9594 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
9597 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9598 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9602 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
9603 switch (internalformat
) {
9614 case GL_LUMINANCE8_ALPHA8_EXT
:
9615 return GL_LUMINANCE_ALPHA
;
9616 case GL_LUMINANCE8_EXT
:
9617 return GL_LUMINANCE
;
9620 case GL_RGBA32F_EXT
:
9624 case GL_ALPHA32F_EXT
:
9626 case GL_LUMINANCE32F_EXT
:
9627 return GL_LUMINANCE
;
9628 case GL_LUMINANCE_ALPHA32F_EXT
:
9629 return GL_LUMINANCE_ALPHA
;
9630 case GL_RGBA16F_EXT
:
9634 case GL_ALPHA16F_EXT
:
9636 case GL_LUMINANCE16F_EXT
:
9637 return GL_LUMINANCE
;
9638 case GL_LUMINANCE_ALPHA16F_EXT
:
9639 return GL_LUMINANCE_ALPHA
;
9647 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9648 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
9649 GLenum internal_format
, GLenum dest_type
) {
9650 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
9651 TextureRef
* source_texture_ref
= GetTexture(source_id
);
9653 if (!source_texture_ref
|| !dest_texture_ref
) {
9655 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
9659 if (GL_TEXTURE_2D
!= target
) {
9661 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
9665 Texture
* source_texture
= source_texture_ref
->texture();
9666 Texture
* dest_texture
= dest_texture_ref
->texture();
9667 if (dest_texture
->target() != GL_TEXTURE_2D
||
9668 (source_texture
->target() != GL_TEXTURE_2D
&&
9669 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
9672 "glCopyTextureCHROMIUM", "invalid texture target binding");
9676 int source_width
, source_height
, dest_width
, dest_height
;
9678 if (source_texture
->target() == GL_TEXTURE_2D
) {
9679 if (!source_texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &source_width
,
9683 "glCopyTextureChromium", "source texture has no level 0");
9687 // Check that this type of texture is allowed.
9688 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D
, level
, source_width
,
9689 source_height
, 1)) {
9692 "glCopyTextureCHROMIUM", "Bad dimensions");
9697 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
9698 DCHECK(stream_texture_manager());
9699 StreamTexture
* stream_tex
=
9700 stream_texture_manager()->LookupStreamTexture(
9701 source_texture
->service_id());
9705 "glCopyTextureChromium", "Stream texture lookup failed");
9708 gfx::Size size
= stream_tex
->GetSize();
9709 source_width
= size
.width();
9710 source_height
= size
.height();
9711 if (source_width
<= 0 || source_height
<= 0) {
9714 "glCopyTextureChromium", "invalid streamtexture size");
9719 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9720 // needed because it takes 10s of milliseconds to initialize.
9721 if (!copy_texture_CHROMIUM_
.get()) {
9722 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9723 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
9724 copy_texture_CHROMIUM_
->Initialize(this);
9725 RestoreCurrentFramebufferBindings();
9726 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
9730 GLenum dest_type_previous
;
9731 GLenum dest_internal_format
;
9732 bool dest_level_defined
= dest_texture
->GetLevelSize(
9733 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
9735 if (dest_level_defined
) {
9736 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
9737 &dest_internal_format
);
9740 // Resize the destination texture to the dimensions of the source texture.
9741 if (!dest_level_defined
|| dest_width
!= source_width
||
9742 dest_height
!= source_height
||
9743 dest_internal_format
!= internal_format
||
9744 dest_type_previous
!= dest_type
) {
9745 // Ensure that the glTexImage2D succeeds.
9746 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9747 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
9749 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
9750 0, internal_format
, dest_type
, NULL
);
9751 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9752 if (error
!= GL_NO_ERROR
) {
9753 RestoreCurrentTexture2DBindings();
9757 texture_manager()->SetLevelInfo(
9758 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
9759 source_height
, 1, 0, internal_format
, dest_type
, true);
9761 texture_manager()->SetLevelCleared(
9762 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
9765 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9766 // before presenting.
9767 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
9768 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9769 // instead of using default matrix crbug.com/226218.
9770 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
9771 0.0f
, 1.0f
, 0.0f
, 0.0f
,
9772 0.0f
, 0.0f
, 1.0f
, 0.0f
,
9773 0.0f
, 0.0f
, 0.0f
, 1.0f
};
9774 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
9776 source_texture
->target(),
9777 dest_texture
->target(),
9778 source_texture
->service_id(),
9779 dest_texture
->service_id(), level
,
9780 source_width
, source_height
,
9782 unpack_premultiply_alpha_
,
9783 unpack_unpremultiply_alpha_
,
9786 copy_texture_CHROMIUM_
->DoCopyTexture(
9788 source_texture
->target(),
9789 dest_texture
->target(),
9790 source_texture
->service_id(),
9791 dest_texture
->service_id(), level
,
9792 source_width
, source_height
,
9794 unpack_premultiply_alpha_
,
9795 unpack_unpremultiply_alpha_
);
9799 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
9800 switch (internalformat
) {
9802 return GL_UNSIGNED_SHORT_5_6_5
;
9804 return GL_UNSIGNED_SHORT_4_4_4_4
;
9806 return GL_UNSIGNED_SHORT_5_5_5_1
;
9808 return GL_UNSIGNED_BYTE
;
9810 return GL_UNSIGNED_BYTE
;
9811 case GL_LUMINANCE8_ALPHA8_EXT
:
9812 return GL_UNSIGNED_BYTE
;
9813 case GL_LUMINANCE8_EXT
:
9814 return GL_UNSIGNED_BYTE
;
9816 return GL_UNSIGNED_BYTE
;
9817 case GL_RGBA32F_EXT
:
9821 case GL_ALPHA32F_EXT
:
9823 case GL_LUMINANCE32F_EXT
:
9825 case GL_LUMINANCE_ALPHA32F_EXT
:
9827 case GL_RGBA16F_EXT
:
9828 return GL_HALF_FLOAT_OES
;
9830 return GL_HALF_FLOAT_OES
;
9831 case GL_ALPHA16F_EXT
:
9832 return GL_HALF_FLOAT_OES
;
9833 case GL_LUMINANCE16F_EXT
:
9834 return GL_HALF_FLOAT_OES
;
9835 case GL_LUMINANCE_ALPHA16F_EXT
:
9836 return GL_HALF_FLOAT_OES
;
9838 return GL_UNSIGNED_BYTE
;
9844 void GLES2DecoderImpl::DoTexStorage2DEXT(
9847 GLenum internal_format
,
9850 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9851 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
9852 TextureManager::ComputeMipMapCount(width
, height
, 1) < levels
) {
9854 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
9857 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
9860 GL_INVALID_OPERATION
,
9861 "glTexStorage2DEXT", "unknown texture for target");
9864 Texture
* texture
= texture_ref
->texture();
9865 if (texture
->IsAttachedToFramebuffer()) {
9866 clear_state_dirty_
= true;
9868 if (texture
->IsImmutable()) {
9870 GL_INVALID_OPERATION
,
9871 "glTexStorage2DEXT", "texture is immutable");
9875 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
9876 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
9879 GLsizei level_width
= width
;
9880 GLsizei level_height
= height
;
9881 uint32 estimated_size
= 0;
9882 for (int ii
= 0; ii
< levels
; ++ii
) {
9883 uint32 level_size
= 0;
9884 if (!GLES2Util::ComputeImageDataSizes(
9885 level_width
, level_height
, format
, type
, state_
.unpack_alignment
,
9886 &estimated_size
, NULL
, NULL
) ||
9887 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
9889 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
9892 level_width
= std::max(1, level_width
>> 1);
9893 level_height
= std::max(1, level_height
>> 1);
9895 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9897 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
9902 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
9903 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
9904 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
9905 if (error
== GL_NO_ERROR
) {
9906 GLsizei level_width
= width
;
9907 GLsizei level_height
= height
;
9908 for (int ii
= 0; ii
< levels
; ++ii
) {
9909 texture_manager()->SetLevelInfo(
9910 texture_ref
, target
, ii
, format
,
9911 level_width
, level_height
, 1, 0, format
, type
, false);
9912 level_width
= std::max(1, level_width
>> 1);
9913 level_height
= std::max(1, level_height
>> 1);
9915 texture
->SetImmutable(true);
9919 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9920 uint32 immediate_data_size
, const cmds::GenMailboxCHROMIUM
& c
) {
9922 mailbox_manager()->GenerateMailboxName(&name
);
9923 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
9924 Bucket
* bucket
= CreateBucket(bucket_id
);
9926 bucket
->SetSize(GL_MAILBOX_SIZE_CHROMIUM
);
9927 bucket
->SetData(&name
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
9929 return error::kNoError
;
9932 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
9933 const GLbyte
* mailbox
) {
9934 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
9935 "context", logger_
.GetLogPrefix(),
9936 "mailbox[0]", static_cast<unsigned char>(mailbox
[0]));
9938 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
9941 GL_INVALID_OPERATION
,
9942 "glProduceTextureCHROMIUM", "unknown texture for target");
9946 Texture
* produced
= texture_manager()->Produce(texture_ref
);
9949 GL_INVALID_OPERATION
,
9950 "glProduceTextureCHROMIUM", "invalid texture");
9954 if (!group_
->mailbox_manager()->ProduceTexture(
9956 *reinterpret_cast<const MailboxName
*>(mailbox
),
9959 GL_INVALID_OPERATION
,
9960 "glProduceTextureCHROMIUM", "invalid mailbox name");
9965 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
9966 const GLbyte
* mailbox
) {
9967 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
9968 "context", logger_
.GetLogPrefix(),
9969 "mailbox[0]", static_cast<unsigned char>(mailbox
[0]));
9971 scoped_refptr
<TextureRef
> texture_ref
=
9972 GetTextureInfoForTargetUnlessDefault(target
);
9973 if (!texture_ref
.get()) {
9974 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9975 "glConsumeTextureCHROMIUM",
9976 "unknown texture for target");
9979 GLuint client_id
= texture_ref
->client_id();
9982 GL_INVALID_OPERATION
,
9983 "glConsumeTextureCHROMIUM", "unknown texture for target");
9987 group_
->mailbox_manager()->ConsumeTexture(
9989 *reinterpret_cast<const MailboxName
*>(mailbox
));
9992 GL_INVALID_OPERATION
,
9993 "glConsumeTextureCHROMIUM", "invalid mailbox name");
9996 if (texture
->target() != target
) {
9998 GL_INVALID_OPERATION
,
9999 "glConsumeTextureCHROMIUM", "invalid target");
10003 DeleteTexturesHelper(1, &client_id
);
10004 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10005 glBindTexture(target
, texture_ref
->service_id());
10007 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10008 unit
.bind_target
= target
;
10010 case GL_TEXTURE_2D
:
10011 unit
.bound_texture_2d
= texture_ref
;
10013 case GL_TEXTURE_CUBE_MAP
:
10014 unit
.bound_texture_cube_map
= texture_ref
;
10016 case GL_TEXTURE_EXTERNAL_OES
:
10017 unit
.bound_texture_external_oes
= texture_ref
;
10019 case GL_TEXTURE_RECTANGLE_ARB
:
10020 unit
.bound_texture_rectangle_arb
= texture_ref
;
10023 NOTREACHED(); // Validation should prevent us getting here.
10028 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10029 GLsizei length
, const GLchar
* marker
) {
10033 debug_marker_manager_
.SetMarker(
10034 length
? std::string(marker
, length
) : std::string(marker
));
10037 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10038 GLsizei length
, const GLchar
* marker
) {
10042 debug_marker_manager_
.PushGroup(
10043 length
? std::string(marker
, length
) : std::string(marker
));
10046 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10047 debug_marker_manager_
.PopGroup();
10050 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10051 GLenum target
, GLint image_id
) {
10052 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10053 if (target
!= GL_TEXTURE_2D
) {
10054 // This might be supported in the future.
10055 LOCAL_SET_GL_ERROR(
10056 GL_INVALID_OPERATION
,
10057 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10061 // Default target might be conceptually valid, but disallow it to avoid
10063 TextureRef
* texture_ref
= GetTextureInfoForTargetUnlessDefault(target
);
10064 if (!texture_ref
) {
10065 LOCAL_SET_GL_ERROR(
10066 GL_INVALID_OPERATION
,
10067 "glBindTexImage2DCHROMIUM", "no texture bound");
10071 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10073 LOCAL_SET_GL_ERROR(
10074 GL_INVALID_OPERATION
,
10075 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10080 ScopedGLErrorSuppressor
suppressor(
10081 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
10082 if (!gl_image
->BindTexImage()) {
10083 LOCAL_SET_GL_ERROR(
10084 GL_INVALID_OPERATION
,
10085 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10090 gfx::Size size
= gl_image
->GetSize();
10091 texture_manager()->SetLevelInfo(
10092 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
10093 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
10094 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
10097 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10098 GLenum target
, GLint image_id
) {
10099 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10100 if (target
!= GL_TEXTURE_2D
) {
10101 // This might be supported in the future.
10102 LOCAL_SET_GL_ERROR(
10103 GL_INVALID_OPERATION
,
10104 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10108 // Default target might be conceptually valid, but disallow it to avoid
10110 TextureRef
* texture_ref
= GetTextureInfoForTargetUnlessDefault(target
);
10111 if (!texture_ref
) {
10112 LOCAL_SET_GL_ERROR(
10113 GL_INVALID_OPERATION
,
10114 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10118 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10120 LOCAL_SET_GL_ERROR(
10121 GL_INVALID_OPERATION
,
10122 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10126 // Do nothing when image is not currently bound.
10127 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
10131 ScopedGLErrorSuppressor
suppressor(
10132 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
10133 gl_image
->ReleaseTexImage();
10136 texture_manager()->SetLevelInfo(
10137 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
10138 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
10141 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10142 uint32 immediate_data_size
, const cmds::TraceBeginCHROMIUM
& c
) {
10143 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10144 if (!bucket
|| bucket
->size() == 0) {
10145 return error::kInvalidArguments
;
10147 std::string command_name
;
10148 if (!bucket
->GetAsString(&command_name
)) {
10149 return error::kInvalidArguments
;
10151 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name
.c_str(), this);
10152 if (!gpu_tracer_
->Begin(command_name
)) {
10153 LOCAL_SET_GL_ERROR(
10154 GL_INVALID_OPERATION
,
10155 "glTraceBeginCHROMIUM", "unable to create begin trace");
10156 return error::kNoError
;
10158 return error::kNoError
;
10161 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10162 if (gpu_tracer_
->CurrentName().empty()) {
10163 LOCAL_SET_GL_ERROR(
10164 GL_INVALID_OPERATION
,
10165 "glTraceEndCHROMIUM", "no trace begin found");
10168 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_
->CurrentName().c_str(), this);
10169 gpu_tracer_
->End();
10172 void GLES2DecoderImpl::DoDrawBuffersEXT(
10173 GLsizei count
, const GLenum
* bufs
) {
10174 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
10175 LOCAL_SET_GL_ERROR(
10177 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10181 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
10183 for (GLsizei i
= 0; i
< count
; ++i
) {
10184 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
10185 bufs
[i
] != GL_NONE
) {
10186 LOCAL_SET_GL_ERROR(
10187 GL_INVALID_OPERATION
,
10188 "glDrawBuffersEXT",
10189 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10193 glDrawBuffersARB(count
, bufs
);
10194 framebuffer
->SetDrawBuffers(count
, bufs
);
10195 } else { // backbuffer
10197 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
10198 LOCAL_SET_GL_ERROR(
10199 GL_INVALID_OPERATION
,
10200 "glDrawBuffersEXT",
10201 "more than one buffer or bufs not GL_NONE or GL_BACK");
10204 GLenum mapped_buf
= bufs
[0];
10205 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10206 bufs
[0] == GL_BACK
) {
10207 mapped_buf
= GL_COLOR_ATTACHMENT0
;
10209 glDrawBuffersARB(count
, &mapped_buf
);
10210 group_
->set_draw_buffer(bufs
[0]);
10214 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10215 const char* function_name
,
10216 TextureRef
* texture_ref
,
10219 const void * data
) {
10220 // We only support async uploads to 2D textures for now.
10221 if (GL_TEXTURE_2D
!= target
) {
10222 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10225 // We only support uploads to level zero for now.
10227 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
10230 // A transfer buffer must be bound, even for asyncTexImage2D.
10231 if (data
== NULL
) {
10232 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
10235 // We only support one async transfer in progress.
10236 if (!texture_ref
||
10237 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10238 LOCAL_SET_GL_ERROR(
10239 GL_INVALID_OPERATION
,
10240 function_name
, "transfer already in progress");
10246 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10247 uint32 immediate_data_size
, const cmds::AsyncTexImage2DCHROMIUM
& c
) {
10248 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10249 GLenum target
= static_cast<GLenum
>(c
.target
);
10250 GLint level
= static_cast<GLint
>(c
.level
);
10251 GLint internal_format
= static_cast<GLint
>(c
.internalformat
);
10252 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10253 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10254 GLint border
= static_cast<GLint
>(c
.border
);
10255 GLenum format
= static_cast<GLenum
>(c
.format
);
10256 GLenum type
= static_cast<GLenum
>(c
.type
);
10257 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10258 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10259 uint32 pixels_size
;
10261 // TODO(epenner): Move this and copies of this memory validation
10262 // into ValidateTexImage2D step.
10263 if (!GLES2Util::ComputeImageDataSizes(
10264 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
10266 return error::kOutOfBounds
;
10268 const void* pixels
= NULL
;
10269 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10270 pixels
= GetSharedMemoryAs
<const void*>(
10271 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10273 return error::kOutOfBounds
;
10277 // All the normal glTexSubImage2D validation.
10278 if (!ValidateTexImage2D(
10279 "glAsyncTexImage2DCHROMIUM", target
, level
, internal_format
,
10280 width
, height
, border
, format
, type
, pixels
, pixels_size
)) {
10281 return error::kNoError
;
10284 // Extra async validation.
10285 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
10286 Texture
* texture
= texture_ref
->texture();
10287 if (!ValidateAsyncTransfer(
10288 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10289 return error::kNoError
;
10291 // Don't allow async redefinition of a textures.
10292 if (texture
->IsDefined()) {
10293 LOCAL_SET_GL_ERROR(
10294 GL_INVALID_OPERATION
,
10295 "glAsyncTexImage2DCHROMIUM", "already defined");
10296 return error::kNoError
;
10299 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
10300 LOCAL_SET_GL_ERROR(
10301 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
10302 return error::kNoError
;
10305 // We know the memory/size is safe, so get the real shared memory since
10306 // it might need to be duped to prevent use-after-free of the memory.
10307 gpu::Buffer buffer
= GetSharedMemoryBuffer(c
.pixels_shm_id
);
10308 base::SharedMemory
* shared_memory
= buffer
.shared_memory
;
10309 uint32 shm_size
= buffer
.size
;
10310 uint32 shm_data_offset
= c
.pixels_shm_offset
;
10311 uint32 shm_data_size
= pixels_size
;
10313 // Setup the parameters.
10314 AsyncTexImage2DParams tex_params
= {
10315 target
, level
, static_cast<GLenum
>(internal_format
),
10316 width
, height
, border
, format
, type
};
10317 AsyncMemoryParams mem_params
= {
10318 shared_memory
, shm_size
, shm_data_offset
, shm_data_size
};
10320 // Set up the async state if needed, and make the texture
10321 // immutable so the async state stays valid. The level info
10322 // is set up lazily when the transfer completes.
10323 AsyncPixelTransferDelegate
* delegate
=
10324 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
10326 texture
->SetImmutable(true);
10328 delegate
->AsyncTexImage2D(
10331 base::Bind(&TextureManager::SetLevelInfoFromParams
,
10332 // The callback is only invoked if the transfer delegate still
10333 // exists, which implies through manager->texture_ref->state
10334 // ownership that both of these pointers are valid.
10335 base::Unretained(texture_manager()),
10336 base::Unretained(texture_ref
),
10338 return error::kNoError
;
10341 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10342 uint32 immediate_data_size
, const cmds::AsyncTexSubImage2DCHROMIUM
& c
) {
10343 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10344 GLenum target
= static_cast<GLenum
>(c
.target
);
10345 GLint level
= static_cast<GLint
>(c
.level
);
10346 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10347 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10348 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10349 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10350 GLenum format
= static_cast<GLenum
>(c
.format
);
10351 GLenum type
= static_cast<GLenum
>(c
.type
);
10353 // TODO(epenner): Move this and copies of this memory validation
10354 // into ValidateTexSubImage2D step.
10356 if (!GLES2Util::ComputeImageDataSizes(
10357 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
10359 return error::kOutOfBounds
;
10361 const void* pixels
= GetSharedMemoryAs
<const void*>(
10362 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
10364 // All the normal glTexSubImage2D validation.
10365 error::Error error
= error::kNoError
;
10366 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
10367 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
10371 // Extra async validation.
10372 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
10373 Texture
* texture
= texture_ref
->texture();
10374 if (!ValidateAsyncTransfer(
10375 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10376 return error::kNoError
;
10378 // Guarantee async textures are always 'cleared' as follows:
10379 // - AsyncTexImage2D can not redefine an existing texture
10380 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10381 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10382 // - Textures become immutable after an async call.
10383 // This way we know in all cases that an async texture is always clear.
10384 if (!texture
->SafeToRenderFrom()) {
10385 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10387 LOCAL_SET_GL_ERROR(
10389 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10390 return error::kNoError
;
10394 // We know the memory/size is safe, so get the real shared memory since
10395 // it might need to be duped to prevent use-after-free of the memory.
10396 gpu::Buffer buffer
= GetSharedMemoryBuffer(c
.data_shm_id
);
10397 base::SharedMemory
* shared_memory
= buffer
.shared_memory
;
10398 uint32 shm_size
= buffer
.size
;
10399 uint32 shm_data_offset
= c
.data_shm_offset
;
10400 uint32 shm_data_size
= data_size
;
10402 // Setup the parameters.
10403 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
10404 width
, height
, format
, type
};
10405 AsyncMemoryParams mem_params
= {shared_memory
, shm_size
,
10406 shm_data_offset
, shm_data_size
};
10407 AsyncPixelTransferDelegate
* delegate
=
10408 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10410 // TODO(epenner): We may want to enforce exclusive use
10411 // of async APIs in which case this should become an error,
10412 // (the texture should have been async defined).
10413 AsyncTexImage2DParams define_params
= {target
, level
,
10415 texture
->GetLevelSize(target
, level
, &define_params
.width
,
10416 &define_params
.height
);
10417 texture
->GetLevelType(target
, level
, &define_params
.type
,
10418 &define_params
.internal_format
);
10419 // Set up the async state if needed, and make the texture
10420 // immutable so the async state stays valid.
10421 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
10422 texture_ref
, define_params
);
10423 texture
->SetImmutable(true);
10426 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
10427 return error::kNoError
;
10430 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10431 uint32 immediate_data_size
, const cmds::WaitAsyncTexImage2DCHROMIUM
& c
) {
10432 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10433 GLenum target
= static_cast<GLenum
>(c
.target
);
10435 if (GL_TEXTURE_2D
!= target
) {
10436 LOCAL_SET_GL_ERROR(
10437 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
10438 return error::kNoError
;
10440 TextureRef
* texture_ref
= GetTextureInfoForTarget(target
);
10441 if (!texture_ref
) {
10442 LOCAL_SET_GL_ERROR(
10443 GL_INVALID_OPERATION
,
10444 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10445 return error::kNoError
;
10447 AsyncPixelTransferDelegate
* delegate
=
10448 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION
,
10452 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10453 return error::kNoError
;
10455 delegate
->WaitForTransferCompletion();
10456 ProcessFinishedAsyncTransfers();
10457 return error::kNoError
;
10460 // Include the auto-generated part of this file. We split this because it means
10461 // we can easily edit the non-auto generated parts right here in this file
10462 // instead of having to edit some template or the code generator.
10463 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10465 } // namespace gles2