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 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
90 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
93 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
94 GLenum precision_type
,
95 GLint
*range
, GLint
*precision
) {
96 switch (precision_type
) {
100 // These values are for a 32-bit twos-complement integer format.
106 case GL_MEDIUM_FLOAT
:
108 // These values are for an IEEE single-precision floating-point format.
118 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
119 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
120 // This function is sometimes defined even though it's really just
121 // a stub, so we need to set range and precision as if it weren't
122 // defined before calling it.
123 // On Mac OS with some GPUs, calling this generates a
124 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
126 glGetShaderPrecisionFormat(shader_type
, precision_type
,
129 // TODO(brianderson): Make the following official workarounds.
131 // Some drivers have bugs where they report the ranges as a negative number.
132 // Taking the absolute value here shouldn't hurt because negative numbers
133 // aren't expected anyway.
134 range
[0] = abs(range
[0]);
135 range
[1] = abs(range
[1]);
137 // If the driver reports a precision for highp float that isn't actually
138 // highp, don't pretend like it's supported because shader compilation will
140 if (precision_type
== GL_HIGH_FLOAT
&&
141 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
149 static gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
150 switch (plane_transform
) {
151 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
152 return gfx::OVERLAY_TRANSFORM_NONE
;
153 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
154 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
155 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
156 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
157 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
158 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
159 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
161 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
164 return gfx::OVERLAY_TRANSFORM_INVALID
;
170 class GLES2DecoderImpl
;
172 // Local versions of the SET_GL_ERROR macros
173 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
174 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
175 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
176 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
177 function_name, value, label)
178 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
179 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
180 function_name, pname)
181 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
182 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
184 #define LOCAL_PEEK_GL_ERROR(function_name) \
185 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
186 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
187 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
188 #define LOCAL_PERFORMANCE_WARNING(msg) \
189 PerformanceWarning(__FILE__, __LINE__, msg)
190 #define LOCAL_RENDER_WARNING(msg) \
191 RenderWarning(__FILE__, __LINE__, msg)
193 // Check that certain assumptions the code makes are true. There are places in
194 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
195 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
196 // a few others) are 32bits. If they are not 32bits the code will have to change
197 // to call those GL functions with service side memory and then copy the results
198 // to shared memory, converting the sizes.
199 COMPILE_ASSERT(sizeof(GLint
) == sizeof(uint32
), // NOLINT
200 GLint_not_same_size_as_uint32
);
201 COMPILE_ASSERT(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
202 GLint_not_same_size_as_uint32
);
203 COMPILE_ASSERT(sizeof(GLfloat
) == sizeof(float), // NOLINT
204 GLfloat_not_same_size_as_float
);
206 // TODO(kbr): the use of this anonymous namespace core dumps the
207 // linker on Mac OS X 10.6 when the symbol ordering file is used
210 // Returns the address of the first byte after a struct.
211 template <typename T
>
212 const void* AddressAfterStruct(const T
& pod
) {
213 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
216 // Returns the address of the frst byte after the struct or NULL if size >
217 // immediate_data_size.
218 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
219 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
221 uint32 immediate_data_size
) {
222 return (size
<= immediate_data_size
) ?
223 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
227 // Computes the data size for certain gl commands like glUniform.
228 bool ComputeDataSize(
231 unsigned int elements_per_unit
,
234 if (!SafeMultiplyUint32(count
, size
, &value
)) {
237 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
244 // Return true if a character belongs to the ASCII subset as defined in
245 // GLSL ES 1.0 spec section 3.1.
246 static bool CharacterIsValidForGLES(unsigned char c
) {
247 // Printing characters are valid except " $ ` @ \ ' DEL.
248 if (c
>= 32 && c
<= 126 &&
257 // Horizontal tab, line feed, vertical tab, form feed, carriage return
259 if (c
>= 9 && c
<= 13) {
266 static bool StringIsValidForGLES(const char* str
) {
267 for (; *str
; ++str
) {
268 if (!CharacterIsValidForGLES(*str
)) {
275 // This class prevents any GL errors that occur when it is in scope from
276 // being reported to the client.
277 class ScopedGLErrorSuppressor
{
279 explicit ScopedGLErrorSuppressor(
280 const char* function_name
, ErrorState
* error_state
);
281 ~ScopedGLErrorSuppressor();
283 const char* function_name_
;
284 ErrorState
* error_state_
;
285 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
288 // Temporarily changes a decoder's bound texture and restore it when this
289 // object goes out of scope. Also temporarily switches to using active texture
290 // unit zero in case the client has changed that to something invalid.
291 class ScopedTextureBinder
{
293 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
294 ~ScopedTextureBinder();
297 ContextState
* state_
;
299 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
302 // Temporarily changes a decoder's bound render buffer and restore it when this
303 // object goes out of scope.
304 class ScopedRenderBufferBinder
{
306 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
307 ~ScopedRenderBufferBinder();
310 ContextState
* state_
;
311 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
314 // Temporarily changes a decoder's bound frame buffer and restore it when this
315 // object goes out of scope.
316 class ScopedFrameBufferBinder
{
318 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
319 ~ScopedFrameBufferBinder();
322 GLES2DecoderImpl
* decoder_
;
323 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
326 // Temporarily changes a decoder's bound frame buffer to a resolved version of
327 // the multisampled offscreen render buffer if that buffer is multisampled, and,
328 // if it is bound or enforce_internal_framebuffer is true. If internal is
329 // true, the resolved framebuffer is not visible to the parent.
330 class ScopedResolvedFrameBufferBinder
{
332 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
333 bool enforce_internal_framebuffer
,
335 ~ScopedResolvedFrameBufferBinder();
338 GLES2DecoderImpl
* decoder_
;
339 bool resolve_and_bind_
;
340 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
343 class ScopedModifyPixels
{
345 explicit ScopedModifyPixels(TextureRef
* ref
);
346 ~ScopedModifyPixels();
352 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
354 ref_
->texture()->OnWillModifyPixels();
357 ScopedModifyPixels::~ScopedModifyPixels() {
359 ref_
->texture()->OnDidModifyPixels();
362 class ScopedRenderTo
{
364 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
368 const Framebuffer
* framebuffer_
;
371 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
372 : framebuffer_(framebuffer
) {
374 framebuffer_
->OnWillRenderTo();
377 ScopedRenderTo::~ScopedRenderTo() {
379 framebuffer_
->OnDidRenderTo();
382 // Encapsulates an OpenGL texture.
385 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
388 // Create a new render texture.
391 // Set the initial size and format of a render texture or resize it.
392 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
394 // Copy the contents of the currently bound frame buffer.
395 void Copy(const gfx::Size
& size
, GLenum format
);
397 // Destroy the render texture. This must be explicitly called before
398 // destroying this object.
401 // Invalidate the texture. This can be used when a context is lost and it is
402 // not possible to make it current in order to free the resource.
409 gfx::Size
size() const {
414 MemoryTypeTracker memory_tracker_
;
415 ContextState
* state_
;
416 size_t bytes_allocated_
;
419 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
422 // Encapsulates an OpenGL render buffer of any format.
423 class BackRenderbuffer
{
425 explicit BackRenderbuffer(
426 RenderbufferManager
* renderbuffer_manager
,
427 MemoryTracker
* memory_tracker
,
428 ContextState
* state
);
431 // Create a new render buffer.
434 // Set the initial size and format of a render buffer or resize it.
435 bool AllocateStorage(const FeatureInfo
* feature_info
,
436 const gfx::Size
& size
,
440 // Destroy the render buffer. This must be explicitly called before destroying
444 // Invalidate the render buffer. This can be used when a context is lost and
445 // it is not possible to make it current in order to free the resource.
453 RenderbufferManager
* renderbuffer_manager_
;
454 MemoryTypeTracker memory_tracker_
;
455 ContextState
* state_
;
456 size_t bytes_allocated_
;
458 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
461 // Encapsulates an OpenGL frame buffer.
462 class BackFramebuffer
{
464 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
467 // Create a new frame buffer.
470 // Attach a color render buffer to a frame buffer.
471 void AttachRenderTexture(BackTexture
* texture
);
473 // Attach a render buffer to a frame buffer. Note that this unbinds any
474 // currently bound frame buffer.
475 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
477 // Destroy the frame buffer. This must be explicitly called before destroying
481 // Invalidate the frame buffer. This can be used when a context is lost and it
482 // is not possible to make it current in order to free the resource.
485 // See glCheckFramebufferStatusEXT.
486 GLenum
CheckStatus();
493 GLES2DecoderImpl
* decoder_
;
495 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
498 struct FenceCallback
{
499 explicit FenceCallback()
500 : fence(gfx::GLFence::Create()) {
503 std::vector
<base::Closure
> callbacks
;
504 scoped_ptr
<gfx::GLFence
> fence
;
507 class AsyncUploadTokenCompletionObserver
508 : public AsyncPixelTransferCompletionObserver
{
510 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
511 : async_upload_token_(async_upload_token
) {
514 virtual void DidComplete(const AsyncMemoryParams
& mem_params
) OVERRIDE
{
515 DCHECK(mem_params
.buffer().get());
516 void* data
= mem_params
.GetDataAddress();
517 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
518 sync
->SetAsyncUploadToken(async_upload_token_
);
522 virtual ~AsyncUploadTokenCompletionObserver() {
525 uint32 async_upload_token_
;
527 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
530 // } // anonymous namespace.
533 const unsigned int GLES2Decoder::kDefaultStencilMask
=
534 static_cast<unsigned int>(-1);
536 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
537 uint32
* service_texture_id
) {
541 GLES2Decoder::GLES2Decoder()
542 : initialized_(false),
544 log_commands_(false) {
547 GLES2Decoder::~GLES2Decoder() {
550 void GLES2Decoder::BeginDecoding() {}
552 void GLES2Decoder::EndDecoding() {}
554 // This class implements GLES2Decoder so we don't have to expose all the GLES2
555 // cmd stuff to outside this class.
556 class GLES2DecoderImpl
: public GLES2Decoder
,
557 public FramebufferManager::TextureDetachObserver
,
558 public ErrorStateClient
{
560 explicit GLES2DecoderImpl(ContextGroup
* group
);
561 virtual ~GLES2DecoderImpl();
563 // Overridden from AsyncAPIInterface.
564 virtual Error
DoCommand(unsigned int command
,
565 unsigned int arg_count
,
566 const void* args
) OVERRIDE
;
568 virtual error::Error
DoCommands(unsigned int num_commands
,
571 int* entries_processed
) OVERRIDE
;
573 template <bool DebugImpl
>
574 error::Error
DoCommandsImpl(unsigned int num_commands
,
577 int* entries_processed
);
579 // Overridden from AsyncAPIInterface.
580 virtual const char* GetCommandName(unsigned int command_id
) const OVERRIDE
;
582 // Overridden from GLES2Decoder.
583 virtual bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
584 const scoped_refptr
<gfx::GLContext
>& context
,
586 const gfx::Size
& size
,
587 const DisallowedFeatures
& disallowed_features
,
588 const std::vector
<int32
>& attribs
) OVERRIDE
;
589 virtual void Destroy(bool have_context
) OVERRIDE
;
590 virtual void SetSurface(
591 const scoped_refptr
<gfx::GLSurface
>& surface
) OVERRIDE
;
592 virtual void ProduceFrontBuffer(const Mailbox
& mailbox
) OVERRIDE
;
593 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) OVERRIDE
;
594 void UpdateParentTextureInfo();
595 virtual bool MakeCurrent() OVERRIDE
;
596 virtual GLES2Util
* GetGLES2Util() OVERRIDE
{ return &util_
; }
597 virtual gfx::GLContext
* GetGLContext() OVERRIDE
{ return context_
.get(); }
598 virtual ContextGroup
* GetContextGroup() OVERRIDE
{ return group_
.get(); }
599 virtual Capabilities
GetCapabilities() OVERRIDE
;
600 virtual void RestoreState(const ContextState
* prev_state
) OVERRIDE
;
602 virtual void RestoreActiveTexture() const OVERRIDE
{
603 state_
.RestoreActiveTexture();
605 virtual void RestoreAllTextureUnitBindings(
606 const ContextState
* prev_state
) const OVERRIDE
{
607 state_
.RestoreAllTextureUnitBindings(prev_state
);
609 virtual void RestoreActiveTextureUnitBinding(
610 unsigned int target
) const OVERRIDE
{
611 state_
.RestoreActiveTextureUnitBinding(target
);
613 virtual void RestoreBufferBindings() const OVERRIDE
{
614 state_
.RestoreBufferBindings();
616 virtual void RestoreGlobalState() const OVERRIDE
{
617 state_
.RestoreGlobalState(NULL
);
619 virtual void RestoreProgramBindings() const OVERRIDE
{
620 state_
.RestoreProgramBindings();
622 virtual void RestoreTextureUnitBindings(unsigned unit
) const OVERRIDE
{
623 state_
.RestoreTextureUnitBindings(unit
, NULL
);
625 virtual void RestoreFramebufferBindings() const OVERRIDE
;
626 virtual void RestoreRenderbufferBindings() OVERRIDE
;
627 virtual void RestoreTextureState(unsigned service_id
) const OVERRIDE
;
629 virtual void ClearAllAttributes() const OVERRIDE
;
630 virtual void RestoreAllAttributes() const OVERRIDE
;
632 virtual QueryManager
* GetQueryManager() OVERRIDE
{
633 return query_manager_
.get();
635 virtual VertexArrayManager
* GetVertexArrayManager() OVERRIDE
{
636 return vertex_array_manager_
.get();
638 virtual ImageManager
* GetImageManager() OVERRIDE
{
639 return image_manager_
.get();
641 virtual bool ProcessPendingQueries() OVERRIDE
;
642 virtual bool HasMoreIdleWork() OVERRIDE
;
643 virtual void PerformIdleWork() OVERRIDE
;
645 virtual void WaitForReadPixels(base::Closure callback
) OVERRIDE
;
647 virtual void SetResizeCallback(
648 const base::Callback
<void(gfx::Size
, float)>& callback
) OVERRIDE
;
650 virtual Logger
* GetLogger() OVERRIDE
;
652 virtual void BeginDecoding() OVERRIDE
;
653 virtual void EndDecoding() OVERRIDE
;
655 virtual ErrorState
* GetErrorState() OVERRIDE
;
656 virtual const ContextState
* GetContextState() OVERRIDE
{ return &state_
; }
658 virtual void SetShaderCacheCallback(
659 const ShaderCacheCallback
& callback
) OVERRIDE
;
660 virtual void SetWaitSyncPointCallback(
661 const WaitSyncPointCallback
& callback
) OVERRIDE
;
663 virtual AsyncPixelTransferManager
*
664 GetAsyncPixelTransferManager() OVERRIDE
;
665 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE
;
666 virtual void SetAsyncPixelTransferManagerForTest(
667 AsyncPixelTransferManager
* manager
) OVERRIDE
;
668 virtual void SetIgnoreCachedStateForTest(bool ignore
) OVERRIDE
;
669 void ProcessFinishedAsyncTransfers();
671 virtual bool GetServiceTextureId(uint32 client_texture_id
,
672 uint32
* service_texture_id
) OVERRIDE
;
674 virtual uint32
GetTextureUploadCount() OVERRIDE
;
675 virtual base::TimeDelta
GetTotalTextureUploadTime() OVERRIDE
;
676 virtual base::TimeDelta
GetTotalProcessingCommandsTime() OVERRIDE
;
677 virtual void AddProcessingCommandsTime(base::TimeDelta
) OVERRIDE
;
679 // Restores the current state to the user's settings.
680 void RestoreCurrentFramebufferBindings();
682 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
683 void ApplyDirtyState();
685 // These check the state of the currently bound framebuffer or the
686 // backbuffer if no framebuffer is bound.
687 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
688 // check with all attached and enabled color attachments.
689 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
690 bool BoundFramebufferHasDepthAttachment();
691 bool BoundFramebufferHasStencilAttachment();
693 virtual error::ContextLostReason
GetContextLostReason() OVERRIDE
;
695 // Overridden from FramebufferManager::TextureDetachObserver:
696 virtual void OnTextureRefDetachedFromFramebuffer(
697 TextureRef
* texture
) OVERRIDE
;
699 // Overriden from ErrorStateClient.
700 virtual void OnOutOfMemoryError() OVERRIDE
;
702 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
703 void EnsureRenderbufferBound();
705 // Helpers to facilitate calling into compatible extensions.
706 static void RenderbufferStorageMultisampleHelper(
707 const FeatureInfo
* feature_info
,
710 GLenum internal_format
,
714 void BlitFramebufferHelper(GLint srcX0
,
726 friend class ScopedFrameBufferBinder
;
727 friend class ScopedResolvedFrameBufferBinder
;
728 friend class BackFramebuffer
;
730 // Initialize or re-initialize the shader translator.
731 bool InitializeShaderTranslator();
733 void UpdateCapabilities();
735 // Helpers for the glGen and glDelete functions.
736 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
737 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
738 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
739 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
740 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
741 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
742 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
743 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
744 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
745 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
746 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
747 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
749 // Helper for async upload token completion notification callback.
750 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
751 uint32 sync_data_shm_id
,
752 uint32 sync_data_shm_offset
);
757 void OnFboChanged() const;
758 void OnUseFramebuffer() const;
760 // TODO(gman): Cache these pointers?
761 BufferManager
* buffer_manager() {
762 return group_
->buffer_manager();
765 RenderbufferManager
* renderbuffer_manager() {
766 return group_
->renderbuffer_manager();
769 FramebufferManager
* framebuffer_manager() {
770 return group_
->framebuffer_manager();
773 ProgramManager
* program_manager() {
774 return group_
->program_manager();
777 ShaderManager
* shader_manager() {
778 return group_
->shader_manager();
781 ShaderTranslatorCache
* shader_translator_cache() {
782 return group_
->shader_translator_cache();
785 const TextureManager
* texture_manager() const {
786 return group_
->texture_manager();
789 TextureManager
* texture_manager() {
790 return group_
->texture_manager();
793 MailboxManager
* mailbox_manager() {
794 return group_
->mailbox_manager();
797 ImageManager
* image_manager() { return image_manager_
.get(); }
799 VertexArrayManager
* vertex_array_manager() {
800 return vertex_array_manager_
.get();
803 MemoryTracker
* memory_tracker() {
804 return group_
->memory_tracker();
807 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
808 MemoryTracker
* tracker
= memory_tracker();
810 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
815 bool IsOffscreenBufferMultisampled() const {
816 return offscreen_target_samples_
> 1;
819 // Creates a Texture for the given texture.
820 TextureRef
* CreateTexture(
821 GLuint client_id
, GLuint service_id
) {
822 return texture_manager()->CreateTexture(client_id
, service_id
);
825 // Gets the texture info for the given texture. Returns NULL if none exists.
826 TextureRef
* GetTexture(GLuint client_id
) const {
827 return texture_manager()->GetTexture(client_id
);
830 // Deletes the texture info for the given texture.
831 void RemoveTexture(GLuint client_id
) {
832 texture_manager()->RemoveTexture(client_id
);
835 // Get the size (in pixels) of the currently bound frame buffer (either FBO
836 // or regular back buffer).
837 gfx::Size
GetBoundReadFrameBufferSize();
839 // Get the format of the currently bound frame buffer (either FBO or regular
841 GLenum
GetBoundReadFrameBufferTextureType();
842 GLenum
GetBoundReadFrameBufferInternalFormat();
843 GLenum
GetBoundDrawFrameBufferInternalFormat();
845 // Wrapper for CompressedTexImage2D commands.
846 error::Error
DoCompressedTexImage2D(
849 GLenum internal_format
,
856 // Wrapper for CompressedTexSubImage2D.
857 void DoCompressedTexSubImage2D(
868 // Wrapper for CopyTexImage2D.
869 void DoCopyTexImage2D(
872 GLenum internal_format
,
879 // Wrapper for SwapBuffers.
880 void DoSwapBuffers();
882 // Wrapper for CopyTexSubImage2D.
883 void DoCopyTexSubImage2D(
893 // Validation for TexSubImage2D.
894 bool ValidateTexSubImage2D(
896 const char* function_name
,
907 // Wrapper for TexSubImage2D.
908 error::Error
DoTexSubImage2D(
919 // Extra validation for async tex(Sub)Image2D.
920 bool ValidateAsyncTransfer(
921 const char* function_name
,
922 TextureRef
* texture_ref
,
927 // Wrapper for TexImageIOSurface2DCHROMIUM.
928 void DoTexImageIOSurface2DCHROMIUM(
932 GLuint io_surface_id
,
935 void DoCopyTextureCHROMIUM(
940 GLenum internal_format
,
943 // Wrapper for TexStorage2DEXT.
944 void DoTexStorage2DEXT(
947 GLenum internal_format
,
951 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
952 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
954 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
955 GLenum target
, const GLbyte
* data
);
957 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
958 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
961 void DoBindTexImage2DCHROMIUM(
964 void DoReleaseTexImage2DCHROMIUM(
968 void DoTraceEndCHROMIUM(void);
970 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
972 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
974 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
975 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
977 // Creates a Program for the given program.
978 Program
* CreateProgram(
979 GLuint client_id
, GLuint service_id
) {
980 return program_manager()->CreateProgram(client_id
, service_id
);
983 // Gets the program info for the given program. Returns NULL if none exists.
984 Program
* GetProgram(GLuint client_id
) {
985 return program_manager()->GetProgram(client_id
);
989 void LogClientServiceMapping(
990 const char* /* function_name */,
991 GLuint
/* client_id */,
992 GLuint
/* service_id */) {
995 void LogClientServiceForInfo(
996 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
999 void LogClientServiceMapping(
1000 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1001 if (service_logging_
) {
1002 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1003 << ": client_id = " << client_id
1004 << ", service_id = " << service_id
;
1007 template<typename T
>
1008 void LogClientServiceForInfo(
1009 T
* info
, GLuint client_id
, const char* function_name
) {
1011 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1016 // Gets the program info for the given program. If it's not a program
1017 // generates a GL error. Returns NULL if not program.
1018 Program
* GetProgramInfoNotShader(
1019 GLuint client_id
, const char* function_name
) {
1020 Program
* program
= GetProgram(client_id
);
1022 if (GetShader(client_id
)) {
1024 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1029 LogClientServiceForInfo(program
, client_id
, function_name
);
1034 // Creates a Shader for the given shader.
1035 Shader
* CreateShader(
1038 GLenum shader_type
) {
1039 return shader_manager()->CreateShader(
1040 client_id
, service_id
, shader_type
);
1043 // Gets the shader info for the given shader. Returns NULL if none exists.
1044 Shader
* GetShader(GLuint client_id
) {
1045 return shader_manager()->GetShader(client_id
);
1048 // Gets the shader info for the given shader. If it's not a shader generates a
1049 // GL error. Returns NULL if not shader.
1050 Shader
* GetShaderInfoNotProgram(
1051 GLuint client_id
, const char* function_name
) {
1052 Shader
* shader
= GetShader(client_id
);
1054 if (GetProgram(client_id
)) {
1056 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1059 GL_INVALID_VALUE
, function_name
, "unknown shader");
1062 LogClientServiceForInfo(shader
, client_id
, function_name
);
1066 // Creates a buffer info for the given buffer.
1067 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1068 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1071 // Gets the buffer info for the given buffer.
1072 Buffer
* GetBuffer(GLuint client_id
) {
1073 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1077 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1078 // on glDeleteBuffers so we can make sure the user does not try to render
1079 // with deleted buffers.
1080 void RemoveBuffer(GLuint client_id
);
1082 // Creates a framebuffer info for the given framebuffer.
1083 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1084 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1087 // Gets the framebuffer info for the given framebuffer.
1088 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1089 return framebuffer_manager()->GetFramebuffer(client_id
);
1092 // Removes the framebuffer info for the given framebuffer.
1093 void RemoveFramebuffer(GLuint client_id
) {
1094 framebuffer_manager()->RemoveFramebuffer(client_id
);
1097 // Creates a renderbuffer info for the given renderbuffer.
1098 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1099 return renderbuffer_manager()->CreateRenderbuffer(
1100 client_id
, service_id
);
1103 // Gets the renderbuffer info for the given renderbuffer.
1104 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1105 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1108 // Removes the renderbuffer info for the given renderbuffer.
1109 void RemoveRenderbuffer(GLuint client_id
) {
1110 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1113 // Gets the vertex attrib manager for the given vertex array.
1114 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1115 VertexAttribManager
* info
=
1116 vertex_array_manager()->GetVertexAttribManager(client_id
);
1120 // Removes the vertex attrib manager for the given vertex array.
1121 void RemoveVertexAttribManager(GLuint client_id
) {
1122 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1125 // Creates a vertex attrib manager for the given vertex array.
1126 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1129 bool client_visible
) {
1130 return vertex_array_manager()->CreateVertexAttribManager(
1131 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1134 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1135 void DoBindUniformLocationCHROMIUM(
1136 GLuint client_id
, GLint location
, const char* name
);
1138 error::Error
GetAttribLocationHelper(
1139 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1140 const std::string
& name_str
);
1142 error::Error
GetUniformLocationHelper(
1143 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1144 const std::string
& name_str
);
1146 // Helper for glShaderSource.
1147 error::Error
ShaderSourceHelper(
1148 GLuint client_id
, const char* data
, uint32 data_size
);
1150 // Clear any textures used by the current program.
1151 bool ClearUnclearedTextures();
1153 // Clears any uncleared attachments attached to the given frame buffer.
1154 // Returns false if there was a generated GL error.
1155 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1157 // overridden from GLES2Decoder
1158 virtual bool ClearLevel(unsigned service_id
,
1159 unsigned bind_target
,
1162 unsigned internal_format
,
1167 bool is_texture_immutable
) OVERRIDE
;
1169 // Restore all GL state that affects clearing.
1170 void RestoreClearState();
1172 // Remembers the state of some capabilities.
1173 // Returns: true if glEnable/glDisable should actually be called.
1174 bool SetCapabilityState(GLenum cap
, bool enabled
);
1176 // Check that the currently bound framebuffers are valid.
1177 // Generates GL error if not.
1178 bool CheckBoundFramebuffersValid(const char* func_name
);
1180 // Check that the currently bound read framebuffer has a color image
1181 // attached. Generates GL error if not.
1182 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1184 // Check if a framebuffer meets our requirements.
1185 bool CheckFramebufferValid(
1186 Framebuffer
* framebuffer
,
1188 const char* func_name
);
1190 // Checks if the current program exists and is valid. If not generates the
1191 // appropriate GL error. Returns true if the current program is in a usable
1193 bool CheckCurrentProgram(const char* function_name
);
1195 // Checks if the current program exists and is valid and that location is not
1196 // -1. If the current program is not valid generates the appropriate GL
1197 // error. Returns true if the current program is in a usable state and
1198 // location is not -1.
1199 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1201 // Gets the type of a uniform for a location in the current program. Sets GL
1202 // errors if the current program is not valid. Returns true if the current
1203 // program is valid and the location exists. Adjusts count so it
1204 // does not overflow the uniform.
1205 bool PrepForSetUniformByLocation(GLint fake_location
,
1206 const char* function_name
,
1207 Program::UniformApiType api_type
,
1208 GLint
* real_location
,
1212 // Gets the service id for any simulated backbuffer fbo.
1213 GLuint
GetBackbufferServiceId() const;
1215 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1216 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1218 // Helper for glGetVertexAttrib
1219 void GetVertexAttribHelper(
1220 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1222 // Wrapper for glCreateProgram
1223 bool CreateProgramHelper(GLuint client_id
);
1225 // Wrapper for glCreateShader
1226 bool CreateShaderHelper(GLenum type
, GLuint client_id
);
1228 // Wrapper for glActiveTexture
1229 void DoActiveTexture(GLenum texture_unit
);
1231 // Wrapper for glAttachShader
1232 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1234 // Wrapper for glBindBuffer since we need to track the current targets.
1235 void DoBindBuffer(GLenum target
, GLuint buffer
);
1237 // Wrapper for glBindFramebuffer since we need to track the current targets.
1238 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1240 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1241 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1243 // Wrapper for glBindTexture since we need to track the current targets.
1244 void DoBindTexture(GLenum target
, GLuint texture
);
1246 // Wrapper for glBindVertexArrayOES
1247 void DoBindVertexArrayOES(GLuint array
);
1248 void EmulateVertexArrayState();
1250 // Wrapper for glBlitFramebufferCHROMIUM.
1251 void DoBlitFramebufferCHROMIUM(
1252 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1253 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1254 GLbitfield mask
, GLenum filter
);
1256 // Wrapper for glBufferSubData.
1257 void DoBufferSubData(
1258 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1260 // Wrapper for glCheckFramebufferStatus
1261 GLenum
DoCheckFramebufferStatus(GLenum target
);
1263 // Wrapper for glClear
1264 error::Error
DoClear(GLbitfield mask
);
1266 // Wrappers for various state.
1267 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1268 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1270 // Wrapper for glCompileShader.
1271 void DoCompileShader(GLuint shader
);
1273 // Helper for DeleteSharedIdsCHROMIUM commands.
1274 void DoDeleteSharedIdsCHROMIUM(
1275 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1277 // Wrapper for glDetachShader
1278 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1280 // Wrapper for glDisable
1281 void DoDisable(GLenum cap
);
1283 // Wrapper for glDisableVertexAttribArray.
1284 void DoDisableVertexAttribArray(GLuint index
);
1286 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1288 void DoDiscardFramebufferEXT(GLenum target
,
1289 GLsizei numAttachments
,
1290 const GLenum
* attachments
);
1292 // Wrapper for glEnable
1293 void DoEnable(GLenum cap
);
1295 // Wrapper for glEnableVertexAttribArray.
1296 void DoEnableVertexAttribArray(GLuint index
);
1298 // Wrapper for glFinish.
1301 // Wrapper for glFlush.
1304 // Wrapper for glFramebufferRenderbufffer.
1305 void DoFramebufferRenderbuffer(
1306 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1307 GLuint renderbuffer
);
1309 // Wrapper for glFramebufferTexture2D.
1310 void DoFramebufferTexture2D(
1311 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1314 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1315 void DoFramebufferTexture2DMultisample(
1316 GLenum target
, GLenum attachment
, GLenum textarget
,
1317 GLuint texture
, GLint level
, GLsizei samples
);
1319 // Common implementation for both DoFramebufferTexture2D wrappers.
1320 void DoFramebufferTexture2DCommon(const char* name
,
1321 GLenum target
, GLenum attachment
, GLenum textarget
,
1322 GLuint texture
, GLint level
, GLsizei samples
);
1324 // Wrapper for glGenerateMipmap
1325 void DoGenerateMipmap(GLenum target
);
1327 // Helper for GenSharedIdsCHROMIUM commands.
1328 void DoGenSharedIdsCHROMIUM(
1329 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
);
1331 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1332 // to account for different pname values defined in different extension
1334 GLenum
AdjustGetPname(GLenum pname
);
1336 // Wrapper for DoGetBooleanv.
1337 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1339 // Wrapper for DoGetFloatv.
1340 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1342 // Wrapper for glGetFramebufferAttachmentParameteriv.
1343 void DoGetFramebufferAttachmentParameteriv(
1344 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1346 // Wrapper for glGetIntegerv.
1347 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1349 // Gets the max value in a range in a buffer.
1350 GLuint
DoGetMaxValueInBufferCHROMIUM(
1351 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1353 // Wrapper for glGetBufferParameteriv.
1354 void DoGetBufferParameteriv(
1355 GLenum target
, GLenum pname
, GLint
* params
);
1357 // Wrapper for glGetProgramiv.
1358 void DoGetProgramiv(
1359 GLuint program_id
, GLenum pname
, GLint
* params
);
1361 // Wrapper for glRenderbufferParameteriv.
1362 void DoGetRenderbufferParameteriv(
1363 GLenum target
, GLenum pname
, GLint
* params
);
1365 // Wrapper for glGetShaderiv
1366 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1368 // Wrappers for glGetTexParameter.
1369 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1370 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1371 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1373 // Wrappers for glGetVertexAttrib.
1374 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1375 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1377 // Wrappers for glIsXXX functions.
1378 bool DoIsEnabled(GLenum cap
);
1379 bool DoIsBuffer(GLuint client_id
);
1380 bool DoIsFramebuffer(GLuint client_id
);
1381 bool DoIsProgram(GLuint client_id
);
1382 bool DoIsRenderbuffer(GLuint client_id
);
1383 bool DoIsShader(GLuint client_id
);
1384 bool DoIsTexture(GLuint client_id
);
1385 bool DoIsVertexArrayOES(GLuint client_id
);
1387 // Wrapper for glLinkProgram
1388 void DoLinkProgram(GLuint program
);
1390 // Helper for RegisterSharedIdsCHROMIUM.
1391 void DoRegisterSharedIdsCHROMIUM(
1392 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1394 // Wrapper for glRenderbufferStorage.
1395 void DoRenderbufferStorage(
1396 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1398 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1399 void DoRenderbufferStorageMultisampleCHROMIUM(
1400 GLenum target
, GLsizei samples
, GLenum internalformat
,
1401 GLsizei width
, GLsizei height
);
1403 // Handler for glRenderbufferStorageMultisampleEXT
1404 // (multisampled_render_to_texture).
1405 void DoRenderbufferStorageMultisampleEXT(
1406 GLenum target
, GLsizei samples
, GLenum internalformat
,
1407 GLsizei width
, GLsizei height
);
1409 // Common validation for multisample extensions.
1410 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1411 GLenum internalformat
,
1415 // Verifies that the currently bound multisample renderbuffer is valid
1416 // Very slow! Only done on platforms with driver bugs that return invalid
1417 // buffers under memory pressure
1418 bool VerifyMultisampleRenderbufferIntegrity(
1419 GLuint renderbuffer
, GLenum format
);
1421 // Wrapper for glReleaseShaderCompiler.
1422 void DoReleaseShaderCompiler() { }
1424 // Wrappers for glTexParameter functions.
1425 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1426 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1427 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1428 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1430 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1431 // spec only these 2 functions can be used to set sampler uniforms.
1432 void DoUniform1i(GLint fake_location
, GLint v0
);
1433 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1434 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1435 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1436 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1438 // Wrappers for glUniformfv because some drivers don't correctly accept
1440 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1441 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1442 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1443 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1445 void DoUniformMatrix2fv(
1446 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1447 const GLfloat
* value
);
1448 void DoUniformMatrix3fv(
1449 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1450 const GLfloat
* value
);
1451 void DoUniformMatrix4fv(
1452 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1453 const GLfloat
* value
);
1455 bool SetVertexAttribValue(
1456 const char* function_name
, GLuint index
, const GLfloat
* value
);
1458 // Wrappers for glVertexAttrib??
1459 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1460 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1461 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1462 void DoVertexAttrib4f(
1463 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1464 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1465 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1466 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1467 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1469 // Wrapper for glViewport
1470 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1472 // Wrapper for glUseProgram
1473 void DoUseProgram(GLuint program
);
1475 // Wrapper for glValidateProgram.
1476 void DoValidateProgram(GLuint program_client_id
);
1478 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1479 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1480 void DoPopGroupMarkerEXT(void);
1482 // Gets the number of values that will be returned by glGetXXX. Returns
1483 // false if pname is unknown.
1484 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1486 // Checks if the current program and vertex attributes are valid for drawing.
1488 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1491 // Returns true if successful, simulated will be true if attrib0 was
1493 bool SimulateAttrib0(
1494 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1495 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1497 // If an image is bound to texture, this will call Will/DidUseTexImage
1499 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1500 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1502 // Returns false if textures were replaced.
1503 bool PrepareTexturesForRender();
1504 void RestoreStateForTextures();
1506 // Returns true if GL_FIXED attribs were simulated.
1507 bool SimulateFixedAttribs(
1508 const char* function_name
,
1509 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1510 void RestoreStateForSimulatedFixedAttribs();
1512 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1513 // cases (primcount is always 1 for non-instanced).
1514 error::Error
DoDrawArrays(
1515 const char* function_name
,
1516 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1518 error::Error
DoDrawElements(
1519 const char* function_name
,
1520 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1521 int32 offset
, GLsizei primcount
);
1523 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1524 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1525 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1528 return GL_TEXTURE_2D
;
1529 case GL_SAMPLER_CUBE
:
1530 return GL_TEXTURE_CUBE_MAP
;
1531 case GL_SAMPLER_EXTERNAL_OES
:
1532 return GL_TEXTURE_EXTERNAL_OES
;
1533 case GL_SAMPLER_2D_RECT_ARB
:
1534 return GL_TEXTURE_RECTANGLE_ARB
;
1541 // Gets the framebuffer info for a particular target.
1542 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1543 Framebuffer
* framebuffer
= NULL
;
1545 case GL_FRAMEBUFFER
:
1546 case GL_DRAW_FRAMEBUFFER_EXT
:
1547 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1549 case GL_READ_FRAMEBUFFER_EXT
:
1550 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1559 Renderbuffer
* GetRenderbufferInfoForTarget(
1561 Renderbuffer
* renderbuffer
= NULL
;
1563 case GL_RENDERBUFFER
:
1564 renderbuffer
= state_
.bound_renderbuffer
.get();
1570 return renderbuffer
;
1573 // Validates the program and location for a glGetUniform call and returns
1574 // a SizeResult setup to receive the result. Returns true if glGetUniform
1575 // should be called.
1576 bool GetUniformSetup(
1577 GLuint program
, GLint fake_location
,
1578 uint32 shm_id
, uint32 shm_offset
,
1579 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1580 void** result
, GLenum
* result_type
);
1582 virtual bool WasContextLost() OVERRIDE
;
1583 virtual bool WasContextLostByRobustnessExtension() OVERRIDE
;
1584 virtual void LoseContext(uint32 reset_status
) OVERRIDE
;
1586 #if defined(OS_MACOSX)
1587 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1590 bool ValidateCompressedTexDimensions(
1591 const char* function_name
,
1592 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1593 bool ValidateCompressedTexFuncData(
1594 const char* function_name
,
1595 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1596 bool ValidateCompressedTexSubDimensions(
1597 const char* function_name
,
1598 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1599 GLsizei width
, GLsizei height
, GLenum format
,
1602 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1603 void PerformanceWarning(
1604 const char* filename
, int line
, const std::string
& msg
);
1606 const FeatureInfo::FeatureFlags
& features() const {
1607 return feature_info_
->feature_flags();
1610 const FeatureInfo::Workarounds
& workarounds() const {
1611 return feature_info_
->workarounds();
1614 bool ShouldDeferDraws() {
1615 return !offscreen_target_frame_buffer_
.get() &&
1616 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1617 surface_
->DeferDraws();
1620 bool ShouldDeferReads() {
1621 return !offscreen_target_frame_buffer_
.get() &&
1622 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1623 surface_
->DeferDraws();
1626 error::Error
WillAccessBoundFramebufferForDraw() {
1627 if (ShouldDeferDraws())
1628 return error::kDeferCommandUntilLater
;
1629 if (!offscreen_target_frame_buffer_
.get() &&
1630 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1631 !surface_
->SetBackbufferAllocation(true))
1632 return error::kLostContext
;
1633 return error::kNoError
;
1636 error::Error
WillAccessBoundFramebufferForRead() {
1637 if (ShouldDeferReads())
1638 return error::kDeferCommandUntilLater
;
1639 if (!offscreen_target_frame_buffer_
.get() &&
1640 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1641 !surface_
->SetBackbufferAllocation(true))
1642 return error::kLostContext
;
1643 return error::kNoError
;
1646 // Set remaining commands to process to 0 to force DoCommands to return
1647 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1648 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1650 void ProcessPendingReadPixels();
1651 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1653 // Generate a member function prototype for each command in an automated and
1655 #define GLES2_CMD_OP(name) \
1656 Error Handle##name(uint32 immediate_data_size, const void* data);
1658 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1662 // The GL context this decoder renders to on behalf of the client.
1663 scoped_refptr
<gfx::GLSurface
> surface_
;
1664 scoped_refptr
<gfx::GLContext
> context_
;
1666 // The ContextGroup for this decoder uses to track resources.
1667 scoped_refptr
<ContextGroup
> group_
;
1669 DebugMarkerManager debug_marker_manager_
;
1672 // All the state for this context.
1673 ContextState state_
;
1675 // Current width and height of the offscreen frame buffer.
1676 gfx::Size offscreen_size_
;
1678 // Util to help with GL.
1681 // unpack flip y as last set by glPixelStorei
1682 bool unpack_flip_y_
;
1684 // unpack (un)premultiply alpha as last set by glPixelStorei
1685 bool unpack_premultiply_alpha_
;
1686 bool unpack_unpremultiply_alpha_
;
1688 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1689 GLuint attrib_0_buffer_id_
;
1691 // The value currently in attrib_0.
1692 Vec4 attrib_0_value_
;
1694 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1695 bool attrib_0_buffer_matches_value_
;
1697 // The size of attrib 0.
1698 GLsizei attrib_0_size_
;
1700 // The buffer used to simulate GL_FIXED attribs.
1701 GLuint fixed_attrib_buffer_id_
;
1703 // The size of fiixed attrib buffer.
1704 GLsizei fixed_attrib_buffer_size_
;
1706 // The offscreen frame buffer that the client renders to. With EGL, the
1707 // depth and stencil buffers are separate. With regular GL there is a single
1708 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1709 // offscreen_target_stencil_render_buffer_ is unused.
1710 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1711 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1712 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1713 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1714 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1715 GLenum offscreen_target_color_format_
;
1716 GLenum offscreen_target_depth_format_
;
1717 GLenum offscreen_target_stencil_format_
;
1718 GLsizei offscreen_target_samples_
;
1719 GLboolean offscreen_target_buffer_preserved_
;
1721 // The copy that is saved when SwapBuffers is called.
1722 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1723 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1724 scoped_refptr
<TextureRef
>
1725 offscreen_saved_color_texture_info_
;
1727 // The copy that is used as the destination for multi-sample resolves.
1728 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1729 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1730 GLenum offscreen_saved_color_format_
;
1732 scoped_ptr
<QueryManager
> query_manager_
;
1734 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1736 scoped_ptr
<ImageManager
> image_manager_
;
1738 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1740 WaitSyncPointCallback wait_sync_point_callback_
;
1742 ShaderCacheCallback shader_cache_callback_
;
1744 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1746 // The format of the back buffer_
1747 GLenum back_buffer_color_format_
;
1748 bool back_buffer_has_depth_
;
1749 bool back_buffer_has_stencil_
;
1751 // Backbuffer attachments that are currently undefined.
1752 uint32 backbuffer_needs_clear_bits_
;
1754 // The current decoder error communicates the decoder error through command
1755 // processing functions that do not return the error value. Should be set only
1756 // if not returning an error.
1757 error::Error current_decoder_error_
;
1759 bool use_shader_translator_
;
1760 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1761 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1763 DisallowedFeatures disallowed_features_
;
1765 // Cached from ContextGroup
1766 const Validators
* validators_
;
1767 scoped_refptr
<FeatureInfo
> feature_info_
;
1771 // Number of commands remaining to be processed in DoCommands().
1772 int commands_to_process_
;
1774 bool has_robustness_extension_
;
1775 GLenum reset_status_
;
1776 bool reset_by_robustness_extension_
;
1777 bool supports_post_sub_buffer_
;
1779 // These flags are used to override the state of the shared feature_info_
1780 // member. Because the same FeatureInfo instance may be shared among many
1781 // contexts, the assumptions on the availablity of extensions in WebGL
1782 // contexts may be broken. These flags override the shared state to preserve
1784 bool force_webgl_glsl_validation_
;
1785 bool derivatives_explicitly_enabled_
;
1786 bool frag_depth_explicitly_enabled_
;
1787 bool draw_buffers_explicitly_enabled_
;
1788 bool shader_texture_lod_explicitly_enabled_
;
1790 bool compile_shader_always_succeeds_
;
1792 // An optional behaviour to lose the context and group when OOM.
1793 bool lose_context_when_out_of_memory_
;
1796 bool service_logging_
;
1798 #if defined(OS_MACOSX)
1799 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1800 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1803 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1805 // Cached values of the currently assigned viewport dimensions.
1806 GLsizei viewport_max_width_
;
1807 GLsizei viewport_max_height_
;
1809 // Command buffer stats.
1810 base::TimeDelta total_processing_commands_time_
;
1812 // States related to each manager.
1813 DecoderTextureState texture_state_
;
1814 DecoderFramebufferState framebuffer_state_
;
1816 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1817 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1818 const unsigned char* cb_command_trace_category_
;
1819 int gpu_trace_level_
;
1820 bool gpu_trace_commands_
;
1821 bool gpu_debug_commands_
;
1823 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1825 // Used to validate multisample renderbuffers if needed
1826 GLuint validation_texture_
;
1827 GLuint validation_fbo_multisample_
;
1828 GLuint validation_fbo_
;
1830 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1831 uint32 immediate_data_size
,
1834 // A struct to hold info about each command.
1835 struct CommandInfo
{
1836 CmdHandler cmd_handler
;
1837 uint8 arg_flags
; // How to handle the arguments for this command
1838 uint8 cmd_flags
; // How to handle this command
1839 uint16 arg_count
; // How many arguments are expected for this command.
1842 // A table of CommandInfo for all the commands.
1843 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1845 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1848 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1849 #define GLES2_CMD_OP(name) \
1851 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1852 cmds::name::cmd_flags, \
1853 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1856 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1860 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1861 const char* function_name
, ErrorState
* error_state
)
1862 : function_name_(function_name
),
1863 error_state_(error_state
) {
1864 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1867 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1868 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1871 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1872 TextureUnit
& info
= state
->texture_units
[0];
1874 scoped_refptr
<TextureRef
> texture_ref
;
1877 texture_ref
= info
.bound_texture_2d
;
1879 case GL_TEXTURE_CUBE_MAP
:
1880 texture_ref
= info
.bound_texture_cube_map
;
1882 case GL_TEXTURE_EXTERNAL_OES
:
1883 texture_ref
= info
.bound_texture_external_oes
;
1885 case GL_TEXTURE_RECTANGLE_ARB
:
1886 texture_ref
= info
.bound_texture_rectangle_arb
;
1892 if (texture_ref
.get()) {
1893 last_id
= texture_ref
->service_id();
1898 glBindTexture(target
, last_id
);
1899 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1902 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1907 ScopedGLErrorSuppressor
suppressor(
1908 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1910 // TODO(apatrick): Check if there are any other states that need to be reset
1911 // before binding a new texture.
1912 glActiveTexture(GL_TEXTURE0
);
1913 glBindTexture(target
, id
);
1916 ScopedTextureBinder::~ScopedTextureBinder() {
1917 ScopedGLErrorSuppressor
suppressor(
1918 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1919 RestoreCurrentTextureBindings(state_
, target_
);
1922 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1925 ScopedGLErrorSuppressor
suppressor(
1926 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1927 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1930 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1931 ScopedGLErrorSuppressor
suppressor(
1932 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
1933 state_
->RestoreRenderbufferBindings();
1936 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
1938 : decoder_(decoder
) {
1939 ScopedGLErrorSuppressor
suppressor(
1940 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1941 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
1942 decoder
->OnFboChanged();
1945 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1946 ScopedGLErrorSuppressor
suppressor(
1947 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1948 decoder_
->RestoreCurrentFramebufferBindings();
1951 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1952 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
1953 : decoder_(decoder
) {
1954 resolve_and_bind_
= (
1955 decoder_
->offscreen_target_frame_buffer_
.get() &&
1956 decoder_
->IsOffscreenBufferMultisampled() &&
1957 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
1958 enforce_internal_framebuffer
));
1959 if (!resolve_and_bind_
)
1962 ScopedGLErrorSuppressor
suppressor(
1963 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1964 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
1965 decoder_
->offscreen_target_frame_buffer_
->id());
1968 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
1969 decoder_
->offscreen_resolved_frame_buffer_
.reset(
1970 new BackFramebuffer(decoder_
));
1971 decoder_
->offscreen_resolved_frame_buffer_
->Create();
1972 decoder_
->offscreen_resolved_color_texture_
.reset(
1973 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
1974 decoder_
->offscreen_resolved_color_texture_
->Create();
1976 DCHECK(decoder_
->offscreen_saved_color_format_
);
1977 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
1978 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
1980 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
1981 decoder_
->offscreen_resolved_color_texture_
.get());
1982 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
1983 GL_FRAMEBUFFER_COMPLETE
) {
1984 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
1985 << "because offscreen resolved FBO was incomplete.";
1989 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
1991 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
1993 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
1994 const int width
= decoder_
->offscreen_size_
.width();
1995 const int height
= decoder_
->offscreen_size_
.height();
1996 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
1997 decoder
->BlitFramebufferHelper(0,
2005 GL_COLOR_BUFFER_BIT
,
2007 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2010 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2011 if (!resolve_and_bind_
)
2014 ScopedGLErrorSuppressor
suppressor(
2015 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2016 decoder_
->RestoreCurrentFramebufferBindings();
2017 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2018 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2022 BackTexture::BackTexture(
2023 MemoryTracker
* memory_tracker
,
2024 ContextState
* state
)
2025 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2027 bytes_allocated_(0),
2031 BackTexture::~BackTexture() {
2032 // This does not destroy the render texture because that would require that
2033 // the associated GL context was current. Just check that it was explicitly
2038 void BackTexture::Create() {
2039 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2040 state_
->GetErrorState());
2042 glGenTextures(1, &id_
);
2043 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2044 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2045 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2046 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2047 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2049 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2050 // never called on an offscreen context, no data will ever be uploaded to the
2051 // saved offscreen color texture (it is deferred until to when SwapBuffers
2052 // is called). My idea is that some nvidia drivers might have a bug where
2053 // deleting a texture that has never been populated might cause a
2056 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2058 bytes_allocated_
= 16u * 16u * 4u;
2059 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2062 bool BackTexture::AllocateStorage(
2063 const gfx::Size
& size
, GLenum format
, bool zero
) {
2065 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2066 state_
->GetErrorState());
2067 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2068 uint32 image_size
= 0;
2069 GLES2Util::ComputeImageDataSizes(
2070 size
.width(), size
.height(), format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2073 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2077 scoped_ptr
<char[]> zero_data
;
2079 zero_data
.reset(new char[image_size
]);
2080 memset(zero_data
.get(), 0, image_size
);
2083 glTexImage2D(GL_TEXTURE_2D
,
2095 bool success
= glGetError() == GL_NO_ERROR
;
2097 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2098 bytes_allocated_
= image_size
;
2099 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2104 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2106 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2107 state_
->GetErrorState());
2108 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2109 glCopyTexImage2D(GL_TEXTURE_2D
,
2118 void BackTexture::Destroy() {
2120 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2121 state_
->GetErrorState());
2122 glDeleteTextures(1, &id_
);
2125 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2126 bytes_allocated_
= 0;
2129 void BackTexture::Invalidate() {
2133 BackRenderbuffer::BackRenderbuffer(
2134 RenderbufferManager
* renderbuffer_manager
,
2135 MemoryTracker
* memory_tracker
,
2136 ContextState
* state
)
2137 : renderbuffer_manager_(renderbuffer_manager
),
2138 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2140 bytes_allocated_(0),
2144 BackRenderbuffer::~BackRenderbuffer() {
2145 // This does not destroy the render buffer because that would require that
2146 // the associated GL context was current. Just check that it was explicitly
2151 void BackRenderbuffer::Create() {
2152 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2153 state_
->GetErrorState());
2155 glGenRenderbuffersEXT(1, &id_
);
2158 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2159 const gfx::Size
& size
,
2162 ScopedGLErrorSuppressor
suppressor(
2163 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2164 ScopedRenderBufferBinder
binder(state_
, id_
);
2166 uint32 estimated_size
= 0;
2167 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2168 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2172 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2177 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2182 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2189 bool success
= glGetError() == GL_NO_ERROR
;
2191 // Mark the previously allocated bytes as free.
2192 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2193 bytes_allocated_
= estimated_size
;
2194 // Track the newly allocated bytes.
2195 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2200 void BackRenderbuffer::Destroy() {
2202 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2203 state_
->GetErrorState());
2204 glDeleteRenderbuffersEXT(1, &id_
);
2207 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2208 bytes_allocated_
= 0;
2211 void BackRenderbuffer::Invalidate() {
2215 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2216 : decoder_(decoder
),
2220 BackFramebuffer::~BackFramebuffer() {
2221 // This does not destroy the frame buffer because that would require that
2222 // the associated GL context was current. Just check that it was explicitly
2227 void BackFramebuffer::Create() {
2228 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2229 decoder_
->GetErrorState());
2231 glGenFramebuffersEXT(1, &id_
);
2234 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2236 ScopedGLErrorSuppressor
suppressor(
2237 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2238 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2239 GLuint attach_id
= texture
? texture
->id() : 0;
2240 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2241 GL_COLOR_ATTACHMENT0
,
2247 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2248 BackRenderbuffer
* render_buffer
) {
2250 ScopedGLErrorSuppressor
suppressor(
2251 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2252 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2253 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2254 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2260 void BackFramebuffer::Destroy() {
2262 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2263 decoder_
->GetErrorState());
2264 glDeleteFramebuffersEXT(1, &id_
);
2269 void BackFramebuffer::Invalidate() {
2273 GLenum
BackFramebuffer::CheckStatus() {
2275 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2276 decoder_
->GetErrorState());
2277 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2278 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2281 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2282 return new GLES2DecoderImpl(group
);
2285 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2288 logger_(&debug_marker_manager_
),
2289 state_(group_
->feature_info(), this, &logger_
),
2290 unpack_flip_y_(false),
2291 unpack_premultiply_alpha_(false),
2292 unpack_unpremultiply_alpha_(false),
2293 attrib_0_buffer_id_(0),
2294 attrib_0_buffer_matches_value_(true),
2296 fixed_attrib_buffer_id_(0),
2297 fixed_attrib_buffer_size_(0),
2298 offscreen_target_color_format_(0),
2299 offscreen_target_depth_format_(0),
2300 offscreen_target_stencil_format_(0),
2301 offscreen_target_samples_(0),
2302 offscreen_target_buffer_preserved_(true),
2303 offscreen_saved_color_format_(0),
2304 back_buffer_color_format_(0),
2305 back_buffer_has_depth_(false),
2306 back_buffer_has_stencil_(false),
2307 backbuffer_needs_clear_bits_(0),
2308 current_decoder_error_(error::kNoError
),
2309 use_shader_translator_(true),
2310 validators_(group_
->feature_info()->validators()),
2311 feature_info_(group_
->feature_info()),
2313 has_robustness_extension_(false),
2314 reset_status_(GL_NO_ERROR
),
2315 reset_by_robustness_extension_(false),
2316 supports_post_sub_buffer_(false),
2317 force_webgl_glsl_validation_(false),
2318 derivatives_explicitly_enabled_(false),
2319 frag_depth_explicitly_enabled_(false),
2320 draw_buffers_explicitly_enabled_(false),
2321 shader_texture_lod_explicitly_enabled_(false),
2322 compile_shader_always_succeeds_(false),
2323 lose_context_when_out_of_memory_(false),
2324 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2325 switches::kEnableGPUServiceLoggingGPU
)),
2326 viewport_max_width_(0),
2327 viewport_max_height_(0),
2328 texture_state_(group_
->feature_info()
2330 .texsubimage2d_faster_than_teximage2d
),
2331 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2332 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2333 gpu_trace_level_(2),
2334 gpu_trace_commands_(false),
2335 gpu_debug_commands_(false),
2336 validation_texture_(0),
2337 validation_fbo_multisample_(0),
2338 validation_fbo_(0) {
2341 attrib_0_value_
.v
[0] = 0.0f
;
2342 attrib_0_value_
.v
[1] = 0.0f
;
2343 attrib_0_value_
.v
[2] = 0.0f
;
2344 attrib_0_value_
.v
[3] = 1.0f
;
2346 // The shader translator is used for WebGL even when running on EGL
2347 // because additional restrictions are needed (like only enabling
2348 // GL_OES_standard_derivatives on demand). It is used for the unit
2349 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2350 // the empty string to CompileShader and this is not a valid shader.
2351 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2352 CommandLine::ForCurrentProcess()->HasSwitch(
2353 switches::kDisableGLSLTranslator
)) {
2354 use_shader_translator_
= false;
2358 GLES2DecoderImpl::~GLES2DecoderImpl() {
2361 bool GLES2DecoderImpl::Initialize(
2362 const scoped_refptr
<gfx::GLSurface
>& surface
,
2363 const scoped_refptr
<gfx::GLContext
>& context
,
2365 const gfx::Size
& size
,
2366 const DisallowedFeatures
& disallowed_features
,
2367 const std::vector
<int32
>& attribs
) {
2368 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2369 DCHECK(context
->IsCurrent(surface
.get()));
2370 DCHECK(!context_
.get());
2373 gpu_tracer_
.reset(new GPUTracer(this));
2374 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2376 if (CommandLine::ForCurrentProcess()->HasSwitch(
2377 switches::kEnableGPUDebugging
)) {
2381 if (CommandLine::ForCurrentProcess()->HasSwitch(
2382 switches::kEnableGPUCommandLogging
)) {
2383 set_log_commands(true);
2386 compile_shader_always_succeeds_
= CommandLine::ForCurrentProcess()->HasSwitch(
2387 switches::kCompileShaderAlwaysSucceeds
);
2390 // Take ownership of the context and surface. The surface can be replaced with
2395 ContextCreationAttribHelper attrib_parser
;
2396 if (!attrib_parser
.Parse(attribs
))
2399 // Save the loseContextWhenOutOfMemory context creation attribute.
2400 lose_context_when_out_of_memory_
=
2401 attrib_parser
.lose_context_when_out_of_memory
;
2403 // If the failIfMajorPerformanceCaveat context creation attribute was true
2404 // and we are using a software renderer, fail.
2405 if (attrib_parser
.fail_if_major_perf_caveat
&&
2406 feature_info_
->feature_flags().is_swiftshader
) {
2407 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2412 if (!group_
->Initialize(this, disallowed_features
)) {
2413 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2414 << "failed to initialize.";
2415 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2421 disallowed_features_
= disallowed_features
;
2423 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2424 vertex_array_manager_
.reset(new VertexArrayManager());
2426 GLuint default_vertex_attrib_service_id
= 0;
2427 if (features().native_vertex_array_object
) {
2428 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2429 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2432 state_
.default_vertex_attrib_manager
=
2433 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2435 state_
.default_vertex_attrib_manager
->Initialize(
2436 group_
->max_vertex_attribs(),
2437 feature_info_
->workarounds().init_vertex_attributes
);
2439 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2440 DoBindVertexArrayOES(0);
2442 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2444 image_manager_
.reset(new ImageManager
);
2446 util_
.set_num_compressed_texture_formats(
2447 validators_
->compressed_texture_format
.GetValues().size());
2449 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2450 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2451 // OpenGL ES 2.0 does not have this issue.
2452 glEnableVertexAttribArray(0);
2454 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2455 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2456 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2457 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2458 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2460 state_
.texture_units
.resize(group_
->max_texture_units());
2461 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2462 glActiveTexture(GL_TEXTURE0
+ tt
);
2463 // We want the last bind to be 2D.
2465 if (features().oes_egl_image_external
) {
2466 ref
= texture_manager()->GetDefaultTextureInfo(
2467 GL_TEXTURE_EXTERNAL_OES
);
2468 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2469 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2471 if (features().arb_texture_rectangle
) {
2472 ref
= texture_manager()->GetDefaultTextureInfo(
2473 GL_TEXTURE_RECTANGLE_ARB
);
2474 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2475 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2477 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2478 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2479 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2480 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2481 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2482 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2484 glActiveTexture(GL_TEXTURE0
);
2488 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2489 features().chromium_framebuffer_multisample
) {
2490 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2491 // max_sample_count must be initialized to a sane value. If
2492 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2493 GLint max_sample_count
= 1;
2494 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2495 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2498 offscreen_target_samples_
= 1;
2500 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2502 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2503 const bool rgb8_supported
=
2504 context_
->HasExtension("GL_OES_rgb8_rgba8");
2505 // The only available default render buffer formats in GLES2 have very
2506 // little precision. Don't enable multisampling unless 8-bit render
2507 // buffer formats are available--instead fall back to 8-bit textures.
2508 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2509 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2512 offscreen_target_samples_
= 1;
2513 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2517 // ANGLE only supports packed depth/stencil formats, so use it if it is
2519 const bool depth24_stencil8_supported
=
2520 feature_info_
->feature_flags().packed_depth24_stencil8
;
2521 VLOG(1) << "GL_OES_packed_depth_stencil "
2522 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2523 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2524 depth24_stencil8_supported
) {
2525 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2526 offscreen_target_stencil_format_
= 0;
2528 // It may be the case that this depth/stencil combination is not
2529 // supported, but this will be checked later by CheckFramebufferStatus.
2530 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2531 GL_DEPTH_COMPONENT16
: 0;
2532 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2533 GL_STENCIL_INDEX8
: 0;
2536 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2539 // If depth is requested at all, use the packed depth stencil format if
2540 // it's available, as some desktop GL drivers don't support any non-packed
2541 // formats for depth attachments.
2542 const bool depth24_stencil8_supported
=
2543 feature_info_
->feature_flags().packed_depth24_stencil8
;
2544 VLOG(1) << "GL_EXT_packed_depth_stencil "
2545 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2547 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2548 depth24_stencil8_supported
) {
2549 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2550 offscreen_target_stencil_format_
= 0;
2552 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2553 GL_DEPTH_COMPONENT
: 0;
2554 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2555 GL_STENCIL_INDEX
: 0;
2559 offscreen_saved_color_format_
= attrib_parser
.alpha_size
> 0 ?
2562 // Create the target frame buffer. This is the one that the client renders
2564 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2565 offscreen_target_frame_buffer_
->Create();
2566 // Due to GLES2 format limitations, either the color texture (for
2567 // non-multisampling) or the color render buffer (for multisampling) will be
2568 // attached to the offscreen frame buffer. The render buffer has more
2569 // limited formats available to it, but the texture can't do multisampling.
2570 if (IsOffscreenBufferMultisampled()) {
2571 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2572 renderbuffer_manager(), memory_tracker(), &state_
));
2573 offscreen_target_color_render_buffer_
->Create();
2575 offscreen_target_color_texture_
.reset(new BackTexture(
2576 memory_tracker(), &state_
));
2577 offscreen_target_color_texture_
->Create();
2579 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2580 renderbuffer_manager(), memory_tracker(), &state_
));
2581 offscreen_target_depth_render_buffer_
->Create();
2582 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2583 renderbuffer_manager(), memory_tracker(), &state_
));
2584 offscreen_target_stencil_render_buffer_
->Create();
2586 // Create the saved offscreen texture. The target frame buffer is copied
2587 // here when SwapBuffers is called.
2588 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2589 offscreen_saved_frame_buffer_
->Create();
2591 offscreen_saved_color_texture_
.reset(new BackTexture(
2592 memory_tracker(), &state_
));
2593 offscreen_saved_color_texture_
->Create();
2595 // Allocate the render buffers at their initial size and check the status
2596 // of the frame buffers is okay.
2597 if (!ResizeOffscreenFrameBuffer(size
)) {
2598 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2603 // Allocate the offscreen saved color texture.
2604 DCHECK(offscreen_saved_color_format_
);
2605 offscreen_saved_color_texture_
->AllocateStorage(
2606 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2608 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2609 offscreen_saved_color_texture_
.get());
2610 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2611 GL_FRAMEBUFFER_COMPLETE
) {
2612 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2617 // Bind to the new default frame buffer (the offscreen target frame buffer).
2618 // This should now be associated with ID zero.
2619 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2621 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2622 // These are NOT if the back buffer has these proprorties. They are
2623 // if we want the command buffer to enforce them regardless of what
2624 // the real backbuffer is assuming the real back buffer gives us more than
2625 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2626 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2627 // can't do anything about that.
2630 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2631 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2632 // user requested RGB then RGB. If the user did not specify a preference
2633 // than use whatever we were given. Same for DEPTH and STENCIL.
2634 back_buffer_color_format_
=
2635 (attrib_parser
.alpha_size
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2636 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2637 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && v
> 0;
2638 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2639 back_buffer_has_stencil_
= attrib_parser
.stencil_size
!= 0 && v
> 0;
2642 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2643 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2644 // isn't well documented; it was discovered in the Khronos OpenGL ES
2645 // mailing list archives. It also implicitly enables the desktop GL
2646 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2647 // variable in fragment shaders.
2648 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2649 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2650 glEnable(GL_POINT_SPRITE
);
2653 has_robustness_extension_
=
2654 context
->HasExtension("GL_ARB_robustness") ||
2655 context
->HasExtension("GL_EXT_robustness");
2657 if (!InitializeShaderTranslator()) {
2661 state_
.viewport_width
= size
.width();
2662 state_
.viewport_height
= size
.height();
2664 GLint viewport_params
[4] = { 0 };
2665 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2666 viewport_max_width_
= viewport_params
[0];
2667 viewport_max_height_
= viewport_params
[1];
2669 state_
.scissor_width
= state_
.viewport_width
;
2670 state_
.scissor_height
= state_
.viewport_height
;
2672 // Set all the default state because some GL drivers get it wrong.
2673 state_
.InitCapabilities(NULL
);
2674 state_
.InitState(NULL
);
2675 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2677 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2678 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2679 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2680 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2682 bool call_gl_clear
= true;
2683 #if defined(OS_ANDROID)
2684 // Temporary workaround for Android WebView because this clear ignores the
2685 // clip and corrupts that external UI of the App. Not calling glClear is ok
2686 // because the system already clears the buffer before each draw. Proper
2687 // fix might be setting the scissor clip properly before initialize. See
2688 // crbug.com/259023 for details.
2689 call_gl_clear
= surface_
->GetHandle();
2691 if (call_gl_clear
) {
2692 // Clear the backbuffer.
2693 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2696 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2697 if (feature_info_
->workarounds()
2698 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2699 !surface
->IsOffscreen())
2700 supports_post_sub_buffer_
= false;
2702 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2703 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2706 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2707 context_
->SetUnbindFboOnMakeCurrent();
2710 // Only compositor contexts are known to use only the subset of GL
2711 // that can be safely migrated between the iGPU and the dGPU. Mark
2712 // those contexts as safe to forcibly transition between the GPUs.
2713 // http://crbug.com/180876, http://crbug.com/227228
2715 context_
->SetSafeToForceGpuSwitch();
2717 async_pixel_transfer_manager_
.reset(
2718 AsyncPixelTransferManager::Create(context
.get()));
2719 async_pixel_transfer_manager_
->Initialize(texture_manager());
2721 framebuffer_manager()->AddObserver(this);
2726 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2727 DCHECK(initialized());
2731 caps
.egl_image_external
=
2732 feature_info_
->feature_flags().oes_egl_image_external
;
2733 caps
.texture_format_bgra8888
=
2734 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2735 caps
.texture_format_etc1
=
2736 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2737 caps
.texture_format_etc1_npot
=
2738 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2739 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2740 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2741 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2742 caps
.discard_framebuffer
=
2743 feature_info_
->feature_flags().ext_discard_framebuffer
;
2744 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2746 #if defined(OS_MACOSX)
2747 // This is unconditionally true on mac, no need to test for it at runtime.
2748 caps
.iosurface
= true;
2751 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2752 caps
.map_image
= true;
2757 void GLES2DecoderImpl::UpdateCapabilities() {
2758 util_
.set_num_compressed_texture_formats(
2759 validators_
->compressed_texture_format
.GetValues().size());
2760 util_
.set_num_shader_binary_formats(
2761 validators_
->shader_binary_format
.GetValues().size());
2764 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2765 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2767 if (!use_shader_translator_
) {
2770 ShBuiltInResources resources
;
2771 ShInitBuiltInResources(&resources
);
2772 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2773 resources
.MaxVertexUniformVectors
=
2774 group_
->max_vertex_uniform_vectors();
2775 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2776 resources
.MaxVertexTextureImageUnits
=
2777 group_
->max_vertex_texture_image_units();
2778 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2779 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2780 resources
.MaxFragmentUniformVectors
=
2781 group_
->max_fragment_uniform_vectors();
2782 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2783 resources
.MaxExpressionComplexity
= 256;
2784 resources
.MaxCallStackDepth
= 256;
2786 GLint range
[2] = { 0, 0 };
2787 GLint precision
= 0;
2788 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2790 resources
.FragmentPrecisionHigh
=
2791 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2793 if (force_webgl_glsl_validation_
) {
2794 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2795 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2796 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2797 if (!draw_buffers_explicitly_enabled_
)
2798 resources
.MaxDrawBuffers
= 1;
2799 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2801 resources
.OES_standard_derivatives
=
2802 features().oes_standard_derivatives
? 1 : 0;
2803 resources
.ARB_texture_rectangle
=
2804 features().arb_texture_rectangle
? 1 : 0;
2805 resources
.OES_EGL_image_external
=
2806 features().oes_egl_image_external
? 1 : 0;
2807 resources
.EXT_draw_buffers
=
2808 features().ext_draw_buffers
? 1 : 0;
2809 resources
.EXT_frag_depth
=
2810 features().ext_frag_depth
? 1 : 0;
2811 resources
.EXT_shader_texture_lod
=
2812 features().ext_shader_texture_lod
? 1 : 0;
2815 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2817 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2818 resources
.HashFunction
= &CityHash64
;
2820 resources
.HashFunction
= NULL
;
2821 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2822 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2823 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2824 int driver_bug_workarounds
= 0;
2825 if (workarounds().needs_glsl_built_in_function_emulation
)
2826 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2827 if (workarounds().init_gl_position_in_vertex_shader
)
2828 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2829 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2830 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2831 if (workarounds().init_varyings_without_static_use
)
2832 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2833 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2834 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2835 if (workarounds().scalarize_vec_and_mat_constructor_args
)
2836 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
2837 if (workarounds().regenerate_struct_names
)
2838 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
2840 vertex_translator_
= shader_translator_cache()->GetTranslator(
2844 implementation_type
,
2845 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2846 if (!vertex_translator_
.get()) {
2847 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2852 fragment_translator_
= shader_translator_cache()->GetTranslator(
2856 implementation_type
,
2857 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2858 if (!fragment_translator_
.get()) {
2859 LOG(ERROR
) << "Could not initialize fragment shader translator.";
2866 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
2867 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2868 if (GetBuffer(client_ids
[ii
])) {
2872 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2873 glGenBuffersARB(n
, service_ids
.get());
2874 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2875 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
2880 bool GLES2DecoderImpl::GenFramebuffersHelper(
2881 GLsizei n
, const GLuint
* client_ids
) {
2882 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2883 if (GetFramebuffer(client_ids
[ii
])) {
2887 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2888 glGenFramebuffersEXT(n
, service_ids
.get());
2889 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2890 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
2895 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2896 GLsizei n
, const GLuint
* client_ids
) {
2897 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2898 if (GetRenderbuffer(client_ids
[ii
])) {
2902 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2903 glGenRenderbuffersEXT(n
, service_ids
.get());
2904 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2905 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
2910 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
2911 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2912 if (GetTexture(client_ids
[ii
])) {
2916 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2917 glGenTextures(n
, service_ids
.get());
2918 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2919 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
2924 void GLES2DecoderImpl::DeleteBuffersHelper(
2925 GLsizei n
, const GLuint
* client_ids
) {
2926 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2927 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
2928 if (buffer
&& !buffer
->IsDeleted()) {
2929 state_
.vertex_attrib_manager
->Unbind(buffer
);
2930 if (state_
.bound_array_buffer
.get() == buffer
) {
2931 state_
.bound_array_buffer
= NULL
;
2933 RemoveBuffer(client_ids
[ii
]);
2938 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2939 GLsizei n
, const GLuint
* client_ids
) {
2940 bool supports_separate_framebuffer_binds
=
2941 features().chromium_framebuffer_multisample
;
2943 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2944 Framebuffer
* framebuffer
=
2945 GetFramebuffer(client_ids
[ii
]);
2946 if (framebuffer
&& !framebuffer
->IsDeleted()) {
2947 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
2948 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
2949 framebuffer_state_
.clear_state_dirty
= true;
2950 GLenum target
= supports_separate_framebuffer_binds
?
2951 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2952 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2954 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
2955 framebuffer_state_
.bound_read_framebuffer
= NULL
;
2956 GLenum target
= supports_separate_framebuffer_binds
?
2957 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2958 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2961 RemoveFramebuffer(client_ids
[ii
]);
2966 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2967 GLsizei n
, const GLuint
* client_ids
) {
2968 bool supports_separate_framebuffer_binds
=
2969 features().chromium_framebuffer_multisample
;
2970 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2971 Renderbuffer
* renderbuffer
=
2972 GetRenderbuffer(client_ids
[ii
]);
2973 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
2974 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
2975 state_
.bound_renderbuffer
= NULL
;
2977 // Unbind from current framebuffers.
2978 if (supports_separate_framebuffer_binds
) {
2979 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2980 framebuffer_state_
.bound_read_framebuffer
2981 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
2983 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2984 framebuffer_state_
.bound_draw_framebuffer
2985 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
2988 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2989 framebuffer_state_
.bound_draw_framebuffer
2990 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
2993 framebuffer_state_
.clear_state_dirty
= true;
2994 RemoveRenderbuffer(client_ids
[ii
]);
2999 void GLES2DecoderImpl::DeleteTexturesHelper(
3000 GLsizei n
, const GLuint
* client_ids
) {
3001 bool supports_separate_framebuffer_binds
=
3002 features().chromium_framebuffer_multisample
;
3003 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3004 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3006 Texture
* texture
= texture_ref
->texture();
3007 if (texture
->IsAttachedToFramebuffer()) {
3008 framebuffer_state_
.clear_state_dirty
= true;
3010 // Unbind texture_ref from texture_ref units.
3011 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3012 state_
.texture_units
[jj
].Unbind(texture_ref
);
3014 // Unbind from current framebuffers.
3015 if (supports_separate_framebuffer_binds
) {
3016 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3017 framebuffer_state_
.bound_read_framebuffer
3018 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3020 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3021 framebuffer_state_
.bound_draw_framebuffer
3022 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3025 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3026 framebuffer_state_
.bound_draw_framebuffer
3027 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3030 #if defined(OS_MACOSX)
3031 GLuint service_id
= texture
->service_id();
3032 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3033 ReleaseIOSurfaceForTexture(service_id
);
3036 RemoveTexture(client_ids
[ii
]);
3041 // } // anonymous namespace
3043 bool GLES2DecoderImpl::MakeCurrent() {
3044 if (!context_
.get())
3047 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3048 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3050 // Some D3D drivers cannot recover from device lost in the GPU process
3051 // sandbox. Allow a new GPU process to launch.
3052 if (workarounds().exit_on_context_lost
) {
3053 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
3054 << " a D3D device in the Chrome GPU process sandbox.";
3056 base::win::SetShouldCrashOnProcessDetach(false);
3064 ProcessFinishedAsyncTransfers();
3066 // Rebind the FBO if it was unbound by the context.
3067 if (workarounds().unbind_fbo_on_context_switch
)
3068 RestoreFramebufferBindings();
3070 framebuffer_state_
.clear_state_dirty
= true;
3075 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3076 ProcessPendingReadPixels();
3077 if (engine() && query_manager_
.get())
3078 query_manager_
->ProcessPendingTransferQueries();
3080 // TODO(epenner): Is there a better place to do this?
3081 // This needs to occur before we execute any batch of commands
3082 // from the client, as the client may have recieved an async
3083 // completion while issuing those commands.
3084 // "DidFlushStart" would be ideal if we had such a callback.
3085 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3088 static void RebindCurrentFramebuffer(
3090 Framebuffer
* framebuffer
,
3091 GLuint back_buffer_service_id
) {
3092 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3094 if (framebuffer_id
== 0) {
3095 framebuffer_id
= back_buffer_service_id
;
3098 glBindFramebufferEXT(target
, framebuffer_id
);
3101 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3102 framebuffer_state_
.clear_state_dirty
= true;
3104 if (!features().chromium_framebuffer_multisample
) {
3105 RebindCurrentFramebuffer(
3107 framebuffer_state_
.bound_draw_framebuffer
.get(),
3108 GetBackbufferServiceId());
3110 RebindCurrentFramebuffer(
3111 GL_READ_FRAMEBUFFER_EXT
,
3112 framebuffer_state_
.bound_read_framebuffer
.get(),
3113 GetBackbufferServiceId());
3114 RebindCurrentFramebuffer(
3115 GL_DRAW_FRAMEBUFFER_EXT
,
3116 framebuffer_state_
.bound_draw_framebuffer
.get(),
3117 GetBackbufferServiceId());
3122 bool GLES2DecoderImpl::CheckFramebufferValid(
3123 Framebuffer
* framebuffer
,
3124 GLenum target
, const char* func_name
) {
3126 if (backbuffer_needs_clear_bits_
) {
3127 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3128 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3129 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3131 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3132 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3134 state_
.SetDeviceDepthMask(GL_TRUE
);
3135 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3136 bool reset_draw_buffer
= false;
3137 if ((backbuffer_needs_clear_bits_
| GL_COLOR_BUFFER_BIT
) != 0 &&
3138 group_
->draw_buffer() == GL_NONE
) {
3139 reset_draw_buffer
= true;
3140 GLenum buf
= GL_BACK
;
3141 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3142 buf
= GL_COLOR_ATTACHMENT0
;
3143 glDrawBuffersARB(1, &buf
);
3145 glClear(backbuffer_needs_clear_bits_
);
3146 if (reset_draw_buffer
) {
3147 GLenum buf
= GL_NONE
;
3148 glDrawBuffersARB(1, &buf
);
3150 backbuffer_needs_clear_bits_
= 0;
3151 RestoreClearState();
3156 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3160 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3161 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3163 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3167 // Are all the attachments cleared?
3168 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3169 texture_manager()->HaveUnclearedMips()) {
3170 if (!framebuffer
->IsCleared()) {
3171 // Can we clear them?
3172 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3173 GL_FRAMEBUFFER_COMPLETE
) {
3175 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3176 "framebuffer incomplete (clear)");
3179 ClearUnclearedAttachments(target
, framebuffer
);
3183 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3184 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3185 GL_FRAMEBUFFER_COMPLETE
) {
3187 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3188 "framebuffer incomplete (check)");
3191 framebuffer_manager()->MarkAsComplete(framebuffer
);
3194 // NOTE: At this point we don't know if the framebuffer is complete but
3195 // we DO know that everything that needs to be cleared has been cleared.
3199 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3200 if (!features().chromium_framebuffer_multisample
) {
3201 bool valid
= CheckFramebufferValid(
3202 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3210 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3211 GL_DRAW_FRAMEBUFFER_EXT
,
3213 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3214 GL_READ_FRAMEBUFFER_EXT
,
3218 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3219 const char* func_name
) {
3220 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3221 framebuffer_state_
.bound_read_framebuffer
.get() :
3222 framebuffer_state_
.bound_draw_framebuffer
.get();
3225 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3227 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3233 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3234 Framebuffer
* framebuffer
=
3235 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3236 if (framebuffer
!= NULL
) {
3237 const Framebuffer::Attachment
* attachment
=
3238 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3240 return gfx::Size(attachment
->width(), attachment
->height());
3242 return gfx::Size(0, 0);
3243 } else if (offscreen_target_frame_buffer_
.get()) {
3244 return offscreen_size_
;
3246 return surface_
->GetSize();
3250 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3251 Framebuffer
* framebuffer
=
3252 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3253 if (framebuffer
!= NULL
) {
3254 return framebuffer
->GetColorAttachmentTextureType();
3256 return GL_UNSIGNED_BYTE
;
3260 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3261 Framebuffer
* framebuffer
=
3262 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3263 if (framebuffer
!= NULL
) {
3264 return framebuffer
->GetColorAttachmentFormat();
3265 } else if (offscreen_target_frame_buffer_
.get()) {
3266 return offscreen_target_color_format_
;
3268 return back_buffer_color_format_
;
3272 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3273 Framebuffer
* framebuffer
=
3274 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3275 if (framebuffer
!= NULL
) {
3276 return framebuffer
->GetColorAttachmentFormat();
3277 } else if (offscreen_target_frame_buffer_
.get()) {
3278 return offscreen_target_color_format_
;
3280 return back_buffer_color_format_
;
3284 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3285 if (!offscreen_saved_color_texture_info_
.get())
3287 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3288 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3289 texture_manager()->SetLevelInfo(
3290 offscreen_saved_color_texture_info_
.get(),
3294 offscreen_size_
.width(),
3295 offscreen_size_
.height(),
3301 texture_manager()->SetParameteri(
3302 "UpdateParentTextureInfo",
3304 offscreen_saved_color_texture_info_
.get(),
3305 GL_TEXTURE_MAG_FILTER
,
3307 texture_manager()->SetParameteri(
3308 "UpdateParentTextureInfo",
3310 offscreen_saved_color_texture_info_
.get(),
3311 GL_TEXTURE_MIN_FILTER
,
3313 texture_manager()->SetParameteri(
3314 "UpdateParentTextureInfo",
3316 offscreen_saved_color_texture_info_
.get(),
3319 texture_manager()->SetParameteri(
3320 "UpdateParentTextureInfo",
3322 offscreen_saved_color_texture_info_
.get(),
3325 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3327 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3330 void GLES2DecoderImpl::SetResizeCallback(
3331 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3332 resize_callback_
= callback
;
3335 Logger
* GLES2DecoderImpl::GetLogger() {
3339 void GLES2DecoderImpl::BeginDecoding() {
3340 gpu_tracer_
->BeginDecoding();
3341 gpu_trace_commands_
= gpu_tracer_
->IsTracing();
3342 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3343 (*cb_command_trace_category_
!= 0);
3346 void GLES2DecoderImpl::EndDecoding() {
3347 gpu_tracer_
->EndDecoding();
3350 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3351 return state_
.GetErrorState();
3354 void GLES2DecoderImpl::SetShaderCacheCallback(
3355 const ShaderCacheCallback
& callback
) {
3356 shader_cache_callback_
= callback
;
3359 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3360 const WaitSyncPointCallback
& callback
) {
3361 wait_sync_point_callback_
= callback
;
3364 AsyncPixelTransferManager
*
3365 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3366 return async_pixel_transfer_manager_
.get();
3369 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3370 async_pixel_transfer_manager_
.reset();
3373 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3374 AsyncPixelTransferManager
* manager
) {
3375 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3378 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3379 uint32
* service_texture_id
) {
3380 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3382 *service_texture_id
= texture_ref
->service_id();
3388 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3389 return texture_state_
.texture_upload_count
+
3390 async_pixel_transfer_manager_
->GetTextureUploadCount();
3393 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3394 return texture_state_
.total_texture_upload_time
+
3395 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3398 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3399 return total_processing_commands_time_
;
3402 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3403 total_processing_commands_time_
+= time
;
3406 void GLES2DecoderImpl::Destroy(bool have_context
) {
3410 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3412 // Unbind everything.
3413 state_
.vertex_attrib_manager
= NULL
;
3414 state_
.default_vertex_attrib_manager
= NULL
;
3415 state_
.texture_units
.clear();
3416 state_
.bound_array_buffer
= NULL
;
3417 state_
.current_queries
.clear();
3418 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3419 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3420 state_
.bound_renderbuffer
= NULL
;
3422 if (offscreen_saved_color_texture_info_
.get()) {
3423 DCHECK(offscreen_target_color_texture_
);
3424 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3425 offscreen_saved_color_texture_
->id());
3426 offscreen_saved_color_texture_
->Invalidate();
3427 offscreen_saved_color_texture_info_
= NULL
;
3430 if (copy_texture_CHROMIUM_
.get()) {
3431 copy_texture_CHROMIUM_
->Destroy();
3432 copy_texture_CHROMIUM_
.reset();
3435 if (state_
.current_program
.get()) {
3436 program_manager()->UnuseProgram(shader_manager(),
3437 state_
.current_program
.get());
3440 if (attrib_0_buffer_id_
) {
3441 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3443 if (fixed_attrib_buffer_id_
) {
3444 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3447 if (validation_texture_
) {
3448 glDeleteTextures(1, &validation_texture_
);
3449 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3450 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3453 if (offscreen_target_frame_buffer_
.get())
3454 offscreen_target_frame_buffer_
->Destroy();
3455 if (offscreen_target_color_texture_
.get())
3456 offscreen_target_color_texture_
->Destroy();
3457 if (offscreen_target_color_render_buffer_
.get())
3458 offscreen_target_color_render_buffer_
->Destroy();
3459 if (offscreen_target_depth_render_buffer_
.get())
3460 offscreen_target_depth_render_buffer_
->Destroy();
3461 if (offscreen_target_stencil_render_buffer_
.get())
3462 offscreen_target_stencil_render_buffer_
->Destroy();
3463 if (offscreen_saved_frame_buffer_
.get())
3464 offscreen_saved_frame_buffer_
->Destroy();
3465 if (offscreen_saved_color_texture_
.get())
3466 offscreen_saved_color_texture_
->Destroy();
3467 if (offscreen_resolved_frame_buffer_
.get())
3468 offscreen_resolved_frame_buffer_
->Destroy();
3469 if (offscreen_resolved_color_texture_
.get())
3470 offscreen_resolved_color_texture_
->Destroy();
3472 if (offscreen_target_frame_buffer_
.get())
3473 offscreen_target_frame_buffer_
->Invalidate();
3474 if (offscreen_target_color_texture_
.get())
3475 offscreen_target_color_texture_
->Invalidate();
3476 if (offscreen_target_color_render_buffer_
.get())
3477 offscreen_target_color_render_buffer_
->Invalidate();
3478 if (offscreen_target_depth_render_buffer_
.get())
3479 offscreen_target_depth_render_buffer_
->Invalidate();
3480 if (offscreen_target_stencil_render_buffer_
.get())
3481 offscreen_target_stencil_render_buffer_
->Invalidate();
3482 if (offscreen_saved_frame_buffer_
.get())
3483 offscreen_saved_frame_buffer_
->Invalidate();
3484 if (offscreen_saved_color_texture_
.get())
3485 offscreen_saved_color_texture_
->Invalidate();
3486 if (offscreen_resolved_frame_buffer_
.get())
3487 offscreen_resolved_frame_buffer_
->Invalidate();
3488 if (offscreen_resolved_color_texture_
.get())
3489 offscreen_resolved_color_texture_
->Invalidate();
3492 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3493 // Otherwise, we can leak objects. http://crbug.com/258772.
3494 // state_.current_program must be reset before group_ is reset because
3495 // the later deletes the ProgramManager object that referred by
3496 // state_.current_program object.
3497 state_
.current_program
= NULL
;
3499 copy_texture_CHROMIUM_
.reset();
3501 if (query_manager_
.get()) {
3502 query_manager_
->Destroy(have_context
);
3503 query_manager_
.reset();
3506 if (vertex_array_manager_
.get()) {
3507 vertex_array_manager_
->Destroy(have_context
);
3508 vertex_array_manager_
.reset();
3511 if (image_manager_
.get()) {
3512 image_manager_
->Destroy(have_context
);
3513 image_manager_
.reset();
3516 offscreen_target_frame_buffer_
.reset();
3517 offscreen_target_color_texture_
.reset();
3518 offscreen_target_color_render_buffer_
.reset();
3519 offscreen_target_depth_render_buffer_
.reset();
3520 offscreen_target_stencil_render_buffer_
.reset();
3521 offscreen_saved_frame_buffer_
.reset();
3522 offscreen_saved_color_texture_
.reset();
3523 offscreen_resolved_frame_buffer_
.reset();
3524 offscreen_resolved_color_texture_
.reset();
3526 // Need to release these before releasing |group_| which may own the
3527 // ShaderTranslatorCache.
3528 fragment_translator_
= NULL
;
3529 vertex_translator_
= NULL
;
3531 // Should destroy the transfer manager before the texture manager held
3532 // by the context group.
3533 async_pixel_transfer_manager_
.reset();
3536 framebuffer_manager()->RemoveObserver(this);
3537 group_
->Destroy(this, have_context
);
3541 if (context_
.get()) {
3542 context_
->ReleaseCurrent(NULL
);
3546 #if defined(OS_MACOSX)
3547 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3548 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3549 CFRelease(it
->second
);
3551 texture_to_io_surface_map_
.clear();
3555 void GLES2DecoderImpl::SetSurface(
3556 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3557 DCHECK(context_
->IsCurrent(NULL
));
3558 DCHECK(surface_
.get());
3560 RestoreCurrentFramebufferBindings();
3563 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3564 if (!offscreen_saved_color_texture_
.get()) {
3565 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3568 if (!offscreen_saved_color_texture_info_
.get()) {
3569 GLuint service_id
= offscreen_saved_color_texture_
->id();
3570 offscreen_saved_color_texture_info_
= TextureRef::Create(
3571 texture_manager(), 0, service_id
);
3572 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3574 UpdateParentTextureInfo();
3576 mailbox_manager()->ProduceTexture(
3577 GL_TEXTURE_2D
, mailbox
, offscreen_saved_color_texture_info_
->texture());
3580 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3581 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3582 if (!is_offscreen
) {
3583 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3584 << " with an onscreen framebuffer.";
3588 if (offscreen_size_
== size
)
3591 offscreen_size_
= size
;
3592 int w
= offscreen_size_
.width();
3593 int h
= offscreen_size_
.height();
3594 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3595 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3596 << "to allocate storage due to excessive dimensions.";
3600 // Reallocate the offscreen target buffers.
3601 DCHECK(offscreen_target_color_format_
);
3602 if (IsOffscreenBufferMultisampled()) {
3603 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3604 feature_info_
.get(),
3606 offscreen_target_color_format_
,
3607 offscreen_target_samples_
)) {
3608 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3609 << "to allocate storage for offscreen target color buffer.";
3613 if (!offscreen_target_color_texture_
->AllocateStorage(
3614 offscreen_size_
, offscreen_target_color_format_
, false)) {
3615 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3616 << "to allocate storage for offscreen target color texture.";
3620 if (offscreen_target_depth_format_
&&
3621 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3622 feature_info_
.get(),
3624 offscreen_target_depth_format_
,
3625 offscreen_target_samples_
)) {
3626 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3627 << "to allocate storage for offscreen target depth buffer.";
3630 if (offscreen_target_stencil_format_
&&
3631 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3632 feature_info_
.get(),
3634 offscreen_target_stencil_format_
,
3635 offscreen_target_samples_
)) {
3636 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3637 << "to allocate storage for offscreen target stencil buffer.";
3641 // Attach the offscreen target buffers to the target frame buffer.
3642 if (IsOffscreenBufferMultisampled()) {
3643 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3644 GL_COLOR_ATTACHMENT0
,
3645 offscreen_target_color_render_buffer_
.get());
3647 offscreen_target_frame_buffer_
->AttachRenderTexture(
3648 offscreen_target_color_texture_
.get());
3650 if (offscreen_target_depth_format_
) {
3651 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3652 GL_DEPTH_ATTACHMENT
,
3653 offscreen_target_depth_render_buffer_
.get());
3655 const bool packed_depth_stencil
=
3656 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3657 if (packed_depth_stencil
) {
3658 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3659 GL_STENCIL_ATTACHMENT
,
3660 offscreen_target_depth_render_buffer_
.get());
3661 } else if (offscreen_target_stencil_format_
) {
3662 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3663 GL_STENCIL_ATTACHMENT
,
3664 offscreen_target_stencil_render_buffer_
.get());
3667 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3668 GL_FRAMEBUFFER_COMPLETE
) {
3669 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3670 << "because offscreen FBO was incomplete.";
3674 // Clear the target frame buffer.
3676 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3677 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3678 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3679 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3681 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3682 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3684 state_
.SetDeviceDepthMask(GL_TRUE
);
3685 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3686 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3687 RestoreClearState();
3690 // Destroy the offscreen resolved framebuffers.
3691 if (offscreen_resolved_frame_buffer_
.get())
3692 offscreen_resolved_frame_buffer_
->Destroy();
3693 if (offscreen_resolved_color_texture_
.get())
3694 offscreen_resolved_color_texture_
->Destroy();
3695 offscreen_resolved_color_texture_
.reset();
3696 offscreen_resolved_frame_buffer_
.reset();
3701 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
3702 const void* cmd_data
) {
3703 const gles2::cmds::ResizeCHROMIUM
& c
=
3704 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
3705 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3706 return error::kDeferCommandUntilLater
;
3708 GLuint width
= static_cast<GLuint
>(c
.width
);
3709 GLuint height
= static_cast<GLuint
>(c
.height
);
3710 GLfloat scale_factor
= c
.scale_factor
;
3711 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3713 width
= std::max(1U, width
);
3714 height
= std::max(1U, height
);
3716 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3717 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3718 // Make sure that we are done drawing to the back buffer before resizing.
3721 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3723 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3724 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3725 << "ResizeOffscreenFrameBuffer failed.";
3726 return error::kLostContext
;
3730 if (!resize_callback_
.is_null()) {
3731 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3732 DCHECK(context_
->IsCurrent(surface_
.get()));
3733 if (!context_
->IsCurrent(surface_
.get())) {
3734 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3735 << "current after resize callback.";
3736 return error::kLostContext
;
3740 return error::kNoError
;
3743 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3744 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3745 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3747 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3750 // Decode a command, and call the corresponding GL functions.
3751 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3752 // of commands at once, and is now only used for tests that need to track
3753 // individual commands.
3754 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
3755 unsigned int arg_count
,
3756 const void* cmd_data
) {
3757 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
3760 // Decode multiple commands, and call the corresponding GL functions.
3761 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3762 // changed by a (malicious) client at any time, so if validation has to happen,
3763 // it should operate on a copy of them.
3764 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3765 // interest of performance in this critical execution loop.
3766 template <bool DebugImpl
>
3767 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
3770 int* entries_processed
) {
3771 commands_to_process_
= num_commands
;
3772 error::Error result
= error::kNoError
;
3773 const CommandBufferEntry
* cmd_data
=
3774 static_cast<const CommandBufferEntry
*>(buffer
);
3775 int process_pos
= 0;
3776 unsigned int command
= 0;
3778 while (process_pos
< num_entries
&& result
== error::kNoError
&&
3779 commands_to_process_
--) {
3780 const unsigned int size
= cmd_data
->value_header
.size
;
3781 command
= cmd_data
->value_header
.command
;
3784 result
= error::kInvalidSize
;
3788 if (static_cast<int>(size
) + process_pos
> num_entries
) {
3789 result
= error::kOutOfBounds
;
3794 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3795 GetCommandName(command
));
3797 if (log_commands()) {
3798 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
3799 << "cmd: " << GetCommandName(command
);
3803 const unsigned int arg_count
= size
- 1;
3804 unsigned int command_index
= command
- kStartPoint
- 1;
3805 if (command_index
< arraysize(command_info
)) {
3806 const CommandInfo
& info
= command_info
[command_index
];
3807 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3808 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3809 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3810 bool doing_gpu_trace
= false;
3811 if (DebugImpl
&& gpu_trace_commands_
) {
3812 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
3813 doing_gpu_trace
= true;
3814 gpu_tracer_
->Begin(GetCommandName(command
), kTraceDecoder
);
3818 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
3819 sizeof(CommandBufferEntry
); // NOLINT
3821 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
3823 if (DebugImpl
&& doing_gpu_trace
)
3824 gpu_tracer_
->End(kTraceDecoder
);
3826 if (DebugImpl
&& debug()) {
3828 while ((error
= glGetError()) != GL_NO_ERROR
) {
3829 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
3830 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
3831 << " : " << GetCommandName(command
);
3832 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
3836 result
= error::kInvalidArguments
;
3839 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
3843 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3844 GetCommandName(command
));
3847 if (result
== error::kNoError
&&
3848 current_decoder_error_
!= error::kNoError
) {
3849 result
= current_decoder_error_
;
3850 current_decoder_error_
= error::kNoError
;
3853 if (result
!= error::kDeferCommandUntilLater
) {
3854 process_pos
+= size
;
3859 if (entries_processed
)
3860 *entries_processed
= process_pos
;
3862 if (error::IsError(result
)) {
3863 LOG(ERROR
) << "Error: " << result
<< " for Command "
3864 << GetCommandName(command
);
3870 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
3873 int* entries_processed
) {
3874 if (gpu_debug_commands_
) {
3875 return DoCommandsImpl
<true>(
3876 num_commands
, buffer
, num_entries
, entries_processed
);
3878 return DoCommandsImpl
<false>(
3879 num_commands
, buffer
, num_entries
, entries_processed
);
3883 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
3884 buffer_manager()->RemoveBuffer(client_id
);
3887 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id
) {
3888 if (GetProgram(client_id
)) {
3891 GLuint service_id
= glCreateProgram();
3892 if (service_id
!= 0) {
3893 CreateProgram(client_id
, service_id
);
3898 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type
, GLuint client_id
) {
3899 if (GetShader(client_id
)) {
3902 GLuint service_id
= glCreateShader(type
);
3903 if (service_id
!= 0) {
3904 CreateShader(client_id
, service_id
, type
);
3909 void GLES2DecoderImpl::DoFinish() {
3911 ProcessPendingReadPixels();
3912 ProcessPendingQueries();
3915 void GLES2DecoderImpl::DoFlush() {
3917 ProcessPendingQueries();
3920 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
3921 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
3922 if (texture_index
>= state_
.texture_units
.size()) {
3923 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3924 "glActiveTexture", texture_unit
, "texture_unit");
3927 state_
.active_texture_unit
= texture_index
;
3928 glActiveTexture(texture_unit
);
3931 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
3932 Buffer
* buffer
= NULL
;
3933 GLuint service_id
= 0;
3934 if (client_id
!= 0) {
3935 buffer
= GetBuffer(client_id
);
3937 if (!group_
->bind_generates_resource()) {
3938 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
3940 "id not generated by glGenBuffers");
3944 // It's a new id so make a buffer buffer for it.
3945 glGenBuffersARB(1, &service_id
);
3946 CreateBuffer(client_id
, service_id
);
3947 buffer
= GetBuffer(client_id
);
3948 IdAllocatorInterface
* id_allocator
=
3949 group_
->GetIdAllocator(id_namespaces::kBuffers
);
3950 id_allocator
->MarkAsUsed(client_id
);
3953 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
3955 if (!buffer_manager()->SetTarget(buffer
, target
)) {
3957 GL_INVALID_OPERATION
,
3958 "glBindBuffer", "buffer bound to more than 1 target");
3961 service_id
= buffer
->service_id();
3964 case GL_ARRAY_BUFFER
:
3965 state_
.bound_array_buffer
= buffer
;
3967 case GL_ELEMENT_ARRAY_BUFFER
:
3968 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
3971 NOTREACHED(); // Validation should prevent us getting here.
3974 glBindBuffer(target
, service_id
);
3977 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3978 bool all_draw_buffers
) {
3979 Framebuffer
* framebuffer
=
3980 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3981 if (!all_draw_buffers
|| !framebuffer
) {
3982 return (GLES2Util::GetChannelsForFormat(
3983 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3985 return framebuffer
->HasAlphaMRT();
3988 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3989 Framebuffer
* framebuffer
=
3990 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3992 return framebuffer
->HasDepthAttachment();
3994 if (offscreen_target_frame_buffer_
.get()) {
3995 return offscreen_target_depth_format_
!= 0;
3997 return back_buffer_has_depth_
;
4000 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4001 Framebuffer
* framebuffer
=
4002 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4004 return framebuffer
->HasStencilAttachment();
4006 if (offscreen_target_frame_buffer_
.get()) {
4007 return offscreen_target_stencil_format_
!= 0 ||
4008 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4010 return back_buffer_has_stencil_
;
4013 void GLES2DecoderImpl::ApplyDirtyState() {
4014 if (framebuffer_state_
.clear_state_dirty
) {
4015 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4016 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4017 state_
.color_mask_green
,
4018 state_
.color_mask_blue
,
4019 state_
.color_mask_alpha
&& have_alpha
);
4021 bool have_depth
= BoundFramebufferHasDepthAttachment();
4022 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4024 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4025 state_
.SetDeviceStencilMaskSeparate(
4026 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4027 state_
.SetDeviceStencilMaskSeparate(
4028 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4030 state_
.SetDeviceCapabilityState(
4031 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4032 state_
.SetDeviceCapabilityState(
4033 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4034 framebuffer_state_
.clear_state_dirty
= false;
4038 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4039 return (offscreen_target_frame_buffer_
.get())
4040 ? offscreen_target_frame_buffer_
->id()
4041 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4044 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4045 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4046 "context", logger_
.GetLogPrefix());
4047 // Restore the Framebuffer first because of bugs in Intel drivers.
4048 // Intel drivers incorrectly clip the viewport settings to
4049 // the size of the current framebuffer object.
4050 RestoreFramebufferBindings();
4051 state_
.RestoreState(prev_state
);
4054 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4056 framebuffer_state_
.bound_draw_framebuffer
.get()
4057 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4058 : GetBackbufferServiceId();
4059 if (!features().chromium_framebuffer_multisample
) {
4060 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4062 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4063 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4064 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4065 : GetBackbufferServiceId();
4066 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4071 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4072 state_
.RestoreRenderbufferBindings();
4075 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4076 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4078 GLenum target
= texture
->target();
4079 glBindTexture(target
, service_id
);
4081 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4083 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4085 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4087 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4088 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4092 void GLES2DecoderImpl::ClearAllAttributes() const {
4093 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4095 if (feature_info_
->feature_flags().native_vertex_array_object
)
4096 glBindVertexArrayOES(0);
4098 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4099 if (i
!= 0) // Never disable attribute 0
4100 glDisableVertexAttribArray(i
);
4101 if(features().angle_instanced_arrays
)
4102 glVertexAttribDivisorANGLE(i
, 0);
4106 void GLES2DecoderImpl::RestoreAllAttributes() const {
4107 state_
.RestoreVertexAttribs();
4110 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4111 state_
.SetIgnoreCachedStateForTest(ignore
);
4114 void GLES2DecoderImpl::OnFboChanged() const {
4115 if (workarounds().restore_scissor_on_fbo_change
)
4116 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
4119 // Called after the FBO is checked for completeness.
4120 void GLES2DecoderImpl::OnUseFramebuffer() const {
4121 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
4122 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
4123 // The driver forgets the correct scissor when modifying the FBO binding.
4124 glScissor(state_
.scissor_x
,
4126 state_
.scissor_width
,
4127 state_
.scissor_height
);
4129 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4130 // it's unclear how this bug works.
4135 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4136 Framebuffer
* framebuffer
= NULL
;
4137 GLuint service_id
= 0;
4138 if (client_id
!= 0) {
4139 framebuffer
= GetFramebuffer(client_id
);
4141 if (!group_
->bind_generates_resource()) {
4142 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4143 "glBindFramebuffer",
4144 "id not generated by glGenFramebuffers");
4148 // It's a new id so make a framebuffer framebuffer for it.
4149 glGenFramebuffersEXT(1, &service_id
);
4150 CreateFramebuffer(client_id
, service_id
);
4151 framebuffer
= GetFramebuffer(client_id
);
4152 IdAllocatorInterface
* id_allocator
=
4153 group_
->GetIdAllocator(id_namespaces::kFramebuffers
);
4154 id_allocator
->MarkAsUsed(client_id
);
4156 service_id
= framebuffer
->service_id();
4158 framebuffer
->MarkAsValid();
4160 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4162 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4163 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4166 // vmiura: This looks like dup code
4167 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4168 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4171 framebuffer_state_
.clear_state_dirty
= true;
4173 // If we are rendering to the backbuffer get the FBO id for any simulated
4175 if (framebuffer
== NULL
) {
4176 service_id
= GetBackbufferServiceId();
4179 glBindFramebufferEXT(target
, service_id
);
4183 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4184 Renderbuffer
* renderbuffer
= NULL
;
4185 GLuint service_id
= 0;
4186 if (client_id
!= 0) {
4187 renderbuffer
= GetRenderbuffer(client_id
);
4188 if (!renderbuffer
) {
4189 if (!group_
->bind_generates_resource()) {
4190 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4191 "glBindRenderbuffer",
4192 "id not generated by glGenRenderbuffers");
4196 // It's a new id so make a renderbuffer for it.
4197 glGenRenderbuffersEXT(1, &service_id
);
4198 CreateRenderbuffer(client_id
, service_id
);
4199 renderbuffer
= GetRenderbuffer(client_id
);
4200 IdAllocatorInterface
* id_allocator
=
4201 group_
->GetIdAllocator(id_namespaces::kRenderbuffers
);
4202 id_allocator
->MarkAsUsed(client_id
);
4204 service_id
= renderbuffer
->service_id();
4206 renderbuffer
->MarkAsValid();
4208 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4209 state_
.bound_renderbuffer
= renderbuffer
;
4210 state_
.bound_renderbuffer_valid
= true;
4211 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4214 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4215 TextureRef
* texture_ref
= NULL
;
4216 GLuint service_id
= 0;
4217 if (client_id
!= 0) {
4218 texture_ref
= GetTexture(client_id
);
4220 if (!group_
->bind_generates_resource()) {
4221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4223 "id not generated by glGenTextures");
4227 // It's a new id so make a texture texture for it.
4228 glGenTextures(1, &service_id
);
4229 DCHECK_NE(0u, service_id
);
4230 CreateTexture(client_id
, service_id
);
4231 texture_ref
= GetTexture(client_id
);
4232 IdAllocatorInterface
* id_allocator
=
4233 group_
->GetIdAllocator(id_namespaces::kTextures
);
4234 id_allocator
->MarkAsUsed(client_id
);
4237 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4240 // Check the texture exists
4242 Texture
* texture
= texture_ref
->texture();
4243 // Check that we are not trying to bind it to a different target.
4244 if (texture
->target() != 0 && texture
->target() != target
) {
4245 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4247 "texture bound to more than 1 target.");
4250 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4251 if (texture
->target() == 0) {
4252 texture_manager()->SetTarget(texture_ref
, target
);
4254 glBindTexture(target
, texture
->service_id());
4256 glBindTexture(target
, 0);
4259 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4260 unit
.bind_target
= target
;
4263 unit
.bound_texture_2d
= texture_ref
;
4265 case GL_TEXTURE_CUBE_MAP
:
4266 unit
.bound_texture_cube_map
= texture_ref
;
4268 case GL_TEXTURE_EXTERNAL_OES
:
4269 unit
.bound_texture_external_oes
= texture_ref
;
4271 case GL_TEXTURE_RECTANGLE_ARB
:
4272 unit
.bound_texture_rectangle_arb
= texture_ref
;
4275 NOTREACHED(); // Validation should prevent us getting here.
4280 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4281 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4283 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4284 glDisableVertexAttribArray(index
);
4289 "glDisableVertexAttribArray", "index out of range");
4293 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4294 GLsizei numAttachments
,
4295 const GLenum
* attachments
) {
4296 Framebuffer
* framebuffer
=
4297 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4299 // Validates the attachments. If one of them fails
4300 // the whole command fails.
4301 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4303 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4305 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4306 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4307 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4312 // Marks each one of them as not cleared
4313 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4315 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4320 switch (attachments
[i
]) {
4322 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4325 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4326 case GL_STENCIL_EXT
:
4327 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4336 // If the default framebuffer is bound but we are still rendering to an
4337 // FBO, translate attachment names that refer to default framebuffer
4338 // channels to corresponding framebuffer attachments.
4339 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4340 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4341 GLenum attachment
= attachments
[i
];
4342 if (!framebuffer
&& GetBackbufferServiceId()) {
4343 switch (attachment
) {
4345 attachment
= GL_COLOR_ATTACHMENT0
;
4348 attachment
= GL_DEPTH_ATTACHMENT
;
4350 case GL_STENCIL_EXT
:
4351 attachment
= GL_STENCIL_ATTACHMENT
;
4358 translated_attachments
[i
] = attachment
;
4361 glDiscardFramebufferEXT(target
, numAttachments
, translated_attachments
.get());
4364 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4365 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4366 glEnableVertexAttribArray(index
);
4369 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4373 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4374 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4377 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4379 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4383 if (target
== GL_TEXTURE_CUBE_MAP
) {
4384 for (int i
= 0; i
< 6; ++i
) {
4385 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4386 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4388 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4393 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4395 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4400 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4401 // Workaround for Mac driver bug. In the large scheme of things setting
4402 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4403 // hit so there's probably no need to make this conditional. The bug appears
4404 // to be that if the filtering mode is set to something that doesn't require
4405 // mipmaps for rendering, or is never set to something other than the default,
4406 // then glGenerateMipmap misbehaves.
4407 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4408 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4410 glGenerateMipmapEXT(target
);
4411 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4412 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4413 texture_ref
->texture()->min_filter());
4415 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4416 if (error
== GL_NO_ERROR
) {
4417 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4421 bool GLES2DecoderImpl::GetHelper(
4422 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4423 DCHECK(num_written
);
4424 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4426 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4428 // Return the GL implementation's preferred format and (see below type)
4429 // if we have the GL extension that exposes this. This allows the GPU
4430 // client to use the implementation's preferred format for glReadPixels
4431 // for optimisation.
4433 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4434 // case when requested on integer/floating point buffers but which is
4435 // acceptable on GLES2 and with the GL_OES_read_format extension.
4437 // Therefore if an error occurs we swallow the error and use the
4438 // internal implementation.
4440 if (context_
->HasExtension("GL_OES_read_format")) {
4441 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4443 glGetIntegerv(pname
, params
);
4444 if (glGetError() == GL_NO_ERROR
)
4447 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4448 GetBoundReadFrameBufferInternalFormat());
4451 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4454 if (context_
->HasExtension("GL_OES_read_format")) {
4455 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4457 glGetIntegerv(pname
, params
);
4458 if (glGetError() == GL_NO_ERROR
)
4461 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4462 GetBoundReadFrameBufferInternalFormat(),
4463 GetBoundReadFrameBufferTextureType());
4466 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4469 *params
= group_
->max_fragment_uniform_vectors();
4472 case GL_MAX_VARYING_VECTORS
:
4475 *params
= group_
->max_varying_vectors();
4478 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4481 *params
= group_
->max_vertex_uniform_vectors();
4487 case GL_MAX_VIEWPORT_DIMS
:
4488 if (offscreen_target_frame_buffer_
.get()) {
4491 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4492 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4497 case GL_MAX_SAMPLES
:
4500 params
[0] = renderbuffer_manager()->max_samples();
4503 case GL_MAX_RENDERBUFFER_SIZE
:
4506 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4509 case GL_MAX_TEXTURE_SIZE
:
4512 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4515 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4518 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4521 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4524 params
[0] = group_
->max_color_attachments();
4527 case GL_MAX_DRAW_BUFFERS_ARB
:
4530 params
[0] = group_
->max_draw_buffers();
4537 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4538 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4545 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4546 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4549 case GL_STENCIL_BITS
:
4553 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4554 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4557 case GL_COMPRESSED_TEXTURE_FORMATS
:
4558 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4560 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4561 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4565 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4568 *params
= validators_
->compressed_texture_format
.GetValues().size();
4571 case GL_NUM_SHADER_BINARY_FORMATS
:
4574 *params
= validators_
->shader_binary_format
.GetValues().size();
4577 case GL_SHADER_BINARY_FORMATS
:
4578 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4580 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4581 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4585 case GL_SHADER_COMPILER
:
4591 case GL_ARRAY_BUFFER_BINDING
:
4594 if (state_
.bound_array_buffer
.get()) {
4595 GLuint client_id
= 0;
4596 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4598 *params
= client_id
;
4604 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4607 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4608 GLuint client_id
= 0;
4609 buffer_manager()->GetClientId(
4610 state_
.vertex_attrib_manager
->element_array_buffer()->
4611 service_id(), &client_id
);
4612 *params
= client_id
;
4618 case GL_FRAMEBUFFER_BINDING
:
4619 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4622 Framebuffer
* framebuffer
=
4623 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4625 GLuint client_id
= 0;
4626 framebuffer_manager()->GetClientId(
4627 framebuffer
->service_id(), &client_id
);
4628 *params
= client_id
;
4634 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4637 Framebuffer
* framebuffer
=
4638 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4640 GLuint client_id
= 0;
4641 framebuffer_manager()->GetClientId(
4642 framebuffer
->service_id(), &client_id
);
4643 *params
= client_id
;
4649 case GL_RENDERBUFFER_BINDING
:
4652 Renderbuffer
* renderbuffer
=
4653 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4655 *params
= renderbuffer
->client_id();
4661 case GL_CURRENT_PROGRAM
:
4664 if (state_
.current_program
.get()) {
4665 GLuint client_id
= 0;
4666 program_manager()->GetClientId(
4667 state_
.current_program
->service_id(), &client_id
);
4668 *params
= client_id
;
4674 case GL_VERTEX_ARRAY_BINDING_OES
:
4677 if (state_
.vertex_attrib_manager
.get() !=
4678 state_
.default_vertex_attrib_manager
.get()) {
4679 GLuint client_id
= 0;
4680 vertex_array_manager_
->GetClientId(
4681 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4682 *params
= client_id
;
4688 case GL_TEXTURE_BINDING_2D
:
4691 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4692 if (unit
.bound_texture_2d
.get()) {
4693 *params
= unit
.bound_texture_2d
->client_id();
4699 case GL_TEXTURE_BINDING_CUBE_MAP
:
4702 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4703 if (unit
.bound_texture_cube_map
.get()) {
4704 *params
= unit
.bound_texture_cube_map
->client_id();
4710 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4713 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4714 if (unit
.bound_texture_external_oes
.get()) {
4715 *params
= unit
.bound_texture_external_oes
->client_id();
4721 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4724 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4725 if (unit
.bound_texture_rectangle_arb
.get()) {
4726 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4732 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4735 params
[0] = unpack_flip_y_
;
4738 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4741 params
[0] = unpack_premultiply_alpha_
;
4744 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4747 params
[0] = unpack_unpremultiply_alpha_
;
4750 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4753 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4757 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4758 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4761 Framebuffer
* framebuffer
=
4762 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4764 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4765 } else { // backbuffer
4766 if (pname
== GL_DRAW_BUFFER0_ARB
)
4767 params
[0] = group_
->draw_buffer();
4769 params
[0] = GL_NONE
;
4774 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4779 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4780 GLenum pname
, GLsizei
* num_values
) {
4781 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4784 return GetHelper(pname
, NULL
, num_values
);
4787 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4788 if (GL_MAX_SAMPLES
== pname
&&
4789 features().use_img_for_multisampled_render_to_texture
) {
4790 return GL_MAX_SAMPLES_IMG
;
4795 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4797 GLsizei num_written
= 0;
4798 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4799 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4800 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4801 GetHelper(pname
, values
.get(), &num_written
);
4803 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4804 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4807 pname
= AdjustGetPname(pname
);
4808 glGetBooleanv(pname
, params
);
4812 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4814 GLsizei num_written
= 0;
4815 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4816 if (GetHelper(pname
, NULL
, &num_written
)) {
4817 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4818 GetHelper(pname
, values
.get(), &num_written
);
4819 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4820 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4823 pname
= AdjustGetPname(pname
);
4824 glGetFloatv(pname
, params
);
4829 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4831 GLsizei num_written
;
4832 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4833 !GetHelper(pname
, params
, &num_written
)) {
4834 pname
= AdjustGetPname(pname
);
4835 glGetIntegerv(pname
, params
);
4839 void GLES2DecoderImpl::DoGetProgramiv(
4840 GLuint program_id
, GLenum pname
, GLint
* params
) {
4841 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
4845 program
->GetProgramiv(pname
, params
);
4848 void GLES2DecoderImpl::DoGetBufferParameteriv(
4849 GLenum target
, GLenum pname
, GLint
* params
) {
4850 // Just delegate it. Some validation is actually done before this.
4851 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4852 &state_
, target
, pname
, params
);
4855 void GLES2DecoderImpl::DoBindAttribLocation(
4856 GLuint program_id
, GLuint index
, const char* name
) {
4857 if (!StringIsValidForGLES(name
)) {
4859 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
4862 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4864 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
4867 if (index
>= group_
->max_vertex_attribs()) {
4869 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
4872 Program
* program
= GetProgramInfoNotShader(
4873 program_id
, "glBindAttribLocation");
4877 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
4878 glBindAttribLocation(program
->service_id(), index
, name
);
4881 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
4882 uint32 immediate_data_size
,
4883 const void* cmd_data
) {
4884 const gles2::cmds::BindAttribLocationBucket
& c
=
4885 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
4886 GLuint program
= static_cast<GLuint
>(c
.program
);
4887 GLuint index
= static_cast<GLuint
>(c
.index
);
4888 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4889 if (!bucket
|| bucket
->size() == 0) {
4890 return error::kInvalidArguments
;
4892 std::string name_str
;
4893 if (!bucket
->GetAsString(&name_str
)) {
4894 return error::kInvalidArguments
;
4896 DoBindAttribLocation(program
, index
, name_str
.c_str());
4897 return error::kNoError
;
4900 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4901 GLuint program_id
, GLint location
, const char* name
) {
4902 if (!StringIsValidForGLES(name
)) {
4905 "glBindUniformLocationCHROMIUM", "Invalid character");
4908 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4910 GL_INVALID_OPERATION
,
4911 "glBindUniformLocationCHROMIUM", "reserved prefix");
4914 if (location
< 0 || static_cast<uint32
>(location
) >=
4915 (group_
->max_fragment_uniform_vectors() +
4916 group_
->max_vertex_uniform_vectors()) * 4) {
4919 "glBindUniformLocationCHROMIUM", "location out of range");
4922 Program
* program
= GetProgramInfoNotShader(
4923 program_id
, "glBindUniformLocationCHROMIUM");
4927 if (!program
->SetUniformLocationBinding(name
, location
)) {
4930 "glBindUniformLocationCHROMIUM", "location out of range");
4934 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4935 uint32 immediate_data_size
,
4936 const void* cmd_data
) {
4937 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
4938 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
4940 GLuint program
= static_cast<GLuint
>(c
.program
);
4941 GLint location
= static_cast<GLint
>(c
.location
);
4942 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4943 if (!bucket
|| bucket
->size() == 0) {
4944 return error::kInvalidArguments
;
4946 std::string name_str
;
4947 if (!bucket
->GetAsString(&name_str
)) {
4948 return error::kInvalidArguments
;
4950 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4951 return error::kNoError
;
4954 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
4955 const void* cmd_data
) {
4956 const gles2::cmds::DeleteShader
& c
=
4957 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
4958 GLuint client_id
= c
.shader
;
4960 Shader
* shader
= GetShader(client_id
);
4962 if (!shader
->IsDeleted()) {
4963 glDeleteShader(shader
->service_id());
4964 shader_manager()->MarkAsDeleted(shader
);
4967 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
4970 return error::kNoError
;
4973 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
4974 const void* cmd_data
) {
4975 const gles2::cmds::DeleteProgram
& c
=
4976 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
4977 GLuint client_id
= c
.program
;
4979 Program
* program
= GetProgram(client_id
);
4981 if (!program
->IsDeleted()) {
4982 program_manager()->MarkAsDeleted(shader_manager(), program
);
4986 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
4989 return error::kNoError
;
4992 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4993 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4994 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4995 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4996 id_allocator
->FreeID(ids
[ii
]);
5000 error::Error
GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
5001 uint32 immediate_data_size
,
5002 const void* cmd_data
) {
5003 const gles2::cmds::DeleteSharedIdsCHROMIUM
& c
=
5004 *static_cast<const gles2::cmds::DeleteSharedIdsCHROMIUM
*>(cmd_data
);
5005 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
5006 GLsizei n
= static_cast<GLsizei
>(c
.n
);
5008 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
5009 return error::kOutOfBounds
;
5011 const GLuint
* ids
= GetSharedMemoryAs
<const GLuint
*>(
5012 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
5014 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "DeleteSharedIdsCHROMIUM", "n < 0");
5015 return error::kNoError
;
5018 return error::kOutOfBounds
;
5020 DoDeleteSharedIdsCHROMIUM(namespace_id
, n
, ids
);
5021 return error::kNoError
;
5024 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
5025 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
5026 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
5027 if (id_offset
== 0) {
5028 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
5029 ids
[ii
] = id_allocator
->AllocateID();
5032 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
5033 ids
[ii
] = id_allocator
->AllocateIDAtOrAbove(id_offset
);
5034 id_offset
= ids
[ii
] + 1;
5039 error::Error
GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
5040 uint32 immediate_data_size
,
5041 const void* cmd_data
) {
5042 const gles2::cmds::GenSharedIdsCHROMIUM
& c
=
5043 *static_cast<const gles2::cmds::GenSharedIdsCHROMIUM
*>(cmd_data
);
5044 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
5045 GLuint id_offset
= static_cast<GLuint
>(c
.id_offset
);
5046 GLsizei n
= static_cast<GLsizei
>(c
.n
);
5048 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
5049 return error::kOutOfBounds
;
5051 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
5052 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
5054 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "GenSharedIdsCHROMIUM", "n < 0");
5055 return error::kNoError
;
5058 return error::kOutOfBounds
;
5060 DoGenSharedIdsCHROMIUM(namespace_id
, id_offset
, n
, ids
);
5061 return error::kNoError
;
5064 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
5065 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
5066 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
5067 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
5068 if (!id_allocator
->MarkAsUsed(ids
[ii
])) {
5069 for (GLsizei jj
= 0; jj
< ii
; ++jj
) {
5070 id_allocator
->FreeID(ids
[jj
]);
5073 GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM",
5074 "attempt to register id that already exists");
5080 error::Error
GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
5081 uint32 immediate_data_size
,
5082 const void* cmd_data
) {
5083 const gles2::cmds::RegisterSharedIdsCHROMIUM
& c
=
5084 *static_cast<const gles2::cmds::RegisterSharedIdsCHROMIUM
*>(cmd_data
);
5085 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
5086 GLsizei n
= static_cast<GLsizei
>(c
.n
);
5088 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
5089 return error::kOutOfBounds
;
5091 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
5092 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
5094 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM", "n < 0");
5095 return error::kNoError
;
5098 return error::kOutOfBounds
;
5100 DoRegisterSharedIdsCHROMIUM(namespace_id
, n
, ids
);
5101 return error::kNoError
;
5104 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5105 DCHECK(!ShouldDeferDraws());
5106 if (CheckBoundFramebuffersValid("glClear")) {
5110 return error::kNoError
;
5113 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5114 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5115 GLuint client_renderbuffer_id
) {
5116 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5119 GL_INVALID_OPERATION
,
5120 "glFramebufferRenderbuffer", "no framebuffer bound");
5123 GLuint service_id
= 0;
5124 Renderbuffer
* renderbuffer
= NULL
;
5125 if (client_renderbuffer_id
) {
5126 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5127 if (!renderbuffer
) {
5129 GL_INVALID_OPERATION
,
5130 "glFramebufferRenderbuffer", "unknown renderbuffer");
5133 service_id
= renderbuffer
->service_id();
5135 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5136 glFramebufferRenderbufferEXT(
5137 target
, attachment
, renderbuffertarget
, service_id
);
5138 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5139 if (error
== GL_NO_ERROR
) {
5140 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5142 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5143 framebuffer_state_
.clear_state_dirty
= true;
5148 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5149 if (SetCapabilityState(cap
, false)) {
5154 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5155 if (SetCapabilityState(cap
, true)) {
5160 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5161 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5162 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5163 glDepthRange(znear
, zfar
);
5166 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5167 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5168 state_
.sample_coverage_invert
= (invert
!= 0);
5169 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5172 // Assumes framebuffer is complete.
5173 void GLES2DecoderImpl::ClearUnclearedAttachments(
5174 GLenum target
, Framebuffer
* framebuffer
) {
5175 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5176 // bind this to the DRAW point, clear then bind back to READ
5177 // TODO(gman): I don't think there is any guarantee that an FBO that
5178 // is complete on the READ attachment will be complete as a DRAW
5180 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5181 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5183 GLbitfield clear_bits
= 0;
5184 if (framebuffer
->HasUnclearedColorAttachments()) {
5187 (GLES2Util::GetChannelsForFormat(
5188 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5190 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5191 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5192 if (feature_info_
->feature_flags().ext_draw_buffers
)
5193 framebuffer
->PrepareDrawBuffersForClear();
5196 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5197 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5199 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5200 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5201 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5204 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5205 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5207 state_
.SetDeviceDepthMask(GL_TRUE
);
5208 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5211 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5212 glClear(clear_bits
);
5214 if ((clear_bits
| GL_COLOR_BUFFER_BIT
) != 0 &&
5215 feature_info_
->feature_flags().ext_draw_buffers
)
5216 framebuffer
->RestoreDrawBuffersAfterClear();
5218 framebuffer_manager()->MarkAttachmentsAsCleared(
5219 framebuffer
, renderbuffer_manager(), texture_manager());
5221 RestoreClearState();
5223 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5224 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5225 Framebuffer
* draw_framebuffer
=
5226 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5227 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5228 GetBackbufferServiceId();
5229 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5233 void GLES2DecoderImpl::RestoreClearState() {
5234 framebuffer_state_
.clear_state_dirty
= true;
5236 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5237 state_
.color_clear_alpha
);
5238 glClearStencil(state_
.stencil_clear
);
5239 glClearDepth(state_
.depth_clear
);
5240 if (state_
.enable_flags
.scissor_test
) {
5241 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5245 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5246 Framebuffer
* framebuffer
=
5247 GetFramebufferInfoForTarget(target
);
5249 return GL_FRAMEBUFFER_COMPLETE
;
5251 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5252 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5253 return completeness
;
5255 return framebuffer
->GetStatus(texture_manager(), target
);
5258 void GLES2DecoderImpl::DoFramebufferTexture2D(
5259 GLenum target
, GLenum attachment
, GLenum textarget
,
5260 GLuint client_texture_id
, GLint level
) {
5261 DoFramebufferTexture2DCommon(
5262 "glFramebufferTexture2D", target
, attachment
,
5263 textarget
, client_texture_id
, level
, 0);
5266 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5267 GLenum target
, GLenum attachment
, GLenum textarget
,
5268 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5269 DoFramebufferTexture2DCommon(
5270 "glFramebufferTexture2DMultisample", target
, attachment
,
5271 textarget
, client_texture_id
, level
, samples
);
5274 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5275 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5276 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5277 if (samples
> renderbuffer_manager()->max_samples()) {
5280 "glFramebufferTexture2DMultisample", "samples too large");
5283 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5286 GL_INVALID_OPERATION
,
5287 name
, "no framebuffer bound.");
5290 GLuint service_id
= 0;
5291 TextureRef
* texture_ref
= NULL
;
5292 if (client_texture_id
) {
5293 texture_ref
= GetTexture(client_texture_id
);
5296 GL_INVALID_OPERATION
,
5297 name
, "unknown texture_ref");
5300 service_id
= texture_ref
->service_id();
5303 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5306 name
, "level out of range");
5311 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5313 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5315 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5317 if (features().use_img_for_multisampled_render_to_texture
) {
5318 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5319 service_id
, level
, samples
);
5321 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5322 service_id
, level
, samples
);
5325 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5326 if (error
== GL_NO_ERROR
) {
5327 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5330 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5331 framebuffer_state_
.clear_state_dirty
= true;
5335 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5340 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5341 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5342 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5345 GL_INVALID_OPERATION
,
5346 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5349 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5350 const Framebuffer::Attachment
* attachment_object
=
5351 framebuffer
->GetAttachment(attachment
);
5352 *params
= attachment_object
? attachment_object
->object_name() : 0;
5354 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5355 features().use_img_for_multisampled_render_to_texture
) {
5356 pname
= GL_TEXTURE_SAMPLES_IMG
;
5358 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5362 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5363 GLenum target
, GLenum pname
, GLint
* params
) {
5364 Renderbuffer
* renderbuffer
=
5365 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5366 if (!renderbuffer
) {
5368 GL_INVALID_OPERATION
,
5369 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5373 EnsureRenderbufferBound();
5375 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5376 *params
= renderbuffer
->internal_format();
5378 case GL_RENDERBUFFER_WIDTH
:
5379 *params
= renderbuffer
->width();
5381 case GL_RENDERBUFFER_HEIGHT
:
5382 *params
= renderbuffer
->height();
5384 case GL_RENDERBUFFER_SAMPLES_EXT
:
5385 if (features().use_img_for_multisampled_render_to_texture
) {
5386 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5389 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5393 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5398 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5399 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5400 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5401 GLbitfield mask
, GLenum filter
) {
5402 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5404 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5408 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5409 BlitFramebufferHelper(
5410 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5411 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5412 state_
.enable_flags
.scissor_test
);
5415 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5416 if (!state_
.bound_renderbuffer_valid
) {
5417 state_
.bound_renderbuffer_valid
= true;
5418 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5419 state_
.bound_renderbuffer
.get()
5420 ? state_
.bound_renderbuffer
->service_id()
5425 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5426 const FeatureInfo
* feature_info
,
5429 GLenum internal_format
,
5432 // TODO(sievers): This could be resolved at the GL binding level, but the
5433 // binding process is currently a bit too 'brute force'.
5434 if (feature_info
->feature_flags().is_angle
) {
5435 glRenderbufferStorageMultisampleANGLE(
5436 target
, samples
, internal_format
, width
, height
);
5437 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5438 glRenderbufferStorageMultisample(
5439 target
, samples
, internal_format
, width
, height
);
5441 glRenderbufferStorageMultisampleEXT(
5442 target
, samples
, internal_format
, width
, height
);
5446 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5456 // TODO(sievers): This could be resolved at the GL binding level, but the
5457 // binding process is currently a bit too 'brute force'.
5458 if (feature_info_
->feature_flags().is_angle
) {
5459 glBlitFramebufferANGLE(
5460 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5461 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5463 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5465 glBlitFramebufferEXT(
5466 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5470 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5472 GLenum internalformat
,
5475 if (samples
> renderbuffer_manager()->max_samples()) {
5478 "glRenderbufferStorageMultisample", "samples too large");
5482 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5483 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5486 "glRenderbufferStorageMultisample", "dimensions too large");
5490 uint32 estimated_size
= 0;
5491 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5492 width
, height
, samples
, internalformat
, &estimated_size
)) {
5495 "glRenderbufferStorageMultisample", "dimensions too large");
5499 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5502 "glRenderbufferStorageMultisample", "out of memory");
5509 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5510 GLenum target
, GLsizei samples
, GLenum internalformat
,
5511 GLsizei width
, GLsizei height
) {
5512 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5513 if (!renderbuffer
) {
5514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5515 "glRenderbufferStorageMultisampleCHROMIUM",
5516 "no renderbuffer bound");
5520 if (!ValidateRenderbufferStorageMultisample(
5521 samples
, internalformat
, width
, height
)) {
5525 EnsureRenderbufferBound();
5526 GLenum impl_format
=
5527 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5530 "glRenderbufferStorageMultisampleCHROMIUM");
5531 RenderbufferStorageMultisampleHelper(
5532 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5534 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5535 if (error
== GL_NO_ERROR
) {
5537 if (workarounds().validate_multisample_buffer_allocation
) {
5538 if (!VerifyMultisampleRenderbufferIntegrity(
5539 renderbuffer
->service_id(), impl_format
)) {
5542 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5547 // TODO(gman): If renderbuffers tracked which framebuffers they were
5548 // attached to we could just mark those framebuffers as not complete.
5549 framebuffer_manager()->IncFramebufferStateChangeCount();
5550 renderbuffer_manager()->SetInfo(
5551 renderbuffer
, samples
, internalformat
, width
, height
);
5555 // This is the handler for multisampled_render_to_texture extensions.
5556 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5557 GLenum target
, GLsizei samples
, GLenum internalformat
,
5558 GLsizei width
, GLsizei height
) {
5559 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5560 if (!renderbuffer
) {
5561 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5562 "glRenderbufferStorageMultisampleEXT",
5563 "no renderbuffer bound");
5567 if (!ValidateRenderbufferStorageMultisample(
5568 samples
, internalformat
, width
, height
)) {
5572 EnsureRenderbufferBound();
5573 GLenum impl_format
=
5574 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5576 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5577 if (features().use_img_for_multisampled_render_to_texture
) {
5578 glRenderbufferStorageMultisampleIMG(
5579 target
, samples
, impl_format
, width
, height
);
5581 glRenderbufferStorageMultisampleEXT(
5582 target
, samples
, impl_format
, width
, height
);
5584 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5585 if (error
== GL_NO_ERROR
) {
5586 // TODO(gman): If renderbuffers tracked which framebuffers they were
5587 // attached to we could just mark those framebuffers as not complete.
5588 framebuffer_manager()->IncFramebufferStateChangeCount();
5589 renderbuffer_manager()->SetInfo(
5590 renderbuffer
, samples
, internalformat
, width
, height
);
5594 // This function validates the allocation of a multisampled renderbuffer
5595 // by clearing it to a key color, blitting the contents to a texture, and
5596 // reading back the color to ensure it matches the key.
5597 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5598 GLuint renderbuffer
, GLenum format
) {
5600 // Only validate color buffers.
5601 // These formats have been selected because they are very common or are known
5602 // to be used by the WebGL backbuffer. If problems are observed with other
5603 // color formats they can be added here.
5614 GLint draw_framebuffer
, read_framebuffer
;
5616 // Cache framebuffer and texture bindings.
5617 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5618 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5620 if (!validation_texture_
) {
5621 GLint bound_texture
;
5622 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5624 // Create additional resources needed for the verification.
5625 glGenTextures(1, &validation_texture_
);
5626 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5627 glGenFramebuffersEXT(1, &validation_fbo_
);
5629 // Texture only needs to be 1x1.
5630 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5631 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5632 GL_UNSIGNED_BYTE
, NULL
);
5634 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5635 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5636 GL_TEXTURE_2D
, validation_texture_
, 0);
5638 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5641 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5642 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5643 GL_RENDERBUFFER
, renderbuffer
);
5645 // Cache current state and reset it to the values we require.
5646 GLboolean scissor_enabled
= false;
5647 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5648 if (scissor_enabled
)
5649 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5651 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5652 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5653 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5655 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5656 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5657 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5659 // Clear the buffer to the desired key color.
5660 glClear(GL_COLOR_BUFFER_BIT
);
5662 // Blit from the multisample buffer to a standard texture.
5663 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5664 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5666 BlitFramebufferHelper(
5667 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5669 // Read a pixel from the buffer.
5670 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5672 unsigned char pixel
[3] = {0, 0, 0};
5673 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5675 // Detach the renderbuffer.
5676 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5677 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5678 GL_RENDERBUFFER
, 0);
5680 // Restore cached state.
5681 if (scissor_enabled
)
5682 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5684 state_
.SetDeviceColorMask(
5685 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5686 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5687 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5688 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5690 // Return true if the pixel matched the desired key color.
5691 return (pixel
[0] == 0xFF &&
5696 void GLES2DecoderImpl::DoRenderbufferStorage(
5697 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5698 Renderbuffer
* renderbuffer
=
5699 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5700 if (!renderbuffer
) {
5702 GL_INVALID_OPERATION
,
5703 "glRenderbufferStorage", "no renderbuffer bound");
5707 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5708 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5710 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5714 uint32 estimated_size
= 0;
5715 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5716 width
, height
, 1, internalformat
, &estimated_size
)) {
5718 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5722 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5724 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5728 EnsureRenderbufferBound();
5729 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5730 glRenderbufferStorageEXT(
5732 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5736 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5737 if (error
== GL_NO_ERROR
) {
5738 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5739 // we could just mark those framebuffers as not complete.
5740 framebuffer_manager()->IncFramebufferStateChangeCount();
5741 renderbuffer_manager()->SetInfo(
5742 renderbuffer
, 1, internalformat
, width
, height
);
5746 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5747 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5748 Program
* program
= GetProgramInfoNotShader(
5749 program_id
, "glLinkProgram");
5754 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5755 ShaderTranslator
* vertex_translator
= NULL
;
5756 ShaderTranslator
* fragment_translator
= NULL
;
5757 if (use_shader_translator_
) {
5758 vertex_translator
= vertex_translator_
.get();
5759 fragment_translator
= fragment_translator_
.get();
5761 if (program
->Link(shader_manager(),
5763 fragment_translator
,
5764 workarounds().count_all_in_varyings_packing
?
5765 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5766 shader_cache_callback_
)) {
5767 if (program
== state_
.current_program
.get()) {
5768 if (workarounds().use_current_program_after_successful_link
)
5769 glUseProgram(program
->service_id());
5770 if (workarounds().clear_uniforms_before_first_program_use
)
5771 program_manager()->ClearUniforms(program
);
5775 // LinkProgram can be very slow. Exit command processing to allow for
5776 // context preemption and GPU watchdog checks.
5777 ExitCommandProcessingEarly();
5780 void GLES2DecoderImpl::DoTexParameterf(
5781 GLenum target
, GLenum pname
, GLfloat param
) {
5782 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5785 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5789 texture_manager()->SetParameterf(
5790 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5793 void GLES2DecoderImpl::DoTexParameteri(
5794 GLenum target
, GLenum pname
, GLint param
) {
5795 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5798 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5802 texture_manager()->SetParameteri(
5803 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5806 void GLES2DecoderImpl::DoTexParameterfv(
5807 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5808 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5815 texture_manager()->SetParameterf(
5816 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5819 void GLES2DecoderImpl::DoTexParameteriv(
5820 GLenum target
, GLenum pname
, const GLint
* params
) {
5821 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5825 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5829 texture_manager()->SetParameteri(
5830 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5833 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5834 if (!state_
.current_program
.get()) {
5835 // The program does not exist.
5837 GL_INVALID_OPERATION
, function_name
, "no program in use");
5840 if (!state_
.current_program
->InUse()) {
5842 GL_INVALID_OPERATION
, function_name
, "program not linked");
5848 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5849 GLint location
, const char* function_name
) {
5850 if (!CheckCurrentProgram(function_name
)) {
5853 return location
!= -1;
5856 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5857 GLint fake_location
,
5858 const char* function_name
,
5859 Program::UniformApiType api_type
,
5860 GLint
* real_location
,
5865 DCHECK(real_location
);
5867 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
5870 GLint array_index
= -1;
5871 const Program::UniformInfo
* info
=
5872 state_
.current_program
->GetUniformInfoByFakeLocation(
5873 fake_location
, real_location
, &array_index
);
5876 GL_INVALID_OPERATION
, function_name
, "unknown location");
5880 if ((api_type
& info
->accepts_api_type
) == 0) {
5882 GL_INVALID_OPERATION
, function_name
,
5883 "wrong uniform function for type");
5886 if (*count
> 1 && !info
->is_array
) {
5888 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
5891 *count
= std::min(info
->size
- array_index
, *count
);
5899 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
5902 GLint real_location
= -1;
5903 if (!PrepForSetUniformByLocation(fake_location
,
5905 Program::kUniform1i
,
5911 if (!state_
.current_program
->SetSamplers(
5912 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
5914 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
5917 glUniform1i(real_location
, v0
);
5920 void GLES2DecoderImpl::DoUniform1iv(
5921 GLint fake_location
, GLsizei count
, const GLint
*value
) {
5923 GLint real_location
= -1;
5924 if (!PrepForSetUniformByLocation(fake_location
,
5926 Program::kUniform1i
,
5932 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
5933 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
5934 if (!state_
.current_program
->SetSamplers(
5935 state_
.texture_units
.size(), fake_location
, count
, value
)) {
5937 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
5941 glUniform1iv(real_location
, count
, value
);
5944 void GLES2DecoderImpl::DoUniform1fv(
5945 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5947 GLint real_location
= -1;
5948 if (!PrepForSetUniformByLocation(fake_location
,
5950 Program::kUniform1f
,
5956 if (type
== GL_BOOL
) {
5957 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
5958 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5959 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5961 DoUniform1iv(real_location
, count
, temp
.get());
5963 glUniform1fv(real_location
, count
, value
);
5967 void GLES2DecoderImpl::DoUniform2fv(
5968 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5970 GLint real_location
= -1;
5971 if (!PrepForSetUniformByLocation(fake_location
,
5973 Program::kUniform2f
,
5979 if (type
== GL_BOOL_VEC2
) {
5980 GLsizei num_values
= count
* 2;
5981 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5982 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5983 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5985 glUniform2iv(real_location
, count
, temp
.get());
5987 glUniform2fv(real_location
, count
, value
);
5991 void GLES2DecoderImpl::DoUniform3fv(
5992 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5994 GLint real_location
= -1;
5995 if (!PrepForSetUniformByLocation(fake_location
,
5997 Program::kUniform3f
,
6003 if (type
== GL_BOOL_VEC3
) {
6004 GLsizei num_values
= count
* 3;
6005 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6006 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6007 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6009 glUniform3iv(real_location
, count
, temp
.get());
6011 glUniform3fv(real_location
, count
, value
);
6015 void GLES2DecoderImpl::DoUniform4fv(
6016 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6018 GLint real_location
= -1;
6019 if (!PrepForSetUniformByLocation(fake_location
,
6021 Program::kUniform4f
,
6027 if (type
== GL_BOOL_VEC4
) {
6028 GLsizei num_values
= count
* 4;
6029 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6030 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6031 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6033 glUniform4iv(real_location
, count
, temp
.get());
6035 glUniform4fv(real_location
, count
, value
);
6039 void GLES2DecoderImpl::DoUniform2iv(
6040 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6042 GLint real_location
= -1;
6043 if (!PrepForSetUniformByLocation(fake_location
,
6045 Program::kUniform2i
,
6051 glUniform2iv(real_location
, count
, value
);
6054 void GLES2DecoderImpl::DoUniform3iv(
6055 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6057 GLint real_location
= -1;
6058 if (!PrepForSetUniformByLocation(fake_location
,
6060 Program::kUniform3i
,
6066 glUniform3iv(real_location
, count
, value
);
6069 void GLES2DecoderImpl::DoUniform4iv(
6070 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6072 GLint real_location
= -1;
6073 if (!PrepForSetUniformByLocation(fake_location
,
6075 Program::kUniform4i
,
6081 glUniform4iv(real_location
, count
, value
);
6084 void GLES2DecoderImpl::DoUniformMatrix2fv(
6085 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6086 const GLfloat
* value
) {
6088 GLint real_location
= -1;
6089 if (!PrepForSetUniformByLocation(fake_location
,
6090 "glUniformMatrix2fv",
6091 Program::kUniformMatrix2f
,
6097 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6100 void GLES2DecoderImpl::DoUniformMatrix3fv(
6101 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6102 const GLfloat
* value
) {
6104 GLint real_location
= -1;
6105 if (!PrepForSetUniformByLocation(fake_location
,
6106 "glUniformMatrix3fv",
6107 Program::kUniformMatrix3f
,
6113 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6116 void GLES2DecoderImpl::DoUniformMatrix4fv(
6117 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6118 const GLfloat
* value
) {
6120 GLint real_location
= -1;
6121 if (!PrepForSetUniformByLocation(fake_location
,
6122 "glUniformMatrix4fv",
6123 Program::kUniformMatrix4f
,
6129 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6132 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6133 GLuint service_id
= 0;
6134 Program
* program
= NULL
;
6136 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6140 if (!program
->IsValid()) {
6141 // Program was not linked successfully. (ie, glLinkProgram)
6143 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6146 service_id
= program
->service_id();
6148 if (state_
.current_program
.get()) {
6149 program_manager()->UnuseProgram(shader_manager(),
6150 state_
.current_program
.get());
6152 state_
.current_program
= program
;
6153 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6154 glUseProgram(service_id
);
6155 if (state_
.current_program
.get()) {
6156 program_manager()->UseProgram(state_
.current_program
.get());
6157 if (workarounds().clear_uniforms_before_first_program_use
)
6158 program_manager()->ClearUniforms(program
);
6162 void GLES2DecoderImpl::RenderWarning(
6163 const char* filename
, int line
, const std::string
& msg
) {
6164 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6167 void GLES2DecoderImpl::PerformanceWarning(
6168 const char* filename
, int line
, const std::string
& msg
) {
6169 logger_
.LogMessage(filename
, line
,
6170 std::string("PERFORMANCE WARNING: ") + msg
);
6173 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6174 Texture
* texture
, GLenum textarget
) {
6175 // Image is already in use if texture is attached to a framebuffer.
6176 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6177 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6179 ScopedGLErrorSuppressor
suppressor(
6180 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6182 glBindTexture(textarget
, texture
->service_id());
6183 image
->WillUseTexImage();
6184 RestoreCurrentTextureBindings(&state_
, textarget
);
6189 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6190 Texture
* texture
, GLenum textarget
) {
6191 // Image is still in use if texture is attached to a framebuffer.
6192 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6193 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6195 ScopedGLErrorSuppressor
suppressor(
6196 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6198 glBindTexture(textarget
, texture
->service_id());
6199 image
->DidUseTexImage();
6200 RestoreCurrentTextureBindings(&state_
, textarget
);
6205 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6206 DCHECK(state_
.current_program
.get());
6207 if (!texture_manager()->HaveUnrenderableTextures() &&
6208 !texture_manager()->HaveImages()) {
6212 bool textures_set
= false;
6213 const Program::SamplerIndices
& sampler_indices
=
6214 state_
.current_program
->sampler_indices();
6215 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6216 const Program::UniformInfo
* uniform_info
=
6217 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6218 DCHECK(uniform_info
);
6219 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6220 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6221 if (texture_unit_index
< state_
.texture_units
.size()) {
6222 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6223 TextureRef
* texture_ref
=
6224 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6225 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6226 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6227 textures_set
= true;
6228 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6231 texture_manager()->black_texture_id(uniform_info
->type
));
6232 LOCAL_RENDER_WARNING(
6233 std::string("texture bound to texture unit ") +
6234 base::IntToString(texture_unit_index
) +
6235 " is not renderable. It maybe non-power-of-2 and have"
6236 " incompatible texture filtering or is not"
6237 " 'texture complete'");
6241 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6242 Texture
* texture
= texture_ref
->texture();
6243 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6244 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6245 ScopedGLErrorSuppressor
suppressor(
6246 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6247 textures_set
= true;
6248 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6249 image
->WillUseTexImage();
6254 // else: should this be an error?
6257 return !textures_set
;
6260 void GLES2DecoderImpl::RestoreStateForTextures() {
6261 DCHECK(state_
.current_program
.get());
6262 const Program::SamplerIndices
& sampler_indices
=
6263 state_
.current_program
->sampler_indices();
6264 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6265 const Program::UniformInfo
* uniform_info
=
6266 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6267 DCHECK(uniform_info
);
6268 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6269 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6270 if (texture_unit_index
< state_
.texture_units
.size()) {
6271 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6272 TextureRef
* texture_ref
=
6273 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6274 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6275 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6276 // Get the texture_ref info that was previously bound here.
6277 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6278 ? texture_unit
.bound_texture_2d
.get()
6279 : texture_unit
.bound_texture_cube_map
.get();
6280 glBindTexture(texture_unit
.bind_target
,
6281 texture_ref
? texture_ref
->service_id() : 0);
6285 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6286 Texture
* texture
= texture_ref
->texture();
6287 gfx::GLImage
* image
=
6288 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6289 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6290 ScopedGLErrorSuppressor
suppressor(
6291 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6292 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6293 image
->DidUseTexImage();
6300 // Set the active texture back to whatever the user had it as.
6301 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6304 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6305 // Only check if there are some uncleared textures.
6306 if (!texture_manager()->HaveUnsafeTextures()) {
6310 // 1: Check all textures we are about to render with.
6311 if (state_
.current_program
.get()) {
6312 const Program::SamplerIndices
& sampler_indices
=
6313 state_
.current_program
->sampler_indices();
6314 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6315 const Program::UniformInfo
* uniform_info
=
6316 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6317 DCHECK(uniform_info
);
6318 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6319 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6320 if (texture_unit_index
< state_
.texture_units
.size()) {
6321 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6322 TextureRef
* texture_ref
=
6323 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6324 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6325 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6336 bool GLES2DecoderImpl::IsDrawValid(
6337 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6338 GLsizei primcount
) {
6339 DCHECK(instanced
|| primcount
== 1);
6341 // NOTE: We specifically do not check current_program->IsValid() because
6342 // it could never be invalid since glUseProgram would have failed. While
6343 // glLinkProgram could later mark the program as invalid the previous
6344 // valid program will still function if it is still the current program.
6345 if (!state_
.current_program
.get()) {
6346 // The program does not exist.
6347 // But GL says no ERROR.
6348 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6352 return state_
.vertex_attrib_manager
6353 ->ValidateBindings(function_name
,
6355 feature_info_
.get(),
6356 state_
.current_program
.get(),
6357 max_vertex_accessed
,
6362 bool GLES2DecoderImpl::SimulateAttrib0(
6363 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6367 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6370 const VertexAttrib
* attrib
=
6371 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6372 // If it's enabled or it's not used then we don't need to do anything.
6373 bool attrib_0_used
=
6374 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6375 if (attrib
->enabled() && attrib_0_used
) {
6379 // Make a buffer with a single repeated vec4 value enough to
6380 // simulate the constant value that is supposed to be here.
6381 // This is required to emulate GLES2 on GL.
6382 GLuint num_vertices
= max_vertex_accessed
+ 1;
6383 uint32 size_needed
= 0;
6385 if (num_vertices
== 0 ||
6386 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6387 size_needed
> 0x7FFFFFFFU
) {
6388 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6392 LOCAL_PERFORMANCE_WARNING(
6393 "Attribute 0 is disabled. This has signficant performance penalty");
6395 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6396 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6398 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6400 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6401 GLenum error
= glGetError();
6402 if (error
!= GL_NO_ERROR
) {
6404 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6409 const Vec4
& value
= state_
.attrib_values
[0];
6412 (!attrib_0_buffer_matches_value_
||
6413 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6414 value
.v
[1] != attrib_0_value_
.v
[1] ||
6415 value
.v
[2] != attrib_0_value_
.v
[2] ||
6416 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6417 std::vector
<Vec4
> temp(num_vertices
, value
);
6418 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6419 attrib_0_buffer_matches_value_
= true;
6420 attrib_0_value_
= value
;
6421 attrib_0_size_
= size_needed
;
6424 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6426 if (attrib
->divisor())
6427 glVertexAttribDivisorANGLE(0, 0);
6433 void GLES2DecoderImpl::RestoreStateForAttrib(
6434 GLuint attrib_index
, bool restore_array_binding
) {
6435 const VertexAttrib
* attrib
=
6436 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6437 if (restore_array_binding
) {
6438 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6439 Buffer
* buffer
= attrib
->buffer();
6440 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6441 glVertexAttribPointer(
6442 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6443 attrib
->gl_stride(), ptr
);
6445 if (attrib
->divisor())
6446 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6448 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6449 state_
.bound_array_buffer
->service_id() : 0);
6451 // Never touch vertex attribute 0's state (in particular, never
6452 // disable it) when running on desktop GL because it will never be
6454 if (attrib_index
!= 0 ||
6455 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6456 if (attrib
->enabled()) {
6457 glEnableVertexAttribArray(attrib_index
);
6459 glDisableVertexAttribArray(attrib_index
);
6464 bool GLES2DecoderImpl::SimulateFixedAttribs(
6465 const char* function_name
,
6466 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6469 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6472 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6476 LOCAL_PERFORMANCE_WARNING(
6477 "GL_FIXED attributes have a signficant performance penalty");
6479 // NOTE: we could be smart and try to check if a buffer is used
6480 // twice in 2 different attribs, find the overlapping parts and therefore
6481 // duplicate the minimum amount of data but this whole code path is not meant
6482 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6483 // tests so we just add to the buffer attrib used.
6485 GLuint elements_needed
= 0;
6486 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6487 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6488 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6489 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6490 const VertexAttrib
* attrib
= *it
;
6491 const Program::VertexAttrib
* attrib_info
=
6492 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6493 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6494 max_vertex_accessed
);
6495 GLuint num_vertices
= max_accessed
+ 1;
6496 if (num_vertices
== 0) {
6498 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6502 attrib
->CanAccess(max_accessed
) &&
6503 attrib
->type() == GL_FIXED
) {
6504 uint32 elements_used
= 0;
6505 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6506 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6508 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6514 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6515 uint32 size_needed
= 0;
6516 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6517 size_needed
> 0x7FFFFFFFU
) {
6519 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6523 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6525 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6526 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6527 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6528 GLenum error
= glGetError();
6529 if (error
!= GL_NO_ERROR
) {
6531 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6536 // Copy the elements and convert to float
6537 GLintptr offset
= 0;
6538 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6539 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6540 const VertexAttrib
* attrib
= *it
;
6541 const Program::VertexAttrib
* attrib_info
=
6542 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6543 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6544 max_vertex_accessed
);
6545 GLuint num_vertices
= max_accessed
+ 1;
6546 if (num_vertices
== 0) {
6548 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6552 attrib
->CanAccess(max_accessed
) &&
6553 attrib
->type() == GL_FIXED
) {
6554 int num_elements
= attrib
->size() * kSizeOfFloat
;
6555 int size
= num_elements
* num_vertices
;
6556 scoped_ptr
<float[]> data(new float[size
]);
6557 const int32
* src
= reinterpret_cast<const int32
*>(
6558 attrib
->buffer()->GetRange(attrib
->offset(), size
));
6559 const int32
* end
= src
+ num_elements
;
6560 float* dst
= data
.get();
6561 while (src
!= end
) {
6562 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6564 glBufferSubData(GL_ARRAY_BUFFER
, offset
, size
, data
.get());
6565 glVertexAttribPointer(
6566 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6567 reinterpret_cast<GLvoid
*>(offset
));
6575 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6576 // There's no need to call glVertexAttribPointer because we shadow all the
6577 // settings and passing GL_FIXED to it will not work.
6580 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6584 error::Error
GLES2DecoderImpl::DoDrawArrays(
6585 const char* function_name
,
6590 GLsizei primcount
) {
6591 error::Error error
= WillAccessBoundFramebufferForDraw();
6592 if (error
!= error::kNoError
)
6594 if (!validators_
->draw_mode
.IsValid(mode
)) {
6595 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6596 return error::kNoError
;
6599 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6600 return error::kNoError
;
6602 if (primcount
< 0) {
6603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6604 return error::kNoError
;
6606 if (!CheckBoundFramebuffersValid(function_name
)) {
6607 return error::kNoError
;
6609 // We have to check this here because the prototype for glDrawArrays
6610 // is GLint not GLsizei.
6612 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6613 return error::kNoError
;
6616 if (count
== 0 || primcount
== 0) {
6617 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6618 return error::kNoError
;
6621 GLuint max_vertex_accessed
= first
+ count
- 1;
6622 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6623 if (!ClearUnclearedTextures()) {
6624 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6625 return error::kNoError
;
6627 bool simulated_attrib_0
= false;
6628 if (!SimulateAttrib0(
6629 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6630 return error::kNoError
;
6632 bool simulated_fixed_attribs
= false;
6633 if (SimulateFixedAttribs(
6634 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6636 bool textures_set
= !PrepareTexturesForRender();
6638 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6640 glDrawArrays(mode
, first
, count
);
6642 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6645 RestoreStateForTextures();
6647 if (simulated_fixed_attribs
) {
6648 RestoreStateForSimulatedFixedAttribs();
6651 if (simulated_attrib_0
) {
6652 // We don't have to restore attrib 0 generic data at the end of this
6653 // function even if it is simulated. This is because we will simulate
6654 // it in each draw call, and attrib 0 generic data queries use cached
6655 // values instead of passing down to the underlying driver.
6656 RestoreStateForAttrib(0, false);
6659 return error::kNoError
;
6662 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
6663 const void* cmd_data
) {
6664 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
6665 return DoDrawArrays("glDrawArrays",
6667 static_cast<GLenum
>(c
.mode
),
6668 static_cast<GLint
>(c
.first
),
6669 static_cast<GLsizei
>(c
.count
),
6673 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6674 uint32 immediate_data_size
,
6675 const void* cmd_data
) {
6676 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
6677 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
6678 if (!features().angle_instanced_arrays
) {
6680 GL_INVALID_OPERATION
,
6681 "glDrawArraysInstancedANGLE", "function not available");
6682 return error::kNoError
;
6684 return DoDrawArrays("glDrawArraysIntancedANGLE",
6686 static_cast<GLenum
>(c
.mode
),
6687 static_cast<GLint
>(c
.first
),
6688 static_cast<GLsizei
>(c
.count
),
6689 static_cast<GLsizei
>(c
.primcount
));
6692 error::Error
GLES2DecoderImpl::DoDrawElements(
6693 const char* function_name
,
6699 GLsizei primcount
) {
6700 error::Error error
= WillAccessBoundFramebufferForDraw();
6701 if (error
!= error::kNoError
)
6703 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6705 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6706 return error::kNoError
;
6710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6711 return error::kNoError
;
6714 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6715 return error::kNoError
;
6717 if (!validators_
->draw_mode
.IsValid(mode
)) {
6718 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6719 return error::kNoError
;
6721 if (!validators_
->index_type
.IsValid(type
)) {
6722 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6723 return error::kNoError
;
6725 if (primcount
< 0) {
6726 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6727 return error::kNoError
;
6730 if (!CheckBoundFramebuffersValid(function_name
)) {
6731 return error::kNoError
;
6734 if (count
== 0 || primcount
== 0) {
6735 return error::kNoError
;
6738 GLuint max_vertex_accessed
;
6739 Buffer
* element_array_buffer
=
6740 state_
.vertex_attrib_manager
->element_array_buffer();
6742 if (!element_array_buffer
->GetMaxValueForRange(
6743 offset
, count
, type
, &max_vertex_accessed
)) {
6745 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6746 return error::kNoError
;
6749 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6750 if (!ClearUnclearedTextures()) {
6751 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6752 return error::kNoError
;
6754 bool simulated_attrib_0
= false;
6755 if (!SimulateAttrib0(
6756 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6757 return error::kNoError
;
6759 bool simulated_fixed_attribs
= false;
6760 if (SimulateFixedAttribs(
6761 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6763 bool textures_set
= !PrepareTexturesForRender();
6765 // TODO(gman): Refactor to hide these details in BufferManager or
6766 // VertexAttribManager.
6767 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6768 bool used_client_side_array
= false;
6769 if (element_array_buffer
->IsClientSideArray()) {
6770 used_client_side_array
= true;
6771 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6772 indices
= element_array_buffer
->GetRange(offset
, 0);
6775 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6777 glDrawElements(mode
, count
, type
, indices
);
6779 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6782 if (used_client_side_array
) {
6783 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6784 element_array_buffer
->service_id());
6788 RestoreStateForTextures();
6790 if (simulated_fixed_attribs
) {
6791 RestoreStateForSimulatedFixedAttribs();
6794 if (simulated_attrib_0
) {
6795 // We don't have to restore attrib 0 generic data at the end of this
6796 // function even if it is simulated. This is because we will simulate
6797 // it in each draw call, and attrib 0 generic data queries use cached
6798 // values instead of passing down to the underlying driver.
6799 RestoreStateForAttrib(0, false);
6802 return error::kNoError
;
6805 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
6806 const void* cmd_data
) {
6807 const gles2::cmds::DrawElements
& c
=
6808 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
6809 return DoDrawElements("glDrawElements",
6811 static_cast<GLenum
>(c
.mode
),
6812 static_cast<GLsizei
>(c
.count
),
6813 static_cast<GLenum
>(c
.type
),
6814 static_cast<int32
>(c
.index_offset
),
6818 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6819 uint32 immediate_data_size
,
6820 const void* cmd_data
) {
6821 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
6822 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
6823 if (!features().angle_instanced_arrays
) {
6825 GL_INVALID_OPERATION
,
6826 "glDrawElementsInstancedANGLE", "function not available");
6827 return error::kNoError
;
6829 return DoDrawElements("glDrawElementsInstancedANGLE",
6831 static_cast<GLenum
>(c
.mode
),
6832 static_cast<GLsizei
>(c
.count
),
6833 static_cast<GLenum
>(c
.type
),
6834 static_cast<int32
>(c
.index_offset
),
6835 static_cast<GLsizei
>(c
.primcount
));
6838 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6839 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
6840 GLuint max_vertex_accessed
= 0;
6841 Buffer
* buffer
= GetBuffer(buffer_id
);
6843 // TODO(gman): Should this be a GL error or a command buffer error?
6845 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6847 if (!buffer
->GetMaxValueForRange(
6848 offset
, count
, type
, &max_vertex_accessed
)) {
6849 // TODO(gman): Should this be a GL error or a command buffer error?
6851 GL_INVALID_OPERATION
,
6852 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6855 return max_vertex_accessed
;
6858 // Calls glShaderSource for the various versions of the ShaderSource command.
6859 // Assumes that data / data_size points to a piece of memory that is in range
6860 // of whatever context it came from (shared memory, immediate memory, bucket
6862 error::Error
GLES2DecoderImpl::ShaderSourceHelper(
6863 GLuint client_id
, const char* data
, uint32 data_size
) {
6864 std::string
str(data
, data
+ data_size
);
6865 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
6867 return error::kNoError
;
6869 // Note: We don't actually call glShaderSource here. We wait until
6870 // the call to glCompileShader.
6871 shader
->set_source(str
);
6872 return error::kNoError
;
6875 error::Error
GLES2DecoderImpl::HandleShaderSourceBucket(
6876 uint32 immediate_data_size
,
6877 const void* cmd_data
) {
6878 const gles2::cmds::ShaderSourceBucket
& c
=
6879 *static_cast<const gles2::cmds::ShaderSourceBucket
*>(cmd_data
);
6880 Bucket
* bucket
= GetBucket(c
.data_bucket_id
);
6881 if (!bucket
|| bucket
->size() == 0) {
6882 return error::kInvalidArguments
;
6884 return ShaderSourceHelper(
6885 c
.shader
, bucket
->GetDataAs
<const char*>(0, bucket
->size() - 1),
6886 bucket
->size() - 1);
6889 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
6890 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6891 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
6895 ShaderTranslator
* translator
= NULL
;
6896 if (use_shader_translator_
) {
6897 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
6898 vertex_translator_
.get() : fragment_translator_
.get();
6903 feature_info_
->feature_flags().angle_translated_shader_source
?
6904 Shader::kANGLE
: Shader::kGL
);
6906 // CompileShader can be very slow. Exit command processing to allow for
6907 // context preemption and GPU watchdog checks.
6908 ExitCommandProcessingEarly();
6911 void GLES2DecoderImpl::DoGetShaderiv(
6912 GLuint shader_id
, GLenum pname
, GLint
* params
) {
6913 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
6918 case GL_SHADER_SOURCE_LENGTH
:
6919 *params
= shader
->source().size();
6923 case GL_COMPILE_STATUS
:
6924 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
6926 case GL_INFO_LOG_LENGTH
:
6927 *params
= shader
->log_info().size();
6931 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
6932 *params
= shader
->translated_source().size();
6939 glGetShaderiv(shader
->service_id(), pname
, params
);
6942 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
6943 const void* cmd_data
) {
6944 const gles2::cmds::GetShaderSource
& c
=
6945 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
6946 GLuint shader_id
= c
.shader
;
6947 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6948 Bucket
* bucket
= CreateBucket(bucket_id
);
6949 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
6950 if (!shader
|| shader
->source().empty()) {
6952 return error::kNoError
;
6954 bucket
->SetFromString(shader
->source().c_str());
6955 return error::kNoError
;
6958 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6959 uint32 immediate_data_size
,
6960 const void* cmd_data
) {
6961 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
6962 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
6964 GLuint shader_id
= c
.shader
;
6965 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6966 Bucket
* bucket
= CreateBucket(bucket_id
);
6967 Shader
* shader
= GetShaderInfoNotProgram(
6968 shader_id
, "glGetTranslatedShaderSourceANGLE");
6971 return error::kNoError
;
6974 bucket
->SetFromString(shader
->translated_source().c_str());
6975 return error::kNoError
;
6978 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
6979 uint32 immediate_data_size
,
6980 const void* cmd_data
) {
6981 const gles2::cmds::GetProgramInfoLog
& c
=
6982 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
6983 GLuint program_id
= c
.program
;
6984 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6985 Bucket
* bucket
= CreateBucket(bucket_id
);
6986 Program
* program
= GetProgramInfoNotShader(
6987 program_id
, "glGetProgramInfoLog");
6988 if (!program
|| !program
->log_info()) {
6989 bucket
->SetFromString("");
6990 return error::kNoError
;
6992 bucket
->SetFromString(program
->log_info()->c_str());
6993 return error::kNoError
;
6996 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
6997 uint32 immediate_data_size
,
6998 const void* cmd_data
) {
6999 const gles2::cmds::GetShaderInfoLog
& c
=
7000 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7001 GLuint shader_id
= c
.shader
;
7002 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7003 Bucket
* bucket
= CreateBucket(bucket_id
);
7004 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7006 bucket
->SetFromString("");
7007 return error::kNoError
;
7009 bucket
->SetFromString(shader
->log_info().c_str());
7010 return error::kNoError
;
7013 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7014 return state_
.GetEnabled(cap
);
7017 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7018 const Buffer
* buffer
= GetBuffer(client_id
);
7019 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7022 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7023 const Framebuffer
* framebuffer
=
7024 GetFramebuffer(client_id
);
7025 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7028 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7029 // IsProgram is true for programs as soon as they are created, until they are
7030 // deleted and no longer in use.
7031 const Program
* program
= GetProgram(client_id
);
7032 return program
!= NULL
&& !program
->IsDeleted();
7035 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7036 const Renderbuffer
* renderbuffer
=
7037 GetRenderbuffer(client_id
);
7038 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7041 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7042 // IsShader is true for shaders as soon as they are created, until they
7043 // are deleted and not attached to any programs.
7044 const Shader
* shader
= GetShader(client_id
);
7045 return shader
!= NULL
&& !shader
->IsDeleted();
7048 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7049 const TextureRef
* texture_ref
= GetTexture(client_id
);
7050 return texture_ref
&& texture_ref
->texture()->IsValid();
7053 void GLES2DecoderImpl::DoAttachShader(
7054 GLuint program_client_id
, GLint shader_client_id
) {
7055 Program
* program
= GetProgramInfoNotShader(
7056 program_client_id
, "glAttachShader");
7060 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7064 if (!program
->AttachShader(shader_manager(), shader
)) {
7066 GL_INVALID_OPERATION
,
7068 "can not attach more than one shader of the same type.");
7071 glAttachShader(program
->service_id(), shader
->service_id());
7074 void GLES2DecoderImpl::DoDetachShader(
7075 GLuint program_client_id
, GLint shader_client_id
) {
7076 Program
* program
= GetProgramInfoNotShader(
7077 program_client_id
, "glDetachShader");
7081 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7085 if (!program
->DetachShader(shader_manager(), shader
)) {
7087 GL_INVALID_OPERATION
,
7088 "glDetachShader", "shader not attached to program");
7091 glDetachShader(program
->service_id(), shader
->service_id());
7094 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7095 Program
* program
= GetProgramInfoNotShader(
7096 program_client_id
, "glValidateProgram");
7100 program
->Validate();
7103 void GLES2DecoderImpl::GetVertexAttribHelper(
7104 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7106 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7107 Buffer
* buffer
= attrib
->buffer();
7108 if (buffer
&& !buffer
->IsDeleted()) {
7110 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7111 *params
= client_id
;
7115 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7116 *params
= attrib
->enabled();
7118 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7119 *params
= attrib
->size();
7121 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7122 *params
= attrib
->gl_stride();
7124 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7125 *params
= attrib
->type();
7127 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7128 *params
= attrib
->normalized();
7130 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7131 *params
= attrib
->divisor();
7139 void GLES2DecoderImpl::DoGetTexParameterfv(
7140 GLenum target
, GLenum pname
, GLfloat
* params
) {
7141 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7142 glGetTexParameterfv(target
, pname
, params
);
7145 void GLES2DecoderImpl::DoGetTexParameteriv(
7146 GLenum target
, GLenum pname
, GLint
* params
) {
7147 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7148 glGetTexParameteriv(target
, pname
, params
);
7151 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7152 GLenum target
, GLenum pname
) {
7153 if (!workarounds().init_texture_max_anisotropy
)
7155 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7156 !validators_
->texture_parameter
.IsValid(pname
)) {
7160 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7164 GL_INVALID_OPERATION
,
7165 "glGetTexParamter{fi}v", "unknown texture for target");
7168 Texture
* texture
= texture_ref
->texture();
7169 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7172 void GLES2DecoderImpl::DoGetVertexAttribfv(
7173 GLuint index
, GLenum pname
, GLfloat
* params
) {
7174 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7177 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7181 case GL_CURRENT_VERTEX_ATTRIB
: {
7182 const Vec4
& value
= state_
.attrib_values
[index
];
7183 params
[0] = value
.v
[0];
7184 params
[1] = value
.v
[1];
7185 params
[2] = value
.v
[2];
7186 params
[3] = value
.v
[3];
7191 GetVertexAttribHelper(attrib
, pname
, &value
);
7192 *params
= static_cast<GLfloat
>(value
);
7198 void GLES2DecoderImpl::DoGetVertexAttribiv(
7199 GLuint index
, GLenum pname
, GLint
* params
) {
7200 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7203 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7207 case GL_CURRENT_VERTEX_ATTRIB
: {
7208 const Vec4
& value
= state_
.attrib_values
[index
];
7209 params
[0] = static_cast<GLint
>(value
.v
[0]);
7210 params
[1] = static_cast<GLint
>(value
.v
[1]);
7211 params
[2] = static_cast<GLint
>(value
.v
[2]);
7212 params
[3] = static_cast<GLint
>(value
.v
[3]);
7216 GetVertexAttribHelper(attrib
, pname
, params
);
7221 bool GLES2DecoderImpl::SetVertexAttribValue(
7222 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7223 if (index
>= state_
.attrib_values
.size()) {
7224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7227 Vec4
& v
= state_
.attrib_values
[index
];
7235 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7236 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7237 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7238 glVertexAttrib1f(index
, v0
);
7242 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7243 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7244 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7245 glVertexAttrib2f(index
, v0
, v1
);
7249 void GLES2DecoderImpl::DoVertexAttrib3f(
7250 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7251 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7252 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7253 glVertexAttrib3f(index
, v0
, v1
, v2
);
7257 void GLES2DecoderImpl::DoVertexAttrib4f(
7258 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7259 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7260 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7261 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7265 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7266 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7267 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7268 glVertexAttrib1fv(index
, v
);
7272 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7273 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7274 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7275 glVertexAttrib2fv(index
, v
);
7279 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7280 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7281 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7282 glVertexAttrib3fv(index
, v
);
7286 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7287 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7288 glVertexAttrib4fv(index
, v
);
7292 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7293 uint32 immediate_data_size
,
7294 const void* cmd_data
) {
7295 const gles2::cmds::VertexAttribPointer
& c
=
7296 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7298 if (!state_
.bound_array_buffer
.get() ||
7299 state_
.bound_array_buffer
->IsDeleted()) {
7300 if (state_
.vertex_attrib_manager
.get() ==
7301 state_
.default_vertex_attrib_manager
.get()) {
7303 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7304 return error::kNoError
;
7305 } else if (c
.offset
!= 0) {
7308 "glVertexAttribPointer", "client side arrays are not allowed");
7309 return error::kNoError
;
7313 GLuint indx
= c
.indx
;
7314 GLint size
= c
.size
;
7315 GLenum type
= c
.type
;
7316 GLboolean normalized
= c
.normalized
;
7317 GLsizei stride
= c
.stride
;
7318 GLsizei offset
= c
.offset
;
7319 const void* ptr
= reinterpret_cast<const void*>(offset
);
7320 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7321 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7322 return error::kNoError
;
7324 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7326 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7327 return error::kNoError
;
7329 if (indx
>= group_
->max_vertex_attribs()) {
7331 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7332 return error::kNoError
;
7336 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7337 return error::kNoError
;
7341 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7342 return error::kNoError
;
7346 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7347 return error::kNoError
;
7349 GLsizei component_size
=
7350 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7351 // component_size must be a power of two to use & as optimized modulo.
7352 DCHECK(GLES2Util::IsPOT(component_size
));
7353 if (offset
& (component_size
- 1)) {
7355 GL_INVALID_OPERATION
,
7356 "glVertexAttribPointer", "offset not valid for type");
7357 return error::kNoError
;
7359 if (stride
& (component_size
- 1)) {
7361 GL_INVALID_OPERATION
,
7362 "glVertexAttribPointer", "stride not valid for type");
7363 return error::kNoError
;
7365 state_
.vertex_attrib_manager
7366 ->SetAttribInfo(indx
,
7367 state_
.bound_array_buffer
.get(),
7372 stride
!= 0 ? stride
: component_size
* size
,
7374 if (type
!= GL_FIXED
) {
7375 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7377 return error::kNoError
;
7380 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7382 state_
.viewport_x
= x
;
7383 state_
.viewport_y
= y
;
7384 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7385 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7386 glViewport(x
, y
, width
, height
);
7389 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7390 uint32 immediate_data_size
,
7391 const void* cmd_data
) {
7392 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7393 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7394 if (!features().angle_instanced_arrays
) {
7396 GL_INVALID_OPERATION
,
7397 "glVertexAttribDivisorANGLE", "function not available");
7398 return error::kNoError
;
7400 GLuint index
= c
.index
;
7401 GLuint divisor
= c
.divisor
;
7402 if (index
>= group_
->max_vertex_attribs()) {
7405 "glVertexAttribDivisorANGLE", "index out of range");
7406 return error::kNoError
;
7409 state_
.vertex_attrib_manager
->SetDivisor(
7412 glVertexAttribDivisorANGLE(index
, divisor
);
7413 return error::kNoError
;
7416 template <typename pixel_data_type
>
7417 static void WriteAlphaData(
7418 void *pixels
, uint32 row_count
, uint32 channel_count
,
7419 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7420 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7421 DCHECK_GT(channel_count
, 0U);
7422 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7423 uint32 unpadded_row_size_in_elements
=
7424 unpadded_row_size
/ sizeof(pixel_data_type
);
7425 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7426 uint32 padded_row_size_in_elements
=
7427 padded_row_size
/ sizeof(pixel_data_type
);
7428 pixel_data_type
* dst
=
7429 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7430 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7431 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7432 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7435 dst
+= padded_row_size_in_elements
;
7439 void GLES2DecoderImpl::FinishReadPixels(
7440 const cmds::ReadPixels
& c
,
7442 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7443 GLsizei width
= c
.width
;
7444 GLsizei height
= c
.height
;
7445 GLenum format
= c
.format
;
7446 GLenum type
= c
.type
;
7447 typedef cmds::ReadPixels::Result Result
;
7449 Result
* result
= NULL
;
7450 if (c
.result_shm_id
!= 0) {
7451 result
= GetSharedMemoryAs
<Result
*>(
7452 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7455 glDeleteBuffersARB(1, &buffer
);
7460 GLES2Util::ComputeImageDataSizes(
7461 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7463 void* pixels
= GetSharedMemoryAs
<void*>(
7464 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7467 glDeleteBuffersARB(1, &buffer
);
7473 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7475 if (features().map_buffer_range
) {
7476 data
= glMapBufferRange(
7477 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7479 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7481 memcpy(pixels
, data
, pixels_size
);
7482 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7483 // have to restore the state.
7484 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7485 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7486 glDeleteBuffersARB(1, &buffer
);
7489 if (result
!= NULL
) {
7493 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7494 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7495 if ((channels_exist
& 0x0008) == 0 &&
7496 workarounds().clear_alpha_in_readpixels
) {
7497 // Set the alpha to 255 because some drivers are buggy in this regard.
7500 uint32 unpadded_row_size
;
7501 uint32 padded_row_size
;
7502 if (!GLES2Util::ComputeImageDataSizes(
7503 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7504 &unpadded_row_size
, &padded_row_size
)) {
7508 uint32 channel_count
= 0;
7509 uint32 alpha_channel
= 0;
7522 if (channel_count
> 0) {
7524 case GL_UNSIGNED_BYTE
:
7525 WriteAlphaData
<uint8
>(
7526 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7527 padded_row_size
, 0xFF);
7530 WriteAlphaData
<float>(
7531 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7532 padded_row_size
, 1.0f
);
7535 WriteAlphaData
<uint16
>(
7536 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7537 padded_row_size
, 0x3C00);
7544 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
7545 const void* cmd_data
) {
7546 const gles2::cmds::ReadPixels
& c
=
7547 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
7548 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7549 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7550 if (fbo_error
!= error::kNoError
)
7554 GLsizei width
= c
.width
;
7555 GLsizei height
= c
.height
;
7556 GLenum format
= c
.format
;
7557 GLenum type
= c
.type
;
7558 GLboolean async
= c
.async
;
7559 if (width
< 0 || height
< 0) {
7560 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7561 return error::kNoError
;
7563 typedef cmds::ReadPixels::Result Result
;
7565 if (!GLES2Util::ComputeImageDataSizes(
7566 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7568 return error::kOutOfBounds
;
7570 void* pixels
= GetSharedMemoryAs
<void*>(
7571 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7573 return error::kOutOfBounds
;
7575 Result
* result
= NULL
;
7576 if (c
.result_shm_id
!= 0) {
7577 result
= GetSharedMemoryAs
<Result
*>(
7578 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7580 return error::kOutOfBounds
;
7584 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7585 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7586 return error::kNoError
;
7588 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7589 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7590 return error::kNoError
;
7592 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7593 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7594 // format and type are acceptable enums but not guaranteed to be supported
7595 // for this framebuffer. Have to ask gl if they are valid.
7596 GLint preferred_format
= 0;
7597 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7598 GLint preferred_type
= 0;
7599 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7600 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7601 type
!= static_cast<GLenum
>(preferred_type
)) {
7603 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7604 "with the current read framebuffer");
7605 return error::kNoError
;
7608 if (width
== 0 || height
== 0) {
7609 return error::kNoError
;
7612 // Get the size of the current fbo or backbuffer.
7613 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7617 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7619 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7620 return error::kNoError
;
7623 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7624 return error::kNoError
;
7627 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7628 return error::kNoError
;
7631 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7633 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7635 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7636 // The user requested an out of range area. Get the results 1 line
7639 uint32 unpadded_row_size
;
7640 uint32 padded_row_size
;
7641 if (!GLES2Util::ComputeImageDataSizes(
7642 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7643 &unpadded_row_size
, &padded_row_size
)) {
7645 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7646 return error::kNoError
;
7649 GLint dest_x_offset
= std::max(-x
, 0);
7650 uint32 dest_row_offset
;
7651 if (!GLES2Util::ComputeImageDataSizes(
7652 dest_x_offset
, 1, format
, type
, state_
.pack_alignment
, &dest_row_offset
,
7655 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7656 return error::kNoError
;
7659 // Copy each row into the larger dest rect.
7660 int8
* dst
= static_cast<int8
*>(pixels
);
7661 GLint read_x
= std::max(0, x
);
7662 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7663 GLint read_width
= read_end_x
- read_x
;
7664 for (GLint yy
= 0; yy
< height
; ++yy
) {
7668 memset(dst
, 0, unpadded_row_size
);
7670 // If the row is in range, copy it.
7671 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7673 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7675 dst
+= padded_row_size
;
7678 if (async
&& features().use_async_readpixels
) {
7680 glGenBuffersARB(1, &buffer
);
7681 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7682 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, GL_STREAM_READ
);
7683 GLenum error
= glGetError();
7684 if (error
== GL_NO_ERROR
) {
7685 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7686 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7687 new FenceCallback()));
7688 WaitForReadPixels(base::Bind(
7689 &GLES2DecoderImpl::FinishReadPixels
,
7690 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7691 <GLES2DecoderImpl
>(this),
7693 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7694 return error::kNoError
;
7696 // On error, unbind pack buffer and fall through to sync readpixels
7697 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7700 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7702 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7703 if (error
== GL_NO_ERROR
) {
7704 if (result
!= NULL
) {
7707 FinishReadPixels(c
, 0);
7710 return error::kNoError
;
7713 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
7714 const void* cmd_data
) {
7715 const gles2::cmds::PixelStorei
& c
=
7716 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
7717 GLenum pname
= c
.pname
;
7718 GLenum param
= c
.param
;
7719 if (!validators_
->pixel_store
.IsValid(pname
)) {
7720 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7721 return error::kNoError
;
7724 case GL_PACK_ALIGNMENT
:
7725 case GL_UNPACK_ALIGNMENT
:
7726 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7728 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7729 return error::kNoError
;
7732 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7733 unpack_flip_y_
= (param
!= 0);
7734 return error::kNoError
;
7735 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7736 unpack_premultiply_alpha_
= (param
!= 0);
7737 return error::kNoError
;
7738 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7739 unpack_unpremultiply_alpha_
= (param
!= 0);
7740 return error::kNoError
;
7744 glPixelStorei(pname
, param
);
7746 case GL_PACK_ALIGNMENT
:
7747 state_
.pack_alignment
= param
;
7749 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
7750 state_
.pack_reverse_row_order
= (param
!= 0);
7752 case GL_UNPACK_ALIGNMENT
:
7753 state_
.unpack_alignment
= param
;
7756 // Validation should have prevented us from getting here.
7760 return error::kNoError
;
7763 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7764 uint32 immediate_data_size
,
7765 const void* cmd_data
) {
7766 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
7767 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
7768 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7770 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7772 if (!supports_post_sub_buffer_
) {
7774 GL_INVALID_OPERATION
,
7775 "glPostSubBufferCHROMIUM", "command not supported by surface");
7776 return error::kNoError
;
7779 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7782 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
7783 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
7784 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
7785 is_offscreen
? offscreen_size_
: surface_
->GetSize());
7787 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
7788 return error::kNoError
;
7790 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
7791 return error::kLostContext
;
7795 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7796 uint32 immediate_data_size
,
7797 const void* cmd_data
) {
7798 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
7799 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
7800 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
7802 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
7803 "glScheduleOverlayPlaneCHROMIUM",
7805 return error::kNoError
;
7807 gfx::GLImage
* image
=
7808 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
7810 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
7811 "glScheduleOverlayPlaneCHROMIUM",
7812 "unsupported texture format");
7813 return error::kNoError
;
7815 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
7816 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
7817 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
7818 "glScheduleOverlayPlaneCHROMIUM",
7819 "invalid transform enum");
7820 return error::kNoError
;
7822 if (!surface_
->ScheduleOverlayPlane(
7826 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
7827 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
7828 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
7829 "glScheduleOverlayPlaneCHROMIUM",
7830 "failed to schedule overlay");
7832 return error::kNoError
;
7835 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
7836 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7837 const std::string
& name_str
) {
7838 if (!StringIsValidForGLES(name_str
.c_str())) {
7840 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
7841 return error::kNoError
;
7843 Program
* program
= GetProgramInfoNotShader(
7844 client_id
, "glGetAttribLocation");
7846 return error::kNoError
;
7848 if (!program
->IsValid()) {
7850 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
7851 return error::kNoError
;
7853 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7854 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7856 return error::kOutOfBounds
;
7858 // Require the client to init this incase the context is lost and we are no
7859 // longer executing commands.
7860 if (*location
!= -1) {
7861 return error::kGenericError
;
7863 *location
= program
->GetAttribLocation(name_str
);
7864 return error::kNoError
;
7867 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
7868 uint32 immediate_data_size
,
7869 const void* cmd_data
) {
7870 const gles2::cmds::GetAttribLocation
& c
=
7871 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
7872 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7874 return error::kInvalidArguments
;
7876 std::string name_str
;
7877 if (!bucket
->GetAsString(&name_str
)) {
7878 return error::kInvalidArguments
;
7880 return GetAttribLocationHelper(
7881 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7884 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
7885 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7886 const std::string
& name_str
) {
7887 if (!StringIsValidForGLES(name_str
.c_str())) {
7889 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
7890 return error::kNoError
;
7892 Program
* program
= GetProgramInfoNotShader(
7893 client_id
, "glGetUniformLocation");
7895 return error::kNoError
;
7897 if (!program
->IsValid()) {
7899 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
7900 return error::kNoError
;
7902 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7903 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7905 return error::kOutOfBounds
;
7907 // Require the client to init this incase the context is lost an we are no
7908 // longer executing commands.
7909 if (*location
!= -1) {
7910 return error::kGenericError
;
7912 *location
= program
->GetUniformFakeLocation(name_str
);
7913 return error::kNoError
;
7916 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
7917 uint32 immediate_data_size
,
7918 const void* cmd_data
) {
7919 const gles2::cmds::GetUniformLocation
& c
=
7920 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
7921 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7923 return error::kInvalidArguments
;
7925 std::string name_str
;
7926 if (!bucket
->GetAsString(&name_str
)) {
7927 return error::kInvalidArguments
;
7929 return GetUniformLocationHelper(
7930 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7933 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
7934 const void* cmd_data
) {
7935 const gles2::cmds::GetString
& c
=
7936 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
7937 GLenum name
= static_cast<GLenum
>(c
.name
);
7938 if (!validators_
->string_type
.IsValid(name
)) {
7939 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
7940 return error::kNoError
;
7942 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
7943 std::string extensions
;
7946 str
= "OpenGL ES 2.0 Chromium";
7948 case GL_SHADING_LANGUAGE_VERSION
:
7949 str
= "OpenGL ES GLSL ES 1.0 Chromium";
7953 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7954 // They are used by WEBGL_debug_renderer_info.
7955 if (!force_webgl_glsl_validation_
)
7960 // For WebGL contexts, strip out the OES derivatives and
7961 // EXT frag depth extensions if they have not been enabled.
7962 if (force_webgl_glsl_validation_
) {
7963 extensions
= feature_info_
->extensions();
7964 if (!derivatives_explicitly_enabled_
) {
7965 size_t offset
= extensions
.find(kOESDerivativeExtension
);
7966 if (std::string::npos
!= offset
) {
7967 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
7971 if (!frag_depth_explicitly_enabled_
) {
7972 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
7973 if (std::string::npos
!= offset
) {
7974 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
7978 if (!draw_buffers_explicitly_enabled_
) {
7979 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
7980 if (std::string::npos
!= offset
) {
7981 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
7985 if (!shader_texture_lod_explicitly_enabled_
) {
7986 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
7987 if (std::string::npos
!= offset
) {
7988 extensions
.replace(offset
,
7989 arraysize(kEXTShaderTextureLodExtension
),
7994 extensions
= feature_info_
->extensions().c_str();
7996 if (supports_post_sub_buffer_
)
7997 extensions
+= " GL_CHROMIUM_post_sub_buffer";
7998 str
= extensions
.c_str();
8004 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8005 bucket
->SetFromString(str
);
8006 return error::kNoError
;
8009 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8010 const void* cmd_data
) {
8011 const gles2::cmds::BufferData
& c
=
8012 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8013 GLenum target
= static_cast<GLenum
>(c
.target
);
8014 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8015 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8016 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8017 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8018 const void* data
= NULL
;
8019 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8020 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8022 return error::kOutOfBounds
;
8025 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8026 return error::kNoError
;
8029 void GLES2DecoderImpl::DoBufferSubData(
8030 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8031 // Just delegate it. Some validation is actually done before this.
8032 buffer_manager()->ValidateAndDoBufferSubData(
8033 &state_
, target
, offset
, size
, data
);
8036 bool GLES2DecoderImpl::ClearLevel(
8037 unsigned service_id
,
8038 unsigned bind_target
,
8041 unsigned internal_format
,
8046 bool is_texture_immutable
) {
8047 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8048 if (feature_info_
->feature_flags().angle_depth_texture
&&
8049 (channels
& GLES2Util::kDepth
) != 0) {
8050 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8051 // on depth formats.
8053 glGenFramebuffersEXT(1, &fb
);
8054 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8056 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8057 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8058 GL_DEPTH_ATTACHMENT
;
8060 glFramebufferTexture2DEXT(
8061 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
8062 // ANGLE promises a depth only attachment ok.
8063 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8064 GL_FRAMEBUFFER_COMPLETE
) {
8068 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8069 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8071 state_
.SetDeviceDepthMask(GL_TRUE
);
8072 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8073 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8075 RestoreClearState();
8077 glDeleteFramebuffersEXT(1, &fb
);
8078 Framebuffer
* framebuffer
=
8079 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8080 GLuint fb_service_id
=
8081 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8082 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8086 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8089 uint32 padded_row_size
;
8090 if (!GLES2Util::ComputeImageDataSizes(
8091 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
8092 NULL
, &padded_row_size
)) {
8096 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8100 if (size
> kMaxZeroSize
) {
8101 if (kMaxZeroSize
< padded_row_size
) {
8102 // That'd be an awfully large texture.
8105 // We should never have a large total size with a zero row size.
8106 DCHECK_GT(padded_row_size
, 0U);
8107 tile_height
= kMaxZeroSize
/ padded_row_size
;
8108 if (!GLES2Util::ComputeImageDataSizes(
8109 width
, tile_height
, format
, type
, state_
.unpack_alignment
, &size
,
8114 tile_height
= height
;
8117 // Assumes the size has already been checked.
8118 scoped_ptr
<char[]> zero(new char[size
]);
8119 memset(zero
.get(), 0, size
);
8120 glBindTexture(bind_target
, service_id
);
8123 while (y
< height
) {
8124 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8125 if (is_texture_immutable
|| h
!= height
) {
8126 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8129 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8134 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
8135 &state_
, bind_target
);
8136 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
8142 const int kS3TCBlockWidth
= 4;
8143 const int kS3TCBlockHeight
= 4;
8144 const int kS3TCDXT1BlockSize
= 8;
8145 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8147 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8148 return (size
== 1) ||
8149 (size
== 2) || !(size
% kS3TCBlockWidth
);
8152 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8153 return GLES2Util::IsPOT(size
);
8156 } // anonymous namespace.
8158 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8159 const char* function_name
,
8160 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
8161 unsigned int bytes_required
= 0;
8164 case GL_ATC_RGB_AMD
:
8165 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8166 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8167 case GL_ETC1_RGB8_OES
: {
8168 int num_blocks_across
=
8169 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8170 int num_blocks_down
=
8171 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8172 int num_blocks
= num_blocks_across
* num_blocks_down
;
8173 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
8176 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8177 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8178 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8179 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8180 int num_blocks_across
=
8181 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8182 int num_blocks_down
=
8183 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8184 int num_blocks
= num_blocks_across
* num_blocks_down
;
8185 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
8188 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8189 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
8190 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
8193 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8194 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8195 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
8199 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8203 if (size
!= bytes_required
) {
8205 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8212 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8213 const char* function_name
,
8214 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
8216 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8217 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8218 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8219 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8220 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8222 GL_INVALID_OPERATION
, function_name
,
8223 "width or height invalid for level");
8228 case GL_ATC_RGB_AMD
:
8229 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8230 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8231 case GL_ETC1_RGB8_OES
: {
8232 if (width
<= 0 || height
<= 0) {
8234 GL_INVALID_OPERATION
, function_name
,
8235 "width or height invalid for level");
8240 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8241 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8242 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8243 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8244 if (!IsValidPVRTCSize(level
, width
) ||
8245 !IsValidPVRTCSize(level
, height
)) {
8247 GL_INVALID_OPERATION
, function_name
,
8248 "width or height invalid for level");
8258 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8259 const char* function_name
,
8260 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8261 GLsizei width
, GLsizei height
, GLenum format
,
8263 if (xoffset
< 0 || yoffset
< 0) {
8265 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8270 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8271 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8272 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8273 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8274 const int kBlockWidth
= 4;
8275 const int kBlockHeight
= 4;
8276 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8278 GL_INVALID_OPERATION
, function_name
,
8279 "xoffset or yoffset not multiple of 4");
8282 GLsizei tex_width
= 0;
8283 GLsizei tex_height
= 0;
8284 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8285 width
- xoffset
> tex_width
||
8286 height
- yoffset
> tex_height
) {
8288 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8291 return ValidateCompressedTexDimensions(
8292 function_name
, level
, width
, height
, format
);
8294 case GL_ATC_RGB_AMD
:
8295 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8296 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8298 GL_INVALID_OPERATION
, function_name
,
8299 "not supported for ATC textures");
8302 case GL_ETC1_RGB8_OES
: {
8304 GL_INVALID_OPERATION
, function_name
,
8305 "not supported for ECT1_RGB8_OES textures");
8308 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8309 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8310 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8311 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8312 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8314 GL_INVALID_OPERATION
, function_name
,
8315 "xoffset and yoffset must be zero");
8318 GLsizei tex_width
= 0;
8319 GLsizei tex_height
= 0;
8320 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8321 width
!= tex_width
||
8322 height
!= tex_height
) {
8324 GL_INVALID_OPERATION
, function_name
,
8325 "dimensions must match existing texture level dimensions");
8328 return ValidateCompressedTexDimensions(
8329 function_name
, level
, width
, height
, format
);
8336 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8339 GLenum internal_format
,
8345 // TODO(gman): Validate image_size is correct for width, height and format.
8346 if (!validators_
->texture_target
.IsValid(target
)) {
8347 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8348 "glCompressedTexImage2D", target
, "target");
8349 return error::kNoError
;
8351 if (!validators_
->compressed_texture_format
.IsValid(
8353 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8354 "glCompressedTexImage2D", internal_format
, "internal_format");
8355 return error::kNoError
;
8357 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8361 "glCompressedTexImage2D", "dimensions out of range");
8362 return error::kNoError
;
8364 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8369 "glCompressedTexImage2D", "unknown texture target");
8370 return error::kNoError
;
8372 Texture
* texture
= texture_ref
->texture();
8373 if (texture
->IsImmutable()) {
8375 GL_INVALID_OPERATION
,
8376 "glCompressedTexImage2D", "texture is immutable");
8377 return error::kNoError
;
8380 if (!ValidateCompressedTexDimensions(
8381 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8382 !ValidateCompressedTexFuncData(
8383 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8384 return error::kNoError
;
8387 if (!EnsureGPUMemoryAvailable(image_size
)) {
8389 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8390 return error::kNoError
;
8393 if (texture
->IsAttachedToFramebuffer()) {
8394 framebuffer_state_
.clear_state_dirty
= true;
8397 scoped_ptr
<int8
[]> zero
;
8399 zero
.reset(new int8
[image_size
]);
8400 memset(zero
.get(), 0, image_size
);
8403 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8404 glCompressedTexImage2D(
8405 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8406 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8407 if (error
== GL_NO_ERROR
) {
8408 texture_manager()->SetLevelInfo(
8409 texture_ref
, target
, level
, internal_format
,
8410 width
, height
, 1, border
, 0, 0, true);
8413 // This may be a slow command. Exit command processing to allow for
8414 // context preemption and GPU watchdog checks.
8415 ExitCommandProcessingEarly();
8416 return error::kNoError
;
8419 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8420 uint32 immediate_data_size
,
8421 const void* cmd_data
) {
8422 const gles2::cmds::CompressedTexImage2D
& c
=
8423 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
8424 GLenum target
= static_cast<GLenum
>(c
.target
);
8425 GLint level
= static_cast<GLint
>(c
.level
);
8426 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8427 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8428 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8429 GLint border
= static_cast<GLint
>(c
.border
);
8430 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8431 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8432 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8433 const void* data
= NULL
;
8434 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8435 data
= GetSharedMemoryAs
<const void*>(
8436 data_shm_id
, data_shm_offset
, image_size
);
8438 return error::kOutOfBounds
;
8441 return DoCompressedTexImage2D(
8442 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8445 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8446 uint32 immediate_data_size
,
8447 const void* cmd_data
) {
8448 const gles2::cmds::CompressedTexImage2DBucket
& c
=
8449 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
8450 GLenum target
= static_cast<GLenum
>(c
.target
);
8451 GLint level
= static_cast<GLint
>(c
.level
);
8452 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8453 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8454 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8455 GLint border
= static_cast<GLint
>(c
.border
);
8456 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8458 return error::kInvalidArguments
;
8460 uint32 data_size
= bucket
->size();
8461 GLsizei imageSize
= data_size
;
8462 const void* data
= bucket
->GetData(0, data_size
);
8464 return error::kInvalidArguments
;
8466 return DoCompressedTexImage2D(
8467 target
, level
, internal_format
, width
, height
, border
,
8471 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8472 uint32 immediate_data_size
,
8473 const void* cmd_data
) {
8474 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
8475 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
8476 GLenum target
= static_cast<GLenum
>(c
.target
);
8477 GLint level
= static_cast<GLint
>(c
.level
);
8478 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8479 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8480 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8481 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8482 GLenum format
= static_cast<GLenum
>(c
.format
);
8483 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8485 return error::kInvalidArguments
;
8487 uint32 data_size
= bucket
->size();
8488 GLsizei imageSize
= data_size
;
8489 const void* data
= bucket
->GetData(0, data_size
);
8491 return error::kInvalidArguments
;
8493 if (!validators_
->texture_target
.IsValid(target
)) {
8495 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8496 return error::kNoError
;
8498 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8499 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8500 "glCompressedTexSubImage2D", format
, "format");
8501 return error::kNoError
;
8505 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8506 return error::kNoError
;
8510 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8511 return error::kNoError
;
8513 if (imageSize
< 0) {
8515 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8516 return error::kNoError
;
8518 DoCompressedTexSubImage2D(
8519 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8520 return error::kNoError
;
8523 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
8524 const void* cmd_data
) {
8525 const gles2::cmds::TexImage2D
& c
=
8526 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
8527 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8528 "width", c
.width
, "height", c
.height
);
8529 // Set as failed for now, but if it successed, this will be set to not failed.
8530 texture_state_
.tex_image_2d_failed
= true;
8531 GLenum target
= static_cast<GLenum
>(c
.target
);
8532 GLint level
= static_cast<GLint
>(c
.level
);
8533 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8534 // for internalformat.
8535 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8536 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8537 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8538 GLint border
= static_cast<GLint
>(c
.border
);
8539 GLenum format
= static_cast<GLenum
>(c
.format
);
8540 GLenum type
= static_cast<GLenum
>(c
.type
);
8541 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8542 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8544 if (!GLES2Util::ComputeImageDataSizes(
8545 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
8547 return error::kOutOfBounds
;
8549 const void* pixels
= NULL
;
8550 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8551 pixels
= GetSharedMemoryAs
<const void*>(
8552 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8554 return error::kOutOfBounds
;
8558 TextureManager::DoTextImage2DArguments args
= {
8559 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8560 pixels
, pixels_size
};
8561 texture_manager()->ValidateAndDoTexImage2D(
8562 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8564 // This may be a slow command. Exit command processing to allow for
8565 // context preemption and GPU watchdog checks.
8566 ExitCommandProcessingEarly();
8567 return error::kNoError
;
8570 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8579 const void * data
) {
8580 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8584 GL_INVALID_OPERATION
,
8585 "glCompressedTexSubImage2D", "unknown texture for target");
8588 Texture
* texture
= texture_ref
->texture();
8590 GLenum internal_format
= 0;
8591 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
8593 GL_INVALID_OPERATION
,
8594 "glCompressedTexSubImage2D", "level does not exist.");
8597 if (internal_format
!= format
) {
8599 GL_INVALID_OPERATION
,
8600 "glCompressedTexSubImage2D", "format does not match internal format.");
8603 if (!texture
->ValidForTexture(
8604 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8606 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8610 if (!ValidateCompressedTexFuncData(
8611 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8612 !ValidateCompressedTexSubDimensions(
8613 "glCompressedTexSubImage2D",
8614 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8619 // Note: There is no need to deal with texture cleared tracking here
8620 // because the validation above means you can only get here if the level
8621 // is already a matching compressed format and in that case
8622 // CompressedTexImage2D already cleared the texture.
8623 glCompressedTexSubImage2D(
8624 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8626 // This may be a slow command. Exit command processing to allow for
8627 // context preemption and GPU watchdog checks.
8628 ExitCommandProcessingEarly();
8632 GLint start
, GLint range
, GLint sourceRange
,
8633 GLint
* out_start
, GLint
* out_range
) {
8640 GLint end
= start
+ range
;
8641 if (end
> sourceRange
) {
8642 range
-= end
- sourceRange
;
8648 void GLES2DecoderImpl::DoCopyTexImage2D(
8651 GLenum internal_format
,
8657 DCHECK(!ShouldDeferReads());
8658 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8662 GL_INVALID_OPERATION
,
8663 "glCopyTexImage2D", "unknown texture for target");
8666 Texture
* texture
= texture_ref
->texture();
8667 if (texture
->IsImmutable()) {
8669 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8672 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8675 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8678 if (!texture_manager()->ValidateFormatAndTypeCombination(
8679 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
8680 GL_UNSIGNED_BYTE
)) {
8684 // Check we have compatible formats.
8685 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8686 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8687 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
8689 if ((channels_needed
& channels_exist
) != channels_needed
) {
8691 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
8695 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8697 GL_INVALID_OPERATION
,
8698 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8702 uint32 estimated_size
= 0;
8703 if (!GLES2Util::ComputeImageDataSizes(
8704 width
, height
, internal_format
, GL_UNSIGNED_BYTE
, state_
.unpack_alignment
,
8705 &estimated_size
, NULL
, NULL
)) {
8707 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
8711 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
8712 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
8716 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8720 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8724 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8725 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8726 gfx::Size size
= GetBoundReadFrameBufferSize();
8728 if (texture
->IsAttachedToFramebuffer()) {
8729 framebuffer_state_
.clear_state_dirty
= true;
8732 // Clip to size to source dimensions
8735 GLint copyWidth
= 0;
8736 GLint copyHeight
= 0;
8737 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8738 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8742 copyWidth
!= width
||
8743 copyHeight
!= height
) {
8744 // some part was clipped so clear the texture.
8746 texture
->service_id(), texture
->target(),
8747 target
, level
, internal_format
, internal_format
, GL_UNSIGNED_BYTE
,
8748 width
, height
, texture
->IsImmutable())) {
8750 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
8753 if (copyHeight
> 0 && copyWidth
> 0) {
8754 GLint dx
= copyX
- x
;
8755 GLint dy
= copyY
- y
;
8758 ScopedModifyPixels
modify(texture_ref
);
8759 glCopyTexSubImage2D(target
, level
,
8760 destX
, destY
, copyX
, copyY
,
8761 copyWidth
, copyHeight
);
8764 ScopedModifyPixels
modify(texture_ref
);
8765 glCopyTexImage2D(target
, level
, internal_format
,
8766 copyX
, copyY
, copyWidth
, copyHeight
, border
);
8768 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8769 if (error
== GL_NO_ERROR
) {
8770 texture_manager()->SetLevelInfo(
8771 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
8772 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
8775 // This may be a slow command. Exit command processing to allow for
8776 // context preemption and GPU watchdog checks.
8777 ExitCommandProcessingEarly();
8780 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8789 DCHECK(!ShouldDeferReads());
8790 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8794 GL_INVALID_OPERATION
,
8795 "glCopyTexSubImage2D", "unknown texture for target");
8798 Texture
* texture
= texture_ref
->texture();
8801 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
8802 !texture
->ValidForTexture(
8803 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8805 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
8808 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8810 GL_INVALID_OPERATION
,
8811 "glCopyTexSubImage2D", "async upload pending for texture");
8815 // Check we have compatible formats.
8816 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8817 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8818 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
8820 if (!channels_needed
||
8821 (channels_needed
& channels_exist
) != channels_needed
) {
8823 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
8827 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8829 GL_INVALID_OPERATION
,
8830 "glCopySubImage2D", "can not be used with depth or stencil textures");
8834 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8838 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8842 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8843 gfx::Size size
= GetBoundReadFrameBufferSize();
8846 GLint copyWidth
= 0;
8847 GLint copyHeight
= 0;
8848 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8849 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8851 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, level
)) {
8853 GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D", "dimensions too big");
8859 copyWidth
!= width
||
8860 copyHeight
!= height
) {
8861 // some part was clipped so clear the sub rect.
8862 uint32 pixels_size
= 0;
8863 if (!GLES2Util::ComputeImageDataSizes(
8864 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8867 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
8870 scoped_ptr
<char[]> zero(new char[pixels_size
]);
8871 memset(zero
.get(), 0, pixels_size
);
8872 ScopedModifyPixels
modify(texture_ref
);
8874 target
, level
, xoffset
, yoffset
, width
, height
,
8875 format
, type
, zero
.get());
8878 if (copyHeight
> 0 && copyWidth
> 0) {
8879 GLint dx
= copyX
- x
;
8880 GLint dy
= copyY
- y
;
8881 GLint destX
= xoffset
+ dx
;
8882 GLint destY
= yoffset
+ dy
;
8883 ScopedModifyPixels
modify(texture_ref
);
8884 glCopyTexSubImage2D(target
, level
,
8885 destX
, destY
, copyX
, copyY
,
8886 copyWidth
, copyHeight
);
8889 // This may be a slow command. Exit command processing to allow for
8890 // context preemption and GPU watchdog checks.
8891 ExitCommandProcessingEarly();
8894 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8895 error::Error
* error
,
8896 const char* function_name
,
8905 const void * data
) {
8906 (*error
) = error::kNoError
;
8907 if (!validators_
->texture_target
.IsValid(target
)) {
8908 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
8912 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
8916 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
8919 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8923 GL_INVALID_OPERATION
,
8924 function_name
, "unknown texture for target");
8927 Texture
* texture
= texture_ref
->texture();
8928 GLenum current_type
= 0;
8929 GLenum internal_format
= 0;
8930 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
8932 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
8935 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
8936 function_name
, format
, type
, internal_format
, level
)) {
8939 if (type
!= current_type
) {
8941 GL_INVALID_OPERATION
,
8942 function_name
, "type does not match type of texture.");
8945 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8947 GL_INVALID_OPERATION
,
8948 function_name
, "async upload pending for texture");
8951 if (!texture
->ValidForTexture(
8952 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8953 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
8956 if ((GLES2Util::GetChannelsForFormat(format
) &
8957 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8959 GL_INVALID_OPERATION
,
8960 function_name
, "can not supply data for depth or stencil textures");
8964 (*error
) = error::kOutOfBounds
;
8970 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
8979 const void * data
) {
8980 error::Error error
= error::kNoError
;
8981 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
8982 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
8985 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8987 Texture
* texture
= texture_ref
->texture();
8988 GLsizei tex_width
= 0;
8989 GLsizei tex_height
= 0;
8990 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
8992 if (xoffset
!= 0 || yoffset
!= 0 ||
8993 width
!= tex_width
|| height
!= tex_height
) {
8994 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
8997 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
8998 return error::kNoError
;
9000 ScopedTextureUploadTimer
timer(&texture_state_
);
9002 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9003 return error::kNoError
;
9006 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
9007 !texture
->IsImmutable()) {
9008 ScopedTextureUploadTimer
timer(&texture_state_
);
9009 GLenum internal_format
;
9011 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
9012 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9015 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
9017 ScopedTextureUploadTimer
timer(&texture_state_
);
9019 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9021 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9023 // This may be a slow command. Exit command processing to allow for
9024 // context preemption and GPU watchdog checks.
9025 ExitCommandProcessingEarly();
9026 return error::kNoError
;
9029 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
9030 const void* cmd_data
) {
9031 const gles2::cmds::TexSubImage2D
& c
=
9032 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
9033 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9034 "width", c
.width
, "height", c
.height
);
9035 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
9036 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
9037 return error::kNoError
;
9039 GLenum target
= static_cast<GLenum
>(c
.target
);
9040 GLint level
= static_cast<GLint
>(c
.level
);
9041 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9042 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9043 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9044 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9045 GLenum format
= static_cast<GLenum
>(c
.format
);
9046 GLenum type
= static_cast<GLenum
>(c
.type
);
9048 if (!GLES2Util::ComputeImageDataSizes(
9049 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
9051 return error::kOutOfBounds
;
9053 const void* pixels
= GetSharedMemoryAs
<const void*>(
9054 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9055 return DoTexSubImage2D(
9056 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
9059 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9060 uint32 immediate_data_size
,
9061 const void* cmd_data
) {
9062 const gles2::cmds::GetVertexAttribPointerv
& c
=
9063 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
9064 GLuint index
= static_cast<GLuint
>(c
.index
);
9065 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9066 typedef cmds::GetVertexAttribPointerv::Result Result
;
9067 Result
* result
= GetSharedMemoryAs
<Result
*>(
9068 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
9070 return error::kOutOfBounds
;
9072 // Check that the client initialized the result.
9073 if (result
->size
!= 0) {
9074 return error::kInvalidArguments
;
9076 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
9077 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9078 "glGetVertexAttribPointerv", pname
, "pname");
9079 return error::kNoError
;
9081 if (index
>= group_
->max_vertex_attribs()) {
9083 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
9084 return error::kNoError
;
9086 result
->SetNumResults(1);
9087 *result
->GetData() =
9088 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
9089 return error::kNoError
;
9092 bool GLES2DecoderImpl::GetUniformSetup(
9093 GLuint program_id
, GLint fake_location
,
9094 uint32 shm_id
, uint32 shm_offset
,
9095 error::Error
* error
, GLint
* real_location
,
9096 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
9099 DCHECK(result_pointer
);
9100 DCHECK(result_type
);
9101 DCHECK(real_location
);
9102 *error
= error::kNoError
;
9103 // Make sure we have enough room for the result on failure.
9104 SizedResult
<GLint
>* result
;
9105 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9106 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
9108 *error
= error::kOutOfBounds
;
9111 *result_pointer
= result
;
9112 // Set the result size to 0 so the client does not have to check for success.
9113 result
->SetNumResults(0);
9114 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
9118 if (!program
->IsValid()) {
9119 // Program was not linked successfully. (ie, glLinkProgram)
9121 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
9124 *service_id
= program
->service_id();
9125 GLint array_index
= -1;
9126 const Program::UniformInfo
* uniform_info
=
9127 program
->GetUniformInfoByFakeLocation(
9128 fake_location
, real_location
, &array_index
);
9129 if (!uniform_info
) {
9130 // No such location.
9132 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
9135 GLenum type
= uniform_info
->type
;
9136 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
9138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
9141 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9142 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
9144 *error
= error::kOutOfBounds
;
9147 result
->size
= size
;
9148 *result_type
= type
;
9152 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
9153 const void* cmd_data
) {
9154 const gles2::cmds::GetUniformiv
& c
=
9155 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
9156 GLuint program
= c
.program
;
9157 GLint fake_location
= c
.location
;
9160 GLint real_location
= -1;
9163 if (GetUniformSetup(
9164 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9165 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
9167 service_id
, real_location
,
9168 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
9173 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
9174 const void* cmd_data
) {
9175 const gles2::cmds::GetUniformfv
& c
=
9176 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
9177 GLuint program
= c
.program
;
9178 GLint fake_location
= c
.location
;
9180 GLint real_location
= -1;
9182 typedef cmds::GetUniformfv::Result Result
;
9185 if (GetUniformSetup(
9186 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9187 &error
, &real_location
, &service_id
,
9188 reinterpret_cast<void**>(&result
), &result_type
)) {
9189 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
9190 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
9191 GLsizei num_values
= result
->GetNumResults();
9192 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
9193 glGetUniformiv(service_id
, real_location
, temp
.get());
9194 GLfloat
* dst
= result
->GetData();
9195 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
9196 dst
[ii
] = (temp
[ii
] != 0);
9199 glGetUniformfv(service_id
, real_location
, result
->GetData());
9205 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9206 uint32 immediate_data_size
,
9207 const void* cmd_data
) {
9208 const gles2::cmds::GetShaderPrecisionFormat
& c
=
9209 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
9210 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
9211 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
9212 typedef cmds::GetShaderPrecisionFormat::Result Result
;
9213 Result
* result
= GetSharedMemoryAs
<Result
*>(
9214 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9216 return error::kOutOfBounds
;
9218 // Check that the client initialized the result.
9219 if (result
->success
!= 0) {
9220 return error::kInvalidArguments
;
9222 if (!validators_
->shader_type
.IsValid(shader_type
)) {
9223 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9224 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
9225 return error::kNoError
;
9227 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
9228 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9229 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
9230 return error::kNoError
;
9233 result
->success
= 1; // true
9235 GLint range
[2] = { 0, 0 };
9236 GLint precision
= 0;
9237 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
9239 result
->min_range
= range
[0];
9240 result
->max_range
= range
[1];
9241 result
->precision
= precision
;
9243 return error::kNoError
;
9246 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
9247 uint32 immediate_data_size
,
9248 const void* cmd_data
) {
9249 const gles2::cmds::GetAttachedShaders
& c
=
9250 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
9251 uint32 result_size
= c
.result_size
;
9252 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9253 Program
* program
= GetProgramInfoNotShader(
9254 program_id
, "glGetAttachedShaders");
9256 return error::kNoError
;
9258 typedef cmds::GetAttachedShaders::Result Result
;
9259 uint32 max_count
= Result::ComputeMaxResults(result_size
);
9260 Result
* result
= GetSharedMemoryAs
<Result
*>(
9261 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
9263 return error::kOutOfBounds
;
9265 // Check that the client initialized the result.
9266 if (result
->size
!= 0) {
9267 return error::kInvalidArguments
;
9270 glGetAttachedShaders(
9271 program
->service_id(), max_count
, &count
, result
->GetData());
9272 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
9273 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
9274 &result
->GetData()[ii
])) {
9276 return error::kGenericError
;
9279 result
->SetNumResults(count
);
9280 return error::kNoError
;
9283 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
9284 uint32 immediate_data_size
,
9285 const void* cmd_data
) {
9286 const gles2::cmds::GetActiveUniform
& c
=
9287 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
9288 GLuint program_id
= c
.program
;
9289 GLuint index
= c
.index
;
9290 uint32 name_bucket_id
= c
.name_bucket_id
;
9291 typedef cmds::GetActiveUniform::Result Result
;
9292 Result
* result
= GetSharedMemoryAs
<Result
*>(
9293 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9295 return error::kOutOfBounds
;
9297 // Check that the client initialized the result.
9298 if (result
->success
!= 0) {
9299 return error::kInvalidArguments
;
9301 Program
* program
= GetProgramInfoNotShader(
9302 program_id
, "glGetActiveUniform");
9304 return error::kNoError
;
9306 const Program::UniformInfo
* uniform_info
=
9307 program
->GetUniformInfo(index
);
9308 if (!uniform_info
) {
9310 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
9311 return error::kNoError
;
9313 result
->success
= 1; // true.
9314 result
->size
= uniform_info
->size
;
9315 result
->type
= uniform_info
->type
;
9316 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9317 bucket
->SetFromString(uniform_info
->name
.c_str());
9318 return error::kNoError
;
9321 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
9322 const void* cmd_data
) {
9323 const gles2::cmds::GetActiveAttrib
& c
=
9324 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
9325 GLuint program_id
= c
.program
;
9326 GLuint index
= c
.index
;
9327 uint32 name_bucket_id
= c
.name_bucket_id
;
9328 typedef cmds::GetActiveAttrib::Result Result
;
9329 Result
* result
= GetSharedMemoryAs
<Result
*>(
9330 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9332 return error::kOutOfBounds
;
9334 // Check that the client initialized the result.
9335 if (result
->success
!= 0) {
9336 return error::kInvalidArguments
;
9338 Program
* program
= GetProgramInfoNotShader(
9339 program_id
, "glGetActiveAttrib");
9341 return error::kNoError
;
9343 const Program::VertexAttrib
* attrib_info
=
9344 program
->GetAttribInfo(index
);
9347 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9348 return error::kNoError
;
9350 result
->success
= 1; // true.
9351 result
->size
= attrib_info
->size
;
9352 result
->type
= attrib_info
->type
;
9353 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9354 bucket
->SetFromString(attrib_info
->name
.c_str());
9355 return error::kNoError
;
9358 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
9359 const void* cmd_data
) {
9360 #if 1 // No binary shader support.
9361 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
9362 return error::kNoError
;
9364 GLsizei n
= static_cast<GLsizei
>(c
.n
);
9366 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
9367 return error::kNoError
;
9369 GLsizei length
= static_cast<GLsizei
>(c
.length
);
9371 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
9372 return error::kNoError
;
9375 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
9376 return error::kOutOfBounds
;
9378 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
9379 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
9380 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
9381 const void* binary
= GetSharedMemoryAs
<const void*>(
9382 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
9383 if (shaders
== NULL
|| binary
== NULL
) {
9384 return error::kOutOfBounds
;
9386 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9387 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9388 Shader
* shader
= GetShader(shaders
[ii
]);
9390 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
9391 return error::kNoError
;
9393 service_ids
[ii
] = shader
->service_id();
9395 // TODO(gman): call glShaderBinary
9396 return error::kNoError
;
9400 void GLES2DecoderImpl::DoSwapBuffers() {
9401 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9403 int this_frame_number
= frame_number_
++;
9404 // TRACE_EVENT for gpu tests:
9405 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9406 TRACE_EVENT_SCOPE_THREAD
,
9407 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9408 "width", (is_offscreen
? offscreen_size_
.width() :
9409 surface_
->GetSize().width()));
9410 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9411 "offscreen", is_offscreen
,
9412 "frame", this_frame_number
);
9414 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9418 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9421 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9422 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9423 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9426 // If offscreen then don't actually SwapBuffers to the display. Just copy
9427 // the rendered frame to another frame buffer.
9429 TRACE_EVENT2("gpu", "Offscreen",
9430 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
9431 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
9432 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9433 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9435 if (workarounds().needs_offscreen_buffer_workaround
) {
9436 offscreen_saved_frame_buffer_
->Create();
9440 // Allocate the offscreen saved color texture.
9441 DCHECK(offscreen_saved_color_format_
);
9442 offscreen_saved_color_texture_
->AllocateStorage(
9443 offscreen_size_
, offscreen_saved_color_format_
, false);
9445 offscreen_saved_frame_buffer_
->AttachRenderTexture(
9446 offscreen_saved_color_texture_
.get());
9447 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
9448 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
9449 GL_FRAMEBUFFER_COMPLETE
) {
9450 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9451 << "because offscreen saved FBO was incomplete.";
9452 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9456 // Clear the offscreen color texture.
9457 // TODO(piman): Is this still necessary?
9459 ScopedFrameBufferBinder
binder(this,
9460 offscreen_saved_frame_buffer_
->id());
9461 glClearColor(0, 0, 0, 0);
9462 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
9463 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
9464 glClear(GL_COLOR_BUFFER_BIT
);
9465 RestoreClearState();
9469 UpdateParentTextureInfo();
9472 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
9474 ScopedGLErrorSuppressor
suppressor(
9475 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9477 if (IsOffscreenBufferMultisampled()) {
9478 // For multisampled buffers, resolve the frame buffer.
9479 ScopedResolvedFrameBufferBinder
binder(this, true, false);
9481 ScopedFrameBufferBinder
binder(this,
9482 offscreen_target_frame_buffer_
->id());
9484 if (offscreen_target_buffer_preserved_
) {
9485 // Copy the target frame buffer to the saved offscreen texture.
9486 offscreen_saved_color_texture_
->Copy(
9487 offscreen_saved_color_texture_
->size(),
9488 offscreen_saved_color_format_
);
9490 // Flip the textures in the parent context via the texture manager.
9491 if (!!offscreen_saved_color_texture_info_
.get())
9492 offscreen_saved_color_texture_info_
->texture()->
9493 SetServiceId(offscreen_target_color_texture_
->id());
9495 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
9496 offscreen_target_frame_buffer_
->AttachRenderTexture(
9497 offscreen_target_color_texture_
.get());
9500 // Ensure the side effects of the copy are visible to the parent
9501 // context. There is no need to do this for ANGLE because it uses a
9502 // single D3D device for all contexts.
9503 if (!feature_info_
->feature_flags().is_angle
)
9507 if (!surface_
->SwapBuffers()) {
9508 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
9509 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9513 // This may be a slow command. Exit command processing to allow for
9514 // context preemption and GPU watchdog checks.
9515 ExitCommandProcessingEarly();
9518 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9519 uint32 immediate_data_size
,
9520 const void* cmd_data
) {
9521 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
9522 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
9523 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9524 if (!bucket
|| bucket
->size() == 0) {
9525 return error::kInvalidArguments
;
9527 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
9528 Result
* result
= GetSharedMemoryAs
<Result
*>(
9529 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9531 return error::kOutOfBounds
;
9533 // Check that the client initialized the result.
9535 return error::kInvalidArguments
;
9537 std::string feature_str
;
9538 if (!bucket
->GetAsString(&feature_str
)) {
9539 return error::kInvalidArguments
;
9542 // TODO(gman): make this some kind of table to function pointer thingy.
9543 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9544 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9545 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
9546 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9547 // TODO(gman): decide how to remove the need for this const_cast.
9548 // I could make validators_ non const but that seems bad as this is the only
9549 // place it is needed. I could make some special friend class of validators
9550 // just to allow this to set them. That seems silly. I could refactor this
9551 // code to use the extension mechanism or the initialization attributes to
9552 // turn this feature on. Given that the only real point of this is to make
9553 // the conformance tests pass and given that there is lots of real work that
9554 // needs to be done it seems like refactoring for one to one of those
9555 // methods is a very low priority.
9556 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
9557 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
9558 force_webgl_glsl_validation_
= true;
9559 InitializeShaderTranslator();
9561 return error::kNoError
;
9564 *result
= 1; // true.
9565 return error::kNoError
;
9568 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9569 uint32 immediate_data_size
,
9570 const void* cmd_data
) {
9571 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
9572 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
9574 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9575 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
9576 info
->Initialize(disallowed_features_
);
9577 bucket
->SetFromString(info
->extensions().c_str());
9578 return error::kNoError
;
9581 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9582 uint32 immediate_data_size
,
9583 const void* cmd_data
) {
9584 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
9585 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
9586 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9587 if (!bucket
|| bucket
->size() == 0) {
9588 return error::kInvalidArguments
;
9590 std::string feature_str
;
9591 if (!bucket
->GetAsString(&feature_str
)) {
9592 return error::kInvalidArguments
;
9595 bool desire_webgl_glsl_validation
=
9596 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
9597 bool desire_standard_derivatives
= false;
9598 bool desire_frag_depth
= false;
9599 bool desire_draw_buffers
= false;
9600 bool desire_shader_texture_lod
= false;
9601 if (force_webgl_glsl_validation_
) {
9602 desire_standard_derivatives
=
9603 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
9605 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
9606 desire_draw_buffers
=
9607 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
9608 desire_shader_texture_lod
=
9609 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
9612 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
9613 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
9614 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
9615 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
9616 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
9617 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
9618 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
9619 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
9620 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
9621 InitializeShaderTranslator();
9624 UpdateCapabilities();
9626 return error::kNoError
;
9629 error::Error
GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9630 uint32 immediate_data_size
,
9631 const void* cmd_data
) {
9632 const gles2::cmds::GetMultipleIntegervCHROMIUM
& c
=
9633 *static_cast<const gles2::cmds::GetMultipleIntegervCHROMIUM
*>(cmd_data
);
9634 GLuint count
= c
.count
;
9636 if (!SafeMultiplyUint32(count
, sizeof(GLenum
), &pnames_size
)) {
9637 return error::kOutOfBounds
;
9639 const GLenum
* pnames
= GetSharedMemoryAs
<const GLenum
*>(
9640 c
.pnames_shm_id
, c
.pnames_shm_offset
, pnames_size
);
9641 if (pnames
== NULL
) {
9642 return error::kOutOfBounds
;
9645 // We have to copy them since we use them twice so the client
9646 // can't change them between the time we validate them and the time we use
9648 scoped_ptr
<GLenum
[]> enums(new GLenum
[count
]);
9649 memcpy(enums
.get(), pnames
, pnames_size
);
9651 // Count up the space needed for the result.
9652 uint32 num_results
= 0;
9653 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9654 uint32 num
= util_
.GLGetNumValuesReturned(enums
[ii
]);
9656 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9657 "glGetMultipleCHROMIUM", enums
[ii
], "pname");
9658 return error::kNoError
;
9660 // Num will never be more than 4.
9662 if (!SafeAddUint32(num_results
, num
, &num_results
)) {
9663 return error::kOutOfBounds
;
9667 uint32 result_size
= 0;
9668 if (!SafeMultiplyUint32(num_results
, sizeof(GLint
), &result_size
)) {
9669 return error::kOutOfBounds
;
9672 if (result_size
!= static_cast<uint32
>(c
.size
)) {
9675 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9676 return error::kNoError
;
9679 GLint
* results
= GetSharedMemoryAs
<GLint
*>(
9680 c
.results_shm_id
, c
.results_shm_offset
, result_size
);
9681 if (results
== NULL
) {
9682 return error::kOutOfBounds
;
9685 // Check the results have been cleared in case the context was lost.
9686 for (uint32 ii
= 0; ii
< num_results
; ++ii
) {
9688 return error::kInvalidArguments
;
9693 GLint
* start
= results
;
9694 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9695 GLsizei num_written
= 0;
9696 if (!state_
.GetStateAsGLint(enums
[ii
], results
, &num_written
) &&
9697 !GetHelper(enums
[ii
], results
, &num_written
)) {
9698 DoGetIntegerv(enums
[ii
], results
);
9700 results
+= num_written
;
9703 // Just to verify. Should this be a DCHECK?
9704 if (static_cast<uint32
>(results
- start
) != num_results
) {
9705 return error::kOutOfBounds
;
9708 return error::kNoError
;
9711 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9712 uint32 immediate_data_size
,
9713 const void* cmd_data
) {
9714 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
9715 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
9716 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9717 uint32 bucket_id
= c
.bucket_id
;
9718 Bucket
* bucket
= CreateBucket(bucket_id
);
9719 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
9720 Program
* program
= NULL
;
9721 program
= GetProgram(program_id
);
9722 if (!program
|| !program
->IsValid()) {
9723 return error::kNoError
;
9725 program
->GetProgramInfo(program_manager(), bucket
);
9726 return error::kNoError
;
9729 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
9730 switch (reset_status_
) {
9732 // TODO(kbr): improve the precision of the error code in this case.
9733 // Consider delegating to context for error code if MakeCurrent fails.
9734 return error::kUnknown
;
9735 case GL_GUILTY_CONTEXT_RESET_ARB
:
9736 return error::kGuilty
;
9737 case GL_INNOCENT_CONTEXT_RESET_ARB
:
9738 return error::kInnocent
;
9739 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
9740 return error::kUnknown
;
9744 return error::kUnknown
;
9747 bool GLES2DecoderImpl::WasContextLost() {
9748 if (reset_status_
!= GL_NO_ERROR
) {
9751 if (context_
->WasAllocatedUsingRobustnessExtension()) {
9752 GLenum status
= GL_NO_ERROR
;
9753 if (has_robustness_extension_
)
9754 status
= glGetGraphicsResetStatusARB();
9755 if (status
!= GL_NO_ERROR
) {
9756 // The graphics card was reset. Signal a lost context to the application.
9757 reset_status_
= status
;
9758 reset_by_robustness_extension_
= true;
9759 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
9760 << " context lost via ARB/EXT_robustness. Reset status = "
9761 << GLES2Util::GetStringEnum(status
);
9768 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9769 return WasContextLost() && reset_by_robustness_extension_
;
9772 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
9773 // Only loses the context once.
9774 if (reset_status_
!= GL_NO_ERROR
) {
9778 // Marks this context as lost.
9779 reset_status_
= reset_status
;
9780 current_decoder_error_
= error::kLostContext
;
9783 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9784 uint32 immediate_data_size
,
9785 const void* cmd_data
) {
9786 return error::kUnknownCommand
;
9789 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9790 uint32 immediate_data_size
,
9791 const void* cmd_data
) {
9792 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
9793 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
9794 group_
->mailbox_manager()->PullTextureUpdates();
9795 if (wait_sync_point_callback_
.is_null())
9796 return error::kNoError
;
9798 return wait_sync_point_callback_
.Run(c
.sync_point
) ?
9799 error::kNoError
: error::kDeferCommandUntilLater
;
9802 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9803 uint32 immediate_data_size
,
9804 const void* cmd_data
) {
9805 if (surface_
->DeferDraws())
9806 return error::kDeferCommandUntilLater
;
9807 if (!surface_
->SetBackbufferAllocation(false))
9808 return error::kLostContext
;
9809 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
9810 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
9811 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
9812 return error::kNoError
;
9815 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9816 GLsizei n
, const GLuint
* client_ids
) {
9817 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9818 if (query_manager_
->GetQuery(client_ids
[ii
])) {
9822 query_manager_
->GenQueries(n
, client_ids
);
9826 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9827 GLsizei n
, const GLuint
* client_ids
) {
9828 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9829 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
9830 if (query
&& !query
->IsDeleted()) {
9831 ContextState::QueryMap::iterator it
=
9832 state_
.current_queries
.find(query
->target());
9833 if (it
!= state_
.current_queries
.end())
9834 state_
.current_queries
.erase(it
);
9836 query
->Destroy(true);
9838 query_manager_
->RemoveQuery(client_ids
[ii
]);
9842 bool GLES2DecoderImpl::ProcessPendingQueries() {
9843 if (query_manager_
.get() == NULL
) {
9846 if (!query_manager_
->ProcessPendingQueries()) {
9847 current_decoder_error_
= error::kOutOfBounds
;
9849 return query_manager_
->HavePendingQueries();
9852 // Note that if there are no pending readpixels right now,
9853 // this function will call the callback immediately.
9854 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
9855 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
9856 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
9862 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9863 while (!pending_readpixel_fences_
.empty() &&
9864 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
9865 std::vector
<base::Closure
> callbacks
=
9866 pending_readpixel_fences_
.front()->callbacks
;
9867 pending_readpixel_fences_
.pop();
9868 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
9874 bool GLES2DecoderImpl::HasMoreIdleWork() {
9875 return !pending_readpixel_fences_
.empty() ||
9876 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
9879 void GLES2DecoderImpl::PerformIdleWork() {
9880 ProcessPendingReadPixels();
9881 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
9883 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
9884 ProcessFinishedAsyncTransfers();
9887 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
9888 const void* cmd_data
) {
9889 const gles2::cmds::BeginQueryEXT
& c
=
9890 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
9891 GLenum target
= static_cast<GLenum
>(c
.target
);
9892 GLuint client_id
= static_cast<GLuint
>(c
.id
);
9893 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
9894 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
9897 case GL_COMMANDS_ISSUED_CHROMIUM
:
9898 case GL_LATENCY_QUERY_CHROMIUM
:
9899 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
9900 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
9901 case GL_GET_ERROR_QUERY_CHROMIUM
:
9903 case GL_COMMANDS_COMPLETED_CHROMIUM
:
9904 if (!features().chromium_sync_query
) {
9906 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9907 "not enabled for commands completed queries");
9908 return error::kNoError
;
9912 if (!features().occlusion_query_boolean
) {
9914 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9915 "not enabled for occlusion queries");
9916 return error::kNoError
;
9921 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
9923 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
9924 return error::kNoError
;
9927 if (client_id
== 0) {
9928 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
9929 return error::kNoError
;
9932 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
9934 if (!query_manager_
->IsValidQuery(client_id
)) {
9935 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9937 "id not made by glGenQueriesEXT");
9938 return error::kNoError
;
9940 query
= query_manager_
->CreateQuery(
9941 target
, client_id
, sync_shm_id
, sync_shm_offset
);
9944 if (query
->target() != target
) {
9946 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
9947 return error::kNoError
;
9948 } else if (query
->shm_id() != sync_shm_id
||
9949 query
->shm_offset() != sync_shm_offset
) {
9950 DLOG(ERROR
) << "Shared memory used by query not the same as before";
9951 return error::kInvalidArguments
;
9954 if (!query_manager_
->BeginQuery(query
)) {
9955 return error::kOutOfBounds
;
9958 state_
.current_queries
[target
] = query
;
9959 return error::kNoError
;
9962 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
9963 const void* cmd_data
) {
9964 const gles2::cmds::EndQueryEXT
& c
=
9965 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
9966 GLenum target
= static_cast<GLenum
>(c
.target
);
9967 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
9968 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
9970 if (it
== state_
.current_queries
.end()) {
9972 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
9973 return error::kNoError
;
9976 QueryManager::Query
* query
= it
->second
.get();
9977 if (!query_manager_
->EndQuery(query
, submit_count
)) {
9978 return error::kOutOfBounds
;
9981 query_manager_
->ProcessPendingTransferQueries();
9983 state_
.current_queries
.erase(it
);
9984 return error::kNoError
;
9987 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9988 GLsizei n
, const GLuint
* client_ids
) {
9989 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9990 if (GetVertexAttribManager(client_ids
[ii
])) {
9995 if (!features().native_vertex_array_object
) {
9997 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9998 CreateVertexAttribManager(client_ids
[ii
], 0, true);
10001 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10003 glGenVertexArraysOES(n
, service_ids
.get());
10004 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10005 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
10012 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10013 GLsizei n
, const GLuint
* client_ids
) {
10014 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10015 VertexAttribManager
* vao
=
10016 GetVertexAttribManager(client_ids
[ii
]);
10017 if (vao
&& !vao
->IsDeleted()) {
10018 if (state_
.vertex_attrib_manager
.get() == vao
) {
10019 DoBindVertexArrayOES(0);
10021 RemoveVertexAttribManager(client_ids
[ii
]);
10026 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
10027 VertexAttribManager
* vao
= NULL
;
10028 if (client_id
!= 0) {
10029 vao
= GetVertexAttribManager(client_id
);
10031 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10032 // only allows names that have been previously generated. As such, we do
10033 // not generate new names here.
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION
,
10036 "glBindVertexArrayOES", "bad vertex array id.");
10037 current_decoder_error_
= error::kNoError
;
10041 vao
= state_
.default_vertex_attrib_manager
.get();
10044 // Only set the VAO state if it's changed
10045 if (state_
.vertex_attrib_manager
.get() != vao
) {
10046 state_
.vertex_attrib_manager
= vao
;
10047 if (!features().native_vertex_array_object
) {
10048 EmulateVertexArrayState();
10050 GLuint service_id
= vao
->service_id();
10051 glBindVertexArrayOES(service_id
);
10056 // Used when OES_vertex_array_object isn't natively supported
10057 void GLES2DecoderImpl::EmulateVertexArrayState() {
10058 // Setup the Vertex attribute state
10059 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
10060 RestoreStateForAttrib(vv
, true);
10063 // Setup the element buffer
10064 Buffer
* element_array_buffer
=
10065 state_
.vertex_attrib_manager
->element_array_buffer();
10066 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
10067 element_array_buffer
? element_array_buffer
->service_id() : 0);
10070 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
10071 const VertexAttribManager
* vao
=
10072 GetVertexAttribManager(client_id
);
10073 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
10076 #if defined(OS_MACOSX)
10077 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
10078 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
10080 if (it
!= texture_to_io_surface_map_
.end()) {
10081 // Found a previous IOSurface bound to this texture; release it.
10082 IOSurfaceRef surface
= it
->second
;
10083 CFRelease(surface
);
10084 texture_to_io_surface_map_
.erase(it
);
10089 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10090 GLenum target
, GLsizei width
, GLsizei height
,
10091 GLuint io_surface_id
, GLuint plane
) {
10092 #if defined(OS_MACOSX)
10093 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
10094 LOCAL_SET_GL_ERROR(
10095 GL_INVALID_OPERATION
,
10096 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10100 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
10101 // This might be supported in the future, and if we could require
10102 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10103 // could delete a lot of code. For now, perform strict validation so we
10104 // know what's going on.
10105 LOCAL_SET_GL_ERROR(
10106 GL_INVALID_OPERATION
,
10107 "glTexImageIOSurface2DCHROMIUM",
10108 "requires TEXTURE_RECTANGLE_ARB target");
10112 // Default target might be conceptually valid, but disallow it to avoid
10114 TextureRef
* texture_ref
=
10115 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10116 if (!texture_ref
) {
10117 LOCAL_SET_GL_ERROR(
10118 GL_INVALID_OPERATION
,
10119 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10123 // Look up the new IOSurface. Note that because of asynchrony
10124 // between processes this might fail; during live resizing the
10125 // plugin process might allocate and release an IOSurface before
10126 // this process gets a chance to look it up. Hold on to any old
10127 // IOSurface in this case.
10128 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
10130 LOCAL_SET_GL_ERROR(
10131 GL_INVALID_OPERATION
,
10132 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10136 // Release any IOSurface previously bound to this texture.
10137 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
10139 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10140 texture_to_io_surface_map_
.insert(
10141 std::make_pair(texture_ref
->service_id(), surface
));
10143 CGLContextObj context
=
10144 static_cast<CGLContextObj
>(context_
->GetHandle());
10146 CGLError err
= CGLTexImageIOSurface2D(
10153 GL_UNSIGNED_INT_8_8_8_8_REV
,
10157 if (err
!= kCGLNoError
) {
10158 LOCAL_SET_GL_ERROR(
10159 GL_INVALID_OPERATION
,
10160 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10164 texture_manager()->SetLevelInfo(
10165 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
10166 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
10169 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10170 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10174 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
10175 switch (internalformat
) {
10186 case GL_LUMINANCE8_ALPHA8_EXT
:
10187 return GL_LUMINANCE_ALPHA
;
10188 case GL_LUMINANCE8_EXT
:
10189 return GL_LUMINANCE
;
10190 case GL_ALPHA8_EXT
:
10192 case GL_RGBA32F_EXT
:
10194 case GL_RGB32F_EXT
:
10196 case GL_ALPHA32F_EXT
:
10198 case GL_LUMINANCE32F_EXT
:
10199 return GL_LUMINANCE
;
10200 case GL_LUMINANCE_ALPHA32F_EXT
:
10201 return GL_LUMINANCE_ALPHA
;
10202 case GL_RGBA16F_EXT
:
10204 case GL_RGB16F_EXT
:
10206 case GL_ALPHA16F_EXT
:
10208 case GL_LUMINANCE16F_EXT
:
10209 return GL_LUMINANCE
;
10210 case GL_LUMINANCE_ALPHA16F_EXT
:
10211 return GL_LUMINANCE_ALPHA
;
10213 return GL_BGRA_EXT
;
10219 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10220 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
10221 GLenum internal_format
, GLenum dest_type
) {
10222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10224 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
10225 TextureRef
* source_texture_ref
= GetTexture(source_id
);
10227 if (!source_texture_ref
|| !dest_texture_ref
) {
10228 LOCAL_SET_GL_ERROR(
10229 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
10233 if (GL_TEXTURE_2D
!= target
) {
10234 LOCAL_SET_GL_ERROR(
10235 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
10239 Texture
* source_texture
= source_texture_ref
->texture();
10240 Texture
* dest_texture
= dest_texture_ref
->texture();
10241 if (dest_texture
->target() != GL_TEXTURE_2D
||
10242 (source_texture
->target() != GL_TEXTURE_2D
&&
10243 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
10244 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
10245 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10246 "glCopyTextureCHROMIUM",
10247 "invalid texture target binding");
10251 int source_width
, source_height
, dest_width
, dest_height
;
10253 gfx::GLImage
* image
=
10254 source_texture
->GetLevelImage(source_texture
->target(), 0);
10256 gfx::Size size
= image
->GetSize();
10257 source_width
= size
.width();
10258 source_height
= size
.height();
10259 if (source_width
<= 0 || source_height
<= 0) {
10260 LOCAL_SET_GL_ERROR(
10262 "glCopyTextureChromium", "invalid image size");
10266 if (!source_texture
->GetLevelSize(
10267 source_texture
->target(), 0, &source_width
, &source_height
)) {
10268 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10269 "glCopyTextureChromium",
10270 "source texture has no level 0");
10274 // Check that this type of texture is allowed.
10275 if (!texture_manager()->ValidForTarget(
10276 source_texture
->target(), level
, source_width
, source_height
, 1)) {
10277 LOCAL_SET_GL_ERROR(
10278 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
10283 // Clear the source texture if necessary.
10284 if (!texture_manager()->ClearTextureLevel(
10285 this, source_texture_ref
, source_texture
->target(), 0)) {
10286 LOCAL_SET_GL_ERROR(
10287 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
10291 GLenum source_type
= 0;
10292 GLenum source_internal_format
= 0;
10293 source_texture
->GetLevelType(
10294 source_texture
->target(), 0, &source_type
, &source_internal_format
);
10296 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10297 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10298 // renderable on some platforms.
10299 bool valid_dest_format
= internal_format
== GL_RGB
||
10300 internal_format
== GL_RGBA
||
10301 internal_format
== GL_BGRA_EXT
;
10302 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
10303 source_internal_format
== GL_RGB
||
10304 source_internal_format
== GL_RGBA
||
10305 source_internal_format
== GL_LUMINANCE
||
10306 source_internal_format
== GL_LUMINANCE_ALPHA
||
10307 source_internal_format
== GL_BGRA_EXT
;
10308 if (!valid_source_format
|| !valid_dest_format
) {
10309 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10310 "glCopyTextureCHROMIUM",
10311 "invalid internal format");
10315 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10316 // needed because it takes 10s of milliseconds to initialize.
10317 if (!copy_texture_CHROMIUM_
.get()) {
10318 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10319 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
10320 copy_texture_CHROMIUM_
->Initialize(this);
10321 RestoreCurrentFramebufferBindings();
10322 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
10326 GLenum dest_type_previous
= dest_type
;
10327 GLenum dest_internal_format
= internal_format
;
10328 bool dest_level_defined
= dest_texture
->GetLevelSize(
10329 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
10331 if (dest_level_defined
) {
10332 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
10333 &dest_internal_format
);
10336 // Resize the destination texture to the dimensions of the source texture.
10337 if (!dest_level_defined
|| dest_width
!= source_width
||
10338 dest_height
!= source_height
||
10339 dest_internal_format
!= internal_format
||
10340 dest_type_previous
!= dest_type
) {
10341 // Ensure that the glTexImage2D succeeds.
10342 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10343 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
10345 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
10346 0, internal_format
, dest_type
, NULL
);
10347 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10348 if (error
!= GL_NO_ERROR
) {
10349 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
10353 texture_manager()->SetLevelInfo(
10354 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
10355 source_height
, 1, 0, internal_format
, dest_type
, true);
10357 texture_manager()->SetLevelCleared(
10358 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
10361 ScopedModifyPixels
modify(dest_texture_ref
);
10363 // Try using GLImage::CopyTexImage when possible.
10364 bool unpack_premultiply_alpha_change
=
10365 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
10366 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&& !level
) {
10367 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
10368 if (image
->CopyTexImage(GL_TEXTURE_2D
))
10372 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
10374 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10375 // before presenting.
10376 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
10377 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10378 // instead of using default matrix crbug.com/226218.
10379 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
10380 0.0f
, 1.0f
, 0.0f
, 0.0f
,
10381 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10382 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10383 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
10385 source_texture
->target(),
10386 source_texture
->service_id(),
10387 dest_texture
->service_id(),
10392 unpack_premultiply_alpha_
,
10393 unpack_unpremultiply_alpha_
,
10396 copy_texture_CHROMIUM_
->DoCopyTexture(this,
10397 source_texture
->target(),
10398 source_texture
->service_id(),
10399 source_internal_format
,
10400 dest_texture
->service_id(),
10406 unpack_premultiply_alpha_
,
10407 unpack_unpremultiply_alpha_
);
10410 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
10413 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
10414 switch (internalformat
) {
10416 return GL_UNSIGNED_SHORT_5_6_5
;
10418 return GL_UNSIGNED_SHORT_4_4_4_4
;
10420 return GL_UNSIGNED_SHORT_5_5_5_1
;
10422 return GL_UNSIGNED_BYTE
;
10424 return GL_UNSIGNED_BYTE
;
10425 case GL_LUMINANCE8_ALPHA8_EXT
:
10426 return GL_UNSIGNED_BYTE
;
10427 case GL_LUMINANCE8_EXT
:
10428 return GL_UNSIGNED_BYTE
;
10429 case GL_ALPHA8_EXT
:
10430 return GL_UNSIGNED_BYTE
;
10431 case GL_RGBA32F_EXT
:
10433 case GL_RGB32F_EXT
:
10435 case GL_ALPHA32F_EXT
:
10437 case GL_LUMINANCE32F_EXT
:
10439 case GL_LUMINANCE_ALPHA32F_EXT
:
10441 case GL_RGBA16F_EXT
:
10442 return GL_HALF_FLOAT_OES
;
10443 case GL_RGB16F_EXT
:
10444 return GL_HALF_FLOAT_OES
;
10445 case GL_ALPHA16F_EXT
:
10446 return GL_HALF_FLOAT_OES
;
10447 case GL_LUMINANCE16F_EXT
:
10448 return GL_HALF_FLOAT_OES
;
10449 case GL_LUMINANCE_ALPHA16F_EXT
:
10450 return GL_HALF_FLOAT_OES
;
10452 return GL_UNSIGNED_BYTE
;
10458 void GLES2DecoderImpl::DoTexStorage2DEXT(
10461 GLenum internal_format
,
10464 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10465 "width", width
, "height", height
);
10466 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
10467 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
10468 LOCAL_SET_GL_ERROR(
10469 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
10472 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10474 if (!texture_ref
) {
10475 LOCAL_SET_GL_ERROR(
10476 GL_INVALID_OPERATION
,
10477 "glTexStorage2DEXT", "unknown texture for target");
10480 Texture
* texture
= texture_ref
->texture();
10481 if (texture
->IsAttachedToFramebuffer()) {
10482 framebuffer_state_
.clear_state_dirty
= true;
10484 if (texture
->IsImmutable()) {
10485 LOCAL_SET_GL_ERROR(
10486 GL_INVALID_OPERATION
,
10487 "glTexStorage2DEXT", "texture is immutable");
10491 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
10492 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
10495 GLsizei level_width
= width
;
10496 GLsizei level_height
= height
;
10497 uint32 estimated_size
= 0;
10498 for (int ii
= 0; ii
< levels
; ++ii
) {
10499 uint32 level_size
= 0;
10500 if (!GLES2Util::ComputeImageDataSizes(
10501 level_width
, level_height
, format
, type
, state_
.unpack_alignment
,
10502 &estimated_size
, NULL
, NULL
) ||
10503 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
10504 LOCAL_SET_GL_ERROR(
10505 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
10508 level_width
= std::max(1, level_width
>> 1);
10509 level_height
= std::max(1, level_height
>> 1);
10511 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10512 LOCAL_SET_GL_ERROR(
10513 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
10518 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10519 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
10520 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10521 if (error
== GL_NO_ERROR
) {
10522 GLsizei level_width
= width
;
10523 GLsizei level_height
= height
;
10524 for (int ii
= 0; ii
< levels
; ++ii
) {
10525 texture_manager()->SetLevelInfo(
10526 texture_ref
, target
, ii
, format
,
10527 level_width
, level_height
, 1, 0, format
, type
, false);
10528 level_width
= std::max(1, level_width
>> 1);
10529 level_height
= std::max(1, level_height
>> 1);
10531 texture
->SetImmutable(true);
10535 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10536 uint32 immediate_data_size
,
10537 const void* cmd_data
) {
10538 return error::kUnknownCommand
;
10541 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
10542 const GLbyte
* data
) {
10543 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10544 "context", logger_
.GetLogPrefix(),
10545 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10547 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10549 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
10552 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
10553 GLenum target
, const GLbyte
* data
) {
10554 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10555 "context", logger_
.GetLogPrefix(),
10556 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10558 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
10562 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
10563 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
10564 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10565 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
10566 "mailbox that was not generated by "
10567 "GenMailboxCHROMIUM.";
10569 if (!texture_ref
) {
10570 LOCAL_SET_GL_ERROR(
10571 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
10575 Texture
* produced
= texture_manager()->Produce(texture_ref
);
10577 LOCAL_SET_GL_ERROR(
10578 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
10582 if (produced
->target() != target
) {
10583 LOCAL_SET_GL_ERROR(
10584 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
10588 group_
->mailbox_manager()->ProduceTexture(target
, mailbox
, produced
);
10591 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
10592 const GLbyte
* data
) {
10593 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10594 "context", logger_
.GetLogPrefix(),
10595 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10596 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10597 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10598 "mailbox that was not generated by "
10599 "GenMailboxCHROMIUM.";
10601 scoped_refptr
<TextureRef
> texture_ref
=
10602 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10603 if (!texture_ref
.get()) {
10604 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10605 "glConsumeTextureCHROMIUM",
10606 "unknown texture for target");
10609 GLuint client_id
= texture_ref
->client_id();
10611 LOCAL_SET_GL_ERROR(
10612 GL_INVALID_OPERATION
,
10613 "glConsumeTextureCHROMIUM", "unknown texture for target");
10616 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10618 LOCAL_SET_GL_ERROR(
10619 GL_INVALID_OPERATION
,
10620 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10623 if (texture
->target() != target
) {
10624 LOCAL_SET_GL_ERROR(
10625 GL_INVALID_OPERATION
,
10626 "glConsumeTextureCHROMIUM", "invalid target");
10630 DeleteTexturesHelper(1, &client_id
);
10631 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10632 glBindTexture(target
, texture_ref
->service_id());
10634 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10635 unit
.bind_target
= target
;
10637 case GL_TEXTURE_2D
:
10638 unit
.bound_texture_2d
= texture_ref
;
10640 case GL_TEXTURE_CUBE_MAP
:
10641 unit
.bound_texture_cube_map
= texture_ref
;
10643 case GL_TEXTURE_EXTERNAL_OES
:
10644 unit
.bound_texture_external_oes
= texture_ref
;
10646 case GL_TEXTURE_RECTANGLE_ARB
:
10647 unit
.bound_texture_rectangle_arb
= texture_ref
;
10650 NOTREACHED(); // Validation should prevent us getting here.
10655 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10656 uint32_t immediate_data_size
,
10657 const void* cmd_data
) {
10658 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
10660 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
10662 GLenum target
= static_cast<GLenum
>(c
.target
);
10663 uint32_t data_size
;
10664 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
10665 return error::kOutOfBounds
;
10667 if (data_size
> immediate_data_size
) {
10668 return error::kOutOfBounds
;
10670 const GLbyte
* mailbox
=
10671 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
10672 if (!validators_
->texture_bind_target
.IsValid(target
)) {
10673 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10674 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
10675 return error::kNoError
;
10677 if (mailbox
== NULL
) {
10678 return error::kOutOfBounds
;
10680 uint32_t client_id
= c
.client_id
;
10681 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
10682 return error::kNoError
;
10685 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
10686 const GLbyte
* data
, GLuint client_id
) {
10687 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10688 "context", logger_
.GetLogPrefix(),
10689 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10690 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10691 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10692 "passed a mailbox that was not "
10693 "generated by GenMailboxCHROMIUM.";
10695 TextureRef
* texture_ref
= GetTexture(client_id
);
10697 LOCAL_SET_GL_ERROR(
10698 GL_INVALID_OPERATION
,
10699 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10702 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10704 LOCAL_SET_GL_ERROR(
10705 GL_INVALID_OPERATION
,
10706 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10709 if (texture
->target() != target
) {
10710 LOCAL_SET_GL_ERROR(
10711 GL_INVALID_OPERATION
,
10712 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10716 IdAllocatorInterface
* id_allocator
=
10717 group_
->GetIdAllocator(id_namespaces::kTextures
);
10718 id_allocator
->MarkAsUsed(client_id
);
10720 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10723 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10724 GLsizei length
, const GLchar
* marker
) {
10728 debug_marker_manager_
.SetMarker(
10729 length
? std::string(marker
, length
) : std::string(marker
));
10732 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10733 GLsizei length
, const GLchar
* marker
) {
10737 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
10738 debug_marker_manager_
.PushGroup(name
);
10739 gpu_tracer_
->Begin(name
, kTraceGroupMarker
);
10742 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10743 debug_marker_manager_
.PopGroup();
10744 gpu_tracer_
->End(kTraceGroupMarker
);
10747 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10748 GLenum target
, GLint image_id
) {
10749 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10751 if (target
== GL_TEXTURE_CUBE_MAP
) {
10752 LOCAL_SET_GL_ERROR(
10754 "glBindTexImage2DCHROMIUM", "invalid target");
10758 // Default target might be conceptually valid, but disallow it to avoid
10760 TextureRef
* texture_ref
=
10761 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10762 if (!texture_ref
) {
10763 LOCAL_SET_GL_ERROR(
10764 GL_INVALID_OPERATION
,
10765 "glBindTexImage2DCHROMIUM", "no texture bound");
10769 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10771 LOCAL_SET_GL_ERROR(
10772 GL_INVALID_OPERATION
,
10773 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10778 ScopedGLErrorSuppressor
suppressor(
10779 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10780 if (!gl_image
->BindTexImage(target
)) {
10781 LOCAL_SET_GL_ERROR(
10782 GL_INVALID_OPERATION
,
10783 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10788 gfx::Size size
= gl_image
->GetSize();
10789 texture_manager()->SetLevelInfo(
10790 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
10791 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
10792 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
10795 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10796 GLenum target
, GLint image_id
) {
10797 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10799 // Default target might be conceptually valid, but disallow it to avoid
10801 TextureRef
* texture_ref
=
10802 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10803 if (!texture_ref
) {
10804 LOCAL_SET_GL_ERROR(
10805 GL_INVALID_OPERATION
,
10806 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10810 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10812 LOCAL_SET_GL_ERROR(
10813 GL_INVALID_OPERATION
,
10814 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10818 // Do nothing when image is not currently bound.
10819 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
10823 ScopedGLErrorSuppressor
suppressor(
10824 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10825 gl_image
->ReleaseTexImage(target
);
10828 texture_manager()->SetLevelInfo(
10829 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
10830 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
10833 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10834 uint32 immediate_data_size
,
10835 const void* cmd_data
) {
10836 const gles2::cmds::TraceBeginCHROMIUM
& c
=
10837 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
10838 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10839 if (!bucket
|| bucket
->size() == 0) {
10840 return error::kInvalidArguments
;
10842 std::string command_name
;
10843 if (!bucket
->GetAsString(&command_name
)) {
10844 return error::kInvalidArguments
;
10846 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name
.c_str(), this);
10847 if (!gpu_tracer_
->Begin(command_name
, kTraceCHROMIUM
)) {
10848 LOCAL_SET_GL_ERROR(
10849 GL_INVALID_OPERATION
,
10850 "glTraceBeginCHROMIUM", "unable to create begin trace");
10851 return error::kNoError
;
10853 return error::kNoError
;
10856 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10857 if (gpu_tracer_
->CurrentName().empty()) {
10858 LOCAL_SET_GL_ERROR(
10859 GL_INVALID_OPERATION
,
10860 "glTraceEndCHROMIUM", "no trace begin found");
10863 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_
->CurrentName().c_str(), this);
10864 gpu_tracer_
->End(kTraceCHROMIUM
);
10867 void GLES2DecoderImpl::DoDrawBuffersEXT(
10868 GLsizei count
, const GLenum
* bufs
) {
10869 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
10870 LOCAL_SET_GL_ERROR(
10872 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10876 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
10878 for (GLsizei i
= 0; i
< count
; ++i
) {
10879 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
10880 bufs
[i
] != GL_NONE
) {
10881 LOCAL_SET_GL_ERROR(
10882 GL_INVALID_OPERATION
,
10883 "glDrawBuffersEXT",
10884 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10888 glDrawBuffersARB(count
, bufs
);
10889 framebuffer
->SetDrawBuffers(count
, bufs
);
10890 } else { // backbuffer
10892 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
10893 LOCAL_SET_GL_ERROR(
10894 GL_INVALID_OPERATION
,
10895 "glDrawBuffersEXT",
10896 "more than one buffer or bufs not GL_NONE or GL_BACK");
10899 GLenum mapped_buf
= bufs
[0];
10900 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10901 bufs
[0] == GL_BACK
) {
10902 mapped_buf
= GL_COLOR_ATTACHMENT0
;
10904 glDrawBuffersARB(count
, &mapped_buf
);
10905 group_
->set_draw_buffer(bufs
[0]);
10909 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
10910 group_
->LoseContexts(other
);
10911 reset_status_
= current
;
10912 current_decoder_error_
= error::kLostContext
;
10915 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
10916 const GLfloat
* matrix
) {
10917 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
10918 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
10919 if (!features().chromium_path_rendering
) {
10920 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10921 "glMatrixLoadfCHROMIUM",
10922 "function not available");
10926 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
10927 ? state_
.projection_matrix
10928 : state_
.modelview_matrix
;
10929 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
10930 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10931 // since the values of the _NV and _CHROMIUM tokens match.
10932 glMatrixLoadfEXT(matrix_mode
, matrix
);
10935 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
10936 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
10937 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
10939 if (!features().chromium_path_rendering
) {
10940 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10941 "glMatrixLoadIdentityCHROMIUM",
10942 "function not available");
10946 static GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
,
10947 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10948 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10950 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
10951 ? state_
.projection_matrix
10952 : state_
.modelview_matrix
;
10953 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
10954 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10955 // since the values of the _NV and _CHROMIUM tokens match.
10956 glMatrixLoadIdentityEXT(matrix_mode
);
10959 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10960 const char* function_name
,
10961 TextureRef
* texture_ref
,
10964 const void * data
) {
10965 // We only support async uploads to 2D textures for now.
10966 if (GL_TEXTURE_2D
!= target
) {
10967 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10970 // We only support uploads to level zero for now.
10972 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
10975 // A transfer buffer must be bound, even for asyncTexImage2D.
10976 if (data
== NULL
) {
10977 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
10980 // We only support one async transfer in progress.
10981 if (!texture_ref
||
10982 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10983 LOCAL_SET_GL_ERROR(
10984 GL_INVALID_OPERATION
,
10985 function_name
, "transfer already in progress");
10991 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10992 uint32 async_upload_token
,
10993 uint32 sync_data_shm_id
,
10994 uint32 sync_data_shm_offset
) {
10995 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
10996 if (!buffer
.get() ||
10997 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
10998 return base::Closure();
11000 AsyncMemoryParams
mem_params(buffer
,
11001 sync_data_shm_offset
,
11002 sizeof(AsyncUploadSync
));
11004 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
11005 new AsyncUploadTokenCompletionObserver(async_upload_token
));
11008 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
11009 base::Unretained(GetAsyncPixelTransferManager()),
11014 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11015 uint32 immediate_data_size
,
11016 const void* cmd_data
) {
11017 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
11018 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
11019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11020 GLenum target
= static_cast<GLenum
>(c
.target
);
11021 GLint level
= static_cast<GLint
>(c
.level
);
11022 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
11023 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11024 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11025 GLint border
= static_cast<GLint
>(c
.border
);
11026 GLenum format
= static_cast<GLenum
>(c
.format
);
11027 GLenum type
= static_cast<GLenum
>(c
.type
);
11028 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
11029 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
11030 uint32 pixels_size
;
11031 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11032 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11033 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11035 base::ScopedClosureRunner scoped_completion_callback
;
11036 if (async_upload_token
) {
11037 base::Closure completion_closure
=
11038 AsyncUploadTokenCompletionClosure(async_upload_token
,
11040 sync_data_shm_offset
);
11041 if (completion_closure
.is_null())
11042 return error::kInvalidArguments
;
11044 scoped_completion_callback
.Reset(completion_closure
);
11047 // TODO(epenner): Move this and copies of this memory validation
11048 // into ValidateTexImage2D step.
11049 if (!GLES2Util::ComputeImageDataSizes(
11050 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
11052 return error::kOutOfBounds
;
11054 const void* pixels
= NULL
;
11055 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
11056 pixels
= GetSharedMemoryAs
<const void*>(
11057 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
11059 return error::kOutOfBounds
;
11063 TextureManager::DoTextImage2DArguments args
= {
11064 target
, level
, internal_format
, width
, height
, border
, format
, type
,
11065 pixels
, pixels_size
};
11066 TextureRef
* texture_ref
;
11067 // All the normal glTexSubImage2D validation.
11068 if (!texture_manager()->ValidateTexImage2D(
11069 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
11070 return error::kNoError
;
11073 // Extra async validation.
11074 Texture
* texture
= texture_ref
->texture();
11075 if (!ValidateAsyncTransfer(
11076 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11077 return error::kNoError
;
11079 // Don't allow async redefinition of a textures.
11080 if (texture
->IsDefined()) {
11081 LOCAL_SET_GL_ERROR(
11082 GL_INVALID_OPERATION
,
11083 "glAsyncTexImage2DCHROMIUM", "already defined");
11084 return error::kNoError
;
11087 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
11088 LOCAL_SET_GL_ERROR(
11089 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
11090 return error::kNoError
;
11093 // Setup the parameters.
11094 AsyncTexImage2DParams tex_params
= {
11095 target
, level
, static_cast<GLenum
>(internal_format
),
11096 width
, height
, border
, format
, type
};
11097 AsyncMemoryParams
mem_params(
11098 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
11100 // Set up the async state if needed, and make the texture
11101 // immutable so the async state stays valid. The level info
11102 // is set up lazily when the transfer completes.
11103 AsyncPixelTransferDelegate
* delegate
=
11104 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
11106 texture
->SetImmutable(true);
11108 delegate
->AsyncTexImage2D(
11111 base::Bind(&TextureManager::SetLevelInfoFromParams
,
11112 // The callback is only invoked if the transfer delegate still
11113 // exists, which implies through manager->texture_ref->state
11114 // ownership that both of these pointers are valid.
11115 base::Unretained(texture_manager()),
11116 base::Unretained(texture_ref
),
11118 return error::kNoError
;
11121 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11122 uint32 immediate_data_size
,
11123 const void* cmd_data
) {
11124 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
11125 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
11126 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11127 GLenum target
= static_cast<GLenum
>(c
.target
);
11128 GLint level
= static_cast<GLint
>(c
.level
);
11129 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11130 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11131 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11132 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11133 GLenum format
= static_cast<GLenum
>(c
.format
);
11134 GLenum type
= static_cast<GLenum
>(c
.type
);
11135 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11136 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11137 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11139 base::ScopedClosureRunner scoped_completion_callback
;
11140 if (async_upload_token
) {
11141 base::Closure completion_closure
=
11142 AsyncUploadTokenCompletionClosure(async_upload_token
,
11144 sync_data_shm_offset
);
11145 if (completion_closure
.is_null())
11146 return error::kInvalidArguments
;
11148 scoped_completion_callback
.Reset(completion_closure
);
11151 // TODO(epenner): Move this and copies of this memory validation
11152 // into ValidateTexSubImage2D step.
11154 if (!GLES2Util::ComputeImageDataSizes(
11155 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
11157 return error::kOutOfBounds
;
11159 const void* pixels
= GetSharedMemoryAs
<const void*>(
11160 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
11162 // All the normal glTexSubImage2D validation.
11163 error::Error error
= error::kNoError
;
11164 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
11165 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
11169 // Extra async validation.
11170 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11172 Texture
* texture
= texture_ref
->texture();
11173 if (!ValidateAsyncTransfer(
11174 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11175 return error::kNoError
;
11177 // Guarantee async textures are always 'cleared' as follows:
11178 // - AsyncTexImage2D can not redefine an existing texture
11179 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11180 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11181 // - Textures become immutable after an async call.
11182 // This way we know in all cases that an async texture is always clear.
11183 if (!texture
->SafeToRenderFrom()) {
11184 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
11186 LOCAL_SET_GL_ERROR(
11188 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11189 return error::kNoError
;
11193 // Setup the parameters.
11194 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
11195 width
, height
, format
, type
};
11196 AsyncMemoryParams
mem_params(
11197 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
11198 AsyncPixelTransferDelegate
* delegate
=
11199 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
11201 // TODO(epenner): We may want to enforce exclusive use
11202 // of async APIs in which case this should become an error,
11203 // (the texture should have been async defined).
11204 AsyncTexImage2DParams define_params
= {target
, level
,
11206 texture
->GetLevelSize(target
, level
, &define_params
.width
,
11207 &define_params
.height
);
11208 texture
->GetLevelType(target
, level
, &define_params
.type
,
11209 &define_params
.internal_format
);
11210 // Set up the async state if needed, and make the texture
11211 // immutable so the async state stays valid.
11212 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
11213 texture_ref
, define_params
);
11214 texture
->SetImmutable(true);
11217 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
11218 return error::kNoError
;
11221 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11222 uint32 immediate_data_size
,
11223 const void* cmd_data
) {
11224 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
11225 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
11226 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11227 GLenum target
= static_cast<GLenum
>(c
.target
);
11229 if (GL_TEXTURE_2D
!= target
) {
11230 LOCAL_SET_GL_ERROR(
11231 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
11232 return error::kNoError
;
11234 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11236 if (!texture_ref
) {
11237 LOCAL_SET_GL_ERROR(
11238 GL_INVALID_OPERATION
,
11239 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11240 return error::kNoError
;
11242 AsyncPixelTransferDelegate
* delegate
=
11243 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
11245 LOCAL_SET_GL_ERROR(
11246 GL_INVALID_OPERATION
,
11247 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11248 return error::kNoError
;
11250 delegate
->WaitForTransferCompletion();
11251 ProcessFinishedAsyncTransfers();
11252 return error::kNoError
;
11255 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11256 uint32 immediate_data_size
,
11257 const void* data
) {
11258 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11260 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11261 ProcessFinishedAsyncTransfers();
11262 return error::kNoError
;
11265 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11266 TextureRef
* texture_ref
) {
11267 Texture
* texture
= texture_ref
->texture();
11268 DoDidUseTexImageIfNeeded(texture
, texture
->target());
11271 void GLES2DecoderImpl::OnOutOfMemoryError() {
11272 if (lose_context_when_out_of_memory_
) {
11273 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
11274 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB
);
11278 // Include the auto-generated part of this file. We split this because it means
11279 // we can easily edit the non-auto generated parts right here in this file
11280 // instead of having to edit some template or the code generator.
11281 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11283 } // namespace gles2