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/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #include "base/debug/trace_event_synthetic_delay.h"
22 #include "base/float_util.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/numerics/safe_math.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
45 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
46 #include "gpu/command_buffer/service/gpu_state_tracer.h"
47 #include "gpu/command_buffer/service/gpu_switches.h"
48 #include "gpu/command_buffer/service/gpu_tracer.h"
49 #include "gpu/command_buffer/service/image_manager.h"
50 #include "gpu/command_buffer/service/mailbox_manager.h"
51 #include "gpu/command_buffer/service/memory_tracking.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/shader_translator_cache.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 "third_party/smhasher/src/City.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 <IOSurface/IOSurfaceAPI.h>
69 // Note that this must be included after gl_bindings.h to avoid conflicts.
70 #include <OpenGL/CGLIOSurface.h>
74 #include "base/win/win_util.h"
82 static const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
83 static const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
84 static const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
85 static const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
87 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
88 khronos_uint64_t
CityHashForAngle(const char* name
, unsigned int len
) {
89 return static_cast<khronos_uint64_t
>(
90 CityHash64(name
, static_cast<size_t>(len
)));
94 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
97 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
100 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
101 GLenum precision_type
,
102 GLint
*range
, GLint
*precision
) {
103 switch (precision_type
) {
107 // These values are for a 32-bit twos-complement integer format.
113 case GL_MEDIUM_FLOAT
:
115 // These values are for an IEEE single-precision floating-point format.
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
126 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 glGetShaderPrecisionFormat(shader_type
, precision_type
,
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range
[0] = abs(range
[0]);
142 range
[1] = abs(range
[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
147 if (precision_type
== GL_HIGH_FLOAT
&&
148 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
156 static gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
157 switch (plane_transform
) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
159 return gfx::OVERLAY_TRANSFORM_NONE
;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
171 return gfx::OVERLAY_TRANSFORM_INVALID
;
177 class GLES2DecoderImpl
;
179 // Local versions of the SET_GL_ERROR macros
180 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
181 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
182 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
183 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
184 function_name, value, label)
185 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
186 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
187 function_name, pname)
188 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
189 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
191 #define LOCAL_PEEK_GL_ERROR(function_name) \
192 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
193 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
194 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
195 #define LOCAL_PERFORMANCE_WARNING(msg) \
196 PerformanceWarning(__FILE__, __LINE__, msg)
197 #define LOCAL_RENDER_WARNING(msg) \
198 RenderWarning(__FILE__, __LINE__, msg)
200 // Check that certain assumptions the code makes are true. There are places in
201 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
202 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
203 // a few others) are 32bits. If they are not 32bits the code will have to change
204 // to call those GL functions with service side memory and then copy the results
205 // to shared memory, converting the sizes.
206 COMPILE_ASSERT(sizeof(GLint
) == sizeof(uint32
), // NOLINT
207 GLint_not_same_size_as_uint32
);
208 COMPILE_ASSERT(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
209 GLint_not_same_size_as_uint32
);
210 COMPILE_ASSERT(sizeof(GLfloat
) == sizeof(float), // NOLINT
211 GLfloat_not_same_size_as_float
);
213 // TODO(kbr): the use of this anonymous namespace core dumps the
214 // linker on Mac OS X 10.6 when the symbol ordering file is used
217 // Returns the address of the first byte after a struct.
218 template <typename T
>
219 const void* AddressAfterStruct(const T
& pod
) {
220 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
223 // Returns the address of the frst byte after the struct or NULL if size >
224 // immediate_data_size.
225 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
226 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
228 uint32 immediate_data_size
) {
229 return (size
<= immediate_data_size
) ?
230 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
234 // Computes the data size for certain gl commands like glUniform.
235 bool ComputeDataSize(
238 unsigned int elements_per_unit
,
241 if (!SafeMultiplyUint32(count
, size
, &value
)) {
244 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
251 // A struct to hold info about each command.
253 uint8 arg_flags
; // How to handle the arguments for this command
254 uint8 cmd_flags
; // How to handle this command
255 uint16 arg_count
; // How many arguments are expected for this command.
258 // cmds::name::cmd_flags,
259 // A table of CommandInfo for all the commands.
260 const CommandInfo g_command_info
[] = {
261 #define GLES2_CMD_OP(name) { \
262 cmds::name::kArgFlags, \
263 cmds::name::cmd_flags, \
264 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
266 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
271 // Return true if a character belongs to the ASCII subset as defined in
272 // GLSL ES 1.0 spec section 3.1.
273 static bool CharacterIsValidForGLES(unsigned char c
) {
274 // Printing characters are valid except " $ ` @ \ ' DEL.
275 if (c
>= 32 && c
<= 126 &&
284 // Horizontal tab, line feed, vertical tab, form feed, carriage return
286 if (c
>= 9 && c
<= 13) {
293 static bool StringIsValidForGLES(const char* str
) {
294 for (; *str
; ++str
) {
295 if (!CharacterIsValidForGLES(*str
)) {
302 // This class prevents any GL errors that occur when it is in scope from
303 // being reported to the client.
304 class ScopedGLErrorSuppressor
{
306 explicit ScopedGLErrorSuppressor(
307 const char* function_name
, ErrorState
* error_state
);
308 ~ScopedGLErrorSuppressor();
310 const char* function_name_
;
311 ErrorState
* error_state_
;
312 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
315 // Temporarily changes a decoder's bound texture and restore it when this
316 // object goes out of scope. Also temporarily switches to using active texture
317 // unit zero in case the client has changed that to something invalid.
318 class ScopedTextureBinder
{
320 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
321 ~ScopedTextureBinder();
324 ContextState
* state_
;
326 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
329 // Temporarily changes a decoder's bound render buffer and restore it when this
330 // object goes out of scope.
331 class ScopedRenderBufferBinder
{
333 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
334 ~ScopedRenderBufferBinder();
337 ContextState
* state_
;
338 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
341 // Temporarily changes a decoder's bound frame buffer and restore it when this
342 // object goes out of scope.
343 class ScopedFrameBufferBinder
{
345 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
346 ~ScopedFrameBufferBinder();
349 GLES2DecoderImpl
* decoder_
;
350 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
353 // Temporarily changes a decoder's bound frame buffer to a resolved version of
354 // the multisampled offscreen render buffer if that buffer is multisampled, and,
355 // if it is bound or enforce_internal_framebuffer is true. If internal is
356 // true, the resolved framebuffer is not visible to the parent.
357 class ScopedResolvedFrameBufferBinder
{
359 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
360 bool enforce_internal_framebuffer
,
362 ~ScopedResolvedFrameBufferBinder();
365 GLES2DecoderImpl
* decoder_
;
366 bool resolve_and_bind_
;
367 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
370 class ScopedModifyPixels
{
372 explicit ScopedModifyPixels(TextureRef
* ref
);
373 ~ScopedModifyPixels();
379 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
381 ref_
->texture()->OnWillModifyPixels();
384 ScopedModifyPixels::~ScopedModifyPixels() {
386 ref_
->texture()->OnDidModifyPixels();
389 class ScopedRenderTo
{
391 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
395 const Framebuffer
* framebuffer_
;
398 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
399 : framebuffer_(framebuffer
) {
401 framebuffer_
->OnWillRenderTo();
404 ScopedRenderTo::~ScopedRenderTo() {
406 framebuffer_
->OnDidRenderTo();
409 // Encapsulates an OpenGL texture.
412 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
415 // Create a new render texture.
418 // Set the initial size and format of a render texture or resize it.
419 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
421 // Copy the contents of the currently bound frame buffer.
422 void Copy(const gfx::Size
& size
, GLenum format
);
424 // Destroy the render texture. This must be explicitly called before
425 // destroying this object.
428 // Invalidate the texture. This can be used when a context is lost and it is
429 // not possible to make it current in order to free the resource.
436 gfx::Size
size() const {
441 MemoryTypeTracker memory_tracker_
;
442 ContextState
* state_
;
443 size_t bytes_allocated_
;
446 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
449 // Encapsulates an OpenGL render buffer of any format.
450 class BackRenderbuffer
{
452 explicit BackRenderbuffer(
453 RenderbufferManager
* renderbuffer_manager
,
454 MemoryTracker
* memory_tracker
,
455 ContextState
* state
);
458 // Create a new render buffer.
461 // Set the initial size and format of a render buffer or resize it.
462 bool AllocateStorage(const FeatureInfo
* feature_info
,
463 const gfx::Size
& size
,
467 // Destroy the render buffer. This must be explicitly called before destroying
471 // Invalidate the render buffer. This can be used when a context is lost and
472 // it is not possible to make it current in order to free the resource.
480 RenderbufferManager
* renderbuffer_manager_
;
481 MemoryTypeTracker memory_tracker_
;
482 ContextState
* state_
;
483 size_t bytes_allocated_
;
485 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
488 // Encapsulates an OpenGL frame buffer.
489 class BackFramebuffer
{
491 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
494 // Create a new frame buffer.
497 // Attach a color render buffer to a frame buffer.
498 void AttachRenderTexture(BackTexture
* texture
);
500 // Attach a render buffer to a frame buffer. Note that this unbinds any
501 // currently bound frame buffer.
502 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
504 // Destroy the frame buffer. This must be explicitly called before destroying
508 // Invalidate the frame buffer. This can be used when a context is lost and it
509 // is not possible to make it current in order to free the resource.
512 // See glCheckFramebufferStatusEXT.
513 GLenum
CheckStatus();
520 GLES2DecoderImpl
* decoder_
;
522 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
525 struct FenceCallback
{
526 explicit FenceCallback()
527 : fence(gfx::GLFence::Create()) {
530 std::vector
<base::Closure
> callbacks
;
531 scoped_ptr
<gfx::GLFence
> fence
;
534 class AsyncUploadTokenCompletionObserver
535 : public AsyncPixelTransferCompletionObserver
{
537 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
538 : async_upload_token_(async_upload_token
) {
541 virtual void DidComplete(const AsyncMemoryParams
& mem_params
) OVERRIDE
{
542 DCHECK(mem_params
.buffer());
543 void* data
= mem_params
.GetDataAddress();
544 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
545 sync
->SetAsyncUploadToken(async_upload_token_
);
549 virtual ~AsyncUploadTokenCompletionObserver() {
552 uint32 async_upload_token_
;
554 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
557 // } // anonymous namespace.
560 const unsigned int GLES2Decoder::kDefaultStencilMask
=
561 static_cast<unsigned int>(-1);
563 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
564 uint32
* service_texture_id
) {
568 GLES2Decoder::GLES2Decoder()
569 : initialized_(false),
571 log_commands_(false) {
574 GLES2Decoder::~GLES2Decoder() {
577 void GLES2Decoder::BeginDecoding() {}
579 void GLES2Decoder::EndDecoding() {}
581 // This class implements GLES2Decoder so we don't have to expose all the GLES2
582 // cmd stuff to outside this class.
583 class GLES2DecoderImpl
: public GLES2Decoder
,
584 public FramebufferManager::TextureDetachObserver
,
585 public ErrorStateClient
{
587 explicit GLES2DecoderImpl(ContextGroup
* group
);
588 virtual ~GLES2DecoderImpl();
590 // Overridden from AsyncAPIInterface.
591 virtual Error
DoCommand(unsigned int command
,
592 unsigned int arg_count
,
593 const void* args
) OVERRIDE
;
595 // Overridden from AsyncAPIInterface.
596 virtual const char* GetCommandName(unsigned int command_id
) const OVERRIDE
;
598 // Overridden from GLES2Decoder.
599 virtual bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
600 const scoped_refptr
<gfx::GLContext
>& context
,
602 const gfx::Size
& size
,
603 const DisallowedFeatures
& disallowed_features
,
604 const std::vector
<int32
>& attribs
) OVERRIDE
;
605 virtual void Destroy(bool have_context
) OVERRIDE
;
606 virtual void SetSurface(
607 const scoped_refptr
<gfx::GLSurface
>& surface
) OVERRIDE
;
608 virtual void ProduceFrontBuffer(const Mailbox
& mailbox
) OVERRIDE
;
609 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) OVERRIDE
;
610 void UpdateParentTextureInfo();
611 virtual bool MakeCurrent() OVERRIDE
;
612 virtual GLES2Util
* GetGLES2Util() OVERRIDE
{ return &util_
; }
613 virtual gfx::GLContext
* GetGLContext() OVERRIDE
{ return context_
.get(); }
614 virtual ContextGroup
* GetContextGroup() OVERRIDE
{ return group_
.get(); }
615 virtual Capabilities
GetCapabilities() OVERRIDE
;
616 virtual void RestoreState(const ContextState
* prev_state
) OVERRIDE
;
618 virtual void RestoreActiveTexture() const OVERRIDE
{
619 state_
.RestoreActiveTexture();
621 virtual void RestoreAllTextureUnitBindings(
622 const ContextState
* prev_state
) const OVERRIDE
{
623 state_
.RestoreAllTextureUnitBindings(prev_state
);
625 virtual void RestoreActiveTextureUnitBinding(
626 unsigned int target
) const OVERRIDE
{
627 state_
.RestoreActiveTextureUnitBinding(target
);
629 virtual void RestoreBufferBindings() const OVERRIDE
{
630 state_
.RestoreBufferBindings();
632 virtual void RestoreGlobalState() const OVERRIDE
{
633 state_
.RestoreGlobalState(NULL
);
635 virtual void RestoreProgramBindings() const OVERRIDE
{
636 state_
.RestoreProgramBindings();
638 virtual void RestoreTextureUnitBindings(unsigned unit
) const OVERRIDE
{
639 state_
.RestoreTextureUnitBindings(unit
, NULL
);
641 virtual void RestoreFramebufferBindings() const OVERRIDE
;
642 virtual void RestoreRenderbufferBindings() OVERRIDE
;
643 virtual void RestoreTextureState(unsigned service_id
) const OVERRIDE
;
645 virtual void ClearAllAttributes() const OVERRIDE
;
646 virtual void RestoreAllAttributes() const OVERRIDE
;
648 virtual QueryManager
* GetQueryManager() OVERRIDE
{
649 return query_manager_
.get();
651 virtual VertexArrayManager
* GetVertexArrayManager() OVERRIDE
{
652 return vertex_array_manager_
.get();
654 virtual ImageManager
* GetImageManager() OVERRIDE
{
655 return image_manager_
.get();
657 virtual bool ProcessPendingQueries() OVERRIDE
;
658 virtual bool HasMoreIdleWork() OVERRIDE
;
659 virtual void PerformIdleWork() OVERRIDE
;
661 virtual void WaitForReadPixels(base::Closure callback
) OVERRIDE
;
663 virtual void SetResizeCallback(
664 const base::Callback
<void(gfx::Size
, float)>& callback
) OVERRIDE
;
666 virtual Logger
* GetLogger() OVERRIDE
;
668 virtual void BeginDecoding() OVERRIDE
;
669 virtual void EndDecoding() OVERRIDE
;
671 virtual ErrorState
* GetErrorState() OVERRIDE
;
672 virtual const ContextState
* GetContextState() OVERRIDE
{ return &state_
; }
674 virtual void SetShaderCacheCallback(
675 const ShaderCacheCallback
& callback
) OVERRIDE
;
676 virtual void SetWaitSyncPointCallback(
677 const WaitSyncPointCallback
& callback
) OVERRIDE
;
679 virtual AsyncPixelTransferManager
*
680 GetAsyncPixelTransferManager() OVERRIDE
;
681 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE
;
682 virtual void SetAsyncPixelTransferManagerForTest(
683 AsyncPixelTransferManager
* manager
) OVERRIDE
;
684 virtual void SetIgnoreCachedStateForTest(bool ignore
) OVERRIDE
;
685 void ProcessFinishedAsyncTransfers();
687 virtual bool GetServiceTextureId(uint32 client_texture_id
,
688 uint32
* service_texture_id
) OVERRIDE
;
690 virtual uint32
GetTextureUploadCount() OVERRIDE
;
691 virtual base::TimeDelta
GetTotalTextureUploadTime() OVERRIDE
;
692 virtual base::TimeDelta
GetTotalProcessingCommandsTime() OVERRIDE
;
693 virtual void AddProcessingCommandsTime(base::TimeDelta
) OVERRIDE
;
695 // Restores the current state to the user's settings.
696 void RestoreCurrentFramebufferBindings();
698 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
699 void ApplyDirtyState();
701 // These check the state of the currently bound framebuffer or the
702 // backbuffer if no framebuffer is bound.
703 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
704 // check with all attached and enabled color attachments.
705 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
706 bool BoundFramebufferHasDepthAttachment();
707 bool BoundFramebufferHasStencilAttachment();
709 virtual error::ContextLostReason
GetContextLostReason() OVERRIDE
;
711 // Overridden from FramebufferManager::TextureDetachObserver:
712 virtual void OnTextureRefDetachedFromFramebuffer(
713 TextureRef
* texture
) OVERRIDE
;
715 // Overriden from ErrorStateClient.
716 virtual void OnOutOfMemoryError() OVERRIDE
;
718 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
719 void EnsureRenderbufferBound();
721 // Helpers to facilitate calling into compatible extensions.
722 static void RenderbufferStorageMultisampleHelper(
723 const FeatureInfo
* feature_info
,
726 GLenum internal_format
,
730 void BlitFramebufferHelper(GLint srcX0
,
742 friend class ScopedFrameBufferBinder
;
743 friend class ScopedResolvedFrameBufferBinder
;
744 friend class BackFramebuffer
;
746 // Initialize or re-initialize the shader translator.
747 bool InitializeShaderTranslator();
749 void UpdateCapabilities();
751 // Helpers for the glGen and glDelete functions.
752 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
753 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
754 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
755 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
756 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
757 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
758 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
759 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
760 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
761 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
762 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
763 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
765 // Helper for async upload token completion notification callback.
766 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
767 uint32 sync_data_shm_id
,
768 uint32 sync_data_shm_offset
);
773 void OnFboChanged() const;
774 void OnUseFramebuffer() const;
776 // TODO(gman): Cache these pointers?
777 BufferManager
* buffer_manager() {
778 return group_
->buffer_manager();
781 RenderbufferManager
* renderbuffer_manager() {
782 return group_
->renderbuffer_manager();
785 FramebufferManager
* framebuffer_manager() {
786 return group_
->framebuffer_manager();
789 ProgramManager
* program_manager() {
790 return group_
->program_manager();
793 ShaderManager
* shader_manager() {
794 return group_
->shader_manager();
797 ShaderTranslatorCache
* shader_translator_cache() {
798 return group_
->shader_translator_cache();
801 const TextureManager
* texture_manager() const {
802 return group_
->texture_manager();
805 TextureManager
* texture_manager() {
806 return group_
->texture_manager();
809 MailboxManager
* mailbox_manager() {
810 return group_
->mailbox_manager();
813 ImageManager
* image_manager() { return image_manager_
.get(); }
815 VertexArrayManager
* vertex_array_manager() {
816 return vertex_array_manager_
.get();
819 MemoryTracker
* memory_tracker() {
820 return group_
->memory_tracker();
823 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
824 MemoryTracker
* tracker
= memory_tracker();
826 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
831 bool IsOffscreenBufferMultisampled() const {
832 return offscreen_target_samples_
> 1;
835 // Creates a Texture for the given texture.
836 TextureRef
* CreateTexture(
837 GLuint client_id
, GLuint service_id
) {
838 return texture_manager()->CreateTexture(client_id
, service_id
);
841 // Gets the texture info for the given texture. Returns NULL if none exists.
842 TextureRef
* GetTexture(GLuint client_id
) const {
843 return texture_manager()->GetTexture(client_id
);
846 // Deletes the texture info for the given texture.
847 void RemoveTexture(GLuint client_id
) {
848 texture_manager()->RemoveTexture(client_id
);
851 // Get the size (in pixels) of the currently bound frame buffer (either FBO
852 // or regular back buffer).
853 gfx::Size
GetBoundReadFrameBufferSize();
855 // Get the format of the currently bound frame buffer (either FBO or regular
857 GLenum
GetBoundReadFrameBufferTextureType();
858 GLenum
GetBoundReadFrameBufferInternalFormat();
859 GLenum
GetBoundDrawFrameBufferInternalFormat();
861 // Wrapper for CompressedTexImage2D commands.
862 error::Error
DoCompressedTexImage2D(
865 GLenum internal_format
,
872 // Wrapper for CompressedTexSubImage2D.
873 void DoCompressedTexSubImage2D(
884 // Wrapper for CopyTexImage2D.
885 void DoCopyTexImage2D(
888 GLenum internal_format
,
895 // Wrapper for SwapBuffers.
896 void DoSwapBuffers();
898 // Wrapper for CopyTexSubImage2D.
899 void DoCopyTexSubImage2D(
909 // Validation for TexSubImage2D.
910 bool ValidateTexSubImage2D(
912 const char* function_name
,
923 // Wrapper for TexSubImage2D.
924 error::Error
DoTexSubImage2D(
935 // Extra validation for async tex(Sub)Image2D.
936 bool ValidateAsyncTransfer(
937 const char* function_name
,
938 TextureRef
* texture_ref
,
943 // Wrapper for TexImageIOSurface2DCHROMIUM.
944 void DoTexImageIOSurface2DCHROMIUM(
948 GLuint io_surface_id
,
951 void DoCopyTextureCHROMIUM(
956 GLenum internal_format
,
959 // Wrapper for TexStorage2DEXT.
960 void DoTexStorage2DEXT(
963 GLenum internal_format
,
967 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
968 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
970 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
971 GLenum target
, const GLbyte
* data
);
973 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
974 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
977 void DoBindTexImage2DCHROMIUM(
980 void DoReleaseTexImage2DCHROMIUM(
984 void DoTraceEndCHROMIUM(void);
986 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
988 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
990 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
991 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
993 // Creates a Program for the given program.
994 Program
* CreateProgram(
995 GLuint client_id
, GLuint service_id
) {
996 return program_manager()->CreateProgram(client_id
, service_id
);
999 // Gets the program info for the given program. Returns NULL if none exists.
1000 Program
* GetProgram(GLuint client_id
) {
1001 return program_manager()->GetProgram(client_id
);
1005 void LogClientServiceMapping(
1006 const char* /* function_name */,
1007 GLuint
/* client_id */,
1008 GLuint
/* service_id */) {
1010 template<typename T
>
1011 void LogClientServiceForInfo(
1012 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1015 void LogClientServiceMapping(
1016 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1017 if (service_logging_
) {
1018 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1019 << ": client_id = " << client_id
1020 << ", service_id = " << service_id
;
1023 template<typename T
>
1024 void LogClientServiceForInfo(
1025 T
* info
, GLuint client_id
, const char* function_name
) {
1027 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1032 // Gets the program info for the given program. If it's not a program
1033 // generates a GL error. Returns NULL if not program.
1034 Program
* GetProgramInfoNotShader(
1035 GLuint client_id
, const char* function_name
) {
1036 Program
* program
= GetProgram(client_id
);
1038 if (GetShader(client_id
)) {
1040 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1042 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1045 LogClientServiceForInfo(program
, client_id
, function_name
);
1050 // Creates a Shader for the given shader.
1051 Shader
* CreateShader(
1054 GLenum shader_type
) {
1055 return shader_manager()->CreateShader(
1056 client_id
, service_id
, shader_type
);
1059 // Gets the shader info for the given shader. Returns NULL if none exists.
1060 Shader
* GetShader(GLuint client_id
) {
1061 return shader_manager()->GetShader(client_id
);
1064 // Gets the shader info for the given shader. If it's not a shader generates a
1065 // GL error. Returns NULL if not shader.
1066 Shader
* GetShaderInfoNotProgram(
1067 GLuint client_id
, const char* function_name
) {
1068 Shader
* shader
= GetShader(client_id
);
1070 if (GetProgram(client_id
)) {
1072 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1075 GL_INVALID_VALUE
, function_name
, "unknown shader");
1078 LogClientServiceForInfo(shader
, client_id
, function_name
);
1082 // Creates a buffer info for the given buffer.
1083 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1084 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1087 // Gets the buffer info for the given buffer.
1088 Buffer
* GetBuffer(GLuint client_id
) {
1089 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1093 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1094 // on glDeleteBuffers so we can make sure the user does not try to render
1095 // with deleted buffers.
1096 void RemoveBuffer(GLuint client_id
);
1098 // Creates a framebuffer info for the given framebuffer.
1099 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1100 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1103 // Gets the framebuffer info for the given framebuffer.
1104 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1105 return framebuffer_manager()->GetFramebuffer(client_id
);
1108 // Removes the framebuffer info for the given framebuffer.
1109 void RemoveFramebuffer(GLuint client_id
) {
1110 framebuffer_manager()->RemoveFramebuffer(client_id
);
1113 // Creates a renderbuffer info for the given renderbuffer.
1114 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1115 return renderbuffer_manager()->CreateRenderbuffer(
1116 client_id
, service_id
);
1119 // Gets the renderbuffer info for the given renderbuffer.
1120 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1121 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1124 // Removes the renderbuffer info for the given renderbuffer.
1125 void RemoveRenderbuffer(GLuint client_id
) {
1126 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1129 // Gets the vertex attrib manager for the given vertex array.
1130 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1131 VertexAttribManager
* info
=
1132 vertex_array_manager()->GetVertexAttribManager(client_id
);
1136 // Removes the vertex attrib manager for the given vertex array.
1137 void RemoveVertexAttribManager(GLuint client_id
) {
1138 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1141 // Creates a vertex attrib manager for the given vertex array.
1142 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1145 bool client_visible
) {
1146 return vertex_array_manager()->CreateVertexAttribManager(
1147 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1150 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1151 void DoBindUniformLocationCHROMIUM(
1152 GLuint client_id
, GLint location
, const char* name
);
1154 error::Error
GetAttribLocationHelper(
1155 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1156 const std::string
& name_str
);
1158 error::Error
GetUniformLocationHelper(
1159 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1160 const std::string
& name_str
);
1162 // Helper for glShaderSource.
1163 error::Error
ShaderSourceHelper(
1164 GLuint client_id
, const char* data
, uint32 data_size
);
1166 // Clear any textures used by the current program.
1167 bool ClearUnclearedTextures();
1169 // Clears any uncleared attachments attached to the given frame buffer.
1170 // Returns false if there was a generated GL error.
1171 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1173 // overridden from GLES2Decoder
1174 virtual bool ClearLevel(unsigned service_id
,
1175 unsigned bind_target
,
1178 unsigned internal_format
,
1183 bool is_texture_immutable
) OVERRIDE
;
1185 // Restore all GL state that affects clearing.
1186 void RestoreClearState();
1188 // Remembers the state of some capabilities.
1189 // Returns: true if glEnable/glDisable should actually be called.
1190 bool SetCapabilityState(GLenum cap
, bool enabled
);
1192 // Check that the currently bound framebuffers are valid.
1193 // Generates GL error if not.
1194 bool CheckBoundFramebuffersValid(const char* func_name
);
1196 // Check that the currently bound read framebuffer has a color image
1197 // attached. Generates GL error if not.
1198 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1200 // Check if a framebuffer meets our requirements.
1201 bool CheckFramebufferValid(
1202 Framebuffer
* framebuffer
,
1204 const char* func_name
);
1206 // Checks if the current program exists and is valid. If not generates the
1207 // appropriate GL error. Returns true if the current program is in a usable
1209 bool CheckCurrentProgram(const char* function_name
);
1211 // Checks if the current program exists and is valid and that location is not
1212 // -1. If the current program is not valid generates the appropriate GL
1213 // error. Returns true if the current program is in a usable state and
1214 // location is not -1.
1215 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1217 // Gets the type of a uniform for a location in the current program. Sets GL
1218 // errors if the current program is not valid. Returns true if the current
1219 // program is valid and the location exists. Adjusts count so it
1220 // does not overflow the uniform.
1221 bool PrepForSetUniformByLocation(GLint fake_location
,
1222 const char* function_name
,
1223 Program::UniformApiType api_type
,
1224 GLint
* real_location
,
1228 // Gets the service id for any simulated backbuffer fbo.
1229 GLuint
GetBackbufferServiceId() const;
1231 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1232 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1234 // Helper for glGetVertexAttrib
1235 void GetVertexAttribHelper(
1236 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1238 // Wrapper for glCreateProgram
1239 bool CreateProgramHelper(GLuint client_id
);
1241 // Wrapper for glCreateShader
1242 bool CreateShaderHelper(GLenum type
, GLuint client_id
);
1244 // Wrapper for glActiveTexture
1245 void DoActiveTexture(GLenum texture_unit
);
1247 // Wrapper for glAttachShader
1248 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1250 // Wrapper for glBindBuffer since we need to track the current targets.
1251 void DoBindBuffer(GLenum target
, GLuint buffer
);
1253 // Wrapper for glBindFramebuffer since we need to track the current targets.
1254 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1256 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1257 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1259 // Wrapper for glBindTexture since we need to track the current targets.
1260 void DoBindTexture(GLenum target
, GLuint texture
);
1262 // Wrapper for glBindVertexArrayOES
1263 void DoBindVertexArrayOES(GLuint array
);
1264 void EmulateVertexArrayState();
1266 // Wrapper for glBlitFramebufferCHROMIUM.
1267 void DoBlitFramebufferCHROMIUM(
1268 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1269 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1270 GLbitfield mask
, GLenum filter
);
1272 // Wrapper for glBufferSubData.
1273 void DoBufferSubData(
1274 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1276 // Wrapper for glCheckFramebufferStatus
1277 GLenum
DoCheckFramebufferStatus(GLenum target
);
1279 // Wrapper for glClear
1280 error::Error
DoClear(GLbitfield mask
);
1282 // Wrappers for various state.
1283 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1284 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1286 // Wrapper for glCompileShader.
1287 void DoCompileShader(GLuint shader
);
1289 // Helper for DeleteSharedIdsCHROMIUM commands.
1290 void DoDeleteSharedIdsCHROMIUM(
1291 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1293 // Wrapper for glDetachShader
1294 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1296 // Wrapper for glDisable
1297 void DoDisable(GLenum cap
);
1299 // Wrapper for glDisableVertexAttribArray.
1300 void DoDisableVertexAttribArray(GLuint index
);
1302 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1304 void DoDiscardFramebufferEXT(GLenum target
,
1305 GLsizei numAttachments
,
1306 const GLenum
* attachments
);
1308 // Wrapper for glEnable
1309 void DoEnable(GLenum cap
);
1311 // Wrapper for glEnableVertexAttribArray.
1312 void DoEnableVertexAttribArray(GLuint index
);
1314 // Wrapper for glFinish.
1317 // Wrapper for glFlush.
1320 // Wrapper for glFramebufferRenderbufffer.
1321 void DoFramebufferRenderbuffer(
1322 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1323 GLuint renderbuffer
);
1325 // Wrapper for glFramebufferTexture2D.
1326 void DoFramebufferTexture2D(
1327 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1330 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1331 void DoFramebufferTexture2DMultisample(
1332 GLenum target
, GLenum attachment
, GLenum textarget
,
1333 GLuint texture
, GLint level
, GLsizei samples
);
1335 // Common implementation for both DoFramebufferTexture2D wrappers.
1336 void DoFramebufferTexture2DCommon(const char* name
,
1337 GLenum target
, GLenum attachment
, GLenum textarget
,
1338 GLuint texture
, GLint level
, GLsizei samples
);
1340 // Wrapper for glGenerateMipmap
1341 void DoGenerateMipmap(GLenum target
);
1343 // Helper for GenSharedIdsCHROMIUM commands.
1344 void DoGenSharedIdsCHROMIUM(
1345 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
);
1347 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1348 // to account for different pname values defined in different extension
1350 GLenum
AdjustGetPname(GLenum pname
);
1352 // Wrapper for DoGetBooleanv.
1353 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1355 // Wrapper for DoGetFloatv.
1356 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1358 // Wrapper for glGetFramebufferAttachmentParameteriv.
1359 void DoGetFramebufferAttachmentParameteriv(
1360 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1362 // Wrapper for glGetIntegerv.
1363 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1365 // Gets the max value in a range in a buffer.
1366 GLuint
DoGetMaxValueInBufferCHROMIUM(
1367 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1369 // Wrapper for glGetBufferParameteriv.
1370 void DoGetBufferParameteriv(
1371 GLenum target
, GLenum pname
, GLint
* params
);
1373 // Wrapper for glGetProgramiv.
1374 void DoGetProgramiv(
1375 GLuint program_id
, GLenum pname
, GLint
* params
);
1377 // Wrapper for glRenderbufferParameteriv.
1378 void DoGetRenderbufferParameteriv(
1379 GLenum target
, GLenum pname
, GLint
* params
);
1381 // Wrapper for glGetShaderiv
1382 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1384 // Wrappers for glGetTexParameter.
1385 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1386 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1387 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1389 // Wrappers for glGetVertexAttrib.
1390 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1391 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1393 // Wrappers for glIsXXX functions.
1394 bool DoIsEnabled(GLenum cap
);
1395 bool DoIsBuffer(GLuint client_id
);
1396 bool DoIsFramebuffer(GLuint client_id
);
1397 bool DoIsProgram(GLuint client_id
);
1398 bool DoIsRenderbuffer(GLuint client_id
);
1399 bool DoIsShader(GLuint client_id
);
1400 bool DoIsTexture(GLuint client_id
);
1401 bool DoIsVertexArrayOES(GLuint client_id
);
1403 // Wrapper for glLinkProgram
1404 void DoLinkProgram(GLuint program
);
1406 // Helper for RegisterSharedIdsCHROMIUM.
1407 void DoRegisterSharedIdsCHROMIUM(
1408 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1410 // Wrapper for glRenderbufferStorage.
1411 void DoRenderbufferStorage(
1412 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1414 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1415 void DoRenderbufferStorageMultisampleCHROMIUM(
1416 GLenum target
, GLsizei samples
, GLenum internalformat
,
1417 GLsizei width
, GLsizei height
);
1419 // Handler for glRenderbufferStorageMultisampleEXT
1420 // (multisampled_render_to_texture).
1421 void DoRenderbufferStorageMultisampleEXT(
1422 GLenum target
, GLsizei samples
, GLenum internalformat
,
1423 GLsizei width
, GLsizei height
);
1425 // Common validation for multisample extensions.
1426 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1427 GLenum internalformat
,
1431 // Verifies that the currently bound multisample renderbuffer is valid
1432 // Very slow! Only done on platforms with driver bugs that return invalid
1433 // buffers under memory pressure
1434 bool VerifyMultisampleRenderbufferIntegrity(
1435 GLuint renderbuffer
, GLenum format
);
1437 // Wrapper for glReleaseShaderCompiler.
1438 void DoReleaseShaderCompiler() { }
1440 // Wrappers for glTexParameter functions.
1441 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1442 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1443 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1444 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1446 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1447 // spec only these 2 functions can be used to set sampler uniforms.
1448 void DoUniform1i(GLint fake_location
, GLint v0
);
1449 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1450 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1451 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1452 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1454 // Wrappers for glUniformfv because some drivers don't correctly accept
1456 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1457 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1458 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1459 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1461 void DoUniformMatrix2fv(
1462 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1463 const GLfloat
* value
);
1464 void DoUniformMatrix3fv(
1465 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1466 const GLfloat
* value
);
1467 void DoUniformMatrix4fv(
1468 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1469 const GLfloat
* value
);
1471 bool SetVertexAttribValue(
1472 const char* function_name
, GLuint index
, const GLfloat
* value
);
1474 // Wrappers for glVertexAttrib??
1475 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1476 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1477 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1478 void DoVertexAttrib4f(
1479 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1480 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1481 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1482 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1483 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1485 // Wrapper for glViewport
1486 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1488 // Wrapper for glUseProgram
1489 void DoUseProgram(GLuint program
);
1491 // Wrapper for glValidateProgram.
1492 void DoValidateProgram(GLuint program_client_id
);
1494 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1495 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1496 void DoPopGroupMarkerEXT(void);
1498 // Gets the number of values that will be returned by glGetXXX. Returns
1499 // false if pname is unknown.
1500 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1502 // Checks if the current program and vertex attributes are valid for drawing.
1504 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1507 // Returns true if successful, simulated will be true if attrib0 was
1509 bool SimulateAttrib0(
1510 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1511 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1513 // If an image is bound to texture, this will call Will/DidUseTexImage
1515 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1516 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1518 // Returns false if textures were replaced.
1519 bool PrepareTexturesForRender();
1520 void RestoreStateForTextures();
1522 // Returns true if GL_FIXED attribs were simulated.
1523 bool SimulateFixedAttribs(
1524 const char* function_name
,
1525 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1526 void RestoreStateForSimulatedFixedAttribs();
1528 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1529 // cases (primcount is always 1 for non-instanced).
1530 error::Error
DoDrawArrays(
1531 const char* function_name
,
1532 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1534 error::Error
DoDrawElements(
1535 const char* function_name
,
1536 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1537 int32 offset
, GLsizei primcount
);
1539 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1540 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1541 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1544 return GL_TEXTURE_2D
;
1545 case GL_SAMPLER_CUBE
:
1546 return GL_TEXTURE_CUBE_MAP
;
1547 case GL_SAMPLER_EXTERNAL_OES
:
1548 return GL_TEXTURE_EXTERNAL_OES
;
1549 case GL_SAMPLER_2D_RECT_ARB
:
1550 return GL_TEXTURE_RECTANGLE_ARB
;
1557 // Gets the framebuffer info for a particular target.
1558 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1559 Framebuffer
* framebuffer
= NULL
;
1561 case GL_FRAMEBUFFER
:
1562 case GL_DRAW_FRAMEBUFFER_EXT
:
1563 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1565 case GL_READ_FRAMEBUFFER_EXT
:
1566 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1575 Renderbuffer
* GetRenderbufferInfoForTarget(
1577 Renderbuffer
* renderbuffer
= NULL
;
1579 case GL_RENDERBUFFER
:
1580 renderbuffer
= state_
.bound_renderbuffer
.get();
1586 return renderbuffer
;
1589 // Validates the program and location for a glGetUniform call and returns
1590 // a SizeResult setup to receive the result. Returns true if glGetUniform
1591 // should be called.
1592 bool GetUniformSetup(
1593 GLuint program
, GLint fake_location
,
1594 uint32 shm_id
, uint32 shm_offset
,
1595 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1596 void** result
, GLenum
* result_type
);
1598 virtual bool WasContextLost() OVERRIDE
;
1599 virtual bool WasContextLostByRobustnessExtension() OVERRIDE
;
1600 virtual void LoseContext(uint32 reset_status
) OVERRIDE
;
1602 #if defined(OS_MACOSX)
1603 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1606 bool ValidateCompressedTexDimensions(
1607 const char* function_name
,
1608 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1609 bool ValidateCompressedTexFuncData(
1610 const char* function_name
,
1611 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1612 bool ValidateCompressedTexSubDimensions(
1613 const char* function_name
,
1614 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1615 GLsizei width
, GLsizei height
, GLenum format
,
1618 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1619 void PerformanceWarning(
1620 const char* filename
, int line
, const std::string
& msg
);
1622 const FeatureInfo::FeatureFlags
& features() const {
1623 return feature_info_
->feature_flags();
1626 const FeatureInfo::Workarounds
& workarounds() const {
1627 return feature_info_
->workarounds();
1630 bool ShouldDeferDraws() {
1631 return !offscreen_target_frame_buffer_
.get() &&
1632 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1633 surface_
->DeferDraws();
1636 bool ShouldDeferReads() {
1637 return !offscreen_target_frame_buffer_
.get() &&
1638 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1639 surface_
->DeferDraws();
1642 error::Error
WillAccessBoundFramebufferForDraw() {
1643 if (ShouldDeferDraws())
1644 return error::kDeferCommandUntilLater
;
1645 if (!offscreen_target_frame_buffer_
.get() &&
1646 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1647 !surface_
->SetBackbufferAllocation(true))
1648 return error::kLostContext
;
1649 return error::kNoError
;
1652 error::Error
WillAccessBoundFramebufferForRead() {
1653 if (ShouldDeferReads())
1654 return error::kDeferCommandUntilLater
;
1655 if (!offscreen_target_frame_buffer_
.get() &&
1656 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1657 !surface_
->SetBackbufferAllocation(true))
1658 return error::kLostContext
;
1659 return error::kNoError
;
1662 void ProcessPendingReadPixels();
1663 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1665 // Generate a member function prototype for each command in an automated and
1667 #define GLES2_CMD_OP(name) \
1668 Error Handle ## name( \
1669 uint32 immediate_data_size, \
1670 const cmds::name& args); \
1672 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1676 // The GL context this decoder renders to on behalf of the client.
1677 scoped_refptr
<gfx::GLSurface
> surface_
;
1678 scoped_refptr
<gfx::GLContext
> context_
;
1680 // The ContextGroup for this decoder uses to track resources.
1681 scoped_refptr
<ContextGroup
> group_
;
1683 DebugMarkerManager debug_marker_manager_
;
1686 // All the state for this context.
1687 ContextState state_
;
1689 // Current width and height of the offscreen frame buffer.
1690 gfx::Size offscreen_size_
;
1692 // Util to help with GL.
1695 // unpack flip y as last set by glPixelStorei
1696 bool unpack_flip_y_
;
1698 // unpack (un)premultiply alpha as last set by glPixelStorei
1699 bool unpack_premultiply_alpha_
;
1700 bool unpack_unpremultiply_alpha_
;
1702 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1703 GLuint attrib_0_buffer_id_
;
1705 // The value currently in attrib_0.
1706 Vec4 attrib_0_value_
;
1708 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1709 bool attrib_0_buffer_matches_value_
;
1711 // The size of attrib 0.
1712 GLsizei attrib_0_size_
;
1714 // The buffer used to simulate GL_FIXED attribs.
1715 GLuint fixed_attrib_buffer_id_
;
1717 // The size of fiixed attrib buffer.
1718 GLsizei fixed_attrib_buffer_size_
;
1720 // The offscreen frame buffer that the client renders to. With EGL, the
1721 // depth and stencil buffers are separate. With regular GL there is a single
1722 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1723 // offscreen_target_stencil_render_buffer_ is unused.
1724 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1725 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1726 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1727 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1728 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1729 GLenum offscreen_target_color_format_
;
1730 GLenum offscreen_target_depth_format_
;
1731 GLenum offscreen_target_stencil_format_
;
1732 GLsizei offscreen_target_samples_
;
1733 GLboolean offscreen_target_buffer_preserved_
;
1735 // The copy that is saved when SwapBuffers is called.
1736 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1737 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1738 scoped_refptr
<TextureRef
>
1739 offscreen_saved_color_texture_info_
;
1741 // The copy that is used as the destination for multi-sample resolves.
1742 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1743 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1744 GLenum offscreen_saved_color_format_
;
1746 scoped_ptr
<QueryManager
> query_manager_
;
1748 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1750 scoped_ptr
<ImageManager
> image_manager_
;
1752 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1754 WaitSyncPointCallback wait_sync_point_callback_
;
1756 ShaderCacheCallback shader_cache_callback_
;
1758 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1760 // The format of the back buffer_
1761 GLenum back_buffer_color_format_
;
1762 bool back_buffer_has_depth_
;
1763 bool back_buffer_has_stencil_
;
1765 // Backbuffer attachments that are currently undefined.
1766 uint32 backbuffer_needs_clear_bits_
;
1768 // The current decoder error communicates the decoder error through command
1769 // processing functions that do not return the error value. Should be set only
1770 // if not returning an error.
1771 error::Error current_decoder_error_
;
1773 bool use_shader_translator_
;
1774 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1775 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1777 DisallowedFeatures disallowed_features_
;
1779 // Cached from ContextGroup
1780 const Validators
* validators_
;
1781 scoped_refptr
<FeatureInfo
> feature_info_
;
1785 bool has_robustness_extension_
;
1786 GLenum reset_status_
;
1787 bool reset_by_robustness_extension_
;
1788 bool supports_post_sub_buffer_
;
1790 // These flags are used to override the state of the shared feature_info_
1791 // member. Because the same FeatureInfo instance may be shared among many
1792 // contexts, the assumptions on the availablity of extensions in WebGL
1793 // contexts may be broken. These flags override the shared state to preserve
1795 bool force_webgl_glsl_validation_
;
1796 bool derivatives_explicitly_enabled_
;
1797 bool frag_depth_explicitly_enabled_
;
1798 bool draw_buffers_explicitly_enabled_
;
1799 bool shader_texture_lod_explicitly_enabled_
;
1801 bool compile_shader_always_succeeds_
;
1803 // An optional behaviour to lose the context and group when OOM.
1804 bool lose_context_when_out_of_memory_
;
1807 bool service_logging_
;
1809 #if defined(OS_MACOSX)
1810 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1811 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1814 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1816 // Cached values of the currently assigned viewport dimensions.
1817 GLsizei viewport_max_width_
;
1818 GLsizei viewport_max_height_
;
1820 // Command buffer stats.
1821 base::TimeDelta total_processing_commands_time_
;
1823 // States related to each manager.
1824 DecoderTextureState texture_state_
;
1825 DecoderFramebufferState framebuffer_state_
;
1827 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1828 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1829 int gpu_trace_level_
;
1830 bool gpu_trace_commands_
;
1832 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1834 // Used to validate multisample renderbuffers if needed
1835 GLuint validation_texture_
;
1836 GLuint validation_fbo_multisample_
;
1837 GLuint validation_fbo_
;
1839 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1842 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1843 const char* function_name
, ErrorState
* error_state
)
1844 : function_name_(function_name
),
1845 error_state_(error_state
) {
1846 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1849 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1850 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1853 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1854 TextureUnit
& info
= state
->texture_units
[0];
1856 scoped_refptr
<TextureRef
> texture_ref
;
1859 texture_ref
= info
.bound_texture_2d
;
1861 case GL_TEXTURE_CUBE_MAP
:
1862 texture_ref
= info
.bound_texture_cube_map
;
1864 case GL_TEXTURE_EXTERNAL_OES
:
1865 texture_ref
= info
.bound_texture_external_oes
;
1867 case GL_TEXTURE_RECTANGLE_ARB
:
1868 texture_ref
= info
.bound_texture_rectangle_arb
;
1874 if (texture_ref
.get()) {
1875 last_id
= texture_ref
->service_id();
1880 glBindTexture(target
, last_id
);
1881 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1884 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1889 ScopedGLErrorSuppressor
suppressor(
1890 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1892 // TODO(apatrick): Check if there are any other states that need to be reset
1893 // before binding a new texture.
1894 glActiveTexture(GL_TEXTURE0
);
1895 glBindTexture(target
, id
);
1898 ScopedTextureBinder::~ScopedTextureBinder() {
1899 ScopedGLErrorSuppressor
suppressor(
1900 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1901 RestoreCurrentTextureBindings(state_
, target_
);
1904 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1907 ScopedGLErrorSuppressor
suppressor(
1908 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1909 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1912 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1913 ScopedGLErrorSuppressor
suppressor(
1914 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
1915 state_
->RestoreRenderbufferBindings();
1918 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
1920 : decoder_(decoder
) {
1921 ScopedGLErrorSuppressor
suppressor(
1922 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1923 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
1924 decoder
->OnFboChanged();
1927 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1928 ScopedGLErrorSuppressor
suppressor(
1929 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1930 decoder_
->RestoreCurrentFramebufferBindings();
1933 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1934 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
1935 : decoder_(decoder
) {
1936 resolve_and_bind_
= (
1937 decoder_
->offscreen_target_frame_buffer_
.get() &&
1938 decoder_
->IsOffscreenBufferMultisampled() &&
1939 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
1940 enforce_internal_framebuffer
));
1941 if (!resolve_and_bind_
)
1944 ScopedGLErrorSuppressor
suppressor(
1945 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1946 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
1947 decoder_
->offscreen_target_frame_buffer_
->id());
1950 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
1951 decoder_
->offscreen_resolved_frame_buffer_
.reset(
1952 new BackFramebuffer(decoder_
));
1953 decoder_
->offscreen_resolved_frame_buffer_
->Create();
1954 decoder_
->offscreen_resolved_color_texture_
.reset(
1955 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
1956 decoder_
->offscreen_resolved_color_texture_
->Create();
1958 DCHECK(decoder_
->offscreen_saved_color_format_
);
1959 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
1960 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
1962 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
1963 decoder_
->offscreen_resolved_color_texture_
.get());
1964 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
1965 GL_FRAMEBUFFER_COMPLETE
) {
1966 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
1967 << "because offscreen resolved FBO was incomplete.";
1971 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
1973 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
1975 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
1976 const int width
= decoder_
->offscreen_size_
.width();
1977 const int height
= decoder_
->offscreen_size_
.height();
1978 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
1979 decoder
->BlitFramebufferHelper(0,
1987 GL_COLOR_BUFFER_BIT
,
1989 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
1992 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1993 if (!resolve_and_bind_
)
1996 ScopedGLErrorSuppressor
suppressor(
1997 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1998 decoder_
->RestoreCurrentFramebufferBindings();
1999 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2000 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2004 BackTexture::BackTexture(
2005 MemoryTracker
* memory_tracker
,
2006 ContextState
* state
)
2007 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2009 bytes_allocated_(0),
2013 BackTexture::~BackTexture() {
2014 // This does not destroy the render texture because that would require that
2015 // the associated GL context was current. Just check that it was explicitly
2020 void BackTexture::Create() {
2021 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2022 state_
->GetErrorState());
2024 glGenTextures(1, &id_
);
2025 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2026 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2027 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2028 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2029 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2031 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2032 // never called on an offscreen context, no data will ever be uploaded to the
2033 // saved offscreen color texture (it is deferred until to when SwapBuffers
2034 // is called). My idea is that some nvidia drivers might have a bug where
2035 // deleting a texture that has never been populated might cause a
2038 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2040 bytes_allocated_
= 16u * 16u * 4u;
2041 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2044 bool BackTexture::AllocateStorage(
2045 const gfx::Size
& size
, GLenum format
, bool zero
) {
2047 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2048 state_
->GetErrorState());
2049 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2050 uint32 image_size
= 0;
2051 GLES2Util::ComputeImageDataSizes(
2052 size
.width(), size
.height(), format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2055 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2059 scoped_ptr
<char[]> zero_data
;
2061 zero_data
.reset(new char[image_size
]);
2062 memset(zero_data
.get(), 0, image_size
);
2065 glTexImage2D(GL_TEXTURE_2D
,
2077 bool success
= glGetError() == GL_NO_ERROR
;
2079 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2080 bytes_allocated_
= image_size
;
2081 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2086 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2088 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2089 state_
->GetErrorState());
2090 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2091 glCopyTexImage2D(GL_TEXTURE_2D
,
2100 void BackTexture::Destroy() {
2102 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2103 state_
->GetErrorState());
2104 glDeleteTextures(1, &id_
);
2107 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2108 bytes_allocated_
= 0;
2111 void BackTexture::Invalidate() {
2115 BackRenderbuffer::BackRenderbuffer(
2116 RenderbufferManager
* renderbuffer_manager
,
2117 MemoryTracker
* memory_tracker
,
2118 ContextState
* state
)
2119 : renderbuffer_manager_(renderbuffer_manager
),
2120 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2122 bytes_allocated_(0),
2126 BackRenderbuffer::~BackRenderbuffer() {
2127 // This does not destroy the render buffer because that would require that
2128 // the associated GL context was current. Just check that it was explicitly
2133 void BackRenderbuffer::Create() {
2134 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2135 state_
->GetErrorState());
2137 glGenRenderbuffersEXT(1, &id_
);
2140 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2141 const gfx::Size
& size
,
2144 ScopedGLErrorSuppressor
suppressor(
2145 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2146 ScopedRenderBufferBinder
binder(state_
, id_
);
2148 uint32 estimated_size
= 0;
2149 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2150 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2154 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2159 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2164 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2171 bool success
= glGetError() == GL_NO_ERROR
;
2173 // Mark the previously allocated bytes as free.
2174 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2175 bytes_allocated_
= estimated_size
;
2176 // Track the newly allocated bytes.
2177 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2182 void BackRenderbuffer::Destroy() {
2184 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2185 state_
->GetErrorState());
2186 glDeleteRenderbuffersEXT(1, &id_
);
2189 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2190 bytes_allocated_
= 0;
2193 void BackRenderbuffer::Invalidate() {
2197 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2198 : decoder_(decoder
),
2202 BackFramebuffer::~BackFramebuffer() {
2203 // This does not destroy the frame buffer because that would require that
2204 // the associated GL context was current. Just check that it was explicitly
2209 void BackFramebuffer::Create() {
2210 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2211 decoder_
->GetErrorState());
2213 glGenFramebuffersEXT(1, &id_
);
2216 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2218 ScopedGLErrorSuppressor
suppressor(
2219 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2220 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2221 GLuint attach_id
= texture
? texture
->id() : 0;
2222 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2223 GL_COLOR_ATTACHMENT0
,
2229 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2230 BackRenderbuffer
* render_buffer
) {
2232 ScopedGLErrorSuppressor
suppressor(
2233 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2234 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2235 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2236 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2242 void BackFramebuffer::Destroy() {
2244 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2245 decoder_
->GetErrorState());
2246 glDeleteFramebuffersEXT(1, &id_
);
2251 void BackFramebuffer::Invalidate() {
2255 GLenum
BackFramebuffer::CheckStatus() {
2257 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2258 decoder_
->GetErrorState());
2259 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2260 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2263 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2264 return new GLES2DecoderImpl(group
);
2267 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2270 logger_(&debug_marker_manager_
),
2271 state_(group_
->feature_info(), this, &logger_
),
2272 unpack_flip_y_(false),
2273 unpack_premultiply_alpha_(false),
2274 unpack_unpremultiply_alpha_(false),
2275 attrib_0_buffer_id_(0),
2276 attrib_0_buffer_matches_value_(true),
2278 fixed_attrib_buffer_id_(0),
2279 fixed_attrib_buffer_size_(0),
2280 offscreen_target_color_format_(0),
2281 offscreen_target_depth_format_(0),
2282 offscreen_target_stencil_format_(0),
2283 offscreen_target_samples_(0),
2284 offscreen_target_buffer_preserved_(true),
2285 offscreen_saved_color_format_(0),
2286 back_buffer_color_format_(0),
2287 back_buffer_has_depth_(false),
2288 back_buffer_has_stencil_(false),
2289 backbuffer_needs_clear_bits_(0),
2290 current_decoder_error_(error::kNoError
),
2291 use_shader_translator_(true),
2292 validators_(group_
->feature_info()->validators()),
2293 feature_info_(group_
->feature_info()),
2295 has_robustness_extension_(false),
2296 reset_status_(GL_NO_ERROR
),
2297 reset_by_robustness_extension_(false),
2298 supports_post_sub_buffer_(false),
2299 force_webgl_glsl_validation_(false),
2300 derivatives_explicitly_enabled_(false),
2301 frag_depth_explicitly_enabled_(false),
2302 draw_buffers_explicitly_enabled_(false),
2303 shader_texture_lod_explicitly_enabled_(false),
2304 compile_shader_always_succeeds_(false),
2305 lose_context_when_out_of_memory_(false),
2306 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2307 switches::kEnableGPUServiceLoggingGPU
)),
2308 viewport_max_width_(0),
2309 viewport_max_height_(0),
2310 texture_state_(group_
->feature_info()
2312 .texsubimage2d_faster_than_teximage2d
),
2313 validation_texture_(0),
2314 validation_fbo_multisample_(0),
2315 validation_fbo_(0) {
2318 attrib_0_value_
.v
[0] = 0.0f
;
2319 attrib_0_value_
.v
[1] = 0.0f
;
2320 attrib_0_value_
.v
[2] = 0.0f
;
2321 attrib_0_value_
.v
[3] = 1.0f
;
2323 // The shader translator is used for WebGL even when running on EGL
2324 // because additional restrictions are needed (like only enabling
2325 // GL_OES_standard_derivatives on demand). It is used for the unit
2326 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2327 // the empty string to CompileShader and this is not a valid shader.
2328 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2329 CommandLine::ForCurrentProcess()->HasSwitch(
2330 switches::kDisableGLSLTranslator
)) {
2331 use_shader_translator_
= false;
2335 GLES2DecoderImpl::~GLES2DecoderImpl() {
2338 bool GLES2DecoderImpl::Initialize(
2339 const scoped_refptr
<gfx::GLSurface
>& surface
,
2340 const scoped_refptr
<gfx::GLContext
>& context
,
2342 const gfx::Size
& size
,
2343 const DisallowedFeatures
& disallowed_features
,
2344 const std::vector
<int32
>& attribs
) {
2345 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2346 DCHECK(context
->IsCurrent(surface
.get()));
2347 DCHECK(!context_
.get());
2350 gpu_tracer_
.reset(new GPUTracer(this));
2351 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2352 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2353 gpu_trace_level_
= 2;
2354 gpu_trace_commands_
= false;
2356 if (CommandLine::ForCurrentProcess()->HasSwitch(
2357 switches::kEnableGPUDebugging
)) {
2361 if (CommandLine::ForCurrentProcess()->HasSwitch(
2362 switches::kEnableGPUCommandLogging
)) {
2363 set_log_commands(true);
2366 compile_shader_always_succeeds_
= CommandLine::ForCurrentProcess()->HasSwitch(
2367 switches::kCompileShaderAlwaysSucceeds
);
2370 // Take ownership of the context and surface. The surface can be replaced with
2375 ContextCreationAttribHelper attrib_parser
;
2376 if (!attrib_parser
.Parse(attribs
))
2379 // Save the loseContextWhenOutOfMemory context creation attribute.
2380 lose_context_when_out_of_memory_
=
2381 attrib_parser
.lose_context_when_out_of_memory
;
2383 // If the failIfMajorPerformanceCaveat context creation attribute was true
2384 // and we are using a software renderer, fail.
2385 if (attrib_parser
.fail_if_major_perf_caveat
&&
2386 feature_info_
->feature_flags().is_swiftshader
) {
2387 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2392 if (!group_
->Initialize(this, disallowed_features
)) {
2393 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2394 << "failed to initialize.";
2395 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2401 disallowed_features_
= disallowed_features
;
2403 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2404 vertex_array_manager_
.reset(new VertexArrayManager());
2406 GLuint default_vertex_attrib_service_id
= 0;
2407 if (features().native_vertex_array_object
) {
2408 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2409 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2412 state_
.default_vertex_attrib_manager
=
2413 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2415 state_
.default_vertex_attrib_manager
->Initialize(
2416 group_
->max_vertex_attribs(),
2417 feature_info_
->workarounds().init_vertex_attributes
);
2419 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2420 DoBindVertexArrayOES(0);
2422 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2424 image_manager_
.reset(new ImageManager
);
2426 util_
.set_num_compressed_texture_formats(
2427 validators_
->compressed_texture_format
.GetValues().size());
2429 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2430 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2431 // OpenGL ES 2.0 does not have this issue.
2432 glEnableVertexAttribArray(0);
2434 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2435 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2436 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2437 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2438 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2440 state_
.texture_units
.resize(group_
->max_texture_units());
2441 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2442 glActiveTexture(GL_TEXTURE0
+ tt
);
2443 // We want the last bind to be 2D.
2445 if (features().oes_egl_image_external
) {
2446 ref
= texture_manager()->GetDefaultTextureInfo(
2447 GL_TEXTURE_EXTERNAL_OES
);
2448 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2449 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2451 if (features().arb_texture_rectangle
) {
2452 ref
= texture_manager()->GetDefaultTextureInfo(
2453 GL_TEXTURE_RECTANGLE_ARB
);
2454 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2455 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2457 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2458 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2459 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2460 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2461 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2462 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2464 glActiveTexture(GL_TEXTURE0
);
2468 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2469 features().chromium_framebuffer_multisample
) {
2470 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2471 // max_sample_count must be initialized to a sane value. If
2472 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2473 GLint max_sample_count
= 1;
2474 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2475 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2478 offscreen_target_samples_
= 1;
2480 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2482 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2483 const bool rgb8_supported
=
2484 context_
->HasExtension("GL_OES_rgb8_rgba8");
2485 // The only available default render buffer formats in GLES2 have very
2486 // little precision. Don't enable multisampling unless 8-bit render
2487 // buffer formats are available--instead fall back to 8-bit textures.
2488 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2489 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2492 offscreen_target_samples_
= 1;
2493 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2497 // ANGLE only supports packed depth/stencil formats, so use it if it is
2499 const bool depth24_stencil8_supported
=
2500 feature_info_
->feature_flags().packed_depth24_stencil8
;
2501 VLOG(1) << "GL_OES_packed_depth_stencil "
2502 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2503 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2504 depth24_stencil8_supported
) {
2505 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2506 offscreen_target_stencil_format_
= 0;
2508 // It may be the case that this depth/stencil combination is not
2509 // supported, but this will be checked later by CheckFramebufferStatus.
2510 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2511 GL_DEPTH_COMPONENT16
: 0;
2512 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2513 GL_STENCIL_INDEX8
: 0;
2516 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2519 // If depth is requested at all, use the packed depth stencil format if
2520 // it's available, as some desktop GL drivers don't support any non-packed
2521 // formats for depth attachments.
2522 const bool depth24_stencil8_supported
=
2523 feature_info_
->feature_flags().packed_depth24_stencil8
;
2524 VLOG(1) << "GL_EXT_packed_depth_stencil "
2525 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2527 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2528 depth24_stencil8_supported
) {
2529 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2530 offscreen_target_stencil_format_
= 0;
2532 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2533 GL_DEPTH_COMPONENT
: 0;
2534 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2535 GL_STENCIL_INDEX
: 0;
2539 offscreen_saved_color_format_
= attrib_parser
.alpha_size
> 0 ?
2542 // Create the target frame buffer. This is the one that the client renders
2544 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2545 offscreen_target_frame_buffer_
->Create();
2546 // Due to GLES2 format limitations, either the color texture (for
2547 // non-multisampling) or the color render buffer (for multisampling) will be
2548 // attached to the offscreen frame buffer. The render buffer has more
2549 // limited formats available to it, but the texture can't do multisampling.
2550 if (IsOffscreenBufferMultisampled()) {
2551 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2552 renderbuffer_manager(), memory_tracker(), &state_
));
2553 offscreen_target_color_render_buffer_
->Create();
2555 offscreen_target_color_texture_
.reset(new BackTexture(
2556 memory_tracker(), &state_
));
2557 offscreen_target_color_texture_
->Create();
2559 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2560 renderbuffer_manager(), memory_tracker(), &state_
));
2561 offscreen_target_depth_render_buffer_
->Create();
2562 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2563 renderbuffer_manager(), memory_tracker(), &state_
));
2564 offscreen_target_stencil_render_buffer_
->Create();
2566 // Create the saved offscreen texture. The target frame buffer is copied
2567 // here when SwapBuffers is called.
2568 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2569 offscreen_saved_frame_buffer_
->Create();
2571 offscreen_saved_color_texture_
.reset(new BackTexture(
2572 memory_tracker(), &state_
));
2573 offscreen_saved_color_texture_
->Create();
2575 // Allocate the render buffers at their initial size and check the status
2576 // of the frame buffers is okay.
2577 if (!ResizeOffscreenFrameBuffer(size
)) {
2578 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2583 // Allocate the offscreen saved color texture.
2584 DCHECK(offscreen_saved_color_format_
);
2585 offscreen_saved_color_texture_
->AllocateStorage(
2586 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2588 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2589 offscreen_saved_color_texture_
.get());
2590 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2591 GL_FRAMEBUFFER_COMPLETE
) {
2592 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2597 // Bind to the new default frame buffer (the offscreen target frame buffer).
2598 // This should now be associated with ID zero.
2599 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2601 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2602 // These are NOT if the back buffer has these proprorties. They are
2603 // if we want the command buffer to enforce them regardless of what
2604 // the real backbuffer is assuming the real back buffer gives us more than
2605 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2606 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2607 // can't do anything about that.
2610 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2611 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2612 // user requested RGB then RGB. If the user did not specify a preference
2613 // than use whatever we were given. Same for DEPTH and STENCIL.
2614 back_buffer_color_format_
=
2615 (attrib_parser
.alpha_size
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2616 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2617 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && v
> 0;
2618 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2619 back_buffer_has_stencil_
= attrib_parser
.stencil_size
!= 0 && v
> 0;
2622 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2623 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2624 // isn't well documented; it was discovered in the Khronos OpenGL ES
2625 // mailing list archives. It also implicitly enables the desktop GL
2626 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2627 // variable in fragment shaders.
2628 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2629 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2630 glEnable(GL_POINT_SPRITE
);
2633 has_robustness_extension_
=
2634 context
->HasExtension("GL_ARB_robustness") ||
2635 context
->HasExtension("GL_EXT_robustness");
2637 if (!InitializeShaderTranslator()) {
2641 state_
.viewport_width
= size
.width();
2642 state_
.viewport_height
= size
.height();
2644 GLint viewport_params
[4] = { 0 };
2645 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2646 viewport_max_width_
= viewport_params
[0];
2647 viewport_max_height_
= viewport_params
[1];
2649 state_
.scissor_width
= state_
.viewport_width
;
2650 state_
.scissor_height
= state_
.viewport_height
;
2652 // Set all the default state because some GL drivers get it wrong.
2653 state_
.InitCapabilities(NULL
);
2654 state_
.InitState(NULL
);
2655 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2657 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2658 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2659 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2660 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2662 bool call_gl_clear
= true;
2663 #if defined(OS_ANDROID)
2664 // Temporary workaround for Android WebView because this clear ignores the
2665 // clip and corrupts that external UI of the App. Not calling glClear is ok
2666 // because the system already clears the buffer before each draw. Proper
2667 // fix might be setting the scissor clip properly before initialize. See
2668 // crbug.com/259023 for details.
2669 call_gl_clear
= surface_
->GetHandle();
2671 if (call_gl_clear
) {
2672 // Clear the backbuffer.
2673 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2676 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2677 if (feature_info_
->workarounds()
2678 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2679 !surface
->IsOffscreen())
2680 supports_post_sub_buffer_
= false;
2682 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2683 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2686 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2687 context_
->SetUnbindFboOnMakeCurrent();
2690 // Only compositor contexts are known to use only the subset of GL
2691 // that can be safely migrated between the iGPU and the dGPU. Mark
2692 // those contexts as safe to forcibly transition between the GPUs.
2693 // http://crbug.com/180876, http://crbug.com/227228
2695 context_
->SetSafeToForceGpuSwitch();
2697 async_pixel_transfer_manager_
.reset(
2698 AsyncPixelTransferManager::Create(context
.get()));
2699 async_pixel_transfer_manager_
->Initialize(texture_manager());
2701 framebuffer_manager()->AddObserver(this);
2706 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2707 DCHECK(initialized());
2711 caps
.egl_image_external
=
2712 feature_info_
->feature_flags().oes_egl_image_external
;
2713 caps
.texture_format_bgra8888
=
2714 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2715 caps
.texture_format_etc1
=
2716 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2717 caps
.texture_format_etc1_npot
=
2718 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2719 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2720 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2721 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2722 caps
.discard_framebuffer
=
2723 feature_info_
->feature_flags().ext_discard_framebuffer
;
2724 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2726 #if defined(OS_MACOSX)
2727 // This is unconditionally true on mac, no need to test for it at runtime.
2728 caps
.iosurface
= true;
2731 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2732 caps
.map_image
= true;
2737 void GLES2DecoderImpl::UpdateCapabilities() {
2738 util_
.set_num_compressed_texture_formats(
2739 validators_
->compressed_texture_format
.GetValues().size());
2740 util_
.set_num_shader_binary_formats(
2741 validators_
->shader_binary_format
.GetValues().size());
2744 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2745 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2747 if (!use_shader_translator_
) {
2750 ShBuiltInResources resources
;
2751 ShInitBuiltInResources(&resources
);
2752 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2753 resources
.MaxVertexUniformVectors
=
2754 group_
->max_vertex_uniform_vectors();
2755 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2756 resources
.MaxVertexTextureImageUnits
=
2757 group_
->max_vertex_texture_image_units();
2758 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2759 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2760 resources
.MaxFragmentUniformVectors
=
2761 group_
->max_fragment_uniform_vectors();
2762 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2763 resources
.MaxExpressionComplexity
= 256;
2764 resources
.MaxCallStackDepth
= 256;
2766 #if (ANGLE_SH_VERSION >= 110)
2767 GLint range
[2] = { 0, 0 };
2768 GLint precision
= 0;
2769 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2771 resources
.FragmentPrecisionHigh
=
2772 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2775 if (force_webgl_glsl_validation_
) {
2776 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2777 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2778 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2779 if (!draw_buffers_explicitly_enabled_
)
2780 resources
.MaxDrawBuffers
= 1;
2781 #if (ANGLE_SH_VERSION >= 123)
2782 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2785 resources
.OES_standard_derivatives
=
2786 features().oes_standard_derivatives
? 1 : 0;
2787 resources
.ARB_texture_rectangle
=
2788 features().arb_texture_rectangle
? 1 : 0;
2789 resources
.OES_EGL_image_external
=
2790 features().oes_egl_image_external
? 1 : 0;
2791 resources
.EXT_draw_buffers
=
2792 features().ext_draw_buffers
? 1 : 0;
2793 resources
.EXT_frag_depth
=
2794 features().ext_frag_depth
? 1 : 0;
2795 #if (ANGLE_SH_VERSION >= 123)
2796 resources
.EXT_shader_texture_lod
=
2797 features().ext_shader_texture_lod
? 1 : 0;
2801 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2803 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2804 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2805 resources
.HashFunction
= &CityHashForAngle
;
2807 resources
.HashFunction
= &CityHash64
;
2810 resources
.HashFunction
= NULL
;
2811 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2812 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2813 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2814 int driver_bug_workarounds
= 0;
2815 if (workarounds().needs_glsl_built_in_function_emulation
)
2816 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2817 if (workarounds().init_gl_position_in_vertex_shader
)
2818 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2819 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2820 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2821 if (workarounds().init_varyings_without_static_use
)
2822 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2823 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2824 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2825 if (workarounds().scalarize_vec_and_mat_constructor_args
)
2826 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
2827 if (workarounds().regenerate_struct_names
)
2828 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
2830 vertex_translator_
= shader_translator_cache()->GetTranslator(
2831 #if (ANGLE_SH_VERSION >= 126)
2838 implementation_type
,
2839 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2840 if (!vertex_translator_
.get()) {
2841 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2846 fragment_translator_
= shader_translator_cache()->GetTranslator(
2847 #if (ANGLE_SH_VERSION >= 126)
2854 implementation_type
,
2855 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2856 if (!fragment_translator_
.get()) {
2857 LOG(ERROR
) << "Could not initialize fragment shader translator.";
2864 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
2865 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2866 if (GetBuffer(client_ids
[ii
])) {
2870 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2871 glGenBuffersARB(n
, service_ids
.get());
2872 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2873 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
2878 bool GLES2DecoderImpl::GenFramebuffersHelper(
2879 GLsizei n
, const GLuint
* client_ids
) {
2880 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2881 if (GetFramebuffer(client_ids
[ii
])) {
2885 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2886 glGenFramebuffersEXT(n
, service_ids
.get());
2887 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2888 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
2893 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2894 GLsizei n
, const GLuint
* client_ids
) {
2895 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2896 if (GetRenderbuffer(client_ids
[ii
])) {
2900 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2901 glGenRenderbuffersEXT(n
, service_ids
.get());
2902 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2903 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
2908 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
2909 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2910 if (GetTexture(client_ids
[ii
])) {
2914 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2915 glGenTextures(n
, service_ids
.get());
2916 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2917 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
2922 void GLES2DecoderImpl::DeleteBuffersHelper(
2923 GLsizei n
, const GLuint
* client_ids
) {
2924 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2925 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
2926 if (buffer
&& !buffer
->IsDeleted()) {
2927 state_
.vertex_attrib_manager
->Unbind(buffer
);
2928 if (state_
.bound_array_buffer
.get() == buffer
) {
2929 state_
.bound_array_buffer
= NULL
;
2931 RemoveBuffer(client_ids
[ii
]);
2936 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2937 GLsizei n
, const GLuint
* client_ids
) {
2938 bool supports_separate_framebuffer_binds
=
2939 features().chromium_framebuffer_multisample
;
2941 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2942 Framebuffer
* framebuffer
=
2943 GetFramebuffer(client_ids
[ii
]);
2944 if (framebuffer
&& !framebuffer
->IsDeleted()) {
2945 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
2946 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
2947 framebuffer_state_
.clear_state_dirty
= true;
2948 GLenum target
= supports_separate_framebuffer_binds
?
2949 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2950 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2952 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
2953 framebuffer_state_
.bound_read_framebuffer
= NULL
;
2954 GLenum target
= supports_separate_framebuffer_binds
?
2955 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2956 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2959 RemoveFramebuffer(client_ids
[ii
]);
2964 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2965 GLsizei n
, const GLuint
* client_ids
) {
2966 bool supports_separate_framebuffer_binds
=
2967 features().chromium_framebuffer_multisample
;
2968 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2969 Renderbuffer
* renderbuffer
=
2970 GetRenderbuffer(client_ids
[ii
]);
2971 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
2972 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
2973 state_
.bound_renderbuffer
= NULL
;
2975 // Unbind from current framebuffers.
2976 if (supports_separate_framebuffer_binds
) {
2977 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2978 framebuffer_state_
.bound_read_framebuffer
2979 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
2981 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2982 framebuffer_state_
.bound_draw_framebuffer
2983 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
2986 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2987 framebuffer_state_
.bound_draw_framebuffer
2988 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
2991 framebuffer_state_
.clear_state_dirty
= true;
2992 RemoveRenderbuffer(client_ids
[ii
]);
2997 void GLES2DecoderImpl::DeleteTexturesHelper(
2998 GLsizei n
, const GLuint
* client_ids
) {
2999 bool supports_separate_framebuffer_binds
=
3000 features().chromium_framebuffer_multisample
;
3001 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3002 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3004 Texture
* texture
= texture_ref
->texture();
3005 if (texture
->IsAttachedToFramebuffer()) {
3006 framebuffer_state_
.clear_state_dirty
= true;
3008 // Unbind texture_ref from texture_ref units.
3009 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3010 state_
.texture_units
[jj
].Unbind(texture_ref
);
3012 // Unbind from current framebuffers.
3013 if (supports_separate_framebuffer_binds
) {
3014 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3015 framebuffer_state_
.bound_read_framebuffer
3016 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3018 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3019 framebuffer_state_
.bound_draw_framebuffer
3020 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3023 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3024 framebuffer_state_
.bound_draw_framebuffer
3025 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3028 #if defined(OS_MACOSX)
3029 GLuint service_id
= texture
->service_id();
3030 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3031 ReleaseIOSurfaceForTexture(service_id
);
3034 RemoveTexture(client_ids
[ii
]);
3039 // } // anonymous namespace
3041 bool GLES2DecoderImpl::MakeCurrent() {
3042 if (!context_
.get())
3045 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3046 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3048 // Some D3D drivers cannot recover from device lost in the GPU process
3049 // sandbox. Allow a new GPU process to launch.
3050 if (workarounds().exit_on_context_lost
) {
3051 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
3052 << " a D3D device in the Chrome GPU process sandbox.";
3054 base::win::SetShouldCrashOnProcessDetach(false);
3062 ProcessFinishedAsyncTransfers();
3064 // Rebind the FBO if it was unbound by the context.
3065 if (workarounds().unbind_fbo_on_context_switch
)
3066 RestoreFramebufferBindings();
3068 framebuffer_state_
.clear_state_dirty
= true;
3073 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3074 ProcessPendingReadPixels();
3075 if (engine() && query_manager_
.get())
3076 query_manager_
->ProcessPendingTransferQueries();
3078 // TODO(epenner): Is there a better place to do this?
3079 // This needs to occur before we execute any batch of commands
3080 // from the client, as the client may have recieved an async
3081 // completion while issuing those commands.
3082 // "DidFlushStart" would be ideal if we had such a callback.
3083 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3086 static void RebindCurrentFramebuffer(
3088 Framebuffer
* framebuffer
,
3089 GLuint back_buffer_service_id
) {
3090 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3092 if (framebuffer_id
== 0) {
3093 framebuffer_id
= back_buffer_service_id
;
3096 glBindFramebufferEXT(target
, framebuffer_id
);
3099 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3100 framebuffer_state_
.clear_state_dirty
= true;
3102 if (!features().chromium_framebuffer_multisample
) {
3103 RebindCurrentFramebuffer(
3105 framebuffer_state_
.bound_draw_framebuffer
.get(),
3106 GetBackbufferServiceId());
3108 RebindCurrentFramebuffer(
3109 GL_READ_FRAMEBUFFER_EXT
,
3110 framebuffer_state_
.bound_read_framebuffer
.get(),
3111 GetBackbufferServiceId());
3112 RebindCurrentFramebuffer(
3113 GL_DRAW_FRAMEBUFFER_EXT
,
3114 framebuffer_state_
.bound_draw_framebuffer
.get(),
3115 GetBackbufferServiceId());
3120 bool GLES2DecoderImpl::CheckFramebufferValid(
3121 Framebuffer
* framebuffer
,
3122 GLenum target
, const char* func_name
) {
3124 if (backbuffer_needs_clear_bits_
) {
3125 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3126 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3127 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3129 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3130 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3132 state_
.SetDeviceDepthMask(GL_TRUE
);
3133 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3134 bool reset_draw_buffer
= false;
3135 if ((backbuffer_needs_clear_bits_
| GL_COLOR_BUFFER_BIT
) != 0 &&
3136 group_
->draw_buffer() == GL_NONE
) {
3137 reset_draw_buffer
= true;
3138 GLenum buf
= GL_BACK
;
3139 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3140 buf
= GL_COLOR_ATTACHMENT0
;
3141 glDrawBuffersARB(1, &buf
);
3143 glClear(backbuffer_needs_clear_bits_
);
3144 if (reset_draw_buffer
) {
3145 GLenum buf
= GL_NONE
;
3146 glDrawBuffersARB(1, &buf
);
3148 backbuffer_needs_clear_bits_
= 0;
3149 RestoreClearState();
3154 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3158 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3159 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3161 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3165 // Are all the attachments cleared?
3166 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3167 texture_manager()->HaveUnclearedMips()) {
3168 if (!framebuffer
->IsCleared()) {
3169 // Can we clear them?
3170 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3171 GL_FRAMEBUFFER_COMPLETE
) {
3173 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3174 "framebuffer incomplete (clear)");
3177 ClearUnclearedAttachments(target
, framebuffer
);
3181 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3182 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3183 GL_FRAMEBUFFER_COMPLETE
) {
3185 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3186 "framebuffer incomplete (check)");
3189 framebuffer_manager()->MarkAsComplete(framebuffer
);
3192 // NOTE: At this point we don't know if the framebuffer is complete but
3193 // we DO know that everything that needs to be cleared has been cleared.
3197 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3198 if (!features().chromium_framebuffer_multisample
) {
3199 bool valid
= CheckFramebufferValid(
3200 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3208 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3209 GL_DRAW_FRAMEBUFFER_EXT
,
3211 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3212 GL_READ_FRAMEBUFFER_EXT
,
3216 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3217 const char* func_name
) {
3218 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3219 framebuffer_state_
.bound_read_framebuffer
.get() :
3220 framebuffer_state_
.bound_draw_framebuffer
.get();
3223 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3225 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3231 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3232 Framebuffer
* framebuffer
=
3233 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3234 if (framebuffer
!= NULL
) {
3235 const Framebuffer::Attachment
* attachment
=
3236 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3238 return gfx::Size(attachment
->width(), attachment
->height());
3240 return gfx::Size(0, 0);
3241 } else if (offscreen_target_frame_buffer_
.get()) {
3242 return offscreen_size_
;
3244 return surface_
->GetSize();
3248 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3249 Framebuffer
* framebuffer
=
3250 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3251 if (framebuffer
!= NULL
) {
3252 return framebuffer
->GetColorAttachmentTextureType();
3254 return GL_UNSIGNED_BYTE
;
3258 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3259 Framebuffer
* framebuffer
=
3260 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3261 if (framebuffer
!= NULL
) {
3262 return framebuffer
->GetColorAttachmentFormat();
3263 } else if (offscreen_target_frame_buffer_
.get()) {
3264 return offscreen_target_color_format_
;
3266 return back_buffer_color_format_
;
3270 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3271 Framebuffer
* framebuffer
=
3272 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3273 if (framebuffer
!= NULL
) {
3274 return framebuffer
->GetColorAttachmentFormat();
3275 } else if (offscreen_target_frame_buffer_
.get()) {
3276 return offscreen_target_color_format_
;
3278 return back_buffer_color_format_
;
3282 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3283 if (!offscreen_saved_color_texture_info_
.get())
3285 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3286 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3287 texture_manager()->SetLevelInfo(
3288 offscreen_saved_color_texture_info_
.get(),
3292 offscreen_size_
.width(),
3293 offscreen_size_
.height(),
3299 texture_manager()->SetParameteri(
3300 "UpdateParentTextureInfo",
3302 offscreen_saved_color_texture_info_
.get(),
3303 GL_TEXTURE_MAG_FILTER
,
3305 texture_manager()->SetParameteri(
3306 "UpdateParentTextureInfo",
3308 offscreen_saved_color_texture_info_
.get(),
3309 GL_TEXTURE_MIN_FILTER
,
3311 texture_manager()->SetParameteri(
3312 "UpdateParentTextureInfo",
3314 offscreen_saved_color_texture_info_
.get(),
3317 texture_manager()->SetParameteri(
3318 "UpdateParentTextureInfo",
3320 offscreen_saved_color_texture_info_
.get(),
3323 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3325 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3328 void GLES2DecoderImpl::SetResizeCallback(
3329 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3330 resize_callback_
= callback
;
3333 Logger
* GLES2DecoderImpl::GetLogger() {
3337 void GLES2DecoderImpl::BeginDecoding() {
3338 gpu_tracer_
->BeginDecoding();
3339 gpu_trace_commands_
= gpu_tracer_
->IsTracing();
3342 void GLES2DecoderImpl::EndDecoding() {
3343 gpu_tracer_
->EndDecoding();
3346 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3347 return state_
.GetErrorState();
3350 void GLES2DecoderImpl::SetShaderCacheCallback(
3351 const ShaderCacheCallback
& callback
) {
3352 shader_cache_callback_
= callback
;
3355 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3356 const WaitSyncPointCallback
& callback
) {
3357 wait_sync_point_callback_
= callback
;
3360 AsyncPixelTransferManager
*
3361 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3362 return async_pixel_transfer_manager_
.get();
3365 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3366 async_pixel_transfer_manager_
.reset();
3369 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3370 AsyncPixelTransferManager
* manager
) {
3371 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3374 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3375 uint32
* service_texture_id
) {
3376 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3378 *service_texture_id
= texture_ref
->service_id();
3384 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3385 return texture_state_
.texture_upload_count
+
3386 async_pixel_transfer_manager_
->GetTextureUploadCount();
3389 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3390 return texture_state_
.total_texture_upload_time
+
3391 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3394 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3395 return total_processing_commands_time_
;
3398 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3399 total_processing_commands_time_
+= time
;
3402 void GLES2DecoderImpl::Destroy(bool have_context
) {
3406 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3408 // Unbind everything.
3409 state_
.vertex_attrib_manager
= NULL
;
3410 state_
.default_vertex_attrib_manager
= NULL
;
3411 state_
.texture_units
.clear();
3412 state_
.bound_array_buffer
= NULL
;
3413 state_
.current_queries
.clear();
3414 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3415 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3416 state_
.bound_renderbuffer
= NULL
;
3418 if (offscreen_saved_color_texture_info_
.get()) {
3419 DCHECK(offscreen_target_color_texture_
);
3420 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3421 offscreen_saved_color_texture_
->id());
3422 offscreen_saved_color_texture_
->Invalidate();
3423 offscreen_saved_color_texture_info_
= NULL
;
3426 if (copy_texture_CHROMIUM_
.get()) {
3427 copy_texture_CHROMIUM_
->Destroy();
3428 copy_texture_CHROMIUM_
.reset();
3431 if (state_
.current_program
.get()) {
3432 program_manager()->UnuseProgram(shader_manager(),
3433 state_
.current_program
.get());
3436 if (attrib_0_buffer_id_
) {
3437 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3439 if (fixed_attrib_buffer_id_
) {
3440 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3443 if (validation_texture_
) {
3444 glDeleteTextures(1, &validation_texture_
);
3445 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3446 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3449 if (offscreen_target_frame_buffer_
.get())
3450 offscreen_target_frame_buffer_
->Destroy();
3451 if (offscreen_target_color_texture_
.get())
3452 offscreen_target_color_texture_
->Destroy();
3453 if (offscreen_target_color_render_buffer_
.get())
3454 offscreen_target_color_render_buffer_
->Destroy();
3455 if (offscreen_target_depth_render_buffer_
.get())
3456 offscreen_target_depth_render_buffer_
->Destroy();
3457 if (offscreen_target_stencil_render_buffer_
.get())
3458 offscreen_target_stencil_render_buffer_
->Destroy();
3459 if (offscreen_saved_frame_buffer_
.get())
3460 offscreen_saved_frame_buffer_
->Destroy();
3461 if (offscreen_saved_color_texture_
.get())
3462 offscreen_saved_color_texture_
->Destroy();
3463 if (offscreen_resolved_frame_buffer_
.get())
3464 offscreen_resolved_frame_buffer_
->Destroy();
3465 if (offscreen_resolved_color_texture_
.get())
3466 offscreen_resolved_color_texture_
->Destroy();
3468 if (offscreen_target_frame_buffer_
.get())
3469 offscreen_target_frame_buffer_
->Invalidate();
3470 if (offscreen_target_color_texture_
.get())
3471 offscreen_target_color_texture_
->Invalidate();
3472 if (offscreen_target_color_render_buffer_
.get())
3473 offscreen_target_color_render_buffer_
->Invalidate();
3474 if (offscreen_target_depth_render_buffer_
.get())
3475 offscreen_target_depth_render_buffer_
->Invalidate();
3476 if (offscreen_target_stencil_render_buffer_
.get())
3477 offscreen_target_stencil_render_buffer_
->Invalidate();
3478 if (offscreen_saved_frame_buffer_
.get())
3479 offscreen_saved_frame_buffer_
->Invalidate();
3480 if (offscreen_saved_color_texture_
.get())
3481 offscreen_saved_color_texture_
->Invalidate();
3482 if (offscreen_resolved_frame_buffer_
.get())
3483 offscreen_resolved_frame_buffer_
->Invalidate();
3484 if (offscreen_resolved_color_texture_
.get())
3485 offscreen_resolved_color_texture_
->Invalidate();
3488 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3489 // Otherwise, we can leak objects. http://crbug.com/258772.
3490 // state_.current_program must be reset before group_ is reset because
3491 // the later deletes the ProgramManager object that referred by
3492 // state_.current_program object.
3493 state_
.current_program
= NULL
;
3495 copy_texture_CHROMIUM_
.reset();
3497 if (query_manager_
.get()) {
3498 query_manager_
->Destroy(have_context
);
3499 query_manager_
.reset();
3502 if (vertex_array_manager_
.get()) {
3503 vertex_array_manager_
->Destroy(have_context
);
3504 vertex_array_manager_
.reset();
3507 if (image_manager_
.get()) {
3508 image_manager_
->Destroy(have_context
);
3509 image_manager_
.reset();
3512 offscreen_target_frame_buffer_
.reset();
3513 offscreen_target_color_texture_
.reset();
3514 offscreen_target_color_render_buffer_
.reset();
3515 offscreen_target_depth_render_buffer_
.reset();
3516 offscreen_target_stencil_render_buffer_
.reset();
3517 offscreen_saved_frame_buffer_
.reset();
3518 offscreen_saved_color_texture_
.reset();
3519 offscreen_resolved_frame_buffer_
.reset();
3520 offscreen_resolved_color_texture_
.reset();
3522 // Need to release these before releasing |group_| which may own the
3523 // ShaderTranslatorCache.
3524 fragment_translator_
= NULL
;
3525 vertex_translator_
= NULL
;
3527 // Should destroy the transfer manager before the texture manager held
3528 // by the context group.
3529 async_pixel_transfer_manager_
.reset();
3532 framebuffer_manager()->RemoveObserver(this);
3533 group_
->Destroy(this, have_context
);
3537 if (context_
.get()) {
3538 context_
->ReleaseCurrent(NULL
);
3542 #if defined(OS_MACOSX)
3543 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3544 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3545 CFRelease(it
->second
);
3547 texture_to_io_surface_map_
.clear();
3551 void GLES2DecoderImpl::SetSurface(
3552 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3553 DCHECK(context_
->IsCurrent(NULL
));
3554 DCHECK(surface_
.get());
3556 RestoreCurrentFramebufferBindings();
3559 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3560 if (!offscreen_saved_color_texture_
.get()) {
3561 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3564 if (!offscreen_saved_color_texture_info_
.get()) {
3565 GLuint service_id
= offscreen_saved_color_texture_
->id();
3566 offscreen_saved_color_texture_info_
= TextureRef::Create(
3567 texture_manager(), 0, service_id
);
3568 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3570 UpdateParentTextureInfo();
3572 mailbox_manager()->ProduceTexture(
3573 GL_TEXTURE_2D
, mailbox
, offscreen_saved_color_texture_info_
->texture());
3576 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3577 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3578 if (!is_offscreen
) {
3579 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3580 << " with an onscreen framebuffer.";
3584 if (offscreen_size_
== size
)
3587 offscreen_size_
= size
;
3588 int w
= offscreen_size_
.width();
3589 int h
= offscreen_size_
.height();
3590 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3591 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3592 << "to allocate storage due to excessive dimensions.";
3596 // Reallocate the offscreen target buffers.
3597 DCHECK(offscreen_target_color_format_
);
3598 if (IsOffscreenBufferMultisampled()) {
3599 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3600 feature_info_
.get(),
3602 offscreen_target_color_format_
,
3603 offscreen_target_samples_
)) {
3604 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3605 << "to allocate storage for offscreen target color buffer.";
3609 if (!offscreen_target_color_texture_
->AllocateStorage(
3610 offscreen_size_
, offscreen_target_color_format_
, false)) {
3611 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3612 << "to allocate storage for offscreen target color texture.";
3616 if (offscreen_target_depth_format_
&&
3617 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3618 feature_info_
.get(),
3620 offscreen_target_depth_format_
,
3621 offscreen_target_samples_
)) {
3622 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3623 << "to allocate storage for offscreen target depth buffer.";
3626 if (offscreen_target_stencil_format_
&&
3627 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3628 feature_info_
.get(),
3630 offscreen_target_stencil_format_
,
3631 offscreen_target_samples_
)) {
3632 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3633 << "to allocate storage for offscreen target stencil buffer.";
3637 // Attach the offscreen target buffers to the target frame buffer.
3638 if (IsOffscreenBufferMultisampled()) {
3639 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3640 GL_COLOR_ATTACHMENT0
,
3641 offscreen_target_color_render_buffer_
.get());
3643 offscreen_target_frame_buffer_
->AttachRenderTexture(
3644 offscreen_target_color_texture_
.get());
3646 if (offscreen_target_depth_format_
) {
3647 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3648 GL_DEPTH_ATTACHMENT
,
3649 offscreen_target_depth_render_buffer_
.get());
3651 const bool packed_depth_stencil
=
3652 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3653 if (packed_depth_stencil
) {
3654 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3655 GL_STENCIL_ATTACHMENT
,
3656 offscreen_target_depth_render_buffer_
.get());
3657 } else if (offscreen_target_stencil_format_
) {
3658 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3659 GL_STENCIL_ATTACHMENT
,
3660 offscreen_target_stencil_render_buffer_
.get());
3663 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3664 GL_FRAMEBUFFER_COMPLETE
) {
3665 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3666 << "because offscreen FBO was incomplete.";
3670 // Clear the target frame buffer.
3672 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3673 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3674 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3675 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3677 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3678 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3680 state_
.SetDeviceDepthMask(GL_TRUE
);
3681 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3682 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3683 RestoreClearState();
3686 // Destroy the offscreen resolved framebuffers.
3687 if (offscreen_resolved_frame_buffer_
.get())
3688 offscreen_resolved_frame_buffer_
->Destroy();
3689 if (offscreen_resolved_color_texture_
.get())
3690 offscreen_resolved_color_texture_
->Destroy();
3691 offscreen_resolved_color_texture_
.reset();
3692 offscreen_resolved_frame_buffer_
.reset();
3697 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(
3698 uint32 immediate_data_size
, const cmds::ResizeCHROMIUM
& c
) {
3699 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3700 return error::kDeferCommandUntilLater
;
3702 GLuint width
= static_cast<GLuint
>(c
.width
);
3703 GLuint height
= static_cast<GLuint
>(c
.height
);
3704 GLfloat scale_factor
= c
.scale_factor
;
3705 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3707 width
= std::max(1U, width
);
3708 height
= std::max(1U, height
);
3710 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3711 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3712 // Make sure that we are done drawing to the back buffer before resizing.
3715 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3717 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3718 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3719 << "ResizeOffscreenFrameBuffer failed.";
3720 return error::kLostContext
;
3724 if (!resize_callback_
.is_null()) {
3725 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3726 DCHECK(context_
->IsCurrent(surface_
.get()));
3727 if (!context_
->IsCurrent(surface_
.get())) {
3728 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3729 << "current after resize callback.";
3730 return error::kLostContext
;
3734 return error::kNoError
;
3737 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3738 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3739 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3741 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3744 // Decode command with its arguments, and call the corresponding GL function.
3745 // Note: args is a pointer to the command buffer. As such, it could be changed
3746 // by a (malicious) client at any time, so if validation has to happen, it
3747 // should operate on a copy of them.
3748 error::Error
GLES2DecoderImpl::DoCommand(
3749 unsigned int command
,
3750 unsigned int arg_count
,
3751 const void* cmd_data
) {
3752 error::Error result
= error::kNoError
;
3753 if (log_commands()) {
3754 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3755 // VLOG(1), no luck.
3756 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]" << "cmd: "
3757 << GetCommandName(command
);
3759 unsigned int command_index
= command
- kStartPoint
- 1;
3760 if (command_index
< arraysize(g_command_info
)) {
3761 const CommandInfo
& info
= g_command_info
[command_index
];
3762 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3763 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3764 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3765 bool doing_gpu_trace
= false;
3766 if (gpu_trace_commands_
) {
3767 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
3768 doing_gpu_trace
= true;
3769 gpu_tracer_
->Begin(GetCommandName(command
), kTraceDecoder
);
3773 uint32 immediate_data_size
=
3774 (arg_count
- info_arg_count
) * sizeof(CommandBufferEntry
); // NOLINT
3776 #define GLES2_CMD_OP(name) \
3777 case cmds::name::kCmdId: \
3778 result = Handle ## name( \
3779 immediate_data_size, \
3780 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3783 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3787 if (doing_gpu_trace
)
3788 gpu_tracer_
->End(kTraceDecoder
);
3792 while ((error
= glGetError()) != GL_NO_ERROR
) {
3793 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
3794 << "GL ERROR: " << GLES2Util::GetStringEnum(error
) << " : "
3795 << GetCommandName(command
);
3796 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
3800 result
= error::kInvalidArguments
;
3803 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
3805 if (result
== error::kNoError
&& current_decoder_error_
!= error::kNoError
) {
3806 result
= current_decoder_error_
;
3807 current_decoder_error_
= error::kNoError
;
3812 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
3813 buffer_manager()->RemoveBuffer(client_id
);
3816 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id
) {
3817 if (GetProgram(client_id
)) {
3820 GLuint service_id
= glCreateProgram();
3821 if (service_id
!= 0) {
3822 CreateProgram(client_id
, service_id
);
3827 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type
, GLuint client_id
) {
3828 if (GetShader(client_id
)) {
3831 GLuint service_id
= glCreateShader(type
);
3832 if (service_id
!= 0) {
3833 CreateShader(client_id
, service_id
, type
);
3838 void GLES2DecoderImpl::DoFinish() {
3840 ProcessPendingReadPixels();
3841 ProcessPendingQueries();
3844 void GLES2DecoderImpl::DoFlush() {
3846 ProcessPendingQueries();
3849 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
3850 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
3851 if (texture_index
>= state_
.texture_units
.size()) {
3852 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3853 "glActiveTexture", texture_unit
, "texture_unit");
3856 state_
.active_texture_unit
= texture_index
;
3857 glActiveTexture(texture_unit
);
3860 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
3861 Buffer
* buffer
= NULL
;
3862 GLuint service_id
= 0;
3863 if (client_id
!= 0) {
3864 buffer
= GetBuffer(client_id
);
3866 if (!group_
->bind_generates_resource()) {
3867 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
3869 "id not generated by glGenBuffers");
3873 // It's a new id so make a buffer buffer for it.
3874 glGenBuffersARB(1, &service_id
);
3875 CreateBuffer(client_id
, service_id
);
3876 buffer
= GetBuffer(client_id
);
3877 IdAllocatorInterface
* id_allocator
=
3878 group_
->GetIdAllocator(id_namespaces::kBuffers
);
3879 id_allocator
->MarkAsUsed(client_id
);
3882 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
3884 if (!buffer_manager()->SetTarget(buffer
, target
)) {
3886 GL_INVALID_OPERATION
,
3887 "glBindBuffer", "buffer bound to more than 1 target");
3890 service_id
= buffer
->service_id();
3893 case GL_ARRAY_BUFFER
:
3894 state_
.bound_array_buffer
= buffer
;
3896 case GL_ELEMENT_ARRAY_BUFFER
:
3897 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
3900 NOTREACHED(); // Validation should prevent us getting here.
3903 glBindBuffer(target
, service_id
);
3906 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3907 bool all_draw_buffers
) {
3908 Framebuffer
* framebuffer
=
3909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3910 if (!all_draw_buffers
|| !framebuffer
) {
3911 return (GLES2Util::GetChannelsForFormat(
3912 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3914 return framebuffer
->HasAlphaMRT();
3917 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3918 Framebuffer
* framebuffer
=
3919 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3921 return framebuffer
->HasDepthAttachment();
3923 if (offscreen_target_frame_buffer_
.get()) {
3924 return offscreen_target_depth_format_
!= 0;
3926 return back_buffer_has_depth_
;
3929 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3930 Framebuffer
* framebuffer
=
3931 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3933 return framebuffer
->HasStencilAttachment();
3935 if (offscreen_target_frame_buffer_
.get()) {
3936 return offscreen_target_stencil_format_
!= 0 ||
3937 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3939 return back_buffer_has_stencil_
;
3942 void GLES2DecoderImpl::ApplyDirtyState() {
3943 if (framebuffer_state_
.clear_state_dirty
) {
3944 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
3945 state_
.SetDeviceColorMask(state_
.color_mask_red
,
3946 state_
.color_mask_green
,
3947 state_
.color_mask_blue
,
3948 state_
.color_mask_alpha
&& have_alpha
);
3950 bool have_depth
= BoundFramebufferHasDepthAttachment();
3951 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
3953 bool have_stencil
= BoundFramebufferHasStencilAttachment();
3954 state_
.SetDeviceStencilMaskSeparate(
3955 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
3956 state_
.SetDeviceStencilMaskSeparate(
3957 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
3959 state_
.SetDeviceCapabilityState(
3960 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
3961 state_
.SetDeviceCapabilityState(
3962 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
3963 framebuffer_state_
.clear_state_dirty
= false;
3967 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
3968 return (offscreen_target_frame_buffer_
.get())
3969 ? offscreen_target_frame_buffer_
->id()
3970 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
3973 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
3974 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3975 "context", logger_
.GetLogPrefix());
3976 // Restore the Framebuffer first because of bugs in Intel drivers.
3977 // Intel drivers incorrectly clip the viewport settings to
3978 // the size of the current framebuffer object.
3979 RestoreFramebufferBindings();
3980 state_
.RestoreState(prev_state
);
3983 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3985 framebuffer_state_
.bound_draw_framebuffer
.get()
3986 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
3987 : GetBackbufferServiceId();
3988 if (!features().chromium_framebuffer_multisample
) {
3989 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
3991 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
3992 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
3993 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
3994 : GetBackbufferServiceId();
3995 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4000 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4001 state_
.RestoreRenderbufferBindings();
4004 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4005 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4007 GLenum target
= texture
->target();
4008 glBindTexture(target
, service_id
);
4010 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4012 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4014 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4016 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4017 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4021 void GLES2DecoderImpl::ClearAllAttributes() const {
4022 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4024 if (feature_info_
->feature_flags().native_vertex_array_object
)
4025 glBindVertexArrayOES(0);
4027 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4028 if (i
!= 0) // Never disable attribute 0
4029 glDisableVertexAttribArray(i
);
4030 if(features().angle_instanced_arrays
)
4031 glVertexAttribDivisorANGLE(i
, 0);
4035 void GLES2DecoderImpl::RestoreAllAttributes() const {
4036 state_
.RestoreVertexAttribs();
4039 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4040 state_
.SetIgnoreCachedStateForTest(ignore
);
4043 void GLES2DecoderImpl::OnFboChanged() const {
4044 if (workarounds().restore_scissor_on_fbo_change
)
4045 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
4048 // Called after the FBO is checked for completeness.
4049 void GLES2DecoderImpl::OnUseFramebuffer() const {
4050 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
4051 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
4052 // The driver forgets the correct scissor when modifying the FBO binding.
4053 glScissor(state_
.scissor_x
,
4055 state_
.scissor_width
,
4056 state_
.scissor_height
);
4058 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4059 // it's unclear how this bug works.
4064 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4065 Framebuffer
* framebuffer
= NULL
;
4066 GLuint service_id
= 0;
4067 if (client_id
!= 0) {
4068 framebuffer
= GetFramebuffer(client_id
);
4070 if (!group_
->bind_generates_resource()) {
4071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4072 "glBindFramebuffer",
4073 "id not generated by glGenFramebuffers");
4077 // It's a new id so make a framebuffer framebuffer for it.
4078 glGenFramebuffersEXT(1, &service_id
);
4079 CreateFramebuffer(client_id
, service_id
);
4080 framebuffer
= GetFramebuffer(client_id
);
4081 IdAllocatorInterface
* id_allocator
=
4082 group_
->GetIdAllocator(id_namespaces::kFramebuffers
);
4083 id_allocator
->MarkAsUsed(client_id
);
4085 service_id
= framebuffer
->service_id();
4087 framebuffer
->MarkAsValid();
4089 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4091 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4092 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4095 // vmiura: This looks like dup code
4096 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4097 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4100 framebuffer_state_
.clear_state_dirty
= true;
4102 // If we are rendering to the backbuffer get the FBO id for any simulated
4104 if (framebuffer
== NULL
) {
4105 service_id
= GetBackbufferServiceId();
4108 glBindFramebufferEXT(target
, service_id
);
4112 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4113 Renderbuffer
* renderbuffer
= NULL
;
4114 GLuint service_id
= 0;
4115 if (client_id
!= 0) {
4116 renderbuffer
= GetRenderbuffer(client_id
);
4117 if (!renderbuffer
) {
4118 if (!group_
->bind_generates_resource()) {
4119 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4120 "glBindRenderbuffer",
4121 "id not generated by glGenRenderbuffers");
4125 // It's a new id so make a renderbuffer for it.
4126 glGenRenderbuffersEXT(1, &service_id
);
4127 CreateRenderbuffer(client_id
, service_id
);
4128 renderbuffer
= GetRenderbuffer(client_id
);
4129 IdAllocatorInterface
* id_allocator
=
4130 group_
->GetIdAllocator(id_namespaces::kRenderbuffers
);
4131 id_allocator
->MarkAsUsed(client_id
);
4133 service_id
= renderbuffer
->service_id();
4135 renderbuffer
->MarkAsValid();
4137 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4138 state_
.bound_renderbuffer
= renderbuffer
;
4139 state_
.bound_renderbuffer_valid
= true;
4140 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4143 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4144 TextureRef
* texture_ref
= NULL
;
4145 GLuint service_id
= 0;
4146 if (client_id
!= 0) {
4147 texture_ref
= GetTexture(client_id
);
4149 if (!group_
->bind_generates_resource()) {
4150 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4152 "id not generated by glGenTextures");
4156 // It's a new id so make a texture texture for it.
4157 glGenTextures(1, &service_id
);
4158 DCHECK_NE(0u, service_id
);
4159 CreateTexture(client_id
, service_id
);
4160 texture_ref
= GetTexture(client_id
);
4161 IdAllocatorInterface
* id_allocator
=
4162 group_
->GetIdAllocator(id_namespaces::kTextures
);
4163 id_allocator
->MarkAsUsed(client_id
);
4166 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4169 // Check the texture exists
4171 Texture
* texture
= texture_ref
->texture();
4172 // Check that we are not trying to bind it to a different target.
4173 if (texture
->target() != 0 && texture
->target() != target
) {
4174 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4176 "texture bound to more than 1 target.");
4179 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4180 if (texture
->target() == 0) {
4181 texture_manager()->SetTarget(texture_ref
, target
);
4183 glBindTexture(target
, texture
->service_id());
4185 glBindTexture(target
, 0);
4188 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4189 unit
.bind_target
= target
;
4192 unit
.bound_texture_2d
= texture_ref
;
4194 case GL_TEXTURE_CUBE_MAP
:
4195 unit
.bound_texture_cube_map
= texture_ref
;
4197 case GL_TEXTURE_EXTERNAL_OES
:
4198 unit
.bound_texture_external_oes
= texture_ref
;
4200 case GL_TEXTURE_RECTANGLE_ARB
:
4201 unit
.bound_texture_rectangle_arb
= texture_ref
;
4204 NOTREACHED(); // Validation should prevent us getting here.
4209 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4210 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4212 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4213 glDisableVertexAttribArray(index
);
4218 "glDisableVertexAttribArray", "index out of range");
4222 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4223 GLsizei numAttachments
,
4224 const GLenum
* attachments
) {
4225 Framebuffer
* framebuffer
=
4226 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4228 // Validates the attachments. If one of them fails
4229 // the whole command fails.
4230 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4232 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4234 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4235 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4236 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4241 // Marks each one of them as not cleared
4242 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4244 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4249 switch (attachments
[i
]) {
4251 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4254 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4255 case GL_STENCIL_EXT
:
4256 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4265 // If the default framebuffer is bound but we are still rendering to an
4266 // FBO, translate attachment names that refer to default framebuffer
4267 // channels to corresponding framebuffer attachments.
4268 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4269 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4270 GLenum attachment
= attachments
[i
];
4271 if (!framebuffer
&& GetBackbufferServiceId()) {
4272 switch (attachment
) {
4274 attachment
= GL_COLOR_ATTACHMENT0
;
4277 attachment
= GL_DEPTH_ATTACHMENT
;
4279 case GL_STENCIL_EXT
:
4280 attachment
= GL_STENCIL_ATTACHMENT
;
4287 translated_attachments
[i
] = attachment
;
4290 glDiscardFramebufferEXT(target
, numAttachments
, translated_attachments
.get());
4293 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4294 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4295 glEnableVertexAttribArray(index
);
4298 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4302 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4303 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4306 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4308 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4312 if (target
== GL_TEXTURE_CUBE_MAP
) {
4313 for (int i
= 0; i
< 6; ++i
) {
4314 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4315 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4317 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4322 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4324 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4330 // Workaround for Mac driver bug. In the large scheme of things setting
4331 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4332 // hit so there's probably no need to make this conditional. The bug appears
4333 // to be that if the filtering mode is set to something that doesn't require
4334 // mipmaps for rendering, or is never set to something other than the default,
4335 // then glGenerateMipmap misbehaves.
4336 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4337 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4339 glGenerateMipmapEXT(target
);
4340 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4341 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4342 texture_ref
->texture()->min_filter());
4344 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4345 if (error
== GL_NO_ERROR
) {
4346 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4350 bool GLES2DecoderImpl::GetHelper(
4351 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4352 DCHECK(num_written
);
4353 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4355 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4357 // Return the GL implementation's preferred format and (see below type)
4358 // if we have the GL extension that exposes this. This allows the GPU
4359 // client to use the implementation's preferred format for glReadPixels
4360 // for optimisation.
4362 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4363 // case when requested on integer/floating point buffers but which is
4364 // acceptable on GLES2 and with the GL_OES_read_format extension.
4366 // Therefore if an error occurs we swallow the error and use the
4367 // internal implementation.
4369 if (context_
->HasExtension("GL_OES_read_format")) {
4370 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4372 glGetIntegerv(pname
, params
);
4373 if (glGetError() == GL_NO_ERROR
)
4376 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4377 GetBoundReadFrameBufferInternalFormat());
4380 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4383 if (context_
->HasExtension("GL_OES_read_format")) {
4384 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4386 glGetIntegerv(pname
, params
);
4387 if (glGetError() == GL_NO_ERROR
)
4390 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4391 GetBoundReadFrameBufferInternalFormat(),
4392 GetBoundReadFrameBufferTextureType());
4395 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4398 *params
= group_
->max_fragment_uniform_vectors();
4401 case GL_MAX_VARYING_VECTORS
:
4404 *params
= group_
->max_varying_vectors();
4407 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4410 *params
= group_
->max_vertex_uniform_vectors();
4416 case GL_MAX_VIEWPORT_DIMS
:
4417 if (offscreen_target_frame_buffer_
.get()) {
4420 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4421 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4426 case GL_MAX_SAMPLES
:
4429 params
[0] = renderbuffer_manager()->max_samples();
4432 case GL_MAX_RENDERBUFFER_SIZE
:
4435 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4438 case GL_MAX_TEXTURE_SIZE
:
4441 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4444 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4447 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4450 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4453 params
[0] = group_
->max_color_attachments();
4456 case GL_MAX_DRAW_BUFFERS_ARB
:
4459 params
[0] = group_
->max_draw_buffers();
4466 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4467 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4474 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4475 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4478 case GL_STENCIL_BITS
:
4482 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4483 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4486 case GL_COMPRESSED_TEXTURE_FORMATS
:
4487 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4489 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4490 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4494 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4497 *params
= validators_
->compressed_texture_format
.GetValues().size();
4500 case GL_NUM_SHADER_BINARY_FORMATS
:
4503 *params
= validators_
->shader_binary_format
.GetValues().size();
4506 case GL_SHADER_BINARY_FORMATS
:
4507 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4509 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4510 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4514 case GL_SHADER_COMPILER
:
4520 case GL_ARRAY_BUFFER_BINDING
:
4523 if (state_
.bound_array_buffer
.get()) {
4524 GLuint client_id
= 0;
4525 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4527 *params
= client_id
;
4533 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4536 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4537 GLuint client_id
= 0;
4538 buffer_manager()->GetClientId(
4539 state_
.vertex_attrib_manager
->element_array_buffer()->
4540 service_id(), &client_id
);
4541 *params
= client_id
;
4547 case GL_FRAMEBUFFER_BINDING
:
4548 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4551 Framebuffer
* framebuffer
=
4552 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4554 GLuint client_id
= 0;
4555 framebuffer_manager()->GetClientId(
4556 framebuffer
->service_id(), &client_id
);
4557 *params
= client_id
;
4563 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4566 Framebuffer
* framebuffer
=
4567 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4569 GLuint client_id
= 0;
4570 framebuffer_manager()->GetClientId(
4571 framebuffer
->service_id(), &client_id
);
4572 *params
= client_id
;
4578 case GL_RENDERBUFFER_BINDING
:
4581 Renderbuffer
* renderbuffer
=
4582 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4584 *params
= renderbuffer
->client_id();
4590 case GL_CURRENT_PROGRAM
:
4593 if (state_
.current_program
.get()) {
4594 GLuint client_id
= 0;
4595 program_manager()->GetClientId(
4596 state_
.current_program
->service_id(), &client_id
);
4597 *params
= client_id
;
4603 case GL_VERTEX_ARRAY_BINDING_OES
:
4606 if (state_
.vertex_attrib_manager
.get() !=
4607 state_
.default_vertex_attrib_manager
.get()) {
4608 GLuint client_id
= 0;
4609 vertex_array_manager_
->GetClientId(
4610 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4611 *params
= client_id
;
4617 case GL_TEXTURE_BINDING_2D
:
4620 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4621 if (unit
.bound_texture_2d
.get()) {
4622 *params
= unit
.bound_texture_2d
->client_id();
4628 case GL_TEXTURE_BINDING_CUBE_MAP
:
4631 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4632 if (unit
.bound_texture_cube_map
.get()) {
4633 *params
= unit
.bound_texture_cube_map
->client_id();
4639 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4642 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4643 if (unit
.bound_texture_external_oes
.get()) {
4644 *params
= unit
.bound_texture_external_oes
->client_id();
4650 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4653 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4654 if (unit
.bound_texture_rectangle_arb
.get()) {
4655 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4661 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4664 params
[0] = unpack_flip_y_
;
4667 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4670 params
[0] = unpack_premultiply_alpha_
;
4673 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4676 params
[0] = unpack_unpremultiply_alpha_
;
4679 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4682 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4686 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4687 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4690 Framebuffer
* framebuffer
=
4691 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4693 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4694 } else { // backbuffer
4695 if (pname
== GL_DRAW_BUFFER0_ARB
)
4696 params
[0] = group_
->draw_buffer();
4698 params
[0] = GL_NONE
;
4703 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4708 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4709 GLenum pname
, GLsizei
* num_values
) {
4710 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4713 return GetHelper(pname
, NULL
, num_values
);
4716 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4717 if (GL_MAX_SAMPLES
== pname
&&
4718 features().use_img_for_multisampled_render_to_texture
) {
4719 return GL_MAX_SAMPLES_IMG
;
4724 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4726 GLsizei num_written
= 0;
4727 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4728 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4729 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4730 GetHelper(pname
, values
.get(), &num_written
);
4732 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4733 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4736 pname
= AdjustGetPname(pname
);
4737 glGetBooleanv(pname
, params
);
4741 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4743 GLsizei num_written
= 0;
4744 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4745 if (GetHelper(pname
, NULL
, &num_written
)) {
4746 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4747 GetHelper(pname
, values
.get(), &num_written
);
4748 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4749 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4752 pname
= AdjustGetPname(pname
);
4753 glGetFloatv(pname
, params
);
4758 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4760 GLsizei num_written
;
4761 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4762 !GetHelper(pname
, params
, &num_written
)) {
4763 pname
= AdjustGetPname(pname
);
4764 glGetIntegerv(pname
, params
);
4768 void GLES2DecoderImpl::DoGetProgramiv(
4769 GLuint program_id
, GLenum pname
, GLint
* params
) {
4770 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
4774 program
->GetProgramiv(pname
, params
);
4777 void GLES2DecoderImpl::DoGetBufferParameteriv(
4778 GLenum target
, GLenum pname
, GLint
* params
) {
4779 // Just delegate it. Some validation is actually done before this.
4780 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4781 &state_
, target
, pname
, params
);
4784 void GLES2DecoderImpl::DoBindAttribLocation(
4785 GLuint program_id
, GLuint index
, const char* name
) {
4786 if (!StringIsValidForGLES(name
)) {
4788 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
4791 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4793 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
4796 if (index
>= group_
->max_vertex_attribs()) {
4798 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
4801 Program
* program
= GetProgramInfoNotShader(
4802 program_id
, "glBindAttribLocation");
4806 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
4807 glBindAttribLocation(program
->service_id(), index
, name
);
4810 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
4811 uint32 immediate_data_size
, const cmds::BindAttribLocationBucket
& c
) {
4812 GLuint program
= static_cast<GLuint
>(c
.program
);
4813 GLuint index
= static_cast<GLuint
>(c
.index
);
4814 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4815 if (!bucket
|| bucket
->size() == 0) {
4816 return error::kInvalidArguments
;
4818 std::string name_str
;
4819 if (!bucket
->GetAsString(&name_str
)) {
4820 return error::kInvalidArguments
;
4822 DoBindAttribLocation(program
, index
, name_str
.c_str());
4823 return error::kNoError
;
4826 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4827 GLuint program_id
, GLint location
, const char* name
) {
4828 if (!StringIsValidForGLES(name
)) {
4831 "glBindUniformLocationCHROMIUM", "Invalid character");
4834 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4836 GL_INVALID_OPERATION
,
4837 "glBindUniformLocationCHROMIUM", "reserved prefix");
4840 if (location
< 0 || static_cast<uint32
>(location
) >=
4841 (group_
->max_fragment_uniform_vectors() +
4842 group_
->max_vertex_uniform_vectors()) * 4) {
4845 "glBindUniformLocationCHROMIUM", "location out of range");
4848 Program
* program
= GetProgramInfoNotShader(
4849 program_id
, "glBindUniformLocationCHROMIUM");
4853 if (!program
->SetUniformLocationBinding(name
, location
)) {
4856 "glBindUniformLocationCHROMIUM", "location out of range");
4860 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4861 uint32 immediate_data_size
,
4862 const cmds::BindUniformLocationCHROMIUMBucket
& c
) {
4863 GLuint program
= static_cast<GLuint
>(c
.program
);
4864 GLint location
= static_cast<GLint
>(c
.location
);
4865 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4866 if (!bucket
|| bucket
->size() == 0) {
4867 return error::kInvalidArguments
;
4869 std::string name_str
;
4870 if (!bucket
->GetAsString(&name_str
)) {
4871 return error::kInvalidArguments
;
4873 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4874 return error::kNoError
;
4877 error::Error
GLES2DecoderImpl::HandleDeleteShader(
4878 uint32 immediate_data_size
, const cmds::DeleteShader
& c
) {
4879 GLuint client_id
= c
.shader
;
4881 Shader
* shader
= GetShader(client_id
);
4883 if (!shader
->IsDeleted()) {
4884 glDeleteShader(shader
->service_id());
4885 shader_manager()->MarkAsDeleted(shader
);
4888 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
4891 return error::kNoError
;
4894 error::Error
GLES2DecoderImpl::HandleDeleteProgram(
4895 uint32 immediate_data_size
, const cmds::DeleteProgram
& c
) {
4896 GLuint client_id
= c
.program
;
4898 Program
* program
= GetProgram(client_id
);
4900 if (!program
->IsDeleted()) {
4901 program_manager()->MarkAsDeleted(shader_manager(), program
);
4905 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
4908 return error::kNoError
;
4911 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4912 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4913 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4914 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4915 id_allocator
->FreeID(ids
[ii
]);
4919 error::Error
GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4920 uint32 immediate_data_size
, const cmds::DeleteSharedIdsCHROMIUM
& c
) {
4921 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4922 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4924 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4925 return error::kOutOfBounds
;
4927 const GLuint
* ids
= GetSharedMemoryAs
<const GLuint
*>(
4928 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4930 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "DeleteSharedIdsCHROMIUM", "n < 0");
4931 return error::kNoError
;
4934 return error::kOutOfBounds
;
4936 DoDeleteSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4937 return error::kNoError
;
4940 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4941 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
4942 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4943 if (id_offset
== 0) {
4944 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4945 ids
[ii
] = id_allocator
->AllocateID();
4948 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4949 ids
[ii
] = id_allocator
->AllocateIDAtOrAbove(id_offset
);
4950 id_offset
= ids
[ii
] + 1;
4955 error::Error
GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4956 uint32 immediate_data_size
, const cmds::GenSharedIdsCHROMIUM
& c
) {
4957 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4958 GLuint id_offset
= static_cast<GLuint
>(c
.id_offset
);
4959 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4961 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4962 return error::kOutOfBounds
;
4964 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4965 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4967 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "GenSharedIdsCHROMIUM", "n < 0");
4968 return error::kNoError
;
4971 return error::kOutOfBounds
;
4973 DoGenSharedIdsCHROMIUM(namespace_id
, id_offset
, n
, ids
);
4974 return error::kNoError
;
4977 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4978 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4979 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4980 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4981 if (!id_allocator
->MarkAsUsed(ids
[ii
])) {
4982 for (GLsizei jj
= 0; jj
< ii
; ++jj
) {
4983 id_allocator
->FreeID(ids
[jj
]);
4986 GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM",
4987 "attempt to register id that already exists");
4993 error::Error
GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4994 uint32 immediate_data_size
, const cmds::RegisterSharedIdsCHROMIUM
& c
) {
4995 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4996 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4998 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4999 return error::kOutOfBounds
;
5001 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
5002 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
5004 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM", "n < 0");
5005 return error::kNoError
;
5008 return error::kOutOfBounds
;
5010 DoRegisterSharedIdsCHROMIUM(namespace_id
, n
, ids
);
5011 return error::kNoError
;
5014 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5015 DCHECK(!ShouldDeferDraws());
5016 if (CheckBoundFramebuffersValid("glClear")) {
5020 return error::kNoError
;
5023 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5024 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5025 GLuint client_renderbuffer_id
) {
5026 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5029 GL_INVALID_OPERATION
,
5030 "glFramebufferRenderbuffer", "no framebuffer bound");
5033 GLuint service_id
= 0;
5034 Renderbuffer
* renderbuffer
= NULL
;
5035 if (client_renderbuffer_id
) {
5036 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5037 if (!renderbuffer
) {
5039 GL_INVALID_OPERATION
,
5040 "glFramebufferRenderbuffer", "unknown renderbuffer");
5043 service_id
= renderbuffer
->service_id();
5045 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5046 glFramebufferRenderbufferEXT(
5047 target
, attachment
, renderbuffertarget
, service_id
);
5048 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5049 if (error
== GL_NO_ERROR
) {
5050 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5052 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5053 framebuffer_state_
.clear_state_dirty
= true;
5058 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5059 if (SetCapabilityState(cap
, false)) {
5064 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5065 if (SetCapabilityState(cap
, true)) {
5070 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5071 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5072 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5073 glDepthRange(znear
, zfar
);
5076 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5077 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5078 state_
.sample_coverage_invert
= (invert
!= 0);
5079 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5082 // Assumes framebuffer is complete.
5083 void GLES2DecoderImpl::ClearUnclearedAttachments(
5084 GLenum target
, Framebuffer
* framebuffer
) {
5085 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5086 // bind this to the DRAW point, clear then bind back to READ
5087 // TODO(gman): I don't think there is any guarantee that an FBO that
5088 // is complete on the READ attachment will be complete as a DRAW
5090 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5091 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5093 GLbitfield clear_bits
= 0;
5094 if (framebuffer
->HasUnclearedColorAttachments()) {
5097 (GLES2Util::GetChannelsForFormat(
5098 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5100 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5101 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5102 if (feature_info_
->feature_flags().ext_draw_buffers
)
5103 framebuffer
->PrepareDrawBuffersForClear();
5106 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5107 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5109 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5110 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5111 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5114 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5115 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5117 state_
.SetDeviceDepthMask(GL_TRUE
);
5118 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5121 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5122 glClear(clear_bits
);
5124 if ((clear_bits
| GL_COLOR_BUFFER_BIT
) != 0 &&
5125 feature_info_
->feature_flags().ext_draw_buffers
)
5126 framebuffer
->RestoreDrawBuffersAfterClear();
5128 framebuffer_manager()->MarkAttachmentsAsCleared(
5129 framebuffer
, renderbuffer_manager(), texture_manager());
5131 RestoreClearState();
5133 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5134 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5135 Framebuffer
* draw_framebuffer
=
5136 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5137 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5138 GetBackbufferServiceId();
5139 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5143 void GLES2DecoderImpl::RestoreClearState() {
5144 framebuffer_state_
.clear_state_dirty
= true;
5146 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5147 state_
.color_clear_alpha
);
5148 glClearStencil(state_
.stencil_clear
);
5149 glClearDepth(state_
.depth_clear
);
5150 if (state_
.enable_flags
.scissor_test
) {
5151 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5155 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5156 Framebuffer
* framebuffer
=
5157 GetFramebufferInfoForTarget(target
);
5159 return GL_FRAMEBUFFER_COMPLETE
;
5161 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5162 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5163 return completeness
;
5165 return framebuffer
->GetStatus(texture_manager(), target
);
5168 void GLES2DecoderImpl::DoFramebufferTexture2D(
5169 GLenum target
, GLenum attachment
, GLenum textarget
,
5170 GLuint client_texture_id
, GLint level
) {
5171 DoFramebufferTexture2DCommon(
5172 "glFramebufferTexture2D", target
, attachment
,
5173 textarget
, client_texture_id
, level
, 0);
5176 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5177 GLenum target
, GLenum attachment
, GLenum textarget
,
5178 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5179 DoFramebufferTexture2DCommon(
5180 "glFramebufferTexture2DMultisample", target
, attachment
,
5181 textarget
, client_texture_id
, level
, samples
);
5184 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5185 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5186 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5187 if (samples
> renderbuffer_manager()->max_samples()) {
5190 "glFramebufferTexture2DMultisample", "samples too large");
5193 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5196 GL_INVALID_OPERATION
,
5197 name
, "no framebuffer bound.");
5200 GLuint service_id
= 0;
5201 TextureRef
* texture_ref
= NULL
;
5202 if (client_texture_id
) {
5203 texture_ref
= GetTexture(client_texture_id
);
5206 GL_INVALID_OPERATION
,
5207 name
, "unknown texture_ref");
5210 service_id
= texture_ref
->service_id();
5213 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5216 name
, "level out of range");
5221 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5223 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5225 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5227 if (features().use_img_for_multisampled_render_to_texture
) {
5228 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5229 service_id
, level
, samples
);
5231 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5232 service_id
, level
, samples
);
5235 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5236 if (error
== GL_NO_ERROR
) {
5237 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5240 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5241 framebuffer_state_
.clear_state_dirty
= true;
5245 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5250 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5251 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5252 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5255 GL_INVALID_OPERATION
,
5256 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5259 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5260 const Framebuffer::Attachment
* attachment_object
=
5261 framebuffer
->GetAttachment(attachment
);
5262 *params
= attachment_object
? attachment_object
->object_name() : 0;
5264 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5265 features().use_img_for_multisampled_render_to_texture
) {
5266 pname
= GL_TEXTURE_SAMPLES_IMG
;
5268 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5272 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5273 GLenum target
, GLenum pname
, GLint
* params
) {
5274 Renderbuffer
* renderbuffer
=
5275 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5276 if (!renderbuffer
) {
5278 GL_INVALID_OPERATION
,
5279 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5283 EnsureRenderbufferBound();
5285 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5286 *params
= renderbuffer
->internal_format();
5288 case GL_RENDERBUFFER_WIDTH
:
5289 *params
= renderbuffer
->width();
5291 case GL_RENDERBUFFER_HEIGHT
:
5292 *params
= renderbuffer
->height();
5294 case GL_RENDERBUFFER_SAMPLES_EXT
:
5295 if (features().use_img_for_multisampled_render_to_texture
) {
5296 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5299 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5303 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5308 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5309 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5310 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5311 GLbitfield mask
, GLenum filter
) {
5312 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5314 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5318 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5319 BlitFramebufferHelper(
5320 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5321 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5322 state_
.enable_flags
.scissor_test
);
5325 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5326 if (!state_
.bound_renderbuffer_valid
) {
5327 state_
.bound_renderbuffer_valid
= true;
5328 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5329 state_
.bound_renderbuffer
.get()
5330 ? state_
.bound_renderbuffer
->service_id()
5335 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5336 const FeatureInfo
* feature_info
,
5339 GLenum internal_format
,
5342 // TODO(sievers): This could be resolved at the GL binding level, but the
5343 // binding process is currently a bit too 'brute force'.
5344 if (feature_info
->feature_flags().is_angle
) {
5345 glRenderbufferStorageMultisampleANGLE(
5346 target
, samples
, internal_format
, width
, height
);
5347 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5348 glRenderbufferStorageMultisample(
5349 target
, samples
, internal_format
, width
, height
);
5351 glRenderbufferStorageMultisampleEXT(
5352 target
, samples
, internal_format
, width
, height
);
5356 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5366 // TODO(sievers): This could be resolved at the GL binding level, but the
5367 // binding process is currently a bit too 'brute force'.
5368 if (feature_info_
->feature_flags().is_angle
) {
5369 glBlitFramebufferANGLE(
5370 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5371 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5373 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5375 glBlitFramebufferEXT(
5376 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5380 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5382 GLenum internalformat
,
5385 if (samples
> renderbuffer_manager()->max_samples()) {
5388 "glRenderbufferStorageMultisample", "samples too large");
5392 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5393 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5396 "glRenderbufferStorageMultisample", "dimensions too large");
5400 uint32 estimated_size
= 0;
5401 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5402 width
, height
, samples
, internalformat
, &estimated_size
)) {
5405 "glRenderbufferStorageMultisample", "dimensions too large");
5409 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5412 "glRenderbufferStorageMultisample", "out of memory");
5419 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5420 GLenum target
, GLsizei samples
, GLenum internalformat
,
5421 GLsizei width
, GLsizei height
) {
5422 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5423 if (!renderbuffer
) {
5424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5425 "glRenderbufferStorageMultisampleCHROMIUM",
5426 "no renderbuffer bound");
5430 if (!ValidateRenderbufferStorageMultisample(
5431 samples
, internalformat
, width
, height
)) {
5435 EnsureRenderbufferBound();
5436 GLenum impl_format
=
5437 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5439 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5440 "glRenderbufferStorageMultisampleCHROMIUM");
5441 RenderbufferStorageMultisampleHelper(
5442 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5444 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5445 if (error
== GL_NO_ERROR
) {
5447 if (workarounds().validate_multisample_buffer_allocation
) {
5448 if (!VerifyMultisampleRenderbufferIntegrity(
5449 renderbuffer
->service_id(), impl_format
)) {
5452 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5457 // TODO(gman): If renderbuffers tracked which framebuffers they were
5458 // attached to we could just mark those framebuffers as not complete.
5459 framebuffer_manager()->IncFramebufferStateChangeCount();
5460 renderbuffer_manager()->SetInfo(
5461 renderbuffer
, samples
, internalformat
, width
, height
);
5465 // This is the handler for multisampled_render_to_texture extensions.
5466 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5467 GLenum target
, GLsizei samples
, GLenum internalformat
,
5468 GLsizei width
, GLsizei height
) {
5469 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5470 if (!renderbuffer
) {
5471 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5472 "glRenderbufferStorageMultisampleEXT",
5473 "no renderbuffer bound");
5477 if (!ValidateRenderbufferStorageMultisample(
5478 samples
, internalformat
, width
, height
)) {
5482 EnsureRenderbufferBound();
5483 GLenum impl_format
=
5484 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5486 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5487 if (features().use_img_for_multisampled_render_to_texture
) {
5488 glRenderbufferStorageMultisampleIMG(
5489 target
, samples
, impl_format
, width
, height
);
5491 glRenderbufferStorageMultisampleEXT(
5492 target
, samples
, impl_format
, width
, height
);
5494 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5495 if (error
== GL_NO_ERROR
) {
5496 // TODO(gman): If renderbuffers tracked which framebuffers they were
5497 // attached to we could just mark those framebuffers as not complete.
5498 framebuffer_manager()->IncFramebufferStateChangeCount();
5499 renderbuffer_manager()->SetInfo(
5500 renderbuffer
, samples
, internalformat
, width
, height
);
5504 // This function validates the allocation of a multisampled renderbuffer
5505 // by clearing it to a key color, blitting the contents to a texture, and
5506 // reading back the color to ensure it matches the key.
5507 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5508 GLuint renderbuffer
, GLenum format
) {
5510 // Only validate color buffers.
5511 // These formats have been selected because they are very common or are known
5512 // to be used by the WebGL backbuffer. If problems are observed with other
5513 // color formats they can be added here.
5524 GLint draw_framebuffer
, read_framebuffer
;
5526 // Cache framebuffer and texture bindings.
5527 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5528 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5530 if (!validation_texture_
) {
5531 GLint bound_texture
;
5532 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5534 // Create additional resources needed for the verification.
5535 glGenTextures(1, &validation_texture_
);
5536 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5537 glGenFramebuffersEXT(1, &validation_fbo_
);
5539 // Texture only needs to be 1x1.
5540 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5541 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5542 GL_UNSIGNED_BYTE
, NULL
);
5544 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5545 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5546 GL_TEXTURE_2D
, validation_texture_
, 0);
5548 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5551 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5552 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5553 GL_RENDERBUFFER
, renderbuffer
);
5555 // Cache current state and reset it to the values we require.
5556 GLboolean scissor_enabled
= false;
5557 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5558 if (scissor_enabled
)
5559 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5561 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5562 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5563 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5565 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5566 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5567 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5569 // Clear the buffer to the desired key color.
5570 glClear(GL_COLOR_BUFFER_BIT
);
5572 // Blit from the multisample buffer to a standard texture.
5573 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5574 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5576 BlitFramebufferHelper(
5577 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5579 // Read a pixel from the buffer.
5580 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5582 unsigned char pixel
[3] = {0, 0, 0};
5583 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5585 // Detach the renderbuffer.
5586 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5587 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5588 GL_RENDERBUFFER
, 0);
5590 // Restore cached state.
5591 if (scissor_enabled
)
5592 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5594 state_
.SetDeviceColorMask(
5595 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5596 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5597 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5598 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5600 // Return true if the pixel matched the desired key color.
5601 return (pixel
[0] == 0xFF &&
5606 void GLES2DecoderImpl::DoRenderbufferStorage(
5607 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5608 Renderbuffer
* renderbuffer
=
5609 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5610 if (!renderbuffer
) {
5612 GL_INVALID_OPERATION
,
5613 "glRenderbufferStorage", "no renderbuffer bound");
5617 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5618 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5620 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5624 uint32 estimated_size
= 0;
5625 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5626 width
, height
, 1, internalformat
, &estimated_size
)) {
5628 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5632 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5634 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5638 EnsureRenderbufferBound();
5639 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5640 glRenderbufferStorageEXT(
5642 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5646 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5647 if (error
== GL_NO_ERROR
) {
5648 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5649 // we could just mark those framebuffers as not complete.
5650 framebuffer_manager()->IncFramebufferStateChangeCount();
5651 renderbuffer_manager()->SetInfo(
5652 renderbuffer
, 1, internalformat
, width
, height
);
5656 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5657 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5658 Program
* program
= GetProgramInfoNotShader(
5659 program_id
, "glLinkProgram");
5664 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5665 ShaderTranslator
* vertex_translator
= NULL
;
5666 ShaderTranslator
* fragment_translator
= NULL
;
5667 if (use_shader_translator_
) {
5668 vertex_translator
= vertex_translator_
.get();
5669 fragment_translator
= fragment_translator_
.get();
5671 if (program
->Link(shader_manager(),
5673 fragment_translator
,
5674 workarounds().count_all_in_varyings_packing
?
5675 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5676 shader_cache_callback_
)) {
5677 if (program
== state_
.current_program
.get()) {
5678 if (workarounds().use_current_program_after_successful_link
)
5679 glUseProgram(program
->service_id());
5680 if (workarounds().clear_uniforms_before_first_program_use
)
5681 program_manager()->ClearUniforms(program
);
5686 void GLES2DecoderImpl::DoTexParameterf(
5687 GLenum target
, GLenum pname
, GLfloat param
) {
5688 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5691 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5695 texture_manager()->SetParameterf(
5696 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5699 void GLES2DecoderImpl::DoTexParameteri(
5700 GLenum target
, GLenum pname
, GLint param
) {
5701 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5704 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5708 texture_manager()->SetParameteri(
5709 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5712 void GLES2DecoderImpl::DoTexParameterfv(
5713 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5714 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5717 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5721 texture_manager()->SetParameterf(
5722 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5725 void GLES2DecoderImpl::DoTexParameteriv(
5726 GLenum target
, GLenum pname
, const GLint
* params
) {
5727 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5731 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5735 texture_manager()->SetParameteri(
5736 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5739 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5740 if (!state_
.current_program
.get()) {
5741 // The program does not exist.
5743 GL_INVALID_OPERATION
, function_name
, "no program in use");
5746 if (!state_
.current_program
->InUse()) {
5748 GL_INVALID_OPERATION
, function_name
, "program not linked");
5754 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5755 GLint location
, const char* function_name
) {
5756 if (!CheckCurrentProgram(function_name
)) {
5759 return location
!= -1;
5762 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5763 GLint fake_location
,
5764 const char* function_name
,
5765 Program::UniformApiType api_type
,
5766 GLint
* real_location
,
5771 DCHECK(real_location
);
5773 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
5776 GLint array_index
= -1;
5777 const Program::UniformInfo
* info
=
5778 state_
.current_program
->GetUniformInfoByFakeLocation(
5779 fake_location
, real_location
, &array_index
);
5782 GL_INVALID_OPERATION
, function_name
, "unknown location");
5786 if ((api_type
& info
->accepts_api_type
) == 0) {
5788 GL_INVALID_OPERATION
, function_name
,
5789 "wrong uniform function for type");
5792 if (*count
> 1 && !info
->is_array
) {
5794 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
5797 *count
= std::min(info
->size
- array_index
, *count
);
5805 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
5808 GLint real_location
= -1;
5809 if (!PrepForSetUniformByLocation(fake_location
,
5811 Program::kUniform1i
,
5817 if (!state_
.current_program
->SetSamplers(
5818 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
5820 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
5823 glUniform1i(real_location
, v0
);
5826 void GLES2DecoderImpl::DoUniform1iv(
5827 GLint fake_location
, GLsizei count
, const GLint
*value
) {
5829 GLint real_location
= -1;
5830 if (!PrepForSetUniformByLocation(fake_location
,
5832 Program::kUniform1i
,
5838 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
5839 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
5840 if (!state_
.current_program
->SetSamplers(
5841 state_
.texture_units
.size(), fake_location
, count
, value
)) {
5843 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
5847 glUniform1iv(real_location
, count
, value
);
5850 void GLES2DecoderImpl::DoUniform1fv(
5851 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5853 GLint real_location
= -1;
5854 if (!PrepForSetUniformByLocation(fake_location
,
5856 Program::kUniform1f
,
5862 if (type
== GL_BOOL
) {
5863 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
5864 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5865 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5867 DoUniform1iv(real_location
, count
, temp
.get());
5869 glUniform1fv(real_location
, count
, value
);
5873 void GLES2DecoderImpl::DoUniform2fv(
5874 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5876 GLint real_location
= -1;
5877 if (!PrepForSetUniformByLocation(fake_location
,
5879 Program::kUniform2f
,
5885 if (type
== GL_BOOL_VEC2
) {
5886 GLsizei num_values
= count
* 2;
5887 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5888 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5889 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5891 glUniform2iv(real_location
, count
, temp
.get());
5893 glUniform2fv(real_location
, count
, value
);
5897 void GLES2DecoderImpl::DoUniform3fv(
5898 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5900 GLint real_location
= -1;
5901 if (!PrepForSetUniformByLocation(fake_location
,
5903 Program::kUniform3f
,
5909 if (type
== GL_BOOL_VEC3
) {
5910 GLsizei num_values
= count
* 3;
5911 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5912 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5913 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5915 glUniform3iv(real_location
, count
, temp
.get());
5917 glUniform3fv(real_location
, count
, value
);
5921 void GLES2DecoderImpl::DoUniform4fv(
5922 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5924 GLint real_location
= -1;
5925 if (!PrepForSetUniformByLocation(fake_location
,
5927 Program::kUniform4f
,
5933 if (type
== GL_BOOL_VEC4
) {
5934 GLsizei num_values
= count
* 4;
5935 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5936 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5937 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5939 glUniform4iv(real_location
, count
, temp
.get());
5941 glUniform4fv(real_location
, count
, value
);
5945 void GLES2DecoderImpl::DoUniform2iv(
5946 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5948 GLint real_location
= -1;
5949 if (!PrepForSetUniformByLocation(fake_location
,
5951 Program::kUniform2i
,
5957 glUniform2iv(real_location
, count
, value
);
5960 void GLES2DecoderImpl::DoUniform3iv(
5961 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5963 GLint real_location
= -1;
5964 if (!PrepForSetUniformByLocation(fake_location
,
5966 Program::kUniform3i
,
5972 glUniform3iv(real_location
, count
, value
);
5975 void GLES2DecoderImpl::DoUniform4iv(
5976 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5978 GLint real_location
= -1;
5979 if (!PrepForSetUniformByLocation(fake_location
,
5981 Program::kUniform4i
,
5987 glUniform4iv(real_location
, count
, value
);
5990 void GLES2DecoderImpl::DoUniformMatrix2fv(
5991 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5992 const GLfloat
* value
) {
5994 GLint real_location
= -1;
5995 if (!PrepForSetUniformByLocation(fake_location
,
5996 "glUniformMatrix2fv",
5997 Program::kUniformMatrix2f
,
6003 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6006 void GLES2DecoderImpl::DoUniformMatrix3fv(
6007 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6008 const GLfloat
* value
) {
6010 GLint real_location
= -1;
6011 if (!PrepForSetUniformByLocation(fake_location
,
6012 "glUniformMatrix3fv",
6013 Program::kUniformMatrix3f
,
6019 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6022 void GLES2DecoderImpl::DoUniformMatrix4fv(
6023 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6024 const GLfloat
* value
) {
6026 GLint real_location
= -1;
6027 if (!PrepForSetUniformByLocation(fake_location
,
6028 "glUniformMatrix4fv",
6029 Program::kUniformMatrix4f
,
6035 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6038 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6039 GLuint service_id
= 0;
6040 Program
* program
= NULL
;
6042 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6046 if (!program
->IsValid()) {
6047 // Program was not linked successfully. (ie, glLinkProgram)
6049 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6052 service_id
= program
->service_id();
6054 if (state_
.current_program
.get()) {
6055 program_manager()->UnuseProgram(shader_manager(),
6056 state_
.current_program
.get());
6058 state_
.current_program
= program
;
6059 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6060 glUseProgram(service_id
);
6061 if (state_
.current_program
.get()) {
6062 program_manager()->UseProgram(state_
.current_program
.get());
6063 if (workarounds().clear_uniforms_before_first_program_use
)
6064 program_manager()->ClearUniforms(program
);
6068 void GLES2DecoderImpl::RenderWarning(
6069 const char* filename
, int line
, const std::string
& msg
) {
6070 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6073 void GLES2DecoderImpl::PerformanceWarning(
6074 const char* filename
, int line
, const std::string
& msg
) {
6075 logger_
.LogMessage(filename
, line
,
6076 std::string("PERFORMANCE WARNING: ") + msg
);
6079 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6080 Texture
* texture
, GLenum textarget
) {
6081 // Image is already in use if texture is attached to a framebuffer.
6082 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6083 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6085 ScopedGLErrorSuppressor
suppressor(
6086 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6088 glBindTexture(textarget
, texture
->service_id());
6089 image
->WillUseTexImage();
6090 RestoreCurrentTextureBindings(&state_
, textarget
);
6095 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6096 Texture
* texture
, GLenum textarget
) {
6097 // Image is still in use if texture is attached to a framebuffer.
6098 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6099 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6101 ScopedGLErrorSuppressor
suppressor(
6102 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6104 glBindTexture(textarget
, texture
->service_id());
6105 image
->DidUseTexImage();
6106 RestoreCurrentTextureBindings(&state_
, textarget
);
6111 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6112 DCHECK(state_
.current_program
.get());
6113 if (!texture_manager()->HaveUnrenderableTextures() &&
6114 !texture_manager()->HaveImages()) {
6118 bool textures_set
= false;
6119 const Program::SamplerIndices
& sampler_indices
=
6120 state_
.current_program
->sampler_indices();
6121 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6122 const Program::UniformInfo
* uniform_info
=
6123 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6124 DCHECK(uniform_info
);
6125 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6126 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6127 if (texture_unit_index
< state_
.texture_units
.size()) {
6128 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6129 TextureRef
* texture_ref
=
6130 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6131 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6132 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6133 textures_set
= true;
6134 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6137 texture_manager()->black_texture_id(uniform_info
->type
));
6138 LOCAL_RENDER_WARNING(
6139 std::string("texture bound to texture unit ") +
6140 base::IntToString(texture_unit_index
) +
6141 " is not renderable. It maybe non-power-of-2 and have"
6142 " incompatible texture filtering or is not"
6143 " 'texture complete'");
6147 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6148 Texture
* texture
= texture_ref
->texture();
6149 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6150 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6151 ScopedGLErrorSuppressor
suppressor(
6152 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6153 textures_set
= true;
6154 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6155 image
->WillUseTexImage();
6160 // else: should this be an error?
6163 return !textures_set
;
6166 void GLES2DecoderImpl::RestoreStateForTextures() {
6167 DCHECK(state_
.current_program
.get());
6168 const Program::SamplerIndices
& sampler_indices
=
6169 state_
.current_program
->sampler_indices();
6170 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6171 const Program::UniformInfo
* uniform_info
=
6172 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6173 DCHECK(uniform_info
);
6174 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6175 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6176 if (texture_unit_index
< state_
.texture_units
.size()) {
6177 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6178 TextureRef
* texture_ref
=
6179 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6180 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6181 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6182 // Get the texture_ref info that was previously bound here.
6183 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6184 ? texture_unit
.bound_texture_2d
.get()
6185 : texture_unit
.bound_texture_cube_map
.get();
6186 glBindTexture(texture_unit
.bind_target
,
6187 texture_ref
? texture_ref
->service_id() : 0);
6191 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6192 Texture
* texture
= texture_ref
->texture();
6193 gfx::GLImage
* image
=
6194 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6195 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6196 ScopedGLErrorSuppressor
suppressor(
6197 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6198 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6199 image
->DidUseTexImage();
6206 // Set the active texture back to whatever the user had it as.
6207 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6210 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6211 // Only check if there are some uncleared textures.
6212 if (!texture_manager()->HaveUnsafeTextures()) {
6216 // 1: Check all textures we are about to render with.
6217 if (state_
.current_program
.get()) {
6218 const Program::SamplerIndices
& sampler_indices
=
6219 state_
.current_program
->sampler_indices();
6220 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6221 const Program::UniformInfo
* uniform_info
=
6222 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6223 DCHECK(uniform_info
);
6224 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6225 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6226 if (texture_unit_index
< state_
.texture_units
.size()) {
6227 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6228 TextureRef
* texture_ref
=
6229 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6230 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6231 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6242 bool GLES2DecoderImpl::IsDrawValid(
6243 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6244 GLsizei primcount
) {
6245 DCHECK(instanced
|| primcount
== 1);
6247 // NOTE: We specifically do not check current_program->IsValid() because
6248 // it could never be invalid since glUseProgram would have failed. While
6249 // glLinkProgram could later mark the program as invalid the previous
6250 // valid program will still function if it is still the current program.
6251 if (!state_
.current_program
.get()) {
6252 // The program does not exist.
6253 // But GL says no ERROR.
6254 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6258 return state_
.vertex_attrib_manager
6259 ->ValidateBindings(function_name
,
6261 feature_info_
.get(),
6262 state_
.current_program
.get(),
6263 max_vertex_accessed
,
6268 bool GLES2DecoderImpl::SimulateAttrib0(
6269 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6273 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6276 const VertexAttrib
* attrib
=
6277 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6278 // If it's enabled or it's not used then we don't need to do anything.
6279 bool attrib_0_used
=
6280 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6281 if (attrib
->enabled() && attrib_0_used
) {
6285 // Make a buffer with a single repeated vec4 value enough to
6286 // simulate the constant value that is supposed to be here.
6287 // This is required to emulate GLES2 on GL.
6288 GLuint num_vertices
= max_vertex_accessed
+ 1;
6289 uint32 size_needed
= 0;
6291 if (num_vertices
== 0 ||
6292 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6293 size_needed
> 0x7FFFFFFFU
) {
6294 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6298 LOCAL_PERFORMANCE_WARNING(
6299 "Attribute 0 is disabled. This has signficant performance penalty");
6301 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6302 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6304 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6306 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6307 GLenum error
= glGetError();
6308 if (error
!= GL_NO_ERROR
) {
6310 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6315 const Vec4
& value
= state_
.attrib_values
[0];
6318 (!attrib_0_buffer_matches_value_
||
6319 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6320 value
.v
[1] != attrib_0_value_
.v
[1] ||
6321 value
.v
[2] != attrib_0_value_
.v
[2] ||
6322 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6323 std::vector
<Vec4
> temp(num_vertices
, value
);
6324 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6325 attrib_0_buffer_matches_value_
= true;
6326 attrib_0_value_
= value
;
6327 attrib_0_size_
= size_needed
;
6330 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6332 if (attrib
->divisor())
6333 glVertexAttribDivisorANGLE(0, 0);
6339 void GLES2DecoderImpl::RestoreStateForAttrib(
6340 GLuint attrib_index
, bool restore_array_binding
) {
6341 const VertexAttrib
* attrib
=
6342 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6343 if (restore_array_binding
) {
6344 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6345 Buffer
* buffer
= attrib
->buffer();
6346 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6347 glVertexAttribPointer(
6348 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6349 attrib
->gl_stride(), ptr
);
6351 if (attrib
->divisor())
6352 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6354 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6355 state_
.bound_array_buffer
->service_id() : 0);
6357 // Never touch vertex attribute 0's state (in particular, never
6358 // disable it) when running on desktop GL because it will never be
6360 if (attrib_index
!= 0 ||
6361 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6362 if (attrib
->enabled()) {
6363 glEnableVertexAttribArray(attrib_index
);
6365 glDisableVertexAttribArray(attrib_index
);
6370 bool GLES2DecoderImpl::SimulateFixedAttribs(
6371 const char* function_name
,
6372 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6375 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6378 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6382 LOCAL_PERFORMANCE_WARNING(
6383 "GL_FIXED attributes have a signficant performance penalty");
6385 // NOTE: we could be smart and try to check if a buffer is used
6386 // twice in 2 different attribs, find the overlapping parts and therefore
6387 // duplicate the minimum amount of data but this whole code path is not meant
6388 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6389 // tests so we just add to the buffer attrib used.
6391 GLuint elements_needed
= 0;
6392 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6393 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6394 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6395 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6396 const VertexAttrib
* attrib
= *it
;
6397 const Program::VertexAttrib
* attrib_info
=
6398 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6399 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6400 max_vertex_accessed
);
6401 GLuint num_vertices
= max_accessed
+ 1;
6402 if (num_vertices
== 0) {
6404 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6408 attrib
->CanAccess(max_accessed
) &&
6409 attrib
->type() == GL_FIXED
) {
6410 uint32 elements_used
= 0;
6411 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6412 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6414 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6420 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6421 uint32 size_needed
= 0;
6422 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6423 size_needed
> 0x7FFFFFFFU
) {
6425 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6429 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6431 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6432 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6433 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6434 GLenum error
= glGetError();
6435 if (error
!= GL_NO_ERROR
) {
6437 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6442 // Copy the elements and convert to float
6443 GLintptr offset
= 0;
6444 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6445 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6446 const VertexAttrib
* attrib
= *it
;
6447 const Program::VertexAttrib
* attrib_info
=
6448 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6449 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6450 max_vertex_accessed
);
6451 GLuint num_vertices
= max_accessed
+ 1;
6452 if (num_vertices
== 0) {
6454 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6458 attrib
->CanAccess(max_accessed
) &&
6459 attrib
->type() == GL_FIXED
) {
6460 int num_elements
= attrib
->size() * kSizeOfFloat
;
6461 int size
= num_elements
* num_vertices
;
6462 scoped_ptr
<float[]> data(new float[size
]);
6463 const int32
* src
= reinterpret_cast<const int32
*>(
6464 attrib
->buffer()->GetRange(attrib
->offset(), size
));
6465 const int32
* end
= src
+ num_elements
;
6466 float* dst
= data
.get();
6467 while (src
!= end
) {
6468 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6470 glBufferSubData(GL_ARRAY_BUFFER
, offset
, size
, data
.get());
6471 glVertexAttribPointer(
6472 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6473 reinterpret_cast<GLvoid
*>(offset
));
6481 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6482 // There's no need to call glVertexAttribPointer because we shadow all the
6483 // settings and passing GL_FIXED to it will not work.
6486 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6490 error::Error
GLES2DecoderImpl::DoDrawArrays(
6491 const char* function_name
,
6496 GLsizei primcount
) {
6497 error::Error error
= WillAccessBoundFramebufferForDraw();
6498 if (error
!= error::kNoError
)
6500 if (!validators_
->draw_mode
.IsValid(mode
)) {
6501 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6502 return error::kNoError
;
6505 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6506 return error::kNoError
;
6508 if (primcount
< 0) {
6509 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6510 return error::kNoError
;
6512 if (!CheckBoundFramebuffersValid(function_name
)) {
6513 return error::kNoError
;
6515 // We have to check this here because the prototype for glDrawArrays
6516 // is GLint not GLsizei.
6518 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6519 return error::kNoError
;
6522 if (count
== 0 || primcount
== 0) {
6523 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6524 return error::kNoError
;
6527 GLuint max_vertex_accessed
= first
+ count
- 1;
6528 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6529 if (!ClearUnclearedTextures()) {
6530 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6531 return error::kNoError
;
6533 bool simulated_attrib_0
= false;
6534 if (!SimulateAttrib0(
6535 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6536 return error::kNoError
;
6538 bool simulated_fixed_attribs
= false;
6539 if (SimulateFixedAttribs(
6540 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6542 bool textures_set
= !PrepareTexturesForRender();
6544 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6546 glDrawArrays(mode
, first
, count
);
6548 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6551 RestoreStateForTextures();
6553 if (simulated_fixed_attribs
) {
6554 RestoreStateForSimulatedFixedAttribs();
6557 if (simulated_attrib_0
) {
6558 // We don't have to restore attrib 0 generic data at the end of this
6559 // function even if it is simulated. This is because we will simulate
6560 // it in each draw call, and attrib 0 generic data queries use cached
6561 // values instead of passing down to the underlying driver.
6562 RestoreStateForAttrib(0, false);
6565 return error::kNoError
;
6568 error::Error
GLES2DecoderImpl::HandleDrawArrays(
6569 uint32 immediate_data_size
, const cmds::DrawArrays
& c
) {
6570 return DoDrawArrays("glDrawArrays",
6572 static_cast<GLenum
>(c
.mode
),
6573 static_cast<GLint
>(c
.first
),
6574 static_cast<GLsizei
>(c
.count
),
6578 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6579 uint32 immediate_data_size
, const cmds::DrawArraysInstancedANGLE
& c
) {
6580 if (!features().angle_instanced_arrays
) {
6582 GL_INVALID_OPERATION
,
6583 "glDrawArraysInstancedANGLE", "function not available");
6584 return error::kNoError
;
6586 return DoDrawArrays("glDrawArraysIntancedANGLE",
6588 static_cast<GLenum
>(c
.mode
),
6589 static_cast<GLint
>(c
.first
),
6590 static_cast<GLsizei
>(c
.count
),
6591 static_cast<GLsizei
>(c
.primcount
));
6594 error::Error
GLES2DecoderImpl::DoDrawElements(
6595 const char* function_name
,
6601 GLsizei primcount
) {
6602 error::Error error
= WillAccessBoundFramebufferForDraw();
6603 if (error
!= error::kNoError
)
6605 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6607 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6608 return error::kNoError
;
6612 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6613 return error::kNoError
;
6616 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6617 return error::kNoError
;
6619 if (!validators_
->draw_mode
.IsValid(mode
)) {
6620 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6621 return error::kNoError
;
6623 if (!validators_
->index_type
.IsValid(type
)) {
6624 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6625 return error::kNoError
;
6627 if (primcount
< 0) {
6628 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6629 return error::kNoError
;
6632 if (!CheckBoundFramebuffersValid(function_name
)) {
6633 return error::kNoError
;
6636 if (count
== 0 || primcount
== 0) {
6637 return error::kNoError
;
6640 GLuint max_vertex_accessed
;
6641 Buffer
* element_array_buffer
=
6642 state_
.vertex_attrib_manager
->element_array_buffer();
6644 if (!element_array_buffer
->GetMaxValueForRange(
6645 offset
, count
, type
, &max_vertex_accessed
)) {
6647 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6648 return error::kNoError
;
6651 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6652 if (!ClearUnclearedTextures()) {
6653 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6654 return error::kNoError
;
6656 bool simulated_attrib_0
= false;
6657 if (!SimulateAttrib0(
6658 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6659 return error::kNoError
;
6661 bool simulated_fixed_attribs
= false;
6662 if (SimulateFixedAttribs(
6663 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6665 bool textures_set
= !PrepareTexturesForRender();
6667 // TODO(gman): Refactor to hide these details in BufferManager or
6668 // VertexAttribManager.
6669 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6670 bool used_client_side_array
= false;
6671 if (element_array_buffer
->IsClientSideArray()) {
6672 used_client_side_array
= true;
6673 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6674 indices
= element_array_buffer
->GetRange(offset
, 0);
6677 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6679 glDrawElements(mode
, count
, type
, indices
);
6681 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6684 if (used_client_side_array
) {
6685 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6686 element_array_buffer
->service_id());
6690 RestoreStateForTextures();
6692 if (simulated_fixed_attribs
) {
6693 RestoreStateForSimulatedFixedAttribs();
6696 if (simulated_attrib_0
) {
6697 // We don't have to restore attrib 0 generic data at the end of this
6698 // function even if it is simulated. This is because we will simulate
6699 // it in each draw call, and attrib 0 generic data queries use cached
6700 // values instead of passing down to the underlying driver.
6701 RestoreStateForAttrib(0, false);
6704 return error::kNoError
;
6707 error::Error
GLES2DecoderImpl::HandleDrawElements(
6708 uint32 immediate_data_size
, const cmds::DrawElements
& c
) {
6709 return DoDrawElements("glDrawElements",
6711 static_cast<GLenum
>(c
.mode
),
6712 static_cast<GLsizei
>(c
.count
),
6713 static_cast<GLenum
>(c
.type
),
6714 static_cast<int32
>(c
.index_offset
),
6718 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6719 uint32 immediate_data_size
, const cmds::DrawElementsInstancedANGLE
& c
) {
6720 if (!features().angle_instanced_arrays
) {
6722 GL_INVALID_OPERATION
,
6723 "glDrawElementsInstancedANGLE", "function not available");
6724 return error::kNoError
;
6726 return DoDrawElements("glDrawElementsInstancedANGLE",
6728 static_cast<GLenum
>(c
.mode
),
6729 static_cast<GLsizei
>(c
.count
),
6730 static_cast<GLenum
>(c
.type
),
6731 static_cast<int32
>(c
.index_offset
),
6732 static_cast<GLsizei
>(c
.primcount
));
6735 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6736 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
6737 GLuint max_vertex_accessed
= 0;
6738 Buffer
* buffer
= GetBuffer(buffer_id
);
6740 // TODO(gman): Should this be a GL error or a command buffer error?
6742 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6744 if (!buffer
->GetMaxValueForRange(
6745 offset
, count
, type
, &max_vertex_accessed
)) {
6746 // TODO(gman): Should this be a GL error or a command buffer error?
6748 GL_INVALID_OPERATION
,
6749 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6752 return max_vertex_accessed
;
6755 // Calls glShaderSource for the various versions of the ShaderSource command.
6756 // Assumes that data / data_size points to a piece of memory that is in range
6757 // of whatever context it came from (shared memory, immediate memory, bucket
6759 error::Error
GLES2DecoderImpl::ShaderSourceHelper(
6760 GLuint client_id
, const char* data
, uint32 data_size
) {
6761 std::string
str(data
, data
+ data_size
);
6762 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
6764 return error::kNoError
;
6766 // Note: We don't actually call glShaderSource here. We wait until
6767 // the call to glCompileShader.
6768 shader
->UpdateSource(str
.c_str());
6769 return error::kNoError
;
6772 error::Error
GLES2DecoderImpl::HandleShaderSourceBucket(
6773 uint32 immediate_data_size
, const cmds::ShaderSourceBucket
& c
) {
6774 Bucket
* bucket
= GetBucket(c
.data_bucket_id
);
6775 if (!bucket
|| bucket
->size() == 0) {
6776 return error::kInvalidArguments
;
6778 return ShaderSourceHelper(
6779 c
.shader
, bucket
->GetDataAs
<const char*>(0, bucket
->size() - 1),
6780 bucket
->size() - 1);
6783 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
6784 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6785 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
6789 ShaderTranslator
* translator
= NULL
;
6790 if (use_shader_translator_
) {
6791 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
6792 vertex_translator_
.get() : fragment_translator_
.get();
6795 program_manager()->DoCompileShader(
6798 feature_info_
->feature_flags().angle_translated_shader_source
?
6799 ProgramManager::kANGLE
: ProgramManager::kGL
);
6802 void GLES2DecoderImpl::DoGetShaderiv(
6803 GLuint shader_id
, GLenum pname
, GLint
* params
) {
6804 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
6809 case GL_SHADER_SOURCE_LENGTH
:
6810 *params
= shader
->source() ? shader
->source()->size() + 1 : 0;
6812 case GL_COMPILE_STATUS
:
6813 *params
= compile_shader_always_succeeds_
? true : shader
->IsValid();
6815 case GL_INFO_LOG_LENGTH
:
6816 *params
= shader
->log_info() ? shader
->log_info()->size() + 1 : 0;
6818 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
6819 *params
= shader
->translated_source() ?
6820 shader
->translated_source()->size() + 1 : 0;
6825 glGetShaderiv(shader
->service_id(), pname
, params
);
6828 error::Error
GLES2DecoderImpl::HandleGetShaderSource(
6829 uint32 immediate_data_size
, const cmds::GetShaderSource
& c
) {
6830 GLuint shader_id
= c
.shader
;
6831 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6832 Bucket
* bucket
= CreateBucket(bucket_id
);
6833 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
6834 if (!shader
|| !shader
->source()) {
6836 return error::kNoError
;
6838 bucket
->SetFromString(shader
->source()->c_str());
6839 return error::kNoError
;
6842 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6843 uint32 immediate_data_size
,
6844 const cmds::GetTranslatedShaderSourceANGLE
& c
) {
6845 GLuint shader_id
= c
.shader
;
6846 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6847 Bucket
* bucket
= CreateBucket(bucket_id
);
6848 Shader
* shader
= GetShaderInfoNotProgram(
6849 shader_id
, "glGetTranslatedShaderSourceANGLE");
6852 return error::kNoError
;
6855 bucket
->SetFromString(shader
->translated_source() ?
6856 shader
->translated_source()->c_str() : NULL
);
6857 return error::kNoError
;
6860 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
6861 uint32 immediate_data_size
, const cmds::GetProgramInfoLog
& c
) {
6862 GLuint program_id
= c
.program
;
6863 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6864 Bucket
* bucket
= CreateBucket(bucket_id
);
6865 Program
* program
= GetProgramInfoNotShader(
6866 program_id
, "glGetProgramInfoLog");
6867 if (!program
|| !program
->log_info()) {
6868 bucket
->SetFromString("");
6869 return error::kNoError
;
6871 bucket
->SetFromString(program
->log_info()->c_str());
6872 return error::kNoError
;
6875 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
6876 uint32 immediate_data_size
, const cmds::GetShaderInfoLog
& c
) {
6877 GLuint shader_id
= c
.shader
;
6878 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6879 Bucket
* bucket
= CreateBucket(bucket_id
);
6880 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
6881 if (!shader
|| !shader
->log_info()) {
6882 bucket
->SetFromString("");
6883 return error::kNoError
;
6885 bucket
->SetFromString(shader
->log_info()->c_str());
6886 return error::kNoError
;
6889 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
6890 return state_
.GetEnabled(cap
);
6893 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
6894 const Buffer
* buffer
= GetBuffer(client_id
);
6895 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
6898 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
6899 const Framebuffer
* framebuffer
=
6900 GetFramebuffer(client_id
);
6901 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
6904 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
6905 // IsProgram is true for programs as soon as they are created, until they are
6906 // deleted and no longer in use.
6907 const Program
* program
= GetProgram(client_id
);
6908 return program
!= NULL
&& !program
->IsDeleted();
6911 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
6912 const Renderbuffer
* renderbuffer
=
6913 GetRenderbuffer(client_id
);
6914 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
6917 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
6918 // IsShader is true for shaders as soon as they are created, until they
6919 // are deleted and not attached to any programs.
6920 const Shader
* shader
= GetShader(client_id
);
6921 return shader
!= NULL
&& !shader
->IsDeleted();
6924 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
6925 const TextureRef
* texture_ref
= GetTexture(client_id
);
6926 return texture_ref
&& texture_ref
->texture()->IsValid();
6929 void GLES2DecoderImpl::DoAttachShader(
6930 GLuint program_client_id
, GLint shader_client_id
) {
6931 Program
* program
= GetProgramInfoNotShader(
6932 program_client_id
, "glAttachShader");
6936 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
6940 if (!program
->AttachShader(shader_manager(), shader
)) {
6942 GL_INVALID_OPERATION
,
6944 "can not attach more than one shader of the same type.");
6947 glAttachShader(program
->service_id(), shader
->service_id());
6950 void GLES2DecoderImpl::DoDetachShader(
6951 GLuint program_client_id
, GLint shader_client_id
) {
6952 Program
* program
= GetProgramInfoNotShader(
6953 program_client_id
, "glDetachShader");
6957 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
6961 if (!program
->DetachShader(shader_manager(), shader
)) {
6963 GL_INVALID_OPERATION
,
6964 "glDetachShader", "shader not attached to program");
6967 glDetachShader(program
->service_id(), shader
->service_id());
6970 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
6971 Program
* program
= GetProgramInfoNotShader(
6972 program_client_id
, "glValidateProgram");
6976 program
->Validate();
6979 void GLES2DecoderImpl::GetVertexAttribHelper(
6980 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
6982 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
6983 Buffer
* buffer
= attrib
->buffer();
6984 if (buffer
&& !buffer
->IsDeleted()) {
6986 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
6987 *params
= client_id
;
6991 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
6992 *params
= attrib
->enabled();
6994 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
6995 *params
= attrib
->size();
6997 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
6998 *params
= attrib
->gl_stride();
7000 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7001 *params
= attrib
->type();
7003 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7004 *params
= attrib
->normalized();
7006 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7007 *params
= attrib
->divisor();
7015 void GLES2DecoderImpl::DoGetTexParameterfv(
7016 GLenum target
, GLenum pname
, GLfloat
* params
) {
7017 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7018 glGetTexParameterfv(target
, pname
, params
);
7021 void GLES2DecoderImpl::DoGetTexParameteriv(
7022 GLenum target
, GLenum pname
, GLint
* params
) {
7023 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7024 glGetTexParameteriv(target
, pname
, params
);
7027 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7028 GLenum target
, GLenum pname
) {
7029 if (!workarounds().init_texture_max_anisotropy
)
7031 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7032 !validators_
->texture_parameter
.IsValid(pname
)) {
7036 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7040 GL_INVALID_OPERATION
,
7041 "glGetTexParamter{fi}v", "unknown texture for target");
7044 Texture
* texture
= texture_ref
->texture();
7045 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7048 void GLES2DecoderImpl::DoGetVertexAttribfv(
7049 GLuint index
, GLenum pname
, GLfloat
* params
) {
7050 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7053 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7057 case GL_CURRENT_VERTEX_ATTRIB
: {
7058 const Vec4
& value
= state_
.attrib_values
[index
];
7059 params
[0] = value
.v
[0];
7060 params
[1] = value
.v
[1];
7061 params
[2] = value
.v
[2];
7062 params
[3] = value
.v
[3];
7067 GetVertexAttribHelper(attrib
, pname
, &value
);
7068 *params
= static_cast<GLfloat
>(value
);
7074 void GLES2DecoderImpl::DoGetVertexAttribiv(
7075 GLuint index
, GLenum pname
, GLint
* params
) {
7076 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7079 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7083 case GL_CURRENT_VERTEX_ATTRIB
: {
7084 const Vec4
& value
= state_
.attrib_values
[index
];
7085 params
[0] = static_cast<GLint
>(value
.v
[0]);
7086 params
[1] = static_cast<GLint
>(value
.v
[1]);
7087 params
[2] = static_cast<GLint
>(value
.v
[2]);
7088 params
[3] = static_cast<GLint
>(value
.v
[3]);
7092 GetVertexAttribHelper(attrib
, pname
, params
);
7097 bool GLES2DecoderImpl::SetVertexAttribValue(
7098 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7099 if (index
>= state_
.attrib_values
.size()) {
7100 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7103 Vec4
& v
= state_
.attrib_values
[index
];
7111 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7112 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7113 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7114 glVertexAttrib1f(index
, v0
);
7118 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7119 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7120 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7121 glVertexAttrib2f(index
, v0
, v1
);
7125 void GLES2DecoderImpl::DoVertexAttrib3f(
7126 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7127 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7128 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7129 glVertexAttrib3f(index
, v0
, v1
, v2
);
7133 void GLES2DecoderImpl::DoVertexAttrib4f(
7134 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7135 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7136 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7137 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7141 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7142 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7143 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7144 glVertexAttrib1fv(index
, v
);
7148 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7149 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7150 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7151 glVertexAttrib2fv(index
, v
);
7155 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7156 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7157 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7158 glVertexAttrib3fv(index
, v
);
7162 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7163 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7164 glVertexAttrib4fv(index
, v
);
7168 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7169 uint32 immediate_data_size
, const cmds::VertexAttribPointer
& c
) {
7171 if (!state_
.bound_array_buffer
.get() ||
7172 state_
.bound_array_buffer
->IsDeleted()) {
7173 if (state_
.vertex_attrib_manager
.get() ==
7174 state_
.default_vertex_attrib_manager
.get()) {
7176 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7177 return error::kNoError
;
7178 } else if (c
.offset
!= 0) {
7181 "glVertexAttribPointer", "client side arrays are not allowed");
7182 return error::kNoError
;
7186 GLuint indx
= c
.indx
;
7187 GLint size
= c
.size
;
7188 GLenum type
= c
.type
;
7189 GLboolean normalized
= c
.normalized
;
7190 GLsizei stride
= c
.stride
;
7191 GLsizei offset
= c
.offset
;
7192 const void* ptr
= reinterpret_cast<const void*>(offset
);
7193 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7194 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7195 return error::kNoError
;
7197 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7199 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7200 return error::kNoError
;
7202 if (indx
>= group_
->max_vertex_attribs()) {
7204 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7205 return error::kNoError
;
7209 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7210 return error::kNoError
;
7214 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7215 return error::kNoError
;
7219 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7220 return error::kNoError
;
7222 GLsizei component_size
=
7223 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7224 // component_size must be a power of two to use & as optimized modulo.
7225 DCHECK(GLES2Util::IsPOT(component_size
));
7226 if (offset
& (component_size
- 1)) {
7228 GL_INVALID_OPERATION
,
7229 "glVertexAttribPointer", "offset not valid for type");
7230 return error::kNoError
;
7232 if (stride
& (component_size
- 1)) {
7234 GL_INVALID_OPERATION
,
7235 "glVertexAttribPointer", "stride not valid for type");
7236 return error::kNoError
;
7238 state_
.vertex_attrib_manager
7239 ->SetAttribInfo(indx
,
7240 state_
.bound_array_buffer
.get(),
7245 stride
!= 0 ? stride
: component_size
* size
,
7247 if (type
!= GL_FIXED
) {
7248 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7250 return error::kNoError
;
7253 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7255 state_
.viewport_x
= x
;
7256 state_
.viewport_y
= y
;
7257 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7258 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7259 glViewport(x
, y
, width
, height
);
7262 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7263 uint32 immediate_data_size
, const cmds::VertexAttribDivisorANGLE
& c
) {
7264 if (!features().angle_instanced_arrays
) {
7266 GL_INVALID_OPERATION
,
7267 "glVertexAttribDivisorANGLE", "function not available");
7268 return error::kNoError
;
7270 GLuint index
= c
.index
;
7271 GLuint divisor
= c
.divisor
;
7272 if (index
>= group_
->max_vertex_attribs()) {
7275 "glVertexAttribDivisorANGLE", "index out of range");
7276 return error::kNoError
;
7279 state_
.vertex_attrib_manager
->SetDivisor(
7282 glVertexAttribDivisorANGLE(index
, divisor
);
7283 return error::kNoError
;
7286 template <typename pixel_data_type
>
7287 static void WriteAlphaData(
7288 void *pixels
, uint32 row_count
, uint32 channel_count
,
7289 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7290 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7291 DCHECK_GT(channel_count
, 0U);
7292 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7293 uint32 unpadded_row_size_in_elements
=
7294 unpadded_row_size
/ sizeof(pixel_data_type
);
7295 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7296 uint32 padded_row_size_in_elements
=
7297 padded_row_size
/ sizeof(pixel_data_type
);
7298 pixel_data_type
* dst
=
7299 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7300 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7301 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7302 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7305 dst
+= padded_row_size_in_elements
;
7309 void GLES2DecoderImpl::FinishReadPixels(
7310 const cmds::ReadPixels
& c
,
7312 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7313 GLsizei width
= c
.width
;
7314 GLsizei height
= c
.height
;
7315 GLenum format
= c
.format
;
7316 GLenum type
= c
.type
;
7317 typedef cmds::ReadPixels::Result Result
;
7319 Result
* result
= NULL
;
7320 if (c
.result_shm_id
!= 0) {
7321 result
= GetSharedMemoryAs
<Result
*>(
7322 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7325 glDeleteBuffersARB(1, &buffer
);
7330 GLES2Util::ComputeImageDataSizes(
7331 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7333 void* pixels
= GetSharedMemoryAs
<void*>(
7334 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7337 glDeleteBuffersARB(1, &buffer
);
7343 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7345 if (features().map_buffer_range
) {
7346 data
= glMapBufferRange(
7347 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7349 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7351 memcpy(pixels
, data
, pixels_size
);
7352 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7353 // have to restore the state.
7354 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7355 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7356 glDeleteBuffersARB(1, &buffer
);
7359 if (result
!= NULL
) {
7363 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7364 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7365 if ((channels_exist
& 0x0008) == 0 &&
7366 workarounds().clear_alpha_in_readpixels
) {
7367 // Set the alpha to 255 because some drivers are buggy in this regard.
7370 uint32 unpadded_row_size
;
7371 uint32 padded_row_size
;
7372 if (!GLES2Util::ComputeImageDataSizes(
7373 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7374 &unpadded_row_size
, &padded_row_size
)) {
7378 uint32 channel_count
= 0;
7379 uint32 alpha_channel
= 0;
7392 if (channel_count
> 0) {
7394 case GL_UNSIGNED_BYTE
:
7395 WriteAlphaData
<uint8
>(
7396 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7397 padded_row_size
, 0xFF);
7400 WriteAlphaData
<float>(
7401 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7402 padded_row_size
, 1.0f
);
7405 WriteAlphaData
<uint16
>(
7406 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7407 padded_row_size
, 0x3C00);
7415 error::Error
GLES2DecoderImpl::HandleReadPixels(
7416 uint32 immediate_data_size
, const cmds::ReadPixels
& c
) {
7417 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7418 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7419 if (fbo_error
!= error::kNoError
)
7423 GLsizei width
= c
.width
;
7424 GLsizei height
= c
.height
;
7425 GLenum format
= c
.format
;
7426 GLenum type
= c
.type
;
7427 GLboolean async
= c
.async
;
7428 if (width
< 0 || height
< 0) {
7429 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7430 return error::kNoError
;
7432 typedef cmds::ReadPixels::Result Result
;
7434 if (!GLES2Util::ComputeImageDataSizes(
7435 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7437 return error::kOutOfBounds
;
7439 void* pixels
= GetSharedMemoryAs
<void*>(
7440 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7442 return error::kOutOfBounds
;
7444 Result
* result
= NULL
;
7445 if (c
.result_shm_id
!= 0) {
7446 result
= GetSharedMemoryAs
<Result
*>(
7447 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7449 return error::kOutOfBounds
;
7453 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7454 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7455 return error::kNoError
;
7457 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7458 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7459 return error::kNoError
;
7461 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7462 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7463 // format and type are acceptable enums but not guaranteed to be supported
7464 // for this framebuffer. Have to ask gl if they are valid.
7465 GLint preferred_format
= 0;
7466 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7467 GLint preferred_type
= 0;
7468 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7469 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7470 type
!= static_cast<GLenum
>(preferred_type
)) {
7472 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7473 "with the current read framebuffer");
7474 return error::kNoError
;
7477 if (width
== 0 || height
== 0) {
7478 return error::kNoError
;
7481 // Get the size of the current fbo or backbuffer.
7482 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7486 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7488 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7489 return error::kNoError
;
7492 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7493 return error::kNoError
;
7496 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7497 return error::kNoError
;
7500 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7502 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7504 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7505 // The user requested an out of range area. Get the results 1 line
7508 uint32 unpadded_row_size
;
7509 uint32 padded_row_size
;
7510 if (!GLES2Util::ComputeImageDataSizes(
7511 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7512 &unpadded_row_size
, &padded_row_size
)) {
7514 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7515 return error::kNoError
;
7518 GLint dest_x_offset
= std::max(-x
, 0);
7519 uint32 dest_row_offset
;
7520 if (!GLES2Util::ComputeImageDataSizes(
7521 dest_x_offset
, 1, format
, type
, state_
.pack_alignment
, &dest_row_offset
,
7524 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7525 return error::kNoError
;
7528 // Copy each row into the larger dest rect.
7529 int8
* dst
= static_cast<int8
*>(pixels
);
7530 GLint read_x
= std::max(0, x
);
7531 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7532 GLint read_width
= read_end_x
- read_x
;
7533 for (GLint yy
= 0; yy
< height
; ++yy
) {
7537 memset(dst
, 0, unpadded_row_size
);
7539 // If the row is in range, copy it.
7540 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7542 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7544 dst
+= padded_row_size
;
7547 if (async
&& features().use_async_readpixels
) {
7549 glGenBuffersARB(1, &buffer
);
7550 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7551 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, GL_STREAM_READ
);
7552 GLenum error
= glGetError();
7553 if (error
== GL_NO_ERROR
) {
7554 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7555 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7556 new FenceCallback()));
7557 WaitForReadPixels(base::Bind(
7558 &GLES2DecoderImpl::FinishReadPixels
,
7559 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7560 <GLES2DecoderImpl
>(this),
7562 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7563 return error::kNoError
;
7565 // On error, unbind pack buffer and fall through to sync readpixels
7566 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7569 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7571 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7572 if (error
== GL_NO_ERROR
) {
7573 if (result
!= NULL
) {
7576 FinishReadPixels(c
, 0);
7579 return error::kNoError
;
7582 error::Error
GLES2DecoderImpl::HandlePixelStorei(
7583 uint32 immediate_data_size
, const cmds::PixelStorei
& c
) {
7584 GLenum pname
= c
.pname
;
7585 GLenum param
= c
.param
;
7586 if (!validators_
->pixel_store
.IsValid(pname
)) {
7587 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7588 return error::kNoError
;
7591 case GL_PACK_ALIGNMENT
:
7592 case GL_UNPACK_ALIGNMENT
:
7593 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7595 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7596 return error::kNoError
;
7599 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7600 unpack_flip_y_
= (param
!= 0);
7601 return error::kNoError
;
7602 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7603 unpack_premultiply_alpha_
= (param
!= 0);
7604 return error::kNoError
;
7605 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7606 unpack_unpremultiply_alpha_
= (param
!= 0);
7607 return error::kNoError
;
7611 glPixelStorei(pname
, param
);
7613 case GL_PACK_ALIGNMENT
:
7614 state_
.pack_alignment
= param
;
7616 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
7617 state_
.pack_reverse_row_order
= (param
!= 0);
7619 case GL_UNPACK_ALIGNMENT
:
7620 state_
.unpack_alignment
= param
;
7623 // Validation should have prevented us from getting here.
7627 return error::kNoError
;
7630 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7631 uint32 immediate_data_size
, const cmds::PostSubBufferCHROMIUM
& c
) {
7632 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7634 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7636 if (!supports_post_sub_buffer_
) {
7638 GL_INVALID_OPERATION
,
7639 "glPostSubBufferCHROMIUM", "command not supported by surface");
7640 return error::kNoError
;
7643 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7646 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
7647 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
7648 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
7649 is_offscreen
? offscreen_size_
: surface_
->GetSize());
7651 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
7652 return error::kNoError
;
7654 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
7655 return error::kLostContext
;
7659 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7660 uint32 immediate_data_size
,
7661 const cmds::ScheduleOverlayPlaneCHROMIUM
& c
) {
7662 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
7664 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
7665 "glScheduleOverlayPlaneCHROMIUM",
7667 return error::kNoError
;
7669 gfx::GLImage
* image
=
7670 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
7672 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
7673 "glScheduleOverlayPlaneCHROMIUM",
7674 "unsupported texture format");
7675 return error::kNoError
;
7677 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
7678 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
7679 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
7680 "glScheduleOverlayPlaneCHROMIUM",
7681 "invalid transform enum");
7682 return error::kNoError
;
7684 if (!surface_
->ScheduleOverlayPlane(
7688 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
7689 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
7690 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
7691 "glScheduleOverlayPlaneCHROMIUM",
7692 "failed to schedule overlay");
7694 return error::kNoError
;
7697 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
7698 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7699 const std::string
& name_str
) {
7700 if (!StringIsValidForGLES(name_str
.c_str())) {
7702 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
7703 return error::kNoError
;
7705 Program
* program
= GetProgramInfoNotShader(
7706 client_id
, "glGetAttribLocation");
7708 return error::kNoError
;
7710 if (!program
->IsValid()) {
7712 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
7713 return error::kNoError
;
7715 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7716 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7718 return error::kOutOfBounds
;
7720 // Require the client to init this incase the context is lost and we are no
7721 // longer executing commands.
7722 if (*location
!= -1) {
7723 return error::kGenericError
;
7725 *location
= program
->GetAttribLocation(name_str
);
7726 return error::kNoError
;
7729 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
7730 uint32 immediate_data_size
, const cmds::GetAttribLocation
& c
) {
7731 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7733 return error::kInvalidArguments
;
7735 std::string name_str
;
7736 if (!bucket
->GetAsString(&name_str
)) {
7737 return error::kInvalidArguments
;
7739 return GetAttribLocationHelper(
7740 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7743 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
7744 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7745 const std::string
& name_str
) {
7746 if (!StringIsValidForGLES(name_str
.c_str())) {
7748 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
7749 return error::kNoError
;
7751 Program
* program
= GetProgramInfoNotShader(
7752 client_id
, "glGetUniformLocation");
7754 return error::kNoError
;
7756 if (!program
->IsValid()) {
7758 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
7759 return error::kNoError
;
7761 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7762 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7764 return error::kOutOfBounds
;
7766 // Require the client to init this incase the context is lost an we are no
7767 // longer executing commands.
7768 if (*location
!= -1) {
7769 return error::kGenericError
;
7771 *location
= program
->GetUniformFakeLocation(name_str
);
7772 return error::kNoError
;
7775 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
7776 uint32 immediate_data_size
, const cmds::GetUniformLocation
& c
) {
7777 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7779 return error::kInvalidArguments
;
7781 std::string name_str
;
7782 if (!bucket
->GetAsString(&name_str
)) {
7783 return error::kInvalidArguments
;
7785 return GetUniformLocationHelper(
7786 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7789 error::Error
GLES2DecoderImpl::HandleGetString(
7790 uint32 immediate_data_size
, const cmds::GetString
& c
) {
7791 GLenum name
= static_cast<GLenum
>(c
.name
);
7792 if (!validators_
->string_type
.IsValid(name
)) {
7793 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
7794 return error::kNoError
;
7796 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
7797 std::string extensions
;
7800 str
= "OpenGL ES 2.0 Chromium";
7802 case GL_SHADING_LANGUAGE_VERSION
:
7803 str
= "OpenGL ES GLSL ES 1.0 Chromium";
7807 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7808 // They are used by WEBGL_debug_renderer_info.
7809 if (!force_webgl_glsl_validation_
)
7814 // For WebGL contexts, strip out the OES derivatives and
7815 // EXT frag depth extensions if they have not been enabled.
7816 if (force_webgl_glsl_validation_
) {
7817 extensions
= feature_info_
->extensions();
7818 if (!derivatives_explicitly_enabled_
) {
7819 size_t offset
= extensions
.find(kOESDerivativeExtension
);
7820 if (std::string::npos
!= offset
) {
7821 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
7825 if (!frag_depth_explicitly_enabled_
) {
7826 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
7827 if (std::string::npos
!= offset
) {
7828 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
7832 if (!draw_buffers_explicitly_enabled_
) {
7833 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
7834 if (std::string::npos
!= offset
) {
7835 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
7839 if (!shader_texture_lod_explicitly_enabled_
) {
7840 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
7841 if (std::string::npos
!= offset
) {
7842 extensions
.replace(offset
,
7843 arraysize(kEXTShaderTextureLodExtension
),
7848 extensions
= feature_info_
->extensions().c_str();
7850 if (supports_post_sub_buffer_
)
7851 extensions
+= " GL_CHROMIUM_post_sub_buffer";
7852 str
= extensions
.c_str();
7858 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
7859 bucket
->SetFromString(str
);
7860 return error::kNoError
;
7863 error::Error
GLES2DecoderImpl::HandleBufferData(
7864 uint32 immediate_data_size
, const cmds::BufferData
& c
) {
7865 GLenum target
= static_cast<GLenum
>(c
.target
);
7866 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
7867 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
7868 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
7869 GLenum usage
= static_cast<GLenum
>(c
.usage
);
7870 const void* data
= NULL
;
7871 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
7872 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
7874 return error::kOutOfBounds
;
7877 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
7878 return error::kNoError
;
7881 void GLES2DecoderImpl::DoBufferSubData(
7882 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
7883 // Just delegate it. Some validation is actually done before this.
7884 buffer_manager()->ValidateAndDoBufferSubData(
7885 &state_
, target
, offset
, size
, data
);
7888 bool GLES2DecoderImpl::ClearLevel(
7889 unsigned service_id
,
7890 unsigned bind_target
,
7893 unsigned internal_format
,
7898 bool is_texture_immutable
) {
7899 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
7900 if (feature_info_
->feature_flags().angle_depth_texture
&&
7901 (channels
& GLES2Util::kDepth
) != 0) {
7902 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7903 // on depth formats.
7905 glGenFramebuffersEXT(1, &fb
);
7906 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
7908 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
7909 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
7910 GL_DEPTH_ATTACHMENT
;
7912 glFramebufferTexture2DEXT(
7913 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
7914 // ANGLE promises a depth only attachment ok.
7915 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
7916 GL_FRAMEBUFFER_COMPLETE
) {
7920 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
7921 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
7923 state_
.SetDeviceDepthMask(GL_TRUE
);
7924 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
7925 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
7927 RestoreClearState();
7929 glDeleteFramebuffersEXT(1, &fb
);
7930 Framebuffer
* framebuffer
=
7931 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
7932 GLuint fb_service_id
=
7933 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
7934 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
7938 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
7941 uint32 padded_row_size
;
7942 if (!GLES2Util::ComputeImageDataSizes(
7943 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
7944 NULL
, &padded_row_size
)) {
7948 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
7952 if (size
> kMaxZeroSize
) {
7953 if (kMaxZeroSize
< padded_row_size
) {
7954 // That'd be an awfully large texture.
7957 // We should never have a large total size with a zero row size.
7958 DCHECK_GT(padded_row_size
, 0U);
7959 tile_height
= kMaxZeroSize
/ padded_row_size
;
7960 if (!GLES2Util::ComputeImageDataSizes(
7961 width
, tile_height
, format
, type
, state_
.unpack_alignment
, &size
,
7966 tile_height
= height
;
7969 // Assumes the size has already been checked.
7970 scoped_ptr
<char[]> zero(new char[size
]);
7971 memset(zero
.get(), 0, size
);
7972 glBindTexture(bind_target
, service_id
);
7975 while (y
< height
) {
7976 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
7977 if (is_texture_immutable
|| h
!= height
) {
7978 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
7981 target
, level
, internal_format
, width
, h
, 0, format
, type
,
7986 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
7987 &state_
, bind_target
);
7988 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
7994 const int kS3TCBlockWidth
= 4;
7995 const int kS3TCBlockHeight
= 4;
7996 const int kS3TCDXT1BlockSize
= 8;
7997 const int kS3TCDXT3AndDXT5BlockSize
= 16;
7999 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8000 return (size
== 1) ||
8001 (size
== 2) || !(size
% kS3TCBlockWidth
);
8004 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8005 return GLES2Util::IsPOT(size
);
8008 } // anonymous namespace.
8010 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8011 const char* function_name
,
8012 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
8013 unsigned int bytes_required
= 0;
8016 case GL_ATC_RGB_AMD
:
8017 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8018 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8019 case GL_ETC1_RGB8_OES
: {
8020 int num_blocks_across
=
8021 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8022 int num_blocks_down
=
8023 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8024 int num_blocks
= num_blocks_across
* num_blocks_down
;
8025 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
8028 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8029 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8030 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8031 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8032 int num_blocks_across
=
8033 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8034 int num_blocks_down
=
8035 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8036 int num_blocks
= num_blocks_across
* num_blocks_down
;
8037 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
8040 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8041 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
8042 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
8045 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8046 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8047 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
8051 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8055 if (size
!= bytes_required
) {
8057 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8064 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8065 const char* function_name
,
8066 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
8068 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8069 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8070 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8071 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8072 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8074 GL_INVALID_OPERATION
, function_name
,
8075 "width or height invalid for level");
8080 case GL_ATC_RGB_AMD
:
8081 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8082 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8083 case GL_ETC1_RGB8_OES
: {
8084 if (width
<= 0 || height
<= 0) {
8086 GL_INVALID_OPERATION
, function_name
,
8087 "width or height invalid for level");
8092 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8093 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8094 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8095 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8096 if (!IsValidPVRTCSize(level
, width
) ||
8097 !IsValidPVRTCSize(level
, height
)) {
8099 GL_INVALID_OPERATION
, function_name
,
8100 "width or height invalid for level");
8110 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8111 const char* function_name
,
8112 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8113 GLsizei width
, GLsizei height
, GLenum format
,
8115 if (xoffset
< 0 || yoffset
< 0) {
8117 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8122 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8123 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8124 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8125 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8126 const int kBlockWidth
= 4;
8127 const int kBlockHeight
= 4;
8128 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8130 GL_INVALID_OPERATION
, function_name
,
8131 "xoffset or yoffset not multiple of 4");
8134 GLsizei tex_width
= 0;
8135 GLsizei tex_height
= 0;
8136 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8137 width
- xoffset
> tex_width
||
8138 height
- yoffset
> tex_height
) {
8140 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8143 return ValidateCompressedTexDimensions(
8144 function_name
, level
, width
, height
, format
);
8146 case GL_ATC_RGB_AMD
:
8147 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8148 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8150 GL_INVALID_OPERATION
, function_name
,
8151 "not supported for ATC textures");
8154 case GL_ETC1_RGB8_OES
: {
8156 GL_INVALID_OPERATION
, function_name
,
8157 "not supported for ECT1_RGB8_OES textures");
8160 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8161 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8162 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8163 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8164 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8166 GL_INVALID_OPERATION
, function_name
,
8167 "xoffset and yoffset must be zero");
8170 GLsizei tex_width
= 0;
8171 GLsizei tex_height
= 0;
8172 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8173 width
!= tex_width
||
8174 height
!= tex_height
) {
8176 GL_INVALID_OPERATION
, function_name
,
8177 "dimensions must match existing texture level dimensions");
8180 return ValidateCompressedTexDimensions(
8181 function_name
, level
, width
, height
, format
);
8188 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8191 GLenum internal_format
,
8197 // TODO(gman): Validate image_size is correct for width, height and format.
8198 if (!validators_
->texture_target
.IsValid(target
)) {
8199 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8200 "glCompressedTexImage2D", target
, "target");
8201 return error::kNoError
;
8203 if (!validators_
->compressed_texture_format
.IsValid(
8205 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8206 "glCompressedTexImage2D", internal_format
, "internal_format");
8207 return error::kNoError
;
8209 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8213 "glCompressedTexImage2D", "dimensions out of range");
8214 return error::kNoError
;
8216 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8221 "glCompressedTexImage2D", "unknown texture target");
8222 return error::kNoError
;
8224 Texture
* texture
= texture_ref
->texture();
8225 if (texture
->IsImmutable()) {
8227 GL_INVALID_OPERATION
,
8228 "glCompressedTexImage2D", "texture is immutable");
8229 return error::kNoError
;
8232 if (!ValidateCompressedTexDimensions(
8233 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8234 !ValidateCompressedTexFuncData(
8235 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8236 return error::kNoError
;
8239 if (!EnsureGPUMemoryAvailable(image_size
)) {
8241 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8242 return error::kNoError
;
8245 if (texture
->IsAttachedToFramebuffer()) {
8246 framebuffer_state_
.clear_state_dirty
= true;
8249 scoped_ptr
<int8
[]> zero
;
8251 zero
.reset(new int8
[image_size
]);
8252 memset(zero
.get(), 0, image_size
);
8255 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8256 glCompressedTexImage2D(
8257 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8258 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8259 if (error
== GL_NO_ERROR
) {
8260 texture_manager()->SetLevelInfo(
8261 texture_ref
, target
, level
, internal_format
,
8262 width
, height
, 1, border
, 0, 0, true);
8264 return error::kNoError
;
8267 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8268 uint32 immediate_data_size
, const cmds::CompressedTexImage2D
& c
) {
8269 GLenum target
= static_cast<GLenum
>(c
.target
);
8270 GLint level
= static_cast<GLint
>(c
.level
);
8271 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8272 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8273 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8274 GLint border
= static_cast<GLint
>(c
.border
);
8275 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8276 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8277 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8278 const void* data
= NULL
;
8279 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8280 data
= GetSharedMemoryAs
<const void*>(
8281 data_shm_id
, data_shm_offset
, image_size
);
8283 return error::kOutOfBounds
;
8286 return DoCompressedTexImage2D(
8287 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8290 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8291 uint32 immediate_data_size
, const cmds::CompressedTexImage2DBucket
& c
) {
8292 GLenum target
= static_cast<GLenum
>(c
.target
);
8293 GLint level
= static_cast<GLint
>(c
.level
);
8294 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8295 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8296 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8297 GLint border
= static_cast<GLint
>(c
.border
);
8298 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8300 return error::kInvalidArguments
;
8302 uint32 data_size
= bucket
->size();
8303 GLsizei imageSize
= data_size
;
8304 const void* data
= bucket
->GetData(0, data_size
);
8306 return error::kInvalidArguments
;
8308 return DoCompressedTexImage2D(
8309 target
, level
, internal_format
, width
, height
, border
,
8313 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8314 uint32 immediate_data_size
,
8315 const cmds::CompressedTexSubImage2DBucket
& c
) {
8316 GLenum target
= static_cast<GLenum
>(c
.target
);
8317 GLint level
= static_cast<GLint
>(c
.level
);
8318 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8319 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8320 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8321 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8322 GLenum format
= static_cast<GLenum
>(c
.format
);
8323 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8325 return error::kInvalidArguments
;
8327 uint32 data_size
= bucket
->size();
8328 GLsizei imageSize
= data_size
;
8329 const void* data
= bucket
->GetData(0, data_size
);
8331 return error::kInvalidArguments
;
8333 if (!validators_
->texture_target
.IsValid(target
)) {
8335 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8336 return error::kNoError
;
8338 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8339 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8340 "glCompressedTexSubImage2D", format
, "format");
8341 return error::kNoError
;
8345 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8346 return error::kNoError
;
8350 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8351 return error::kNoError
;
8353 if (imageSize
< 0) {
8355 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8356 return error::kNoError
;
8358 DoCompressedTexSubImage2D(
8359 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8360 return error::kNoError
;
8363 error::Error
GLES2DecoderImpl::HandleTexImage2D(
8364 uint32 immediate_data_size
, const cmds::TexImage2D
& c
) {
8365 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8366 "width", c
.width
, "height", c
.height
);
8367 // Set as failed for now, but if it successed, this will be set to not failed.
8368 texture_state_
.tex_image_2d_failed
= true;
8369 GLenum target
= static_cast<GLenum
>(c
.target
);
8370 GLint level
= static_cast<GLint
>(c
.level
);
8371 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8372 // for internalformat.
8373 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8374 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8375 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8376 GLint border
= static_cast<GLint
>(c
.border
);
8377 GLenum format
= static_cast<GLenum
>(c
.format
);
8378 GLenum type
= static_cast<GLenum
>(c
.type
);
8379 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8380 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8382 if (!GLES2Util::ComputeImageDataSizes(
8383 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
8385 return error::kOutOfBounds
;
8387 const void* pixels
= NULL
;
8388 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8389 pixels
= GetSharedMemoryAs
<const void*>(
8390 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8392 return error::kOutOfBounds
;
8396 TextureManager::DoTextImage2DArguments args
= {
8397 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8398 pixels
, pixels_size
};
8399 texture_manager()->ValidateAndDoTexImage2D(
8400 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8401 return error::kNoError
;
8404 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8413 const void * data
) {
8414 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8418 GL_INVALID_OPERATION
,
8419 "glCompressedTexSubImage2D", "unknown texture for target");
8422 Texture
* texture
= texture_ref
->texture();
8424 GLenum internal_format
= 0;
8425 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
8427 GL_INVALID_OPERATION
,
8428 "glCompressedTexSubImage2D", "level does not exist.");
8431 if (internal_format
!= format
) {
8433 GL_INVALID_OPERATION
,
8434 "glCompressedTexSubImage2D", "format does not match internal format.");
8437 if (!texture
->ValidForTexture(
8438 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8440 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8444 if (!ValidateCompressedTexFuncData(
8445 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8446 !ValidateCompressedTexSubDimensions(
8447 "glCompressedTexSubImage2D",
8448 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8453 // Note: There is no need to deal with texture cleared tracking here
8454 // because the validation above means you can only get here if the level
8455 // is already a matching compressed format and in that case
8456 // CompressedTexImage2D already cleared the texture.
8457 glCompressedTexSubImage2D(
8458 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8462 GLint start
, GLint range
, GLint sourceRange
,
8463 GLint
* out_start
, GLint
* out_range
) {
8470 GLint end
= start
+ range
;
8471 if (end
> sourceRange
) {
8472 range
-= end
- sourceRange
;
8478 void GLES2DecoderImpl::DoCopyTexImage2D(
8481 GLenum internal_format
,
8487 DCHECK(!ShouldDeferReads());
8488 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8492 GL_INVALID_OPERATION
,
8493 "glCopyTexImage2D", "unknown texture for target");
8496 Texture
* texture
= texture_ref
->texture();
8497 if (texture
->IsImmutable()) {
8499 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8502 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8505 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8508 if (!texture_manager()->ValidateFormatAndTypeCombination(
8509 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
8510 GL_UNSIGNED_BYTE
)) {
8514 // Check we have compatible formats.
8515 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8516 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8517 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
8519 if ((channels_needed
& channels_exist
) != channels_needed
) {
8521 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
8525 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8527 GL_INVALID_OPERATION
,
8528 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8532 uint32 estimated_size
= 0;
8533 if (!GLES2Util::ComputeImageDataSizes(
8534 width
, height
, internal_format
, GL_UNSIGNED_BYTE
, state_
.unpack_alignment
,
8535 &estimated_size
, NULL
, NULL
)) {
8537 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
8541 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
8542 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
8546 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8550 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8554 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8555 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8556 gfx::Size size
= GetBoundReadFrameBufferSize();
8558 if (texture
->IsAttachedToFramebuffer()) {
8559 framebuffer_state_
.clear_state_dirty
= true;
8562 // Clip to size to source dimensions
8565 GLint copyWidth
= 0;
8566 GLint copyHeight
= 0;
8567 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8568 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8572 copyWidth
!= width
||
8573 copyHeight
!= height
) {
8574 // some part was clipped so clear the texture.
8576 texture
->service_id(), texture
->target(),
8577 target
, level
, internal_format
, internal_format
, GL_UNSIGNED_BYTE
,
8578 width
, height
, texture
->IsImmutable())) {
8580 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
8583 if (copyHeight
> 0 && copyWidth
> 0) {
8584 GLint dx
= copyX
- x
;
8585 GLint dy
= copyY
- y
;
8588 ScopedModifyPixels
modify(texture_ref
);
8589 glCopyTexSubImage2D(target
, level
,
8590 destX
, destY
, copyX
, copyY
,
8591 copyWidth
, copyHeight
);
8594 ScopedModifyPixels
modify(texture_ref
);
8595 glCopyTexImage2D(target
, level
, internal_format
,
8596 copyX
, copyY
, copyWidth
, copyHeight
, border
);
8598 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8599 if (error
== GL_NO_ERROR
) {
8600 texture_manager()->SetLevelInfo(
8601 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
8602 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
8606 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8615 DCHECK(!ShouldDeferReads());
8616 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8620 GL_INVALID_OPERATION
,
8621 "glCopyTexSubImage2D", "unknown texture for target");
8624 Texture
* texture
= texture_ref
->texture();
8627 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
8628 !texture
->ValidForTexture(
8629 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8631 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
8634 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8636 GL_INVALID_OPERATION
,
8637 "glCopyTexSubImage2D", "async upload pending for texture");
8641 // Check we have compatible formats.
8642 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8643 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8644 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
8646 if (!channels_needed
||
8647 (channels_needed
& channels_exist
) != channels_needed
) {
8649 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
8653 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8655 GL_INVALID_OPERATION
,
8656 "glCopySubImage2D", "can not be used with depth or stencil textures");
8660 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8664 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8668 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8669 gfx::Size size
= GetBoundReadFrameBufferSize();
8672 GLint copyWidth
= 0;
8673 GLint copyHeight
= 0;
8674 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8675 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8677 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, level
)) {
8679 GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D", "dimensions too big");
8685 copyWidth
!= width
||
8686 copyHeight
!= height
) {
8687 // some part was clipped so clear the sub rect.
8688 uint32 pixels_size
= 0;
8689 if (!GLES2Util::ComputeImageDataSizes(
8690 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8693 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
8696 scoped_ptr
<char[]> zero(new char[pixels_size
]);
8697 memset(zero
.get(), 0, pixels_size
);
8698 ScopedModifyPixels
modify(texture_ref
);
8700 target
, level
, xoffset
, yoffset
, width
, height
,
8701 format
, type
, zero
.get());
8704 if (copyHeight
> 0 && copyWidth
> 0) {
8705 GLint dx
= copyX
- x
;
8706 GLint dy
= copyY
- y
;
8707 GLint destX
= xoffset
+ dx
;
8708 GLint destY
= yoffset
+ dy
;
8709 ScopedModifyPixels
modify(texture_ref
);
8710 glCopyTexSubImage2D(target
, level
,
8711 destX
, destY
, copyX
, copyY
,
8712 copyWidth
, copyHeight
);
8716 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8717 error::Error
* error
,
8718 const char* function_name
,
8727 const void * data
) {
8728 (*error
) = error::kNoError
;
8729 if (!validators_
->texture_target
.IsValid(target
)) {
8730 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
8734 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
8738 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
8741 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8745 GL_INVALID_OPERATION
,
8746 function_name
, "unknown texture for target");
8749 Texture
* texture
= texture_ref
->texture();
8750 GLenum current_type
= 0;
8751 GLenum internal_format
= 0;
8752 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
8754 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
8757 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
8758 function_name
, format
, type
, internal_format
, level
)) {
8761 if (type
!= current_type
) {
8763 GL_INVALID_OPERATION
,
8764 function_name
, "type does not match type of texture.");
8767 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8769 GL_INVALID_OPERATION
,
8770 function_name
, "async upload pending for texture");
8773 if (!texture
->ValidForTexture(
8774 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8775 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
8778 if ((GLES2Util::GetChannelsForFormat(format
) &
8779 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8781 GL_INVALID_OPERATION
,
8782 function_name
, "can not supply data for depth or stencil textures");
8786 (*error
) = error::kOutOfBounds
;
8792 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
8801 const void * data
) {
8802 error::Error error
= error::kNoError
;
8803 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
8804 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
8807 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8809 Texture
* texture
= texture_ref
->texture();
8810 GLsizei tex_width
= 0;
8811 GLsizei tex_height
= 0;
8812 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
8814 if (xoffset
!= 0 || yoffset
!= 0 ||
8815 width
!= tex_width
|| height
!= tex_height
) {
8816 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
8819 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
8820 return error::kNoError
;
8822 ScopedTextureUploadTimer
timer(&texture_state_
);
8824 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8825 return error::kNoError
;
8828 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
8829 !texture
->IsImmutable()) {
8830 ScopedTextureUploadTimer
timer(&texture_state_
);
8831 GLenum internal_format
;
8833 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
8834 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8837 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
8839 ScopedTextureUploadTimer
timer(&texture_state_
);
8841 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8843 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
8844 return error::kNoError
;
8847 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(
8848 uint32 immediate_data_size
, const cmds::TexSubImage2D
& c
) {
8849 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8850 "width", c
.width
, "height", c
.height
);
8851 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
8852 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
8853 return error::kNoError
;
8855 GLenum target
= static_cast<GLenum
>(c
.target
);
8856 GLint level
= static_cast<GLint
>(c
.level
);
8857 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8858 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8859 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8860 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8861 GLenum format
= static_cast<GLenum
>(c
.format
);
8862 GLenum type
= static_cast<GLenum
>(c
.type
);
8864 if (!GLES2Util::ComputeImageDataSizes(
8865 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
8867 return error::kOutOfBounds
;
8869 const void* pixels
= GetSharedMemoryAs
<const void*>(
8870 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
8871 return DoTexSubImage2D(
8872 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
8875 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8876 uint32 immediate_data_size
, const cmds::GetVertexAttribPointerv
& c
) {
8877 GLuint index
= static_cast<GLuint
>(c
.index
);
8878 GLenum pname
= static_cast<GLenum
>(c
.pname
);
8879 typedef cmds::GetVertexAttribPointerv::Result Result
;
8880 Result
* result
= GetSharedMemoryAs
<Result
*>(
8881 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
8883 return error::kOutOfBounds
;
8885 // Check that the client initialized the result.
8886 if (result
->size
!= 0) {
8887 return error::kInvalidArguments
;
8889 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
8890 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8891 "glGetVertexAttribPointerv", pname
, "pname");
8892 return error::kNoError
;
8894 if (index
>= group_
->max_vertex_attribs()) {
8896 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
8897 return error::kNoError
;
8899 result
->SetNumResults(1);
8900 *result
->GetData() =
8901 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
8902 return error::kNoError
;
8905 bool GLES2DecoderImpl::GetUniformSetup(
8906 GLuint program_id
, GLint fake_location
,
8907 uint32 shm_id
, uint32 shm_offset
,
8908 error::Error
* error
, GLint
* real_location
,
8909 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
8912 DCHECK(result_pointer
);
8913 DCHECK(result_type
);
8914 DCHECK(real_location
);
8915 *error
= error::kNoError
;
8916 // Make sure we have enough room for the result on failure.
8917 SizedResult
<GLint
>* result
;
8918 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8919 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
8921 *error
= error::kOutOfBounds
;
8924 *result_pointer
= result
;
8925 // Set the result size to 0 so the client does not have to check for success.
8926 result
->SetNumResults(0);
8927 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
8931 if (!program
->IsValid()) {
8932 // Program was not linked successfully. (ie, glLinkProgram)
8934 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
8937 *service_id
= program
->service_id();
8938 GLint array_index
= -1;
8939 const Program::UniformInfo
* uniform_info
=
8940 program
->GetUniformInfoByFakeLocation(
8941 fake_location
, real_location
, &array_index
);
8942 if (!uniform_info
) {
8943 // No such location.
8945 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
8948 GLenum type
= uniform_info
->type
;
8949 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
8951 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
8954 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8955 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
8957 *error
= error::kOutOfBounds
;
8960 result
->size
= size
;
8961 *result_type
= type
;
8965 error::Error
GLES2DecoderImpl::HandleGetUniformiv(
8966 uint32 immediate_data_size
, const cmds::GetUniformiv
& c
) {
8967 GLuint program
= c
.program
;
8968 GLint fake_location
= c
.location
;
8971 GLint real_location
= -1;
8974 if (GetUniformSetup(
8975 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8976 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
8978 service_id
, real_location
,
8979 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
8984 error::Error
GLES2DecoderImpl::HandleGetUniformfv(
8985 uint32 immediate_data_size
, const cmds::GetUniformfv
& c
) {
8986 GLuint program
= c
.program
;
8987 GLint fake_location
= c
.location
;
8989 GLint real_location
= -1;
8991 typedef cmds::GetUniformfv::Result Result
;
8994 if (GetUniformSetup(
8995 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8996 &error
, &real_location
, &service_id
,
8997 reinterpret_cast<void**>(&result
), &result_type
)) {
8998 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
8999 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
9000 GLsizei num_values
= result
->GetNumResults();
9001 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
9002 glGetUniformiv(service_id
, real_location
, temp
.get());
9003 GLfloat
* dst
= result
->GetData();
9004 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
9005 dst
[ii
] = (temp
[ii
] != 0);
9008 glGetUniformfv(service_id
, real_location
, result
->GetData());
9014 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9015 uint32 immediate_data_size
, const cmds::GetShaderPrecisionFormat
& c
) {
9016 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
9017 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
9018 typedef cmds::GetShaderPrecisionFormat::Result Result
;
9019 Result
* result
= GetSharedMemoryAs
<Result
*>(
9020 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9022 return error::kOutOfBounds
;
9024 // Check that the client initialized the result.
9025 if (result
->success
!= 0) {
9026 return error::kInvalidArguments
;
9028 if (!validators_
->shader_type
.IsValid(shader_type
)) {
9029 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9030 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
9031 return error::kNoError
;
9033 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
9034 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9035 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
9036 return error::kNoError
;
9039 result
->success
= 1; // true
9041 GLint range
[2] = { 0, 0 };
9042 GLint precision
= 0;
9043 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
9045 result
->min_range
= range
[0];
9046 result
->max_range
= range
[1];
9047 result
->precision
= precision
;
9049 return error::kNoError
;
9052 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
9053 uint32 immediate_data_size
, const cmds::GetAttachedShaders
& c
) {
9054 uint32 result_size
= c
.result_size
;
9055 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9056 Program
* program
= GetProgramInfoNotShader(
9057 program_id
, "glGetAttachedShaders");
9059 return error::kNoError
;
9061 typedef cmds::GetAttachedShaders::Result Result
;
9062 uint32 max_count
= Result::ComputeMaxResults(result_size
);
9063 Result
* result
= GetSharedMemoryAs
<Result
*>(
9064 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
9066 return error::kOutOfBounds
;
9068 // Check that the client initialized the result.
9069 if (result
->size
!= 0) {
9070 return error::kInvalidArguments
;
9073 glGetAttachedShaders(
9074 program
->service_id(), max_count
, &count
, result
->GetData());
9075 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
9076 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
9077 &result
->GetData()[ii
])) {
9079 return error::kGenericError
;
9082 result
->SetNumResults(count
);
9083 return error::kNoError
;
9086 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
9087 uint32 immediate_data_size
, const cmds::GetActiveUniform
& c
) {
9088 GLuint program_id
= c
.program
;
9089 GLuint index
= c
.index
;
9090 uint32 name_bucket_id
= c
.name_bucket_id
;
9091 typedef cmds::GetActiveUniform::Result Result
;
9092 Result
* result
= GetSharedMemoryAs
<Result
*>(
9093 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9095 return error::kOutOfBounds
;
9097 // Check that the client initialized the result.
9098 if (result
->success
!= 0) {
9099 return error::kInvalidArguments
;
9101 Program
* program
= GetProgramInfoNotShader(
9102 program_id
, "glGetActiveUniform");
9104 return error::kNoError
;
9106 const Program::UniformInfo
* uniform_info
=
9107 program
->GetUniformInfo(index
);
9108 if (!uniform_info
) {
9110 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
9111 return error::kNoError
;
9113 result
->success
= 1; // true.
9114 result
->size
= uniform_info
->size
;
9115 result
->type
= uniform_info
->type
;
9116 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9117 bucket
->SetFromString(uniform_info
->name
.c_str());
9118 return error::kNoError
;
9121 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(
9122 uint32 immediate_data_size
, const cmds::GetActiveAttrib
& c
) {
9123 GLuint program_id
= c
.program
;
9124 GLuint index
= c
.index
;
9125 uint32 name_bucket_id
= c
.name_bucket_id
;
9126 typedef cmds::GetActiveAttrib::Result Result
;
9127 Result
* result
= GetSharedMemoryAs
<Result
*>(
9128 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9130 return error::kOutOfBounds
;
9132 // Check that the client initialized the result.
9133 if (result
->success
!= 0) {
9134 return error::kInvalidArguments
;
9136 Program
* program
= GetProgramInfoNotShader(
9137 program_id
, "glGetActiveAttrib");
9139 return error::kNoError
;
9141 const Program::VertexAttrib
* attrib_info
=
9142 program
->GetAttribInfo(index
);
9145 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9146 return error::kNoError
;
9148 result
->success
= 1; // true.
9149 result
->size
= attrib_info
->size
;
9150 result
->type
= attrib_info
->type
;
9151 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9152 bucket
->SetFromString(attrib_info
->name
.c_str());
9153 return error::kNoError
;
9156 error::Error
GLES2DecoderImpl::HandleShaderBinary(
9157 uint32 immediate_data_size
, const cmds::ShaderBinary
& c
) {
9158 #if 1 // No binary shader support.
9159 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
9160 return error::kNoError
;
9162 GLsizei n
= static_cast<GLsizei
>(c
.n
);
9164 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
9165 return error::kNoError
;
9167 GLsizei length
= static_cast<GLsizei
>(c
.length
);
9169 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
9170 return error::kNoError
;
9173 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
9174 return error::kOutOfBounds
;
9176 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
9177 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
9178 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
9179 const void* binary
= GetSharedMemoryAs
<const void*>(
9180 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
9181 if (shaders
== NULL
|| binary
== NULL
) {
9182 return error::kOutOfBounds
;
9184 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9185 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9186 Shader
* shader
= GetShader(shaders
[ii
]);
9188 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
9189 return error::kNoError
;
9191 service_ids
[ii
] = shader
->service_id();
9193 // TODO(gman): call glShaderBinary
9194 return error::kNoError
;
9198 void GLES2DecoderImpl::DoSwapBuffers() {
9199 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9201 int this_frame_number
= frame_number_
++;
9202 // TRACE_EVENT for gpu tests:
9203 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9204 TRACE_EVENT_SCOPE_THREAD
,
9205 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9206 "width", (is_offscreen
? offscreen_size_
.width() :
9207 surface_
->GetSize().width()));
9208 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9209 "offscreen", is_offscreen
,
9210 "frame", this_frame_number
);
9212 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9216 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9219 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9220 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9221 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9224 // If offscreen then don't actually SwapBuffers to the display. Just copy
9225 // the rendered frame to another frame buffer.
9227 TRACE_EVENT2("gpu", "Offscreen",
9228 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
9229 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
9230 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9231 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9233 if (workarounds().needs_offscreen_buffer_workaround
) {
9234 offscreen_saved_frame_buffer_
->Create();
9238 // Allocate the offscreen saved color texture.
9239 DCHECK(offscreen_saved_color_format_
);
9240 offscreen_saved_color_texture_
->AllocateStorage(
9241 offscreen_size_
, offscreen_saved_color_format_
, false);
9243 offscreen_saved_frame_buffer_
->AttachRenderTexture(
9244 offscreen_saved_color_texture_
.get());
9245 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
9246 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
9247 GL_FRAMEBUFFER_COMPLETE
) {
9248 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9249 << "because offscreen saved FBO was incomplete.";
9250 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9254 // Clear the offscreen color texture.
9255 // TODO(piman): Is this still necessary?
9257 ScopedFrameBufferBinder
binder(this,
9258 offscreen_saved_frame_buffer_
->id());
9259 glClearColor(0, 0, 0, 0);
9260 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
9261 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
9262 glClear(GL_COLOR_BUFFER_BIT
);
9263 RestoreClearState();
9267 UpdateParentTextureInfo();
9270 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
9272 ScopedGLErrorSuppressor
suppressor(
9273 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9275 if (IsOffscreenBufferMultisampled()) {
9276 // For multisampled buffers, resolve the frame buffer.
9277 ScopedResolvedFrameBufferBinder
binder(this, true, false);
9279 ScopedFrameBufferBinder
binder(this,
9280 offscreen_target_frame_buffer_
->id());
9282 if (offscreen_target_buffer_preserved_
) {
9283 // Copy the target frame buffer to the saved offscreen texture.
9284 offscreen_saved_color_texture_
->Copy(
9285 offscreen_saved_color_texture_
->size(),
9286 offscreen_saved_color_format_
);
9288 // Flip the textures in the parent context via the texture manager.
9289 if (!!offscreen_saved_color_texture_info_
.get())
9290 offscreen_saved_color_texture_info_
->texture()->
9291 SetServiceId(offscreen_target_color_texture_
->id());
9293 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
9294 offscreen_target_frame_buffer_
->AttachRenderTexture(
9295 offscreen_target_color_texture_
.get());
9298 // Ensure the side effects of the copy are visible to the parent
9299 // context. There is no need to do this for ANGLE because it uses a
9300 // single D3D device for all contexts.
9301 if (!feature_info_
->feature_flags().is_angle
)
9305 if (!surface_
->SwapBuffers()) {
9306 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
9307 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9312 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9313 uint32 immediate_data_size
, const cmds::EnableFeatureCHROMIUM
& c
) {
9314 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9315 if (!bucket
|| bucket
->size() == 0) {
9316 return error::kInvalidArguments
;
9318 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
9319 Result
* result
= GetSharedMemoryAs
<Result
*>(
9320 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9322 return error::kOutOfBounds
;
9324 // Check that the client initialized the result.
9326 return error::kInvalidArguments
;
9328 std::string feature_str
;
9329 if (!bucket
->GetAsString(&feature_str
)) {
9330 return error::kInvalidArguments
;
9333 // TODO(gman): make this some kind of table to function pointer thingy.
9334 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9335 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9336 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
9337 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9338 // TODO(gman): decide how to remove the need for this const_cast.
9339 // I could make validators_ non const but that seems bad as this is the only
9340 // place it is needed. I could make some special friend class of validators
9341 // just to allow this to set them. That seems silly. I could refactor this
9342 // code to use the extension mechanism or the initialization attributes to
9343 // turn this feature on. Given that the only real point of this is to make
9344 // the conformance tests pass and given that there is lots of real work that
9345 // needs to be done it seems like refactoring for one to one of those
9346 // methods is a very low priority.
9347 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
9348 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
9349 force_webgl_glsl_validation_
= true;
9350 InitializeShaderTranslator();
9352 return error::kNoError
;
9355 *result
= 1; // true.
9356 return error::kNoError
;
9359 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9360 uint32 immediate_data_size
,
9361 const cmds::GetRequestableExtensionsCHROMIUM
& c
) {
9362 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9363 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
9364 info
->Initialize(disallowed_features_
);
9365 bucket
->SetFromString(info
->extensions().c_str());
9366 return error::kNoError
;
9369 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9370 uint32 immediate_data_size
, const cmds::RequestExtensionCHROMIUM
& c
) {
9371 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9372 if (!bucket
|| bucket
->size() == 0) {
9373 return error::kInvalidArguments
;
9375 std::string feature_str
;
9376 if (!bucket
->GetAsString(&feature_str
)) {
9377 return error::kInvalidArguments
;
9380 bool desire_webgl_glsl_validation
=
9381 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
9382 bool desire_standard_derivatives
= false;
9383 bool desire_frag_depth
= false;
9384 bool desire_draw_buffers
= false;
9385 bool desire_shader_texture_lod
= false;
9386 if (force_webgl_glsl_validation_
) {
9387 desire_standard_derivatives
=
9388 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
9390 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
9391 desire_draw_buffers
=
9392 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
9393 desire_shader_texture_lod
=
9394 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
9397 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
9398 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
9399 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
9400 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
9401 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
9402 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
9403 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
9404 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
9405 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
9406 InitializeShaderTranslator();
9409 UpdateCapabilities();
9411 return error::kNoError
;
9414 error::Error
GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9415 uint32 immediate_data_size
, const cmds::GetMultipleIntegervCHROMIUM
& c
) {
9416 GLuint count
= c
.count
;
9418 if (!SafeMultiplyUint32(count
, sizeof(GLenum
), &pnames_size
)) {
9419 return error::kOutOfBounds
;
9421 const GLenum
* pnames
= GetSharedMemoryAs
<const GLenum
*>(
9422 c
.pnames_shm_id
, c
.pnames_shm_offset
, pnames_size
);
9423 if (pnames
== NULL
) {
9424 return error::kOutOfBounds
;
9427 // We have to copy them since we use them twice so the client
9428 // can't change them between the time we validate them and the time we use
9430 scoped_ptr
<GLenum
[]> enums(new GLenum
[count
]);
9431 memcpy(enums
.get(), pnames
, pnames_size
);
9433 // Count up the space needed for the result.
9434 uint32 num_results
= 0;
9435 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9436 uint32 num
= util_
.GLGetNumValuesReturned(enums
[ii
]);
9438 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9439 "glGetMultipleCHROMIUM", enums
[ii
], "pname");
9440 return error::kNoError
;
9442 // Num will never be more than 4.
9444 if (!SafeAddUint32(num_results
, num
, &num_results
)) {
9445 return error::kOutOfBounds
;
9449 uint32 result_size
= 0;
9450 if (!SafeMultiplyUint32(num_results
, sizeof(GLint
), &result_size
)) {
9451 return error::kOutOfBounds
;
9454 if (result_size
!= static_cast<uint32
>(c
.size
)) {
9457 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9458 return error::kNoError
;
9461 GLint
* results
= GetSharedMemoryAs
<GLint
*>(
9462 c
.results_shm_id
, c
.results_shm_offset
, result_size
);
9463 if (results
== NULL
) {
9464 return error::kOutOfBounds
;
9467 // Check the results have been cleared in case the context was lost.
9468 for (uint32 ii
= 0; ii
< num_results
; ++ii
) {
9470 return error::kInvalidArguments
;
9475 GLint
* start
= results
;
9476 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9477 GLsizei num_written
= 0;
9478 if (!state_
.GetStateAsGLint(enums
[ii
], results
, &num_written
) &&
9479 !GetHelper(enums
[ii
], results
, &num_written
)) {
9480 DoGetIntegerv(enums
[ii
], results
);
9482 results
+= num_written
;
9485 // Just to verify. Should this be a DCHECK?
9486 if (static_cast<uint32
>(results
- start
) != num_results
) {
9487 return error::kOutOfBounds
;
9490 return error::kNoError
;
9493 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9494 uint32 immediate_data_size
, const cmds::GetProgramInfoCHROMIUM
& c
) {
9495 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9496 uint32 bucket_id
= c
.bucket_id
;
9497 Bucket
* bucket
= CreateBucket(bucket_id
);
9498 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
9499 Program
* program
= NULL
;
9500 program
= GetProgram(program_id
);
9501 if (!program
|| !program
->IsValid()) {
9502 return error::kNoError
;
9504 program
->GetProgramInfo(program_manager(), bucket
);
9505 return error::kNoError
;
9508 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
9509 switch (reset_status_
) {
9511 // TODO(kbr): improve the precision of the error code in this case.
9512 // Consider delegating to context for error code if MakeCurrent fails.
9513 return error::kUnknown
;
9514 case GL_GUILTY_CONTEXT_RESET_ARB
:
9515 return error::kGuilty
;
9516 case GL_INNOCENT_CONTEXT_RESET_ARB
:
9517 return error::kInnocent
;
9518 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
9519 return error::kUnknown
;
9523 return error::kUnknown
;
9526 bool GLES2DecoderImpl::WasContextLost() {
9527 if (reset_status_
!= GL_NO_ERROR
) {
9530 if (context_
->WasAllocatedUsingRobustnessExtension()) {
9531 GLenum status
= GL_NO_ERROR
;
9532 if (has_robustness_extension_
)
9533 status
= glGetGraphicsResetStatusARB();
9534 if (status
!= GL_NO_ERROR
) {
9535 // The graphics card was reset. Signal a lost context to the application.
9536 reset_status_
= status
;
9537 reset_by_robustness_extension_
= true;
9538 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
9539 << " context lost via ARB/EXT_robustness. Reset status = "
9540 << GLES2Util::GetStringEnum(status
);
9547 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9548 return WasContextLost() && reset_by_robustness_extension_
;
9551 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
9552 // Only loses the context once.
9553 if (reset_status_
!= GL_NO_ERROR
) {
9557 // Marks this context as lost.
9558 reset_status_
= reset_status
;
9559 current_decoder_error_
= error::kLostContext
;
9562 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9563 uint32 immediate_data_size
, const cmds::InsertSyncPointCHROMIUM
& c
) {
9564 return error::kUnknownCommand
;
9567 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9568 uint32 immediate_data_size
, const cmds::WaitSyncPointCHROMIUM
& c
) {
9569 group_
->mailbox_manager()->PullTextureUpdates();
9570 if (wait_sync_point_callback_
.is_null())
9571 return error::kNoError
;
9573 return wait_sync_point_callback_
.Run(c
.sync_point
) ?
9574 error::kNoError
: error::kDeferCommandUntilLater
;
9577 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9578 uint32 immediate_data_size
, const cmds::DiscardBackbufferCHROMIUM
& c
) {
9579 if (surface_
->DeferDraws())
9580 return error::kDeferCommandUntilLater
;
9581 if (!surface_
->SetBackbufferAllocation(false))
9582 return error::kLostContext
;
9583 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
9584 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
9585 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
9586 return error::kNoError
;
9589 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9590 GLsizei n
, const GLuint
* client_ids
) {
9591 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9592 if (query_manager_
->GetQuery(client_ids
[ii
])) {
9596 query_manager_
->GenQueries(n
, client_ids
);
9600 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9601 GLsizei n
, const GLuint
* client_ids
) {
9602 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9603 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
9604 if (query
&& !query
->IsDeleted()) {
9605 ContextState::QueryMap::iterator it
=
9606 state_
.current_queries
.find(query
->target());
9607 if (it
!= state_
.current_queries
.end())
9608 state_
.current_queries
.erase(it
);
9610 query
->Destroy(true);
9612 query_manager_
->RemoveQuery(client_ids
[ii
]);
9616 bool GLES2DecoderImpl::ProcessPendingQueries() {
9617 if (query_manager_
.get() == NULL
) {
9620 if (!query_manager_
->ProcessPendingQueries()) {
9621 current_decoder_error_
= error::kOutOfBounds
;
9623 return query_manager_
->HavePendingQueries();
9626 // Note that if there are no pending readpixels right now,
9627 // this function will call the callback immediately.
9628 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
9629 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
9630 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
9636 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9637 while (!pending_readpixel_fences_
.empty() &&
9638 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
9639 std::vector
<base::Closure
> callbacks
=
9640 pending_readpixel_fences_
.front()->callbacks
;
9641 pending_readpixel_fences_
.pop();
9642 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
9648 bool GLES2DecoderImpl::HasMoreIdleWork() {
9649 return !pending_readpixel_fences_
.empty() ||
9650 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
9653 void GLES2DecoderImpl::PerformIdleWork() {
9654 ProcessPendingReadPixels();
9655 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
9657 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
9658 ProcessFinishedAsyncTransfers();
9661 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(
9662 uint32 immediate_data_size
, const cmds::BeginQueryEXT
& c
) {
9663 GLenum target
= static_cast<GLenum
>(c
.target
);
9664 GLuint client_id
= static_cast<GLuint
>(c
.id
);
9665 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
9666 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
9669 case GL_COMMANDS_ISSUED_CHROMIUM
:
9670 case GL_LATENCY_QUERY_CHROMIUM
:
9671 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
9672 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
9673 case GL_GET_ERROR_QUERY_CHROMIUM
:
9675 case GL_COMMANDS_COMPLETED_CHROMIUM
:
9676 if (!features().chromium_sync_query
) {
9678 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9679 "not enabled for commands completed queries");
9680 return error::kNoError
;
9684 if (!features().occlusion_query_boolean
) {
9686 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9687 "not enabled for occlusion queries");
9688 return error::kNoError
;
9693 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
9695 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
9696 return error::kNoError
;
9699 if (client_id
== 0) {
9700 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
9701 return error::kNoError
;
9704 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
9706 if (!query_manager_
->IsValidQuery(client_id
)) {
9707 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9709 "id not made by glGenQueriesEXT");
9710 return error::kNoError
;
9712 query
= query_manager_
->CreateQuery(
9713 target
, client_id
, sync_shm_id
, sync_shm_offset
);
9716 if (query
->target() != target
) {
9718 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
9719 return error::kNoError
;
9720 } else if (query
->shm_id() != sync_shm_id
||
9721 query
->shm_offset() != sync_shm_offset
) {
9722 DLOG(ERROR
) << "Shared memory used by query not the same as before";
9723 return error::kInvalidArguments
;
9726 if (!query_manager_
->BeginQuery(query
)) {
9727 return error::kOutOfBounds
;
9730 state_
.current_queries
[target
] = query
;
9731 return error::kNoError
;
9734 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(
9735 uint32 immediate_data_size
, const cmds::EndQueryEXT
& c
) {
9736 GLenum target
= static_cast<GLenum
>(c
.target
);
9737 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
9738 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
9740 if (it
== state_
.current_queries
.end()) {
9742 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
9743 return error::kNoError
;
9746 QueryManager::Query
* query
= it
->second
.get();
9747 if (!query_manager_
->EndQuery(query
, submit_count
)) {
9748 return error::kOutOfBounds
;
9751 query_manager_
->ProcessPendingTransferQueries();
9753 state_
.current_queries
.erase(it
);
9754 return error::kNoError
;
9757 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9758 GLsizei n
, const GLuint
* client_ids
) {
9759 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9760 if (GetVertexAttribManager(client_ids
[ii
])) {
9765 if (!features().native_vertex_array_object
) {
9767 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9768 CreateVertexAttribManager(client_ids
[ii
], 0, true);
9771 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9773 glGenVertexArraysOES(n
, service_ids
.get());
9774 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9775 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
9782 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9783 GLsizei n
, const GLuint
* client_ids
) {
9784 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9785 VertexAttribManager
* vao
=
9786 GetVertexAttribManager(client_ids
[ii
]);
9787 if (vao
&& !vao
->IsDeleted()) {
9788 if (state_
.vertex_attrib_manager
.get() == vao
) {
9789 DoBindVertexArrayOES(0);
9791 RemoveVertexAttribManager(client_ids
[ii
]);
9796 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
9797 VertexAttribManager
* vao
= NULL
;
9798 if (client_id
!= 0) {
9799 vao
= GetVertexAttribManager(client_id
);
9801 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9802 // only allows names that have been previously generated. As such, we do
9803 // not generate new names here.
9805 GL_INVALID_OPERATION
,
9806 "glBindVertexArrayOES", "bad vertex array id.");
9807 current_decoder_error_
= error::kNoError
;
9811 vao
= state_
.default_vertex_attrib_manager
.get();
9814 // Only set the VAO state if it's changed
9815 if (state_
.vertex_attrib_manager
.get() != vao
) {
9816 state_
.vertex_attrib_manager
= vao
;
9817 if (!features().native_vertex_array_object
) {
9818 EmulateVertexArrayState();
9820 GLuint service_id
= vao
->service_id();
9821 glBindVertexArrayOES(service_id
);
9826 // Used when OES_vertex_array_object isn't natively supported
9827 void GLES2DecoderImpl::EmulateVertexArrayState() {
9828 // Setup the Vertex attribute state
9829 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
9830 RestoreStateForAttrib(vv
, true);
9833 // Setup the element buffer
9834 Buffer
* element_array_buffer
=
9835 state_
.vertex_attrib_manager
->element_array_buffer();
9836 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
9837 element_array_buffer
? element_array_buffer
->service_id() : 0);
9840 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
9841 const VertexAttribManager
* vao
=
9842 GetVertexAttribManager(client_id
);
9843 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
9846 #if defined(OS_MACOSX)
9847 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
9848 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
9850 if (it
!= texture_to_io_surface_map_
.end()) {
9851 // Found a previous IOSurface bound to this texture; release it.
9852 IOSurfaceRef surface
= it
->second
;
9854 texture_to_io_surface_map_
.erase(it
);
9859 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9860 GLenum target
, GLsizei width
, GLsizei height
,
9861 GLuint io_surface_id
, GLuint plane
) {
9862 #if defined(OS_MACOSX)
9863 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
9865 GL_INVALID_OPERATION
,
9866 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9870 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
9871 // This might be supported in the future, and if we could require
9872 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9873 // could delete a lot of code. For now, perform strict validation so we
9874 // know what's going on.
9876 GL_INVALID_OPERATION
,
9877 "glTexImageIOSurface2DCHROMIUM",
9878 "requires TEXTURE_RECTANGLE_ARB target");
9882 // Default target might be conceptually valid, but disallow it to avoid
9884 TextureRef
* texture_ref
=
9885 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
9888 GL_INVALID_OPERATION
,
9889 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9893 // Look up the new IOSurface. Note that because of asynchrony
9894 // between processes this might fail; during live resizing the
9895 // plugin process might allocate and release an IOSurface before
9896 // this process gets a chance to look it up. Hold on to any old
9897 // IOSurface in this case.
9898 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
9901 GL_INVALID_OPERATION
,
9902 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9906 // Release any IOSurface previously bound to this texture.
9907 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
9909 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9910 texture_to_io_surface_map_
.insert(
9911 std::make_pair(texture_ref
->service_id(), surface
));
9913 CGLContextObj context
=
9914 static_cast<CGLContextObj
>(context_
->GetHandle());
9916 CGLError err
= CGLTexImageIOSurface2D(
9923 GL_UNSIGNED_INT_8_8_8_8_REV
,
9927 if (err
!= kCGLNoError
) {
9929 GL_INVALID_OPERATION
,
9930 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9934 texture_manager()->SetLevelInfo(
9935 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
9936 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
9939 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9940 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9944 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
9945 switch (internalformat
) {
9956 case GL_LUMINANCE8_ALPHA8_EXT
:
9957 return GL_LUMINANCE_ALPHA
;
9958 case GL_LUMINANCE8_EXT
:
9959 return GL_LUMINANCE
;
9962 case GL_RGBA32F_EXT
:
9966 case GL_ALPHA32F_EXT
:
9968 case GL_LUMINANCE32F_EXT
:
9969 return GL_LUMINANCE
;
9970 case GL_LUMINANCE_ALPHA32F_EXT
:
9971 return GL_LUMINANCE_ALPHA
;
9972 case GL_RGBA16F_EXT
:
9976 case GL_ALPHA16F_EXT
:
9978 case GL_LUMINANCE16F_EXT
:
9979 return GL_LUMINANCE
;
9980 case GL_LUMINANCE_ALPHA16F_EXT
:
9981 return GL_LUMINANCE_ALPHA
;
9989 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9990 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
9991 GLenum internal_format
, GLenum dest_type
) {
9992 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9994 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
9995 TextureRef
* source_texture_ref
= GetTexture(source_id
);
9997 if (!source_texture_ref
|| !dest_texture_ref
) {
9999 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
10003 if (GL_TEXTURE_2D
!= target
) {
10004 LOCAL_SET_GL_ERROR(
10005 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
10009 Texture
* source_texture
= source_texture_ref
->texture();
10010 Texture
* dest_texture
= dest_texture_ref
->texture();
10011 if (dest_texture
->target() != GL_TEXTURE_2D
||
10012 (source_texture
->target() != GL_TEXTURE_2D
&&
10013 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
10014 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
10015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10016 "glCopyTextureCHROMIUM",
10017 "invalid texture target binding");
10021 int source_width
, source_height
, dest_width
, dest_height
;
10023 gfx::GLImage
* image
=
10024 source_texture
->GetLevelImage(source_texture
->target(), 0);
10026 gfx::Size size
= image
->GetSize();
10027 source_width
= size
.width();
10028 source_height
= size
.height();
10029 if (source_width
<= 0 || source_height
<= 0) {
10030 LOCAL_SET_GL_ERROR(
10032 "glCopyTextureChromium", "invalid image size");
10036 if (!source_texture
->GetLevelSize(
10037 source_texture
->target(), 0, &source_width
, &source_height
)) {
10038 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10039 "glCopyTextureChromium",
10040 "source texture has no level 0");
10044 // Check that this type of texture is allowed.
10045 if (!texture_manager()->ValidForTarget(
10046 source_texture
->target(), level
, source_width
, source_height
, 1)) {
10047 LOCAL_SET_GL_ERROR(
10048 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
10053 // Clear the source texture if necessary.
10054 if (!texture_manager()->ClearTextureLevel(
10055 this, source_texture_ref
, source_texture
->target(), 0)) {
10056 LOCAL_SET_GL_ERROR(
10057 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
10061 GLenum source_type
= 0;
10062 GLenum source_internal_format
= 0;
10063 source_texture
->GetLevelType(
10064 source_texture
->target(), 0, &source_type
, &source_internal_format
);
10066 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10067 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10068 // renderable on some platforms.
10069 bool valid_dest_format
=
10070 internal_format
== GL_RGB
|| internal_format
== GL_RGBA
;
10071 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
10072 source_internal_format
== GL_RGB
||
10073 source_internal_format
== GL_RGBA
||
10074 source_internal_format
== GL_LUMINANCE
||
10075 source_internal_format
== GL_LUMINANCE_ALPHA
||
10076 source_internal_format
== GL_BGRA_EXT
;
10077 if (!valid_source_format
|| !valid_dest_format
) {
10078 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10079 "glCopyTextureCHROMIUM",
10080 "invalid internal format");
10084 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10085 // needed because it takes 10s of milliseconds to initialize.
10086 if (!copy_texture_CHROMIUM_
.get()) {
10087 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10088 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
10089 copy_texture_CHROMIUM_
->Initialize(this);
10090 RestoreCurrentFramebufferBindings();
10091 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
10095 GLenum dest_type_previous
= dest_type
;
10096 GLenum dest_internal_format
= internal_format
;
10097 bool dest_level_defined
= dest_texture
->GetLevelSize(
10098 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
10100 if (dest_level_defined
) {
10101 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
10102 &dest_internal_format
);
10105 // Resize the destination texture to the dimensions of the source texture.
10106 if (!dest_level_defined
|| dest_width
!= source_width
||
10107 dest_height
!= source_height
||
10108 dest_internal_format
!= internal_format
||
10109 dest_type_previous
!= dest_type
) {
10110 // Ensure that the glTexImage2D succeeds.
10111 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10112 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
10114 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
10115 0, internal_format
, dest_type
, NULL
);
10116 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10117 if (error
!= GL_NO_ERROR
) {
10118 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
10122 texture_manager()->SetLevelInfo(
10123 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
10124 source_height
, 1, 0, internal_format
, dest_type
, true);
10126 texture_manager()->SetLevelCleared(
10127 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
10130 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
10131 ScopedModifyPixels
modify(dest_texture_ref
);
10133 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10134 // before presenting.
10135 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
10136 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10137 // instead of using default matrix crbug.com/226218.
10138 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
10139 0.0f
, 1.0f
, 0.0f
, 0.0f
,
10140 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10141 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10142 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
10144 source_texture
->target(),
10145 source_texture
->service_id(),
10146 dest_texture
->service_id(),
10151 unpack_premultiply_alpha_
,
10152 unpack_unpremultiply_alpha_
,
10155 copy_texture_CHROMIUM_
->DoCopyTexture(this,
10156 source_texture
->target(),
10157 source_texture
->service_id(),
10158 source_internal_format
,
10159 dest_texture
->service_id(),
10165 unpack_premultiply_alpha_
,
10166 unpack_unpremultiply_alpha_
);
10169 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
10172 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
10173 switch (internalformat
) {
10175 return GL_UNSIGNED_SHORT_5_6_5
;
10177 return GL_UNSIGNED_SHORT_4_4_4_4
;
10179 return GL_UNSIGNED_SHORT_5_5_5_1
;
10181 return GL_UNSIGNED_BYTE
;
10183 return GL_UNSIGNED_BYTE
;
10184 case GL_LUMINANCE8_ALPHA8_EXT
:
10185 return GL_UNSIGNED_BYTE
;
10186 case GL_LUMINANCE8_EXT
:
10187 return GL_UNSIGNED_BYTE
;
10188 case GL_ALPHA8_EXT
:
10189 return GL_UNSIGNED_BYTE
;
10190 case GL_RGBA32F_EXT
:
10192 case GL_RGB32F_EXT
:
10194 case GL_ALPHA32F_EXT
:
10196 case GL_LUMINANCE32F_EXT
:
10198 case GL_LUMINANCE_ALPHA32F_EXT
:
10200 case GL_RGBA16F_EXT
:
10201 return GL_HALF_FLOAT_OES
;
10202 case GL_RGB16F_EXT
:
10203 return GL_HALF_FLOAT_OES
;
10204 case GL_ALPHA16F_EXT
:
10205 return GL_HALF_FLOAT_OES
;
10206 case GL_LUMINANCE16F_EXT
:
10207 return GL_HALF_FLOAT_OES
;
10208 case GL_LUMINANCE_ALPHA16F_EXT
:
10209 return GL_HALF_FLOAT_OES
;
10211 return GL_UNSIGNED_BYTE
;
10217 void GLES2DecoderImpl::DoTexStorage2DEXT(
10220 GLenum internal_format
,
10223 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10224 "width", width
, "height", height
);
10225 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
10226 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
10227 LOCAL_SET_GL_ERROR(
10228 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
10231 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10233 if (!texture_ref
) {
10234 LOCAL_SET_GL_ERROR(
10235 GL_INVALID_OPERATION
,
10236 "glTexStorage2DEXT", "unknown texture for target");
10239 Texture
* texture
= texture_ref
->texture();
10240 if (texture
->IsAttachedToFramebuffer()) {
10241 framebuffer_state_
.clear_state_dirty
= true;
10243 if (texture
->IsImmutable()) {
10244 LOCAL_SET_GL_ERROR(
10245 GL_INVALID_OPERATION
,
10246 "glTexStorage2DEXT", "texture is immutable");
10250 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
10251 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
10254 GLsizei level_width
= width
;
10255 GLsizei level_height
= height
;
10256 uint32 estimated_size
= 0;
10257 for (int ii
= 0; ii
< levels
; ++ii
) {
10258 uint32 level_size
= 0;
10259 if (!GLES2Util::ComputeImageDataSizes(
10260 level_width
, level_height
, format
, type
, state_
.unpack_alignment
,
10261 &estimated_size
, NULL
, NULL
) ||
10262 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
10263 LOCAL_SET_GL_ERROR(
10264 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
10267 level_width
= std::max(1, level_width
>> 1);
10268 level_height
= std::max(1, level_height
>> 1);
10270 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10271 LOCAL_SET_GL_ERROR(
10272 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
10277 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10278 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
10279 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10280 if (error
== GL_NO_ERROR
) {
10281 GLsizei level_width
= width
;
10282 GLsizei level_height
= height
;
10283 for (int ii
= 0; ii
< levels
; ++ii
) {
10284 texture_manager()->SetLevelInfo(
10285 texture_ref
, target
, ii
, format
,
10286 level_width
, level_height
, 1, 0, format
, type
, false);
10287 level_width
= std::max(1, level_width
>> 1);
10288 level_height
= std::max(1, level_height
>> 1);
10290 texture
->SetImmutable(true);
10294 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10295 uint32 immediate_data_size
, const cmds::GenMailboxCHROMIUM
& c
) {
10296 return error::kUnknownCommand
;
10299 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
10300 const GLbyte
* data
) {
10301 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10302 "context", logger_
.GetLogPrefix(),
10303 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10305 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10307 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
10310 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
10311 GLenum target
, const GLbyte
* data
) {
10312 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10313 "context", logger_
.GetLogPrefix(),
10314 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10316 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
10320 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
10321 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
10322 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10323 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
10324 "mailbox that was not generated by "
10325 "GenMailboxCHROMIUM.";
10327 if (!texture_ref
) {
10328 LOCAL_SET_GL_ERROR(
10329 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
10333 Texture
* produced
= texture_manager()->Produce(texture_ref
);
10335 LOCAL_SET_GL_ERROR(
10336 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
10340 if (produced
->target() != target
) {
10341 LOCAL_SET_GL_ERROR(
10342 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
10346 group_
->mailbox_manager()->ProduceTexture(target
, mailbox
, produced
);
10349 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
10350 const GLbyte
* data
) {
10351 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10352 "context", logger_
.GetLogPrefix(),
10353 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10354 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10355 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10356 "mailbox that was not generated by "
10357 "GenMailboxCHROMIUM.";
10359 scoped_refptr
<TextureRef
> texture_ref
=
10360 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10361 if (!texture_ref
.get()) {
10362 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10363 "glConsumeTextureCHROMIUM",
10364 "unknown texture for target");
10367 GLuint client_id
= texture_ref
->client_id();
10369 LOCAL_SET_GL_ERROR(
10370 GL_INVALID_OPERATION
,
10371 "glConsumeTextureCHROMIUM", "unknown texture for target");
10374 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10376 LOCAL_SET_GL_ERROR(
10377 GL_INVALID_OPERATION
,
10378 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10381 if (texture
->target() != target
) {
10382 LOCAL_SET_GL_ERROR(
10383 GL_INVALID_OPERATION
,
10384 "glConsumeTextureCHROMIUM", "invalid target");
10388 DeleteTexturesHelper(1, &client_id
);
10389 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10390 glBindTexture(target
, texture_ref
->service_id());
10392 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10393 unit
.bind_target
= target
;
10395 case GL_TEXTURE_2D
:
10396 unit
.bound_texture_2d
= texture_ref
;
10398 case GL_TEXTURE_CUBE_MAP
:
10399 unit
.bound_texture_cube_map
= texture_ref
;
10401 case GL_TEXTURE_EXTERNAL_OES
:
10402 unit
.bound_texture_external_oes
= texture_ref
;
10404 case GL_TEXTURE_RECTANGLE_ARB
:
10405 unit
.bound_texture_rectangle_arb
= texture_ref
;
10408 NOTREACHED(); // Validation should prevent us getting here.
10413 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10414 uint32_t immediate_data_size
,
10415 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
) {
10416 GLenum target
= static_cast<GLenum
>(c
.target
);
10417 uint32_t data_size
;
10418 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
10419 return error::kOutOfBounds
;
10421 if (data_size
> immediate_data_size
) {
10422 return error::kOutOfBounds
;
10424 const GLbyte
* mailbox
=
10425 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
10426 if (!validators_
->texture_bind_target
.IsValid(target
)) {
10427 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10428 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
10429 return error::kNoError
;
10431 if (mailbox
== NULL
) {
10432 return error::kOutOfBounds
;
10434 uint32_t client_id
= c
.client_id
;
10435 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
10436 return error::kNoError
;
10439 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
10440 const GLbyte
* data
, GLuint client_id
) {
10441 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10442 "context", logger_
.GetLogPrefix(),
10443 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10444 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10445 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10446 "passed a mailbox that was not "
10447 "generated by GenMailboxCHROMIUM.";
10449 TextureRef
* texture_ref
= GetTexture(client_id
);
10451 LOCAL_SET_GL_ERROR(
10452 GL_INVALID_OPERATION
,
10453 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10456 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10458 LOCAL_SET_GL_ERROR(
10459 GL_INVALID_OPERATION
,
10460 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10463 if (texture
->target() != target
) {
10464 LOCAL_SET_GL_ERROR(
10465 GL_INVALID_OPERATION
,
10466 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10470 IdAllocatorInterface
* id_allocator
=
10471 group_
->GetIdAllocator(id_namespaces::kTextures
);
10472 id_allocator
->MarkAsUsed(client_id
);
10474 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10477 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10478 GLsizei length
, const GLchar
* marker
) {
10482 debug_marker_manager_
.SetMarker(
10483 length
? std::string(marker
, length
) : std::string(marker
));
10486 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10487 GLsizei length
, const GLchar
* marker
) {
10491 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
10492 debug_marker_manager_
.PushGroup(name
);
10493 gpu_tracer_
->Begin(name
, kTraceGroupMarker
);
10496 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10497 debug_marker_manager_
.PopGroup();
10498 gpu_tracer_
->End(kTraceGroupMarker
);
10501 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10502 GLenum target
, GLint image_id
) {
10503 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10505 if (target
== GL_TEXTURE_CUBE_MAP
) {
10506 LOCAL_SET_GL_ERROR(
10508 "glBindTexImage2DCHROMIUM", "invalid target");
10512 // Default target might be conceptually valid, but disallow it to avoid
10514 TextureRef
* texture_ref
=
10515 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10516 if (!texture_ref
) {
10517 LOCAL_SET_GL_ERROR(
10518 GL_INVALID_OPERATION
,
10519 "glBindTexImage2DCHROMIUM", "no texture bound");
10523 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10525 LOCAL_SET_GL_ERROR(
10526 GL_INVALID_OPERATION
,
10527 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10532 ScopedGLErrorSuppressor
suppressor(
10533 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10534 if (!gl_image
->BindTexImage(target
)) {
10535 LOCAL_SET_GL_ERROR(
10536 GL_INVALID_OPERATION
,
10537 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10542 gfx::Size size
= gl_image
->GetSize();
10543 texture_manager()->SetLevelInfo(
10544 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
10545 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
10546 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
10549 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10550 GLenum target
, GLint image_id
) {
10551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10553 // Default target might be conceptually valid, but disallow it to avoid
10555 TextureRef
* texture_ref
=
10556 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10557 if (!texture_ref
) {
10558 LOCAL_SET_GL_ERROR(
10559 GL_INVALID_OPERATION
,
10560 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10564 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10566 LOCAL_SET_GL_ERROR(
10567 GL_INVALID_OPERATION
,
10568 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10572 // Do nothing when image is not currently bound.
10573 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
10577 ScopedGLErrorSuppressor
suppressor(
10578 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10579 gl_image
->ReleaseTexImage(target
);
10582 texture_manager()->SetLevelInfo(
10583 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
10584 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
10587 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10588 uint32 immediate_data_size
, const cmds::TraceBeginCHROMIUM
& c
) {
10589 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10590 if (!bucket
|| bucket
->size() == 0) {
10591 return error::kInvalidArguments
;
10593 std::string command_name
;
10594 if (!bucket
->GetAsString(&command_name
)) {
10595 return error::kInvalidArguments
;
10597 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name
.c_str(), this);
10598 if (!gpu_tracer_
->Begin(command_name
, kTraceCHROMIUM
)) {
10599 LOCAL_SET_GL_ERROR(
10600 GL_INVALID_OPERATION
,
10601 "glTraceBeginCHROMIUM", "unable to create begin trace");
10602 return error::kNoError
;
10604 return error::kNoError
;
10607 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10608 if (gpu_tracer_
->CurrentName().empty()) {
10609 LOCAL_SET_GL_ERROR(
10610 GL_INVALID_OPERATION
,
10611 "glTraceEndCHROMIUM", "no trace begin found");
10614 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_
->CurrentName().c_str(), this);
10615 gpu_tracer_
->End(kTraceCHROMIUM
);
10618 void GLES2DecoderImpl::DoDrawBuffersEXT(
10619 GLsizei count
, const GLenum
* bufs
) {
10620 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
10621 LOCAL_SET_GL_ERROR(
10623 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10627 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
10629 for (GLsizei i
= 0; i
< count
; ++i
) {
10630 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
10631 bufs
[i
] != GL_NONE
) {
10632 LOCAL_SET_GL_ERROR(
10633 GL_INVALID_OPERATION
,
10634 "glDrawBuffersEXT",
10635 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10639 glDrawBuffersARB(count
, bufs
);
10640 framebuffer
->SetDrawBuffers(count
, bufs
);
10641 } else { // backbuffer
10643 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
10644 LOCAL_SET_GL_ERROR(
10645 GL_INVALID_OPERATION
,
10646 "glDrawBuffersEXT",
10647 "more than one buffer or bufs not GL_NONE or GL_BACK");
10650 GLenum mapped_buf
= bufs
[0];
10651 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10652 bufs
[0] == GL_BACK
) {
10653 mapped_buf
= GL_COLOR_ATTACHMENT0
;
10655 glDrawBuffersARB(count
, &mapped_buf
);
10656 group_
->set_draw_buffer(bufs
[0]);
10660 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
10661 group_
->LoseContexts(other
);
10662 reset_status_
= current
;
10663 current_decoder_error_
= error::kLostContext
;
10666 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
10667 const GLfloat
* matrix
) {
10668 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
10669 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
10670 if (!features().chromium_path_rendering
) {
10671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10672 "glMatrixLoadfCHROMIUM",
10673 "function not available");
10677 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
10678 ? state_
.projection_matrix
10679 : state_
.modelview_matrix
;
10680 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
10681 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10682 // since the values of the _NV and _CHROMIUM tokens match.
10683 glMatrixLoadfEXT(matrix_mode
, matrix
);
10686 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
10687 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
10688 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
10690 if (!features().chromium_path_rendering
) {
10691 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10692 "glMatrixLoadIdentityCHROMIUM",
10693 "function not available");
10697 static GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
,
10698 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10699 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10701 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
10702 ? state_
.projection_matrix
10703 : state_
.modelview_matrix
;
10704 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
10705 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10706 // since the values of the _NV and _CHROMIUM tokens match.
10707 glMatrixLoadIdentityEXT(matrix_mode
);
10710 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10711 const char* function_name
,
10712 TextureRef
* texture_ref
,
10715 const void * data
) {
10716 // We only support async uploads to 2D textures for now.
10717 if (GL_TEXTURE_2D
!= target
) {
10718 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10721 // We only support uploads to level zero for now.
10723 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
10726 // A transfer buffer must be bound, even for asyncTexImage2D.
10727 if (data
== NULL
) {
10728 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
10731 // We only support one async transfer in progress.
10732 if (!texture_ref
||
10733 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10734 LOCAL_SET_GL_ERROR(
10735 GL_INVALID_OPERATION
,
10736 function_name
, "transfer already in progress");
10742 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10743 uint32 async_upload_token
,
10744 uint32 sync_data_shm_id
,
10745 uint32 sync_data_shm_offset
) {
10746 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
10747 if (!buffer
.get() ||
10748 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
10749 return base::Closure();
10751 AsyncMemoryParams
mem_params(buffer
,
10752 sync_data_shm_offset
,
10753 sizeof(AsyncUploadSync
));
10755 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
10756 new AsyncUploadTokenCompletionObserver(async_upload_token
));
10759 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
10760 base::Unretained(GetAsyncPixelTransferManager()),
10765 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10766 uint32 immediate_data_size
, const cmds::AsyncTexImage2DCHROMIUM
& c
) {
10767 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10768 GLenum target
= static_cast<GLenum
>(c
.target
);
10769 GLint level
= static_cast<GLint
>(c
.level
);
10770 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10771 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10772 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10773 GLint border
= static_cast<GLint
>(c
.border
);
10774 GLenum format
= static_cast<GLenum
>(c
.format
);
10775 GLenum type
= static_cast<GLenum
>(c
.type
);
10776 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10777 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10778 uint32 pixels_size
;
10779 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10780 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10781 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10783 base::ScopedClosureRunner scoped_completion_callback
;
10784 if (async_upload_token
) {
10785 base::Closure completion_closure
=
10786 AsyncUploadTokenCompletionClosure(async_upload_token
,
10788 sync_data_shm_offset
);
10789 if (completion_closure
.is_null())
10790 return error::kInvalidArguments
;
10792 scoped_completion_callback
.Reset(completion_closure
);
10795 // TODO(epenner): Move this and copies of this memory validation
10796 // into ValidateTexImage2D step.
10797 if (!GLES2Util::ComputeImageDataSizes(
10798 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
10800 return error::kOutOfBounds
;
10802 const void* pixels
= NULL
;
10803 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10804 pixels
= GetSharedMemoryAs
<const void*>(
10805 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10807 return error::kOutOfBounds
;
10811 TextureManager::DoTextImage2DArguments args
= {
10812 target
, level
, internal_format
, width
, height
, border
, format
, type
,
10813 pixels
, pixels_size
};
10814 TextureRef
* texture_ref
;
10815 // All the normal glTexSubImage2D validation.
10816 if (!texture_manager()->ValidateTexImage2D(
10817 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
10818 return error::kNoError
;
10821 // Extra async validation.
10822 Texture
* texture
= texture_ref
->texture();
10823 if (!ValidateAsyncTransfer(
10824 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10825 return error::kNoError
;
10827 // Don't allow async redefinition of a textures.
10828 if (texture
->IsDefined()) {
10829 LOCAL_SET_GL_ERROR(
10830 GL_INVALID_OPERATION
,
10831 "glAsyncTexImage2DCHROMIUM", "already defined");
10832 return error::kNoError
;
10835 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
10836 LOCAL_SET_GL_ERROR(
10837 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
10838 return error::kNoError
;
10841 // Setup the parameters.
10842 AsyncTexImage2DParams tex_params
= {
10843 target
, level
, static_cast<GLenum
>(internal_format
),
10844 width
, height
, border
, format
, type
};
10845 AsyncMemoryParams
mem_params(
10846 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
10848 // Set up the async state if needed, and make the texture
10849 // immutable so the async state stays valid. The level info
10850 // is set up lazily when the transfer completes.
10851 AsyncPixelTransferDelegate
* delegate
=
10852 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
10854 texture
->SetImmutable(true);
10856 delegate
->AsyncTexImage2D(
10859 base::Bind(&TextureManager::SetLevelInfoFromParams
,
10860 // The callback is only invoked if the transfer delegate still
10861 // exists, which implies through manager->texture_ref->state
10862 // ownership that both of these pointers are valid.
10863 base::Unretained(texture_manager()),
10864 base::Unretained(texture_ref
),
10866 return error::kNoError
;
10869 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10870 uint32 immediate_data_size
, const cmds::AsyncTexSubImage2DCHROMIUM
& c
) {
10871 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10872 GLenum target
= static_cast<GLenum
>(c
.target
);
10873 GLint level
= static_cast<GLint
>(c
.level
);
10874 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10875 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10876 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10877 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10878 GLenum format
= static_cast<GLenum
>(c
.format
);
10879 GLenum type
= static_cast<GLenum
>(c
.type
);
10880 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10881 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10882 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10884 base::ScopedClosureRunner scoped_completion_callback
;
10885 if (async_upload_token
) {
10886 base::Closure completion_closure
=
10887 AsyncUploadTokenCompletionClosure(async_upload_token
,
10889 sync_data_shm_offset
);
10890 if (completion_closure
.is_null())
10891 return error::kInvalidArguments
;
10893 scoped_completion_callback
.Reset(completion_closure
);
10896 // TODO(epenner): Move this and copies of this memory validation
10897 // into ValidateTexSubImage2D step.
10899 if (!GLES2Util::ComputeImageDataSizes(
10900 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
10902 return error::kOutOfBounds
;
10904 const void* pixels
= GetSharedMemoryAs
<const void*>(
10905 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
10907 // All the normal glTexSubImage2D validation.
10908 error::Error error
= error::kNoError
;
10909 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
10910 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
10914 // Extra async validation.
10915 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10917 Texture
* texture
= texture_ref
->texture();
10918 if (!ValidateAsyncTransfer(
10919 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10920 return error::kNoError
;
10922 // Guarantee async textures are always 'cleared' as follows:
10923 // - AsyncTexImage2D can not redefine an existing texture
10924 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10925 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10926 // - Textures become immutable after an async call.
10927 // This way we know in all cases that an async texture is always clear.
10928 if (!texture
->SafeToRenderFrom()) {
10929 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10931 LOCAL_SET_GL_ERROR(
10933 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10934 return error::kNoError
;
10938 // Setup the parameters.
10939 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
10940 width
, height
, format
, type
};
10941 AsyncMemoryParams
mem_params(
10942 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
10943 AsyncPixelTransferDelegate
* delegate
=
10944 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10946 // TODO(epenner): We may want to enforce exclusive use
10947 // of async APIs in which case this should become an error,
10948 // (the texture should have been async defined).
10949 AsyncTexImage2DParams define_params
= {target
, level
,
10951 texture
->GetLevelSize(target
, level
, &define_params
.width
,
10952 &define_params
.height
);
10953 texture
->GetLevelType(target
, level
, &define_params
.type
,
10954 &define_params
.internal_format
);
10955 // Set up the async state if needed, and make the texture
10956 // immutable so the async state stays valid.
10957 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
10958 texture_ref
, define_params
);
10959 texture
->SetImmutable(true);
10962 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
10963 return error::kNoError
;
10966 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10967 uint32 immediate_data_size
, const cmds::WaitAsyncTexImage2DCHROMIUM
& c
) {
10968 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10969 GLenum target
= static_cast<GLenum
>(c
.target
);
10971 if (GL_TEXTURE_2D
!= target
) {
10972 LOCAL_SET_GL_ERROR(
10973 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
10974 return error::kNoError
;
10976 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10978 if (!texture_ref
) {
10979 LOCAL_SET_GL_ERROR(
10980 GL_INVALID_OPERATION
,
10981 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10982 return error::kNoError
;
10984 AsyncPixelTransferDelegate
* delegate
=
10985 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10987 LOCAL_SET_GL_ERROR(
10988 GL_INVALID_OPERATION
,
10989 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10990 return error::kNoError
;
10992 delegate
->WaitForTransferCompletion();
10993 ProcessFinishedAsyncTransfers();
10994 return error::kNoError
;
10997 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10998 uint32 immediate_data_size
, const cmds::WaitAllAsyncTexImage2DCHROMIUM
& c
) {
10999 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11001 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11002 ProcessFinishedAsyncTransfers();
11003 return error::kNoError
;
11006 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11007 TextureRef
* texture_ref
) {
11008 Texture
* texture
= texture_ref
->texture();
11009 DoDidUseTexImageIfNeeded(texture
, texture
->target());
11012 void GLES2DecoderImpl::OnOutOfMemoryError() {
11013 if (lose_context_when_out_of_memory_
) {
11014 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
11015 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB
);
11019 // Include the auto-generated part of this file. We split this because it means
11020 // we can easily edit the non-auto generated parts right here in this file
11021 // instead of having to edit some template or the code generator.
11022 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11024 } // namespace gles2