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/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_state_tracer.h"
46 #include "gpu/command_buffer/service/gpu_switches.h"
47 #include "gpu/command_buffer/service/gpu_tracer.h"
48 #include "gpu/command_buffer/service/image_manager.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/shader_translator_cache.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gl/gl_bindings.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include <IOSurface/IOSurfaceAPI.h>
69 // Note that this must be included after gl_bindings.h to avoid conflicts.
70 #include <OpenGL/CGLIOSurface.h>
74 #include "base/win/win_util.h"
82 static const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
83 static const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
84 static const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
85 static const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
87 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
88 khronos_uint64_t
CityHashForAngle(const char* name
, unsigned int len
) {
89 return static_cast<khronos_uint64_t
>(
90 CityHash64(name
, static_cast<size_t>(len
)));
94 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
97 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
100 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
101 GLenum precision_type
,
102 GLint
*range
, GLint
*precision
) {
103 switch (precision_type
) {
107 // These values are for a 32-bit twos-complement integer format.
113 case GL_MEDIUM_FLOAT
:
115 // These values are for an IEEE single-precision floating-point format.
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
126 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 glGetShaderPrecisionFormat(shader_type
, precision_type
,
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range
[0] = abs(range
[0]);
142 range
[1] = abs(range
[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
147 if (precision_type
== GL_HIGH_FLOAT
&&
148 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
158 class GLES2DecoderImpl
;
160 // Local versions of the SET_GL_ERROR macros
161 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
162 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
163 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
164 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
165 function_name, value, label)
166 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
167 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
168 function_name, pname)
169 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
170 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
172 #define LOCAL_PEEK_GL_ERROR(function_name) \
173 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
174 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
175 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
176 #define LOCAL_PERFORMANCE_WARNING(msg) \
177 PerformanceWarning(__FILE__, __LINE__, msg)
178 #define LOCAL_RENDER_WARNING(msg) \
179 RenderWarning(__FILE__, __LINE__, msg)
181 // Check that certain assumptions the code makes are true. There are places in
182 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
183 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
184 // a few others) are 32bits. If they are not 32bits the code will have to change
185 // to call those GL functions with service side memory and then copy the results
186 // to shared memory, converting the sizes.
187 COMPILE_ASSERT(sizeof(GLint
) == sizeof(uint32
), // NOLINT
188 GLint_not_same_size_as_uint32
);
189 COMPILE_ASSERT(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
190 GLint_not_same_size_as_uint32
);
191 COMPILE_ASSERT(sizeof(GLfloat
) == sizeof(float), // NOLINT
192 GLfloat_not_same_size_as_float
);
194 // TODO(kbr): the use of this anonymous namespace core dumps the
195 // linker on Mac OS X 10.6 when the symbol ordering file is used
198 // Returns the address of the first byte after a struct.
199 template <typename T
>
200 const void* AddressAfterStruct(const T
& pod
) {
201 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
204 // Returns the address of the frst byte after the struct or NULL if size >
205 // immediate_data_size.
206 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
207 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
209 uint32 immediate_data_size
) {
210 return (size
<= immediate_data_size
) ?
211 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
215 // Computes the data size for certain gl commands like glUniform.
216 bool ComputeDataSize(
219 unsigned int elements_per_unit
,
222 if (!SafeMultiplyUint32(count
, size
, &value
)) {
225 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
232 // A struct to hold info about each command.
234 uint8 arg_flags
; // How to handle the arguments for this command
235 uint8 cmd_flags
; // How to handle this command
236 uint16 arg_count
; // How many arguments are expected for this command.
239 // cmds::name::cmd_flags,
240 // A table of CommandInfo for all the commands.
241 const CommandInfo g_command_info
[] = {
242 #define GLES2_CMD_OP(name) { \
243 cmds::name::kArgFlags, \
244 cmds::name::cmd_flags, \
245 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
247 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 static bool CharacterIsValidForGLES(unsigned char c
) {
255 // Printing characters are valid except " $ ` @ \ ' DEL.
256 if (c
>= 32 && c
<= 126 &&
265 // Horizontal tab, line feed, vertical tab, form feed, carriage return
267 if (c
>= 9 && c
<= 13) {
274 static bool StringIsValidForGLES(const char* str
) {
275 for (; *str
; ++str
) {
276 if (!CharacterIsValidForGLES(*str
)) {
283 // This class prevents any GL errors that occur when it is in scope from
284 // being reported to the client.
285 class ScopedGLErrorSuppressor
{
287 explicit ScopedGLErrorSuppressor(
288 const char* function_name
, ErrorState
* error_state
);
289 ~ScopedGLErrorSuppressor();
291 const char* function_name_
;
292 ErrorState
* error_state_
;
293 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
296 // Temporarily changes a decoder's bound texture and restore it when this
297 // object goes out of scope. Also temporarily switches to using active texture
298 // unit zero in case the client has changed that to something invalid.
299 class ScopedTextureBinder
{
301 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
302 ~ScopedTextureBinder();
305 ContextState
* state_
;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
310 // Temporarily changes a decoder's bound render buffer and restore it when this
311 // object goes out of scope.
312 class ScopedRenderBufferBinder
{
314 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
315 ~ScopedRenderBufferBinder();
318 ContextState
* state_
;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
322 // Temporarily changes a decoder's bound frame buffer and restore it when this
323 // object goes out of scope.
324 class ScopedFrameBufferBinder
{
326 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
327 ~ScopedFrameBufferBinder();
330 GLES2DecoderImpl
* decoder_
;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
334 // Temporarily changes a decoder's bound frame buffer to a resolved version of
335 // the multisampled offscreen render buffer if that buffer is multisampled, and,
336 // if it is bound or enforce_internal_framebuffer is true. If internal is
337 // true, the resolved framebuffer is not visible to the parent.
338 class ScopedResolvedFrameBufferBinder
{
340 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
341 bool enforce_internal_framebuffer
,
343 ~ScopedResolvedFrameBufferBinder();
346 GLES2DecoderImpl
* decoder_
;
347 bool resolve_and_bind_
;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
351 class ScopedModifyPixels
{
353 explicit ScopedModifyPixels(TextureRef
* ref
);
354 ~ScopedModifyPixels();
360 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
362 ref_
->texture()->OnWillModifyPixels();
365 ScopedModifyPixels::~ScopedModifyPixels() {
367 ref_
->texture()->OnDidModifyPixels();
370 class ScopedRenderTo
{
372 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
376 const Framebuffer
* framebuffer_
;
379 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
380 : framebuffer_(framebuffer
) {
382 framebuffer_
->OnWillRenderTo();
385 ScopedRenderTo::~ScopedRenderTo() {
387 framebuffer_
->OnDidRenderTo();
390 // Encapsulates an OpenGL texture.
393 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
396 // Create a new render texture.
399 // Set the initial size and format of a render texture or resize it.
400 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
402 // Copy the contents of the currently bound frame buffer.
403 void Copy(const gfx::Size
& size
, GLenum format
);
405 // Destroy the render texture. This must be explicitly called before
406 // destroying this object.
409 // Invalidate the texture. This can be used when a context is lost and it is
410 // not possible to make it current in order to free the resource.
417 gfx::Size
size() const {
422 MemoryTypeTracker memory_tracker_
;
423 ContextState
* state_
;
424 size_t bytes_allocated_
;
427 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
430 // Encapsulates an OpenGL render buffer of any format.
431 class BackRenderbuffer
{
433 explicit BackRenderbuffer(
434 RenderbufferManager
* renderbuffer_manager
,
435 MemoryTracker
* memory_tracker
,
436 ContextState
* state
);
439 // Create a new render buffer.
442 // Set the initial size and format of a render buffer or resize it.
443 bool AllocateStorage(const FeatureInfo
* feature_info
,
444 const gfx::Size
& size
,
448 // Destroy the render buffer. This must be explicitly called before destroying
452 // Invalidate the render buffer. This can be used when a context is lost and
453 // it is not possible to make it current in order to free the resource.
461 RenderbufferManager
* renderbuffer_manager_
;
462 MemoryTypeTracker memory_tracker_
;
463 ContextState
* state_
;
464 size_t bytes_allocated_
;
466 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
469 // Encapsulates an OpenGL frame buffer.
470 class BackFramebuffer
{
472 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
475 // Create a new frame buffer.
478 // Attach a color render buffer to a frame buffer.
479 void AttachRenderTexture(BackTexture
* texture
);
481 // Attach a render buffer to a frame buffer. Note that this unbinds any
482 // currently bound frame buffer.
483 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
485 // Destroy the frame buffer. This must be explicitly called before destroying
489 // Invalidate the frame buffer. This can be used when a context is lost and it
490 // is not possible to make it current in order to free the resource.
493 // See glCheckFramebufferStatusEXT.
494 GLenum
CheckStatus();
501 GLES2DecoderImpl
* decoder_
;
503 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
506 struct FenceCallback
{
507 explicit FenceCallback()
508 : fence(gfx::GLFence::Create()) {
511 std::vector
<base::Closure
> callbacks
;
512 scoped_ptr
<gfx::GLFence
> fence
;
515 class AsyncUploadTokenCompletionObserver
516 : public AsyncPixelTransferCompletionObserver
{
518 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
519 : async_upload_token_(async_upload_token
) {
522 virtual void DidComplete(const AsyncMemoryParams
& mem_params
) OVERRIDE
{
523 DCHECK(mem_params
.buffer());
524 void* data
= mem_params
.GetDataAddress();
525 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
526 sync
->SetAsyncUploadToken(async_upload_token_
);
530 virtual ~AsyncUploadTokenCompletionObserver() {
533 uint32 async_upload_token_
;
535 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
538 // } // anonymous namespace.
540 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
541 uint32
* service_texture_id
) {
545 GLES2Decoder::GLES2Decoder()
546 : initialized_(false),
548 log_commands_(false) {
551 GLES2Decoder::~GLES2Decoder() {
554 void GLES2Decoder::BeginDecoding() {}
556 void GLES2Decoder::EndDecoding() {}
558 // This class implements GLES2Decoder so we don't have to expose all the GLES2
559 // cmd stuff to outside this class.
560 class GLES2DecoderImpl
: public GLES2Decoder
,
561 public FramebufferManager::TextureDetachObserver
,
562 public ErrorStateClient
{
564 explicit GLES2DecoderImpl(ContextGroup
* group
);
565 virtual ~GLES2DecoderImpl();
567 // Overridden from AsyncAPIInterface.
568 virtual Error
DoCommand(unsigned int command
,
569 unsigned int arg_count
,
570 const void* args
) OVERRIDE
;
572 // Overridden from AsyncAPIInterface.
573 virtual const char* GetCommandName(unsigned int command_id
) const OVERRIDE
;
575 // Overridden from GLES2Decoder.
576 virtual bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
577 const scoped_refptr
<gfx::GLContext
>& context
,
579 const gfx::Size
& size
,
580 const DisallowedFeatures
& disallowed_features
,
581 const std::vector
<int32
>& attribs
) OVERRIDE
;
582 virtual void Destroy(bool have_context
) OVERRIDE
;
583 virtual void SetSurface(
584 const scoped_refptr
<gfx::GLSurface
>& surface
) OVERRIDE
;
585 virtual void ProduceFrontBuffer(const Mailbox
& mailbox
) OVERRIDE
;
586 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) OVERRIDE
;
587 void UpdateParentTextureInfo();
588 virtual bool MakeCurrent() OVERRIDE
;
589 virtual GLES2Util
* GetGLES2Util() OVERRIDE
{ return &util_
; }
590 virtual gfx::GLContext
* GetGLContext() OVERRIDE
{ return context_
.get(); }
591 virtual ContextGroup
* GetContextGroup() OVERRIDE
{ return group_
.get(); }
592 virtual Capabilities
GetCapabilities() OVERRIDE
;
593 virtual void RestoreState(const ContextState
* prev_state
) const OVERRIDE
;
595 virtual void RestoreActiveTexture() const OVERRIDE
{
596 state_
.RestoreActiveTexture();
598 virtual void RestoreAllTextureUnitBindings(
599 const ContextState
* prev_state
) const OVERRIDE
{
600 state_
.RestoreAllTextureUnitBindings(prev_state
);
602 virtual void RestoreActiveTextureUnitBinding(
603 unsigned int target
) const OVERRIDE
{
604 state_
.RestoreActiveTextureUnitBinding(target
);
606 virtual void RestoreBufferBindings() const OVERRIDE
{
607 state_
.RestoreBufferBindings();
609 virtual void RestoreGlobalState() const OVERRIDE
{
610 state_
.RestoreGlobalState(NULL
);
612 virtual void RestoreProgramBindings() const OVERRIDE
{
613 state_
.RestoreProgramBindings();
615 virtual void RestoreTextureUnitBindings(unsigned unit
) const OVERRIDE
{
616 state_
.RestoreTextureUnitBindings(unit
, NULL
);
618 virtual void RestoreFramebufferBindings() const OVERRIDE
;
619 virtual void RestoreTextureState(unsigned service_id
) const OVERRIDE
;
621 virtual void ClearAllAttributes() const OVERRIDE
;
622 virtual void RestoreAllAttributes() const OVERRIDE
;
624 virtual QueryManager
* GetQueryManager() OVERRIDE
{
625 return query_manager_
.get();
627 virtual VertexArrayManager
* GetVertexArrayManager() OVERRIDE
{
628 return vertex_array_manager_
.get();
630 virtual bool ProcessPendingQueries() OVERRIDE
;
631 virtual bool HasMoreIdleWork() OVERRIDE
;
632 virtual void PerformIdleWork() OVERRIDE
;
634 virtual void WaitForReadPixels(base::Closure callback
) OVERRIDE
;
636 virtual void SetResizeCallback(
637 const base::Callback
<void(gfx::Size
, float)>& callback
) OVERRIDE
;
639 virtual Logger
* GetLogger() OVERRIDE
;
641 virtual void BeginDecoding() OVERRIDE
;
642 virtual void EndDecoding() OVERRIDE
;
644 virtual ErrorState
* GetErrorState() OVERRIDE
;
645 virtual const ContextState
* GetContextState() OVERRIDE
{ return &state_
; }
647 virtual void SetShaderCacheCallback(
648 const ShaderCacheCallback
& callback
) OVERRIDE
;
649 virtual void SetWaitSyncPointCallback(
650 const WaitSyncPointCallback
& callback
) OVERRIDE
;
652 virtual AsyncPixelTransferManager
*
653 GetAsyncPixelTransferManager() OVERRIDE
;
654 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE
;
655 virtual void SetAsyncPixelTransferManagerForTest(
656 AsyncPixelTransferManager
* manager
) OVERRIDE
;
657 virtual void SetIgnoreCachedStateForTest(bool ignore
) OVERRIDE
;
658 void ProcessFinishedAsyncTransfers();
660 virtual bool GetServiceTextureId(uint32 client_texture_id
,
661 uint32
* service_texture_id
) OVERRIDE
;
663 virtual uint32
GetTextureUploadCount() OVERRIDE
;
664 virtual base::TimeDelta
GetTotalTextureUploadTime() OVERRIDE
;
665 virtual base::TimeDelta
GetTotalProcessingCommandsTime() OVERRIDE
;
666 virtual void AddProcessingCommandsTime(base::TimeDelta
) OVERRIDE
;
668 // Restores the current state to the user's settings.
669 void RestoreCurrentFramebufferBindings();
671 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
672 void ApplyDirtyState();
674 // These check the state of the currently bound framebuffer or the
675 // backbuffer if no framebuffer is bound.
676 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
677 // check with all attached and enabled color attachments.
678 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
679 bool BoundFramebufferHasDepthAttachment();
680 bool BoundFramebufferHasStencilAttachment();
682 virtual error::ContextLostReason
GetContextLostReason() OVERRIDE
;
684 // Overridden from FramebufferManager::TextureDetachObserver:
685 virtual void OnTextureRefDetachedFromFramebuffer(
686 TextureRef
* texture
) OVERRIDE
;
688 // Overriden from ErrorStateClient.
689 virtual void OnOutOfMemoryError() OVERRIDE
;
691 // Helpers to facilitate calling into compatible extensions.
692 static void RenderbufferStorageMultisampleHelper(
693 const FeatureInfo
* feature_info
,
696 GLenum internal_format
,
700 void BlitFramebufferHelper(GLint srcX0
,
712 friend class ScopedFrameBufferBinder
;
713 friend class ScopedResolvedFrameBufferBinder
;
714 friend class BackFramebuffer
;
716 // Initialize or re-initialize the shader translator.
717 bool InitializeShaderTranslator();
719 void UpdateCapabilities();
721 // Helpers for the glGen and glDelete functions.
722 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
723 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
724 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
725 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
726 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
727 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
728 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
729 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
730 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
731 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
732 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
733 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
735 // Helper for async upload token completion notification callback.
736 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
737 uint32 sync_data_shm_id
,
738 uint32 sync_data_shm_offset
);
743 void OnFboChanged() const;
744 void OnUseFramebuffer() const;
746 // TODO(gman): Cache these pointers?
747 BufferManager
* buffer_manager() {
748 return group_
->buffer_manager();
751 RenderbufferManager
* renderbuffer_manager() {
752 return group_
->renderbuffer_manager();
755 FramebufferManager
* framebuffer_manager() {
756 return group_
->framebuffer_manager();
759 ProgramManager
* program_manager() {
760 return group_
->program_manager();
763 ShaderManager
* shader_manager() {
764 return group_
->shader_manager();
767 ShaderTranslatorCache
* shader_translator_cache() {
768 return group_
->shader_translator_cache();
771 const TextureManager
* texture_manager() const {
772 return group_
->texture_manager();
775 TextureManager
* texture_manager() {
776 return group_
->texture_manager();
779 MailboxManager
* mailbox_manager() {
780 return group_
->mailbox_manager();
783 ImageManager
* image_manager() {
784 return group_
->image_manager();
787 VertexArrayManager
* vertex_array_manager() {
788 return vertex_array_manager_
.get();
791 MemoryTracker
* memory_tracker() {
792 return group_
->memory_tracker();
795 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
796 MemoryTracker
* tracker
= memory_tracker();
798 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
803 bool IsOffscreenBufferMultisampled() const {
804 return offscreen_target_samples_
> 1;
807 // Creates a Texture for the given texture.
808 TextureRef
* CreateTexture(
809 GLuint client_id
, GLuint service_id
) {
810 return texture_manager()->CreateTexture(client_id
, service_id
);
813 // Gets the texture info for the given texture. Returns NULL if none exists.
814 TextureRef
* GetTexture(GLuint client_id
) const {
815 return texture_manager()->GetTexture(client_id
);
818 // Deletes the texture info for the given texture.
819 void RemoveTexture(GLuint client_id
) {
820 texture_manager()->RemoveTexture(client_id
);
823 // Get the size (in pixels) of the currently bound frame buffer (either FBO
824 // or regular back buffer).
825 gfx::Size
GetBoundReadFrameBufferSize();
827 // Get the format of the currently bound frame buffer (either FBO or regular
829 GLenum
GetBoundReadFrameBufferTextureType();
830 GLenum
GetBoundReadFrameBufferInternalFormat();
831 GLenum
GetBoundDrawFrameBufferInternalFormat();
833 // Wrapper for CompressedTexImage2D commands.
834 error::Error
DoCompressedTexImage2D(
837 GLenum internal_format
,
844 // Wrapper for CompressedTexSubImage2D.
845 void DoCompressedTexSubImage2D(
856 // Wrapper for CopyTexImage2D.
857 void DoCopyTexImage2D(
860 GLenum internal_format
,
867 // Wrapper for SwapBuffers.
868 void DoSwapBuffers();
870 // Wrapper for CopyTexSubImage2D.
871 void DoCopyTexSubImage2D(
881 // Validation for TexSubImage2D.
882 bool ValidateTexSubImage2D(
884 const char* function_name
,
895 // Wrapper for TexSubImage2D.
896 error::Error
DoTexSubImage2D(
907 // Extra validation for async tex(Sub)Image2D.
908 bool ValidateAsyncTransfer(
909 const char* function_name
,
910 TextureRef
* texture_ref
,
915 // Wrapper for TexImageIOSurface2DCHROMIUM.
916 void DoTexImageIOSurface2DCHROMIUM(
920 GLuint io_surface_id
,
923 void DoCopyTextureCHROMIUM(
928 GLenum internal_format
,
931 // Wrapper for TexStorage2DEXT.
932 void DoTexStorage2DEXT(
935 GLenum internal_format
,
939 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
940 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
942 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
943 GLenum target
, const GLbyte
* data
);
945 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
946 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
949 void DoBindTexImage2DCHROMIUM(
952 void DoReleaseTexImage2DCHROMIUM(
956 void DoTraceEndCHROMIUM(void);
958 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
960 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
962 // Creates a Program for the given program.
963 Program
* CreateProgram(
964 GLuint client_id
, GLuint service_id
) {
965 return program_manager()->CreateProgram(client_id
, service_id
);
968 // Gets the program info for the given program. Returns NULL if none exists.
969 Program
* GetProgram(GLuint client_id
) {
970 return program_manager()->GetProgram(client_id
);
974 void LogClientServiceMapping(
975 const char* /* function_name */,
976 GLuint
/* client_id */,
977 GLuint
/* service_id */) {
980 void LogClientServiceForInfo(
981 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
984 void LogClientServiceMapping(
985 const char* function_name
, GLuint client_id
, GLuint service_id
) {
986 if (service_logging_
) {
987 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
988 << ": client_id = " << client_id
989 << ", service_id = " << service_id
;
993 void LogClientServiceForInfo(
994 T
* info
, GLuint client_id
, const char* function_name
) {
996 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1001 // Gets the program info for the given program. If it's not a program
1002 // generates a GL error. Returns NULL if not program.
1003 Program
* GetProgramInfoNotShader(
1004 GLuint client_id
, const char* function_name
) {
1005 Program
* program
= GetProgram(client_id
);
1007 if (GetShader(client_id
)) {
1009 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1011 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1014 LogClientServiceForInfo(program
, client_id
, function_name
);
1019 // Creates a Shader for the given shader.
1020 Shader
* CreateShader(
1023 GLenum shader_type
) {
1024 return shader_manager()->CreateShader(
1025 client_id
, service_id
, shader_type
);
1028 // Gets the shader info for the given shader. Returns NULL if none exists.
1029 Shader
* GetShader(GLuint client_id
) {
1030 return shader_manager()->GetShader(client_id
);
1033 // Gets the shader info for the given shader. If it's not a shader generates a
1034 // GL error. Returns NULL if not shader.
1035 Shader
* GetShaderInfoNotProgram(
1036 GLuint client_id
, const char* function_name
) {
1037 Shader
* shader
= GetShader(client_id
);
1039 if (GetProgram(client_id
)) {
1041 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1044 GL_INVALID_VALUE
, function_name
, "unknown shader");
1047 LogClientServiceForInfo(shader
, client_id
, function_name
);
1051 // Creates a buffer info for the given buffer.
1052 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1053 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1056 // Gets the buffer info for the given buffer.
1057 Buffer
* GetBuffer(GLuint client_id
) {
1058 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1062 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1063 // on glDeleteBuffers so we can make sure the user does not try to render
1064 // with deleted buffers.
1065 void RemoveBuffer(GLuint client_id
);
1067 // Creates a framebuffer info for the given framebuffer.
1068 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1069 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1072 // Gets the framebuffer info for the given framebuffer.
1073 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1074 return framebuffer_manager()->GetFramebuffer(client_id
);
1077 // Removes the framebuffer info for the given framebuffer.
1078 void RemoveFramebuffer(GLuint client_id
) {
1079 framebuffer_manager()->RemoveFramebuffer(client_id
);
1082 // Creates a renderbuffer info for the given renderbuffer.
1083 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1084 return renderbuffer_manager()->CreateRenderbuffer(
1085 client_id
, service_id
);
1088 // Gets the renderbuffer info for the given renderbuffer.
1089 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1090 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1093 // Removes the renderbuffer info for the given renderbuffer.
1094 void RemoveRenderbuffer(GLuint client_id
) {
1095 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1098 // Gets the vertex attrib manager for the given vertex array.
1099 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1100 VertexAttribManager
* info
=
1101 vertex_array_manager()->GetVertexAttribManager(client_id
);
1105 // Removes the vertex attrib manager for the given vertex array.
1106 void RemoveVertexAttribManager(GLuint client_id
) {
1107 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1110 // Creates a vertex attrib manager for the given vertex array.
1111 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1114 bool client_visible
) {
1115 return vertex_array_manager()->CreateVertexAttribManager(
1116 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1119 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1120 void DoBindUniformLocationCHROMIUM(
1121 GLuint client_id
, GLint location
, const char* name
);
1123 error::Error
GetAttribLocationHelper(
1124 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1125 const std::string
& name_str
);
1127 error::Error
GetUniformLocationHelper(
1128 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1129 const std::string
& name_str
);
1131 // Helper for glShaderSource.
1132 error::Error
ShaderSourceHelper(
1133 GLuint client_id
, const char* data
, uint32 data_size
);
1135 // Clear any textures used by the current program.
1136 bool ClearUnclearedTextures();
1138 // Clears any uncleared attachments attached to the given frame buffer.
1139 // Returns false if there was a generated GL error.
1140 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1142 // overridden from GLES2Decoder
1143 virtual bool ClearLevel(unsigned service_id
,
1144 unsigned bind_target
,
1147 unsigned internal_format
,
1152 bool is_texture_immutable
) OVERRIDE
;
1154 // Restore all GL state that affects clearing.
1155 void RestoreClearState();
1157 // Remembers the state of some capabilities.
1158 // Returns: true if glEnable/glDisable should actually be called.
1159 bool SetCapabilityState(GLenum cap
, bool enabled
);
1161 // Check that the currently bound framebuffers are valid.
1162 // Generates GL error if not.
1163 bool CheckBoundFramebuffersValid(const char* func_name
);
1165 // Check if a framebuffer meets our requirements.
1166 bool CheckFramebufferValid(
1167 Framebuffer
* framebuffer
,
1169 const char* func_name
);
1171 // Checks if the current program exists and is valid. If not generates the
1172 // appropriate GL error. Returns true if the current program is in a usable
1174 bool CheckCurrentProgram(const char* function_name
);
1176 // Checks if the current program exists and is valid and that location is not
1177 // -1. If the current program is not valid generates the appropriate GL
1178 // error. Returns true if the current program is in a usable state and
1179 // location is not -1.
1180 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1182 // Gets the type of a uniform for a location in the current program. Sets GL
1183 // errors if the current program is not valid. Returns true if the current
1184 // program is valid and the location exists. Adjusts count so it
1185 // does not overflow the uniform.
1186 bool PrepForSetUniformByLocation(GLint fake_location
,
1187 const char* function_name
,
1188 Program::UniformApiType api_type
,
1189 GLint
* real_location
,
1193 // Gets the service id for any simulated backbuffer fbo.
1194 GLuint
GetBackbufferServiceId() const;
1196 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1197 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1199 // Helper for glGetVertexAttrib
1200 void GetVertexAttribHelper(
1201 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1203 // Wrapper for glCreateProgram
1204 bool CreateProgramHelper(GLuint client_id
);
1206 // Wrapper for glCreateShader
1207 bool CreateShaderHelper(GLenum type
, GLuint client_id
);
1209 // Wrapper for glActiveTexture
1210 void DoActiveTexture(GLenum texture_unit
);
1212 // Wrapper for glAttachShader
1213 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1215 // Wrapper for glBindBuffer since we need to track the current targets.
1216 void DoBindBuffer(GLenum target
, GLuint buffer
);
1218 // Wrapper for glBindFramebuffer since we need to track the current targets.
1219 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1221 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1222 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1224 // Wrapper for glBindTexture since we need to track the current targets.
1225 void DoBindTexture(GLenum target
, GLuint texture
);
1227 // Wrapper for glBindVertexArrayOES
1228 void DoBindVertexArrayOES(GLuint array
);
1229 void EmulateVertexArrayState();
1231 // Wrapper for glBlitFramebufferCHROMIUM.
1232 void DoBlitFramebufferCHROMIUM(
1233 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1234 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1235 GLbitfield mask
, GLenum filter
);
1237 // Wrapper for glBufferSubData.
1238 void DoBufferSubData(
1239 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1241 // Wrapper for glCheckFramebufferStatus
1242 GLenum
DoCheckFramebufferStatus(GLenum target
);
1244 // Wrapper for glClear
1245 error::Error
DoClear(GLbitfield mask
);
1247 // Wrappers for various state.
1248 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1249 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1251 // Wrapper for glCompileShader.
1252 void DoCompileShader(GLuint shader
);
1254 // Helper for DeleteSharedIdsCHROMIUM commands.
1255 void DoDeleteSharedIdsCHROMIUM(
1256 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1258 // Wrapper for glDetachShader
1259 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1261 // Wrapper for glDisable
1262 void DoDisable(GLenum cap
);
1264 // Wrapper for glDisableVertexAttribArray.
1265 void DoDisableVertexAttribArray(GLuint index
);
1267 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1269 void DoDiscardFramebufferEXT(GLenum target
,
1270 GLsizei numAttachments
,
1271 const GLenum
* attachments
);
1273 // Wrapper for glEnable
1274 void DoEnable(GLenum cap
);
1276 // Wrapper for glEnableVertexAttribArray.
1277 void DoEnableVertexAttribArray(GLuint index
);
1279 // Wrapper for glFinish.
1282 // Wrapper for glFlush.
1285 // Wrapper for glFramebufferRenderbufffer.
1286 void DoFramebufferRenderbuffer(
1287 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1288 GLuint renderbuffer
);
1290 // Wrapper for glFramebufferTexture2D.
1291 void DoFramebufferTexture2D(
1292 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1295 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1296 void DoFramebufferTexture2DMultisample(
1297 GLenum target
, GLenum attachment
, GLenum textarget
,
1298 GLuint texture
, GLint level
, GLsizei samples
);
1300 // Common implementation for both DoFramebufferTexture2D wrappers.
1301 void DoFramebufferTexture2DCommon(const char* name
,
1302 GLenum target
, GLenum attachment
, GLenum textarget
,
1303 GLuint texture
, GLint level
, GLsizei samples
);
1305 // Wrapper for glGenerateMipmap
1306 void DoGenerateMipmap(GLenum target
);
1308 // Helper for GenSharedIdsCHROMIUM commands.
1309 void DoGenSharedIdsCHROMIUM(
1310 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
);
1312 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1313 // to account for different pname values defined in different extension
1315 GLenum
AdjustGetPname(GLenum pname
);
1317 // Wrapper for DoGetBooleanv.
1318 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1320 // Wrapper for DoGetFloatv.
1321 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1323 // Wrapper for glGetFramebufferAttachmentParameteriv.
1324 void DoGetFramebufferAttachmentParameteriv(
1325 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1327 // Wrapper for glGetIntegerv.
1328 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1330 // Gets the max value in a range in a buffer.
1331 GLuint
DoGetMaxValueInBufferCHROMIUM(
1332 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1334 // Wrapper for glGetBufferParameteriv.
1335 void DoGetBufferParameteriv(
1336 GLenum target
, GLenum pname
, GLint
* params
);
1338 // Wrapper for glGetProgramiv.
1339 void DoGetProgramiv(
1340 GLuint program_id
, GLenum pname
, GLint
* params
);
1342 // Wrapper for glRenderbufferParameteriv.
1343 void DoGetRenderbufferParameteriv(
1344 GLenum target
, GLenum pname
, GLint
* params
);
1346 // Wrapper for glGetShaderiv
1347 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1349 // Wrappers for glGetTexParameter.
1350 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1351 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1352 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1354 // Wrappers for glGetVertexAttrib.
1355 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1356 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1358 // Wrappers for glIsXXX functions.
1359 bool DoIsEnabled(GLenum cap
);
1360 bool DoIsBuffer(GLuint client_id
);
1361 bool DoIsFramebuffer(GLuint client_id
);
1362 bool DoIsProgram(GLuint client_id
);
1363 bool DoIsRenderbuffer(GLuint client_id
);
1364 bool DoIsShader(GLuint client_id
);
1365 bool DoIsTexture(GLuint client_id
);
1366 bool DoIsVertexArrayOES(GLuint client_id
);
1368 // Wrapper for glLinkProgram
1369 void DoLinkProgram(GLuint program
);
1371 // Helper for RegisterSharedIdsCHROMIUM.
1372 void DoRegisterSharedIdsCHROMIUM(
1373 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1375 // Wrapper for glRenderbufferStorage.
1376 void DoRenderbufferStorage(
1377 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1379 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1380 void DoRenderbufferStorageMultisampleCHROMIUM(
1381 GLenum target
, GLsizei samples
, GLenum internalformat
,
1382 GLsizei width
, GLsizei height
);
1384 // Handler for glRenderbufferStorageMultisampleEXT
1385 // (multisampled_render_to_texture).
1386 void DoRenderbufferStorageMultisampleEXT(
1387 GLenum target
, GLsizei samples
, GLenum internalformat
,
1388 GLsizei width
, GLsizei height
);
1390 // Common validation for multisample extensions.
1391 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1392 GLenum internalformat
,
1396 // Verifies that the currently bound multisample renderbuffer is valid
1397 // Very slow! Only done on platforms with driver bugs that return invalid
1398 // buffers under memory pressure
1399 bool VerifyMultisampleRenderbufferIntegrity(
1400 GLuint renderbuffer
, GLenum format
);
1402 // Wrapper for glReleaseShaderCompiler.
1403 void DoReleaseShaderCompiler() { }
1405 // Wrappers for glTexParameter functions.
1406 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1407 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1408 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1409 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1411 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1412 // spec only these 2 functions can be used to set sampler uniforms.
1413 void DoUniform1i(GLint fake_location
, GLint v0
);
1414 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1415 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1416 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1417 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1419 // Wrappers for glUniformfv because some drivers don't correctly accept
1421 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1422 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1423 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1424 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1426 void DoUniformMatrix2fv(
1427 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1428 const GLfloat
* value
);
1429 void DoUniformMatrix3fv(
1430 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1431 const GLfloat
* value
);
1432 void DoUniformMatrix4fv(
1433 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1434 const GLfloat
* value
);
1436 bool SetVertexAttribValue(
1437 const char* function_name
, GLuint index
, const GLfloat
* value
);
1439 // Wrappers for glVertexAttrib??
1440 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1441 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1442 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1443 void DoVertexAttrib4f(
1444 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1445 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1446 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1447 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1448 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1450 // Wrapper for glViewport
1451 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1453 // Wrapper for glUseProgram
1454 void DoUseProgram(GLuint program
);
1456 // Wrapper for glValidateProgram.
1457 void DoValidateProgram(GLuint program_client_id
);
1459 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1460 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1461 void DoPopGroupMarkerEXT(void);
1463 // Gets the number of values that will be returned by glGetXXX. Returns
1464 // false if pname is unknown.
1465 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1467 // Checks if the current program and vertex attributes are valid for drawing.
1469 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
);
1471 // Returns true if successful, simulated will be true if attrib0 was
1473 bool SimulateAttrib0(
1474 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1475 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1477 // If an image is bound to texture, this will call Will/DidUseTexImage
1479 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1480 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1482 // Returns false if textures were replaced.
1483 bool PrepareTexturesForRender();
1484 void RestoreStateForTextures();
1486 // Returns true if GL_FIXED attribs were simulated.
1487 bool SimulateFixedAttribs(
1488 const char* function_name
,
1489 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1490 void RestoreStateForSimulatedFixedAttribs();
1492 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1493 // cases (primcount is 0 for non-instanced).
1494 error::Error
DoDrawArrays(
1495 const char* function_name
,
1496 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1498 error::Error
DoDrawElements(
1499 const char* function_name
,
1500 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1501 int32 offset
, GLsizei primcount
);
1503 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1504 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1505 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1508 return GL_TEXTURE_2D
;
1509 case GL_SAMPLER_CUBE
:
1510 return GL_TEXTURE_CUBE_MAP
;
1511 case GL_SAMPLER_EXTERNAL_OES
:
1512 return GL_TEXTURE_EXTERNAL_OES
;
1513 case GL_SAMPLER_2D_RECT_ARB
:
1514 return GL_TEXTURE_RECTANGLE_ARB
;
1521 // Gets the framebuffer info for a particular target.
1522 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1523 Framebuffer
* framebuffer
= NULL
;
1525 case GL_FRAMEBUFFER
:
1526 case GL_DRAW_FRAMEBUFFER_EXT
:
1527 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1529 case GL_READ_FRAMEBUFFER_EXT
:
1530 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1539 Renderbuffer
* GetRenderbufferInfoForTarget(
1541 Renderbuffer
* renderbuffer
= NULL
;
1543 case GL_RENDERBUFFER
:
1544 renderbuffer
= state_
.bound_renderbuffer
.get();
1550 return renderbuffer
;
1553 // Validates the program and location for a glGetUniform call and returns
1554 // a SizeResult setup to receive the result. Returns true if glGetUniform
1555 // should be called.
1556 bool GetUniformSetup(
1557 GLuint program
, GLint fake_location
,
1558 uint32 shm_id
, uint32 shm_offset
,
1559 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1560 void** result
, GLenum
* result_type
);
1562 virtual bool WasContextLost() OVERRIDE
;
1563 virtual bool WasContextLostByRobustnessExtension() OVERRIDE
;
1564 virtual void LoseContext(uint32 reset_status
) OVERRIDE
;
1566 #if defined(OS_MACOSX)
1567 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1570 bool ValidateCompressedTexDimensions(
1571 const char* function_name
,
1572 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1573 bool ValidateCompressedTexFuncData(
1574 const char* function_name
,
1575 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1576 bool ValidateCompressedTexSubDimensions(
1577 const char* function_name
,
1578 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1579 GLsizei width
, GLsizei height
, GLenum format
,
1582 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1583 void PerformanceWarning(
1584 const char* filename
, int line
, const std::string
& msg
);
1586 const FeatureInfo::FeatureFlags
& features() const {
1587 return feature_info_
->feature_flags();
1590 const FeatureInfo::Workarounds
& workarounds() const {
1591 return feature_info_
->workarounds();
1594 bool ShouldDeferDraws() {
1595 return !offscreen_target_frame_buffer_
.get() &&
1596 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1597 surface_
->DeferDraws();
1600 bool ShouldDeferReads() {
1601 return !offscreen_target_frame_buffer_
.get() &&
1602 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1603 surface_
->DeferDraws();
1606 error::Error
WillAccessBoundFramebufferForDraw() {
1607 if (ShouldDeferDraws())
1608 return error::kDeferCommandUntilLater
;
1609 if (!offscreen_target_frame_buffer_
.get() &&
1610 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1611 !surface_
->SetBackbufferAllocation(true))
1612 return error::kLostContext
;
1613 return error::kNoError
;
1616 error::Error
WillAccessBoundFramebufferForRead() {
1617 if (ShouldDeferReads())
1618 return error::kDeferCommandUntilLater
;
1619 if (!offscreen_target_frame_buffer_
.get() &&
1620 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1621 !surface_
->SetBackbufferAllocation(true))
1622 return error::kLostContext
;
1623 return error::kNoError
;
1626 void ProcessPendingReadPixels();
1627 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1629 // Generate a member function prototype for each command in an automated and
1631 #define GLES2_CMD_OP(name) \
1632 Error Handle ## name( \
1633 uint32 immediate_data_size, \
1634 const cmds::name& args); \
1636 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1640 // The GL context this decoder renders to on behalf of the client.
1641 scoped_refptr
<gfx::GLSurface
> surface_
;
1642 scoped_refptr
<gfx::GLContext
> context_
;
1644 // The ContextGroup for this decoder uses to track resources.
1645 scoped_refptr
<ContextGroup
> group_
;
1647 DebugMarkerManager debug_marker_manager_
;
1650 // All the state for this context.
1651 ContextState state_
;
1653 // Current width and height of the offscreen frame buffer.
1654 gfx::Size offscreen_size_
;
1656 // Util to help with GL.
1659 // unpack flip y as last set by glPixelStorei
1660 bool unpack_flip_y_
;
1662 // unpack (un)premultiply alpha as last set by glPixelStorei
1663 bool unpack_premultiply_alpha_
;
1664 bool unpack_unpremultiply_alpha_
;
1666 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1667 GLuint attrib_0_buffer_id_
;
1669 // The value currently in attrib_0.
1670 Vec4 attrib_0_value_
;
1672 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1673 bool attrib_0_buffer_matches_value_
;
1675 // The size of attrib 0.
1676 GLsizei attrib_0_size_
;
1678 // The buffer used to simulate GL_FIXED attribs.
1679 GLuint fixed_attrib_buffer_id_
;
1681 // The size of fiixed attrib buffer.
1682 GLsizei fixed_attrib_buffer_size_
;
1684 // The offscreen frame buffer that the client renders to. With EGL, the
1685 // depth and stencil buffers are separate. With regular GL there is a single
1686 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1687 // offscreen_target_stencil_render_buffer_ is unused.
1688 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1689 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1690 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1691 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1692 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1693 GLenum offscreen_target_color_format_
;
1694 GLenum offscreen_target_depth_format_
;
1695 GLenum offscreen_target_stencil_format_
;
1696 GLsizei offscreen_target_samples_
;
1697 GLboolean offscreen_target_buffer_preserved_
;
1699 // The copy that is saved when SwapBuffers is called.
1700 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1701 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1702 scoped_refptr
<TextureRef
>
1703 offscreen_saved_color_texture_info_
;
1705 // The copy that is used as the destination for multi-sample resolves.
1706 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1707 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1708 GLenum offscreen_saved_color_format_
;
1710 scoped_ptr
<QueryManager
> query_manager_
;
1712 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1714 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1716 WaitSyncPointCallback wait_sync_point_callback_
;
1718 ShaderCacheCallback shader_cache_callback_
;
1720 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1722 // The format of the back buffer_
1723 GLenum back_buffer_color_format_
;
1724 bool back_buffer_has_depth_
;
1725 bool back_buffer_has_stencil_
;
1727 // Backbuffer attachments that are currently undefined.
1728 uint32 backbuffer_needs_clear_bits_
;
1730 // The current decoder error communicates the decoder error through command
1731 // processing functions that do not return the error value. Should be set only
1732 // if not returning an error.
1733 error::Error current_decoder_error_
;
1735 bool use_shader_translator_
;
1736 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1737 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1739 DisallowedFeatures disallowed_features_
;
1741 // Cached from ContextGroup
1742 const Validators
* validators_
;
1743 scoped_refptr
<FeatureInfo
> feature_info_
;
1747 bool has_robustness_extension_
;
1748 GLenum reset_status_
;
1749 bool reset_by_robustness_extension_
;
1750 bool supports_post_sub_buffer_
;
1752 // These flags are used to override the state of the shared feature_info_
1753 // member. Because the same FeatureInfo instance may be shared among many
1754 // contexts, the assumptions on the availablity of extensions in WebGL
1755 // contexts may be broken. These flags override the shared state to preserve
1757 bool force_webgl_glsl_validation_
;
1758 bool derivatives_explicitly_enabled_
;
1759 bool frag_depth_explicitly_enabled_
;
1760 bool draw_buffers_explicitly_enabled_
;
1761 bool shader_texture_lod_explicitly_enabled_
;
1763 bool compile_shader_always_succeeds_
;
1765 // An optional behaviour to lose the context and group when OOM.
1766 bool lose_context_when_out_of_memory_
;
1769 bool service_logging_
;
1771 #if defined(OS_MACOSX)
1772 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1773 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1776 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1778 // Cached values of the currently assigned viewport dimensions.
1779 GLsizei viewport_max_width_
;
1780 GLsizei viewport_max_height_
;
1782 // Command buffer stats.
1783 base::TimeDelta total_processing_commands_time_
;
1785 // States related to each manager.
1786 DecoderTextureState texture_state_
;
1787 DecoderFramebufferState framebuffer_state_
;
1789 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1790 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1791 int gpu_trace_level_
;
1792 bool gpu_trace_commands_
;
1794 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1796 // Used to validate multisample renderbuffers if needed
1797 GLuint validation_texture_
;
1798 GLuint validation_fbo_multisample_
;
1799 GLuint validation_fbo_
;
1801 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1804 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1805 const char* function_name
, ErrorState
* error_state
)
1806 : function_name_(function_name
),
1807 error_state_(error_state
) {
1808 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1811 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1812 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1815 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1816 TextureUnit
& info
= state
->texture_units
[0];
1818 scoped_refptr
<TextureRef
> texture_ref
;
1821 texture_ref
= info
.bound_texture_2d
;
1823 case GL_TEXTURE_CUBE_MAP
:
1824 texture_ref
= info
.bound_texture_cube_map
;
1826 case GL_TEXTURE_EXTERNAL_OES
:
1827 texture_ref
= info
.bound_texture_external_oes
;
1829 case GL_TEXTURE_RECTANGLE_ARB
:
1830 texture_ref
= info
.bound_texture_rectangle_arb
;
1836 if (texture_ref
.get()) {
1837 last_id
= texture_ref
->service_id();
1842 glBindTexture(target
, last_id
);
1843 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1846 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1851 ScopedGLErrorSuppressor
suppressor(
1852 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1854 // TODO(apatrick): Check if there are any other states that need to be reset
1855 // before binding a new texture.
1856 glActiveTexture(GL_TEXTURE0
);
1857 glBindTexture(target
, id
);
1860 ScopedTextureBinder::~ScopedTextureBinder() {
1861 ScopedGLErrorSuppressor
suppressor(
1862 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1863 RestoreCurrentTextureBindings(state_
, target_
);
1866 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1869 ScopedGLErrorSuppressor
suppressor(
1870 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1871 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1874 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1875 ScopedGLErrorSuppressor
suppressor(
1876 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
1877 state_
->RestoreRenderbufferBindings();
1880 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
1882 : decoder_(decoder
) {
1883 ScopedGLErrorSuppressor
suppressor(
1884 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1885 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
1886 decoder
->OnFboChanged();
1889 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1890 ScopedGLErrorSuppressor
suppressor(
1891 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1892 decoder_
->RestoreCurrentFramebufferBindings();
1895 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1896 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
1897 : decoder_(decoder
) {
1898 resolve_and_bind_
= (
1899 decoder_
->offscreen_target_frame_buffer_
.get() &&
1900 decoder_
->IsOffscreenBufferMultisampled() &&
1901 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
1902 enforce_internal_framebuffer
));
1903 if (!resolve_and_bind_
)
1906 ScopedGLErrorSuppressor
suppressor(
1907 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1908 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
1909 decoder_
->offscreen_target_frame_buffer_
->id());
1912 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
1913 decoder_
->offscreen_resolved_frame_buffer_
.reset(
1914 new BackFramebuffer(decoder_
));
1915 decoder_
->offscreen_resolved_frame_buffer_
->Create();
1916 decoder_
->offscreen_resolved_color_texture_
.reset(
1917 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
1918 decoder_
->offscreen_resolved_color_texture_
->Create();
1920 DCHECK(decoder_
->offscreen_saved_color_format_
);
1921 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
1922 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
1924 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
1925 decoder_
->offscreen_resolved_color_texture_
.get());
1926 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
1927 GL_FRAMEBUFFER_COMPLETE
) {
1928 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
1929 << "because offscreen resolved FBO was incomplete.";
1933 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
1935 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
1937 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
1938 const int width
= decoder_
->offscreen_size_
.width();
1939 const int height
= decoder_
->offscreen_size_
.height();
1940 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
1941 decoder
->BlitFramebufferHelper(0,
1949 GL_COLOR_BUFFER_BIT
,
1951 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
1954 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1955 if (!resolve_and_bind_
)
1958 ScopedGLErrorSuppressor
suppressor(
1959 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1960 decoder_
->RestoreCurrentFramebufferBindings();
1961 if (decoder_
->state_
.enable_flags
.scissor_test
) {
1962 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
1966 BackTexture::BackTexture(
1967 MemoryTracker
* memory_tracker
,
1968 ContextState
* state
)
1969 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
1971 bytes_allocated_(0),
1975 BackTexture::~BackTexture() {
1976 // This does not destroy the render texture because that would require that
1977 // the associated GL context was current. Just check that it was explicitly
1982 void BackTexture::Create() {
1983 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
1984 state_
->GetErrorState());
1986 glGenTextures(1, &id_
);
1987 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
1988 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
1989 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1990 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1991 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1993 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1994 // never called on an offscreen context, no data will ever be uploaded to the
1995 // saved offscreen color texture (it is deferred until to when SwapBuffers
1996 // is called). My idea is that some nvidia drivers might have a bug where
1997 // deleting a texture that has never been populated might cause a
2000 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2002 bytes_allocated_
= 16u * 16u * 4u;
2003 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2006 bool BackTexture::AllocateStorage(
2007 const gfx::Size
& size
, GLenum format
, bool zero
) {
2009 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2010 state_
->GetErrorState());
2011 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2012 uint32 image_size
= 0;
2013 GLES2Util::ComputeImageDataSizes(
2014 size
.width(), size
.height(), format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2017 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2021 scoped_ptr
<char[]> zero_data
;
2023 zero_data
.reset(new char[image_size
]);
2024 memset(zero_data
.get(), 0, image_size
);
2027 glTexImage2D(GL_TEXTURE_2D
,
2039 bool success
= glGetError() == GL_NO_ERROR
;
2041 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2042 bytes_allocated_
= image_size
;
2043 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2048 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2050 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2051 state_
->GetErrorState());
2052 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2053 glCopyTexImage2D(GL_TEXTURE_2D
,
2062 void BackTexture::Destroy() {
2064 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2065 state_
->GetErrorState());
2066 glDeleteTextures(1, &id_
);
2069 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2070 bytes_allocated_
= 0;
2073 void BackTexture::Invalidate() {
2077 BackRenderbuffer::BackRenderbuffer(
2078 RenderbufferManager
* renderbuffer_manager
,
2079 MemoryTracker
* memory_tracker
,
2080 ContextState
* state
)
2081 : renderbuffer_manager_(renderbuffer_manager
),
2082 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2084 bytes_allocated_(0),
2088 BackRenderbuffer::~BackRenderbuffer() {
2089 // This does not destroy the render buffer because that would require that
2090 // the associated GL context was current. Just check that it was explicitly
2095 void BackRenderbuffer::Create() {
2096 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2097 state_
->GetErrorState());
2099 glGenRenderbuffersEXT(1, &id_
);
2102 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2103 const gfx::Size
& size
,
2106 ScopedGLErrorSuppressor
suppressor(
2107 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2108 ScopedRenderBufferBinder
binder(state_
, id_
);
2110 uint32 estimated_size
= 0;
2111 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2112 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2116 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2121 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2126 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2133 bool success
= glGetError() == GL_NO_ERROR
;
2135 // Mark the previously allocated bytes as free.
2136 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2137 bytes_allocated_
= estimated_size
;
2138 // Track the newly allocated bytes.
2139 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2144 void BackRenderbuffer::Destroy() {
2146 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2147 state_
->GetErrorState());
2148 glDeleteRenderbuffersEXT(1, &id_
);
2151 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2152 bytes_allocated_
= 0;
2155 void BackRenderbuffer::Invalidate() {
2159 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2160 : decoder_(decoder
),
2164 BackFramebuffer::~BackFramebuffer() {
2165 // This does not destroy the frame buffer because that would require that
2166 // the associated GL context was current. Just check that it was explicitly
2171 void BackFramebuffer::Create() {
2172 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2173 decoder_
->GetErrorState());
2175 glGenFramebuffersEXT(1, &id_
);
2178 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2180 ScopedGLErrorSuppressor
suppressor(
2181 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2182 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2183 GLuint attach_id
= texture
? texture
->id() : 0;
2184 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2185 GL_COLOR_ATTACHMENT0
,
2191 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2192 BackRenderbuffer
* render_buffer
) {
2194 ScopedGLErrorSuppressor
suppressor(
2195 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2196 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2197 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2198 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2204 void BackFramebuffer::Destroy() {
2206 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2207 decoder_
->GetErrorState());
2208 glDeleteFramebuffersEXT(1, &id_
);
2213 void BackFramebuffer::Invalidate() {
2217 GLenum
BackFramebuffer::CheckStatus() {
2219 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2220 decoder_
->GetErrorState());
2221 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2222 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2225 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2226 return new GLES2DecoderImpl(group
);
2229 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2232 logger_(&debug_marker_manager_
),
2233 state_(group_
->feature_info(), this, &logger_
),
2234 unpack_flip_y_(false),
2235 unpack_premultiply_alpha_(false),
2236 unpack_unpremultiply_alpha_(false),
2237 attrib_0_buffer_id_(0),
2238 attrib_0_buffer_matches_value_(true),
2240 fixed_attrib_buffer_id_(0),
2241 fixed_attrib_buffer_size_(0),
2242 offscreen_target_color_format_(0),
2243 offscreen_target_depth_format_(0),
2244 offscreen_target_stencil_format_(0),
2245 offscreen_target_samples_(0),
2246 offscreen_target_buffer_preserved_(true),
2247 offscreen_saved_color_format_(0),
2248 back_buffer_color_format_(0),
2249 back_buffer_has_depth_(false),
2250 back_buffer_has_stencil_(false),
2251 backbuffer_needs_clear_bits_(0),
2252 current_decoder_error_(error::kNoError
),
2253 use_shader_translator_(true),
2254 validators_(group_
->feature_info()->validators()),
2255 feature_info_(group_
->feature_info()),
2257 has_robustness_extension_(false),
2258 reset_status_(GL_NO_ERROR
),
2259 reset_by_robustness_extension_(false),
2260 supports_post_sub_buffer_(false),
2261 force_webgl_glsl_validation_(false),
2262 derivatives_explicitly_enabled_(false),
2263 frag_depth_explicitly_enabled_(false),
2264 draw_buffers_explicitly_enabled_(false),
2265 shader_texture_lod_explicitly_enabled_(false),
2266 compile_shader_always_succeeds_(false),
2267 lose_context_when_out_of_memory_(false),
2268 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2269 switches::kEnableGPUServiceLoggingGPU
)),
2270 viewport_max_width_(0),
2271 viewport_max_height_(0),
2272 texture_state_(group_
->feature_info()
2274 .texsubimage2d_faster_than_teximage2d
),
2275 validation_texture_(0),
2276 validation_fbo_multisample_(0),
2277 validation_fbo_(0) {
2280 attrib_0_value_
.v
[0] = 0.0f
;
2281 attrib_0_value_
.v
[1] = 0.0f
;
2282 attrib_0_value_
.v
[2] = 0.0f
;
2283 attrib_0_value_
.v
[3] = 1.0f
;
2285 // The shader translator is used for WebGL even when running on EGL
2286 // because additional restrictions are needed (like only enabling
2287 // GL_OES_standard_derivatives on demand). It is used for the unit
2288 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2289 // the empty string to CompileShader and this is not a valid shader.
2290 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2291 CommandLine::ForCurrentProcess()->HasSwitch(
2292 switches::kDisableGLSLTranslator
)) {
2293 use_shader_translator_
= false;
2297 GLES2DecoderImpl::~GLES2DecoderImpl() {
2300 bool GLES2DecoderImpl::Initialize(
2301 const scoped_refptr
<gfx::GLSurface
>& surface
,
2302 const scoped_refptr
<gfx::GLContext
>& context
,
2304 const gfx::Size
& size
,
2305 const DisallowedFeatures
& disallowed_features
,
2306 const std::vector
<int32
>& attribs
) {
2307 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2308 DCHECK(context
->IsCurrent(surface
.get()));
2309 DCHECK(!context_
.get());
2312 gpu_tracer_
= GPUTracer::Create(this);
2313 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2314 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2315 gpu_trace_level_
= 2;
2316 gpu_trace_commands_
= false;
2318 if (CommandLine::ForCurrentProcess()->HasSwitch(
2319 switches::kEnableGPUDebugging
)) {
2323 if (CommandLine::ForCurrentProcess()->HasSwitch(
2324 switches::kEnableGPUCommandLogging
)) {
2325 set_log_commands(true);
2328 compile_shader_always_succeeds_
= CommandLine::ForCurrentProcess()->HasSwitch(
2329 switches::kCompileShaderAlwaysSucceeds
);
2332 // Take ownership of the context and surface. The surface can be replaced with
2337 ContextCreationAttribHelper attrib_parser
;
2338 if (!attrib_parser
.Parse(attribs
))
2341 // Save the loseContextWhenOutOfMemory context creation attribute.
2342 lose_context_when_out_of_memory_
=
2343 attrib_parser
.lose_context_when_out_of_memory_
;
2345 // If the failIfMajorPerformanceCaveat context creation attribute was true
2346 // and we are using a software renderer, fail.
2347 if (attrib_parser
.fail_if_major_perf_caveat_
&&
2348 feature_info_
->feature_flags().is_swiftshader
) {
2349 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2354 if (!group_
->Initialize(this, disallowed_features
)) {
2355 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2356 << "failed to initialize.";
2357 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2363 disallowed_features_
= disallowed_features
;
2365 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2366 vertex_array_manager_
.reset(new VertexArrayManager());
2368 GLuint default_vertex_attrib_service_id
= 0;
2369 if (features().native_vertex_array_object
) {
2370 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2371 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2374 state_
.default_vertex_attrib_manager
=
2375 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2377 state_
.default_vertex_attrib_manager
->Initialize(
2378 group_
->max_vertex_attribs(),
2379 feature_info_
->workarounds().init_vertex_attributes
);
2381 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2382 DoBindVertexArrayOES(0);
2384 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2386 util_
.set_num_compressed_texture_formats(
2387 validators_
->compressed_texture_format
.GetValues().size());
2389 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2390 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2391 // OpenGL ES 2.0 does not have this issue.
2392 glEnableVertexAttribArray(0);
2394 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2395 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2396 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2397 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2398 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2400 state_
.texture_units
.resize(group_
->max_texture_units());
2401 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2402 glActiveTexture(GL_TEXTURE0
+ tt
);
2403 // We want the last bind to be 2D.
2405 if (features().oes_egl_image_external
) {
2406 ref
= texture_manager()->GetDefaultTextureInfo(
2407 GL_TEXTURE_EXTERNAL_OES
);
2408 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2409 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2411 if (features().arb_texture_rectangle
) {
2412 ref
= texture_manager()->GetDefaultTextureInfo(
2413 GL_TEXTURE_RECTANGLE_ARB
);
2414 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2415 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2417 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2418 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2419 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2420 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2421 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2422 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2424 glActiveTexture(GL_TEXTURE0
);
2428 if (attrib_parser
.samples_
> 0 && attrib_parser
.sample_buffers_
> 0 &&
2429 features().chromium_framebuffer_multisample
) {
2430 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2431 // max_sample_count must be initialized to a sane value. If
2432 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2433 GLint max_sample_count
= 1;
2434 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2435 offscreen_target_samples_
= std::min(attrib_parser
.samples_
,
2438 offscreen_target_samples_
= 1;
2440 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved_
;
2442 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2443 const bool rgb8_supported
=
2444 context_
->HasExtension("GL_OES_rgb8_rgba8");
2445 // The only available default render buffer formats in GLES2 have very
2446 // little precision. Don't enable multisampling unless 8-bit render
2447 // buffer formats are available--instead fall back to 8-bit textures.
2448 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2449 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2452 offscreen_target_samples_
= 1;
2453 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2457 // ANGLE only supports packed depth/stencil formats, so use it if it is
2459 const bool depth24_stencil8_supported
=
2460 feature_info_
->feature_flags().packed_depth24_stencil8
;
2461 VLOG(1) << "GL_OES_packed_depth_stencil "
2462 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2463 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2464 depth24_stencil8_supported
) {
2465 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2466 offscreen_target_stencil_format_
= 0;
2468 // It may be the case that this depth/stencil combination is not
2469 // supported, but this will be checked later by CheckFramebufferStatus.
2470 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2471 GL_DEPTH_COMPONENT16
: 0;
2472 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2473 GL_STENCIL_INDEX8
: 0;
2476 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2479 // If depth is requested at all, use the packed depth stencil format if
2480 // it's available, as some desktop GL drivers don't support any non-packed
2481 // formats for depth attachments.
2482 const bool depth24_stencil8_supported
=
2483 feature_info_
->feature_flags().packed_depth24_stencil8
;
2484 VLOG(1) << "GL_EXT_packed_depth_stencil "
2485 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2487 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2488 depth24_stencil8_supported
) {
2489 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2490 offscreen_target_stencil_format_
= 0;
2492 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2493 GL_DEPTH_COMPONENT
: 0;
2494 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2495 GL_STENCIL_INDEX
: 0;
2499 offscreen_saved_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2502 // Create the target frame buffer. This is the one that the client renders
2504 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2505 offscreen_target_frame_buffer_
->Create();
2506 // Due to GLES2 format limitations, either the color texture (for
2507 // non-multisampling) or the color render buffer (for multisampling) will be
2508 // attached to the offscreen frame buffer. The render buffer has more
2509 // limited formats available to it, but the texture can't do multisampling.
2510 if (IsOffscreenBufferMultisampled()) {
2511 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2512 renderbuffer_manager(), memory_tracker(), &state_
));
2513 offscreen_target_color_render_buffer_
->Create();
2515 offscreen_target_color_texture_
.reset(new BackTexture(
2516 memory_tracker(), &state_
));
2517 offscreen_target_color_texture_
->Create();
2519 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2520 renderbuffer_manager(), memory_tracker(), &state_
));
2521 offscreen_target_depth_render_buffer_
->Create();
2522 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2523 renderbuffer_manager(), memory_tracker(), &state_
));
2524 offscreen_target_stencil_render_buffer_
->Create();
2526 // Create the saved offscreen texture. The target frame buffer is copied
2527 // here when SwapBuffers is called.
2528 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2529 offscreen_saved_frame_buffer_
->Create();
2531 offscreen_saved_color_texture_
.reset(new BackTexture(
2532 memory_tracker(), &state_
));
2533 offscreen_saved_color_texture_
->Create();
2535 // Allocate the render buffers at their initial size and check the status
2536 // of the frame buffers is okay.
2537 if (!ResizeOffscreenFrameBuffer(size
)) {
2538 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2543 // Allocate the offscreen saved color texture.
2544 DCHECK(offscreen_saved_color_format_
);
2545 offscreen_saved_color_texture_
->AllocateStorage(
2546 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2548 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2549 offscreen_saved_color_texture_
.get());
2550 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2551 GL_FRAMEBUFFER_COMPLETE
) {
2552 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2557 // Bind to the new default frame buffer (the offscreen target frame buffer).
2558 // This should now be associated with ID zero.
2559 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2561 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2562 // These are NOT if the back buffer has these proprorties. They are
2563 // if we want the command buffer to enforce them regardless of what
2564 // the real backbuffer is assuming the real back buffer gives us more than
2565 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2566 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2567 // can't do anything about that.
2570 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2571 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2572 // user requested RGB then RGB. If the user did not specify a preference
2573 // than use whatever we were given. Same for DEPTH and STENCIL.
2574 back_buffer_color_format_
=
2575 (attrib_parser
.alpha_size_
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2576 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2577 back_buffer_has_depth_
= attrib_parser
.depth_size_
!= 0 && v
> 0;
2578 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2579 back_buffer_has_stencil_
= attrib_parser
.stencil_size_
!= 0 && v
> 0;
2582 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2583 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2584 // isn't well documented; it was discovered in the Khronos OpenGL ES
2585 // mailing list archives. It also implicitly enables the desktop GL
2586 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2587 // variable in fragment shaders.
2588 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2589 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2590 glEnable(GL_POINT_SPRITE
);
2593 has_robustness_extension_
=
2594 context
->HasExtension("GL_ARB_robustness") ||
2595 context
->HasExtension("GL_EXT_robustness");
2597 if (!InitializeShaderTranslator()) {
2601 state_
.viewport_width
= size
.width();
2602 state_
.viewport_height
= size
.height();
2604 GLint viewport_params
[4] = { 0 };
2605 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2606 viewport_max_width_
= viewport_params
[0];
2607 viewport_max_height_
= viewport_params
[1];
2609 state_
.scissor_width
= state_
.viewport_width
;
2610 state_
.scissor_height
= state_
.viewport_height
;
2612 // Set all the default state because some GL drivers get it wrong.
2613 state_
.InitCapabilities(NULL
);
2614 state_
.InitState(NULL
);
2615 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2617 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2618 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2619 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2620 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2622 bool call_gl_clear
= true;
2623 #if defined(OS_ANDROID)
2624 // Temporary workaround for Android WebView because this clear ignores the
2625 // clip and corrupts that external UI of the App. Not calling glClear is ok
2626 // because the system already clears the buffer before each draw. Proper
2627 // fix might be setting the scissor clip properly before initialize. See
2628 // crbug.com/259023 for details.
2629 call_gl_clear
= surface_
->GetHandle();
2631 if (call_gl_clear
) {
2632 // Clear the backbuffer.
2633 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2636 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2637 if (feature_info_
->workarounds()
2638 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2639 !surface
->IsOffscreen())
2640 supports_post_sub_buffer_
= false;
2642 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2643 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2646 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2647 context_
->SetUnbindFboOnMakeCurrent();
2650 if (feature_info_
->workarounds().release_image_after_use
) {
2651 image_manager()->SetReleaseAfterUse();
2654 // Only compositor contexts are known to use only the subset of GL
2655 // that can be safely migrated between the iGPU and the dGPU. Mark
2656 // those contexts as safe to forcibly transition between the GPUs.
2657 // http://crbug.com/180876, http://crbug.com/227228
2659 context_
->SetSafeToForceGpuSwitch();
2661 async_pixel_transfer_manager_
.reset(
2662 AsyncPixelTransferManager::Create(context
.get()));
2663 async_pixel_transfer_manager_
->Initialize(texture_manager());
2665 framebuffer_manager()->AddObserver(this);
2670 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2671 DCHECK(initialized());
2675 caps
.fast_npot_mo8_textures
=
2676 feature_info_
->workarounds().enable_chromium_fast_npot_mo8_textures
;
2677 caps
.egl_image_external
=
2678 feature_info_
->feature_flags().oes_egl_image_external
;
2679 caps
.texture_format_bgra8888
=
2680 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2681 caps
.texture_format_etc1
=
2682 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2683 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2684 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2685 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2686 caps
.discard_framebuffer
=
2687 feature_info_
->feature_flags().ext_discard_framebuffer
;
2688 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2690 #if defined(OS_MACOSX)
2691 // This is unconditionally true on mac, no need to test for it at runtime.
2692 caps
.iosurface
= true;
2695 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2696 caps
.map_image
= !!image_manager();
2701 void GLES2DecoderImpl::UpdateCapabilities() {
2702 util_
.set_num_compressed_texture_formats(
2703 validators_
->compressed_texture_format
.GetValues().size());
2704 util_
.set_num_shader_binary_formats(
2705 validators_
->shader_binary_format
.GetValues().size());
2708 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2709 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2711 if (!use_shader_translator_
) {
2714 ShBuiltInResources resources
;
2715 ShInitBuiltInResources(&resources
);
2716 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2717 resources
.MaxVertexUniformVectors
=
2718 group_
->max_vertex_uniform_vectors();
2719 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2720 resources
.MaxVertexTextureImageUnits
=
2721 group_
->max_vertex_texture_image_units();
2722 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2723 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2724 resources
.MaxFragmentUniformVectors
=
2725 group_
->max_fragment_uniform_vectors();
2726 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2727 resources
.MaxExpressionComplexity
= 256;
2728 resources
.MaxCallStackDepth
= 256;
2730 #if (ANGLE_SH_VERSION >= 110)
2731 GLint range
[2] = { 0, 0 };
2732 GLint precision
= 0;
2733 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2735 resources
.FragmentPrecisionHigh
=
2736 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2739 if (force_webgl_glsl_validation_
) {
2740 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2741 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2742 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2743 if (!draw_buffers_explicitly_enabled_
)
2744 resources
.MaxDrawBuffers
= 1;
2745 #if (ANGLE_SH_VERSION >= 123)
2746 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2749 resources
.OES_standard_derivatives
=
2750 features().oes_standard_derivatives
? 1 : 0;
2751 resources
.ARB_texture_rectangle
=
2752 features().arb_texture_rectangle
? 1 : 0;
2753 resources
.OES_EGL_image_external
=
2754 features().oes_egl_image_external
? 1 : 0;
2755 resources
.EXT_draw_buffers
=
2756 features().ext_draw_buffers
? 1 : 0;
2757 resources
.EXT_frag_depth
=
2758 features().ext_frag_depth
? 1 : 0;
2759 #if (ANGLE_SH_VERSION >= 123)
2760 resources
.EXT_shader_texture_lod
=
2761 features().ext_shader_texture_lod
? 1 : 0;
2765 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2767 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2768 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2769 resources
.HashFunction
= &CityHashForAngle
;
2771 resources
.HashFunction
= &CityHash64
;
2774 resources
.HashFunction
= NULL
;
2775 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2776 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2777 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2778 int driver_bug_workarounds
= 0;
2779 if (workarounds().needs_glsl_built_in_function_emulation
)
2780 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2781 if (workarounds().init_gl_position_in_vertex_shader
)
2782 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2783 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2784 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2785 if (workarounds().init_varyings_without_static_use
)
2786 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2787 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2788 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2790 vertex_translator_
= shader_translator_cache()->GetTranslator(
2794 implementation_type
,
2795 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2796 if (!vertex_translator_
.get()) {
2797 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2802 fragment_translator_
= shader_translator_cache()->GetTranslator(
2806 implementation_type
,
2807 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2808 if (!fragment_translator_
.get()) {
2809 LOG(ERROR
) << "Could not initialize fragment shader translator.";
2816 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
2817 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2818 if (GetBuffer(client_ids
[ii
])) {
2822 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2823 glGenBuffersARB(n
, service_ids
.get());
2824 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2825 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
2830 bool GLES2DecoderImpl::GenFramebuffersHelper(
2831 GLsizei n
, const GLuint
* client_ids
) {
2832 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2833 if (GetFramebuffer(client_ids
[ii
])) {
2837 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2838 glGenFramebuffersEXT(n
, service_ids
.get());
2839 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2840 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
2845 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2846 GLsizei n
, const GLuint
* client_ids
) {
2847 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2848 if (GetRenderbuffer(client_ids
[ii
])) {
2852 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2853 glGenRenderbuffersEXT(n
, service_ids
.get());
2854 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2855 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
2860 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
2861 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2862 if (GetTexture(client_ids
[ii
])) {
2866 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2867 glGenTextures(n
, service_ids
.get());
2868 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2869 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
2874 void GLES2DecoderImpl::DeleteBuffersHelper(
2875 GLsizei n
, const GLuint
* client_ids
) {
2876 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2877 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
2878 if (buffer
&& !buffer
->IsDeleted()) {
2879 state_
.vertex_attrib_manager
->Unbind(buffer
);
2880 if (state_
.bound_array_buffer
.get() == buffer
) {
2881 state_
.bound_array_buffer
= NULL
;
2883 RemoveBuffer(client_ids
[ii
]);
2888 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2889 GLsizei n
, const GLuint
* client_ids
) {
2890 bool supports_separate_framebuffer_binds
=
2891 features().chromium_framebuffer_multisample
;
2893 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2894 Framebuffer
* framebuffer
=
2895 GetFramebuffer(client_ids
[ii
]);
2896 if (framebuffer
&& !framebuffer
->IsDeleted()) {
2897 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
2898 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
2899 framebuffer_state_
.clear_state_dirty
= true;
2900 GLenum target
= supports_separate_framebuffer_binds
?
2901 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2902 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2904 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
2905 framebuffer_state_
.bound_read_framebuffer
= NULL
;
2906 GLenum target
= supports_separate_framebuffer_binds
?
2907 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2908 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2911 RemoveFramebuffer(client_ids
[ii
]);
2916 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2917 GLsizei n
, const GLuint
* client_ids
) {
2918 bool supports_separate_framebuffer_binds
=
2919 features().chromium_framebuffer_multisample
;
2920 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2921 Renderbuffer
* renderbuffer
=
2922 GetRenderbuffer(client_ids
[ii
]);
2923 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
2924 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
2925 state_
.bound_renderbuffer
= NULL
;
2927 // Unbind from current framebuffers.
2928 if (supports_separate_framebuffer_binds
) {
2929 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2930 framebuffer_state_
.bound_read_framebuffer
2931 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
2933 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2934 framebuffer_state_
.bound_draw_framebuffer
2935 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
2938 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2939 framebuffer_state_
.bound_draw_framebuffer
2940 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
2943 framebuffer_state_
.clear_state_dirty
= true;
2944 RemoveRenderbuffer(client_ids
[ii
]);
2949 void GLES2DecoderImpl::DeleteTexturesHelper(
2950 GLsizei n
, const GLuint
* client_ids
) {
2951 bool supports_separate_framebuffer_binds
=
2952 features().chromium_framebuffer_multisample
;
2953 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2954 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
2956 Texture
* texture
= texture_ref
->texture();
2957 if (texture
->IsAttachedToFramebuffer()) {
2958 framebuffer_state_
.clear_state_dirty
= true;
2960 // Unbind texture_ref from texture_ref units.
2961 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
2962 state_
.texture_units
[jj
].Unbind(texture_ref
);
2964 // Unbind from current framebuffers.
2965 if (supports_separate_framebuffer_binds
) {
2966 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2967 framebuffer_state_
.bound_read_framebuffer
2968 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
2970 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2971 framebuffer_state_
.bound_draw_framebuffer
2972 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
2975 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2976 framebuffer_state_
.bound_draw_framebuffer
2977 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
2980 #if defined(OS_MACOSX)
2981 GLuint service_id
= texture
->service_id();
2982 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
2983 ReleaseIOSurfaceForTexture(service_id
);
2986 RemoveTexture(client_ids
[ii
]);
2991 // } // anonymous namespace
2993 bool GLES2DecoderImpl::MakeCurrent() {
2994 if (!context_
.get())
2997 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
2998 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3000 // Some D3D drivers cannot recover from device lost in the GPU process
3001 // sandbox. Allow a new GPU process to launch.
3002 if (workarounds().exit_on_context_lost
) {
3003 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
3004 << " a D3D device in the Chrome GPU process sandbox.";
3006 base::win::SetShouldCrashOnProcessDetach(false);
3014 ProcessFinishedAsyncTransfers();
3016 // Rebind the FBO if it was unbound by the context.
3017 if (workarounds().unbind_fbo_on_context_switch
)
3018 RestoreFramebufferBindings();
3020 framebuffer_state_
.clear_state_dirty
= true;
3025 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3026 ProcessPendingReadPixels();
3027 if (engine() && query_manager_
.get())
3028 query_manager_
->ProcessPendingTransferQueries();
3030 // TODO(epenner): Is there a better place to do this?
3031 // This needs to occur before we execute any batch of commands
3032 // from the client, as the client may have recieved an async
3033 // completion while issuing those commands.
3034 // "DidFlushStart" would be ideal if we had such a callback.
3035 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3038 static void RebindCurrentFramebuffer(
3040 Framebuffer
* framebuffer
,
3041 GLuint back_buffer_service_id
) {
3042 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3044 if (framebuffer_id
== 0) {
3045 framebuffer_id
= back_buffer_service_id
;
3048 glBindFramebufferEXT(target
, framebuffer_id
);
3051 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3052 framebuffer_state_
.clear_state_dirty
= true;
3054 if (!features().chromium_framebuffer_multisample
) {
3055 RebindCurrentFramebuffer(
3057 framebuffer_state_
.bound_draw_framebuffer
.get(),
3058 GetBackbufferServiceId());
3060 RebindCurrentFramebuffer(
3061 GL_READ_FRAMEBUFFER_EXT
,
3062 framebuffer_state_
.bound_read_framebuffer
.get(),
3063 GetBackbufferServiceId());
3064 RebindCurrentFramebuffer(
3065 GL_DRAW_FRAMEBUFFER_EXT
,
3066 framebuffer_state_
.bound_draw_framebuffer
.get(),
3067 GetBackbufferServiceId());
3072 bool GLES2DecoderImpl::CheckFramebufferValid(
3073 Framebuffer
* framebuffer
,
3074 GLenum target
, const char* func_name
) {
3076 if (backbuffer_needs_clear_bits_
) {
3077 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3078 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3079 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3081 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
3082 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
3084 state_
.SetDeviceDepthMask(GL_TRUE
);
3085 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3086 bool reset_draw_buffer
= false;
3087 if ((backbuffer_needs_clear_bits_
| GL_COLOR_BUFFER_BIT
) != 0 &&
3088 group_
->draw_buffer() == GL_NONE
) {
3089 reset_draw_buffer
= true;
3090 GLenum buf
= GL_BACK
;
3091 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3092 buf
= GL_COLOR_ATTACHMENT0
;
3093 glDrawBuffersARB(1, &buf
);
3095 glClear(backbuffer_needs_clear_bits_
);
3096 if (reset_draw_buffer
) {
3097 GLenum buf
= GL_NONE
;
3098 glDrawBuffersARB(1, &buf
);
3100 backbuffer_needs_clear_bits_
= 0;
3101 RestoreClearState();
3106 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3110 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3111 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3113 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3117 // Are all the attachments cleared?
3118 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3119 texture_manager()->HaveUnclearedMips()) {
3120 if (!framebuffer
->IsCleared()) {
3121 // Can we clear them?
3122 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3123 GL_FRAMEBUFFER_COMPLETE
) {
3125 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3126 "framebuffer incomplete (clear)");
3129 ClearUnclearedAttachments(target
, framebuffer
);
3133 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3134 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3135 GL_FRAMEBUFFER_COMPLETE
) {
3137 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3138 "framebuffer incomplete (check)");
3141 framebuffer_manager()->MarkAsComplete(framebuffer
);
3144 // NOTE: At this point we don't know if the framebuffer is complete but
3145 // we DO know that everything that needs to be cleared has been cleared.
3149 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3150 if (!features().chromium_framebuffer_multisample
) {
3151 bool valid
= CheckFramebufferValid(
3152 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3160 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3161 GL_DRAW_FRAMEBUFFER_EXT
,
3163 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3164 GL_READ_FRAMEBUFFER_EXT
,
3168 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3169 Framebuffer
* framebuffer
=
3170 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3171 if (framebuffer
!= NULL
) {
3172 const Framebuffer::Attachment
* attachment
=
3173 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3175 return gfx::Size(attachment
->width(), attachment
->height());
3177 return gfx::Size(0, 0);
3178 } else if (offscreen_target_frame_buffer_
.get()) {
3179 return offscreen_size_
;
3181 return surface_
->GetSize();
3185 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3186 Framebuffer
* framebuffer
=
3187 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3188 if (framebuffer
!= NULL
) {
3189 return framebuffer
->GetColorAttachmentTextureType();
3191 return GL_UNSIGNED_BYTE
;
3195 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3196 Framebuffer
* framebuffer
=
3197 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3198 if (framebuffer
!= NULL
) {
3199 return framebuffer
->GetColorAttachmentFormat();
3200 } else if (offscreen_target_frame_buffer_
.get()) {
3201 return offscreen_target_color_format_
;
3203 return back_buffer_color_format_
;
3207 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3208 Framebuffer
* framebuffer
=
3209 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3210 if (framebuffer
!= NULL
) {
3211 return framebuffer
->GetColorAttachmentFormat();
3212 } else if (offscreen_target_frame_buffer_
.get()) {
3213 return offscreen_target_color_format_
;
3215 return back_buffer_color_format_
;
3219 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3220 if (!offscreen_saved_color_texture_info_
.get())
3222 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3223 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3224 texture_manager()->SetLevelInfo(
3225 offscreen_saved_color_texture_info_
.get(),
3229 offscreen_size_
.width(),
3230 offscreen_size_
.height(),
3236 texture_manager()->SetParameteri(
3237 "UpdateParentTextureInfo",
3239 offscreen_saved_color_texture_info_
.get(),
3240 GL_TEXTURE_MAG_FILTER
,
3242 texture_manager()->SetParameteri(
3243 "UpdateParentTextureInfo",
3245 offscreen_saved_color_texture_info_
.get(),
3246 GL_TEXTURE_MIN_FILTER
,
3248 texture_manager()->SetParameteri(
3249 "UpdateParentTextureInfo",
3251 offscreen_saved_color_texture_info_
.get(),
3254 texture_manager()->SetParameteri(
3255 "UpdateParentTextureInfo",
3257 offscreen_saved_color_texture_info_
.get(),
3260 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3262 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3265 void GLES2DecoderImpl::SetResizeCallback(
3266 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3267 resize_callback_
= callback
;
3270 Logger
* GLES2DecoderImpl::GetLogger() {
3274 void GLES2DecoderImpl::BeginDecoding() {
3275 gpu_tracer_
->BeginDecoding();
3276 gpu_trace_commands_
= gpu_tracer_
->IsTracing();
3279 void GLES2DecoderImpl::EndDecoding() {
3280 gpu_tracer_
->EndDecoding();
3283 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3284 return state_
.GetErrorState();
3287 void GLES2DecoderImpl::SetShaderCacheCallback(
3288 const ShaderCacheCallback
& callback
) {
3289 shader_cache_callback_
= callback
;
3292 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3293 const WaitSyncPointCallback
& callback
) {
3294 wait_sync_point_callback_
= callback
;
3297 AsyncPixelTransferManager
*
3298 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3299 return async_pixel_transfer_manager_
.get();
3302 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3303 async_pixel_transfer_manager_
.reset();
3306 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3307 AsyncPixelTransferManager
* manager
) {
3308 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3311 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3312 uint32
* service_texture_id
) {
3313 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3315 *service_texture_id
= texture_ref
->service_id();
3321 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3322 return texture_state_
.texture_upload_count
+
3323 async_pixel_transfer_manager_
->GetTextureUploadCount();
3326 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3327 return texture_state_
.total_texture_upload_time
+
3328 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3331 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3332 return total_processing_commands_time_
;
3335 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3336 total_processing_commands_time_
+= time
;
3339 void GLES2DecoderImpl::Destroy(bool have_context
) {
3343 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3345 // Unbind everything.
3346 state_
.vertex_attrib_manager
= NULL
;
3347 state_
.default_vertex_attrib_manager
= NULL
;
3348 state_
.texture_units
.clear();
3349 state_
.bound_array_buffer
= NULL
;
3350 state_
.current_queries
.clear();
3351 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3352 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3353 state_
.bound_renderbuffer
= NULL
;
3355 if (offscreen_saved_color_texture_info_
.get()) {
3356 DCHECK(offscreen_target_color_texture_
);
3357 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3358 offscreen_saved_color_texture_
->id());
3359 offscreen_saved_color_texture_
->Invalidate();
3360 offscreen_saved_color_texture_info_
= NULL
;
3363 if (copy_texture_CHROMIUM_
.get()) {
3364 copy_texture_CHROMIUM_
->Destroy();
3365 copy_texture_CHROMIUM_
.reset();
3368 if (state_
.current_program
.get()) {
3369 program_manager()->UnuseProgram(shader_manager(),
3370 state_
.current_program
.get());
3373 if (attrib_0_buffer_id_
) {
3374 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3376 if (fixed_attrib_buffer_id_
) {
3377 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3380 if (validation_texture_
) {
3381 glDeleteTextures(1, &validation_texture_
);
3382 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3383 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3386 if (offscreen_target_frame_buffer_
.get())
3387 offscreen_target_frame_buffer_
->Destroy();
3388 if (offscreen_target_color_texture_
.get())
3389 offscreen_target_color_texture_
->Destroy();
3390 if (offscreen_target_color_render_buffer_
.get())
3391 offscreen_target_color_render_buffer_
->Destroy();
3392 if (offscreen_target_depth_render_buffer_
.get())
3393 offscreen_target_depth_render_buffer_
->Destroy();
3394 if (offscreen_target_stencil_render_buffer_
.get())
3395 offscreen_target_stencil_render_buffer_
->Destroy();
3396 if (offscreen_saved_frame_buffer_
.get())
3397 offscreen_saved_frame_buffer_
->Destroy();
3398 if (offscreen_saved_color_texture_
.get())
3399 offscreen_saved_color_texture_
->Destroy();
3400 if (offscreen_resolved_frame_buffer_
.get())
3401 offscreen_resolved_frame_buffer_
->Destroy();
3402 if (offscreen_resolved_color_texture_
.get())
3403 offscreen_resolved_color_texture_
->Destroy();
3405 if (offscreen_target_frame_buffer_
.get())
3406 offscreen_target_frame_buffer_
->Invalidate();
3407 if (offscreen_target_color_texture_
.get())
3408 offscreen_target_color_texture_
->Invalidate();
3409 if (offscreen_target_color_render_buffer_
.get())
3410 offscreen_target_color_render_buffer_
->Invalidate();
3411 if (offscreen_target_depth_render_buffer_
.get())
3412 offscreen_target_depth_render_buffer_
->Invalidate();
3413 if (offscreen_target_stencil_render_buffer_
.get())
3414 offscreen_target_stencil_render_buffer_
->Invalidate();
3415 if (offscreen_saved_frame_buffer_
.get())
3416 offscreen_saved_frame_buffer_
->Invalidate();
3417 if (offscreen_saved_color_texture_
.get())
3418 offscreen_saved_color_texture_
->Invalidate();
3419 if (offscreen_resolved_frame_buffer_
.get())
3420 offscreen_resolved_frame_buffer_
->Invalidate();
3421 if (offscreen_resolved_color_texture_
.get())
3422 offscreen_resolved_color_texture_
->Invalidate();
3425 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3426 // Otherwise, we can leak objects. http://crbug.com/258772.
3427 // state_.current_program must be reset before group_ is reset because
3428 // the later deletes the ProgramManager object that referred by
3429 // state_.current_program object.
3430 state_
.current_program
= NULL
;
3432 copy_texture_CHROMIUM_
.reset();
3434 if (query_manager_
.get()) {
3435 query_manager_
->Destroy(have_context
);
3436 query_manager_
.reset();
3439 if (vertex_array_manager_
.get()) {
3440 vertex_array_manager_
->Destroy(have_context
);
3441 vertex_array_manager_
.reset();
3444 offscreen_target_frame_buffer_
.reset();
3445 offscreen_target_color_texture_
.reset();
3446 offscreen_target_color_render_buffer_
.reset();
3447 offscreen_target_depth_render_buffer_
.reset();
3448 offscreen_target_stencil_render_buffer_
.reset();
3449 offscreen_saved_frame_buffer_
.reset();
3450 offscreen_saved_color_texture_
.reset();
3451 offscreen_resolved_frame_buffer_
.reset();
3452 offscreen_resolved_color_texture_
.reset();
3454 // Need to release these before releasing |group_| which may own the
3455 // ShaderTranslatorCache.
3456 fragment_translator_
= NULL
;
3457 vertex_translator_
= NULL
;
3459 // Should destroy the transfer manager before the texture manager held
3460 // by the context group.
3461 async_pixel_transfer_manager_
.reset();
3464 framebuffer_manager()->RemoveObserver(this);
3465 group_
->Destroy(this, have_context
);
3469 if (context_
.get()) {
3470 context_
->ReleaseCurrent(NULL
);
3474 #if defined(OS_MACOSX)
3475 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3476 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3477 CFRelease(it
->second
);
3479 texture_to_io_surface_map_
.clear();
3483 void GLES2DecoderImpl::SetSurface(
3484 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3485 DCHECK(context_
->IsCurrent(NULL
));
3486 DCHECK(surface_
.get());
3488 RestoreCurrentFramebufferBindings();
3491 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3492 if (!offscreen_saved_color_texture_
.get()) {
3493 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3496 if (!offscreen_saved_color_texture_info_
.get()) {
3497 GLuint service_id
= offscreen_saved_color_texture_
->id();
3498 offscreen_saved_color_texture_info_
= TextureRef::Create(
3499 texture_manager(), 0, service_id
);
3500 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3502 UpdateParentTextureInfo();
3504 mailbox_manager()->ProduceTexture(
3505 GL_TEXTURE_2D
, mailbox
, offscreen_saved_color_texture_info_
->texture());
3508 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3509 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3510 if (!is_offscreen
) {
3511 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3512 << " with an onscreen framebuffer.";
3516 if (offscreen_size_
== size
)
3519 offscreen_size_
= size
;
3520 int w
= offscreen_size_
.width();
3521 int h
= offscreen_size_
.height();
3522 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3523 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3524 << "to allocate storage due to excessive dimensions.";
3528 // Reallocate the offscreen target buffers.
3529 DCHECK(offscreen_target_color_format_
);
3530 if (IsOffscreenBufferMultisampled()) {
3531 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3532 feature_info_
, offscreen_size_
, offscreen_target_color_format_
,
3533 offscreen_target_samples_
)) {
3534 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3535 << "to allocate storage for offscreen target color buffer.";
3539 if (!offscreen_target_color_texture_
->AllocateStorage(
3540 offscreen_size_
, offscreen_target_color_format_
, false)) {
3541 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3542 << "to allocate storage for offscreen target color texture.";
3546 if (offscreen_target_depth_format_
&&
3547 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3548 feature_info_
, offscreen_size_
, offscreen_target_depth_format_
,
3549 offscreen_target_samples_
)) {
3550 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3551 << "to allocate storage for offscreen target depth buffer.";
3554 if (offscreen_target_stencil_format_
&&
3555 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3556 feature_info_
, offscreen_size_
, offscreen_target_stencil_format_
,
3557 offscreen_target_samples_
)) {
3558 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3559 << "to allocate storage for offscreen target stencil buffer.";
3563 // Attach the offscreen target buffers to the target frame buffer.
3564 if (IsOffscreenBufferMultisampled()) {
3565 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3566 GL_COLOR_ATTACHMENT0
,
3567 offscreen_target_color_render_buffer_
.get());
3569 offscreen_target_frame_buffer_
->AttachRenderTexture(
3570 offscreen_target_color_texture_
.get());
3572 if (offscreen_target_depth_format_
) {
3573 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3574 GL_DEPTH_ATTACHMENT
,
3575 offscreen_target_depth_render_buffer_
.get());
3577 const bool packed_depth_stencil
=
3578 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3579 if (packed_depth_stencil
) {
3580 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3581 GL_STENCIL_ATTACHMENT
,
3582 offscreen_target_depth_render_buffer_
.get());
3583 } else if (offscreen_target_stencil_format_
) {
3584 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3585 GL_STENCIL_ATTACHMENT
,
3586 offscreen_target_stencil_render_buffer_
.get());
3589 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3590 GL_FRAMEBUFFER_COMPLETE
) {
3591 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3592 << "because offscreen FBO was incomplete.";
3596 // Clear the target frame buffer.
3598 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3599 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3600 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3601 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3603 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
3604 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
3606 state_
.SetDeviceDepthMask(GL_TRUE
);
3607 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3608 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3609 RestoreClearState();
3612 // Destroy the offscreen resolved framebuffers.
3613 if (offscreen_resolved_frame_buffer_
.get())
3614 offscreen_resolved_frame_buffer_
->Destroy();
3615 if (offscreen_resolved_color_texture_
.get())
3616 offscreen_resolved_color_texture_
->Destroy();
3617 offscreen_resolved_color_texture_
.reset();
3618 offscreen_resolved_frame_buffer_
.reset();
3623 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(
3624 uint32 immediate_data_size
, const cmds::ResizeCHROMIUM
& c
) {
3625 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3626 return error::kDeferCommandUntilLater
;
3628 GLuint width
= static_cast<GLuint
>(c
.width
);
3629 GLuint height
= static_cast<GLuint
>(c
.height
);
3630 GLfloat scale_factor
= c
.scale_factor
;
3631 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3633 width
= std::max(1U, width
);
3634 height
= std::max(1U, height
);
3636 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3637 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3638 // Make sure that we are done drawing to the back buffer before resizing.
3641 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3643 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3644 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3645 << "ResizeOffscreenFrameBuffer failed.";
3646 return error::kLostContext
;
3650 if (!resize_callback_
.is_null()) {
3651 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3652 DCHECK(context_
->IsCurrent(surface_
.get()));
3653 if (!context_
->IsCurrent(surface_
.get())) {
3654 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3655 << "current after resize callback.";
3656 return error::kLostContext
;
3660 return error::kNoError
;
3663 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3664 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3665 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3667 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3670 // Decode command with its arguments, and call the corresponding GL function.
3671 // Note: args is a pointer to the command buffer. As such, it could be changed
3672 // by a (malicious) client at any time, so if validation has to happen, it
3673 // should operate on a copy of them.
3674 error::Error
GLES2DecoderImpl::DoCommand(
3675 unsigned int command
,
3676 unsigned int arg_count
,
3677 const void* cmd_data
) {
3678 error::Error result
= error::kNoError
;
3679 if (log_commands()) {
3680 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3681 // VLOG(1), no luck.
3682 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]" << "cmd: "
3683 << GetCommandName(command
);
3685 unsigned int command_index
= command
- kStartPoint
- 1;
3686 if (command_index
< arraysize(g_command_info
)) {
3687 const CommandInfo
& info
= g_command_info
[command_index
];
3688 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3689 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3690 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3691 bool doing_gpu_trace
= false;
3692 if (gpu_trace_commands_
) {
3693 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
3694 doing_gpu_trace
= true;
3695 gpu_tracer_
->Begin(GetCommandName(command
), kTraceDecoder
);
3699 uint32 immediate_data_size
=
3700 (arg_count
- info_arg_count
) * sizeof(CommandBufferEntry
); // NOLINT
3702 #define GLES2_CMD_OP(name) \
3703 case cmds::name::kCmdId: \
3704 result = Handle ## name( \
3705 immediate_data_size, \
3706 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3709 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3713 if (doing_gpu_trace
)
3714 gpu_tracer_
->End(kTraceDecoder
);
3718 while ((error
= glGetError()) != GL_NO_ERROR
) {
3719 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
3720 << "GL ERROR: " << GLES2Util::GetStringEnum(error
) << " : "
3721 << GetCommandName(command
);
3722 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
3726 result
= error::kInvalidArguments
;
3729 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
3731 if (result
== error::kNoError
&& current_decoder_error_
!= error::kNoError
) {
3732 result
= current_decoder_error_
;
3733 current_decoder_error_
= error::kNoError
;
3738 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
3739 buffer_manager()->RemoveBuffer(client_id
);
3742 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id
) {
3743 if (GetProgram(client_id
)) {
3746 GLuint service_id
= glCreateProgram();
3747 if (service_id
!= 0) {
3748 CreateProgram(client_id
, service_id
);
3753 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type
, GLuint client_id
) {
3754 if (GetShader(client_id
)) {
3757 GLuint service_id
= glCreateShader(type
);
3758 if (service_id
!= 0) {
3759 CreateShader(client_id
, service_id
, type
);
3764 void GLES2DecoderImpl::DoFinish() {
3766 ProcessPendingReadPixels();
3767 ProcessPendingQueries();
3770 void GLES2DecoderImpl::DoFlush() {
3772 ProcessPendingQueries();
3775 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
3776 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
3777 if (texture_index
>= state_
.texture_units
.size()) {
3778 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3779 "glActiveTexture", texture_unit
, "texture_unit");
3782 state_
.active_texture_unit
= texture_index
;
3783 glActiveTexture(texture_unit
);
3786 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
3787 Buffer
* buffer
= NULL
;
3788 GLuint service_id
= 0;
3789 if (client_id
!= 0) {
3790 buffer
= GetBuffer(client_id
);
3792 if (!group_
->bind_generates_resource()) {
3793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
3795 "id not generated by glGenBuffers");
3799 // It's a new id so make a buffer buffer for it.
3800 glGenBuffersARB(1, &service_id
);
3801 CreateBuffer(client_id
, service_id
);
3802 buffer
= GetBuffer(client_id
);
3803 IdAllocatorInterface
* id_allocator
=
3804 group_
->GetIdAllocator(id_namespaces::kBuffers
);
3805 id_allocator
->MarkAsUsed(client_id
);
3808 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
3810 if (!buffer_manager()->SetTarget(buffer
, target
)) {
3812 GL_INVALID_OPERATION
,
3813 "glBindBuffer", "buffer bound to more than 1 target");
3816 service_id
= buffer
->service_id();
3819 case GL_ARRAY_BUFFER
:
3820 state_
.bound_array_buffer
= buffer
;
3822 case GL_ELEMENT_ARRAY_BUFFER
:
3823 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
3826 NOTREACHED(); // Validation should prevent us getting here.
3829 glBindBuffer(target
, service_id
);
3832 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3833 bool all_draw_buffers
) {
3834 Framebuffer
* framebuffer
=
3835 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3836 if (!all_draw_buffers
|| !framebuffer
) {
3837 return (GLES2Util::GetChannelsForFormat(
3838 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3840 return framebuffer
->HasAlphaMRT();
3843 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3844 Framebuffer
* framebuffer
=
3845 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3847 return framebuffer
->HasDepthAttachment();
3849 if (offscreen_target_frame_buffer_
.get()) {
3850 return offscreen_target_depth_format_
!= 0;
3852 return back_buffer_has_depth_
;
3855 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3856 Framebuffer
* framebuffer
=
3857 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3859 return framebuffer
->HasStencilAttachment();
3861 if (offscreen_target_frame_buffer_
.get()) {
3862 return offscreen_target_stencil_format_
!= 0 ||
3863 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3865 return back_buffer_has_stencil_
;
3868 void GLES2DecoderImpl::ApplyDirtyState() {
3869 if (framebuffer_state_
.clear_state_dirty
) {
3870 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
3871 state_
.SetDeviceColorMask(state_
.color_mask_red
,
3872 state_
.color_mask_green
,
3873 state_
.color_mask_blue
,
3874 state_
.color_mask_alpha
&& have_alpha
);
3876 bool have_depth
= BoundFramebufferHasDepthAttachment();
3877 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
3879 bool have_stencil
= BoundFramebufferHasStencilAttachment();
3880 state_
.SetDeviceStencilMaskSeparate(
3881 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
3882 state_
.SetDeviceStencilMaskSeparate(
3883 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
3885 state_
.SetDeviceCapabilityState(
3886 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
3887 state_
.SetDeviceCapabilityState(
3888 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
3889 framebuffer_state_
.clear_state_dirty
= false;
3893 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
3894 return (offscreen_target_frame_buffer_
.get())
3895 ? offscreen_target_frame_buffer_
->id()
3896 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
3899 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) const {
3900 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3901 "context", logger_
.GetLogPrefix());
3902 // Restore the Framebuffer first because of bugs in Intel drivers.
3903 // Intel drivers incorrectly clip the viewport settings to
3904 // the size of the current framebuffer object.
3905 RestoreFramebufferBindings();
3906 state_
.RestoreState(prev_state
);
3909 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3911 framebuffer_state_
.bound_draw_framebuffer
.get()
3912 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
3913 : GetBackbufferServiceId();
3914 if (!features().chromium_framebuffer_multisample
) {
3915 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
3917 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
3918 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
3919 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
3920 : GetBackbufferServiceId();
3921 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
3926 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
3927 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
3929 GLenum target
= texture
->target();
3930 glBindTexture(target
, service_id
);
3932 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
3934 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
3936 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
3938 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
3939 RestoreTextureUnitBindings(state_
.active_texture_unit
);
3943 void GLES2DecoderImpl::ClearAllAttributes() const {
3944 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3946 if (feature_info_
->feature_flags().native_vertex_array_object
)
3947 glBindVertexArrayOES(0);
3949 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
3950 if (i
!= 0) // Never disable attribute 0
3951 glDisableVertexAttribArray(i
);
3952 if(features().angle_instanced_arrays
)
3953 glVertexAttribDivisorANGLE(i
, 0);
3957 void GLES2DecoderImpl::RestoreAllAttributes() const {
3958 state_
.RestoreVertexAttribs();
3961 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
3962 state_
.SetIgnoreCachedStateForTest(ignore
);
3965 void GLES2DecoderImpl::OnFboChanged() const {
3966 if (workarounds().restore_scissor_on_fbo_change
)
3967 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
3970 // Called after the FBO is checked for completeness.
3971 void GLES2DecoderImpl::OnUseFramebuffer() const {
3972 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
3973 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
3974 // The driver forgets the correct scissor when modifying the FBO binding.
3975 glScissor(state_
.scissor_x
,
3977 state_
.scissor_width
,
3978 state_
.scissor_height
);
3980 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3981 // it's unclear how this bug works.
3986 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
3987 Framebuffer
* framebuffer
= NULL
;
3988 GLuint service_id
= 0;
3989 if (client_id
!= 0) {
3990 framebuffer
= GetFramebuffer(client_id
);
3992 if (!group_
->bind_generates_resource()) {
3993 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
3994 "glBindFramebuffer",
3995 "id not generated by glGenFramebuffers");
3999 // It's a new id so make a framebuffer framebuffer for it.
4000 glGenFramebuffersEXT(1, &service_id
);
4001 CreateFramebuffer(client_id
, service_id
);
4002 framebuffer
= GetFramebuffer(client_id
);
4003 IdAllocatorInterface
* id_allocator
=
4004 group_
->GetIdAllocator(id_namespaces::kFramebuffers
);
4005 id_allocator
->MarkAsUsed(client_id
);
4007 service_id
= framebuffer
->service_id();
4009 framebuffer
->MarkAsValid();
4011 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4013 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4014 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4017 // vmiura: This looks like dup code
4018 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4019 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4022 framebuffer_state_
.clear_state_dirty
= true;
4024 // If we are rendering to the backbuffer get the FBO id for any simulated
4026 if (framebuffer
== NULL
) {
4027 service_id
= GetBackbufferServiceId();
4030 glBindFramebufferEXT(target
, service_id
);
4034 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4035 Renderbuffer
* renderbuffer
= NULL
;
4036 GLuint service_id
= 0;
4037 if (client_id
!= 0) {
4038 renderbuffer
= GetRenderbuffer(client_id
);
4039 if (!renderbuffer
) {
4040 if (!group_
->bind_generates_resource()) {
4041 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4042 "glBindRenderbuffer",
4043 "id not generated by glGenRenderbuffers");
4047 // It's a new id so make a renderbuffer renderbuffer for it.
4048 glGenRenderbuffersEXT(1, &service_id
);
4049 CreateRenderbuffer(client_id
, service_id
);
4050 renderbuffer
= GetRenderbuffer(client_id
);
4051 IdAllocatorInterface
* id_allocator
=
4052 group_
->GetIdAllocator(id_namespaces::kRenderbuffers
);
4053 id_allocator
->MarkAsUsed(client_id
);
4055 service_id
= renderbuffer
->service_id();
4057 renderbuffer
->MarkAsValid();
4059 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4060 state_
.bound_renderbuffer
= renderbuffer
;
4061 glBindRenderbufferEXT(target
, service_id
);
4064 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4065 TextureRef
* texture_ref
= NULL
;
4066 GLuint service_id
= 0;
4067 if (client_id
!= 0) {
4068 texture_ref
= GetTexture(client_id
);
4070 if (!group_
->bind_generates_resource()) {
4071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4073 "id not generated by glGenTextures");
4077 // It's a new id so make a texture texture for it.
4078 glGenTextures(1, &service_id
);
4079 DCHECK_NE(0u, service_id
);
4080 CreateTexture(client_id
, service_id
);
4081 texture_ref
= GetTexture(client_id
);
4082 IdAllocatorInterface
* id_allocator
=
4083 group_
->GetIdAllocator(id_namespaces::kTextures
);
4084 id_allocator
->MarkAsUsed(client_id
);
4087 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4090 // Check the texture exists
4092 Texture
* texture
= texture_ref
->texture();
4093 // Check that we are not trying to bind it to a different target.
4094 if (texture
->target() != 0 && texture
->target() != target
) {
4095 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4097 "texture bound to more than 1 target.");
4100 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4101 if (texture
->target() == 0) {
4102 texture_manager()->SetTarget(texture_ref
, target
);
4104 glBindTexture(target
, texture
->service_id());
4106 glBindTexture(target
, 0);
4109 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4110 unit
.bind_target
= target
;
4113 unit
.bound_texture_2d
= texture_ref
;
4115 case GL_TEXTURE_CUBE_MAP
:
4116 unit
.bound_texture_cube_map
= texture_ref
;
4118 case GL_TEXTURE_EXTERNAL_OES
:
4119 unit
.bound_texture_external_oes
= texture_ref
;
4121 case GL_TEXTURE_RECTANGLE_ARB
:
4122 unit
.bound_texture_rectangle_arb
= texture_ref
;
4125 NOTREACHED(); // Validation should prevent us getting here.
4130 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4131 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4133 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4134 glDisableVertexAttribArray(index
);
4139 "glDisableVertexAttribArray", "index out of range");
4143 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4144 GLsizei numAttachments
,
4145 const GLenum
* attachments
) {
4146 Framebuffer
* framebuffer
=
4147 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4149 // Validates the attachments. If one of them fails
4150 // the whole command fails.
4151 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4153 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4155 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4156 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4157 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4162 // Marks each one of them as not cleared
4163 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4165 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4170 switch (attachments
[i
]) {
4172 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4175 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4176 case GL_STENCIL_EXT
:
4177 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4186 // If the default framebuffer is bound but we are still rendering to an
4187 // FBO, translate attachment names that refer to default framebuffer
4188 // channels to corresponding framebuffer attachments.
4189 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4190 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4191 GLenum attachment
= attachments
[i
];
4192 if (!framebuffer
&& GetBackbufferServiceId()) {
4193 switch (attachment
) {
4195 attachment
= GL_COLOR_ATTACHMENT0
;
4198 attachment
= GL_DEPTH_ATTACHMENT
;
4200 case GL_STENCIL_EXT
:
4201 attachment
= GL_STENCIL_ATTACHMENT
;
4208 translated_attachments
[i
] = attachment
;
4211 glDiscardFramebufferEXT(target
, numAttachments
, translated_attachments
.get());
4214 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4215 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4216 glEnableVertexAttribArray(index
);
4219 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4223 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4224 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4227 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4229 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4233 if (target
== GL_TEXTURE_CUBE_MAP
) {
4234 for (int i
= 0; i
< 6; ++i
) {
4235 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4236 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4238 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4243 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4245 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4250 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4251 // Workaround for Mac driver bug. In the large scheme of things setting
4252 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4253 // hit so there's probably no need to make this conditional. The bug appears
4254 // to be that if the filtering mode is set to something that doesn't require
4255 // mipmaps for rendering, or is never set to something other than the default,
4256 // then glGenerateMipmap misbehaves.
4257 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4258 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4260 glGenerateMipmapEXT(target
);
4261 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4262 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4263 texture_ref
->texture()->min_filter());
4265 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4266 if (error
== GL_NO_ERROR
) {
4267 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4271 bool GLES2DecoderImpl::GetHelper(
4272 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4273 DCHECK(num_written
);
4274 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4276 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4278 // Return the GL implementation's preferred format and (see below type)
4279 // if we have the GL extension that exposes this. This allows the GPU
4280 // client to use the implementation's preferred format for glReadPixels
4281 // for optimisation.
4283 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4284 // case when requested on integer/floating point buffers but which is
4285 // acceptable on GLES2 and with the GL_OES_read_format extension.
4287 // Therefore if an error occurs we swallow the error and use the
4288 // internal implementation.
4290 if (context_
->HasExtension("GL_OES_read_format")) {
4291 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4293 glGetIntegerv(pname
, params
);
4294 if (glGetError() == GL_NO_ERROR
)
4297 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4298 GetBoundReadFrameBufferInternalFormat());
4301 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4304 if (context_
->HasExtension("GL_OES_read_format")) {
4305 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4307 glGetIntegerv(pname
, params
);
4308 if (glGetError() == GL_NO_ERROR
)
4311 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4312 GetBoundReadFrameBufferInternalFormat(),
4313 GetBoundReadFrameBufferTextureType());
4316 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4319 *params
= group_
->max_fragment_uniform_vectors();
4322 case GL_MAX_VARYING_VECTORS
:
4325 *params
= group_
->max_varying_vectors();
4328 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4331 *params
= group_
->max_vertex_uniform_vectors();
4337 case GL_MAX_VIEWPORT_DIMS
:
4338 if (offscreen_target_frame_buffer_
.get()) {
4341 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4342 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4347 case GL_MAX_SAMPLES
:
4350 params
[0] = renderbuffer_manager()->max_samples();
4353 case GL_MAX_RENDERBUFFER_SIZE
:
4356 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4359 case GL_MAX_TEXTURE_SIZE
:
4362 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4365 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4368 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4371 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4374 params
[0] = group_
->max_color_attachments();
4377 case GL_MAX_DRAW_BUFFERS_ARB
:
4380 params
[0] = group_
->max_draw_buffers();
4387 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4388 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4395 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4396 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4399 case GL_STENCIL_BITS
:
4403 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4404 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4407 case GL_COMPRESSED_TEXTURE_FORMATS
:
4408 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4410 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4411 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4415 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4418 *params
= validators_
->compressed_texture_format
.GetValues().size();
4421 case GL_NUM_SHADER_BINARY_FORMATS
:
4424 *params
= validators_
->shader_binary_format
.GetValues().size();
4427 case GL_SHADER_BINARY_FORMATS
:
4428 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4430 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4431 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4435 case GL_SHADER_COMPILER
:
4441 case GL_ARRAY_BUFFER_BINDING
:
4444 if (state_
.bound_array_buffer
.get()) {
4445 GLuint client_id
= 0;
4446 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4448 *params
= client_id
;
4454 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4457 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4458 GLuint client_id
= 0;
4459 buffer_manager()->GetClientId(
4460 state_
.vertex_attrib_manager
->element_array_buffer()->
4461 service_id(), &client_id
);
4462 *params
= client_id
;
4468 case GL_FRAMEBUFFER_BINDING
:
4469 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4472 Framebuffer
* framebuffer
=
4473 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4475 GLuint client_id
= 0;
4476 framebuffer_manager()->GetClientId(
4477 framebuffer
->service_id(), &client_id
);
4478 *params
= client_id
;
4484 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4487 Framebuffer
* framebuffer
=
4488 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4490 GLuint client_id
= 0;
4491 framebuffer_manager()->GetClientId(
4492 framebuffer
->service_id(), &client_id
);
4493 *params
= client_id
;
4499 case GL_RENDERBUFFER_BINDING
:
4502 Renderbuffer
* renderbuffer
=
4503 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4505 *params
= renderbuffer
->client_id();
4511 case GL_CURRENT_PROGRAM
:
4514 if (state_
.current_program
.get()) {
4515 GLuint client_id
= 0;
4516 program_manager()->GetClientId(
4517 state_
.current_program
->service_id(), &client_id
);
4518 *params
= client_id
;
4524 case GL_VERTEX_ARRAY_BINDING_OES
:
4527 if (state_
.vertex_attrib_manager
.get() !=
4528 state_
.default_vertex_attrib_manager
.get()) {
4529 GLuint client_id
= 0;
4530 vertex_array_manager_
->GetClientId(
4531 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4532 *params
= client_id
;
4538 case GL_TEXTURE_BINDING_2D
:
4541 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4542 if (unit
.bound_texture_2d
.get()) {
4543 *params
= unit
.bound_texture_2d
->client_id();
4549 case GL_TEXTURE_BINDING_CUBE_MAP
:
4552 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4553 if (unit
.bound_texture_cube_map
.get()) {
4554 *params
= unit
.bound_texture_cube_map
->client_id();
4560 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4563 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4564 if (unit
.bound_texture_external_oes
.get()) {
4565 *params
= unit
.bound_texture_external_oes
->client_id();
4571 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4574 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4575 if (unit
.bound_texture_rectangle_arb
.get()) {
4576 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4582 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4585 params
[0] = unpack_flip_y_
;
4588 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4591 params
[0] = unpack_premultiply_alpha_
;
4594 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4597 params
[0] = unpack_unpremultiply_alpha_
;
4600 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4603 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4607 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4608 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4611 Framebuffer
* framebuffer
=
4612 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4614 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4615 } else { // backbuffer
4616 if (pname
== GL_DRAW_BUFFER0_ARB
)
4617 params
[0] = group_
->draw_buffer();
4619 params
[0] = GL_NONE
;
4624 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4629 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4630 GLenum pname
, GLsizei
* num_values
) {
4631 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4634 return GetHelper(pname
, NULL
, num_values
);
4637 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4638 if (GL_MAX_SAMPLES
== pname
&&
4639 features().use_img_for_multisampled_render_to_texture
) {
4640 return GL_MAX_SAMPLES_IMG
;
4645 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4647 GLsizei num_written
= 0;
4648 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4649 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4650 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4651 GetHelper(pname
, values
.get(), &num_written
);
4653 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4654 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4657 pname
= AdjustGetPname(pname
);
4658 glGetBooleanv(pname
, params
);
4662 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4664 GLsizei num_written
= 0;
4665 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4666 if (GetHelper(pname
, NULL
, &num_written
)) {
4667 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4668 GetHelper(pname
, values
.get(), &num_written
);
4669 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4670 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4673 pname
= AdjustGetPname(pname
);
4674 glGetFloatv(pname
, params
);
4679 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4681 GLsizei num_written
;
4682 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4683 !GetHelper(pname
, params
, &num_written
)) {
4684 pname
= AdjustGetPname(pname
);
4685 glGetIntegerv(pname
, params
);
4689 void GLES2DecoderImpl::DoGetProgramiv(
4690 GLuint program_id
, GLenum pname
, GLint
* params
) {
4691 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
4695 program
->GetProgramiv(pname
, params
);
4698 void GLES2DecoderImpl::DoGetBufferParameteriv(
4699 GLenum target
, GLenum pname
, GLint
* params
) {
4700 // Just delegate it. Some validation is actually done before this.
4701 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4702 &state_
, target
, pname
, params
);
4705 void GLES2DecoderImpl::DoBindAttribLocation(
4706 GLuint program_id
, GLuint index
, const char* name
) {
4707 if (!StringIsValidForGLES(name
)) {
4709 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
4712 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4714 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
4717 if (index
>= group_
->max_vertex_attribs()) {
4719 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
4722 Program
* program
= GetProgramInfoNotShader(
4723 program_id
, "glBindAttribLocation");
4727 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
4728 glBindAttribLocation(program
->service_id(), index
, name
);
4731 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
4732 uint32 immediate_data_size
, const cmds::BindAttribLocationBucket
& c
) {
4733 GLuint program
= static_cast<GLuint
>(c
.program
);
4734 GLuint index
= static_cast<GLuint
>(c
.index
);
4735 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4736 if (!bucket
|| bucket
->size() == 0) {
4737 return error::kInvalidArguments
;
4739 std::string name_str
;
4740 if (!bucket
->GetAsString(&name_str
)) {
4741 return error::kInvalidArguments
;
4743 DoBindAttribLocation(program
, index
, name_str
.c_str());
4744 return error::kNoError
;
4747 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4748 GLuint program_id
, GLint location
, const char* name
) {
4749 if (!StringIsValidForGLES(name
)) {
4752 "glBindUniformLocationCHROMIUM", "Invalid character");
4755 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4757 GL_INVALID_OPERATION
,
4758 "glBindUniformLocationCHROMIUM", "reserved prefix");
4761 if (location
< 0 || static_cast<uint32
>(location
) >=
4762 (group_
->max_fragment_uniform_vectors() +
4763 group_
->max_vertex_uniform_vectors()) * 4) {
4766 "glBindUniformLocationCHROMIUM", "location out of range");
4769 Program
* program
= GetProgramInfoNotShader(
4770 program_id
, "glBindUniformLocationCHROMIUM");
4774 if (!program
->SetUniformLocationBinding(name
, location
)) {
4777 "glBindUniformLocationCHROMIUM", "location out of range");
4781 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4782 uint32 immediate_data_size
,
4783 const cmds::BindUniformLocationCHROMIUMBucket
& c
) {
4784 GLuint program
= static_cast<GLuint
>(c
.program
);
4785 GLint location
= static_cast<GLint
>(c
.location
);
4786 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4787 if (!bucket
|| bucket
->size() == 0) {
4788 return error::kInvalidArguments
;
4790 std::string name_str
;
4791 if (!bucket
->GetAsString(&name_str
)) {
4792 return error::kInvalidArguments
;
4794 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4795 return error::kNoError
;
4798 error::Error
GLES2DecoderImpl::HandleDeleteShader(
4799 uint32 immediate_data_size
, const cmds::DeleteShader
& c
) {
4800 GLuint client_id
= c
.shader
;
4802 Shader
* shader
= GetShader(client_id
);
4804 if (!shader
->IsDeleted()) {
4805 glDeleteShader(shader
->service_id());
4806 shader_manager()->MarkAsDeleted(shader
);
4809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
4812 return error::kNoError
;
4815 error::Error
GLES2DecoderImpl::HandleDeleteProgram(
4816 uint32 immediate_data_size
, const cmds::DeleteProgram
& c
) {
4817 GLuint client_id
= c
.program
;
4819 Program
* program
= GetProgram(client_id
);
4821 if (!program
->IsDeleted()) {
4822 program_manager()->MarkAsDeleted(shader_manager(), program
);
4826 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
4829 return error::kNoError
;
4832 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4833 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4834 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4835 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4836 id_allocator
->FreeID(ids
[ii
]);
4840 error::Error
GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4841 uint32 immediate_data_size
, const cmds::DeleteSharedIdsCHROMIUM
& c
) {
4842 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4843 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4845 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4846 return error::kOutOfBounds
;
4848 const GLuint
* ids
= GetSharedMemoryAs
<const GLuint
*>(
4849 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4851 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "DeleteSharedIdsCHROMIUM", "n < 0");
4852 return error::kNoError
;
4855 return error::kOutOfBounds
;
4857 DoDeleteSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4858 return error::kNoError
;
4861 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4862 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
4863 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4864 if (id_offset
== 0) {
4865 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4866 ids
[ii
] = id_allocator
->AllocateID();
4869 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4870 ids
[ii
] = id_allocator
->AllocateIDAtOrAbove(id_offset
);
4871 id_offset
= ids
[ii
] + 1;
4876 error::Error
GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4877 uint32 immediate_data_size
, const cmds::GenSharedIdsCHROMIUM
& c
) {
4878 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4879 GLuint id_offset
= static_cast<GLuint
>(c
.id_offset
);
4880 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4882 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4883 return error::kOutOfBounds
;
4885 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4886 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4888 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "GenSharedIdsCHROMIUM", "n < 0");
4889 return error::kNoError
;
4892 return error::kOutOfBounds
;
4894 DoGenSharedIdsCHROMIUM(namespace_id
, id_offset
, n
, ids
);
4895 return error::kNoError
;
4898 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4899 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4900 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4901 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4902 if (!id_allocator
->MarkAsUsed(ids
[ii
])) {
4903 for (GLsizei jj
= 0; jj
< ii
; ++jj
) {
4904 id_allocator
->FreeID(ids
[jj
]);
4907 GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM",
4908 "attempt to register id that already exists");
4914 error::Error
GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4915 uint32 immediate_data_size
, const cmds::RegisterSharedIdsCHROMIUM
& c
) {
4916 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4917 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4919 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4920 return error::kOutOfBounds
;
4922 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4923 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4925 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM", "n < 0");
4926 return error::kNoError
;
4929 return error::kOutOfBounds
;
4931 DoRegisterSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4932 return error::kNoError
;
4935 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
4936 DCHECK(!ShouldDeferDraws());
4937 if (CheckBoundFramebuffersValid("glClear")) {
4941 return error::kNoError
;
4944 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4945 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
4946 GLuint client_renderbuffer_id
) {
4947 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
4950 GL_INVALID_OPERATION
,
4951 "glFramebufferRenderbuffer", "no framebuffer bound");
4954 GLuint service_id
= 0;
4955 Renderbuffer
* renderbuffer
= NULL
;
4956 if (client_renderbuffer_id
) {
4957 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
4958 if (!renderbuffer
) {
4960 GL_INVALID_OPERATION
,
4961 "glFramebufferRenderbuffer", "unknown renderbuffer");
4964 service_id
= renderbuffer
->service_id();
4966 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4967 glFramebufferRenderbufferEXT(
4968 target
, attachment
, renderbuffertarget
, service_id
);
4969 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4970 if (error
== GL_NO_ERROR
) {
4971 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
4973 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
4974 framebuffer_state_
.clear_state_dirty
= true;
4979 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
4980 if (SetCapabilityState(cap
, false)) {
4985 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
4986 if (SetCapabilityState(cap
, true)) {
4991 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
4992 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
4993 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
4994 glDepthRange(znear
, zfar
);
4997 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
4998 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
4999 state_
.sample_coverage_invert
= (invert
!= 0);
5000 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5003 // Assumes framebuffer is complete.
5004 void GLES2DecoderImpl::ClearUnclearedAttachments(
5005 GLenum target
, Framebuffer
* framebuffer
) {
5006 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5007 // bind this to the DRAW point, clear then bind back to READ
5008 // TODO(gman): I don't think there is any guarantee that an FBO that
5009 // is complete on the READ attachment will be complete as a DRAW
5011 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5012 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5014 GLbitfield clear_bits
= 0;
5015 if (framebuffer
->HasUnclearedColorAttachments()) {
5018 (GLES2Util::GetChannelsForFormat(
5019 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5021 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5022 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5023 framebuffer
->PrepareDrawBuffersForClear();
5026 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5027 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5029 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
5030 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
5031 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5034 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5035 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5037 state_
.SetDeviceDepthMask(GL_TRUE
);
5038 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5041 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5042 glClear(clear_bits
);
5044 if ((clear_bits
| GL_COLOR_BUFFER_BIT
) != 0)
5045 framebuffer
->RestoreDrawBuffersAfterClear();
5047 framebuffer_manager()->MarkAttachmentsAsCleared(
5048 framebuffer
, renderbuffer_manager(), texture_manager());
5050 RestoreClearState();
5052 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5053 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5054 Framebuffer
* draw_framebuffer
=
5055 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5056 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5057 GetBackbufferServiceId();
5058 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5062 void GLES2DecoderImpl::RestoreClearState() {
5063 framebuffer_state_
.clear_state_dirty
= true;
5065 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5066 state_
.color_clear_alpha
);
5067 glClearStencil(state_
.stencil_clear
);
5068 glClearDepth(state_
.depth_clear
);
5069 if (state_
.enable_flags
.scissor_test
) {
5070 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5074 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5075 Framebuffer
* framebuffer
=
5076 GetFramebufferInfoForTarget(target
);
5078 return GL_FRAMEBUFFER_COMPLETE
;
5080 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5081 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5082 return completeness
;
5084 return framebuffer
->GetStatus(texture_manager(), target
);
5087 void GLES2DecoderImpl::DoFramebufferTexture2D(
5088 GLenum target
, GLenum attachment
, GLenum textarget
,
5089 GLuint client_texture_id
, GLint level
) {
5090 DoFramebufferTexture2DCommon(
5091 "glFramebufferTexture2D", target
, attachment
,
5092 textarget
, client_texture_id
, level
, 0);
5095 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5096 GLenum target
, GLenum attachment
, GLenum textarget
,
5097 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5098 DoFramebufferTexture2DCommon(
5099 "glFramebufferTexture2DMultisample", target
, attachment
,
5100 textarget
, client_texture_id
, level
, samples
);
5103 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5104 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5105 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5106 if (samples
> renderbuffer_manager()->max_samples()) {
5109 "glFramebufferTexture2DMultisample", "samples too large");
5112 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5115 GL_INVALID_OPERATION
,
5116 name
, "no framebuffer bound.");
5119 GLuint service_id
= 0;
5120 TextureRef
* texture_ref
= NULL
;
5121 if (client_texture_id
) {
5122 texture_ref
= GetTexture(client_texture_id
);
5125 GL_INVALID_OPERATION
,
5126 name
, "unknown texture_ref");
5129 service_id
= texture_ref
->service_id();
5132 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5135 name
, "level out of range");
5140 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5144 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5146 if (features().use_img_for_multisampled_render_to_texture
) {
5147 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5148 service_id
, level
, samples
);
5150 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5151 service_id
, level
, samples
);
5154 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5155 if (error
== GL_NO_ERROR
) {
5156 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5159 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5160 framebuffer_state_
.clear_state_dirty
= true;
5164 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5169 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5170 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5171 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5174 GL_INVALID_OPERATION
,
5175 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5178 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5179 const Framebuffer::Attachment
* attachment_object
=
5180 framebuffer
->GetAttachment(attachment
);
5181 *params
= attachment_object
? attachment_object
->object_name() : 0;
5183 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5184 features().use_img_for_multisampled_render_to_texture
) {
5185 pname
= GL_TEXTURE_SAMPLES_IMG
;
5187 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5191 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5192 GLenum target
, GLenum pname
, GLint
* params
) {
5193 Renderbuffer
* renderbuffer
=
5194 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5195 if (!renderbuffer
) {
5197 GL_INVALID_OPERATION
,
5198 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5202 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5203 *params
= renderbuffer
->internal_format();
5205 case GL_RENDERBUFFER_WIDTH
:
5206 *params
= renderbuffer
->width();
5208 case GL_RENDERBUFFER_HEIGHT
:
5209 *params
= renderbuffer
->height();
5211 case GL_RENDERBUFFER_SAMPLES_EXT
:
5212 if (features().use_img_for_multisampled_render_to_texture
) {
5213 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5216 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5220 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5225 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5226 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5227 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5228 GLbitfield mask
, GLenum filter
) {
5229 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5231 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5235 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5236 BlitFramebufferHelper(
5237 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5238 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5239 state_
.enable_flags
.scissor_test
);
5242 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5243 const FeatureInfo
* feature_info
,
5246 GLenum internal_format
,
5249 // TODO(sievers): This could be resolved at the GL binding level, but the
5250 // binding process is currently a bit too 'brute force'.
5251 if (feature_info
->feature_flags().is_angle
) {
5252 glRenderbufferStorageMultisampleANGLE(
5253 target
, samples
, internal_format
, width
, height
);
5254 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5255 glRenderbufferStorageMultisample(
5256 target
, samples
, internal_format
, width
, height
);
5258 glRenderbufferStorageMultisampleEXT(
5259 target
, samples
, internal_format
, width
, height
);
5263 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5273 // TODO(sievers): This could be resolved at the GL binding level, but the
5274 // binding process is currently a bit too 'brute force'.
5275 if (feature_info_
->feature_flags().is_angle
) {
5276 glBlitFramebufferANGLE(
5277 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5278 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5280 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5282 glBlitFramebufferEXT(
5283 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5287 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5289 GLenum internalformat
,
5292 if (samples
> renderbuffer_manager()->max_samples()) {
5295 "glRenderbufferStorageMultisample", "samples too large");
5299 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5300 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5303 "glRenderbufferStorageMultisample", "dimensions too large");
5307 uint32 estimated_size
= 0;
5308 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5309 width
, height
, samples
, internalformat
, &estimated_size
)) {
5312 "glRenderbufferStorageMultisample", "dimensions too large");
5316 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5319 "glRenderbufferStorageMultisample", "out of memory");
5326 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5327 GLenum target
, GLsizei samples
, GLenum internalformat
,
5328 GLsizei width
, GLsizei height
) {
5329 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5330 if (!renderbuffer
) {
5331 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5332 "glRenderbufferStorageMultisampleCHROMIUM",
5333 "no renderbuffer bound");
5337 if (!ValidateRenderbufferStorageMultisample(
5338 samples
, internalformat
, width
, height
)) {
5342 GLenum impl_format
=
5343 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5345 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5346 "glRenderbufferStorageMultisampleCHROMIUM");
5347 RenderbufferStorageMultisampleHelper(
5348 feature_info_
, target
, samples
, impl_format
, width
, height
);
5350 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5351 if (error
== GL_NO_ERROR
) {
5353 if (workarounds().validate_multisample_buffer_allocation
) {
5354 if (!VerifyMultisampleRenderbufferIntegrity(
5355 renderbuffer
->service_id(), impl_format
)) {
5358 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5363 // TODO(gman): If renderbuffers tracked which framebuffers they were
5364 // attached to we could just mark those framebuffers as not complete.
5365 framebuffer_manager()->IncFramebufferStateChangeCount();
5366 renderbuffer_manager()->SetInfo(
5367 renderbuffer
, samples
, internalformat
, width
, height
);
5371 // This is the handler for multisampled_render_to_texture extensions.
5372 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5373 GLenum target
, GLsizei samples
, GLenum internalformat
,
5374 GLsizei width
, GLsizei height
) {
5375 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5376 if (!renderbuffer
) {
5377 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5378 "glRenderbufferStorageMultisampleEXT",
5379 "no renderbuffer bound");
5383 if (!ValidateRenderbufferStorageMultisample(
5384 samples
, internalformat
, width
, height
)) {
5388 GLenum impl_format
=
5389 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5391 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5392 if (features().use_img_for_multisampled_render_to_texture
) {
5393 glRenderbufferStorageMultisampleIMG(
5394 target
, samples
, impl_format
, width
, height
);
5396 glRenderbufferStorageMultisampleEXT(
5397 target
, samples
, impl_format
, width
, height
);
5399 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5400 if (error
== GL_NO_ERROR
) {
5401 // TODO(gman): If renderbuffers tracked which framebuffers they were
5402 // attached to we could just mark those framebuffers as not complete.
5403 framebuffer_manager()->IncFramebufferStateChangeCount();
5404 renderbuffer_manager()->SetInfo(
5405 renderbuffer
, samples
, internalformat
, width
, height
);
5409 // This function validates the allocation of a multisampled renderbuffer
5410 // by clearing it to a key color, blitting the contents to a texture, and
5411 // reading back the color to ensure it matches the key.
5412 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5413 GLuint renderbuffer
, GLenum format
) {
5415 // Only validate color buffers.
5416 // These formats have been selected because they are very common or are known
5417 // to be used by the WebGL backbuffer. If problems are observed with other
5418 // color formats they can be added here.
5429 GLint draw_framebuffer
, read_framebuffer
;
5431 // Cache framebuffer and texture bindings.
5432 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5433 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5435 if (!validation_texture_
) {
5436 GLint bound_texture
;
5437 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5439 // Create additional resources needed for the verification.
5440 glGenTextures(1, &validation_texture_
);
5441 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5442 glGenFramebuffersEXT(1, &validation_fbo_
);
5444 // Texture only needs to be 1x1.
5445 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5446 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5447 GL_UNSIGNED_BYTE
, NULL
);
5449 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5450 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5451 GL_TEXTURE_2D
, validation_texture_
, 0);
5453 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5456 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5457 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5458 GL_RENDERBUFFER
, renderbuffer
);
5460 // Cache current state and reset it to the values we require.
5461 GLboolean scissor_enabled
= false;
5462 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5463 if (scissor_enabled
)
5464 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5466 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5467 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5468 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5470 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5471 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5472 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5474 // Clear the buffer to the desired key color.
5475 glClear(GL_COLOR_BUFFER_BIT
);
5477 // Blit from the multisample buffer to a standard texture.
5478 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5479 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5481 BlitFramebufferHelper(
5482 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5484 // Read a pixel from the buffer.
5485 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5487 unsigned char pixel
[3] = {0, 0, 0};
5488 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5490 // Detach the renderbuffer.
5491 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5492 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5493 GL_RENDERBUFFER
, 0);
5495 // Restore cached state.
5496 if (scissor_enabled
)
5497 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5499 state_
.SetDeviceColorMask(
5500 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5501 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5502 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5503 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5505 // Return true if the pixel matched the desired key color.
5506 return (pixel
[0] == 0xFF &&
5511 void GLES2DecoderImpl::DoRenderbufferStorage(
5512 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5513 Renderbuffer
* renderbuffer
=
5514 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5515 if (!renderbuffer
) {
5517 GL_INVALID_OPERATION
,
5518 "glRenderbufferStorage", "no renderbuffer bound");
5522 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5523 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5525 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5529 uint32 estimated_size
= 0;
5530 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5531 width
, height
, 1, internalformat
, &estimated_size
)) {
5533 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5537 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5539 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5543 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5544 glRenderbufferStorageEXT(
5546 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5550 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5551 if (error
== GL_NO_ERROR
) {
5552 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5553 // we could just mark those framebuffers as not complete.
5554 framebuffer_manager()->IncFramebufferStateChangeCount();
5555 renderbuffer_manager()->SetInfo(
5556 renderbuffer
, 1, internalformat
, width
, height
);
5560 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5561 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5562 Program
* program
= GetProgramInfoNotShader(
5563 program_id
, "glLinkProgram");
5568 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5569 ShaderTranslator
* vertex_translator
= NULL
;
5570 ShaderTranslator
* fragment_translator
= NULL
;
5571 if (use_shader_translator_
) {
5572 vertex_translator
= vertex_translator_
.get();
5573 fragment_translator
= fragment_translator_
.get();
5575 if (program
->Link(shader_manager(),
5577 fragment_translator
,
5578 workarounds().count_all_in_varyings_packing
?
5579 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5580 shader_cache_callback_
)) {
5581 if (program
== state_
.current_program
.get()) {
5582 if (workarounds().use_current_program_after_successful_link
)
5583 glUseProgram(program
->service_id());
5584 if (workarounds().clear_uniforms_before_first_program_use
)
5585 program_manager()->ClearUniforms(program
);
5590 void GLES2DecoderImpl::DoTexParameterf(
5591 GLenum target
, GLenum pname
, GLfloat param
) {
5592 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5595 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5599 texture_manager()->SetParameterf(
5600 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5603 void GLES2DecoderImpl::DoTexParameteri(
5604 GLenum target
, GLenum pname
, GLint param
) {
5605 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5608 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5612 texture_manager()->SetParameteri(
5613 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5616 void GLES2DecoderImpl::DoTexParameterfv(
5617 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5618 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5625 texture_manager()->SetParameterf(
5626 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5629 void GLES2DecoderImpl::DoTexParameteriv(
5630 GLenum target
, GLenum pname
, const GLint
* params
) {
5631 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5635 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5639 texture_manager()->SetParameteri(
5640 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5643 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5644 if (!state_
.current_program
.get()) {
5645 // The program does not exist.
5647 GL_INVALID_OPERATION
, function_name
, "no program in use");
5650 if (!state_
.current_program
->InUse()) {
5652 GL_INVALID_OPERATION
, function_name
, "program not linked");
5658 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5659 GLint location
, const char* function_name
) {
5660 if (!CheckCurrentProgram(function_name
)) {
5663 return location
!= -1;
5666 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5667 GLint fake_location
,
5668 const char* function_name
,
5669 Program::UniformApiType api_type
,
5670 GLint
* real_location
,
5675 DCHECK(real_location
);
5677 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
5680 GLint array_index
= -1;
5681 const Program::UniformInfo
* info
=
5682 state_
.current_program
->GetUniformInfoByFakeLocation(
5683 fake_location
, real_location
, &array_index
);
5686 GL_INVALID_OPERATION
, function_name
, "unknown location");
5690 if ((api_type
& info
->accepts_api_type
) == 0) {
5692 GL_INVALID_OPERATION
, function_name
,
5693 "wrong uniform function for type");
5696 if (*count
> 1 && !info
->is_array
) {
5698 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
5701 *count
= std::min(info
->size
- array_index
, *count
);
5709 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
5712 GLint real_location
= -1;
5713 if (!PrepForSetUniformByLocation(fake_location
,
5715 Program::kUniform1i
,
5721 if (!state_
.current_program
->SetSamplers(
5722 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
5724 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
5727 glUniform1i(real_location
, v0
);
5730 void GLES2DecoderImpl::DoUniform1iv(
5731 GLint fake_location
, GLsizei count
, const GLint
*value
) {
5733 GLint real_location
= -1;
5734 if (!PrepForSetUniformByLocation(fake_location
,
5736 Program::kUniform1i
,
5742 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
5743 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
5744 if (!state_
.current_program
->SetSamplers(
5745 state_
.texture_units
.size(), fake_location
, count
, value
)) {
5747 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
5751 glUniform1iv(real_location
, count
, value
);
5754 void GLES2DecoderImpl::DoUniform1fv(
5755 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5757 GLint real_location
= -1;
5758 if (!PrepForSetUniformByLocation(fake_location
,
5760 Program::kUniform1f
,
5766 if (type
== GL_BOOL
) {
5767 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
5768 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5769 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5771 DoUniform1iv(real_location
, count
, temp
.get());
5773 glUniform1fv(real_location
, count
, value
);
5777 void GLES2DecoderImpl::DoUniform2fv(
5778 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5780 GLint real_location
= -1;
5781 if (!PrepForSetUniformByLocation(fake_location
,
5783 Program::kUniform2f
,
5789 if (type
== GL_BOOL_VEC2
) {
5790 GLsizei num_values
= count
* 2;
5791 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5792 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5793 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5795 glUniform2iv(real_location
, count
, temp
.get());
5797 glUniform2fv(real_location
, count
, value
);
5801 void GLES2DecoderImpl::DoUniform3fv(
5802 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5804 GLint real_location
= -1;
5805 if (!PrepForSetUniformByLocation(fake_location
,
5807 Program::kUniform3f
,
5813 if (type
== GL_BOOL_VEC3
) {
5814 GLsizei num_values
= count
* 3;
5815 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5816 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5817 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5819 glUniform3iv(real_location
, count
, temp
.get());
5821 glUniform3fv(real_location
, count
, value
);
5825 void GLES2DecoderImpl::DoUniform4fv(
5826 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5828 GLint real_location
= -1;
5829 if (!PrepForSetUniformByLocation(fake_location
,
5831 Program::kUniform4f
,
5837 if (type
== GL_BOOL_VEC4
) {
5838 GLsizei num_values
= count
* 4;
5839 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5840 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5841 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5843 glUniform4iv(real_location
, count
, temp
.get());
5845 glUniform4fv(real_location
, count
, value
);
5849 void GLES2DecoderImpl::DoUniform2iv(
5850 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5852 GLint real_location
= -1;
5853 if (!PrepForSetUniformByLocation(fake_location
,
5855 Program::kUniform2i
,
5861 glUniform2iv(real_location
, count
, value
);
5864 void GLES2DecoderImpl::DoUniform3iv(
5865 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5867 GLint real_location
= -1;
5868 if (!PrepForSetUniformByLocation(fake_location
,
5870 Program::kUniform3i
,
5876 glUniform3iv(real_location
, count
, value
);
5879 void GLES2DecoderImpl::DoUniform4iv(
5880 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5882 GLint real_location
= -1;
5883 if (!PrepForSetUniformByLocation(fake_location
,
5885 Program::kUniform4i
,
5891 glUniform4iv(real_location
, count
, value
);
5894 void GLES2DecoderImpl::DoUniformMatrix2fv(
5895 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5896 const GLfloat
* value
) {
5898 GLint real_location
= -1;
5899 if (!PrepForSetUniformByLocation(fake_location
,
5900 "glUniformMatrix2fv",
5901 Program::kUniformMatrix2f
,
5907 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
5910 void GLES2DecoderImpl::DoUniformMatrix3fv(
5911 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5912 const GLfloat
* value
) {
5914 GLint real_location
= -1;
5915 if (!PrepForSetUniformByLocation(fake_location
,
5916 "glUniformMatrix3fv",
5917 Program::kUniformMatrix3f
,
5923 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
5926 void GLES2DecoderImpl::DoUniformMatrix4fv(
5927 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5928 const GLfloat
* value
) {
5930 GLint real_location
= -1;
5931 if (!PrepForSetUniformByLocation(fake_location
,
5932 "glUniformMatrix4fv",
5933 Program::kUniformMatrix4f
,
5939 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
5942 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
5943 GLuint service_id
= 0;
5944 Program
* program
= NULL
;
5946 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
5950 if (!program
->IsValid()) {
5951 // Program was not linked successfully. (ie, glLinkProgram)
5953 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
5956 service_id
= program
->service_id();
5958 if (state_
.current_program
.get()) {
5959 program_manager()->UnuseProgram(shader_manager(),
5960 state_
.current_program
.get());
5962 state_
.current_program
= program
;
5963 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
5964 glUseProgram(service_id
);
5965 if (state_
.current_program
.get()) {
5966 program_manager()->UseProgram(state_
.current_program
.get());
5967 if (workarounds().clear_uniforms_before_first_program_use
)
5968 program_manager()->ClearUniforms(program
);
5972 void GLES2DecoderImpl::RenderWarning(
5973 const char* filename
, int line
, const std::string
& msg
) {
5974 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
5977 void GLES2DecoderImpl::PerformanceWarning(
5978 const char* filename
, int line
, const std::string
& msg
) {
5979 logger_
.LogMessage(filename
, line
,
5980 std::string("PERFORMANCE WARNING: ") + msg
);
5983 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5984 Texture
* texture
, GLenum textarget
) {
5985 // Image is already in use if texture is attached to a framebuffer.
5986 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
5987 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
5989 ScopedGLErrorSuppressor
suppressor(
5990 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5992 glBindTexture(textarget
, texture
->service_id());
5993 image
->WillUseTexImage();
5994 RestoreCurrentTextureBindings(&state_
, textarget
);
5999 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6000 Texture
* texture
, GLenum textarget
) {
6001 // Image is still in use if texture is attached to a framebuffer.
6002 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6003 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6005 ScopedGLErrorSuppressor
suppressor(
6006 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6008 glBindTexture(textarget
, texture
->service_id());
6009 image
->DidUseTexImage();
6010 RestoreCurrentTextureBindings(&state_
, textarget
);
6015 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6016 DCHECK(state_
.current_program
.get());
6017 if (!texture_manager()->HaveUnrenderableTextures() &&
6018 !texture_manager()->HaveImages()) {
6022 bool textures_set
= false;
6023 const Program::SamplerIndices
& sampler_indices
=
6024 state_
.current_program
->sampler_indices();
6025 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6026 const Program::UniformInfo
* uniform_info
=
6027 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6028 DCHECK(uniform_info
);
6029 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6030 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6031 if (texture_unit_index
< state_
.texture_units
.size()) {
6032 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6033 TextureRef
* texture_ref
=
6034 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6035 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6036 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6037 textures_set
= true;
6038 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6041 texture_manager()->black_texture_id(uniform_info
->type
));
6042 LOCAL_RENDER_WARNING(
6043 std::string("texture bound to texture unit ") +
6044 base::IntToString(texture_unit_index
) +
6045 " is not renderable. It maybe non-power-of-2 and have"
6046 " incompatible texture filtering or is not"
6047 " 'texture complete'");
6051 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6052 Texture
* texture
= texture_ref
->texture();
6053 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6054 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6055 ScopedGLErrorSuppressor
suppressor(
6056 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6057 textures_set
= true;
6058 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6059 image
->WillUseTexImage();
6064 // else: should this be an error?
6067 return !textures_set
;
6070 void GLES2DecoderImpl::RestoreStateForTextures() {
6071 DCHECK(state_
.current_program
.get());
6072 const Program::SamplerIndices
& sampler_indices
=
6073 state_
.current_program
->sampler_indices();
6074 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6075 const Program::UniformInfo
* uniform_info
=
6076 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6077 DCHECK(uniform_info
);
6078 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6079 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6080 if (texture_unit_index
< state_
.texture_units
.size()) {
6081 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6082 TextureRef
* texture_ref
=
6083 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6084 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6085 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6086 // Get the texture_ref info that was previously bound here.
6087 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6088 ? texture_unit
.bound_texture_2d
.get()
6089 : texture_unit
.bound_texture_cube_map
.get();
6090 glBindTexture(texture_unit
.bind_target
,
6091 texture_ref
? texture_ref
->service_id() : 0);
6095 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6096 Texture
* texture
= texture_ref
->texture();
6097 gfx::GLImage
* image
=
6098 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6099 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6100 ScopedGLErrorSuppressor
suppressor(
6101 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6102 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6103 image
->DidUseTexImage();
6110 // Set the active texture back to whatever the user had it as.
6111 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6114 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6115 // Only check if there are some uncleared textures.
6116 if (!texture_manager()->HaveUnsafeTextures()) {
6120 // 1: Check all textures we are about to render with.
6121 if (state_
.current_program
.get()) {
6122 const Program::SamplerIndices
& sampler_indices
=
6123 state_
.current_program
->sampler_indices();
6124 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6125 const Program::UniformInfo
* uniform_info
=
6126 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6127 DCHECK(uniform_info
);
6128 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6129 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6130 if (texture_unit_index
< state_
.texture_units
.size()) {
6131 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6132 TextureRef
* texture_ref
=
6133 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6134 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6135 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6146 bool GLES2DecoderImpl::IsDrawValid(
6147 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
) {
6148 // NOTE: We specifically do not check current_program->IsValid() because
6149 // it could never be invalid since glUseProgram would have failed. While
6150 // glLinkProgram could later mark the program as invalid the previous
6151 // valid program will still function if it is still the current program.
6152 if (!state_
.current_program
.get()) {
6153 // The program does not exist.
6154 // But GL says no ERROR.
6155 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6159 return state_
.vertex_attrib_manager
6160 ->ValidateBindings(function_name
,
6162 feature_info_
.get(),
6163 state_
.current_program
.get(),
6164 max_vertex_accessed
,
6168 bool GLES2DecoderImpl::SimulateAttrib0(
6169 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6173 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6176 const VertexAttrib
* attrib
=
6177 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6178 // If it's enabled or it's not used then we don't need to do anything.
6179 bool attrib_0_used
=
6180 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6181 if (attrib
->enabled() && attrib_0_used
) {
6185 // Make a buffer with a single repeated vec4 value enough to
6186 // simulate the constant value that is supposed to be here.
6187 // This is required to emulate GLES2 on GL.
6188 GLuint num_vertices
= max_vertex_accessed
+ 1;
6189 uint32 size_needed
= 0;
6191 if (num_vertices
== 0 ||
6192 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6193 size_needed
> 0x7FFFFFFFU
) {
6194 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6198 LOCAL_PERFORMANCE_WARNING(
6199 "Attribute 0 is disabled. This has signficant performance penalty");
6201 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6202 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6204 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6206 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6207 GLenum error
= glGetError();
6208 if (error
!= GL_NO_ERROR
) {
6210 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6215 const Vec4
& value
= state_
.attrib_values
[0];
6218 (!attrib_0_buffer_matches_value_
||
6219 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6220 value
.v
[1] != attrib_0_value_
.v
[1] ||
6221 value
.v
[2] != attrib_0_value_
.v
[2] ||
6222 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6223 std::vector
<Vec4
> temp(num_vertices
, value
);
6224 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6225 attrib_0_buffer_matches_value_
= true;
6226 attrib_0_value_
= value
;
6227 attrib_0_size_
= size_needed
;
6230 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6232 if (attrib
->divisor())
6233 glVertexAttribDivisorANGLE(0, 0);
6239 void GLES2DecoderImpl::RestoreStateForAttrib(
6240 GLuint attrib_index
, bool restore_array_binding
) {
6241 const VertexAttrib
* attrib
=
6242 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6243 if (restore_array_binding
) {
6244 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6245 Buffer
* buffer
= attrib
->buffer();
6246 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6247 glVertexAttribPointer(
6248 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6249 attrib
->gl_stride(), ptr
);
6251 if (attrib
->divisor())
6252 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6254 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6255 state_
.bound_array_buffer
->service_id() : 0);
6257 // Never touch vertex attribute 0's state (in particular, never
6258 // disable it) when running on desktop GL because it will never be
6260 if (attrib_index
!= 0 ||
6261 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6262 if (attrib
->enabled()) {
6263 glEnableVertexAttribArray(attrib_index
);
6265 glDisableVertexAttribArray(attrib_index
);
6270 bool GLES2DecoderImpl::SimulateFixedAttribs(
6271 const char* function_name
,
6272 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6275 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6278 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6282 LOCAL_PERFORMANCE_WARNING(
6283 "GL_FIXED attributes have a signficant performance penalty");
6285 // NOTE: we could be smart and try to check if a buffer is used
6286 // twice in 2 different attribs, find the overlapping parts and therefore
6287 // duplicate the minimum amount of data but this whole code path is not meant
6288 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6289 // tests so we just add to the buffer attrib used.
6291 GLuint elements_needed
= 0;
6292 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6293 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6294 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6295 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6296 const VertexAttrib
* attrib
= *it
;
6297 const Program::VertexAttrib
* attrib_info
=
6298 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6299 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6300 max_vertex_accessed
);
6301 GLuint num_vertices
= max_accessed
+ 1;
6302 if (num_vertices
== 0) {
6304 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6308 attrib
->CanAccess(max_accessed
) &&
6309 attrib
->type() == GL_FIXED
) {
6310 uint32 elements_used
= 0;
6311 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6312 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6314 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6320 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6321 uint32 size_needed
= 0;
6322 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6323 size_needed
> 0x7FFFFFFFU
) {
6325 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6331 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6332 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6333 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6334 GLenum error
= glGetError();
6335 if (error
!= GL_NO_ERROR
) {
6337 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6342 // Copy the elements and convert to float
6343 GLintptr offset
= 0;
6344 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6345 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6346 const VertexAttrib
* attrib
= *it
;
6347 const Program::VertexAttrib
* attrib_info
=
6348 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6349 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6350 max_vertex_accessed
);
6351 GLuint num_vertices
= max_accessed
+ 1;
6352 if (num_vertices
== 0) {
6354 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6358 attrib
->CanAccess(max_accessed
) &&
6359 attrib
->type() == GL_FIXED
) {
6360 int num_elements
= attrib
->size() * kSizeOfFloat
;
6361 int size
= num_elements
* num_vertices
;
6362 scoped_ptr
<float[]> data(new float[size
]);
6363 const int32
* src
= reinterpret_cast<const int32
*>(
6364 attrib
->buffer()->GetRange(attrib
->offset(), size
));
6365 const int32
* end
= src
+ num_elements
;
6366 float* dst
= data
.get();
6367 while (src
!= end
) {
6368 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6370 glBufferSubData(GL_ARRAY_BUFFER
, offset
, size
, data
.get());
6371 glVertexAttribPointer(
6372 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6373 reinterpret_cast<GLvoid
*>(offset
));
6381 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6382 // There's no need to call glVertexAttribPointer because we shadow all the
6383 // settings and passing GL_FIXED to it will not work.
6386 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6390 error::Error
GLES2DecoderImpl::DoDrawArrays(
6391 const char* function_name
,
6396 GLsizei primcount
) {
6397 error::Error error
= WillAccessBoundFramebufferForDraw();
6398 if (error
!= error::kNoError
)
6400 if (!validators_
->draw_mode
.IsValid(mode
)) {
6401 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6402 return error::kNoError
;
6405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6406 return error::kNoError
;
6408 if (primcount
< 0) {
6409 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6410 return error::kNoError
;
6412 if (!CheckBoundFramebuffersValid(function_name
)) {
6413 return error::kNoError
;
6415 // We have to check this here because the prototype for glDrawArrays
6416 // is GLint not GLsizei.
6418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6419 return error::kNoError
;
6422 if (count
== 0 || (instanced
&& primcount
== 0)) {
6423 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6424 return error::kNoError
;
6427 GLuint max_vertex_accessed
= first
+ count
- 1;
6428 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
6429 if (!ClearUnclearedTextures()) {
6430 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6431 return error::kNoError
;
6433 bool simulated_attrib_0
= false;
6434 if (!SimulateAttrib0(
6435 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6436 return error::kNoError
;
6438 bool simulated_fixed_attribs
= false;
6439 if (SimulateFixedAttribs(
6440 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6442 bool textures_set
= !PrepareTexturesForRender();
6444 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6446 glDrawArrays(mode
, first
, count
);
6448 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6451 RestoreStateForTextures();
6453 if (simulated_fixed_attribs
) {
6454 RestoreStateForSimulatedFixedAttribs();
6457 if (simulated_attrib_0
) {
6458 // We don't have to restore attrib 0 generic data at the end of this
6459 // function even if it is simulated. This is because we will simulate
6460 // it in each draw call, and attrib 0 generic data queries use cached
6461 // values instead of passing down to the underlying driver.
6462 RestoreStateForAttrib(0, false);
6465 return error::kNoError
;
6468 error::Error
GLES2DecoderImpl::HandleDrawArrays(
6469 uint32 immediate_data_size
, const cmds::DrawArrays
& c
) {
6470 return DoDrawArrays("glDrawArrays",
6472 static_cast<GLenum
>(c
.mode
),
6473 static_cast<GLint
>(c
.first
),
6474 static_cast<GLsizei
>(c
.count
),
6478 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6479 uint32 immediate_data_size
, const cmds::DrawArraysInstancedANGLE
& c
) {
6480 if (!features().angle_instanced_arrays
) {
6482 GL_INVALID_OPERATION
,
6483 "glDrawArraysInstancedANGLE", "function not available");
6484 return error::kNoError
;
6486 return DoDrawArrays("glDrawArraysIntancedANGLE",
6488 static_cast<GLenum
>(c
.mode
),
6489 static_cast<GLint
>(c
.first
),
6490 static_cast<GLsizei
>(c
.count
),
6491 static_cast<GLsizei
>(c
.primcount
));
6494 error::Error
GLES2DecoderImpl::DoDrawElements(
6495 const char* function_name
,
6501 GLsizei primcount
) {
6502 error::Error error
= WillAccessBoundFramebufferForDraw();
6503 if (error
!= error::kNoError
)
6505 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6507 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6508 return error::kNoError
;
6512 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6513 return error::kNoError
;
6516 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6517 return error::kNoError
;
6519 if (!validators_
->draw_mode
.IsValid(mode
)) {
6520 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6521 return error::kNoError
;
6523 if (!validators_
->index_type
.IsValid(type
)) {
6524 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6525 return error::kNoError
;
6527 if (primcount
< 0) {
6528 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6529 return error::kNoError
;
6532 if (!CheckBoundFramebuffersValid(function_name
)) {
6533 return error::kNoError
;
6536 if (count
== 0 || (instanced
&& primcount
== 0)) {
6537 return error::kNoError
;
6540 GLuint max_vertex_accessed
;
6541 Buffer
* element_array_buffer
=
6542 state_
.vertex_attrib_manager
->element_array_buffer();
6544 if (!element_array_buffer
->GetMaxValueForRange(
6545 offset
, count
, type
, &max_vertex_accessed
)) {
6547 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6548 return error::kNoError
;
6551 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
6552 if (!ClearUnclearedTextures()) {
6553 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6554 return error::kNoError
;
6556 bool simulated_attrib_0
= false;
6557 if (!SimulateAttrib0(
6558 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6559 return error::kNoError
;
6561 bool simulated_fixed_attribs
= false;
6562 if (SimulateFixedAttribs(
6563 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6565 bool textures_set
= !PrepareTexturesForRender();
6567 // TODO(gman): Refactor to hide these details in BufferManager or
6568 // VertexAttribManager.
6569 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6570 bool used_client_side_array
= false;
6571 if (element_array_buffer
->IsClientSideArray()) {
6572 used_client_side_array
= true;
6573 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6574 indices
= element_array_buffer
->GetRange(offset
, 0);
6577 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6579 glDrawElements(mode
, count
, type
, indices
);
6581 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6584 if (used_client_side_array
) {
6585 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6586 element_array_buffer
->service_id());
6590 RestoreStateForTextures();
6592 if (simulated_fixed_attribs
) {
6593 RestoreStateForSimulatedFixedAttribs();
6596 if (simulated_attrib_0
) {
6597 // We don't have to restore attrib 0 generic data at the end of this
6598 // function even if it is simulated. This is because we will simulate
6599 // it in each draw call, and attrib 0 generic data queries use cached
6600 // values instead of passing down to the underlying driver.
6601 RestoreStateForAttrib(0, false);
6604 return error::kNoError
;
6607 error::Error
GLES2DecoderImpl::HandleDrawElements(
6608 uint32 immediate_data_size
, const cmds::DrawElements
& c
) {
6609 return DoDrawElements("glDrawElements",
6611 static_cast<GLenum
>(c
.mode
),
6612 static_cast<GLsizei
>(c
.count
),
6613 static_cast<GLenum
>(c
.type
),
6614 static_cast<int32
>(c
.index_offset
),
6618 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6619 uint32 immediate_data_size
, const cmds::DrawElementsInstancedANGLE
& c
) {
6620 if (!features().angle_instanced_arrays
) {
6622 GL_INVALID_OPERATION
,
6623 "glDrawElementsInstancedANGLE", "function not available");
6624 return error::kNoError
;
6626 return DoDrawElements("glDrawElementsInstancedANGLE",
6628 static_cast<GLenum
>(c
.mode
),
6629 static_cast<GLsizei
>(c
.count
),
6630 static_cast<GLenum
>(c
.type
),
6631 static_cast<int32
>(c
.index_offset
),
6632 static_cast<GLsizei
>(c
.primcount
));
6635 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6636 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
6637 GLuint max_vertex_accessed
= 0;
6638 Buffer
* buffer
= GetBuffer(buffer_id
);
6640 // TODO(gman): Should this be a GL error or a command buffer error?
6642 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6644 if (!buffer
->GetMaxValueForRange(
6645 offset
, count
, type
, &max_vertex_accessed
)) {
6646 // TODO(gman): Should this be a GL error or a command buffer error?
6648 GL_INVALID_OPERATION
,
6649 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6652 return max_vertex_accessed
;
6655 // Calls glShaderSource for the various versions of the ShaderSource command.
6656 // Assumes that data / data_size points to a piece of memory that is in range
6657 // of whatever context it came from (shared memory, immediate memory, bucket
6659 error::Error
GLES2DecoderImpl::ShaderSourceHelper(
6660 GLuint client_id
, const char* data
, uint32 data_size
) {
6661 std::string
str(data
, data
+ data_size
);
6662 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
6664 return error::kNoError
;
6666 // Note: We don't actually call glShaderSource here. We wait until
6667 // the call to glCompileShader.
6668 shader
->UpdateSource(str
.c_str());
6669 return error::kNoError
;
6672 error::Error
GLES2DecoderImpl::HandleShaderSourceBucket(
6673 uint32 immediate_data_size
, const cmds::ShaderSourceBucket
& c
) {
6674 Bucket
* bucket
= GetBucket(c
.data_bucket_id
);
6675 if (!bucket
|| bucket
->size() == 0) {
6676 return error::kInvalidArguments
;
6678 return ShaderSourceHelper(
6679 c
.shader
, bucket
->GetDataAs
<const char*>(0, bucket
->size() - 1),
6680 bucket
->size() - 1);
6683 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
6684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6685 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
6689 ShaderTranslator
* translator
= NULL
;
6690 if (use_shader_translator_
) {
6691 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
6692 vertex_translator_
.get() : fragment_translator_
.get();
6695 program_manager()->DoCompileShader(
6698 feature_info_
->feature_flags().angle_translated_shader_source
?
6699 ProgramManager::kANGLE
: ProgramManager::kGL
);
6702 void GLES2DecoderImpl::DoGetShaderiv(
6703 GLuint shader_id
, GLenum pname
, GLint
* params
) {
6704 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
6709 case GL_SHADER_SOURCE_LENGTH
:
6710 *params
= shader
->source() ? shader
->source()->size() + 1 : 0;
6712 case GL_COMPILE_STATUS
:
6713 *params
= compile_shader_always_succeeds_
? true : shader
->IsValid();
6715 case GL_INFO_LOG_LENGTH
:
6716 *params
= shader
->log_info() ? shader
->log_info()->size() + 1 : 0;
6718 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
6719 *params
= shader
->translated_source() ?
6720 shader
->translated_source()->size() + 1 : 0;
6725 glGetShaderiv(shader
->service_id(), pname
, params
);
6728 error::Error
GLES2DecoderImpl::HandleGetShaderSource(
6729 uint32 immediate_data_size
, const cmds::GetShaderSource
& c
) {
6730 GLuint shader_id
= c
.shader
;
6731 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6732 Bucket
* bucket
= CreateBucket(bucket_id
);
6733 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
6734 if (!shader
|| !shader
->source()) {
6736 return error::kNoError
;
6738 bucket
->SetFromString(shader
->source()->c_str());
6739 return error::kNoError
;
6742 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6743 uint32 immediate_data_size
,
6744 const cmds::GetTranslatedShaderSourceANGLE
& c
) {
6745 GLuint shader_id
= c
.shader
;
6746 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6747 Bucket
* bucket
= CreateBucket(bucket_id
);
6748 Shader
* shader
= GetShaderInfoNotProgram(
6749 shader_id
, "glGetTranslatedShaderSourceANGLE");
6752 return error::kNoError
;
6755 bucket
->SetFromString(shader
->translated_source() ?
6756 shader
->translated_source()->c_str() : NULL
);
6757 return error::kNoError
;
6760 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
6761 uint32 immediate_data_size
, const cmds::GetProgramInfoLog
& c
) {
6762 GLuint program_id
= c
.program
;
6763 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6764 Bucket
* bucket
= CreateBucket(bucket_id
);
6765 Program
* program
= GetProgramInfoNotShader(
6766 program_id
, "glGetProgramInfoLog");
6767 if (!program
|| !program
->log_info()) {
6768 bucket
->SetFromString("");
6769 return error::kNoError
;
6771 bucket
->SetFromString(program
->log_info()->c_str());
6772 return error::kNoError
;
6775 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
6776 uint32 immediate_data_size
, const cmds::GetShaderInfoLog
& c
) {
6777 GLuint shader_id
= c
.shader
;
6778 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6779 Bucket
* bucket
= CreateBucket(bucket_id
);
6780 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
6781 if (!shader
|| !shader
->log_info()) {
6782 bucket
->SetFromString("");
6783 return error::kNoError
;
6785 bucket
->SetFromString(shader
->log_info()->c_str());
6786 return error::kNoError
;
6789 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
6790 return state_
.GetEnabled(cap
);
6793 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
6794 const Buffer
* buffer
= GetBuffer(client_id
);
6795 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
6798 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
6799 const Framebuffer
* framebuffer
=
6800 GetFramebuffer(client_id
);
6801 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
6804 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
6805 // IsProgram is true for programs as soon as they are created, until they are
6806 // deleted and no longer in use.
6807 const Program
* program
= GetProgram(client_id
);
6808 return program
!= NULL
&& !program
->IsDeleted();
6811 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
6812 const Renderbuffer
* renderbuffer
=
6813 GetRenderbuffer(client_id
);
6814 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
6817 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
6818 // IsShader is true for shaders as soon as they are created, until they
6819 // are deleted and not attached to any programs.
6820 const Shader
* shader
= GetShader(client_id
);
6821 return shader
!= NULL
&& !shader
->IsDeleted();
6824 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
6825 const TextureRef
* texture_ref
= GetTexture(client_id
);
6826 return texture_ref
&& texture_ref
->texture()->IsValid();
6829 void GLES2DecoderImpl::DoAttachShader(
6830 GLuint program_client_id
, GLint shader_client_id
) {
6831 Program
* program
= GetProgramInfoNotShader(
6832 program_client_id
, "glAttachShader");
6836 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
6840 if (!program
->AttachShader(shader_manager(), shader
)) {
6842 GL_INVALID_OPERATION
,
6844 "can not attach more than one shader of the same type.");
6847 glAttachShader(program
->service_id(), shader
->service_id());
6850 void GLES2DecoderImpl::DoDetachShader(
6851 GLuint program_client_id
, GLint shader_client_id
) {
6852 Program
* program
= GetProgramInfoNotShader(
6853 program_client_id
, "glDetachShader");
6857 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
6861 if (!program
->DetachShader(shader_manager(), shader
)) {
6863 GL_INVALID_OPERATION
,
6864 "glDetachShader", "shader not attached to program");
6867 glDetachShader(program
->service_id(), shader
->service_id());
6870 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
6871 Program
* program
= GetProgramInfoNotShader(
6872 program_client_id
, "glValidateProgram");
6876 program
->Validate();
6879 void GLES2DecoderImpl::GetVertexAttribHelper(
6880 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
6882 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
6883 Buffer
* buffer
= attrib
->buffer();
6884 if (buffer
&& !buffer
->IsDeleted()) {
6886 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
6887 *params
= client_id
;
6891 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
6892 *params
= attrib
->enabled();
6894 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
6895 *params
= attrib
->size();
6897 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
6898 *params
= attrib
->gl_stride();
6900 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
6901 *params
= attrib
->type();
6903 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
6904 *params
= attrib
->normalized();
6906 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
6907 *params
= attrib
->divisor();
6915 void GLES2DecoderImpl::DoGetTexParameterfv(
6916 GLenum target
, GLenum pname
, GLfloat
* params
) {
6917 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
6918 glGetTexParameterfv(target
, pname
, params
);
6921 void GLES2DecoderImpl::DoGetTexParameteriv(
6922 GLenum target
, GLenum pname
, GLint
* params
) {
6923 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
6924 glGetTexParameteriv(target
, pname
, params
);
6927 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6928 GLenum target
, GLenum pname
) {
6929 if (!workarounds().init_texture_max_anisotropy
)
6931 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
6932 !validators_
->texture_parameter
.IsValid(pname
)) {
6936 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
6940 GL_INVALID_OPERATION
,
6941 "glGetTexParamter{fi}v", "unknown texture for target");
6944 Texture
* texture
= texture_ref
->texture();
6945 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
6948 void GLES2DecoderImpl::DoGetVertexAttribfv(
6949 GLuint index
, GLenum pname
, GLfloat
* params
) {
6950 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
6953 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
6957 case GL_CURRENT_VERTEX_ATTRIB
: {
6958 const Vec4
& value
= state_
.attrib_values
[index
];
6959 params
[0] = value
.v
[0];
6960 params
[1] = value
.v
[1];
6961 params
[2] = value
.v
[2];
6962 params
[3] = value
.v
[3];
6967 GetVertexAttribHelper(attrib
, pname
, &value
);
6968 *params
= static_cast<GLfloat
>(value
);
6974 void GLES2DecoderImpl::DoGetVertexAttribiv(
6975 GLuint index
, GLenum pname
, GLint
* params
) {
6976 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
6979 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
6983 case GL_CURRENT_VERTEX_ATTRIB
: {
6984 const Vec4
& value
= state_
.attrib_values
[index
];
6985 params
[0] = static_cast<GLint
>(value
.v
[0]);
6986 params
[1] = static_cast<GLint
>(value
.v
[1]);
6987 params
[2] = static_cast<GLint
>(value
.v
[2]);
6988 params
[3] = static_cast<GLint
>(value
.v
[3]);
6992 GetVertexAttribHelper(attrib
, pname
, params
);
6997 bool GLES2DecoderImpl::SetVertexAttribValue(
6998 const char* function_name
, GLuint index
, const GLfloat
* value
) {
6999 if (index
>= state_
.attrib_values
.size()) {
7000 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7003 Vec4
& v
= state_
.attrib_values
[index
];
7011 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7012 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7013 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7014 glVertexAttrib1f(index
, v0
);
7018 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7019 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7020 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7021 glVertexAttrib2f(index
, v0
, v1
);
7025 void GLES2DecoderImpl::DoVertexAttrib3f(
7026 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7027 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7028 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7029 glVertexAttrib3f(index
, v0
, v1
, v2
);
7033 void GLES2DecoderImpl::DoVertexAttrib4f(
7034 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7035 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7036 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7037 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7041 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7042 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7043 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7044 glVertexAttrib1fv(index
, v
);
7048 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7049 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7050 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7051 glVertexAttrib2fv(index
, v
);
7055 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7056 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7057 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7058 glVertexAttrib3fv(index
, v
);
7062 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7063 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7064 glVertexAttrib4fv(index
, v
);
7068 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7069 uint32 immediate_data_size
, const cmds::VertexAttribPointer
& c
) {
7071 if (!state_
.bound_array_buffer
.get() ||
7072 state_
.bound_array_buffer
->IsDeleted()) {
7073 if (state_
.vertex_attrib_manager
.get() ==
7074 state_
.default_vertex_attrib_manager
.get()) {
7076 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7077 return error::kNoError
;
7078 } else if (c
.offset
!= 0) {
7081 "glVertexAttribPointer", "client side arrays are not allowed");
7082 return error::kNoError
;
7086 GLuint indx
= c
.indx
;
7087 GLint size
= c
.size
;
7088 GLenum type
= c
.type
;
7089 GLboolean normalized
= c
.normalized
;
7090 GLsizei stride
= c
.stride
;
7091 GLsizei offset
= c
.offset
;
7092 const void* ptr
= reinterpret_cast<const void*>(offset
);
7093 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7094 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7095 return error::kNoError
;
7097 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7099 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7100 return error::kNoError
;
7102 if (indx
>= group_
->max_vertex_attribs()) {
7104 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7105 return error::kNoError
;
7109 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7110 return error::kNoError
;
7114 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7115 return error::kNoError
;
7119 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7120 return error::kNoError
;
7122 GLsizei component_size
=
7123 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7124 if (offset
% component_size
> 0) {
7126 GL_INVALID_OPERATION
,
7127 "glVertexAttribPointer", "offset not valid for type");
7128 return error::kNoError
;
7130 if (stride
% component_size
> 0) {
7132 GL_INVALID_OPERATION
,
7133 "glVertexAttribPointer", "stride not valid for type");
7134 return error::kNoError
;
7136 state_
.vertex_attrib_manager
7137 ->SetAttribInfo(indx
,
7138 state_
.bound_array_buffer
.get(),
7143 stride
!= 0 ? stride
: component_size
* size
,
7145 if (type
!= GL_FIXED
) {
7146 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7148 return error::kNoError
;
7151 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7153 state_
.viewport_x
= x
;
7154 state_
.viewport_y
= y
;
7155 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7156 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7157 glViewport(x
, y
, width
, height
);
7160 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7161 uint32 immediate_data_size
, const cmds::VertexAttribDivisorANGLE
& c
) {
7162 if (!features().angle_instanced_arrays
) {
7164 GL_INVALID_OPERATION
,
7165 "glVertexAttribDivisorANGLE", "function not available");
7166 return error::kNoError
;
7168 GLuint index
= c
.index
;
7169 GLuint divisor
= c
.divisor
;
7170 if (index
>= group_
->max_vertex_attribs()) {
7173 "glVertexAttribDivisorANGLE", "index out of range");
7174 return error::kNoError
;
7177 state_
.vertex_attrib_manager
->SetDivisor(
7180 glVertexAttribDivisorANGLE(index
, divisor
);
7181 return error::kNoError
;
7184 template <typename pixel_data_type
>
7185 static void WriteAlphaData(
7186 void *pixels
, uint32 row_count
, uint32 channel_count
,
7187 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7188 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7189 DCHECK_GT(channel_count
, 0U);
7190 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7191 uint32 unpadded_row_size_in_elements
=
7192 unpadded_row_size
/ sizeof(pixel_data_type
);
7193 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7194 uint32 padded_row_size_in_elements
=
7195 padded_row_size
/ sizeof(pixel_data_type
);
7196 pixel_data_type
* dst
=
7197 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7198 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7199 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7200 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7203 dst
+= padded_row_size_in_elements
;
7207 void GLES2DecoderImpl::FinishReadPixels(
7208 const cmds::ReadPixels
& c
,
7210 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7211 GLsizei width
= c
.width
;
7212 GLsizei height
= c
.height
;
7213 GLenum format
= c
.format
;
7214 GLenum type
= c
.type
;
7215 typedef cmds::ReadPixels::Result Result
;
7217 Result
* result
= NULL
;
7218 if (c
.result_shm_id
!= 0) {
7219 result
= GetSharedMemoryAs
<Result
*>(
7220 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7223 glDeleteBuffersARB(1, &buffer
);
7228 GLES2Util::ComputeImageDataSizes(
7229 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7231 void* pixels
= GetSharedMemoryAs
<void*>(
7232 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7235 glDeleteBuffersARB(1, &buffer
);
7241 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7243 if (features().map_buffer_range
) {
7244 data
= glMapBufferRange(
7245 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7247 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7249 memcpy(pixels
, data
, pixels_size
);
7250 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7251 // have to restore the state.
7252 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7253 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7254 glDeleteBuffersARB(1, &buffer
);
7257 if (result
!= NULL
) {
7261 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7262 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7263 if ((channels_exist
& 0x0008) == 0 &&
7264 workarounds().clear_alpha_in_readpixels
) {
7265 // Set the alpha to 255 because some drivers are buggy in this regard.
7268 uint32 unpadded_row_size
;
7269 uint32 padded_row_size
;
7270 if (!GLES2Util::ComputeImageDataSizes(
7271 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7272 &unpadded_row_size
, &padded_row_size
)) {
7276 uint32 channel_count
= 0;
7277 uint32 alpha_channel
= 0;
7290 if (channel_count
> 0) {
7292 case GL_UNSIGNED_BYTE
:
7293 WriteAlphaData
<uint8
>(
7294 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7295 padded_row_size
, 0xFF);
7298 WriteAlphaData
<float>(
7299 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7300 padded_row_size
, 1.0f
);
7303 WriteAlphaData
<uint16
>(
7304 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7305 padded_row_size
, 0x3C00);
7313 error::Error
GLES2DecoderImpl::HandleReadPixels(
7314 uint32 immediate_data_size
, const cmds::ReadPixels
& c
) {
7315 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7316 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7317 if (fbo_error
!= error::kNoError
)
7321 GLsizei width
= c
.width
;
7322 GLsizei height
= c
.height
;
7323 GLenum format
= c
.format
;
7324 GLenum type
= c
.type
;
7325 GLboolean async
= c
.async
;
7326 if (width
< 0 || height
< 0) {
7327 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7328 return error::kNoError
;
7330 typedef cmds::ReadPixels::Result Result
;
7332 if (!GLES2Util::ComputeImageDataSizes(
7333 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7335 return error::kOutOfBounds
;
7337 void* pixels
= GetSharedMemoryAs
<void*>(
7338 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7340 return error::kOutOfBounds
;
7342 Result
* result
= NULL
;
7343 if (c
.result_shm_id
!= 0) {
7344 result
= GetSharedMemoryAs
<Result
*>(
7345 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7347 return error::kOutOfBounds
;
7351 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7352 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7353 return error::kNoError
;
7355 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7356 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7357 return error::kNoError
;
7359 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7360 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7361 // format and type are acceptable enums but not guaranteed to be supported
7362 // for this framebuffer. Have to ask gl if they are valid.
7363 GLint preferred_format
= 0;
7364 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7365 GLint preferred_type
= 0;
7366 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7367 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7368 type
!= static_cast<GLenum
>(preferred_type
)) {
7370 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7371 "with the current read framebuffer");
7372 return error::kNoError
;
7375 if (width
== 0 || height
== 0) {
7376 return error::kNoError
;
7379 // Get the size of the current fbo or backbuffer.
7380 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7384 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7386 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7387 return error::kNoError
;
7390 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7391 return error::kNoError
;
7394 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7396 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7398 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7399 // The user requested an out of range area. Get the results 1 line
7402 uint32 unpadded_row_size
;
7403 uint32 padded_row_size
;
7404 if (!GLES2Util::ComputeImageDataSizes(
7405 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7406 &unpadded_row_size
, &padded_row_size
)) {
7408 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7409 return error::kNoError
;
7412 GLint dest_x_offset
= std::max(-x
, 0);
7413 uint32 dest_row_offset
;
7414 if (!GLES2Util::ComputeImageDataSizes(
7415 dest_x_offset
, 1, format
, type
, state_
.pack_alignment
, &dest_row_offset
,
7418 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7419 return error::kNoError
;
7422 // Copy each row into the larger dest rect.
7423 int8
* dst
= static_cast<int8
*>(pixels
);
7424 GLint read_x
= std::max(0, x
);
7425 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7426 GLint read_width
= read_end_x
- read_x
;
7427 for (GLint yy
= 0; yy
< height
; ++yy
) {
7431 memset(dst
, 0, unpadded_row_size
);
7433 // If the row is in range, copy it.
7434 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7436 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7438 dst
+= padded_row_size
;
7441 if (async
&& features().use_async_readpixels
) {
7443 glGenBuffersARB(1, &buffer
);
7444 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7445 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, GL_STREAM_READ
);
7446 GLenum error
= glGetError();
7447 if (error
== GL_NO_ERROR
) {
7448 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7449 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7450 new FenceCallback()));
7451 WaitForReadPixels(base::Bind(
7452 &GLES2DecoderImpl::FinishReadPixels
,
7453 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7454 <GLES2DecoderImpl
>(this),
7456 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7457 return error::kNoError
;
7459 // On error, unbind pack buffer and fall through to sync readpixels
7460 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7463 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7465 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7466 if (error
== GL_NO_ERROR
) {
7467 if (result
!= NULL
) {
7470 FinishReadPixels(c
, 0);
7473 return error::kNoError
;
7476 error::Error
GLES2DecoderImpl::HandlePixelStorei(
7477 uint32 immediate_data_size
, const cmds::PixelStorei
& c
) {
7478 GLenum pname
= c
.pname
;
7479 GLenum param
= c
.param
;
7480 if (!validators_
->pixel_store
.IsValid(pname
)) {
7481 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7482 return error::kNoError
;
7485 case GL_PACK_ALIGNMENT
:
7486 case GL_UNPACK_ALIGNMENT
:
7487 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7489 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7490 return error::kNoError
;
7493 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7494 unpack_flip_y_
= (param
!= 0);
7495 return error::kNoError
;
7496 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7497 unpack_premultiply_alpha_
= (param
!= 0);
7498 return error::kNoError
;
7499 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7500 unpack_unpremultiply_alpha_
= (param
!= 0);
7501 return error::kNoError
;
7505 glPixelStorei(pname
, param
);
7507 case GL_PACK_ALIGNMENT
:
7508 state_
.pack_alignment
= param
;
7510 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
7511 state_
.pack_reverse_row_order
= (param
!= 0);
7513 case GL_UNPACK_ALIGNMENT
:
7514 state_
.unpack_alignment
= param
;
7517 // Validation should have prevented us from getting here.
7521 return error::kNoError
;
7524 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7525 uint32 immediate_data_size
, const cmds::PostSubBufferCHROMIUM
& c
) {
7526 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7528 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7530 if (!supports_post_sub_buffer_
) {
7532 GL_INVALID_OPERATION
,
7533 "glPostSubBufferCHROMIUM", "command not supported by surface");
7534 return error::kNoError
;
7537 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7540 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
7541 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
7542 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
7543 is_offscreen
? offscreen_size_
: surface_
->GetSize());
7545 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
7546 return error::kNoError
;
7548 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
7549 return error::kLostContext
;
7553 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7554 uint32 immediate_data_size
,
7555 const cmds::ScheduleOverlayPlaneCHROMIUM
& c
) {
7556 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
7558 "glScheduleOverlayPlaneCHROMIUM",
7559 "function not implemented");
7560 return error::kNoError
;
7563 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
7564 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7565 const std::string
& name_str
) {
7566 if (!StringIsValidForGLES(name_str
.c_str())) {
7568 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
7569 return error::kNoError
;
7571 Program
* program
= GetProgramInfoNotShader(
7572 client_id
, "glGetAttribLocation");
7574 return error::kNoError
;
7576 if (!program
->IsValid()) {
7578 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
7579 return error::kNoError
;
7581 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7582 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7584 return error::kOutOfBounds
;
7586 // Require the client to init this incase the context is lost and we are no
7587 // longer executing commands.
7588 if (*location
!= -1) {
7589 return error::kGenericError
;
7591 *location
= program
->GetAttribLocation(name_str
);
7592 return error::kNoError
;
7595 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
7596 uint32 immediate_data_size
, const cmds::GetAttribLocation
& c
) {
7597 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7599 return error::kInvalidArguments
;
7601 std::string name_str
;
7602 if (!bucket
->GetAsString(&name_str
)) {
7603 return error::kInvalidArguments
;
7605 return GetAttribLocationHelper(
7606 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7609 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
7610 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7611 const std::string
& name_str
) {
7612 if (!StringIsValidForGLES(name_str
.c_str())) {
7614 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
7615 return error::kNoError
;
7617 Program
* program
= GetProgramInfoNotShader(
7618 client_id
, "glGetUniformLocation");
7620 return error::kNoError
;
7622 if (!program
->IsValid()) {
7624 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
7625 return error::kNoError
;
7627 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7628 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7630 return error::kOutOfBounds
;
7632 // Require the client to init this incase the context is lost an we are no
7633 // longer executing commands.
7634 if (*location
!= -1) {
7635 return error::kGenericError
;
7637 *location
= program
->GetUniformFakeLocation(name_str
);
7638 return error::kNoError
;
7641 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
7642 uint32 immediate_data_size
, const cmds::GetUniformLocation
& c
) {
7643 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7645 return error::kInvalidArguments
;
7647 std::string name_str
;
7648 if (!bucket
->GetAsString(&name_str
)) {
7649 return error::kInvalidArguments
;
7651 return GetUniformLocationHelper(
7652 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7655 error::Error
GLES2DecoderImpl::HandleGetString(
7656 uint32 immediate_data_size
, const cmds::GetString
& c
) {
7657 GLenum name
= static_cast<GLenum
>(c
.name
);
7658 if (!validators_
->string_type
.IsValid(name
)) {
7659 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
7660 return error::kNoError
;
7662 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
7663 std::string extensions
;
7666 str
= "OpenGL ES 2.0 Chromium";
7668 case GL_SHADING_LANGUAGE_VERSION
:
7669 str
= "OpenGL ES GLSL ES 1.0 Chromium";
7673 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7674 // They are used by WEBGL_debug_renderer_info.
7675 if (!force_webgl_glsl_validation_
)
7680 // For WebGL contexts, strip out the OES derivatives and
7681 // EXT frag depth extensions if they have not been enabled.
7682 if (force_webgl_glsl_validation_
) {
7683 extensions
= feature_info_
->extensions();
7684 if (!derivatives_explicitly_enabled_
) {
7685 size_t offset
= extensions
.find(kOESDerivativeExtension
);
7686 if (std::string::npos
!= offset
) {
7687 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
7691 if (!frag_depth_explicitly_enabled_
) {
7692 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
7693 if (std::string::npos
!= offset
) {
7694 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
7698 if (!draw_buffers_explicitly_enabled_
) {
7699 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
7700 if (std::string::npos
!= offset
) {
7701 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
7705 if (!shader_texture_lod_explicitly_enabled_
) {
7706 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
7707 if (std::string::npos
!= offset
) {
7708 extensions
.replace(offset
,
7709 arraysize(kEXTShaderTextureLodExtension
),
7714 extensions
= feature_info_
->extensions().c_str();
7716 if (supports_post_sub_buffer_
)
7717 extensions
+= " GL_CHROMIUM_post_sub_buffer";
7718 str
= extensions
.c_str();
7724 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
7725 bucket
->SetFromString(str
);
7726 return error::kNoError
;
7729 error::Error
GLES2DecoderImpl::HandleBufferData(
7730 uint32 immediate_data_size
, const cmds::BufferData
& c
) {
7731 GLenum target
= static_cast<GLenum
>(c
.target
);
7732 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
7733 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
7734 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
7735 GLenum usage
= static_cast<GLenum
>(c
.usage
);
7736 const void* data
= NULL
;
7737 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
7738 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
7740 return error::kOutOfBounds
;
7743 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
7744 return error::kNoError
;
7747 void GLES2DecoderImpl::DoBufferSubData(
7748 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
7749 // Just delegate it. Some validation is actually done before this.
7750 buffer_manager()->ValidateAndDoBufferSubData(
7751 &state_
, target
, offset
, size
, data
);
7754 bool GLES2DecoderImpl::ClearLevel(
7755 unsigned service_id
,
7756 unsigned bind_target
,
7759 unsigned internal_format
,
7764 bool is_texture_immutable
) {
7765 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
7766 if (feature_info_
->feature_flags().angle_depth_texture
&&
7767 (channels
& GLES2Util::kDepth
) != 0) {
7768 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7769 // on depth formats.
7771 glGenFramebuffersEXT(1, &fb
);
7772 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
7774 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
7775 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
7776 GL_DEPTH_ATTACHMENT
;
7778 glFramebufferTexture2DEXT(
7779 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
7780 // ANGLE promises a depth only attachment ok.
7781 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
7782 GL_FRAMEBUFFER_COMPLETE
) {
7786 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
7787 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
7789 state_
.SetDeviceDepthMask(GL_TRUE
);
7790 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
7791 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
7793 RestoreClearState();
7795 glDeleteFramebuffersEXT(1, &fb
);
7796 Framebuffer
* framebuffer
=
7797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
7798 GLuint fb_service_id
=
7799 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
7800 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
7804 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
7807 uint32 padded_row_size
;
7808 if (!GLES2Util::ComputeImageDataSizes(
7809 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
7810 NULL
, &padded_row_size
)) {
7814 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
7818 if (size
> kMaxZeroSize
) {
7819 if (kMaxZeroSize
< padded_row_size
) {
7820 // That'd be an awfully large texture.
7823 // We should never have a large total size with a zero row size.
7824 DCHECK_GT(padded_row_size
, 0U);
7825 tile_height
= kMaxZeroSize
/ padded_row_size
;
7826 if (!GLES2Util::ComputeImageDataSizes(
7827 width
, tile_height
, format
, type
, state_
.unpack_alignment
, &size
,
7832 tile_height
= height
;
7835 // Assumes the size has already been checked.
7836 scoped_ptr
<char[]> zero(new char[size
]);
7837 memset(zero
.get(), 0, size
);
7838 glBindTexture(bind_target
, service_id
);
7841 while (y
< height
) {
7842 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
7843 if (is_texture_immutable
|| h
!= height
) {
7844 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
7847 target
, level
, internal_format
, width
, h
, 0, format
, type
,
7852 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
7853 &state_
, bind_target
);
7854 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
7860 const int kS3TCBlockWidth
= 4;
7861 const int kS3TCBlockHeight
= 4;
7862 const int kS3TCDXT1BlockSize
= 8;
7863 const int kS3TCDXT3AndDXT5BlockSize
= 16;
7865 bool IsValidDXTSize(GLint level
, GLsizei size
) {
7866 return (size
== 1) ||
7867 (size
== 2) || !(size
% kS3TCBlockWidth
);
7870 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
7871 // Ensure that the size is a power of two
7872 return (size
& (size
- 1)) == 0;
7875 } // anonymous namespace.
7877 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7878 const char* function_name
,
7879 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
7880 unsigned int bytes_required
= 0;
7883 case GL_ATC_RGB_AMD
:
7884 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7885 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7886 case GL_ETC1_RGB8_OES
: {
7887 int num_blocks_across
=
7888 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7889 int num_blocks_down
=
7890 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7891 int num_blocks
= num_blocks_across
* num_blocks_down
;
7892 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
7895 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
7896 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
7897 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7898 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7899 int num_blocks_across
=
7900 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7901 int num_blocks_down
=
7902 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7903 int num_blocks
= num_blocks_across
* num_blocks_down
;
7904 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
7907 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
7908 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
7909 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
7912 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
7913 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
7914 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
7918 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
7922 if (size
!= bytes_required
) {
7924 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
7931 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7932 const char* function_name
,
7933 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
7935 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7936 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7937 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7938 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7939 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
7941 GL_INVALID_OPERATION
, function_name
,
7942 "width or height invalid for level");
7947 case GL_ATC_RGB_AMD
:
7948 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
7949 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
7950 case GL_ETC1_RGB8_OES
: {
7951 if (width
<= 0 || height
<= 0) {
7953 GL_INVALID_OPERATION
, function_name
,
7954 "width or height invalid for level");
7959 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
7960 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
7961 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
7962 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
7963 if (!IsValidPVRTCSize(level
, width
) ||
7964 !IsValidPVRTCSize(level
, height
)) {
7966 GL_INVALID_OPERATION
, function_name
,
7967 "width or height invalid for level");
7977 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7978 const char* function_name
,
7979 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
7980 GLsizei width
, GLsizei height
, GLenum format
,
7982 if (xoffset
< 0 || yoffset
< 0) {
7984 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
7989 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7990 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7991 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7992 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7993 const int kBlockWidth
= 4;
7994 const int kBlockHeight
= 4;
7995 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
7997 GL_INVALID_OPERATION
, function_name
,
7998 "xoffset or yoffset not multiple of 4");
8001 GLsizei tex_width
= 0;
8002 GLsizei tex_height
= 0;
8003 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8004 width
- xoffset
> tex_width
||
8005 height
- yoffset
> tex_height
) {
8007 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8010 return ValidateCompressedTexDimensions(
8011 function_name
, level
, width
, height
, format
);
8013 case GL_ATC_RGB_AMD
:
8014 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8015 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8017 GL_INVALID_OPERATION
, function_name
,
8018 "not supported for ATC textures");
8021 case GL_ETC1_RGB8_OES
: {
8023 GL_INVALID_OPERATION
, function_name
,
8024 "not supported for ECT1_RGB8_OES textures");
8027 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8028 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8029 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8030 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8031 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8033 GL_INVALID_OPERATION
, function_name
,
8034 "xoffset and yoffset must be zero");
8037 GLsizei tex_width
= 0;
8038 GLsizei tex_height
= 0;
8039 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8040 width
!= tex_width
||
8041 height
!= tex_height
) {
8043 GL_INVALID_OPERATION
, function_name
,
8044 "dimensions must match existing texture level dimensions");
8047 return ValidateCompressedTexDimensions(
8048 function_name
, level
, width
, height
, format
);
8055 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8058 GLenum internal_format
,
8064 // TODO(gman): Validate image_size is correct for width, height and format.
8065 if (!validators_
->texture_target
.IsValid(target
)) {
8066 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8067 "glCompressedTexImage2D", target
, "target");
8068 return error::kNoError
;
8070 if (!validators_
->compressed_texture_format
.IsValid(
8072 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8073 "glCompressedTexImage2D", internal_format
, "internal_format");
8074 return error::kNoError
;
8076 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8080 "glCompressedTexImage2D", "dimensions out of range");
8081 return error::kNoError
;
8083 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8088 "glCompressedTexImage2D", "unknown texture target");
8089 return error::kNoError
;
8091 Texture
* texture
= texture_ref
->texture();
8092 if (texture
->IsImmutable()) {
8094 GL_INVALID_OPERATION
,
8095 "glCompressedTexImage2D", "texture is immutable");
8096 return error::kNoError
;
8099 if (!ValidateCompressedTexDimensions(
8100 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8101 !ValidateCompressedTexFuncData(
8102 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8103 return error::kNoError
;
8106 if (!EnsureGPUMemoryAvailable(image_size
)) {
8108 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8109 return error::kNoError
;
8112 if (texture
->IsAttachedToFramebuffer()) {
8113 framebuffer_state_
.clear_state_dirty
= true;
8116 scoped_ptr
<int8
[]> zero
;
8118 zero
.reset(new int8
[image_size
]);
8119 memset(zero
.get(), 0, image_size
);
8122 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8123 glCompressedTexImage2D(
8124 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8125 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8126 if (error
== GL_NO_ERROR
) {
8127 texture_manager()->SetLevelInfo(
8128 texture_ref
, target
, level
, internal_format
,
8129 width
, height
, 1, border
, 0, 0, true);
8131 return error::kNoError
;
8134 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8135 uint32 immediate_data_size
, const cmds::CompressedTexImage2D
& c
) {
8136 GLenum target
= static_cast<GLenum
>(c
.target
);
8137 GLint level
= static_cast<GLint
>(c
.level
);
8138 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8139 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8140 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8141 GLint border
= static_cast<GLint
>(c
.border
);
8142 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8143 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8144 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8145 const void* data
= NULL
;
8146 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8147 data
= GetSharedMemoryAs
<const void*>(
8148 data_shm_id
, data_shm_offset
, image_size
);
8150 return error::kOutOfBounds
;
8153 return DoCompressedTexImage2D(
8154 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8157 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8158 uint32 immediate_data_size
, const cmds::CompressedTexImage2DBucket
& c
) {
8159 GLenum target
= static_cast<GLenum
>(c
.target
);
8160 GLint level
= static_cast<GLint
>(c
.level
);
8161 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8162 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8163 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8164 GLint border
= static_cast<GLint
>(c
.border
);
8165 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8167 return error::kInvalidArguments
;
8169 uint32 data_size
= bucket
->size();
8170 GLsizei imageSize
= data_size
;
8171 const void* data
= bucket
->GetData(0, data_size
);
8173 return error::kInvalidArguments
;
8175 return DoCompressedTexImage2D(
8176 target
, level
, internal_format
, width
, height
, border
,
8180 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8181 uint32 immediate_data_size
,
8182 const cmds::CompressedTexSubImage2DBucket
& c
) {
8183 GLenum target
= static_cast<GLenum
>(c
.target
);
8184 GLint level
= static_cast<GLint
>(c
.level
);
8185 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8186 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8187 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8188 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8189 GLenum format
= static_cast<GLenum
>(c
.format
);
8190 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8192 return error::kInvalidArguments
;
8194 uint32 data_size
= bucket
->size();
8195 GLsizei imageSize
= data_size
;
8196 const void* data
= bucket
->GetData(0, data_size
);
8198 return error::kInvalidArguments
;
8200 if (!validators_
->texture_target
.IsValid(target
)) {
8202 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8203 return error::kNoError
;
8205 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8206 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8207 "glCompressedTexSubImage2D", format
, "format");
8208 return error::kNoError
;
8212 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8213 return error::kNoError
;
8217 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8218 return error::kNoError
;
8220 if (imageSize
< 0) {
8222 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8223 return error::kNoError
;
8225 DoCompressedTexSubImage2D(
8226 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8227 return error::kNoError
;
8230 error::Error
GLES2DecoderImpl::HandleTexImage2D(
8231 uint32 immediate_data_size
, const cmds::TexImage2D
& c
) {
8232 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8233 "width", c
.width
, "height", c
.height
);
8234 // Set as failed for now, but if it successed, this will be set to not failed.
8235 texture_state_
.tex_image_2d_failed
= true;
8236 GLenum target
= static_cast<GLenum
>(c
.target
);
8237 GLint level
= static_cast<GLint
>(c
.level
);
8238 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8239 // for internalformat.
8240 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8241 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8242 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8243 GLint border
= static_cast<GLint
>(c
.border
);
8244 GLenum format
= static_cast<GLenum
>(c
.format
);
8245 GLenum type
= static_cast<GLenum
>(c
.type
);
8246 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8247 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8249 if (!GLES2Util::ComputeImageDataSizes(
8250 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
8252 return error::kOutOfBounds
;
8254 const void* pixels
= NULL
;
8255 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8256 pixels
= GetSharedMemoryAs
<const void*>(
8257 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8259 return error::kOutOfBounds
;
8263 TextureManager::DoTextImage2DArguments args
= {
8264 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8265 pixels
, pixels_size
};
8266 texture_manager()->ValidateAndDoTexImage2D(
8267 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8268 return error::kNoError
;
8271 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8280 const void * data
) {
8281 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8285 GL_INVALID_OPERATION
,
8286 "glCompressedTexSubImage2D", "unknown texture for target");
8289 Texture
* texture
= texture_ref
->texture();
8291 GLenum internal_format
= 0;
8292 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
8294 GL_INVALID_OPERATION
,
8295 "glCompressedTexSubImage2D", "level does not exist.");
8298 if (internal_format
!= format
) {
8300 GL_INVALID_OPERATION
,
8301 "glCompressedTexSubImage2D", "format does not match internal format.");
8304 if (!texture
->ValidForTexture(
8305 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8307 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8311 if (!ValidateCompressedTexFuncData(
8312 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8313 !ValidateCompressedTexSubDimensions(
8314 "glCompressedTexSubImage2D",
8315 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8320 // Note: There is no need to deal with texture cleared tracking here
8321 // because the validation above means you can only get here if the level
8322 // is already a matching compressed format and in that case
8323 // CompressedTexImage2D already cleared the texture.
8324 glCompressedTexSubImage2D(
8325 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8329 GLint start
, GLint range
, GLint sourceRange
,
8330 GLint
* out_start
, GLint
* out_range
) {
8337 GLint end
= start
+ range
;
8338 if (end
> sourceRange
) {
8339 range
-= end
- sourceRange
;
8345 void GLES2DecoderImpl::DoCopyTexImage2D(
8348 GLenum internal_format
,
8354 DCHECK(!ShouldDeferReads());
8355 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8359 GL_INVALID_OPERATION
,
8360 "glCopyTexImage2D", "unknown texture for target");
8363 Texture
* texture
= texture_ref
->texture();
8364 if (texture
->IsImmutable()) {
8366 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8369 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8372 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8375 if (!texture_manager()->ValidateFormatAndTypeCombination(
8376 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
8377 GL_UNSIGNED_BYTE
)) {
8381 // Check we have compatible formats.
8382 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8383 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8384 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
8386 if ((channels_needed
& channels_exist
) != channels_needed
) {
8388 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
8392 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8394 GL_INVALID_OPERATION
,
8395 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8399 uint32 estimated_size
= 0;
8400 if (!GLES2Util::ComputeImageDataSizes(
8401 width
, height
, internal_format
, GL_UNSIGNED_BYTE
, state_
.unpack_alignment
,
8402 &estimated_size
, NULL
, NULL
)) {
8404 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
8408 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
8409 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
8413 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8417 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8418 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8419 gfx::Size size
= GetBoundReadFrameBufferSize();
8421 if (texture
->IsAttachedToFramebuffer()) {
8422 framebuffer_state_
.clear_state_dirty
= true;
8425 // Clip to size to source dimensions
8428 GLint copyWidth
= 0;
8429 GLint copyHeight
= 0;
8430 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8431 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8435 copyWidth
!= width
||
8436 copyHeight
!= height
) {
8437 // some part was clipped so clear the texture.
8439 texture
->service_id(), texture
->target(),
8440 target
, level
, internal_format
, internal_format
, GL_UNSIGNED_BYTE
,
8441 width
, height
, texture
->IsImmutable())) {
8443 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
8446 if (copyHeight
> 0 && copyWidth
> 0) {
8447 GLint dx
= copyX
- x
;
8448 GLint dy
= copyY
- y
;
8451 ScopedModifyPixels
modify(texture_ref
);
8452 glCopyTexSubImage2D(target
, level
,
8453 destX
, destY
, copyX
, copyY
,
8454 copyWidth
, copyHeight
);
8457 ScopedModifyPixels
modify(texture_ref
);
8458 glCopyTexImage2D(target
, level
, internal_format
,
8459 copyX
, copyY
, copyWidth
, copyHeight
, border
);
8461 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8462 if (error
== GL_NO_ERROR
) {
8463 texture_manager()->SetLevelInfo(
8464 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
8465 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
8469 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8478 DCHECK(!ShouldDeferReads());
8479 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8483 GL_INVALID_OPERATION
,
8484 "glCopyTexSubImage2D", "unknown texture for target");
8487 Texture
* texture
= texture_ref
->texture();
8490 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
8491 !texture
->ValidForTexture(
8492 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8494 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
8497 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8499 GL_INVALID_OPERATION
,
8500 "glCopyTexSubImage2D", "async upload pending for texture");
8504 // Check we have compatible formats.
8505 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8506 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8507 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
8509 if (!channels_needed
||
8510 (channels_needed
& channels_exist
) != channels_needed
) {
8512 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
8516 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8518 GL_INVALID_OPERATION
,
8519 "glCopySubImage2D", "can not be used with depth or stencil textures");
8523 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8527 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8528 gfx::Size size
= GetBoundReadFrameBufferSize();
8531 GLint copyWidth
= 0;
8532 GLint copyHeight
= 0;
8533 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8534 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8536 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, level
)) {
8538 GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D", "dimensions too big");
8544 copyWidth
!= width
||
8545 copyHeight
!= height
) {
8546 // some part was clipped so clear the sub rect.
8547 uint32 pixels_size
= 0;
8548 if (!GLES2Util::ComputeImageDataSizes(
8549 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8552 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
8555 scoped_ptr
<char[]> zero(new char[pixels_size
]);
8556 memset(zero
.get(), 0, pixels_size
);
8557 ScopedModifyPixels
modify(texture_ref
);
8559 target
, level
, xoffset
, yoffset
, width
, height
,
8560 format
, type
, zero
.get());
8563 if (copyHeight
> 0 && copyWidth
> 0) {
8564 GLint dx
= copyX
- x
;
8565 GLint dy
= copyY
- y
;
8566 GLint destX
= xoffset
+ dx
;
8567 GLint destY
= yoffset
+ dy
;
8568 ScopedModifyPixels
modify(texture_ref
);
8569 glCopyTexSubImage2D(target
, level
,
8570 destX
, destY
, copyX
, copyY
,
8571 copyWidth
, copyHeight
);
8575 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8576 error::Error
* error
,
8577 const char* function_name
,
8586 const void * data
) {
8587 (*error
) = error::kNoError
;
8588 if (!validators_
->texture_target
.IsValid(target
)) {
8589 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
8593 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
8597 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
8600 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8604 GL_INVALID_OPERATION
,
8605 function_name
, "unknown texture for target");
8608 Texture
* texture
= texture_ref
->texture();
8609 GLenum current_type
= 0;
8610 GLenum internal_format
= 0;
8611 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
8613 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
8616 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
8617 function_name
, format
, type
, internal_format
, level
)) {
8620 if (type
!= current_type
) {
8622 GL_INVALID_OPERATION
,
8623 function_name
, "type does not match type of texture.");
8626 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8628 GL_INVALID_OPERATION
,
8629 function_name
, "async upload pending for texture");
8632 if (!texture
->ValidForTexture(
8633 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8634 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
8637 if ((GLES2Util::GetChannelsForFormat(format
) &
8638 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8640 GL_INVALID_OPERATION
,
8641 function_name
, "can not supply data for depth or stencil textures");
8645 (*error
) = error::kOutOfBounds
;
8651 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
8660 const void * data
) {
8661 error::Error error
= error::kNoError
;
8662 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
8663 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
8666 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8668 Texture
* texture
= texture_ref
->texture();
8669 GLsizei tex_width
= 0;
8670 GLsizei tex_height
= 0;
8671 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
8673 if (xoffset
!= 0 || yoffset
!= 0 ||
8674 width
!= tex_width
|| height
!= tex_height
) {
8675 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
8678 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
8679 return error::kNoError
;
8681 ScopedTextureUploadTimer
timer(&texture_state_
);
8683 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8684 return error::kNoError
;
8687 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
8688 !texture
->IsImmutable()) {
8689 ScopedTextureUploadTimer
timer(&texture_state_
);
8690 GLenum internal_format
;
8692 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
8693 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8696 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
8698 ScopedTextureUploadTimer
timer(&texture_state_
);
8700 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8702 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
8703 return error::kNoError
;
8706 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(
8707 uint32 immediate_data_size
, const cmds::TexSubImage2D
& c
) {
8708 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8709 "width", c
.width
, "height", c
.height
);
8710 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
8711 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
8712 return error::kNoError
;
8714 GLenum target
= static_cast<GLenum
>(c
.target
);
8715 GLint level
= static_cast<GLint
>(c
.level
);
8716 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8717 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8718 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8719 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8720 GLenum format
= static_cast<GLenum
>(c
.format
);
8721 GLenum type
= static_cast<GLenum
>(c
.type
);
8723 if (!GLES2Util::ComputeImageDataSizes(
8724 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
8726 return error::kOutOfBounds
;
8728 const void* pixels
= GetSharedMemoryAs
<const void*>(
8729 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
8730 return DoTexSubImage2D(
8731 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
8734 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8735 uint32 immediate_data_size
, const cmds::GetVertexAttribPointerv
& c
) {
8736 GLuint index
= static_cast<GLuint
>(c
.index
);
8737 GLenum pname
= static_cast<GLenum
>(c
.pname
);
8738 typedef cmds::GetVertexAttribPointerv::Result Result
;
8739 Result
* result
= GetSharedMemoryAs
<Result
*>(
8740 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
8742 return error::kOutOfBounds
;
8744 // Check that the client initialized the result.
8745 if (result
->size
!= 0) {
8746 return error::kInvalidArguments
;
8748 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
8749 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8750 "glGetVertexAttribPointerv", pname
, "pname");
8751 return error::kNoError
;
8753 if (index
>= group_
->max_vertex_attribs()) {
8755 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
8756 return error::kNoError
;
8758 result
->SetNumResults(1);
8759 *result
->GetData() =
8760 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
8761 return error::kNoError
;
8764 bool GLES2DecoderImpl::GetUniformSetup(
8765 GLuint program_id
, GLint fake_location
,
8766 uint32 shm_id
, uint32 shm_offset
,
8767 error::Error
* error
, GLint
* real_location
,
8768 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
8771 DCHECK(result_pointer
);
8772 DCHECK(result_type
);
8773 DCHECK(real_location
);
8774 *error
= error::kNoError
;
8775 // Make sure we have enough room for the result on failure.
8776 SizedResult
<GLint
>* result
;
8777 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8778 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
8780 *error
= error::kOutOfBounds
;
8783 *result_pointer
= result
;
8784 // Set the result size to 0 so the client does not have to check for success.
8785 result
->SetNumResults(0);
8786 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
8790 if (!program
->IsValid()) {
8791 // Program was not linked successfully. (ie, glLinkProgram)
8793 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
8796 *service_id
= program
->service_id();
8797 GLint array_index
= -1;
8798 const Program::UniformInfo
* uniform_info
=
8799 program
->GetUniformInfoByFakeLocation(
8800 fake_location
, real_location
, &array_index
);
8801 if (!uniform_info
) {
8802 // No such location.
8804 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
8807 GLenum type
= uniform_info
->type
;
8808 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
8810 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
8813 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8814 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
8816 *error
= error::kOutOfBounds
;
8819 result
->size
= size
;
8820 *result_type
= type
;
8824 error::Error
GLES2DecoderImpl::HandleGetUniformiv(
8825 uint32 immediate_data_size
, const cmds::GetUniformiv
& c
) {
8826 GLuint program
= c
.program
;
8827 GLint fake_location
= c
.location
;
8830 GLint real_location
= -1;
8833 if (GetUniformSetup(
8834 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8835 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
8837 service_id
, real_location
,
8838 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
8843 error::Error
GLES2DecoderImpl::HandleGetUniformfv(
8844 uint32 immediate_data_size
, const cmds::GetUniformfv
& c
) {
8845 GLuint program
= c
.program
;
8846 GLint fake_location
= c
.location
;
8848 GLint real_location
= -1;
8850 typedef cmds::GetUniformfv::Result Result
;
8853 if (GetUniformSetup(
8854 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8855 &error
, &real_location
, &service_id
,
8856 reinterpret_cast<void**>(&result
), &result_type
)) {
8857 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
8858 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
8859 GLsizei num_values
= result
->GetNumResults();
8860 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
8861 glGetUniformiv(service_id
, real_location
, temp
.get());
8862 GLfloat
* dst
= result
->GetData();
8863 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
8864 dst
[ii
] = (temp
[ii
] != 0);
8867 glGetUniformfv(service_id
, real_location
, result
->GetData());
8873 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8874 uint32 immediate_data_size
, const cmds::GetShaderPrecisionFormat
& c
) {
8875 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
8876 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
8877 typedef cmds::GetShaderPrecisionFormat::Result Result
;
8878 Result
* result
= GetSharedMemoryAs
<Result
*>(
8879 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8881 return error::kOutOfBounds
;
8883 // Check that the client initialized the result.
8884 if (result
->success
!= 0) {
8885 return error::kInvalidArguments
;
8887 if (!validators_
->shader_type
.IsValid(shader_type
)) {
8888 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8889 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
8890 return error::kNoError
;
8892 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
8893 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8894 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
8895 return error::kNoError
;
8898 result
->success
= 1; // true
8900 GLint range
[2] = { 0, 0 };
8901 GLint precision
= 0;
8902 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
8904 result
->min_range
= range
[0];
8905 result
->max_range
= range
[1];
8906 result
->precision
= precision
;
8908 return error::kNoError
;
8911 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
8912 uint32 immediate_data_size
, const cmds::GetAttachedShaders
& c
) {
8913 uint32 result_size
= c
.result_size
;
8914 GLuint program_id
= static_cast<GLuint
>(c
.program
);
8915 Program
* program
= GetProgramInfoNotShader(
8916 program_id
, "glGetAttachedShaders");
8918 return error::kNoError
;
8920 typedef cmds::GetAttachedShaders::Result Result
;
8921 uint32 max_count
= Result::ComputeMaxResults(result_size
);
8922 Result
* result
= GetSharedMemoryAs
<Result
*>(
8923 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
8925 return error::kOutOfBounds
;
8927 // Check that the client initialized the result.
8928 if (result
->size
!= 0) {
8929 return error::kInvalidArguments
;
8932 glGetAttachedShaders(
8933 program
->service_id(), max_count
, &count
, result
->GetData());
8934 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
8935 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
8936 &result
->GetData()[ii
])) {
8938 return error::kGenericError
;
8941 result
->SetNumResults(count
);
8942 return error::kNoError
;
8945 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
8946 uint32 immediate_data_size
, const cmds::GetActiveUniform
& c
) {
8947 GLuint program_id
= c
.program
;
8948 GLuint index
= c
.index
;
8949 uint32 name_bucket_id
= c
.name_bucket_id
;
8950 typedef cmds::GetActiveUniform::Result Result
;
8951 Result
* result
= GetSharedMemoryAs
<Result
*>(
8952 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8954 return error::kOutOfBounds
;
8956 // Check that the client initialized the result.
8957 if (result
->success
!= 0) {
8958 return error::kInvalidArguments
;
8960 Program
* program
= GetProgramInfoNotShader(
8961 program_id
, "glGetActiveUniform");
8963 return error::kNoError
;
8965 const Program::UniformInfo
* uniform_info
=
8966 program
->GetUniformInfo(index
);
8967 if (!uniform_info
) {
8969 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
8970 return error::kNoError
;
8972 result
->success
= 1; // true.
8973 result
->size
= uniform_info
->size
;
8974 result
->type
= uniform_info
->type
;
8975 Bucket
* bucket
= CreateBucket(name_bucket_id
);
8976 bucket
->SetFromString(uniform_info
->name
.c_str());
8977 return error::kNoError
;
8980 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(
8981 uint32 immediate_data_size
, const cmds::GetActiveAttrib
& c
) {
8982 GLuint program_id
= c
.program
;
8983 GLuint index
= c
.index
;
8984 uint32 name_bucket_id
= c
.name_bucket_id
;
8985 typedef cmds::GetActiveAttrib::Result Result
;
8986 Result
* result
= GetSharedMemoryAs
<Result
*>(
8987 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8989 return error::kOutOfBounds
;
8991 // Check that the client initialized the result.
8992 if (result
->success
!= 0) {
8993 return error::kInvalidArguments
;
8995 Program
* program
= GetProgramInfoNotShader(
8996 program_id
, "glGetActiveAttrib");
8998 return error::kNoError
;
9000 const Program::VertexAttrib
* attrib_info
=
9001 program
->GetAttribInfo(index
);
9004 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9005 return error::kNoError
;
9007 result
->success
= 1; // true.
9008 result
->size
= attrib_info
->size
;
9009 result
->type
= attrib_info
->type
;
9010 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9011 bucket
->SetFromString(attrib_info
->name
.c_str());
9012 return error::kNoError
;
9015 error::Error
GLES2DecoderImpl::HandleShaderBinary(
9016 uint32 immediate_data_size
, const cmds::ShaderBinary
& c
) {
9017 #if 1 // No binary shader support.
9018 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
9019 return error::kNoError
;
9021 GLsizei n
= static_cast<GLsizei
>(c
.n
);
9023 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
9024 return error::kNoError
;
9026 GLsizei length
= static_cast<GLsizei
>(c
.length
);
9028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
9029 return error::kNoError
;
9032 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
9033 return error::kOutOfBounds
;
9035 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
9036 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
9037 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
9038 const void* binary
= GetSharedMemoryAs
<const void*>(
9039 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
9040 if (shaders
== NULL
|| binary
== NULL
) {
9041 return error::kOutOfBounds
;
9043 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9044 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9045 Shader
* shader
= GetShader(shaders
[ii
]);
9047 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
9048 return error::kNoError
;
9050 service_ids
[ii
] = shader
->service_id();
9052 // TODO(gman): call glShaderBinary
9053 return error::kNoError
;
9057 void GLES2DecoderImpl::DoSwapBuffers() {
9058 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9060 int this_frame_number
= frame_number_
++;
9061 // TRACE_EVENT for gpu tests:
9062 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9063 TRACE_EVENT_SCOPE_THREAD
,
9064 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9065 "width", (is_offscreen
? offscreen_size_
.width() :
9066 surface_
->GetSize().width()));
9067 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9068 "offscreen", is_offscreen
,
9069 "frame", this_frame_number
);
9071 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9075 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9078 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9079 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9080 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9083 // If offscreen then don't actually SwapBuffers to the display. Just copy
9084 // the rendered frame to another frame buffer.
9086 TRACE_EVENT2("gpu", "Offscreen",
9087 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
9088 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
9089 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9090 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9092 if (workarounds().needs_offscreen_buffer_workaround
) {
9093 offscreen_saved_frame_buffer_
->Create();
9097 // Allocate the offscreen saved color texture.
9098 DCHECK(offscreen_saved_color_format_
);
9099 offscreen_saved_color_texture_
->AllocateStorage(
9100 offscreen_size_
, offscreen_saved_color_format_
, false);
9102 offscreen_saved_frame_buffer_
->AttachRenderTexture(
9103 offscreen_saved_color_texture_
.get());
9104 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
9105 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
9106 GL_FRAMEBUFFER_COMPLETE
) {
9107 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9108 << "because offscreen saved FBO was incomplete.";
9109 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9113 // Clear the offscreen color texture.
9114 // TODO(piman): Is this still necessary?
9116 ScopedFrameBufferBinder
binder(this,
9117 offscreen_saved_frame_buffer_
->id());
9118 glClearColor(0, 0, 0, 0);
9119 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
9120 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
9121 glClear(GL_COLOR_BUFFER_BIT
);
9122 RestoreClearState();
9126 UpdateParentTextureInfo();
9129 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
9131 ScopedGLErrorSuppressor
suppressor(
9132 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9134 if (IsOffscreenBufferMultisampled()) {
9135 // For multisampled buffers, resolve the frame buffer.
9136 ScopedResolvedFrameBufferBinder
binder(this, true, false);
9138 ScopedFrameBufferBinder
binder(this,
9139 offscreen_target_frame_buffer_
->id());
9141 if (offscreen_target_buffer_preserved_
) {
9142 // Copy the target frame buffer to the saved offscreen texture.
9143 offscreen_saved_color_texture_
->Copy(
9144 offscreen_saved_color_texture_
->size(),
9145 offscreen_saved_color_format_
);
9147 // Flip the textures in the parent context via the texture manager.
9148 if (!!offscreen_saved_color_texture_info_
.get())
9149 offscreen_saved_color_texture_info_
->texture()->
9150 SetServiceId(offscreen_target_color_texture_
->id());
9152 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
9153 offscreen_target_frame_buffer_
->AttachRenderTexture(
9154 offscreen_target_color_texture_
.get());
9157 // Ensure the side effects of the copy are visible to the parent
9158 // context. There is no need to do this for ANGLE because it uses a
9159 // single D3D device for all contexts.
9160 if (!feature_info_
->feature_flags().is_angle
)
9164 if (!surface_
->SwapBuffers()) {
9165 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
9166 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9171 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9172 uint32 immediate_data_size
, const cmds::EnableFeatureCHROMIUM
& c
) {
9173 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9174 if (!bucket
|| bucket
->size() == 0) {
9175 return error::kInvalidArguments
;
9177 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
9178 Result
* result
= GetSharedMemoryAs
<Result
*>(
9179 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9181 return error::kOutOfBounds
;
9183 // Check that the client initialized the result.
9185 return error::kInvalidArguments
;
9187 std::string feature_str
;
9188 if (!bucket
->GetAsString(&feature_str
)) {
9189 return error::kInvalidArguments
;
9192 // TODO(gman): make this some kind of table to function pointer thingy.
9193 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9194 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9195 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
9196 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9197 // TODO(gman): decide how to remove the need for this const_cast.
9198 // I could make validators_ non const but that seems bad as this is the only
9199 // place it is needed. I could make some special friend class of validators
9200 // just to allow this to set them. That seems silly. I could refactor this
9201 // code to use the extension mechanism or the initialization attributes to
9202 // turn this feature on. Given that the only real point of this is to make
9203 // the conformance tests pass and given that there is lots of real work that
9204 // needs to be done it seems like refactoring for one to one of those
9205 // methods is a very low priority.
9206 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
9207 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
9208 force_webgl_glsl_validation_
= true;
9209 InitializeShaderTranslator();
9211 return error::kNoError
;
9214 *result
= 1; // true.
9215 return error::kNoError
;
9218 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9219 uint32 immediate_data_size
,
9220 const cmds::GetRequestableExtensionsCHROMIUM
& c
) {
9221 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9222 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
9223 info
->Initialize(disallowed_features_
);
9224 bucket
->SetFromString(info
->extensions().c_str());
9225 return error::kNoError
;
9228 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9229 uint32 immediate_data_size
, const cmds::RequestExtensionCHROMIUM
& c
) {
9230 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9231 if (!bucket
|| bucket
->size() == 0) {
9232 return error::kInvalidArguments
;
9234 std::string feature_str
;
9235 if (!bucket
->GetAsString(&feature_str
)) {
9236 return error::kInvalidArguments
;
9239 bool desire_webgl_glsl_validation
=
9240 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
9241 bool desire_standard_derivatives
= false;
9242 bool desire_frag_depth
= false;
9243 bool desire_draw_buffers
= false;
9244 bool desire_shader_texture_lod
= false;
9245 if (force_webgl_glsl_validation_
) {
9246 desire_standard_derivatives
=
9247 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
9249 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
9250 desire_draw_buffers
=
9251 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
9252 desire_shader_texture_lod
=
9253 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
9256 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
9257 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
9258 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
9259 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
9260 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
9261 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
9262 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
9263 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
9264 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
9265 InitializeShaderTranslator();
9268 UpdateCapabilities();
9270 return error::kNoError
;
9273 error::Error
GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9274 uint32 immediate_data_size
, const cmds::GetMultipleIntegervCHROMIUM
& c
) {
9275 GLuint count
= c
.count
;
9277 if (!SafeMultiplyUint32(count
, sizeof(GLenum
), &pnames_size
)) {
9278 return error::kOutOfBounds
;
9280 const GLenum
* pnames
= GetSharedMemoryAs
<const GLenum
*>(
9281 c
.pnames_shm_id
, c
.pnames_shm_offset
, pnames_size
);
9282 if (pnames
== NULL
) {
9283 return error::kOutOfBounds
;
9286 // We have to copy them since we use them twice so the client
9287 // can't change them between the time we validate them and the time we use
9289 scoped_ptr
<GLenum
[]> enums(new GLenum
[count
]);
9290 memcpy(enums
.get(), pnames
, pnames_size
);
9292 // Count up the space needed for the result.
9293 uint32 num_results
= 0;
9294 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9295 uint32 num
= util_
.GLGetNumValuesReturned(enums
[ii
]);
9297 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9298 "glGetMultipleCHROMIUM", enums
[ii
], "pname");
9299 return error::kNoError
;
9301 // Num will never be more than 4.
9303 if (!SafeAddUint32(num_results
, num
, &num_results
)) {
9304 return error::kOutOfBounds
;
9308 uint32 result_size
= 0;
9309 if (!SafeMultiplyUint32(num_results
, sizeof(GLint
), &result_size
)) {
9310 return error::kOutOfBounds
;
9313 if (result_size
!= static_cast<uint32
>(c
.size
)) {
9316 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9317 return error::kNoError
;
9320 GLint
* results
= GetSharedMemoryAs
<GLint
*>(
9321 c
.results_shm_id
, c
.results_shm_offset
, result_size
);
9322 if (results
== NULL
) {
9323 return error::kOutOfBounds
;
9326 // Check the results have been cleared in case the context was lost.
9327 for (uint32 ii
= 0; ii
< num_results
; ++ii
) {
9329 return error::kInvalidArguments
;
9334 GLint
* start
= results
;
9335 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9336 GLsizei num_written
= 0;
9337 if (!state_
.GetStateAsGLint(enums
[ii
], results
, &num_written
) &&
9338 !GetHelper(enums
[ii
], results
, &num_written
)) {
9339 DoGetIntegerv(enums
[ii
], results
);
9341 results
+= num_written
;
9344 // Just to verify. Should this be a DCHECK?
9345 if (static_cast<uint32
>(results
- start
) != num_results
) {
9346 return error::kOutOfBounds
;
9349 return error::kNoError
;
9352 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9353 uint32 immediate_data_size
, const cmds::GetProgramInfoCHROMIUM
& c
) {
9354 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9355 uint32 bucket_id
= c
.bucket_id
;
9356 Bucket
* bucket
= CreateBucket(bucket_id
);
9357 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
9358 Program
* program
= NULL
;
9359 program
= GetProgram(program_id
);
9360 if (!program
|| !program
->IsValid()) {
9361 return error::kNoError
;
9363 program
->GetProgramInfo(program_manager(), bucket
);
9364 return error::kNoError
;
9367 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
9368 switch (reset_status_
) {
9370 // TODO(kbr): improve the precision of the error code in this case.
9371 // Consider delegating to context for error code if MakeCurrent fails.
9372 return error::kUnknown
;
9373 case GL_GUILTY_CONTEXT_RESET_ARB
:
9374 return error::kGuilty
;
9375 case GL_INNOCENT_CONTEXT_RESET_ARB
:
9376 return error::kInnocent
;
9377 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
9378 return error::kUnknown
;
9382 return error::kUnknown
;
9385 bool GLES2DecoderImpl::WasContextLost() {
9386 if (reset_status_
!= GL_NO_ERROR
) {
9389 if (context_
->WasAllocatedUsingRobustnessExtension()) {
9390 GLenum status
= GL_NO_ERROR
;
9391 if (has_robustness_extension_
)
9392 status
= glGetGraphicsResetStatusARB();
9393 if (status
!= GL_NO_ERROR
) {
9394 // The graphics card was reset. Signal a lost context to the application.
9395 reset_status_
= status
;
9396 reset_by_robustness_extension_
= true;
9397 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
9398 << " context lost via ARB/EXT_robustness. Reset status = "
9399 << GLES2Util::GetStringEnum(status
);
9406 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9407 return WasContextLost() && reset_by_robustness_extension_
;
9410 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
9411 // Only loses the context once.
9412 if (reset_status_
!= GL_NO_ERROR
) {
9416 // Marks this context as lost.
9417 reset_status_
= reset_status
;
9418 current_decoder_error_
= error::kLostContext
;
9421 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9422 uint32 immediate_data_size
, const cmds::InsertSyncPointCHROMIUM
& c
) {
9423 return error::kUnknownCommand
;
9426 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9427 uint32 immediate_data_size
, const cmds::WaitSyncPointCHROMIUM
& c
) {
9428 group_
->mailbox_manager()->PullTextureUpdates();
9429 if (wait_sync_point_callback_
.is_null())
9430 return error::kNoError
;
9432 return wait_sync_point_callback_
.Run(c
.sync_point
) ?
9433 error::kNoError
: error::kDeferCommandUntilLater
;
9436 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9437 uint32 immediate_data_size
, const cmds::DiscardBackbufferCHROMIUM
& c
) {
9438 if (surface_
->DeferDraws())
9439 return error::kDeferCommandUntilLater
;
9440 if (!surface_
->SetBackbufferAllocation(false))
9441 return error::kLostContext
;
9442 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
9443 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
9444 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
9445 return error::kNoError
;
9448 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9449 GLsizei n
, const GLuint
* client_ids
) {
9450 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9451 if (query_manager_
->GetQuery(client_ids
[ii
])) {
9455 query_manager_
->GenQueries(n
, client_ids
);
9459 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9460 GLsizei n
, const GLuint
* client_ids
) {
9461 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9462 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
9463 if (query
&& !query
->IsDeleted()) {
9464 ContextState::QueryMap::iterator it
=
9465 state_
.current_queries
.find(query
->target());
9466 if (it
!= state_
.current_queries
.end())
9467 state_
.current_queries
.erase(it
);
9469 query
->Destroy(true);
9471 query_manager_
->RemoveQuery(client_ids
[ii
]);
9475 bool GLES2DecoderImpl::ProcessPendingQueries() {
9476 if (query_manager_
.get() == NULL
) {
9479 if (!query_manager_
->ProcessPendingQueries()) {
9480 current_decoder_error_
= error::kOutOfBounds
;
9482 return query_manager_
->HavePendingQueries();
9485 // Note that if there are no pending readpixels right now,
9486 // this function will call the callback immediately.
9487 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
9488 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
9489 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
9495 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9496 while (!pending_readpixel_fences_
.empty() &&
9497 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
9498 std::vector
<base::Closure
> callbacks
=
9499 pending_readpixel_fences_
.front()->callbacks
;
9500 pending_readpixel_fences_
.pop();
9501 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
9507 bool GLES2DecoderImpl::HasMoreIdleWork() {
9508 return !pending_readpixel_fences_
.empty() ||
9509 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
9512 void GLES2DecoderImpl::PerformIdleWork() {
9513 ProcessPendingReadPixels();
9514 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
9516 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
9517 ProcessFinishedAsyncTransfers();
9520 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(
9521 uint32 immediate_data_size
, const cmds::BeginQueryEXT
& c
) {
9522 GLenum target
= static_cast<GLenum
>(c
.target
);
9523 GLuint client_id
= static_cast<GLuint
>(c
.id
);
9524 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
9525 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
9528 case GL_COMMANDS_ISSUED_CHROMIUM
:
9529 case GL_LATENCY_QUERY_CHROMIUM
:
9530 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
9531 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
9532 case GL_GET_ERROR_QUERY_CHROMIUM
:
9534 case GL_COMMANDS_COMPLETED_CHROMIUM
:
9535 if (!features().chromium_sync_query
) {
9537 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9538 "not enabled for commands completed queries");
9539 return error::kNoError
;
9543 if (!features().occlusion_query_boolean
) {
9545 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9546 "not enabled for occlusion queries");
9547 return error::kNoError
;
9552 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
9554 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
9555 return error::kNoError
;
9558 if (client_id
== 0) {
9559 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
9560 return error::kNoError
;
9563 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
9565 if (!query_manager_
->IsValidQuery(client_id
)) {
9566 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9568 "id not made by glGenQueriesEXT");
9569 return error::kNoError
;
9571 query
= query_manager_
->CreateQuery(
9572 target
, client_id
, sync_shm_id
, sync_shm_offset
);
9575 if (query
->target() != target
) {
9577 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
9578 return error::kNoError
;
9579 } else if (query
->shm_id() != sync_shm_id
||
9580 query
->shm_offset() != sync_shm_offset
) {
9581 DLOG(ERROR
) << "Shared memory used by query not the same as before";
9582 return error::kInvalidArguments
;
9585 if (!query_manager_
->BeginQuery(query
)) {
9586 return error::kOutOfBounds
;
9589 state_
.current_queries
[target
] = query
;
9590 return error::kNoError
;
9593 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(
9594 uint32 immediate_data_size
, const cmds::EndQueryEXT
& c
) {
9595 GLenum target
= static_cast<GLenum
>(c
.target
);
9596 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
9597 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
9599 if (it
== state_
.current_queries
.end()) {
9601 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
9602 return error::kNoError
;
9605 QueryManager::Query
* query
= it
->second
.get();
9606 if (!query_manager_
->EndQuery(query
, submit_count
)) {
9607 return error::kOutOfBounds
;
9610 query_manager_
->ProcessPendingTransferQueries();
9612 state_
.current_queries
.erase(it
);
9613 return error::kNoError
;
9616 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9617 GLsizei n
, const GLuint
* client_ids
) {
9618 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9619 if (GetVertexAttribManager(client_ids
[ii
])) {
9624 if (!features().native_vertex_array_object
) {
9626 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9627 CreateVertexAttribManager(client_ids
[ii
], 0, true);
9630 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9632 glGenVertexArraysOES(n
, service_ids
.get());
9633 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9634 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
9641 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9642 GLsizei n
, const GLuint
* client_ids
) {
9643 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9644 VertexAttribManager
* vao
=
9645 GetVertexAttribManager(client_ids
[ii
]);
9646 if (vao
&& !vao
->IsDeleted()) {
9647 if (state_
.vertex_attrib_manager
.get() == vao
) {
9648 DoBindVertexArrayOES(0);
9650 RemoveVertexAttribManager(client_ids
[ii
]);
9655 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
9656 VertexAttribManager
* vao
= NULL
;
9657 if (client_id
!= 0) {
9658 vao
= GetVertexAttribManager(client_id
);
9660 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9661 // only allows names that have been previously generated. As such, we do
9662 // not generate new names here.
9664 GL_INVALID_OPERATION
,
9665 "glBindVertexArrayOES", "bad vertex array id.");
9666 current_decoder_error_
= error::kNoError
;
9670 vao
= state_
.default_vertex_attrib_manager
.get();
9673 // Only set the VAO state if it's changed
9674 if (state_
.vertex_attrib_manager
.get() != vao
) {
9675 state_
.vertex_attrib_manager
= vao
;
9676 if (!features().native_vertex_array_object
) {
9677 EmulateVertexArrayState();
9679 GLuint service_id
= vao
->service_id();
9680 glBindVertexArrayOES(service_id
);
9685 // Used when OES_vertex_array_object isn't natively supported
9686 void GLES2DecoderImpl::EmulateVertexArrayState() {
9687 // Setup the Vertex attribute state
9688 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
9689 RestoreStateForAttrib(vv
, true);
9692 // Setup the element buffer
9693 Buffer
* element_array_buffer
=
9694 state_
.vertex_attrib_manager
->element_array_buffer();
9695 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
9696 element_array_buffer
? element_array_buffer
->service_id() : 0);
9699 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
9700 const VertexAttribManager
* vao
=
9701 GetVertexAttribManager(client_id
);
9702 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
9705 #if defined(OS_MACOSX)
9706 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
9707 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
9709 if (it
!= texture_to_io_surface_map_
.end()) {
9710 // Found a previous IOSurface bound to this texture; release it.
9711 IOSurfaceRef surface
= it
->second
;
9713 texture_to_io_surface_map_
.erase(it
);
9718 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9719 GLenum target
, GLsizei width
, GLsizei height
,
9720 GLuint io_surface_id
, GLuint plane
) {
9721 #if defined(OS_MACOSX)
9722 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
9724 GL_INVALID_OPERATION
,
9725 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9729 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
9730 // This might be supported in the future, and if we could require
9731 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9732 // could delete a lot of code. For now, perform strict validation so we
9733 // know what's going on.
9735 GL_INVALID_OPERATION
,
9736 "glTexImageIOSurface2DCHROMIUM",
9737 "requires TEXTURE_RECTANGLE_ARB target");
9741 // Default target might be conceptually valid, but disallow it to avoid
9743 TextureRef
* texture_ref
=
9744 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
9747 GL_INVALID_OPERATION
,
9748 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9752 // Look up the new IOSurface. Note that because of asynchrony
9753 // between processes this might fail; during live resizing the
9754 // plugin process might allocate and release an IOSurface before
9755 // this process gets a chance to look it up. Hold on to any old
9756 // IOSurface in this case.
9757 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
9760 GL_INVALID_OPERATION
,
9761 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9765 // Release any IOSurface previously bound to this texture.
9766 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
9768 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9769 texture_to_io_surface_map_
.insert(
9770 std::make_pair(texture_ref
->service_id(), surface
));
9772 CGLContextObj context
=
9773 static_cast<CGLContextObj
>(context_
->GetHandle());
9775 CGLError err
= CGLTexImageIOSurface2D(
9782 GL_UNSIGNED_INT_8_8_8_8_REV
,
9786 if (err
!= kCGLNoError
) {
9788 GL_INVALID_OPERATION
,
9789 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9793 texture_manager()->SetLevelInfo(
9794 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
9795 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
9798 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9799 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9803 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
9804 switch (internalformat
) {
9815 case GL_LUMINANCE8_ALPHA8_EXT
:
9816 return GL_LUMINANCE_ALPHA
;
9817 case GL_LUMINANCE8_EXT
:
9818 return GL_LUMINANCE
;
9821 case GL_RGBA32F_EXT
:
9825 case GL_ALPHA32F_EXT
:
9827 case GL_LUMINANCE32F_EXT
:
9828 return GL_LUMINANCE
;
9829 case GL_LUMINANCE_ALPHA32F_EXT
:
9830 return GL_LUMINANCE_ALPHA
;
9831 case GL_RGBA16F_EXT
:
9835 case GL_ALPHA16F_EXT
:
9837 case GL_LUMINANCE16F_EXT
:
9838 return GL_LUMINANCE
;
9839 case GL_LUMINANCE_ALPHA16F_EXT
:
9840 return GL_LUMINANCE_ALPHA
;
9848 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9849 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
9850 GLenum internal_format
, GLenum dest_type
) {
9851 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9853 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
9854 TextureRef
* source_texture_ref
= GetTexture(source_id
);
9856 if (!source_texture_ref
|| !dest_texture_ref
) {
9858 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
9862 if (GL_TEXTURE_2D
!= target
) {
9864 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
9868 Texture
* source_texture
= source_texture_ref
->texture();
9869 Texture
* dest_texture
= dest_texture_ref
->texture();
9870 if (dest_texture
->target() != GL_TEXTURE_2D
||
9871 (source_texture
->target() != GL_TEXTURE_2D
&&
9872 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
9873 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
9874 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9875 "glCopyTextureCHROMIUM",
9876 "invalid texture target binding");
9880 int source_width
, source_height
, dest_width
, dest_height
;
9882 gfx::GLImage
* image
=
9883 source_texture
->GetLevelImage(source_texture
->target(), 0);
9885 gfx::Size size
= image
->GetSize();
9886 source_width
= size
.width();
9887 source_height
= size
.height();
9888 if (source_width
<= 0 || source_height
<= 0) {
9891 "glCopyTextureChromium", "invalid image size");
9895 if (!source_texture
->GetLevelSize(
9896 source_texture
->target(), 0, &source_width
, &source_height
)) {
9897 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9898 "glCopyTextureChromium",
9899 "source texture has no level 0");
9903 // Check that this type of texture is allowed.
9904 if (!texture_manager()->ValidForTarget(
9905 source_texture
->target(), level
, source_width
, source_height
, 1)) {
9907 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
9912 // Clear the source texture if necessary.
9913 if (!texture_manager()->ClearTextureLevel(
9914 this, source_texture_ref
, source_texture
->target(), 0)) {
9916 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
9920 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9921 // needed because it takes 10s of milliseconds to initialize.
9922 if (!copy_texture_CHROMIUM_
.get()) {
9923 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9924 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
9925 copy_texture_CHROMIUM_
->Initialize(this);
9926 RestoreCurrentFramebufferBindings();
9927 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
9931 GLenum dest_type_previous
;
9932 GLenum dest_internal_format
;
9933 bool dest_level_defined
= dest_texture
->GetLevelSize(
9934 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
9936 if (dest_level_defined
) {
9937 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
9938 &dest_internal_format
);
9941 // Resize the destination texture to the dimensions of the source texture.
9942 if (!dest_level_defined
|| dest_width
!= source_width
||
9943 dest_height
!= source_height
||
9944 dest_internal_format
!= internal_format
||
9945 dest_type_previous
!= dest_type
) {
9946 // Ensure that the glTexImage2D succeeds.
9947 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9948 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
9950 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
9951 0, internal_format
, dest_type
, NULL
);
9952 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9953 if (error
!= GL_NO_ERROR
) {
9954 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
9958 texture_manager()->SetLevelInfo(
9959 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
9960 source_height
, 1, 0, internal_format
, dest_type
, true);
9962 texture_manager()->SetLevelCleared(
9963 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
9966 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
9967 ScopedModifyPixels
modify(dest_texture_ref
);
9969 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9970 // before presenting.
9971 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
9972 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9973 // instead of using default matrix crbug.com/226218.
9974 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
9975 0.0f
, 1.0f
, 0.0f
, 0.0f
,
9976 0.0f
, 0.0f
, 1.0f
, 0.0f
,
9977 0.0f
, 0.0f
, 0.0f
, 1.0f
};
9978 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
9980 source_texture
->target(),
9981 dest_texture
->target(),
9982 source_texture
->service_id(),
9983 dest_texture
->service_id(), level
,
9984 source_width
, source_height
,
9986 unpack_premultiply_alpha_
,
9987 unpack_unpremultiply_alpha_
,
9990 copy_texture_CHROMIUM_
->DoCopyTexture(
9992 source_texture
->target(),
9993 dest_texture
->target(),
9994 source_texture
->service_id(),
9995 dest_texture
->service_id(), level
,
9996 source_width
, source_height
,
9998 unpack_premultiply_alpha_
,
9999 unpack_unpremultiply_alpha_
);
10002 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
10005 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
10006 switch (internalformat
) {
10008 return GL_UNSIGNED_SHORT_5_6_5
;
10010 return GL_UNSIGNED_SHORT_4_4_4_4
;
10012 return GL_UNSIGNED_SHORT_5_5_5_1
;
10014 return GL_UNSIGNED_BYTE
;
10016 return GL_UNSIGNED_BYTE
;
10017 case GL_LUMINANCE8_ALPHA8_EXT
:
10018 return GL_UNSIGNED_BYTE
;
10019 case GL_LUMINANCE8_EXT
:
10020 return GL_UNSIGNED_BYTE
;
10021 case GL_ALPHA8_EXT
:
10022 return GL_UNSIGNED_BYTE
;
10023 case GL_RGBA32F_EXT
:
10025 case GL_RGB32F_EXT
:
10027 case GL_ALPHA32F_EXT
:
10029 case GL_LUMINANCE32F_EXT
:
10031 case GL_LUMINANCE_ALPHA32F_EXT
:
10033 case GL_RGBA16F_EXT
:
10034 return GL_HALF_FLOAT_OES
;
10035 case GL_RGB16F_EXT
:
10036 return GL_HALF_FLOAT_OES
;
10037 case GL_ALPHA16F_EXT
:
10038 return GL_HALF_FLOAT_OES
;
10039 case GL_LUMINANCE16F_EXT
:
10040 return GL_HALF_FLOAT_OES
;
10041 case GL_LUMINANCE_ALPHA16F_EXT
:
10042 return GL_HALF_FLOAT_OES
;
10044 return GL_UNSIGNED_BYTE
;
10050 void GLES2DecoderImpl::DoTexStorage2DEXT(
10053 GLenum internal_format
,
10056 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10057 "width", width
, "height", height
);
10058 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
10059 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
10060 LOCAL_SET_GL_ERROR(
10061 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
10064 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10066 if (!texture_ref
) {
10067 LOCAL_SET_GL_ERROR(
10068 GL_INVALID_OPERATION
,
10069 "glTexStorage2DEXT", "unknown texture for target");
10072 Texture
* texture
= texture_ref
->texture();
10073 if (texture
->IsAttachedToFramebuffer()) {
10074 framebuffer_state_
.clear_state_dirty
= true;
10076 if (texture
->IsImmutable()) {
10077 LOCAL_SET_GL_ERROR(
10078 GL_INVALID_OPERATION
,
10079 "glTexStorage2DEXT", "texture is immutable");
10083 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
10084 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
10087 GLsizei level_width
= width
;
10088 GLsizei level_height
= height
;
10089 uint32 estimated_size
= 0;
10090 for (int ii
= 0; ii
< levels
; ++ii
) {
10091 uint32 level_size
= 0;
10092 if (!GLES2Util::ComputeImageDataSizes(
10093 level_width
, level_height
, format
, type
, state_
.unpack_alignment
,
10094 &estimated_size
, NULL
, NULL
) ||
10095 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
10096 LOCAL_SET_GL_ERROR(
10097 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
10100 level_width
= std::max(1, level_width
>> 1);
10101 level_height
= std::max(1, level_height
>> 1);
10103 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10104 LOCAL_SET_GL_ERROR(
10105 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
10110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10111 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
10112 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10113 if (error
== GL_NO_ERROR
) {
10114 GLsizei level_width
= width
;
10115 GLsizei level_height
= height
;
10116 for (int ii
= 0; ii
< levels
; ++ii
) {
10117 texture_manager()->SetLevelInfo(
10118 texture_ref
, target
, ii
, format
,
10119 level_width
, level_height
, 1, 0, format
, type
, false);
10120 level_width
= std::max(1, level_width
>> 1);
10121 level_height
= std::max(1, level_height
>> 1);
10123 texture
->SetImmutable(true);
10127 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10128 uint32 immediate_data_size
, const cmds::GenMailboxCHROMIUM
& c
) {
10129 return error::kUnknownCommand
;
10132 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
10133 const GLbyte
* data
) {
10134 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10135 "context", logger_
.GetLogPrefix(),
10136 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10138 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10140 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
10143 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
10144 GLenum target
, const GLbyte
* data
) {
10145 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10146 "context", logger_
.GetLogPrefix(),
10147 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10149 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
10153 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
10154 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
10155 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10156 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
10157 "mailbox that was not generated by "
10158 "GenMailboxCHROMIUM.";
10160 if (!texture_ref
) {
10161 LOCAL_SET_GL_ERROR(
10162 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
10166 Texture
* produced
= texture_manager()->Produce(texture_ref
);
10168 LOCAL_SET_GL_ERROR(
10169 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
10173 if (produced
->target() != target
) {
10174 LOCAL_SET_GL_ERROR(
10175 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
10179 group_
->mailbox_manager()->ProduceTexture(target
, mailbox
, produced
);
10182 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
10183 const GLbyte
* data
) {
10184 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10185 "context", logger_
.GetLogPrefix(),
10186 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10187 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10188 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10189 "mailbox that was not generated by "
10190 "GenMailboxCHROMIUM.";
10192 scoped_refptr
<TextureRef
> texture_ref
=
10193 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10194 if (!texture_ref
.get()) {
10195 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10196 "glConsumeTextureCHROMIUM",
10197 "unknown texture for target");
10200 GLuint client_id
= texture_ref
->client_id();
10202 LOCAL_SET_GL_ERROR(
10203 GL_INVALID_OPERATION
,
10204 "glConsumeTextureCHROMIUM", "unknown texture for target");
10207 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10209 LOCAL_SET_GL_ERROR(
10210 GL_INVALID_OPERATION
,
10211 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10214 if (texture
->target() != target
) {
10215 LOCAL_SET_GL_ERROR(
10216 GL_INVALID_OPERATION
,
10217 "glConsumeTextureCHROMIUM", "invalid target");
10221 DeleteTexturesHelper(1, &client_id
);
10222 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10223 glBindTexture(target
, texture_ref
->service_id());
10225 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10226 unit
.bind_target
= target
;
10228 case GL_TEXTURE_2D
:
10229 unit
.bound_texture_2d
= texture_ref
;
10231 case GL_TEXTURE_CUBE_MAP
:
10232 unit
.bound_texture_cube_map
= texture_ref
;
10234 case GL_TEXTURE_EXTERNAL_OES
:
10235 unit
.bound_texture_external_oes
= texture_ref
;
10237 case GL_TEXTURE_RECTANGLE_ARB
:
10238 unit
.bound_texture_rectangle_arb
= texture_ref
;
10241 NOTREACHED(); // Validation should prevent us getting here.
10246 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10247 uint32_t immediate_data_size
,
10248 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
) {
10249 GLenum target
= static_cast<GLenum
>(c
.target
);
10250 uint32_t data_size
;
10251 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
10252 return error::kOutOfBounds
;
10254 if (data_size
> immediate_data_size
) {
10255 return error::kOutOfBounds
;
10257 const GLbyte
* mailbox
=
10258 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
10259 if (!validators_
->texture_bind_target
.IsValid(target
)) {
10260 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10261 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
10262 return error::kNoError
;
10264 if (mailbox
== NULL
) {
10265 return error::kOutOfBounds
;
10267 uint32_t client_id
= c
.client_id
;
10268 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
10269 return error::kNoError
;
10272 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
10273 const GLbyte
* data
, GLuint client_id
) {
10274 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10275 "context", logger_
.GetLogPrefix(),
10276 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10277 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10278 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10279 "passed a mailbox that was not "
10280 "generated by GenMailboxCHROMIUM.";
10282 TextureRef
* texture_ref
= GetTexture(client_id
);
10284 LOCAL_SET_GL_ERROR(
10285 GL_INVALID_OPERATION
,
10286 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10289 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10291 LOCAL_SET_GL_ERROR(
10292 GL_INVALID_OPERATION
,
10293 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10296 if (texture
->target() != target
) {
10297 LOCAL_SET_GL_ERROR(
10298 GL_INVALID_OPERATION
,
10299 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10303 IdAllocatorInterface
* id_allocator
=
10304 group_
->GetIdAllocator(id_namespaces::kTextures
);
10305 id_allocator
->MarkAsUsed(client_id
);
10307 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10310 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10311 GLsizei length
, const GLchar
* marker
) {
10315 debug_marker_manager_
.SetMarker(
10316 length
? std::string(marker
, length
) : std::string(marker
));
10319 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10320 GLsizei length
, const GLchar
* marker
) {
10324 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
10325 debug_marker_manager_
.PushGroup(name
);
10326 gpu_tracer_
->Begin(name
, kTraceGroupMarker
);
10329 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10330 debug_marker_manager_
.PopGroup();
10331 gpu_tracer_
->End(kTraceGroupMarker
);
10334 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10335 GLenum target
, GLint image_id
) {
10336 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10338 if (target
== GL_TEXTURE_CUBE_MAP
) {
10339 LOCAL_SET_GL_ERROR(
10341 "glBindTexImage2DCHROMIUM", "invalid target");
10345 // Default target might be conceptually valid, but disallow it to avoid
10347 TextureRef
* texture_ref
=
10348 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10349 if (!texture_ref
) {
10350 LOCAL_SET_GL_ERROR(
10351 GL_INVALID_OPERATION
,
10352 "glBindTexImage2DCHROMIUM", "no texture bound");
10356 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10358 LOCAL_SET_GL_ERROR(
10359 GL_INVALID_OPERATION
,
10360 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10365 ScopedGLErrorSuppressor
suppressor(
10366 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10367 if (!gl_image
->BindTexImage(target
)) {
10368 LOCAL_SET_GL_ERROR(
10369 GL_INVALID_OPERATION
,
10370 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10375 gfx::Size size
= gl_image
->GetSize();
10376 texture_manager()->SetLevelInfo(
10377 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
10378 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
10379 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
10382 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10383 GLenum target
, GLint image_id
) {
10384 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10386 // Default target might be conceptually valid, but disallow it to avoid
10388 TextureRef
* texture_ref
=
10389 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10390 if (!texture_ref
) {
10391 LOCAL_SET_GL_ERROR(
10392 GL_INVALID_OPERATION
,
10393 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10397 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10399 LOCAL_SET_GL_ERROR(
10400 GL_INVALID_OPERATION
,
10401 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10405 // Do nothing when image is not currently bound.
10406 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
10410 ScopedGLErrorSuppressor
suppressor(
10411 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10412 gl_image
->ReleaseTexImage(target
);
10415 texture_manager()->SetLevelInfo(
10416 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
10417 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
10420 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10421 uint32 immediate_data_size
, const cmds::TraceBeginCHROMIUM
& c
) {
10422 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10423 if (!bucket
|| bucket
->size() == 0) {
10424 return error::kInvalidArguments
;
10426 std::string command_name
;
10427 if (!bucket
->GetAsString(&command_name
)) {
10428 return error::kInvalidArguments
;
10430 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name
.c_str(), this);
10431 if (!gpu_tracer_
->Begin(command_name
, kTraceCHROMIUM
)) {
10432 LOCAL_SET_GL_ERROR(
10433 GL_INVALID_OPERATION
,
10434 "glTraceBeginCHROMIUM", "unable to create begin trace");
10435 return error::kNoError
;
10437 return error::kNoError
;
10440 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10441 if (gpu_tracer_
->CurrentName().empty()) {
10442 LOCAL_SET_GL_ERROR(
10443 GL_INVALID_OPERATION
,
10444 "glTraceEndCHROMIUM", "no trace begin found");
10447 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_
->CurrentName().c_str(), this);
10448 gpu_tracer_
->End(kTraceCHROMIUM
);
10451 void GLES2DecoderImpl::DoDrawBuffersEXT(
10452 GLsizei count
, const GLenum
* bufs
) {
10453 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
10454 LOCAL_SET_GL_ERROR(
10456 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10460 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
10462 for (GLsizei i
= 0; i
< count
; ++i
) {
10463 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
10464 bufs
[i
] != GL_NONE
) {
10465 LOCAL_SET_GL_ERROR(
10466 GL_INVALID_OPERATION
,
10467 "glDrawBuffersEXT",
10468 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10472 glDrawBuffersARB(count
, bufs
);
10473 framebuffer
->SetDrawBuffers(count
, bufs
);
10474 } else { // backbuffer
10476 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
10477 LOCAL_SET_GL_ERROR(
10478 GL_INVALID_OPERATION
,
10479 "glDrawBuffersEXT",
10480 "more than one buffer or bufs not GL_NONE or GL_BACK");
10483 GLenum mapped_buf
= bufs
[0];
10484 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10485 bufs
[0] == GL_BACK
) {
10486 mapped_buf
= GL_COLOR_ATTACHMENT0
;
10488 glDrawBuffersARB(count
, &mapped_buf
);
10489 group_
->set_draw_buffer(bufs
[0]);
10493 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
10494 group_
->LoseContexts(other
);
10495 reset_status_
= current
;
10496 current_decoder_error_
= error::kLostContext
;
10499 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10500 const char* function_name
,
10501 TextureRef
* texture_ref
,
10504 const void * data
) {
10505 // We only support async uploads to 2D textures for now.
10506 if (GL_TEXTURE_2D
!= target
) {
10507 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10510 // We only support uploads to level zero for now.
10512 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
10515 // A transfer buffer must be bound, even for asyncTexImage2D.
10516 if (data
== NULL
) {
10517 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
10520 // We only support one async transfer in progress.
10521 if (!texture_ref
||
10522 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10523 LOCAL_SET_GL_ERROR(
10524 GL_INVALID_OPERATION
,
10525 function_name
, "transfer already in progress");
10531 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10532 uint32 async_upload_token
,
10533 uint32 sync_data_shm_id
,
10534 uint32 sync_data_shm_offset
) {
10535 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
10536 if (!buffer
|| !buffer
->GetDataAddress(sync_data_shm_offset
,
10537 sizeof(AsyncUploadSync
)))
10538 return base::Closure();
10540 AsyncMemoryParams
mem_params(buffer
,
10541 sync_data_shm_offset
,
10542 sizeof(AsyncUploadSync
));
10544 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
10545 new AsyncUploadTokenCompletionObserver(async_upload_token
));
10548 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
10549 base::Unretained(GetAsyncPixelTransferManager()),
10554 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10555 uint32 immediate_data_size
, const cmds::AsyncTexImage2DCHROMIUM
& c
) {
10556 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10557 GLenum target
= static_cast<GLenum
>(c
.target
);
10558 GLint level
= static_cast<GLint
>(c
.level
);
10559 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10560 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10561 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10562 GLint border
= static_cast<GLint
>(c
.border
);
10563 GLenum format
= static_cast<GLenum
>(c
.format
);
10564 GLenum type
= static_cast<GLenum
>(c
.type
);
10565 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10566 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10567 uint32 pixels_size
;
10568 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10569 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10570 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10572 base::ScopedClosureRunner scoped_completion_callback
;
10573 if (async_upload_token
) {
10574 base::Closure completion_closure
=
10575 AsyncUploadTokenCompletionClosure(async_upload_token
,
10577 sync_data_shm_offset
);
10578 if (completion_closure
.is_null())
10579 return error::kInvalidArguments
;
10581 scoped_completion_callback
.Reset(completion_closure
);
10584 // TODO(epenner): Move this and copies of this memory validation
10585 // into ValidateTexImage2D step.
10586 if (!GLES2Util::ComputeImageDataSizes(
10587 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
10589 return error::kOutOfBounds
;
10591 const void* pixels
= NULL
;
10592 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10593 pixels
= GetSharedMemoryAs
<const void*>(
10594 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10596 return error::kOutOfBounds
;
10600 TextureManager::DoTextImage2DArguments args
= {
10601 target
, level
, internal_format
, width
, height
, border
, format
, type
,
10602 pixels
, pixels_size
};
10603 TextureRef
* texture_ref
;
10604 // All the normal glTexSubImage2D validation.
10605 if (!texture_manager()->ValidateTexImage2D(
10606 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
10607 return error::kNoError
;
10610 // Extra async validation.
10611 Texture
* texture
= texture_ref
->texture();
10612 if (!ValidateAsyncTransfer(
10613 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10614 return error::kNoError
;
10616 // Don't allow async redefinition of a textures.
10617 if (texture
->IsDefined()) {
10618 LOCAL_SET_GL_ERROR(
10619 GL_INVALID_OPERATION
,
10620 "glAsyncTexImage2DCHROMIUM", "already defined");
10621 return error::kNoError
;
10624 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
10625 LOCAL_SET_GL_ERROR(
10626 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
10627 return error::kNoError
;
10630 // Setup the parameters.
10631 AsyncTexImage2DParams tex_params
= {
10632 target
, level
, static_cast<GLenum
>(internal_format
),
10633 width
, height
, border
, format
, type
};
10634 AsyncMemoryParams
mem_params(
10635 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
10637 // Set up the async state if needed, and make the texture
10638 // immutable so the async state stays valid. The level info
10639 // is set up lazily when the transfer completes.
10640 AsyncPixelTransferDelegate
* delegate
=
10641 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
10643 texture
->SetImmutable(true);
10645 delegate
->AsyncTexImage2D(
10648 base::Bind(&TextureManager::SetLevelInfoFromParams
,
10649 // The callback is only invoked if the transfer delegate still
10650 // exists, which implies through manager->texture_ref->state
10651 // ownership that both of these pointers are valid.
10652 base::Unretained(texture_manager()),
10653 base::Unretained(texture_ref
),
10655 return error::kNoError
;
10658 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10659 uint32 immediate_data_size
, const cmds::AsyncTexSubImage2DCHROMIUM
& c
) {
10660 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10661 GLenum target
= static_cast<GLenum
>(c
.target
);
10662 GLint level
= static_cast<GLint
>(c
.level
);
10663 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10664 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10665 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10666 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10667 GLenum format
= static_cast<GLenum
>(c
.format
);
10668 GLenum type
= static_cast<GLenum
>(c
.type
);
10669 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10670 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10671 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10673 base::ScopedClosureRunner scoped_completion_callback
;
10674 if (async_upload_token
) {
10675 base::Closure completion_closure
=
10676 AsyncUploadTokenCompletionClosure(async_upload_token
,
10678 sync_data_shm_offset
);
10679 if (completion_closure
.is_null())
10680 return error::kInvalidArguments
;
10682 scoped_completion_callback
.Reset(completion_closure
);
10685 // TODO(epenner): Move this and copies of this memory validation
10686 // into ValidateTexSubImage2D step.
10688 if (!GLES2Util::ComputeImageDataSizes(
10689 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
10691 return error::kOutOfBounds
;
10693 const void* pixels
= GetSharedMemoryAs
<const void*>(
10694 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
10696 // All the normal glTexSubImage2D validation.
10697 error::Error error
= error::kNoError
;
10698 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
10699 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
10703 // Extra async validation.
10704 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10706 Texture
* texture
= texture_ref
->texture();
10707 if (!ValidateAsyncTransfer(
10708 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10709 return error::kNoError
;
10711 // Guarantee async textures are always 'cleared' as follows:
10712 // - AsyncTexImage2D can not redefine an existing texture
10713 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10714 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10715 // - Textures become immutable after an async call.
10716 // This way we know in all cases that an async texture is always clear.
10717 if (!texture
->SafeToRenderFrom()) {
10718 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10720 LOCAL_SET_GL_ERROR(
10722 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10723 return error::kNoError
;
10727 // Setup the parameters.
10728 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
10729 width
, height
, format
, type
};
10730 AsyncMemoryParams
mem_params(
10731 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
10732 AsyncPixelTransferDelegate
* delegate
=
10733 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10735 // TODO(epenner): We may want to enforce exclusive use
10736 // of async APIs in which case this should become an error,
10737 // (the texture should have been async defined).
10738 AsyncTexImage2DParams define_params
= {target
, level
,
10740 texture
->GetLevelSize(target
, level
, &define_params
.width
,
10741 &define_params
.height
);
10742 texture
->GetLevelType(target
, level
, &define_params
.type
,
10743 &define_params
.internal_format
);
10744 // Set up the async state if needed, and make the texture
10745 // immutable so the async state stays valid.
10746 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
10747 texture_ref
, define_params
);
10748 texture
->SetImmutable(true);
10751 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
10752 return error::kNoError
;
10755 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10756 uint32 immediate_data_size
, const cmds::WaitAsyncTexImage2DCHROMIUM
& c
) {
10757 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10758 GLenum target
= static_cast<GLenum
>(c
.target
);
10760 if (GL_TEXTURE_2D
!= target
) {
10761 LOCAL_SET_GL_ERROR(
10762 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
10763 return error::kNoError
;
10765 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10767 if (!texture_ref
) {
10768 LOCAL_SET_GL_ERROR(
10769 GL_INVALID_OPERATION
,
10770 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10771 return error::kNoError
;
10773 AsyncPixelTransferDelegate
* delegate
=
10774 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10776 LOCAL_SET_GL_ERROR(
10777 GL_INVALID_OPERATION
,
10778 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10779 return error::kNoError
;
10781 delegate
->WaitForTransferCompletion();
10782 ProcessFinishedAsyncTransfers();
10783 return error::kNoError
;
10786 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10787 uint32 immediate_data_size
, const cmds::WaitAllAsyncTexImage2DCHROMIUM
& c
) {
10788 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10790 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10791 ProcessFinishedAsyncTransfers();
10792 return error::kNoError
;
10795 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10796 TextureRef
* texture_ref
) {
10797 Texture
* texture
= texture_ref
->texture();
10798 DoDidUseTexImageIfNeeded(texture
, texture
->target());
10801 void GLES2DecoderImpl::OnOutOfMemoryError() {
10802 if (lose_context_when_out_of_memory_
) {
10803 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10804 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB
);
10808 // Include the auto-generated part of this file. We split this because it means
10809 // we can easily edit the non-auto generated parts right here in this file
10810 // instead of having to edit some template or the code generator.
10811 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10813 } // namespace gles2