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
) 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 RestoreRenderbufferBindings() OVERRIDE
;
620 virtual void RestoreTextureState(unsigned service_id
) const OVERRIDE
;
622 virtual void ClearAllAttributes() const OVERRIDE
;
623 virtual void RestoreAllAttributes() const OVERRIDE
;
625 virtual QueryManager
* GetQueryManager() OVERRIDE
{
626 return query_manager_
.get();
628 virtual VertexArrayManager
* GetVertexArrayManager() OVERRIDE
{
629 return vertex_array_manager_
.get();
631 virtual bool ProcessPendingQueries() OVERRIDE
;
632 virtual bool HasMoreIdleWork() OVERRIDE
;
633 virtual void PerformIdleWork() OVERRIDE
;
635 virtual void WaitForReadPixels(base::Closure callback
) OVERRIDE
;
637 virtual void SetResizeCallback(
638 const base::Callback
<void(gfx::Size
, float)>& callback
) OVERRIDE
;
640 virtual Logger
* GetLogger() OVERRIDE
;
642 virtual void BeginDecoding() OVERRIDE
;
643 virtual void EndDecoding() OVERRIDE
;
645 virtual ErrorState
* GetErrorState() OVERRIDE
;
646 virtual const ContextState
* GetContextState() OVERRIDE
{ return &state_
; }
648 virtual void SetShaderCacheCallback(
649 const ShaderCacheCallback
& callback
) OVERRIDE
;
650 virtual void SetWaitSyncPointCallback(
651 const WaitSyncPointCallback
& callback
) OVERRIDE
;
653 virtual AsyncPixelTransferManager
*
654 GetAsyncPixelTransferManager() OVERRIDE
;
655 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE
;
656 virtual void SetAsyncPixelTransferManagerForTest(
657 AsyncPixelTransferManager
* manager
) OVERRIDE
;
658 virtual void SetIgnoreCachedStateForTest(bool ignore
) OVERRIDE
;
659 void ProcessFinishedAsyncTransfers();
661 virtual bool GetServiceTextureId(uint32 client_texture_id
,
662 uint32
* service_texture_id
) OVERRIDE
;
664 virtual uint32
GetTextureUploadCount() OVERRIDE
;
665 virtual base::TimeDelta
GetTotalTextureUploadTime() OVERRIDE
;
666 virtual base::TimeDelta
GetTotalProcessingCommandsTime() OVERRIDE
;
667 virtual void AddProcessingCommandsTime(base::TimeDelta
) OVERRIDE
;
669 // Restores the current state to the user's settings.
670 void RestoreCurrentFramebufferBindings();
672 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
673 void ApplyDirtyState();
675 // These check the state of the currently bound framebuffer or the
676 // backbuffer if no framebuffer is bound.
677 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
678 // check with all attached and enabled color attachments.
679 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
680 bool BoundFramebufferHasDepthAttachment();
681 bool BoundFramebufferHasStencilAttachment();
683 virtual error::ContextLostReason
GetContextLostReason() OVERRIDE
;
685 // Overridden from FramebufferManager::TextureDetachObserver:
686 virtual void OnTextureRefDetachedFromFramebuffer(
687 TextureRef
* texture
) OVERRIDE
;
689 // Overriden from ErrorStateClient.
690 virtual void OnOutOfMemoryError() OVERRIDE
;
692 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
693 void EnsureRenderbufferBound();
695 // Helpers to facilitate calling into compatible extensions.
696 static void RenderbufferStorageMultisampleHelper(
697 const FeatureInfo
* feature_info
,
700 GLenum internal_format
,
704 void BlitFramebufferHelper(GLint srcX0
,
716 friend class ScopedFrameBufferBinder
;
717 friend class ScopedResolvedFrameBufferBinder
;
718 friend class BackFramebuffer
;
720 // Initialize or re-initialize the shader translator.
721 bool InitializeShaderTranslator();
723 void UpdateCapabilities();
725 // Helpers for the glGen and glDelete functions.
726 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
727 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
728 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
729 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
730 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
731 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
732 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
733 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
734 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
735 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
736 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
737 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
739 // Helper for async upload token completion notification callback.
740 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
741 uint32 sync_data_shm_id
,
742 uint32 sync_data_shm_offset
);
747 void OnFboChanged() const;
748 void OnUseFramebuffer() const;
750 // TODO(gman): Cache these pointers?
751 BufferManager
* buffer_manager() {
752 return group_
->buffer_manager();
755 RenderbufferManager
* renderbuffer_manager() {
756 return group_
->renderbuffer_manager();
759 FramebufferManager
* framebuffer_manager() {
760 return group_
->framebuffer_manager();
763 ProgramManager
* program_manager() {
764 return group_
->program_manager();
767 ShaderManager
* shader_manager() {
768 return group_
->shader_manager();
771 ShaderTranslatorCache
* shader_translator_cache() {
772 return group_
->shader_translator_cache();
775 const TextureManager
* texture_manager() const {
776 return group_
->texture_manager();
779 TextureManager
* texture_manager() {
780 return group_
->texture_manager();
783 MailboxManager
* mailbox_manager() {
784 return group_
->mailbox_manager();
787 ImageManager
* image_manager() {
788 return group_
->image_manager();
791 VertexArrayManager
* vertex_array_manager() {
792 return vertex_array_manager_
.get();
795 MemoryTracker
* memory_tracker() {
796 return group_
->memory_tracker();
799 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
800 MemoryTracker
* tracker
= memory_tracker();
802 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
807 bool IsOffscreenBufferMultisampled() const {
808 return offscreen_target_samples_
> 1;
811 // Creates a Texture for the given texture.
812 TextureRef
* CreateTexture(
813 GLuint client_id
, GLuint service_id
) {
814 return texture_manager()->CreateTexture(client_id
, service_id
);
817 // Gets the texture info for the given texture. Returns NULL if none exists.
818 TextureRef
* GetTexture(GLuint client_id
) const {
819 return texture_manager()->GetTexture(client_id
);
822 // Deletes the texture info for the given texture.
823 void RemoveTexture(GLuint client_id
) {
824 texture_manager()->RemoveTexture(client_id
);
827 // Get the size (in pixels) of the currently bound frame buffer (either FBO
828 // or regular back buffer).
829 gfx::Size
GetBoundReadFrameBufferSize();
831 // Get the format of the currently bound frame buffer (either FBO or regular
833 GLenum
GetBoundReadFrameBufferTextureType();
834 GLenum
GetBoundReadFrameBufferInternalFormat();
835 GLenum
GetBoundDrawFrameBufferInternalFormat();
837 // Wrapper for CompressedTexImage2D commands.
838 error::Error
DoCompressedTexImage2D(
841 GLenum internal_format
,
848 // Wrapper for CompressedTexSubImage2D.
849 void DoCompressedTexSubImage2D(
860 // Wrapper for CopyTexImage2D.
861 void DoCopyTexImage2D(
864 GLenum internal_format
,
871 // Wrapper for SwapBuffers.
872 void DoSwapBuffers();
874 // Wrapper for CopyTexSubImage2D.
875 void DoCopyTexSubImage2D(
885 // Validation for TexSubImage2D.
886 bool ValidateTexSubImage2D(
888 const char* function_name
,
899 // Wrapper for TexSubImage2D.
900 error::Error
DoTexSubImage2D(
911 // Extra validation for async tex(Sub)Image2D.
912 bool ValidateAsyncTransfer(
913 const char* function_name
,
914 TextureRef
* texture_ref
,
919 // Wrapper for TexImageIOSurface2DCHROMIUM.
920 void DoTexImageIOSurface2DCHROMIUM(
924 GLuint io_surface_id
,
927 void DoCopyTextureCHROMIUM(
932 GLenum internal_format
,
935 // Wrapper for TexStorage2DEXT.
936 void DoTexStorage2DEXT(
939 GLenum internal_format
,
943 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
944 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
946 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
947 GLenum target
, const GLbyte
* data
);
949 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
950 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
953 void DoBindTexImage2DCHROMIUM(
956 void DoReleaseTexImage2DCHROMIUM(
960 void DoTraceEndCHROMIUM(void);
962 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
964 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
966 // Creates a Program for the given program.
967 Program
* CreateProgram(
968 GLuint client_id
, GLuint service_id
) {
969 return program_manager()->CreateProgram(client_id
, service_id
);
972 // Gets the program info for the given program. Returns NULL if none exists.
973 Program
* GetProgram(GLuint client_id
) {
974 return program_manager()->GetProgram(client_id
);
978 void LogClientServiceMapping(
979 const char* /* function_name */,
980 GLuint
/* client_id */,
981 GLuint
/* service_id */) {
984 void LogClientServiceForInfo(
985 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
988 void LogClientServiceMapping(
989 const char* function_name
, GLuint client_id
, GLuint service_id
) {
990 if (service_logging_
) {
991 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
992 << ": client_id = " << client_id
993 << ", service_id = " << service_id
;
997 void LogClientServiceForInfo(
998 T
* info
, GLuint client_id
, const char* function_name
) {
1000 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1005 // Gets the program info for the given program. If it's not a program
1006 // generates a GL error. Returns NULL if not program.
1007 Program
* GetProgramInfoNotShader(
1008 GLuint client_id
, const char* function_name
) {
1009 Program
* program
= GetProgram(client_id
);
1011 if (GetShader(client_id
)) {
1013 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1018 LogClientServiceForInfo(program
, client_id
, function_name
);
1023 // Creates a Shader for the given shader.
1024 Shader
* CreateShader(
1027 GLenum shader_type
) {
1028 return shader_manager()->CreateShader(
1029 client_id
, service_id
, shader_type
);
1032 // Gets the shader info for the given shader. Returns NULL if none exists.
1033 Shader
* GetShader(GLuint client_id
) {
1034 return shader_manager()->GetShader(client_id
);
1037 // Gets the shader info for the given shader. If it's not a shader generates a
1038 // GL error. Returns NULL if not shader.
1039 Shader
* GetShaderInfoNotProgram(
1040 GLuint client_id
, const char* function_name
) {
1041 Shader
* shader
= GetShader(client_id
);
1043 if (GetProgram(client_id
)) {
1045 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1048 GL_INVALID_VALUE
, function_name
, "unknown shader");
1051 LogClientServiceForInfo(shader
, client_id
, function_name
);
1055 // Creates a buffer info for the given buffer.
1056 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1057 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1060 // Gets the buffer info for the given buffer.
1061 Buffer
* GetBuffer(GLuint client_id
) {
1062 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1066 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1067 // on glDeleteBuffers so we can make sure the user does not try to render
1068 // with deleted buffers.
1069 void RemoveBuffer(GLuint client_id
);
1071 // Creates a framebuffer info for the given framebuffer.
1072 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1073 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1076 // Gets the framebuffer info for the given framebuffer.
1077 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1078 return framebuffer_manager()->GetFramebuffer(client_id
);
1081 // Removes the framebuffer info for the given framebuffer.
1082 void RemoveFramebuffer(GLuint client_id
) {
1083 framebuffer_manager()->RemoveFramebuffer(client_id
);
1086 // Creates a renderbuffer info for the given renderbuffer.
1087 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1088 return renderbuffer_manager()->CreateRenderbuffer(
1089 client_id
, service_id
);
1092 // Gets the renderbuffer info for the given renderbuffer.
1093 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1094 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1097 // Removes the renderbuffer info for the given renderbuffer.
1098 void RemoveRenderbuffer(GLuint client_id
) {
1099 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1102 // Gets the vertex attrib manager for the given vertex array.
1103 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1104 VertexAttribManager
* info
=
1105 vertex_array_manager()->GetVertexAttribManager(client_id
);
1109 // Removes the vertex attrib manager for the given vertex array.
1110 void RemoveVertexAttribManager(GLuint client_id
) {
1111 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1114 // Creates a vertex attrib manager for the given vertex array.
1115 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1118 bool client_visible
) {
1119 return vertex_array_manager()->CreateVertexAttribManager(
1120 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1123 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1124 void DoBindUniformLocationCHROMIUM(
1125 GLuint client_id
, GLint location
, const char* name
);
1127 error::Error
GetAttribLocationHelper(
1128 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1129 const std::string
& name_str
);
1131 error::Error
GetUniformLocationHelper(
1132 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1133 const std::string
& name_str
);
1135 // Helper for glShaderSource.
1136 error::Error
ShaderSourceHelper(
1137 GLuint client_id
, const char* data
, uint32 data_size
);
1139 // Clear any textures used by the current program.
1140 bool ClearUnclearedTextures();
1142 // Clears any uncleared attachments attached to the given frame buffer.
1143 // Returns false if there was a generated GL error.
1144 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1146 // overridden from GLES2Decoder
1147 virtual bool ClearLevel(unsigned service_id
,
1148 unsigned bind_target
,
1151 unsigned internal_format
,
1156 bool is_texture_immutable
) OVERRIDE
;
1158 // Restore all GL state that affects clearing.
1159 void RestoreClearState();
1161 // Remembers the state of some capabilities.
1162 // Returns: true if glEnable/glDisable should actually be called.
1163 bool SetCapabilityState(GLenum cap
, bool enabled
);
1165 // Check that the currently bound framebuffers are valid.
1166 // Generates GL error if not.
1167 bool CheckBoundFramebuffersValid(const char* func_name
);
1169 // Check if a framebuffer meets our requirements.
1170 bool CheckFramebufferValid(
1171 Framebuffer
* framebuffer
,
1173 const char* func_name
);
1175 // Checks if the current program exists and is valid. If not generates the
1176 // appropriate GL error. Returns true if the current program is in a usable
1178 bool CheckCurrentProgram(const char* function_name
);
1180 // Checks if the current program exists and is valid and that location is not
1181 // -1. If the current program is not valid generates the appropriate GL
1182 // error. Returns true if the current program is in a usable state and
1183 // location is not -1.
1184 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1186 // Gets the type of a uniform for a location in the current program. Sets GL
1187 // errors if the current program is not valid. Returns true if the current
1188 // program is valid and the location exists. Adjusts count so it
1189 // does not overflow the uniform.
1190 bool PrepForSetUniformByLocation(GLint fake_location
,
1191 const char* function_name
,
1192 Program::UniformApiType api_type
,
1193 GLint
* real_location
,
1197 // Gets the service id for any simulated backbuffer fbo.
1198 GLuint
GetBackbufferServiceId() const;
1200 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1201 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1203 // Helper for glGetVertexAttrib
1204 void GetVertexAttribHelper(
1205 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1207 // Wrapper for glCreateProgram
1208 bool CreateProgramHelper(GLuint client_id
);
1210 // Wrapper for glCreateShader
1211 bool CreateShaderHelper(GLenum type
, GLuint client_id
);
1213 // Wrapper for glActiveTexture
1214 void DoActiveTexture(GLenum texture_unit
);
1216 // Wrapper for glAttachShader
1217 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1219 // Wrapper for glBindBuffer since we need to track the current targets.
1220 void DoBindBuffer(GLenum target
, GLuint buffer
);
1222 // Wrapper for glBindFramebuffer since we need to track the current targets.
1223 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1225 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1226 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1228 // Wrapper for glBindTexture since we need to track the current targets.
1229 void DoBindTexture(GLenum target
, GLuint texture
);
1231 // Wrapper for glBindVertexArrayOES
1232 void DoBindVertexArrayOES(GLuint array
);
1233 void EmulateVertexArrayState();
1235 // Wrapper for glBlitFramebufferCHROMIUM.
1236 void DoBlitFramebufferCHROMIUM(
1237 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1238 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1239 GLbitfield mask
, GLenum filter
);
1241 // Wrapper for glBufferSubData.
1242 void DoBufferSubData(
1243 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1245 // Wrapper for glCheckFramebufferStatus
1246 GLenum
DoCheckFramebufferStatus(GLenum target
);
1248 // Wrapper for glClear
1249 error::Error
DoClear(GLbitfield mask
);
1251 // Wrappers for various state.
1252 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1253 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1255 // Wrapper for glCompileShader.
1256 void DoCompileShader(GLuint shader
);
1258 // Helper for DeleteSharedIdsCHROMIUM commands.
1259 void DoDeleteSharedIdsCHROMIUM(
1260 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1262 // Wrapper for glDetachShader
1263 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1265 // Wrapper for glDisable
1266 void DoDisable(GLenum cap
);
1268 // Wrapper for glDisableVertexAttribArray.
1269 void DoDisableVertexAttribArray(GLuint index
);
1271 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1273 void DoDiscardFramebufferEXT(GLenum target
,
1274 GLsizei numAttachments
,
1275 const GLenum
* attachments
);
1277 // Wrapper for glEnable
1278 void DoEnable(GLenum cap
);
1280 // Wrapper for glEnableVertexAttribArray.
1281 void DoEnableVertexAttribArray(GLuint index
);
1283 // Wrapper for glFinish.
1286 // Wrapper for glFlush.
1289 // Wrapper for glFramebufferRenderbufffer.
1290 void DoFramebufferRenderbuffer(
1291 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1292 GLuint renderbuffer
);
1294 // Wrapper for glFramebufferTexture2D.
1295 void DoFramebufferTexture2D(
1296 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1299 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1300 void DoFramebufferTexture2DMultisample(
1301 GLenum target
, GLenum attachment
, GLenum textarget
,
1302 GLuint texture
, GLint level
, GLsizei samples
);
1304 // Common implementation for both DoFramebufferTexture2D wrappers.
1305 void DoFramebufferTexture2DCommon(const char* name
,
1306 GLenum target
, GLenum attachment
, GLenum textarget
,
1307 GLuint texture
, GLint level
, GLsizei samples
);
1309 // Wrapper for glGenerateMipmap
1310 void DoGenerateMipmap(GLenum target
);
1312 // Helper for GenSharedIdsCHROMIUM commands.
1313 void DoGenSharedIdsCHROMIUM(
1314 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
);
1316 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1317 // to account for different pname values defined in different extension
1319 GLenum
AdjustGetPname(GLenum pname
);
1321 // Wrapper for DoGetBooleanv.
1322 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1324 // Wrapper for DoGetFloatv.
1325 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1327 // Wrapper for glGetFramebufferAttachmentParameteriv.
1328 void DoGetFramebufferAttachmentParameteriv(
1329 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1331 // Wrapper for glGetIntegerv.
1332 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1334 // Gets the max value in a range in a buffer.
1335 GLuint
DoGetMaxValueInBufferCHROMIUM(
1336 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1338 // Wrapper for glGetBufferParameteriv.
1339 void DoGetBufferParameteriv(
1340 GLenum target
, GLenum pname
, GLint
* params
);
1342 // Wrapper for glGetProgramiv.
1343 void DoGetProgramiv(
1344 GLuint program_id
, GLenum pname
, GLint
* params
);
1346 // Wrapper for glRenderbufferParameteriv.
1347 void DoGetRenderbufferParameteriv(
1348 GLenum target
, GLenum pname
, GLint
* params
);
1350 // Wrapper for glGetShaderiv
1351 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1353 // Wrappers for glGetTexParameter.
1354 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1355 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1356 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1358 // Wrappers for glGetVertexAttrib.
1359 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1360 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1362 // Wrappers for glIsXXX functions.
1363 bool DoIsEnabled(GLenum cap
);
1364 bool DoIsBuffer(GLuint client_id
);
1365 bool DoIsFramebuffer(GLuint client_id
);
1366 bool DoIsProgram(GLuint client_id
);
1367 bool DoIsRenderbuffer(GLuint client_id
);
1368 bool DoIsShader(GLuint client_id
);
1369 bool DoIsTexture(GLuint client_id
);
1370 bool DoIsVertexArrayOES(GLuint client_id
);
1372 // Wrapper for glLinkProgram
1373 void DoLinkProgram(GLuint program
);
1375 // Helper for RegisterSharedIdsCHROMIUM.
1376 void DoRegisterSharedIdsCHROMIUM(
1377 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
);
1379 // Wrapper for glRenderbufferStorage.
1380 void DoRenderbufferStorage(
1381 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1383 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1384 void DoRenderbufferStorageMultisampleCHROMIUM(
1385 GLenum target
, GLsizei samples
, GLenum internalformat
,
1386 GLsizei width
, GLsizei height
);
1388 // Handler for glRenderbufferStorageMultisampleEXT
1389 // (multisampled_render_to_texture).
1390 void DoRenderbufferStorageMultisampleEXT(
1391 GLenum target
, GLsizei samples
, GLenum internalformat
,
1392 GLsizei width
, GLsizei height
);
1394 // Common validation for multisample extensions.
1395 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1396 GLenum internalformat
,
1400 // Verifies that the currently bound multisample renderbuffer is valid
1401 // Very slow! Only done on platforms with driver bugs that return invalid
1402 // buffers under memory pressure
1403 bool VerifyMultisampleRenderbufferIntegrity(
1404 GLuint renderbuffer
, GLenum format
);
1406 // Wrapper for glReleaseShaderCompiler.
1407 void DoReleaseShaderCompiler() { }
1409 // Wrappers for glTexParameter functions.
1410 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1411 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1412 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1413 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1415 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1416 // spec only these 2 functions can be used to set sampler uniforms.
1417 void DoUniform1i(GLint fake_location
, GLint v0
);
1418 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1419 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1420 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1421 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1423 // Wrappers for glUniformfv because some drivers don't correctly accept
1425 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1426 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1427 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1428 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1430 void DoUniformMatrix2fv(
1431 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1432 const GLfloat
* value
);
1433 void DoUniformMatrix3fv(
1434 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1435 const GLfloat
* value
);
1436 void DoUniformMatrix4fv(
1437 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1438 const GLfloat
* value
);
1440 bool SetVertexAttribValue(
1441 const char* function_name
, GLuint index
, const GLfloat
* value
);
1443 // Wrappers for glVertexAttrib??
1444 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1445 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1446 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1447 void DoVertexAttrib4f(
1448 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1449 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1450 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1451 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1452 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1454 // Wrapper for glViewport
1455 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1457 // Wrapper for glUseProgram
1458 void DoUseProgram(GLuint program
);
1460 // Wrapper for glValidateProgram.
1461 void DoValidateProgram(GLuint program_client_id
);
1463 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1464 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1465 void DoPopGroupMarkerEXT(void);
1467 // Gets the number of values that will be returned by glGetXXX. Returns
1468 // false if pname is unknown.
1469 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1471 // Checks if the current program and vertex attributes are valid for drawing.
1473 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
);
1475 // Returns true if successful, simulated will be true if attrib0 was
1477 bool SimulateAttrib0(
1478 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1479 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1481 // If an image is bound to texture, this will call Will/DidUseTexImage
1483 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1484 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1486 // Returns false if textures were replaced.
1487 bool PrepareTexturesForRender();
1488 void RestoreStateForTextures();
1490 // Returns true if GL_FIXED attribs were simulated.
1491 bool SimulateFixedAttribs(
1492 const char* function_name
,
1493 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1494 void RestoreStateForSimulatedFixedAttribs();
1496 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1497 // cases (primcount is 0 for non-instanced).
1498 error::Error
DoDrawArrays(
1499 const char* function_name
,
1500 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1502 error::Error
DoDrawElements(
1503 const char* function_name
,
1504 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1505 int32 offset
, GLsizei primcount
);
1507 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1508 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1509 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1512 return GL_TEXTURE_2D
;
1513 case GL_SAMPLER_CUBE
:
1514 return GL_TEXTURE_CUBE_MAP
;
1515 case GL_SAMPLER_EXTERNAL_OES
:
1516 return GL_TEXTURE_EXTERNAL_OES
;
1517 case GL_SAMPLER_2D_RECT_ARB
:
1518 return GL_TEXTURE_RECTANGLE_ARB
;
1525 // Gets the framebuffer info for a particular target.
1526 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1527 Framebuffer
* framebuffer
= NULL
;
1529 case GL_FRAMEBUFFER
:
1530 case GL_DRAW_FRAMEBUFFER_EXT
:
1531 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1533 case GL_READ_FRAMEBUFFER_EXT
:
1534 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1543 Renderbuffer
* GetRenderbufferInfoForTarget(
1545 Renderbuffer
* renderbuffer
= NULL
;
1547 case GL_RENDERBUFFER
:
1548 renderbuffer
= state_
.bound_renderbuffer
.get();
1554 return renderbuffer
;
1557 // Validates the program and location for a glGetUniform call and returns
1558 // a SizeResult setup to receive the result. Returns true if glGetUniform
1559 // should be called.
1560 bool GetUniformSetup(
1561 GLuint program
, GLint fake_location
,
1562 uint32 shm_id
, uint32 shm_offset
,
1563 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1564 void** result
, GLenum
* result_type
);
1566 virtual bool WasContextLost() OVERRIDE
;
1567 virtual bool WasContextLostByRobustnessExtension() OVERRIDE
;
1568 virtual void LoseContext(uint32 reset_status
) OVERRIDE
;
1570 #if defined(OS_MACOSX)
1571 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1574 bool ValidateCompressedTexDimensions(
1575 const char* function_name
,
1576 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1577 bool ValidateCompressedTexFuncData(
1578 const char* function_name
,
1579 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1580 bool ValidateCompressedTexSubDimensions(
1581 const char* function_name
,
1582 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1583 GLsizei width
, GLsizei height
, GLenum format
,
1586 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1587 void PerformanceWarning(
1588 const char* filename
, int line
, const std::string
& msg
);
1590 const FeatureInfo::FeatureFlags
& features() const {
1591 return feature_info_
->feature_flags();
1594 const FeatureInfo::Workarounds
& workarounds() const {
1595 return feature_info_
->workarounds();
1598 bool ShouldDeferDraws() {
1599 return !offscreen_target_frame_buffer_
.get() &&
1600 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1601 surface_
->DeferDraws();
1604 bool ShouldDeferReads() {
1605 return !offscreen_target_frame_buffer_
.get() &&
1606 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1607 surface_
->DeferDraws();
1610 error::Error
WillAccessBoundFramebufferForDraw() {
1611 if (ShouldDeferDraws())
1612 return error::kDeferCommandUntilLater
;
1613 if (!offscreen_target_frame_buffer_
.get() &&
1614 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1615 !surface_
->SetBackbufferAllocation(true))
1616 return error::kLostContext
;
1617 return error::kNoError
;
1620 error::Error
WillAccessBoundFramebufferForRead() {
1621 if (ShouldDeferReads())
1622 return error::kDeferCommandUntilLater
;
1623 if (!offscreen_target_frame_buffer_
.get() &&
1624 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1625 !surface_
->SetBackbufferAllocation(true))
1626 return error::kLostContext
;
1627 return error::kNoError
;
1630 void ProcessPendingReadPixels();
1631 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1633 // Generate a member function prototype for each command in an automated and
1635 #define GLES2_CMD_OP(name) \
1636 Error Handle ## name( \
1637 uint32 immediate_data_size, \
1638 const cmds::name& args); \
1640 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1644 // The GL context this decoder renders to on behalf of the client.
1645 scoped_refptr
<gfx::GLSurface
> surface_
;
1646 scoped_refptr
<gfx::GLContext
> context_
;
1648 // The ContextGroup for this decoder uses to track resources.
1649 scoped_refptr
<ContextGroup
> group_
;
1651 DebugMarkerManager debug_marker_manager_
;
1654 // All the state for this context.
1655 ContextState state_
;
1657 // Current width and height of the offscreen frame buffer.
1658 gfx::Size offscreen_size_
;
1660 // Util to help with GL.
1663 // unpack flip y as last set by glPixelStorei
1664 bool unpack_flip_y_
;
1666 // unpack (un)premultiply alpha as last set by glPixelStorei
1667 bool unpack_premultiply_alpha_
;
1668 bool unpack_unpremultiply_alpha_
;
1670 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1671 GLuint attrib_0_buffer_id_
;
1673 // The value currently in attrib_0.
1674 Vec4 attrib_0_value_
;
1676 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1677 bool attrib_0_buffer_matches_value_
;
1679 // The size of attrib 0.
1680 GLsizei attrib_0_size_
;
1682 // The buffer used to simulate GL_FIXED attribs.
1683 GLuint fixed_attrib_buffer_id_
;
1685 // The size of fiixed attrib buffer.
1686 GLsizei fixed_attrib_buffer_size_
;
1688 // The offscreen frame buffer that the client renders to. With EGL, the
1689 // depth and stencil buffers are separate. With regular GL there is a single
1690 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1691 // offscreen_target_stencil_render_buffer_ is unused.
1692 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1693 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1694 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1695 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1696 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1697 GLenum offscreen_target_color_format_
;
1698 GLenum offscreen_target_depth_format_
;
1699 GLenum offscreen_target_stencil_format_
;
1700 GLsizei offscreen_target_samples_
;
1701 GLboolean offscreen_target_buffer_preserved_
;
1703 // The copy that is saved when SwapBuffers is called.
1704 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1705 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1706 scoped_refptr
<TextureRef
>
1707 offscreen_saved_color_texture_info_
;
1709 // The copy that is used as the destination for multi-sample resolves.
1710 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1711 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1712 GLenum offscreen_saved_color_format_
;
1714 scoped_ptr
<QueryManager
> query_manager_
;
1716 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1718 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1720 WaitSyncPointCallback wait_sync_point_callback_
;
1722 ShaderCacheCallback shader_cache_callback_
;
1724 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1726 // The format of the back buffer_
1727 GLenum back_buffer_color_format_
;
1728 bool back_buffer_has_depth_
;
1729 bool back_buffer_has_stencil_
;
1731 // Backbuffer attachments that are currently undefined.
1732 uint32 backbuffer_needs_clear_bits_
;
1734 // The current decoder error communicates the decoder error through command
1735 // processing functions that do not return the error value. Should be set only
1736 // if not returning an error.
1737 error::Error current_decoder_error_
;
1739 bool use_shader_translator_
;
1740 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1741 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1743 DisallowedFeatures disallowed_features_
;
1745 // Cached from ContextGroup
1746 const Validators
* validators_
;
1747 scoped_refptr
<FeatureInfo
> feature_info_
;
1751 bool has_robustness_extension_
;
1752 GLenum reset_status_
;
1753 bool reset_by_robustness_extension_
;
1754 bool supports_post_sub_buffer_
;
1756 // These flags are used to override the state of the shared feature_info_
1757 // member. Because the same FeatureInfo instance may be shared among many
1758 // contexts, the assumptions on the availablity of extensions in WebGL
1759 // contexts may be broken. These flags override the shared state to preserve
1761 bool force_webgl_glsl_validation_
;
1762 bool derivatives_explicitly_enabled_
;
1763 bool frag_depth_explicitly_enabled_
;
1764 bool draw_buffers_explicitly_enabled_
;
1765 bool shader_texture_lod_explicitly_enabled_
;
1767 bool compile_shader_always_succeeds_
;
1769 // An optional behaviour to lose the context and group when OOM.
1770 bool lose_context_when_out_of_memory_
;
1773 bool service_logging_
;
1775 #if defined(OS_MACOSX)
1776 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1777 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1780 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1782 // Cached values of the currently assigned viewport dimensions.
1783 GLsizei viewport_max_width_
;
1784 GLsizei viewport_max_height_
;
1786 // Command buffer stats.
1787 base::TimeDelta total_processing_commands_time_
;
1789 // States related to each manager.
1790 DecoderTextureState texture_state_
;
1791 DecoderFramebufferState framebuffer_state_
;
1793 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1794 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1795 int gpu_trace_level_
;
1796 bool gpu_trace_commands_
;
1798 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1800 // Used to validate multisample renderbuffers if needed
1801 GLuint validation_texture_
;
1802 GLuint validation_fbo_multisample_
;
1803 GLuint validation_fbo_
;
1805 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1808 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1809 const char* function_name
, ErrorState
* error_state
)
1810 : function_name_(function_name
),
1811 error_state_(error_state
) {
1812 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1815 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1816 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1819 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1820 TextureUnit
& info
= state
->texture_units
[0];
1822 scoped_refptr
<TextureRef
> texture_ref
;
1825 texture_ref
= info
.bound_texture_2d
;
1827 case GL_TEXTURE_CUBE_MAP
:
1828 texture_ref
= info
.bound_texture_cube_map
;
1830 case GL_TEXTURE_EXTERNAL_OES
:
1831 texture_ref
= info
.bound_texture_external_oes
;
1833 case GL_TEXTURE_RECTANGLE_ARB
:
1834 texture_ref
= info
.bound_texture_rectangle_arb
;
1840 if (texture_ref
.get()) {
1841 last_id
= texture_ref
->service_id();
1846 glBindTexture(target
, last_id
);
1847 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1850 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1855 ScopedGLErrorSuppressor
suppressor(
1856 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1858 // TODO(apatrick): Check if there are any other states that need to be reset
1859 // before binding a new texture.
1860 glActiveTexture(GL_TEXTURE0
);
1861 glBindTexture(target
, id
);
1864 ScopedTextureBinder::~ScopedTextureBinder() {
1865 ScopedGLErrorSuppressor
suppressor(
1866 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1867 RestoreCurrentTextureBindings(state_
, target_
);
1870 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1873 ScopedGLErrorSuppressor
suppressor(
1874 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1875 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1878 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1879 ScopedGLErrorSuppressor
suppressor(
1880 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
1881 state_
->RestoreRenderbufferBindings();
1884 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
1886 : decoder_(decoder
) {
1887 ScopedGLErrorSuppressor
suppressor(
1888 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1889 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
1890 decoder
->OnFboChanged();
1893 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1894 ScopedGLErrorSuppressor
suppressor(
1895 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1896 decoder_
->RestoreCurrentFramebufferBindings();
1899 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1900 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
1901 : decoder_(decoder
) {
1902 resolve_and_bind_
= (
1903 decoder_
->offscreen_target_frame_buffer_
.get() &&
1904 decoder_
->IsOffscreenBufferMultisampled() &&
1905 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
1906 enforce_internal_framebuffer
));
1907 if (!resolve_and_bind_
)
1910 ScopedGLErrorSuppressor
suppressor(
1911 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
1912 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
1913 decoder_
->offscreen_target_frame_buffer_
->id());
1916 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
1917 decoder_
->offscreen_resolved_frame_buffer_
.reset(
1918 new BackFramebuffer(decoder_
));
1919 decoder_
->offscreen_resolved_frame_buffer_
->Create();
1920 decoder_
->offscreen_resolved_color_texture_
.reset(
1921 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
1922 decoder_
->offscreen_resolved_color_texture_
->Create();
1924 DCHECK(decoder_
->offscreen_saved_color_format_
);
1925 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
1926 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
1928 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
1929 decoder_
->offscreen_resolved_color_texture_
.get());
1930 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
1931 GL_FRAMEBUFFER_COMPLETE
) {
1932 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
1933 << "because offscreen resolved FBO was incomplete.";
1937 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
1939 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
1941 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
1942 const int width
= decoder_
->offscreen_size_
.width();
1943 const int height
= decoder_
->offscreen_size_
.height();
1944 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
1945 decoder
->BlitFramebufferHelper(0,
1953 GL_COLOR_BUFFER_BIT
,
1955 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
1958 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1959 if (!resolve_and_bind_
)
1962 ScopedGLErrorSuppressor
suppressor(
1963 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
1964 decoder_
->RestoreCurrentFramebufferBindings();
1965 if (decoder_
->state_
.enable_flags
.scissor_test
) {
1966 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
1970 BackTexture::BackTexture(
1971 MemoryTracker
* memory_tracker
,
1972 ContextState
* state
)
1973 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
1975 bytes_allocated_(0),
1979 BackTexture::~BackTexture() {
1980 // This does not destroy the render texture because that would require that
1981 // the associated GL context was current. Just check that it was explicitly
1986 void BackTexture::Create() {
1987 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
1988 state_
->GetErrorState());
1990 glGenTextures(1, &id_
);
1991 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
1992 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
1993 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1994 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1995 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1997 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1998 // never called on an offscreen context, no data will ever be uploaded to the
1999 // saved offscreen color texture (it is deferred until to when SwapBuffers
2000 // is called). My idea is that some nvidia drivers might have a bug where
2001 // deleting a texture that has never been populated might cause a
2004 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2006 bytes_allocated_
= 16u * 16u * 4u;
2007 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2010 bool BackTexture::AllocateStorage(
2011 const gfx::Size
& size
, GLenum format
, bool zero
) {
2013 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2014 state_
->GetErrorState());
2015 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2016 uint32 image_size
= 0;
2017 GLES2Util::ComputeImageDataSizes(
2018 size
.width(), size
.height(), format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2021 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2025 scoped_ptr
<char[]> zero_data
;
2027 zero_data
.reset(new char[image_size
]);
2028 memset(zero_data
.get(), 0, image_size
);
2031 glTexImage2D(GL_TEXTURE_2D
,
2043 bool success
= glGetError() == GL_NO_ERROR
;
2045 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2046 bytes_allocated_
= image_size
;
2047 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2052 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2054 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2055 state_
->GetErrorState());
2056 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2057 glCopyTexImage2D(GL_TEXTURE_2D
,
2066 void BackTexture::Destroy() {
2068 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2069 state_
->GetErrorState());
2070 glDeleteTextures(1, &id_
);
2073 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2074 bytes_allocated_
= 0;
2077 void BackTexture::Invalidate() {
2081 BackRenderbuffer::BackRenderbuffer(
2082 RenderbufferManager
* renderbuffer_manager
,
2083 MemoryTracker
* memory_tracker
,
2084 ContextState
* state
)
2085 : renderbuffer_manager_(renderbuffer_manager
),
2086 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2088 bytes_allocated_(0),
2092 BackRenderbuffer::~BackRenderbuffer() {
2093 // This does not destroy the render buffer because that would require that
2094 // the associated GL context was current. Just check that it was explicitly
2099 void BackRenderbuffer::Create() {
2100 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2101 state_
->GetErrorState());
2103 glGenRenderbuffersEXT(1, &id_
);
2106 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2107 const gfx::Size
& size
,
2110 ScopedGLErrorSuppressor
suppressor(
2111 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2112 ScopedRenderBufferBinder
binder(state_
, id_
);
2114 uint32 estimated_size
= 0;
2115 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2116 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2120 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2125 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2130 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2137 bool success
= glGetError() == GL_NO_ERROR
;
2139 // Mark the previously allocated bytes as free.
2140 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2141 bytes_allocated_
= estimated_size
;
2142 // Track the newly allocated bytes.
2143 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2148 void BackRenderbuffer::Destroy() {
2150 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2151 state_
->GetErrorState());
2152 glDeleteRenderbuffersEXT(1, &id_
);
2155 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2156 bytes_allocated_
= 0;
2159 void BackRenderbuffer::Invalidate() {
2163 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2164 : decoder_(decoder
),
2168 BackFramebuffer::~BackFramebuffer() {
2169 // This does not destroy the frame buffer because that would require that
2170 // the associated GL context was current. Just check that it was explicitly
2175 void BackFramebuffer::Create() {
2176 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2177 decoder_
->GetErrorState());
2179 glGenFramebuffersEXT(1, &id_
);
2182 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2184 ScopedGLErrorSuppressor
suppressor(
2185 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2186 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2187 GLuint attach_id
= texture
? texture
->id() : 0;
2188 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2189 GL_COLOR_ATTACHMENT0
,
2195 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2196 BackRenderbuffer
* render_buffer
) {
2198 ScopedGLErrorSuppressor
suppressor(
2199 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2200 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2201 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2202 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2208 void BackFramebuffer::Destroy() {
2210 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2211 decoder_
->GetErrorState());
2212 glDeleteFramebuffersEXT(1, &id_
);
2217 void BackFramebuffer::Invalidate() {
2221 GLenum
BackFramebuffer::CheckStatus() {
2223 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2224 decoder_
->GetErrorState());
2225 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2226 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2229 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2230 return new GLES2DecoderImpl(group
);
2233 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2236 logger_(&debug_marker_manager_
),
2237 state_(group_
->feature_info(), this, &logger_
),
2238 unpack_flip_y_(false),
2239 unpack_premultiply_alpha_(false),
2240 unpack_unpremultiply_alpha_(false),
2241 attrib_0_buffer_id_(0),
2242 attrib_0_buffer_matches_value_(true),
2244 fixed_attrib_buffer_id_(0),
2245 fixed_attrib_buffer_size_(0),
2246 offscreen_target_color_format_(0),
2247 offscreen_target_depth_format_(0),
2248 offscreen_target_stencil_format_(0),
2249 offscreen_target_samples_(0),
2250 offscreen_target_buffer_preserved_(true),
2251 offscreen_saved_color_format_(0),
2252 back_buffer_color_format_(0),
2253 back_buffer_has_depth_(false),
2254 back_buffer_has_stencil_(false),
2255 backbuffer_needs_clear_bits_(0),
2256 current_decoder_error_(error::kNoError
),
2257 use_shader_translator_(true),
2258 validators_(group_
->feature_info()->validators()),
2259 feature_info_(group_
->feature_info()),
2261 has_robustness_extension_(false),
2262 reset_status_(GL_NO_ERROR
),
2263 reset_by_robustness_extension_(false),
2264 supports_post_sub_buffer_(false),
2265 force_webgl_glsl_validation_(false),
2266 derivatives_explicitly_enabled_(false),
2267 frag_depth_explicitly_enabled_(false),
2268 draw_buffers_explicitly_enabled_(false),
2269 shader_texture_lod_explicitly_enabled_(false),
2270 compile_shader_always_succeeds_(false),
2271 lose_context_when_out_of_memory_(false),
2272 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2273 switches::kEnableGPUServiceLoggingGPU
)),
2274 viewport_max_width_(0),
2275 viewport_max_height_(0),
2276 texture_state_(group_
->feature_info()
2278 .texsubimage2d_faster_than_teximage2d
),
2279 validation_texture_(0),
2280 validation_fbo_multisample_(0),
2281 validation_fbo_(0) {
2284 attrib_0_value_
.v
[0] = 0.0f
;
2285 attrib_0_value_
.v
[1] = 0.0f
;
2286 attrib_0_value_
.v
[2] = 0.0f
;
2287 attrib_0_value_
.v
[3] = 1.0f
;
2289 // The shader translator is used for WebGL even when running on EGL
2290 // because additional restrictions are needed (like only enabling
2291 // GL_OES_standard_derivatives on demand). It is used for the unit
2292 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2293 // the empty string to CompileShader and this is not a valid shader.
2294 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2295 CommandLine::ForCurrentProcess()->HasSwitch(
2296 switches::kDisableGLSLTranslator
)) {
2297 use_shader_translator_
= false;
2301 GLES2DecoderImpl::~GLES2DecoderImpl() {
2304 bool GLES2DecoderImpl::Initialize(
2305 const scoped_refptr
<gfx::GLSurface
>& surface
,
2306 const scoped_refptr
<gfx::GLContext
>& context
,
2308 const gfx::Size
& size
,
2309 const DisallowedFeatures
& disallowed_features
,
2310 const std::vector
<int32
>& attribs
) {
2311 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2312 DCHECK(context
->IsCurrent(surface
.get()));
2313 DCHECK(!context_
.get());
2316 gpu_tracer_
= GPUTracer::Create(this);
2317 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2318 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2319 gpu_trace_level_
= 2;
2320 gpu_trace_commands_
= false;
2322 if (CommandLine::ForCurrentProcess()->HasSwitch(
2323 switches::kEnableGPUDebugging
)) {
2327 if (CommandLine::ForCurrentProcess()->HasSwitch(
2328 switches::kEnableGPUCommandLogging
)) {
2329 set_log_commands(true);
2332 compile_shader_always_succeeds_
= CommandLine::ForCurrentProcess()->HasSwitch(
2333 switches::kCompileShaderAlwaysSucceeds
);
2336 // Take ownership of the context and surface. The surface can be replaced with
2341 ContextCreationAttribHelper attrib_parser
;
2342 if (!attrib_parser
.Parse(attribs
))
2345 // Save the loseContextWhenOutOfMemory context creation attribute.
2346 lose_context_when_out_of_memory_
=
2347 attrib_parser
.lose_context_when_out_of_memory_
;
2349 // If the failIfMajorPerformanceCaveat context creation attribute was true
2350 // and we are using a software renderer, fail.
2351 if (attrib_parser
.fail_if_major_perf_caveat_
&&
2352 feature_info_
->feature_flags().is_swiftshader
) {
2353 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2358 if (!group_
->Initialize(this, disallowed_features
)) {
2359 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2360 << "failed to initialize.";
2361 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2367 disallowed_features_
= disallowed_features
;
2369 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2370 vertex_array_manager_
.reset(new VertexArrayManager());
2372 GLuint default_vertex_attrib_service_id
= 0;
2373 if (features().native_vertex_array_object
) {
2374 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2375 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2378 state_
.default_vertex_attrib_manager
=
2379 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2381 state_
.default_vertex_attrib_manager
->Initialize(
2382 group_
->max_vertex_attribs(),
2383 feature_info_
->workarounds().init_vertex_attributes
);
2385 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2386 DoBindVertexArrayOES(0);
2388 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2390 util_
.set_num_compressed_texture_formats(
2391 validators_
->compressed_texture_format
.GetValues().size());
2393 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2394 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2395 // OpenGL ES 2.0 does not have this issue.
2396 glEnableVertexAttribArray(0);
2398 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2399 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2400 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2401 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2402 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2404 state_
.texture_units
.resize(group_
->max_texture_units());
2405 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2406 glActiveTexture(GL_TEXTURE0
+ tt
);
2407 // We want the last bind to be 2D.
2409 if (features().oes_egl_image_external
) {
2410 ref
= texture_manager()->GetDefaultTextureInfo(
2411 GL_TEXTURE_EXTERNAL_OES
);
2412 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2413 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2415 if (features().arb_texture_rectangle
) {
2416 ref
= texture_manager()->GetDefaultTextureInfo(
2417 GL_TEXTURE_RECTANGLE_ARB
);
2418 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2419 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2421 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2422 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2423 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2424 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2425 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2426 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2428 glActiveTexture(GL_TEXTURE0
);
2432 if (attrib_parser
.samples_
> 0 && attrib_parser
.sample_buffers_
> 0 &&
2433 features().chromium_framebuffer_multisample
) {
2434 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2435 // max_sample_count must be initialized to a sane value. If
2436 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2437 GLint max_sample_count
= 1;
2438 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2439 offscreen_target_samples_
= std::min(attrib_parser
.samples_
,
2442 offscreen_target_samples_
= 1;
2444 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved_
;
2446 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2447 const bool rgb8_supported
=
2448 context_
->HasExtension("GL_OES_rgb8_rgba8");
2449 // The only available default render buffer formats in GLES2 have very
2450 // little precision. Don't enable multisampling unless 8-bit render
2451 // buffer formats are available--instead fall back to 8-bit textures.
2452 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2453 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2456 offscreen_target_samples_
= 1;
2457 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2461 // ANGLE only supports packed depth/stencil formats, so use it if it is
2463 const bool depth24_stencil8_supported
=
2464 feature_info_
->feature_flags().packed_depth24_stencil8
;
2465 VLOG(1) << "GL_OES_packed_depth_stencil "
2466 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2467 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2468 depth24_stencil8_supported
) {
2469 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2470 offscreen_target_stencil_format_
= 0;
2472 // It may be the case that this depth/stencil combination is not
2473 // supported, but this will be checked later by CheckFramebufferStatus.
2474 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2475 GL_DEPTH_COMPONENT16
: 0;
2476 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2477 GL_STENCIL_INDEX8
: 0;
2480 offscreen_target_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2483 // If depth is requested at all, use the packed depth stencil format if
2484 // it's available, as some desktop GL drivers don't support any non-packed
2485 // formats for depth attachments.
2486 const bool depth24_stencil8_supported
=
2487 feature_info_
->feature_flags().packed_depth24_stencil8
;
2488 VLOG(1) << "GL_EXT_packed_depth_stencil "
2489 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2491 if ((attrib_parser
.depth_size_
> 0 || attrib_parser
.stencil_size_
> 0) &&
2492 depth24_stencil8_supported
) {
2493 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2494 offscreen_target_stencil_format_
= 0;
2496 offscreen_target_depth_format_
= attrib_parser
.depth_size_
> 0 ?
2497 GL_DEPTH_COMPONENT
: 0;
2498 offscreen_target_stencil_format_
= attrib_parser
.stencil_size_
> 0 ?
2499 GL_STENCIL_INDEX
: 0;
2503 offscreen_saved_color_format_
= attrib_parser
.alpha_size_
> 0 ?
2506 // Create the target frame buffer. This is the one that the client renders
2508 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2509 offscreen_target_frame_buffer_
->Create();
2510 // Due to GLES2 format limitations, either the color texture (for
2511 // non-multisampling) or the color render buffer (for multisampling) will be
2512 // attached to the offscreen frame buffer. The render buffer has more
2513 // limited formats available to it, but the texture can't do multisampling.
2514 if (IsOffscreenBufferMultisampled()) {
2515 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2516 renderbuffer_manager(), memory_tracker(), &state_
));
2517 offscreen_target_color_render_buffer_
->Create();
2519 offscreen_target_color_texture_
.reset(new BackTexture(
2520 memory_tracker(), &state_
));
2521 offscreen_target_color_texture_
->Create();
2523 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2524 renderbuffer_manager(), memory_tracker(), &state_
));
2525 offscreen_target_depth_render_buffer_
->Create();
2526 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2527 renderbuffer_manager(), memory_tracker(), &state_
));
2528 offscreen_target_stencil_render_buffer_
->Create();
2530 // Create the saved offscreen texture. The target frame buffer is copied
2531 // here when SwapBuffers is called.
2532 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2533 offscreen_saved_frame_buffer_
->Create();
2535 offscreen_saved_color_texture_
.reset(new BackTexture(
2536 memory_tracker(), &state_
));
2537 offscreen_saved_color_texture_
->Create();
2539 // Allocate the render buffers at their initial size and check the status
2540 // of the frame buffers is okay.
2541 if (!ResizeOffscreenFrameBuffer(size
)) {
2542 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2547 // Allocate the offscreen saved color texture.
2548 DCHECK(offscreen_saved_color_format_
);
2549 offscreen_saved_color_texture_
->AllocateStorage(
2550 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2552 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2553 offscreen_saved_color_texture_
.get());
2554 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2555 GL_FRAMEBUFFER_COMPLETE
) {
2556 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2561 // Bind to the new default frame buffer (the offscreen target frame buffer).
2562 // This should now be associated with ID zero.
2563 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2565 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2566 // These are NOT if the back buffer has these proprorties. They are
2567 // if we want the command buffer to enforce them regardless of what
2568 // the real backbuffer is assuming the real back buffer gives us more than
2569 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2570 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2571 // can't do anything about that.
2574 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2575 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2576 // user requested RGB then RGB. If the user did not specify a preference
2577 // than use whatever we were given. Same for DEPTH and STENCIL.
2578 back_buffer_color_format_
=
2579 (attrib_parser
.alpha_size_
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2580 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2581 back_buffer_has_depth_
= attrib_parser
.depth_size_
!= 0 && v
> 0;
2582 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2583 back_buffer_has_stencil_
= attrib_parser
.stencil_size_
!= 0 && v
> 0;
2586 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2587 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2588 // isn't well documented; it was discovered in the Khronos OpenGL ES
2589 // mailing list archives. It also implicitly enables the desktop GL
2590 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2591 // variable in fragment shaders.
2592 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2593 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2594 glEnable(GL_POINT_SPRITE
);
2597 has_robustness_extension_
=
2598 context
->HasExtension("GL_ARB_robustness") ||
2599 context
->HasExtension("GL_EXT_robustness");
2601 if (!InitializeShaderTranslator()) {
2605 state_
.viewport_width
= size
.width();
2606 state_
.viewport_height
= size
.height();
2608 GLint viewport_params
[4] = { 0 };
2609 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2610 viewport_max_width_
= viewport_params
[0];
2611 viewport_max_height_
= viewport_params
[1];
2613 state_
.scissor_width
= state_
.viewport_width
;
2614 state_
.scissor_height
= state_
.viewport_height
;
2616 // Set all the default state because some GL drivers get it wrong.
2617 state_
.InitCapabilities(NULL
);
2618 state_
.InitState(NULL
);
2619 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2621 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2622 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2623 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2624 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2626 bool call_gl_clear
= true;
2627 #if defined(OS_ANDROID)
2628 // Temporary workaround for Android WebView because this clear ignores the
2629 // clip and corrupts that external UI of the App. Not calling glClear is ok
2630 // because the system already clears the buffer before each draw. Proper
2631 // fix might be setting the scissor clip properly before initialize. See
2632 // crbug.com/259023 for details.
2633 call_gl_clear
= surface_
->GetHandle();
2635 if (call_gl_clear
) {
2636 // Clear the backbuffer.
2637 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2640 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2641 if (feature_info_
->workarounds()
2642 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2643 !surface
->IsOffscreen())
2644 supports_post_sub_buffer_
= false;
2646 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2647 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2650 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2651 context_
->SetUnbindFboOnMakeCurrent();
2654 if (feature_info_
->workarounds().release_image_after_use
) {
2655 image_manager()->SetReleaseAfterUse();
2658 // Only compositor contexts are known to use only the subset of GL
2659 // that can be safely migrated between the iGPU and the dGPU. Mark
2660 // those contexts as safe to forcibly transition between the GPUs.
2661 // http://crbug.com/180876, http://crbug.com/227228
2663 context_
->SetSafeToForceGpuSwitch();
2665 async_pixel_transfer_manager_
.reset(
2666 AsyncPixelTransferManager::Create(context
.get()));
2667 async_pixel_transfer_manager_
->Initialize(texture_manager());
2669 framebuffer_manager()->AddObserver(this);
2674 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2675 DCHECK(initialized());
2679 caps
.fast_npot_mo8_textures
=
2680 feature_info_
->workarounds().enable_chromium_fast_npot_mo8_textures
;
2681 caps
.egl_image_external
=
2682 feature_info_
->feature_flags().oes_egl_image_external
;
2683 caps
.texture_format_bgra8888
=
2684 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2685 caps
.texture_format_etc1
=
2686 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2687 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2688 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2689 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2690 caps
.discard_framebuffer
=
2691 feature_info_
->feature_flags().ext_discard_framebuffer
;
2692 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2694 #if defined(OS_MACOSX)
2695 // This is unconditionally true on mac, no need to test for it at runtime.
2696 caps
.iosurface
= true;
2699 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2700 caps
.map_image
= !!image_manager();
2705 void GLES2DecoderImpl::UpdateCapabilities() {
2706 util_
.set_num_compressed_texture_formats(
2707 validators_
->compressed_texture_format
.GetValues().size());
2708 util_
.set_num_shader_binary_formats(
2709 validators_
->shader_binary_format
.GetValues().size());
2712 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2713 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2715 if (!use_shader_translator_
) {
2718 ShBuiltInResources resources
;
2719 ShInitBuiltInResources(&resources
);
2720 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2721 resources
.MaxVertexUniformVectors
=
2722 group_
->max_vertex_uniform_vectors();
2723 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2724 resources
.MaxVertexTextureImageUnits
=
2725 group_
->max_vertex_texture_image_units();
2726 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2727 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2728 resources
.MaxFragmentUniformVectors
=
2729 group_
->max_fragment_uniform_vectors();
2730 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2731 resources
.MaxExpressionComplexity
= 256;
2732 resources
.MaxCallStackDepth
= 256;
2734 #if (ANGLE_SH_VERSION >= 110)
2735 GLint range
[2] = { 0, 0 };
2736 GLint precision
= 0;
2737 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2739 resources
.FragmentPrecisionHigh
=
2740 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2743 if (force_webgl_glsl_validation_
) {
2744 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2745 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2746 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2747 if (!draw_buffers_explicitly_enabled_
)
2748 resources
.MaxDrawBuffers
= 1;
2749 #if (ANGLE_SH_VERSION >= 123)
2750 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2753 resources
.OES_standard_derivatives
=
2754 features().oes_standard_derivatives
? 1 : 0;
2755 resources
.ARB_texture_rectangle
=
2756 features().arb_texture_rectangle
? 1 : 0;
2757 resources
.OES_EGL_image_external
=
2758 features().oes_egl_image_external
? 1 : 0;
2759 resources
.EXT_draw_buffers
=
2760 features().ext_draw_buffers
? 1 : 0;
2761 resources
.EXT_frag_depth
=
2762 features().ext_frag_depth
? 1 : 0;
2763 #if (ANGLE_SH_VERSION >= 123)
2764 resources
.EXT_shader_texture_lod
=
2765 features().ext_shader_texture_lod
? 1 : 0;
2769 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2771 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2772 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2773 resources
.HashFunction
= &CityHashForAngle
;
2775 resources
.HashFunction
= &CityHash64
;
2778 resources
.HashFunction
= NULL
;
2779 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2780 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2781 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2782 int driver_bug_workarounds
= 0;
2783 if (workarounds().needs_glsl_built_in_function_emulation
)
2784 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2785 if (workarounds().init_gl_position_in_vertex_shader
)
2786 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2787 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2788 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2789 if (workarounds().init_varyings_without_static_use
)
2790 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2791 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2792 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2794 vertex_translator_
= shader_translator_cache()->GetTranslator(
2798 implementation_type
,
2799 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2800 if (!vertex_translator_
.get()) {
2801 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2806 fragment_translator_
= shader_translator_cache()->GetTranslator(
2810 implementation_type
,
2811 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2812 if (!fragment_translator_
.get()) {
2813 LOG(ERROR
) << "Could not initialize fragment shader translator.";
2820 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
2821 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2822 if (GetBuffer(client_ids
[ii
])) {
2826 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2827 glGenBuffersARB(n
, service_ids
.get());
2828 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2829 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
2834 bool GLES2DecoderImpl::GenFramebuffersHelper(
2835 GLsizei n
, const GLuint
* client_ids
) {
2836 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2837 if (GetFramebuffer(client_ids
[ii
])) {
2841 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2842 glGenFramebuffersEXT(n
, service_ids
.get());
2843 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2844 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
2849 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2850 GLsizei n
, const GLuint
* client_ids
) {
2851 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2852 if (GetRenderbuffer(client_ids
[ii
])) {
2856 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2857 glGenRenderbuffersEXT(n
, service_ids
.get());
2858 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2859 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
2864 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
2865 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2866 if (GetTexture(client_ids
[ii
])) {
2870 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
2871 glGenTextures(n
, service_ids
.get());
2872 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2873 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
2878 void GLES2DecoderImpl::DeleteBuffersHelper(
2879 GLsizei n
, const GLuint
* client_ids
) {
2880 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2881 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
2882 if (buffer
&& !buffer
->IsDeleted()) {
2883 state_
.vertex_attrib_manager
->Unbind(buffer
);
2884 if (state_
.bound_array_buffer
.get() == buffer
) {
2885 state_
.bound_array_buffer
= NULL
;
2887 RemoveBuffer(client_ids
[ii
]);
2892 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2893 GLsizei n
, const GLuint
* client_ids
) {
2894 bool supports_separate_framebuffer_binds
=
2895 features().chromium_framebuffer_multisample
;
2897 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2898 Framebuffer
* framebuffer
=
2899 GetFramebuffer(client_ids
[ii
]);
2900 if (framebuffer
&& !framebuffer
->IsDeleted()) {
2901 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
2902 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
2903 framebuffer_state_
.clear_state_dirty
= true;
2904 GLenum target
= supports_separate_framebuffer_binds
?
2905 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2906 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2908 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
2909 framebuffer_state_
.bound_read_framebuffer
= NULL
;
2910 GLenum target
= supports_separate_framebuffer_binds
?
2911 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
2912 glBindFramebufferEXT(target
, GetBackbufferServiceId());
2915 RemoveFramebuffer(client_ids
[ii
]);
2920 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2921 GLsizei n
, const GLuint
* client_ids
) {
2922 bool supports_separate_framebuffer_binds
=
2923 features().chromium_framebuffer_multisample
;
2924 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2925 Renderbuffer
* renderbuffer
=
2926 GetRenderbuffer(client_ids
[ii
]);
2927 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
2928 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
2929 state_
.bound_renderbuffer
= NULL
;
2931 // Unbind from current framebuffers.
2932 if (supports_separate_framebuffer_binds
) {
2933 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2934 framebuffer_state_
.bound_read_framebuffer
2935 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
2937 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2938 framebuffer_state_
.bound_draw_framebuffer
2939 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
2942 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2943 framebuffer_state_
.bound_draw_framebuffer
2944 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
2947 framebuffer_state_
.clear_state_dirty
= true;
2948 RemoveRenderbuffer(client_ids
[ii
]);
2953 void GLES2DecoderImpl::DeleteTexturesHelper(
2954 GLsizei n
, const GLuint
* client_ids
) {
2955 bool supports_separate_framebuffer_binds
=
2956 features().chromium_framebuffer_multisample
;
2957 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
2958 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
2960 Texture
* texture
= texture_ref
->texture();
2961 if (texture
->IsAttachedToFramebuffer()) {
2962 framebuffer_state_
.clear_state_dirty
= true;
2964 // Unbind texture_ref from texture_ref units.
2965 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
2966 state_
.texture_units
[jj
].Unbind(texture_ref
);
2968 // Unbind from current framebuffers.
2969 if (supports_separate_framebuffer_binds
) {
2970 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
2971 framebuffer_state_
.bound_read_framebuffer
2972 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
2974 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2975 framebuffer_state_
.bound_draw_framebuffer
2976 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
2979 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
2980 framebuffer_state_
.bound_draw_framebuffer
2981 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
2984 #if defined(OS_MACOSX)
2985 GLuint service_id
= texture
->service_id();
2986 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
2987 ReleaseIOSurfaceForTexture(service_id
);
2990 RemoveTexture(client_ids
[ii
]);
2995 // } // anonymous namespace
2997 bool GLES2DecoderImpl::MakeCurrent() {
2998 if (!context_
.get())
3001 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3002 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3004 // Some D3D drivers cannot recover from device lost in the GPU process
3005 // sandbox. Allow a new GPU process to launch.
3006 if (workarounds().exit_on_context_lost
) {
3007 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
3008 << " a D3D device in the Chrome GPU process sandbox.";
3010 base::win::SetShouldCrashOnProcessDetach(false);
3018 ProcessFinishedAsyncTransfers();
3020 // Rebind the FBO if it was unbound by the context.
3021 if (workarounds().unbind_fbo_on_context_switch
)
3022 RestoreFramebufferBindings();
3024 framebuffer_state_
.clear_state_dirty
= true;
3029 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3030 ProcessPendingReadPixels();
3031 if (engine() && query_manager_
.get())
3032 query_manager_
->ProcessPendingTransferQueries();
3034 // TODO(epenner): Is there a better place to do this?
3035 // This needs to occur before we execute any batch of commands
3036 // from the client, as the client may have recieved an async
3037 // completion while issuing those commands.
3038 // "DidFlushStart" would be ideal if we had such a callback.
3039 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3042 static void RebindCurrentFramebuffer(
3044 Framebuffer
* framebuffer
,
3045 GLuint back_buffer_service_id
) {
3046 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3048 if (framebuffer_id
== 0) {
3049 framebuffer_id
= back_buffer_service_id
;
3052 glBindFramebufferEXT(target
, framebuffer_id
);
3055 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3056 framebuffer_state_
.clear_state_dirty
= true;
3058 if (!features().chromium_framebuffer_multisample
) {
3059 RebindCurrentFramebuffer(
3061 framebuffer_state_
.bound_draw_framebuffer
.get(),
3062 GetBackbufferServiceId());
3064 RebindCurrentFramebuffer(
3065 GL_READ_FRAMEBUFFER_EXT
,
3066 framebuffer_state_
.bound_read_framebuffer
.get(),
3067 GetBackbufferServiceId());
3068 RebindCurrentFramebuffer(
3069 GL_DRAW_FRAMEBUFFER_EXT
,
3070 framebuffer_state_
.bound_draw_framebuffer
.get(),
3071 GetBackbufferServiceId());
3076 bool GLES2DecoderImpl::CheckFramebufferValid(
3077 Framebuffer
* framebuffer
,
3078 GLenum target
, const char* func_name
) {
3080 if (backbuffer_needs_clear_bits_
) {
3081 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3082 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3083 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3085 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
3086 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
3088 state_
.SetDeviceDepthMask(GL_TRUE
);
3089 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3090 bool reset_draw_buffer
= false;
3091 if ((backbuffer_needs_clear_bits_
| GL_COLOR_BUFFER_BIT
) != 0 &&
3092 group_
->draw_buffer() == GL_NONE
) {
3093 reset_draw_buffer
= true;
3094 GLenum buf
= GL_BACK
;
3095 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3096 buf
= GL_COLOR_ATTACHMENT0
;
3097 glDrawBuffersARB(1, &buf
);
3099 glClear(backbuffer_needs_clear_bits_
);
3100 if (reset_draw_buffer
) {
3101 GLenum buf
= GL_NONE
;
3102 glDrawBuffersARB(1, &buf
);
3104 backbuffer_needs_clear_bits_
= 0;
3105 RestoreClearState();
3110 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3114 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3115 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3117 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3121 // Are all the attachments cleared?
3122 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3123 texture_manager()->HaveUnclearedMips()) {
3124 if (!framebuffer
->IsCleared()) {
3125 // Can we clear them?
3126 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3127 GL_FRAMEBUFFER_COMPLETE
) {
3129 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3130 "framebuffer incomplete (clear)");
3133 ClearUnclearedAttachments(target
, framebuffer
);
3137 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3138 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3139 GL_FRAMEBUFFER_COMPLETE
) {
3141 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3142 "framebuffer incomplete (check)");
3145 framebuffer_manager()->MarkAsComplete(framebuffer
);
3148 // NOTE: At this point we don't know if the framebuffer is complete but
3149 // we DO know that everything that needs to be cleared has been cleared.
3153 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3154 if (!features().chromium_framebuffer_multisample
) {
3155 bool valid
= CheckFramebufferValid(
3156 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3164 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3165 GL_DRAW_FRAMEBUFFER_EXT
,
3167 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3168 GL_READ_FRAMEBUFFER_EXT
,
3172 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3173 Framebuffer
* framebuffer
=
3174 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3175 if (framebuffer
!= NULL
) {
3176 const Framebuffer::Attachment
* attachment
=
3177 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3179 return gfx::Size(attachment
->width(), attachment
->height());
3181 return gfx::Size(0, 0);
3182 } else if (offscreen_target_frame_buffer_
.get()) {
3183 return offscreen_size_
;
3185 return surface_
->GetSize();
3189 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3190 Framebuffer
* framebuffer
=
3191 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3192 if (framebuffer
!= NULL
) {
3193 return framebuffer
->GetColorAttachmentTextureType();
3195 return GL_UNSIGNED_BYTE
;
3199 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3200 Framebuffer
* framebuffer
=
3201 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3202 if (framebuffer
!= NULL
) {
3203 return framebuffer
->GetColorAttachmentFormat();
3204 } else if (offscreen_target_frame_buffer_
.get()) {
3205 return offscreen_target_color_format_
;
3207 return back_buffer_color_format_
;
3211 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3212 Framebuffer
* framebuffer
=
3213 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3214 if (framebuffer
!= NULL
) {
3215 return framebuffer
->GetColorAttachmentFormat();
3216 } else if (offscreen_target_frame_buffer_
.get()) {
3217 return offscreen_target_color_format_
;
3219 return back_buffer_color_format_
;
3223 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3224 if (!offscreen_saved_color_texture_info_
.get())
3226 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3227 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3228 texture_manager()->SetLevelInfo(
3229 offscreen_saved_color_texture_info_
.get(),
3233 offscreen_size_
.width(),
3234 offscreen_size_
.height(),
3240 texture_manager()->SetParameteri(
3241 "UpdateParentTextureInfo",
3243 offscreen_saved_color_texture_info_
.get(),
3244 GL_TEXTURE_MAG_FILTER
,
3246 texture_manager()->SetParameteri(
3247 "UpdateParentTextureInfo",
3249 offscreen_saved_color_texture_info_
.get(),
3250 GL_TEXTURE_MIN_FILTER
,
3252 texture_manager()->SetParameteri(
3253 "UpdateParentTextureInfo",
3255 offscreen_saved_color_texture_info_
.get(),
3258 texture_manager()->SetParameteri(
3259 "UpdateParentTextureInfo",
3261 offscreen_saved_color_texture_info_
.get(),
3264 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3266 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3269 void GLES2DecoderImpl::SetResizeCallback(
3270 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3271 resize_callback_
= callback
;
3274 Logger
* GLES2DecoderImpl::GetLogger() {
3278 void GLES2DecoderImpl::BeginDecoding() {
3279 gpu_tracer_
->BeginDecoding();
3280 gpu_trace_commands_
= gpu_tracer_
->IsTracing();
3283 void GLES2DecoderImpl::EndDecoding() {
3284 gpu_tracer_
->EndDecoding();
3287 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3288 return state_
.GetErrorState();
3291 void GLES2DecoderImpl::SetShaderCacheCallback(
3292 const ShaderCacheCallback
& callback
) {
3293 shader_cache_callback_
= callback
;
3296 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3297 const WaitSyncPointCallback
& callback
) {
3298 wait_sync_point_callback_
= callback
;
3301 AsyncPixelTransferManager
*
3302 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3303 return async_pixel_transfer_manager_
.get();
3306 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3307 async_pixel_transfer_manager_
.reset();
3310 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3311 AsyncPixelTransferManager
* manager
) {
3312 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3315 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3316 uint32
* service_texture_id
) {
3317 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3319 *service_texture_id
= texture_ref
->service_id();
3325 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3326 return texture_state_
.texture_upload_count
+
3327 async_pixel_transfer_manager_
->GetTextureUploadCount();
3330 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3331 return texture_state_
.total_texture_upload_time
+
3332 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3335 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3336 return total_processing_commands_time_
;
3339 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3340 total_processing_commands_time_
+= time
;
3343 void GLES2DecoderImpl::Destroy(bool have_context
) {
3347 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3349 // Unbind everything.
3350 state_
.vertex_attrib_manager
= NULL
;
3351 state_
.default_vertex_attrib_manager
= NULL
;
3352 state_
.texture_units
.clear();
3353 state_
.bound_array_buffer
= NULL
;
3354 state_
.current_queries
.clear();
3355 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3356 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3357 state_
.bound_renderbuffer
= NULL
;
3359 if (offscreen_saved_color_texture_info_
.get()) {
3360 DCHECK(offscreen_target_color_texture_
);
3361 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3362 offscreen_saved_color_texture_
->id());
3363 offscreen_saved_color_texture_
->Invalidate();
3364 offscreen_saved_color_texture_info_
= NULL
;
3367 if (copy_texture_CHROMIUM_
.get()) {
3368 copy_texture_CHROMIUM_
->Destroy();
3369 copy_texture_CHROMIUM_
.reset();
3372 if (state_
.current_program
.get()) {
3373 program_manager()->UnuseProgram(shader_manager(),
3374 state_
.current_program
.get());
3377 if (attrib_0_buffer_id_
) {
3378 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3380 if (fixed_attrib_buffer_id_
) {
3381 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3384 if (validation_texture_
) {
3385 glDeleteTextures(1, &validation_texture_
);
3386 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3387 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3390 if (offscreen_target_frame_buffer_
.get())
3391 offscreen_target_frame_buffer_
->Destroy();
3392 if (offscreen_target_color_texture_
.get())
3393 offscreen_target_color_texture_
->Destroy();
3394 if (offscreen_target_color_render_buffer_
.get())
3395 offscreen_target_color_render_buffer_
->Destroy();
3396 if (offscreen_target_depth_render_buffer_
.get())
3397 offscreen_target_depth_render_buffer_
->Destroy();
3398 if (offscreen_target_stencil_render_buffer_
.get())
3399 offscreen_target_stencil_render_buffer_
->Destroy();
3400 if (offscreen_saved_frame_buffer_
.get())
3401 offscreen_saved_frame_buffer_
->Destroy();
3402 if (offscreen_saved_color_texture_
.get())
3403 offscreen_saved_color_texture_
->Destroy();
3404 if (offscreen_resolved_frame_buffer_
.get())
3405 offscreen_resolved_frame_buffer_
->Destroy();
3406 if (offscreen_resolved_color_texture_
.get())
3407 offscreen_resolved_color_texture_
->Destroy();
3409 if (offscreen_target_frame_buffer_
.get())
3410 offscreen_target_frame_buffer_
->Invalidate();
3411 if (offscreen_target_color_texture_
.get())
3412 offscreen_target_color_texture_
->Invalidate();
3413 if (offscreen_target_color_render_buffer_
.get())
3414 offscreen_target_color_render_buffer_
->Invalidate();
3415 if (offscreen_target_depth_render_buffer_
.get())
3416 offscreen_target_depth_render_buffer_
->Invalidate();
3417 if (offscreen_target_stencil_render_buffer_
.get())
3418 offscreen_target_stencil_render_buffer_
->Invalidate();
3419 if (offscreen_saved_frame_buffer_
.get())
3420 offscreen_saved_frame_buffer_
->Invalidate();
3421 if (offscreen_saved_color_texture_
.get())
3422 offscreen_saved_color_texture_
->Invalidate();
3423 if (offscreen_resolved_frame_buffer_
.get())
3424 offscreen_resolved_frame_buffer_
->Invalidate();
3425 if (offscreen_resolved_color_texture_
.get())
3426 offscreen_resolved_color_texture_
->Invalidate();
3429 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3430 // Otherwise, we can leak objects. http://crbug.com/258772.
3431 // state_.current_program must be reset before group_ is reset because
3432 // the later deletes the ProgramManager object that referred by
3433 // state_.current_program object.
3434 state_
.current_program
= NULL
;
3436 copy_texture_CHROMIUM_
.reset();
3438 if (query_manager_
.get()) {
3439 query_manager_
->Destroy(have_context
);
3440 query_manager_
.reset();
3443 if (vertex_array_manager_
.get()) {
3444 vertex_array_manager_
->Destroy(have_context
);
3445 vertex_array_manager_
.reset();
3448 offscreen_target_frame_buffer_
.reset();
3449 offscreen_target_color_texture_
.reset();
3450 offscreen_target_color_render_buffer_
.reset();
3451 offscreen_target_depth_render_buffer_
.reset();
3452 offscreen_target_stencil_render_buffer_
.reset();
3453 offscreen_saved_frame_buffer_
.reset();
3454 offscreen_saved_color_texture_
.reset();
3455 offscreen_resolved_frame_buffer_
.reset();
3456 offscreen_resolved_color_texture_
.reset();
3458 // Need to release these before releasing |group_| which may own the
3459 // ShaderTranslatorCache.
3460 fragment_translator_
= NULL
;
3461 vertex_translator_
= NULL
;
3463 // Should destroy the transfer manager before the texture manager held
3464 // by the context group.
3465 async_pixel_transfer_manager_
.reset();
3468 framebuffer_manager()->RemoveObserver(this);
3469 group_
->Destroy(this, have_context
);
3473 if (context_
.get()) {
3474 context_
->ReleaseCurrent(NULL
);
3478 #if defined(OS_MACOSX)
3479 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3480 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3481 CFRelease(it
->second
);
3483 texture_to_io_surface_map_
.clear();
3487 void GLES2DecoderImpl::SetSurface(
3488 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3489 DCHECK(context_
->IsCurrent(NULL
));
3490 DCHECK(surface_
.get());
3492 RestoreCurrentFramebufferBindings();
3495 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3496 if (!offscreen_saved_color_texture_
.get()) {
3497 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3500 if (!offscreen_saved_color_texture_info_
.get()) {
3501 GLuint service_id
= offscreen_saved_color_texture_
->id();
3502 offscreen_saved_color_texture_info_
= TextureRef::Create(
3503 texture_manager(), 0, service_id
);
3504 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3506 UpdateParentTextureInfo();
3508 mailbox_manager()->ProduceTexture(
3509 GL_TEXTURE_2D
, mailbox
, offscreen_saved_color_texture_info_
->texture());
3512 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3513 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3514 if (!is_offscreen
) {
3515 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3516 << " with an onscreen framebuffer.";
3520 if (offscreen_size_
== size
)
3523 offscreen_size_
= size
;
3524 int w
= offscreen_size_
.width();
3525 int h
= offscreen_size_
.height();
3526 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3527 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3528 << "to allocate storage due to excessive dimensions.";
3532 // Reallocate the offscreen target buffers.
3533 DCHECK(offscreen_target_color_format_
);
3534 if (IsOffscreenBufferMultisampled()) {
3535 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3536 feature_info_
, offscreen_size_
, offscreen_target_color_format_
,
3537 offscreen_target_samples_
)) {
3538 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3539 << "to allocate storage for offscreen target color buffer.";
3543 if (!offscreen_target_color_texture_
->AllocateStorage(
3544 offscreen_size_
, offscreen_target_color_format_
, false)) {
3545 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3546 << "to allocate storage for offscreen target color texture.";
3550 if (offscreen_target_depth_format_
&&
3551 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3552 feature_info_
, offscreen_size_
, offscreen_target_depth_format_
,
3553 offscreen_target_samples_
)) {
3554 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3555 << "to allocate storage for offscreen target depth buffer.";
3558 if (offscreen_target_stencil_format_
&&
3559 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3560 feature_info_
, offscreen_size_
, offscreen_target_stencil_format_
,
3561 offscreen_target_samples_
)) {
3562 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3563 << "to allocate storage for offscreen target stencil buffer.";
3567 // Attach the offscreen target buffers to the target frame buffer.
3568 if (IsOffscreenBufferMultisampled()) {
3569 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3570 GL_COLOR_ATTACHMENT0
,
3571 offscreen_target_color_render_buffer_
.get());
3573 offscreen_target_frame_buffer_
->AttachRenderTexture(
3574 offscreen_target_color_texture_
.get());
3576 if (offscreen_target_depth_format_
) {
3577 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3578 GL_DEPTH_ATTACHMENT
,
3579 offscreen_target_depth_render_buffer_
.get());
3581 const bool packed_depth_stencil
=
3582 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3583 if (packed_depth_stencil
) {
3584 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3585 GL_STENCIL_ATTACHMENT
,
3586 offscreen_target_depth_render_buffer_
.get());
3587 } else if (offscreen_target_stencil_format_
) {
3588 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3589 GL_STENCIL_ATTACHMENT
,
3590 offscreen_target_stencil_render_buffer_
.get());
3593 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3594 GL_FRAMEBUFFER_COMPLETE
) {
3595 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3596 << "because offscreen FBO was incomplete.";
3600 // Clear the target frame buffer.
3602 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3603 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3604 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1);
3605 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3607 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
3608 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
3610 state_
.SetDeviceDepthMask(GL_TRUE
);
3611 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3612 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3613 RestoreClearState();
3616 // Destroy the offscreen resolved framebuffers.
3617 if (offscreen_resolved_frame_buffer_
.get())
3618 offscreen_resolved_frame_buffer_
->Destroy();
3619 if (offscreen_resolved_color_texture_
.get())
3620 offscreen_resolved_color_texture_
->Destroy();
3621 offscreen_resolved_color_texture_
.reset();
3622 offscreen_resolved_frame_buffer_
.reset();
3627 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(
3628 uint32 immediate_data_size
, const cmds::ResizeCHROMIUM
& c
) {
3629 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3630 return error::kDeferCommandUntilLater
;
3632 GLuint width
= static_cast<GLuint
>(c
.width
);
3633 GLuint height
= static_cast<GLuint
>(c
.height
);
3634 GLfloat scale_factor
= c
.scale_factor
;
3635 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3637 width
= std::max(1U, width
);
3638 height
= std::max(1U, height
);
3640 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3641 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3642 // Make sure that we are done drawing to the back buffer before resizing.
3645 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3647 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3648 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3649 << "ResizeOffscreenFrameBuffer failed.";
3650 return error::kLostContext
;
3654 if (!resize_callback_
.is_null()) {
3655 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3656 DCHECK(context_
->IsCurrent(surface_
.get()));
3657 if (!context_
->IsCurrent(surface_
.get())) {
3658 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3659 << "current after resize callback.";
3660 return error::kLostContext
;
3664 return error::kNoError
;
3667 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3668 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3669 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3671 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3674 // Decode command with its arguments, and call the corresponding GL function.
3675 // Note: args is a pointer to the command buffer. As such, it could be changed
3676 // by a (malicious) client at any time, so if validation has to happen, it
3677 // should operate on a copy of them.
3678 error::Error
GLES2DecoderImpl::DoCommand(
3679 unsigned int command
,
3680 unsigned int arg_count
,
3681 const void* cmd_data
) {
3682 error::Error result
= error::kNoError
;
3683 if (log_commands()) {
3684 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3685 // VLOG(1), no luck.
3686 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]" << "cmd: "
3687 << GetCommandName(command
);
3689 unsigned int command_index
= command
- kStartPoint
- 1;
3690 if (command_index
< arraysize(g_command_info
)) {
3691 const CommandInfo
& info
= g_command_info
[command_index
];
3692 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3693 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3694 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3695 bool doing_gpu_trace
= false;
3696 if (gpu_trace_commands_
) {
3697 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
3698 doing_gpu_trace
= true;
3699 gpu_tracer_
->Begin(GetCommandName(command
), kTraceDecoder
);
3703 uint32 immediate_data_size
=
3704 (arg_count
- info_arg_count
) * sizeof(CommandBufferEntry
); // NOLINT
3706 #define GLES2_CMD_OP(name) \
3707 case cmds::name::kCmdId: \
3708 result = Handle ## name( \
3709 immediate_data_size, \
3710 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3713 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3717 if (doing_gpu_trace
)
3718 gpu_tracer_
->End(kTraceDecoder
);
3722 while ((error
= glGetError()) != GL_NO_ERROR
) {
3723 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
3724 << "GL ERROR: " << GLES2Util::GetStringEnum(error
) << " : "
3725 << GetCommandName(command
);
3726 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
3730 result
= error::kInvalidArguments
;
3733 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
3735 if (result
== error::kNoError
&& current_decoder_error_
!= error::kNoError
) {
3736 result
= current_decoder_error_
;
3737 current_decoder_error_
= error::kNoError
;
3742 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
3743 buffer_manager()->RemoveBuffer(client_id
);
3746 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id
) {
3747 if (GetProgram(client_id
)) {
3750 GLuint service_id
= glCreateProgram();
3751 if (service_id
!= 0) {
3752 CreateProgram(client_id
, service_id
);
3757 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type
, GLuint client_id
) {
3758 if (GetShader(client_id
)) {
3761 GLuint service_id
= glCreateShader(type
);
3762 if (service_id
!= 0) {
3763 CreateShader(client_id
, service_id
, type
);
3768 void GLES2DecoderImpl::DoFinish() {
3770 ProcessPendingReadPixels();
3771 ProcessPendingQueries();
3774 void GLES2DecoderImpl::DoFlush() {
3776 ProcessPendingQueries();
3779 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
3780 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
3781 if (texture_index
>= state_
.texture_units
.size()) {
3782 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3783 "glActiveTexture", texture_unit
, "texture_unit");
3786 state_
.active_texture_unit
= texture_index
;
3787 glActiveTexture(texture_unit
);
3790 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
3791 Buffer
* buffer
= NULL
;
3792 GLuint service_id
= 0;
3793 if (client_id
!= 0) {
3794 buffer
= GetBuffer(client_id
);
3796 if (!group_
->bind_generates_resource()) {
3797 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
3799 "id not generated by glGenBuffers");
3803 // It's a new id so make a buffer buffer for it.
3804 glGenBuffersARB(1, &service_id
);
3805 CreateBuffer(client_id
, service_id
);
3806 buffer
= GetBuffer(client_id
);
3807 IdAllocatorInterface
* id_allocator
=
3808 group_
->GetIdAllocator(id_namespaces::kBuffers
);
3809 id_allocator
->MarkAsUsed(client_id
);
3812 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
3814 if (!buffer_manager()->SetTarget(buffer
, target
)) {
3816 GL_INVALID_OPERATION
,
3817 "glBindBuffer", "buffer bound to more than 1 target");
3820 service_id
= buffer
->service_id();
3823 case GL_ARRAY_BUFFER
:
3824 state_
.bound_array_buffer
= buffer
;
3826 case GL_ELEMENT_ARRAY_BUFFER
:
3827 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
3830 NOTREACHED(); // Validation should prevent us getting here.
3833 glBindBuffer(target
, service_id
);
3836 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3837 bool all_draw_buffers
) {
3838 Framebuffer
* framebuffer
=
3839 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3840 if (!all_draw_buffers
|| !framebuffer
) {
3841 return (GLES2Util::GetChannelsForFormat(
3842 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3844 return framebuffer
->HasAlphaMRT();
3847 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3848 Framebuffer
* framebuffer
=
3849 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3851 return framebuffer
->HasDepthAttachment();
3853 if (offscreen_target_frame_buffer_
.get()) {
3854 return offscreen_target_depth_format_
!= 0;
3856 return back_buffer_has_depth_
;
3859 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3860 Framebuffer
* framebuffer
=
3861 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3863 return framebuffer
->HasStencilAttachment();
3865 if (offscreen_target_frame_buffer_
.get()) {
3866 return offscreen_target_stencil_format_
!= 0 ||
3867 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3869 return back_buffer_has_stencil_
;
3872 void GLES2DecoderImpl::ApplyDirtyState() {
3873 if (framebuffer_state_
.clear_state_dirty
) {
3874 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
3875 state_
.SetDeviceColorMask(state_
.color_mask_red
,
3876 state_
.color_mask_green
,
3877 state_
.color_mask_blue
,
3878 state_
.color_mask_alpha
&& have_alpha
);
3880 bool have_depth
= BoundFramebufferHasDepthAttachment();
3881 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
3883 bool have_stencil
= BoundFramebufferHasStencilAttachment();
3884 state_
.SetDeviceStencilMaskSeparate(
3885 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
3886 state_
.SetDeviceStencilMaskSeparate(
3887 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
3889 state_
.SetDeviceCapabilityState(
3890 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
3891 state_
.SetDeviceCapabilityState(
3892 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
3893 framebuffer_state_
.clear_state_dirty
= false;
3897 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
3898 return (offscreen_target_frame_buffer_
.get())
3899 ? offscreen_target_frame_buffer_
->id()
3900 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
3903 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
3904 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3905 "context", logger_
.GetLogPrefix());
3906 // Restore the Framebuffer first because of bugs in Intel drivers.
3907 // Intel drivers incorrectly clip the viewport settings to
3908 // the size of the current framebuffer object.
3909 RestoreFramebufferBindings();
3910 state_
.RestoreState(prev_state
);
3913 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3915 framebuffer_state_
.bound_draw_framebuffer
.get()
3916 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
3917 : GetBackbufferServiceId();
3918 if (!features().chromium_framebuffer_multisample
) {
3919 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
3921 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
3922 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
3923 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
3924 : GetBackbufferServiceId();
3925 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
3930 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
3931 state_
.RestoreRenderbufferBindings();
3934 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
3935 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
3937 GLenum target
= texture
->target();
3938 glBindTexture(target
, service_id
);
3940 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
3942 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
3944 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
3946 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
3947 RestoreTextureUnitBindings(state_
.active_texture_unit
);
3951 void GLES2DecoderImpl::ClearAllAttributes() const {
3952 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3954 if (feature_info_
->feature_flags().native_vertex_array_object
)
3955 glBindVertexArrayOES(0);
3957 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
3958 if (i
!= 0) // Never disable attribute 0
3959 glDisableVertexAttribArray(i
);
3960 if(features().angle_instanced_arrays
)
3961 glVertexAttribDivisorANGLE(i
, 0);
3965 void GLES2DecoderImpl::RestoreAllAttributes() const {
3966 state_
.RestoreVertexAttribs();
3969 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
3970 state_
.SetIgnoreCachedStateForTest(ignore
);
3973 void GLES2DecoderImpl::OnFboChanged() const {
3974 if (workarounds().restore_scissor_on_fbo_change
)
3975 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
3978 // Called after the FBO is checked for completeness.
3979 void GLES2DecoderImpl::OnUseFramebuffer() const {
3980 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
3981 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
3982 // The driver forgets the correct scissor when modifying the FBO binding.
3983 glScissor(state_
.scissor_x
,
3985 state_
.scissor_width
,
3986 state_
.scissor_height
);
3988 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3989 // it's unclear how this bug works.
3994 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
3995 Framebuffer
* framebuffer
= NULL
;
3996 GLuint service_id
= 0;
3997 if (client_id
!= 0) {
3998 framebuffer
= GetFramebuffer(client_id
);
4000 if (!group_
->bind_generates_resource()) {
4001 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4002 "glBindFramebuffer",
4003 "id not generated by glGenFramebuffers");
4007 // It's a new id so make a framebuffer framebuffer for it.
4008 glGenFramebuffersEXT(1, &service_id
);
4009 CreateFramebuffer(client_id
, service_id
);
4010 framebuffer
= GetFramebuffer(client_id
);
4011 IdAllocatorInterface
* id_allocator
=
4012 group_
->GetIdAllocator(id_namespaces::kFramebuffers
);
4013 id_allocator
->MarkAsUsed(client_id
);
4015 service_id
= framebuffer
->service_id();
4017 framebuffer
->MarkAsValid();
4019 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4021 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4022 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4025 // vmiura: This looks like dup code
4026 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4027 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4030 framebuffer_state_
.clear_state_dirty
= true;
4032 // If we are rendering to the backbuffer get the FBO id for any simulated
4034 if (framebuffer
== NULL
) {
4035 service_id
= GetBackbufferServiceId();
4038 glBindFramebufferEXT(target
, service_id
);
4042 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4043 Renderbuffer
* renderbuffer
= NULL
;
4044 GLuint service_id
= 0;
4045 if (client_id
!= 0) {
4046 renderbuffer
= GetRenderbuffer(client_id
);
4047 if (!renderbuffer
) {
4048 if (!group_
->bind_generates_resource()) {
4049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4050 "glBindRenderbuffer",
4051 "id not generated by glGenRenderbuffers");
4055 // It's a new id so make a renderbuffer for it.
4056 glGenRenderbuffersEXT(1, &service_id
);
4057 CreateRenderbuffer(client_id
, service_id
);
4058 renderbuffer
= GetRenderbuffer(client_id
);
4059 IdAllocatorInterface
* id_allocator
=
4060 group_
->GetIdAllocator(id_namespaces::kRenderbuffers
);
4061 id_allocator
->MarkAsUsed(client_id
);
4063 service_id
= renderbuffer
->service_id();
4065 renderbuffer
->MarkAsValid();
4067 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4068 state_
.bound_renderbuffer
= renderbuffer
;
4069 state_
.bound_renderbuffer_valid
= true;
4070 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4073 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4074 TextureRef
* texture_ref
= NULL
;
4075 GLuint service_id
= 0;
4076 if (client_id
!= 0) {
4077 texture_ref
= GetTexture(client_id
);
4079 if (!group_
->bind_generates_resource()) {
4080 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4082 "id not generated by glGenTextures");
4086 // It's a new id so make a texture texture for it.
4087 glGenTextures(1, &service_id
);
4088 DCHECK_NE(0u, service_id
);
4089 CreateTexture(client_id
, service_id
);
4090 texture_ref
= GetTexture(client_id
);
4091 IdAllocatorInterface
* id_allocator
=
4092 group_
->GetIdAllocator(id_namespaces::kTextures
);
4093 id_allocator
->MarkAsUsed(client_id
);
4096 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4099 // Check the texture exists
4101 Texture
* texture
= texture_ref
->texture();
4102 // Check that we are not trying to bind it to a different target.
4103 if (texture
->target() != 0 && texture
->target() != target
) {
4104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4106 "texture bound to more than 1 target.");
4109 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4110 if (texture
->target() == 0) {
4111 texture_manager()->SetTarget(texture_ref
, target
);
4113 glBindTexture(target
, texture
->service_id());
4115 glBindTexture(target
, 0);
4118 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4119 unit
.bind_target
= target
;
4122 unit
.bound_texture_2d
= texture_ref
;
4124 case GL_TEXTURE_CUBE_MAP
:
4125 unit
.bound_texture_cube_map
= texture_ref
;
4127 case GL_TEXTURE_EXTERNAL_OES
:
4128 unit
.bound_texture_external_oes
= texture_ref
;
4130 case GL_TEXTURE_RECTANGLE_ARB
:
4131 unit
.bound_texture_rectangle_arb
= texture_ref
;
4134 NOTREACHED(); // Validation should prevent us getting here.
4139 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4140 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4142 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4143 glDisableVertexAttribArray(index
);
4148 "glDisableVertexAttribArray", "index out of range");
4152 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4153 GLsizei numAttachments
,
4154 const GLenum
* attachments
) {
4155 Framebuffer
* framebuffer
=
4156 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4158 // Validates the attachments. If one of them fails
4159 // the whole command fails.
4160 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4162 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4164 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4165 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4166 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4171 // Marks each one of them as not cleared
4172 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4174 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4179 switch (attachments
[i
]) {
4181 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4184 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4185 case GL_STENCIL_EXT
:
4186 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4195 // If the default framebuffer is bound but we are still rendering to an
4196 // FBO, translate attachment names that refer to default framebuffer
4197 // channels to corresponding framebuffer attachments.
4198 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4199 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4200 GLenum attachment
= attachments
[i
];
4201 if (!framebuffer
&& GetBackbufferServiceId()) {
4202 switch (attachment
) {
4204 attachment
= GL_COLOR_ATTACHMENT0
;
4207 attachment
= GL_DEPTH_ATTACHMENT
;
4209 case GL_STENCIL_EXT
:
4210 attachment
= GL_STENCIL_ATTACHMENT
;
4217 translated_attachments
[i
] = attachment
;
4220 glDiscardFramebufferEXT(target
, numAttachments
, translated_attachments
.get());
4223 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4224 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4225 glEnableVertexAttribArray(index
);
4228 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4232 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4233 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4236 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4238 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4242 if (target
== GL_TEXTURE_CUBE_MAP
) {
4243 for (int i
= 0; i
< 6; ++i
) {
4244 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4245 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4247 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4252 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4254 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4259 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4260 // Workaround for Mac driver bug. In the large scheme of things setting
4261 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4262 // hit so there's probably no need to make this conditional. The bug appears
4263 // to be that if the filtering mode is set to something that doesn't require
4264 // mipmaps for rendering, or is never set to something other than the default,
4265 // then glGenerateMipmap misbehaves.
4266 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4267 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4269 glGenerateMipmapEXT(target
);
4270 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4271 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4272 texture_ref
->texture()->min_filter());
4274 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4275 if (error
== GL_NO_ERROR
) {
4276 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4280 bool GLES2DecoderImpl::GetHelper(
4281 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4282 DCHECK(num_written
);
4283 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4285 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4287 // Return the GL implementation's preferred format and (see below type)
4288 // if we have the GL extension that exposes this. This allows the GPU
4289 // client to use the implementation's preferred format for glReadPixels
4290 // for optimisation.
4292 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4293 // case when requested on integer/floating point buffers but which is
4294 // acceptable on GLES2 and with the GL_OES_read_format extension.
4296 // Therefore if an error occurs we swallow the error and use the
4297 // internal implementation.
4299 if (context_
->HasExtension("GL_OES_read_format")) {
4300 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4302 glGetIntegerv(pname
, params
);
4303 if (glGetError() == GL_NO_ERROR
)
4306 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4307 GetBoundReadFrameBufferInternalFormat());
4310 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4313 if (context_
->HasExtension("GL_OES_read_format")) {
4314 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4316 glGetIntegerv(pname
, params
);
4317 if (glGetError() == GL_NO_ERROR
)
4320 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4321 GetBoundReadFrameBufferInternalFormat(),
4322 GetBoundReadFrameBufferTextureType());
4325 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4328 *params
= group_
->max_fragment_uniform_vectors();
4331 case GL_MAX_VARYING_VECTORS
:
4334 *params
= group_
->max_varying_vectors();
4337 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4340 *params
= group_
->max_vertex_uniform_vectors();
4346 case GL_MAX_VIEWPORT_DIMS
:
4347 if (offscreen_target_frame_buffer_
.get()) {
4350 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4351 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4356 case GL_MAX_SAMPLES
:
4359 params
[0] = renderbuffer_manager()->max_samples();
4362 case GL_MAX_RENDERBUFFER_SIZE
:
4365 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4368 case GL_MAX_TEXTURE_SIZE
:
4371 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4374 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4377 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4380 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4383 params
[0] = group_
->max_color_attachments();
4386 case GL_MAX_DRAW_BUFFERS_ARB
:
4389 params
[0] = group_
->max_draw_buffers();
4396 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4397 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4404 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4405 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4408 case GL_STENCIL_BITS
:
4412 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4413 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4416 case GL_COMPRESSED_TEXTURE_FORMATS
:
4417 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4419 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4420 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4424 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4427 *params
= validators_
->compressed_texture_format
.GetValues().size();
4430 case GL_NUM_SHADER_BINARY_FORMATS
:
4433 *params
= validators_
->shader_binary_format
.GetValues().size();
4436 case GL_SHADER_BINARY_FORMATS
:
4437 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4439 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4440 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4444 case GL_SHADER_COMPILER
:
4450 case GL_ARRAY_BUFFER_BINDING
:
4453 if (state_
.bound_array_buffer
.get()) {
4454 GLuint client_id
= 0;
4455 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4457 *params
= client_id
;
4463 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4466 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4467 GLuint client_id
= 0;
4468 buffer_manager()->GetClientId(
4469 state_
.vertex_attrib_manager
->element_array_buffer()->
4470 service_id(), &client_id
);
4471 *params
= client_id
;
4477 case GL_FRAMEBUFFER_BINDING
:
4478 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4481 Framebuffer
* framebuffer
=
4482 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4484 GLuint client_id
= 0;
4485 framebuffer_manager()->GetClientId(
4486 framebuffer
->service_id(), &client_id
);
4487 *params
= client_id
;
4493 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4496 Framebuffer
* framebuffer
=
4497 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4499 GLuint client_id
= 0;
4500 framebuffer_manager()->GetClientId(
4501 framebuffer
->service_id(), &client_id
);
4502 *params
= client_id
;
4508 case GL_RENDERBUFFER_BINDING
:
4511 Renderbuffer
* renderbuffer
=
4512 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4514 *params
= renderbuffer
->client_id();
4520 case GL_CURRENT_PROGRAM
:
4523 if (state_
.current_program
.get()) {
4524 GLuint client_id
= 0;
4525 program_manager()->GetClientId(
4526 state_
.current_program
->service_id(), &client_id
);
4527 *params
= client_id
;
4533 case GL_VERTEX_ARRAY_BINDING_OES
:
4536 if (state_
.vertex_attrib_manager
.get() !=
4537 state_
.default_vertex_attrib_manager
.get()) {
4538 GLuint client_id
= 0;
4539 vertex_array_manager_
->GetClientId(
4540 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4541 *params
= client_id
;
4547 case GL_TEXTURE_BINDING_2D
:
4550 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4551 if (unit
.bound_texture_2d
.get()) {
4552 *params
= unit
.bound_texture_2d
->client_id();
4558 case GL_TEXTURE_BINDING_CUBE_MAP
:
4561 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4562 if (unit
.bound_texture_cube_map
.get()) {
4563 *params
= unit
.bound_texture_cube_map
->client_id();
4569 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4572 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4573 if (unit
.bound_texture_external_oes
.get()) {
4574 *params
= unit
.bound_texture_external_oes
->client_id();
4580 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4583 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4584 if (unit
.bound_texture_rectangle_arb
.get()) {
4585 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4591 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4594 params
[0] = unpack_flip_y_
;
4597 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4600 params
[0] = unpack_premultiply_alpha_
;
4603 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4606 params
[0] = unpack_unpremultiply_alpha_
;
4609 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4612 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4616 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4617 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4620 Framebuffer
* framebuffer
=
4621 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4623 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4624 } else { // backbuffer
4625 if (pname
== GL_DRAW_BUFFER0_ARB
)
4626 params
[0] = group_
->draw_buffer();
4628 params
[0] = GL_NONE
;
4633 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4638 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4639 GLenum pname
, GLsizei
* num_values
) {
4640 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4643 return GetHelper(pname
, NULL
, num_values
);
4646 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4647 if (GL_MAX_SAMPLES
== pname
&&
4648 features().use_img_for_multisampled_render_to_texture
) {
4649 return GL_MAX_SAMPLES_IMG
;
4654 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4656 GLsizei num_written
= 0;
4657 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4658 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4659 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4660 GetHelper(pname
, values
.get(), &num_written
);
4662 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4663 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4666 pname
= AdjustGetPname(pname
);
4667 glGetBooleanv(pname
, params
);
4671 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4673 GLsizei num_written
= 0;
4674 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4675 if (GetHelper(pname
, NULL
, &num_written
)) {
4676 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4677 GetHelper(pname
, values
.get(), &num_written
);
4678 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4679 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4682 pname
= AdjustGetPname(pname
);
4683 glGetFloatv(pname
, params
);
4688 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4690 GLsizei num_written
;
4691 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4692 !GetHelper(pname
, params
, &num_written
)) {
4693 pname
= AdjustGetPname(pname
);
4694 glGetIntegerv(pname
, params
);
4698 void GLES2DecoderImpl::DoGetProgramiv(
4699 GLuint program_id
, GLenum pname
, GLint
* params
) {
4700 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
4704 program
->GetProgramiv(pname
, params
);
4707 void GLES2DecoderImpl::DoGetBufferParameteriv(
4708 GLenum target
, GLenum pname
, GLint
* params
) {
4709 // Just delegate it. Some validation is actually done before this.
4710 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4711 &state_
, target
, pname
, params
);
4714 void GLES2DecoderImpl::DoBindAttribLocation(
4715 GLuint program_id
, GLuint index
, const char* name
) {
4716 if (!StringIsValidForGLES(name
)) {
4718 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
4721 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4723 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
4726 if (index
>= group_
->max_vertex_attribs()) {
4728 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
4731 Program
* program
= GetProgramInfoNotShader(
4732 program_id
, "glBindAttribLocation");
4736 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
4737 glBindAttribLocation(program
->service_id(), index
, name
);
4740 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
4741 uint32 immediate_data_size
, const cmds::BindAttribLocationBucket
& c
) {
4742 GLuint program
= static_cast<GLuint
>(c
.program
);
4743 GLuint index
= static_cast<GLuint
>(c
.index
);
4744 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4745 if (!bucket
|| bucket
->size() == 0) {
4746 return error::kInvalidArguments
;
4748 std::string name_str
;
4749 if (!bucket
->GetAsString(&name_str
)) {
4750 return error::kInvalidArguments
;
4752 DoBindAttribLocation(program
, index
, name_str
.c_str());
4753 return error::kNoError
;
4756 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4757 GLuint program_id
, GLint location
, const char* name
) {
4758 if (!StringIsValidForGLES(name
)) {
4761 "glBindUniformLocationCHROMIUM", "Invalid character");
4764 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
4766 GL_INVALID_OPERATION
,
4767 "glBindUniformLocationCHROMIUM", "reserved prefix");
4770 if (location
< 0 || static_cast<uint32
>(location
) >=
4771 (group_
->max_fragment_uniform_vectors() +
4772 group_
->max_vertex_uniform_vectors()) * 4) {
4775 "glBindUniformLocationCHROMIUM", "location out of range");
4778 Program
* program
= GetProgramInfoNotShader(
4779 program_id
, "glBindUniformLocationCHROMIUM");
4783 if (!program
->SetUniformLocationBinding(name
, location
)) {
4786 "glBindUniformLocationCHROMIUM", "location out of range");
4790 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4791 uint32 immediate_data_size
,
4792 const cmds::BindUniformLocationCHROMIUMBucket
& c
) {
4793 GLuint program
= static_cast<GLuint
>(c
.program
);
4794 GLint location
= static_cast<GLint
>(c
.location
);
4795 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
4796 if (!bucket
|| bucket
->size() == 0) {
4797 return error::kInvalidArguments
;
4799 std::string name_str
;
4800 if (!bucket
->GetAsString(&name_str
)) {
4801 return error::kInvalidArguments
;
4803 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
4804 return error::kNoError
;
4807 error::Error
GLES2DecoderImpl::HandleDeleteShader(
4808 uint32 immediate_data_size
, const cmds::DeleteShader
& c
) {
4809 GLuint client_id
= c
.shader
;
4811 Shader
* shader
= GetShader(client_id
);
4813 if (!shader
->IsDeleted()) {
4814 glDeleteShader(shader
->service_id());
4815 shader_manager()->MarkAsDeleted(shader
);
4818 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
4821 return error::kNoError
;
4824 error::Error
GLES2DecoderImpl::HandleDeleteProgram(
4825 uint32 immediate_data_size
, const cmds::DeleteProgram
& c
) {
4826 GLuint client_id
= c
.program
;
4828 Program
* program
= GetProgram(client_id
);
4830 if (!program
->IsDeleted()) {
4831 program_manager()->MarkAsDeleted(shader_manager(), program
);
4835 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
4838 return error::kNoError
;
4841 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4842 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4843 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4844 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4845 id_allocator
->FreeID(ids
[ii
]);
4849 error::Error
GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4850 uint32 immediate_data_size
, const cmds::DeleteSharedIdsCHROMIUM
& c
) {
4851 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4852 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4854 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4855 return error::kOutOfBounds
;
4857 const GLuint
* ids
= GetSharedMemoryAs
<const GLuint
*>(
4858 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4860 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "DeleteSharedIdsCHROMIUM", "n < 0");
4861 return error::kNoError
;
4864 return error::kOutOfBounds
;
4866 DoDeleteSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4867 return error::kNoError
;
4870 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4871 GLuint namespace_id
, GLuint id_offset
, GLsizei n
, GLuint
* ids
) {
4872 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4873 if (id_offset
== 0) {
4874 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4875 ids
[ii
] = id_allocator
->AllocateID();
4878 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4879 ids
[ii
] = id_allocator
->AllocateIDAtOrAbove(id_offset
);
4880 id_offset
= ids
[ii
] + 1;
4885 error::Error
GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4886 uint32 immediate_data_size
, const cmds::GenSharedIdsCHROMIUM
& c
) {
4887 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4888 GLuint id_offset
= static_cast<GLuint
>(c
.id_offset
);
4889 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4891 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4892 return error::kOutOfBounds
;
4894 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4895 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4897 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "GenSharedIdsCHROMIUM", "n < 0");
4898 return error::kNoError
;
4901 return error::kOutOfBounds
;
4903 DoGenSharedIdsCHROMIUM(namespace_id
, id_offset
, n
, ids
);
4904 return error::kNoError
;
4907 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4908 GLuint namespace_id
, GLsizei n
, const GLuint
* ids
) {
4909 IdAllocatorInterface
* id_allocator
= group_
->GetIdAllocator(namespace_id
);
4910 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
4911 if (!id_allocator
->MarkAsUsed(ids
[ii
])) {
4912 for (GLsizei jj
= 0; jj
< ii
; ++jj
) {
4913 id_allocator
->FreeID(ids
[jj
]);
4916 GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM",
4917 "attempt to register id that already exists");
4923 error::Error
GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4924 uint32 immediate_data_size
, const cmds::RegisterSharedIdsCHROMIUM
& c
) {
4925 GLuint namespace_id
= static_cast<GLuint
>(c
.namespace_id
);
4926 GLsizei n
= static_cast<GLsizei
>(c
.n
);
4928 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
4929 return error::kOutOfBounds
;
4931 GLuint
* ids
= GetSharedMemoryAs
<GLuint
*>(
4932 c
.ids_shm_id
, c
.ids_shm_offset
, data_size
);
4934 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "RegisterSharedIdsCHROMIUM", "n < 0");
4935 return error::kNoError
;
4938 return error::kOutOfBounds
;
4940 DoRegisterSharedIdsCHROMIUM(namespace_id
, n
, ids
);
4941 return error::kNoError
;
4944 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
4945 DCHECK(!ShouldDeferDraws());
4946 if (CheckBoundFramebuffersValid("glClear")) {
4950 return error::kNoError
;
4953 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4954 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
4955 GLuint client_renderbuffer_id
) {
4956 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
4959 GL_INVALID_OPERATION
,
4960 "glFramebufferRenderbuffer", "no framebuffer bound");
4963 GLuint service_id
= 0;
4964 Renderbuffer
* renderbuffer
= NULL
;
4965 if (client_renderbuffer_id
) {
4966 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
4967 if (!renderbuffer
) {
4969 GL_INVALID_OPERATION
,
4970 "glFramebufferRenderbuffer", "unknown renderbuffer");
4973 service_id
= renderbuffer
->service_id();
4975 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4976 glFramebufferRenderbufferEXT(
4977 target
, attachment
, renderbuffertarget
, service_id
);
4978 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4979 if (error
== GL_NO_ERROR
) {
4980 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
4982 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
4983 framebuffer_state_
.clear_state_dirty
= true;
4988 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
4989 if (SetCapabilityState(cap
, false)) {
4994 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
4995 if (SetCapabilityState(cap
, true)) {
5000 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5001 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5002 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5003 glDepthRange(znear
, zfar
);
5006 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5007 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5008 state_
.sample_coverage_invert
= (invert
!= 0);
5009 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5012 // Assumes framebuffer is complete.
5013 void GLES2DecoderImpl::ClearUnclearedAttachments(
5014 GLenum target
, Framebuffer
* framebuffer
) {
5015 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5016 // bind this to the DRAW point, clear then bind back to READ
5017 // TODO(gman): I don't think there is any guarantee that an FBO that
5018 // is complete on the READ attachment will be complete as a DRAW
5020 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5021 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5023 GLbitfield clear_bits
= 0;
5024 if (framebuffer
->HasUnclearedColorAttachments()) {
5027 (GLES2Util::GetChannelsForFormat(
5028 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5030 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5031 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5032 framebuffer
->PrepareDrawBuffersForClear();
5035 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5036 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5038 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
5039 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
5040 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5043 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5044 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5046 state_
.SetDeviceDepthMask(GL_TRUE
);
5047 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5050 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5051 glClear(clear_bits
);
5053 if ((clear_bits
| GL_COLOR_BUFFER_BIT
) != 0)
5054 framebuffer
->RestoreDrawBuffersAfterClear();
5056 framebuffer_manager()->MarkAttachmentsAsCleared(
5057 framebuffer
, renderbuffer_manager(), texture_manager());
5059 RestoreClearState();
5061 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5062 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5063 Framebuffer
* draw_framebuffer
=
5064 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5065 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5066 GetBackbufferServiceId();
5067 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5071 void GLES2DecoderImpl::RestoreClearState() {
5072 framebuffer_state_
.clear_state_dirty
= true;
5074 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5075 state_
.color_clear_alpha
);
5076 glClearStencil(state_
.stencil_clear
);
5077 glClearDepth(state_
.depth_clear
);
5078 if (state_
.enable_flags
.scissor_test
) {
5079 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5083 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5084 Framebuffer
* framebuffer
=
5085 GetFramebufferInfoForTarget(target
);
5087 return GL_FRAMEBUFFER_COMPLETE
;
5089 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5090 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5091 return completeness
;
5093 return framebuffer
->GetStatus(texture_manager(), target
);
5096 void GLES2DecoderImpl::DoFramebufferTexture2D(
5097 GLenum target
, GLenum attachment
, GLenum textarget
,
5098 GLuint client_texture_id
, GLint level
) {
5099 DoFramebufferTexture2DCommon(
5100 "glFramebufferTexture2D", target
, attachment
,
5101 textarget
, client_texture_id
, level
, 0);
5104 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5105 GLenum target
, GLenum attachment
, GLenum textarget
,
5106 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5107 DoFramebufferTexture2DCommon(
5108 "glFramebufferTexture2DMultisample", target
, attachment
,
5109 textarget
, client_texture_id
, level
, samples
);
5112 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5113 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5114 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5115 if (samples
> renderbuffer_manager()->max_samples()) {
5118 "glFramebufferTexture2DMultisample", "samples too large");
5121 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5124 GL_INVALID_OPERATION
,
5125 name
, "no framebuffer bound.");
5128 GLuint service_id
= 0;
5129 TextureRef
* texture_ref
= NULL
;
5130 if (client_texture_id
) {
5131 texture_ref
= GetTexture(client_texture_id
);
5134 GL_INVALID_OPERATION
,
5135 name
, "unknown texture_ref");
5138 service_id
= texture_ref
->service_id();
5141 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5144 name
, "level out of range");
5149 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5151 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5153 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5155 if (features().use_img_for_multisampled_render_to_texture
) {
5156 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5157 service_id
, level
, samples
);
5159 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5160 service_id
, level
, samples
);
5163 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5164 if (error
== GL_NO_ERROR
) {
5165 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5168 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5169 framebuffer_state_
.clear_state_dirty
= true;
5173 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5178 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5179 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5180 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5183 GL_INVALID_OPERATION
,
5184 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5187 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5188 const Framebuffer::Attachment
* attachment_object
=
5189 framebuffer
->GetAttachment(attachment
);
5190 *params
= attachment_object
? attachment_object
->object_name() : 0;
5192 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5193 features().use_img_for_multisampled_render_to_texture
) {
5194 pname
= GL_TEXTURE_SAMPLES_IMG
;
5196 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5200 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5201 GLenum target
, GLenum pname
, GLint
* params
) {
5202 Renderbuffer
* renderbuffer
=
5203 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5204 if (!renderbuffer
) {
5206 GL_INVALID_OPERATION
,
5207 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5211 EnsureRenderbufferBound();
5213 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5214 *params
= renderbuffer
->internal_format();
5216 case GL_RENDERBUFFER_WIDTH
:
5217 *params
= renderbuffer
->width();
5219 case GL_RENDERBUFFER_HEIGHT
:
5220 *params
= renderbuffer
->height();
5222 case GL_RENDERBUFFER_SAMPLES_EXT
:
5223 if (features().use_img_for_multisampled_render_to_texture
) {
5224 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5227 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5231 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5236 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5237 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5238 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5239 GLbitfield mask
, GLenum filter
) {
5240 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5242 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5246 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5247 BlitFramebufferHelper(
5248 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5249 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5250 state_
.enable_flags
.scissor_test
);
5253 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5254 if (!state_
.bound_renderbuffer_valid
) {
5255 state_
.bound_renderbuffer_valid
= true;
5256 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5257 state_
.bound_renderbuffer
.get()
5258 ? state_
.bound_renderbuffer
->service_id()
5263 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5264 const FeatureInfo
* feature_info
,
5267 GLenum internal_format
,
5270 // TODO(sievers): This could be resolved at the GL binding level, but the
5271 // binding process is currently a bit too 'brute force'.
5272 if (feature_info
->feature_flags().is_angle
) {
5273 glRenderbufferStorageMultisampleANGLE(
5274 target
, samples
, internal_format
, width
, height
);
5275 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5276 glRenderbufferStorageMultisample(
5277 target
, samples
, internal_format
, width
, height
);
5279 glRenderbufferStorageMultisampleEXT(
5280 target
, samples
, internal_format
, width
, height
);
5284 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5294 // TODO(sievers): This could be resolved at the GL binding level, but the
5295 // binding process is currently a bit too 'brute force'.
5296 if (feature_info_
->feature_flags().is_angle
) {
5297 glBlitFramebufferANGLE(
5298 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5299 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5301 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5303 glBlitFramebufferEXT(
5304 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5308 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5310 GLenum internalformat
,
5313 if (samples
> renderbuffer_manager()->max_samples()) {
5316 "glRenderbufferStorageMultisample", "samples too large");
5320 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5321 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5324 "glRenderbufferStorageMultisample", "dimensions too large");
5328 uint32 estimated_size
= 0;
5329 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5330 width
, height
, samples
, internalformat
, &estimated_size
)) {
5333 "glRenderbufferStorageMultisample", "dimensions too large");
5337 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5340 "glRenderbufferStorageMultisample", "out of memory");
5347 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5348 GLenum target
, GLsizei samples
, GLenum internalformat
,
5349 GLsizei width
, GLsizei height
) {
5350 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5351 if (!renderbuffer
) {
5352 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5353 "glRenderbufferStorageMultisampleCHROMIUM",
5354 "no renderbuffer bound");
5358 if (!ValidateRenderbufferStorageMultisample(
5359 samples
, internalformat
, width
, height
)) {
5363 EnsureRenderbufferBound();
5364 GLenum impl_format
=
5365 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5367 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5368 "glRenderbufferStorageMultisampleCHROMIUM");
5369 RenderbufferStorageMultisampleHelper(
5370 feature_info_
, target
, samples
, impl_format
, width
, height
);
5372 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5373 if (error
== GL_NO_ERROR
) {
5375 if (workarounds().validate_multisample_buffer_allocation
) {
5376 if (!VerifyMultisampleRenderbufferIntegrity(
5377 renderbuffer
->service_id(), impl_format
)) {
5380 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5385 // TODO(gman): If renderbuffers tracked which framebuffers they were
5386 // attached to we could just mark those framebuffers as not complete.
5387 framebuffer_manager()->IncFramebufferStateChangeCount();
5388 renderbuffer_manager()->SetInfo(
5389 renderbuffer
, samples
, internalformat
, width
, height
);
5393 // This is the handler for multisampled_render_to_texture extensions.
5394 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5395 GLenum target
, GLsizei samples
, GLenum internalformat
,
5396 GLsizei width
, GLsizei height
) {
5397 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5398 if (!renderbuffer
) {
5399 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5400 "glRenderbufferStorageMultisampleEXT",
5401 "no renderbuffer bound");
5405 if (!ValidateRenderbufferStorageMultisample(
5406 samples
, internalformat
, width
, height
)) {
5410 EnsureRenderbufferBound();
5411 GLenum impl_format
=
5412 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5414 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5415 if (features().use_img_for_multisampled_render_to_texture
) {
5416 glRenderbufferStorageMultisampleIMG(
5417 target
, samples
, impl_format
, width
, height
);
5419 glRenderbufferStorageMultisampleEXT(
5420 target
, samples
, impl_format
, width
, height
);
5422 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5423 if (error
== GL_NO_ERROR
) {
5424 // TODO(gman): If renderbuffers tracked which framebuffers they were
5425 // attached to we could just mark those framebuffers as not complete.
5426 framebuffer_manager()->IncFramebufferStateChangeCount();
5427 renderbuffer_manager()->SetInfo(
5428 renderbuffer
, samples
, internalformat
, width
, height
);
5432 // This function validates the allocation of a multisampled renderbuffer
5433 // by clearing it to a key color, blitting the contents to a texture, and
5434 // reading back the color to ensure it matches the key.
5435 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5436 GLuint renderbuffer
, GLenum format
) {
5438 // Only validate color buffers.
5439 // These formats have been selected because they are very common or are known
5440 // to be used by the WebGL backbuffer. If problems are observed with other
5441 // color formats they can be added here.
5452 GLint draw_framebuffer
, read_framebuffer
;
5454 // Cache framebuffer and texture bindings.
5455 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5456 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5458 if (!validation_texture_
) {
5459 GLint bound_texture
;
5460 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5462 // Create additional resources needed for the verification.
5463 glGenTextures(1, &validation_texture_
);
5464 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5465 glGenFramebuffersEXT(1, &validation_fbo_
);
5467 // Texture only needs to be 1x1.
5468 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5469 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5470 GL_UNSIGNED_BYTE
, NULL
);
5472 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5473 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5474 GL_TEXTURE_2D
, validation_texture_
, 0);
5476 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5479 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5480 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5481 GL_RENDERBUFFER
, renderbuffer
);
5483 // Cache current state and reset it to the values we require.
5484 GLboolean scissor_enabled
= false;
5485 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5486 if (scissor_enabled
)
5487 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5489 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5490 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5491 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5493 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5494 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5495 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5497 // Clear the buffer to the desired key color.
5498 glClear(GL_COLOR_BUFFER_BIT
);
5500 // Blit from the multisample buffer to a standard texture.
5501 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5502 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5504 BlitFramebufferHelper(
5505 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5507 // Read a pixel from the buffer.
5508 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5510 unsigned char pixel
[3] = {0, 0, 0};
5511 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5513 // Detach the renderbuffer.
5514 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5515 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5516 GL_RENDERBUFFER
, 0);
5518 // Restore cached state.
5519 if (scissor_enabled
)
5520 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5522 state_
.SetDeviceColorMask(
5523 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5524 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5525 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5526 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5528 // Return true if the pixel matched the desired key color.
5529 return (pixel
[0] == 0xFF &&
5534 void GLES2DecoderImpl::DoRenderbufferStorage(
5535 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5536 Renderbuffer
* renderbuffer
=
5537 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5538 if (!renderbuffer
) {
5540 GL_INVALID_OPERATION
,
5541 "glRenderbufferStorage", "no renderbuffer bound");
5545 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5546 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5548 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5552 uint32 estimated_size
= 0;
5553 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5554 width
, height
, 1, internalformat
, &estimated_size
)) {
5556 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5560 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5562 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5566 EnsureRenderbufferBound();
5567 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5568 glRenderbufferStorageEXT(
5570 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5574 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5575 if (error
== GL_NO_ERROR
) {
5576 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5577 // we could just mark those framebuffers as not complete.
5578 framebuffer_manager()->IncFramebufferStateChangeCount();
5579 renderbuffer_manager()->SetInfo(
5580 renderbuffer
, 1, internalformat
, width
, height
);
5584 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5585 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5586 Program
* program
= GetProgramInfoNotShader(
5587 program_id
, "glLinkProgram");
5592 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5593 ShaderTranslator
* vertex_translator
= NULL
;
5594 ShaderTranslator
* fragment_translator
= NULL
;
5595 if (use_shader_translator_
) {
5596 vertex_translator
= vertex_translator_
.get();
5597 fragment_translator
= fragment_translator_
.get();
5599 if (program
->Link(shader_manager(),
5601 fragment_translator
,
5602 workarounds().count_all_in_varyings_packing
?
5603 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5604 shader_cache_callback_
)) {
5605 if (program
== state_
.current_program
.get()) {
5606 if (workarounds().use_current_program_after_successful_link
)
5607 glUseProgram(program
->service_id());
5608 if (workarounds().clear_uniforms_before_first_program_use
)
5609 program_manager()->ClearUniforms(program
);
5614 void GLES2DecoderImpl::DoTexParameterf(
5615 GLenum target
, GLenum pname
, GLfloat param
) {
5616 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5619 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5623 texture_manager()->SetParameterf(
5624 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5627 void GLES2DecoderImpl::DoTexParameteri(
5628 GLenum target
, GLenum pname
, GLint param
) {
5629 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5632 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5636 texture_manager()->SetParameteri(
5637 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5640 void GLES2DecoderImpl::DoTexParameterfv(
5641 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5642 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5645 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5649 texture_manager()->SetParameterf(
5650 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5653 void GLES2DecoderImpl::DoTexParameteriv(
5654 GLenum target
, GLenum pname
, const GLint
* params
) {
5655 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5659 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5663 texture_manager()->SetParameteri(
5664 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5667 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5668 if (!state_
.current_program
.get()) {
5669 // The program does not exist.
5671 GL_INVALID_OPERATION
, function_name
, "no program in use");
5674 if (!state_
.current_program
->InUse()) {
5676 GL_INVALID_OPERATION
, function_name
, "program not linked");
5682 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5683 GLint location
, const char* function_name
) {
5684 if (!CheckCurrentProgram(function_name
)) {
5687 return location
!= -1;
5690 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5691 GLint fake_location
,
5692 const char* function_name
,
5693 Program::UniformApiType api_type
,
5694 GLint
* real_location
,
5699 DCHECK(real_location
);
5701 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
5704 GLint array_index
= -1;
5705 const Program::UniformInfo
* info
=
5706 state_
.current_program
->GetUniformInfoByFakeLocation(
5707 fake_location
, real_location
, &array_index
);
5710 GL_INVALID_OPERATION
, function_name
, "unknown location");
5714 if ((api_type
& info
->accepts_api_type
) == 0) {
5716 GL_INVALID_OPERATION
, function_name
,
5717 "wrong uniform function for type");
5720 if (*count
> 1 && !info
->is_array
) {
5722 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
5725 *count
= std::min(info
->size
- array_index
, *count
);
5733 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
5736 GLint real_location
= -1;
5737 if (!PrepForSetUniformByLocation(fake_location
,
5739 Program::kUniform1i
,
5745 if (!state_
.current_program
->SetSamplers(
5746 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
5748 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
5751 glUniform1i(real_location
, v0
);
5754 void GLES2DecoderImpl::DoUniform1iv(
5755 GLint fake_location
, GLsizei count
, const GLint
*value
) {
5757 GLint real_location
= -1;
5758 if (!PrepForSetUniformByLocation(fake_location
,
5760 Program::kUniform1i
,
5766 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
5767 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
5768 if (!state_
.current_program
->SetSamplers(
5769 state_
.texture_units
.size(), fake_location
, count
, value
)) {
5771 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
5775 glUniform1iv(real_location
, count
, value
);
5778 void GLES2DecoderImpl::DoUniform1fv(
5779 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5781 GLint real_location
= -1;
5782 if (!PrepForSetUniformByLocation(fake_location
,
5784 Program::kUniform1f
,
5790 if (type
== GL_BOOL
) {
5791 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
5792 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
5793 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5795 DoUniform1iv(real_location
, count
, temp
.get());
5797 glUniform1fv(real_location
, count
, value
);
5801 void GLES2DecoderImpl::DoUniform2fv(
5802 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5804 GLint real_location
= -1;
5805 if (!PrepForSetUniformByLocation(fake_location
,
5807 Program::kUniform2f
,
5813 if (type
== GL_BOOL_VEC2
) {
5814 GLsizei num_values
= count
* 2;
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 glUniform2iv(real_location
, count
, temp
.get());
5821 glUniform2fv(real_location
, count
, value
);
5825 void GLES2DecoderImpl::DoUniform3fv(
5826 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5828 GLint real_location
= -1;
5829 if (!PrepForSetUniformByLocation(fake_location
,
5831 Program::kUniform3f
,
5837 if (type
== GL_BOOL_VEC3
) {
5838 GLsizei num_values
= count
* 3;
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 glUniform3iv(real_location
, count
, temp
.get());
5845 glUniform3fv(real_location
, count
, value
);
5849 void GLES2DecoderImpl::DoUniform4fv(
5850 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
5852 GLint real_location
= -1;
5853 if (!PrepForSetUniformByLocation(fake_location
,
5855 Program::kUniform4f
,
5861 if (type
== GL_BOOL_VEC4
) {
5862 GLsizei num_values
= count
* 4;
5863 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
5864 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
5865 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
5867 glUniform4iv(real_location
, count
, temp
.get());
5869 glUniform4fv(real_location
, count
, value
);
5873 void GLES2DecoderImpl::DoUniform2iv(
5874 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5876 GLint real_location
= -1;
5877 if (!PrepForSetUniformByLocation(fake_location
,
5879 Program::kUniform2i
,
5885 glUniform2iv(real_location
, count
, value
);
5888 void GLES2DecoderImpl::DoUniform3iv(
5889 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5891 GLint real_location
= -1;
5892 if (!PrepForSetUniformByLocation(fake_location
,
5894 Program::kUniform3i
,
5900 glUniform3iv(real_location
, count
, value
);
5903 void GLES2DecoderImpl::DoUniform4iv(
5904 GLint fake_location
, GLsizei count
, const GLint
* value
) {
5906 GLint real_location
= -1;
5907 if (!PrepForSetUniformByLocation(fake_location
,
5909 Program::kUniform4i
,
5915 glUniform4iv(real_location
, count
, value
);
5918 void GLES2DecoderImpl::DoUniformMatrix2fv(
5919 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5920 const GLfloat
* value
) {
5922 GLint real_location
= -1;
5923 if (!PrepForSetUniformByLocation(fake_location
,
5924 "glUniformMatrix2fv",
5925 Program::kUniformMatrix2f
,
5931 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
5934 void GLES2DecoderImpl::DoUniformMatrix3fv(
5935 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5936 const GLfloat
* value
) {
5938 GLint real_location
= -1;
5939 if (!PrepForSetUniformByLocation(fake_location
,
5940 "glUniformMatrix3fv",
5941 Program::kUniformMatrix3f
,
5947 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
5950 void GLES2DecoderImpl::DoUniformMatrix4fv(
5951 GLint fake_location
, GLsizei count
, GLboolean transpose
,
5952 const GLfloat
* value
) {
5954 GLint real_location
= -1;
5955 if (!PrepForSetUniformByLocation(fake_location
,
5956 "glUniformMatrix4fv",
5957 Program::kUniformMatrix4f
,
5963 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
5966 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
5967 GLuint service_id
= 0;
5968 Program
* program
= NULL
;
5970 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
5974 if (!program
->IsValid()) {
5975 // Program was not linked successfully. (ie, glLinkProgram)
5977 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
5980 service_id
= program
->service_id();
5982 if (state_
.current_program
.get()) {
5983 program_manager()->UnuseProgram(shader_manager(),
5984 state_
.current_program
.get());
5986 state_
.current_program
= program
;
5987 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
5988 glUseProgram(service_id
);
5989 if (state_
.current_program
.get()) {
5990 program_manager()->UseProgram(state_
.current_program
.get());
5991 if (workarounds().clear_uniforms_before_first_program_use
)
5992 program_manager()->ClearUniforms(program
);
5996 void GLES2DecoderImpl::RenderWarning(
5997 const char* filename
, int line
, const std::string
& msg
) {
5998 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6001 void GLES2DecoderImpl::PerformanceWarning(
6002 const char* filename
, int line
, const std::string
& msg
) {
6003 logger_
.LogMessage(filename
, line
,
6004 std::string("PERFORMANCE WARNING: ") + msg
);
6007 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6008 Texture
* texture
, GLenum textarget
) {
6009 // Image is already in use if texture is attached to a framebuffer.
6010 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6011 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6013 ScopedGLErrorSuppressor
suppressor(
6014 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6016 glBindTexture(textarget
, texture
->service_id());
6017 image
->WillUseTexImage();
6018 RestoreCurrentTextureBindings(&state_
, textarget
);
6023 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6024 Texture
* texture
, GLenum textarget
) {
6025 // Image is still in use if texture is attached to a framebuffer.
6026 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6027 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6029 ScopedGLErrorSuppressor
suppressor(
6030 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6032 glBindTexture(textarget
, texture
->service_id());
6033 image
->DidUseTexImage();
6034 RestoreCurrentTextureBindings(&state_
, textarget
);
6039 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6040 DCHECK(state_
.current_program
.get());
6041 if (!texture_manager()->HaveUnrenderableTextures() &&
6042 !texture_manager()->HaveImages()) {
6046 bool textures_set
= false;
6047 const Program::SamplerIndices
& sampler_indices
=
6048 state_
.current_program
->sampler_indices();
6049 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6050 const Program::UniformInfo
* uniform_info
=
6051 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6052 DCHECK(uniform_info
);
6053 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6054 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6055 if (texture_unit_index
< state_
.texture_units
.size()) {
6056 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6057 TextureRef
* texture_ref
=
6058 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6059 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6060 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6061 textures_set
= true;
6062 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6065 texture_manager()->black_texture_id(uniform_info
->type
));
6066 LOCAL_RENDER_WARNING(
6067 std::string("texture bound to texture unit ") +
6068 base::IntToString(texture_unit_index
) +
6069 " is not renderable. It maybe non-power-of-2 and have"
6070 " incompatible texture filtering or is not"
6071 " 'texture complete'");
6075 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6076 Texture
* texture
= texture_ref
->texture();
6077 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6078 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6079 ScopedGLErrorSuppressor
suppressor(
6080 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6081 textures_set
= true;
6082 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6083 image
->WillUseTexImage();
6088 // else: should this be an error?
6091 return !textures_set
;
6094 void GLES2DecoderImpl::RestoreStateForTextures() {
6095 DCHECK(state_
.current_program
.get());
6096 const Program::SamplerIndices
& sampler_indices
=
6097 state_
.current_program
->sampler_indices();
6098 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6099 const Program::UniformInfo
* uniform_info
=
6100 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6101 DCHECK(uniform_info
);
6102 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6103 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6104 if (texture_unit_index
< state_
.texture_units
.size()) {
6105 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6106 TextureRef
* texture_ref
=
6107 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6108 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6109 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6110 // Get the texture_ref info that was previously bound here.
6111 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6112 ? texture_unit
.bound_texture_2d
.get()
6113 : texture_unit
.bound_texture_cube_map
.get();
6114 glBindTexture(texture_unit
.bind_target
,
6115 texture_ref
? texture_ref
->service_id() : 0);
6119 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6120 Texture
* texture
= texture_ref
->texture();
6121 gfx::GLImage
* image
=
6122 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6123 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6124 ScopedGLErrorSuppressor
suppressor(
6125 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6126 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6127 image
->DidUseTexImage();
6134 // Set the active texture back to whatever the user had it as.
6135 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6138 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6139 // Only check if there are some uncleared textures.
6140 if (!texture_manager()->HaveUnsafeTextures()) {
6144 // 1: Check all textures we are about to render with.
6145 if (state_
.current_program
.get()) {
6146 const Program::SamplerIndices
& sampler_indices
=
6147 state_
.current_program
->sampler_indices();
6148 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6149 const Program::UniformInfo
* uniform_info
=
6150 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6151 DCHECK(uniform_info
);
6152 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6153 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6154 if (texture_unit_index
< state_
.texture_units
.size()) {
6155 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6156 TextureRef
* texture_ref
=
6157 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6158 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6159 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6170 bool GLES2DecoderImpl::IsDrawValid(
6171 const char* function_name
, GLuint max_vertex_accessed
, GLsizei primcount
) {
6172 // NOTE: We specifically do not check current_program->IsValid() because
6173 // it could never be invalid since glUseProgram would have failed. While
6174 // glLinkProgram could later mark the program as invalid the previous
6175 // valid program will still function if it is still the current program.
6176 if (!state_
.current_program
.get()) {
6177 // The program does not exist.
6178 // But GL says no ERROR.
6179 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6183 return state_
.vertex_attrib_manager
6184 ->ValidateBindings(function_name
,
6186 feature_info_
.get(),
6187 state_
.current_program
.get(),
6188 max_vertex_accessed
,
6192 bool GLES2DecoderImpl::SimulateAttrib0(
6193 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6197 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6200 const VertexAttrib
* attrib
=
6201 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6202 // If it's enabled or it's not used then we don't need to do anything.
6203 bool attrib_0_used
=
6204 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6205 if (attrib
->enabled() && attrib_0_used
) {
6209 // Make a buffer with a single repeated vec4 value enough to
6210 // simulate the constant value that is supposed to be here.
6211 // This is required to emulate GLES2 on GL.
6212 GLuint num_vertices
= max_vertex_accessed
+ 1;
6213 uint32 size_needed
= 0;
6215 if (num_vertices
== 0 ||
6216 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6217 size_needed
> 0x7FFFFFFFU
) {
6218 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6222 LOCAL_PERFORMANCE_WARNING(
6223 "Attribute 0 is disabled. This has signficant performance penalty");
6225 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6226 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6228 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6230 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6231 GLenum error
= glGetError();
6232 if (error
!= GL_NO_ERROR
) {
6234 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6239 const Vec4
& value
= state_
.attrib_values
[0];
6242 (!attrib_0_buffer_matches_value_
||
6243 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6244 value
.v
[1] != attrib_0_value_
.v
[1] ||
6245 value
.v
[2] != attrib_0_value_
.v
[2] ||
6246 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6247 std::vector
<Vec4
> temp(num_vertices
, value
);
6248 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6249 attrib_0_buffer_matches_value_
= true;
6250 attrib_0_value_
= value
;
6251 attrib_0_size_
= size_needed
;
6254 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6256 if (attrib
->divisor())
6257 glVertexAttribDivisorANGLE(0, 0);
6263 void GLES2DecoderImpl::RestoreStateForAttrib(
6264 GLuint attrib_index
, bool restore_array_binding
) {
6265 const VertexAttrib
* attrib
=
6266 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6267 if (restore_array_binding
) {
6268 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6269 Buffer
* buffer
= attrib
->buffer();
6270 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6271 glVertexAttribPointer(
6272 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6273 attrib
->gl_stride(), ptr
);
6275 if (attrib
->divisor())
6276 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6278 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6279 state_
.bound_array_buffer
->service_id() : 0);
6281 // Never touch vertex attribute 0's state (in particular, never
6282 // disable it) when running on desktop GL because it will never be
6284 if (attrib_index
!= 0 ||
6285 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6286 if (attrib
->enabled()) {
6287 glEnableVertexAttribArray(attrib_index
);
6289 glDisableVertexAttribArray(attrib_index
);
6294 bool GLES2DecoderImpl::SimulateFixedAttribs(
6295 const char* function_name
,
6296 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6299 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6302 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6306 LOCAL_PERFORMANCE_WARNING(
6307 "GL_FIXED attributes have a signficant performance penalty");
6309 // NOTE: we could be smart and try to check if a buffer is used
6310 // twice in 2 different attribs, find the overlapping parts and therefore
6311 // duplicate the minimum amount of data but this whole code path is not meant
6312 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6313 // tests so we just add to the buffer attrib used.
6315 GLuint elements_needed
= 0;
6316 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6317 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6318 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6319 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6320 const VertexAttrib
* attrib
= *it
;
6321 const Program::VertexAttrib
* attrib_info
=
6322 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6323 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6324 max_vertex_accessed
);
6325 GLuint num_vertices
= max_accessed
+ 1;
6326 if (num_vertices
== 0) {
6328 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6332 attrib
->CanAccess(max_accessed
) &&
6333 attrib
->type() == GL_FIXED
) {
6334 uint32 elements_used
= 0;
6335 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6336 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6338 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6344 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6345 uint32 size_needed
= 0;
6346 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6347 size_needed
> 0x7FFFFFFFU
) {
6349 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6353 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6355 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6356 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6357 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6358 GLenum error
= glGetError();
6359 if (error
!= GL_NO_ERROR
) {
6361 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6366 // Copy the elements and convert to float
6367 GLintptr offset
= 0;
6368 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6369 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6370 const VertexAttrib
* attrib
= *it
;
6371 const Program::VertexAttrib
* attrib_info
=
6372 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6373 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6374 max_vertex_accessed
);
6375 GLuint num_vertices
= max_accessed
+ 1;
6376 if (num_vertices
== 0) {
6378 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6382 attrib
->CanAccess(max_accessed
) &&
6383 attrib
->type() == GL_FIXED
) {
6384 int num_elements
= attrib
->size() * kSizeOfFloat
;
6385 int size
= num_elements
* num_vertices
;
6386 scoped_ptr
<float[]> data(new float[size
]);
6387 const int32
* src
= reinterpret_cast<const int32
*>(
6388 attrib
->buffer()->GetRange(attrib
->offset(), size
));
6389 const int32
* end
= src
+ num_elements
;
6390 float* dst
= data
.get();
6391 while (src
!= end
) {
6392 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6394 glBufferSubData(GL_ARRAY_BUFFER
, offset
, size
, data
.get());
6395 glVertexAttribPointer(
6396 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6397 reinterpret_cast<GLvoid
*>(offset
));
6405 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6406 // There's no need to call glVertexAttribPointer because we shadow all the
6407 // settings and passing GL_FIXED to it will not work.
6410 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6414 error::Error
GLES2DecoderImpl::DoDrawArrays(
6415 const char* function_name
,
6420 GLsizei primcount
) {
6421 error::Error error
= WillAccessBoundFramebufferForDraw();
6422 if (error
!= error::kNoError
)
6424 if (!validators_
->draw_mode
.IsValid(mode
)) {
6425 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6426 return error::kNoError
;
6429 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6430 return error::kNoError
;
6432 if (primcount
< 0) {
6433 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6434 return error::kNoError
;
6436 if (!CheckBoundFramebuffersValid(function_name
)) {
6437 return error::kNoError
;
6439 // We have to check this here because the prototype for glDrawArrays
6440 // is GLint not GLsizei.
6442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6443 return error::kNoError
;
6446 if (count
== 0 || (instanced
&& primcount
== 0)) {
6447 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6448 return error::kNoError
;
6451 GLuint max_vertex_accessed
= first
+ count
- 1;
6452 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
6453 if (!ClearUnclearedTextures()) {
6454 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6455 return error::kNoError
;
6457 bool simulated_attrib_0
= false;
6458 if (!SimulateAttrib0(
6459 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6460 return error::kNoError
;
6462 bool simulated_fixed_attribs
= false;
6463 if (SimulateFixedAttribs(
6464 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6466 bool textures_set
= !PrepareTexturesForRender();
6468 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6470 glDrawArrays(mode
, first
, count
);
6472 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6475 RestoreStateForTextures();
6477 if (simulated_fixed_attribs
) {
6478 RestoreStateForSimulatedFixedAttribs();
6481 if (simulated_attrib_0
) {
6482 // We don't have to restore attrib 0 generic data at the end of this
6483 // function even if it is simulated. This is because we will simulate
6484 // it in each draw call, and attrib 0 generic data queries use cached
6485 // values instead of passing down to the underlying driver.
6486 RestoreStateForAttrib(0, false);
6489 return error::kNoError
;
6492 error::Error
GLES2DecoderImpl::HandleDrawArrays(
6493 uint32 immediate_data_size
, const cmds::DrawArrays
& c
) {
6494 return DoDrawArrays("glDrawArrays",
6496 static_cast<GLenum
>(c
.mode
),
6497 static_cast<GLint
>(c
.first
),
6498 static_cast<GLsizei
>(c
.count
),
6502 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6503 uint32 immediate_data_size
, const cmds::DrawArraysInstancedANGLE
& c
) {
6504 if (!features().angle_instanced_arrays
) {
6506 GL_INVALID_OPERATION
,
6507 "glDrawArraysInstancedANGLE", "function not available");
6508 return error::kNoError
;
6510 return DoDrawArrays("glDrawArraysIntancedANGLE",
6512 static_cast<GLenum
>(c
.mode
),
6513 static_cast<GLint
>(c
.first
),
6514 static_cast<GLsizei
>(c
.count
),
6515 static_cast<GLsizei
>(c
.primcount
));
6518 error::Error
GLES2DecoderImpl::DoDrawElements(
6519 const char* function_name
,
6525 GLsizei primcount
) {
6526 error::Error error
= WillAccessBoundFramebufferForDraw();
6527 if (error
!= error::kNoError
)
6529 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6531 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6532 return error::kNoError
;
6536 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6537 return error::kNoError
;
6540 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6541 return error::kNoError
;
6543 if (!validators_
->draw_mode
.IsValid(mode
)) {
6544 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6545 return error::kNoError
;
6547 if (!validators_
->index_type
.IsValid(type
)) {
6548 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6549 return error::kNoError
;
6551 if (primcount
< 0) {
6552 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6553 return error::kNoError
;
6556 if (!CheckBoundFramebuffersValid(function_name
)) {
6557 return error::kNoError
;
6560 if (count
== 0 || (instanced
&& primcount
== 0)) {
6561 return error::kNoError
;
6564 GLuint max_vertex_accessed
;
6565 Buffer
* element_array_buffer
=
6566 state_
.vertex_attrib_manager
->element_array_buffer();
6568 if (!element_array_buffer
->GetMaxValueForRange(
6569 offset
, count
, type
, &max_vertex_accessed
)) {
6571 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6572 return error::kNoError
;
6575 if (IsDrawValid(function_name
, max_vertex_accessed
, primcount
)) {
6576 if (!ClearUnclearedTextures()) {
6577 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6578 return error::kNoError
;
6580 bool simulated_attrib_0
= false;
6581 if (!SimulateAttrib0(
6582 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6583 return error::kNoError
;
6585 bool simulated_fixed_attribs
= false;
6586 if (SimulateFixedAttribs(
6587 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6589 bool textures_set
= !PrepareTexturesForRender();
6591 // TODO(gman): Refactor to hide these details in BufferManager or
6592 // VertexAttribManager.
6593 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6594 bool used_client_side_array
= false;
6595 if (element_array_buffer
->IsClientSideArray()) {
6596 used_client_side_array
= true;
6597 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6598 indices
= element_array_buffer
->GetRange(offset
, 0);
6601 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6603 glDrawElements(mode
, count
, type
, indices
);
6605 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6608 if (used_client_side_array
) {
6609 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6610 element_array_buffer
->service_id());
6614 RestoreStateForTextures();
6616 if (simulated_fixed_attribs
) {
6617 RestoreStateForSimulatedFixedAttribs();
6620 if (simulated_attrib_0
) {
6621 // We don't have to restore attrib 0 generic data at the end of this
6622 // function even if it is simulated. This is because we will simulate
6623 // it in each draw call, and attrib 0 generic data queries use cached
6624 // values instead of passing down to the underlying driver.
6625 RestoreStateForAttrib(0, false);
6628 return error::kNoError
;
6631 error::Error
GLES2DecoderImpl::HandleDrawElements(
6632 uint32 immediate_data_size
, const cmds::DrawElements
& c
) {
6633 return DoDrawElements("glDrawElements",
6635 static_cast<GLenum
>(c
.mode
),
6636 static_cast<GLsizei
>(c
.count
),
6637 static_cast<GLenum
>(c
.type
),
6638 static_cast<int32
>(c
.index_offset
),
6642 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6643 uint32 immediate_data_size
, const cmds::DrawElementsInstancedANGLE
& c
) {
6644 if (!features().angle_instanced_arrays
) {
6646 GL_INVALID_OPERATION
,
6647 "glDrawElementsInstancedANGLE", "function not available");
6648 return error::kNoError
;
6650 return DoDrawElements("glDrawElementsInstancedANGLE",
6652 static_cast<GLenum
>(c
.mode
),
6653 static_cast<GLsizei
>(c
.count
),
6654 static_cast<GLenum
>(c
.type
),
6655 static_cast<int32
>(c
.index_offset
),
6656 static_cast<GLsizei
>(c
.primcount
));
6659 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6660 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
6661 GLuint max_vertex_accessed
= 0;
6662 Buffer
* buffer
= GetBuffer(buffer_id
);
6664 // TODO(gman): Should this be a GL error or a command buffer error?
6666 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6668 if (!buffer
->GetMaxValueForRange(
6669 offset
, count
, type
, &max_vertex_accessed
)) {
6670 // TODO(gman): Should this be a GL error or a command buffer error?
6672 GL_INVALID_OPERATION
,
6673 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6676 return max_vertex_accessed
;
6679 // Calls glShaderSource for the various versions of the ShaderSource command.
6680 // Assumes that data / data_size points to a piece of memory that is in range
6681 // of whatever context it came from (shared memory, immediate memory, bucket
6683 error::Error
GLES2DecoderImpl::ShaderSourceHelper(
6684 GLuint client_id
, const char* data
, uint32 data_size
) {
6685 std::string
str(data
, data
+ data_size
);
6686 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
6688 return error::kNoError
;
6690 // Note: We don't actually call glShaderSource here. We wait until
6691 // the call to glCompileShader.
6692 shader
->UpdateSource(str
.c_str());
6693 return error::kNoError
;
6696 error::Error
GLES2DecoderImpl::HandleShaderSourceBucket(
6697 uint32 immediate_data_size
, const cmds::ShaderSourceBucket
& c
) {
6698 Bucket
* bucket
= GetBucket(c
.data_bucket_id
);
6699 if (!bucket
|| bucket
->size() == 0) {
6700 return error::kInvalidArguments
;
6702 return ShaderSourceHelper(
6703 c
.shader
, bucket
->GetDataAs
<const char*>(0, bucket
->size() - 1),
6704 bucket
->size() - 1);
6707 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
6708 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6709 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
6713 ShaderTranslator
* translator
= NULL
;
6714 if (use_shader_translator_
) {
6715 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
6716 vertex_translator_
.get() : fragment_translator_
.get();
6719 program_manager()->DoCompileShader(
6722 feature_info_
->feature_flags().angle_translated_shader_source
?
6723 ProgramManager::kANGLE
: ProgramManager::kGL
);
6726 void GLES2DecoderImpl::DoGetShaderiv(
6727 GLuint shader_id
, GLenum pname
, GLint
* params
) {
6728 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
6733 case GL_SHADER_SOURCE_LENGTH
:
6734 *params
= shader
->source() ? shader
->source()->size() + 1 : 0;
6736 case GL_COMPILE_STATUS
:
6737 *params
= compile_shader_always_succeeds_
? true : shader
->IsValid();
6739 case GL_INFO_LOG_LENGTH
:
6740 *params
= shader
->log_info() ? shader
->log_info()->size() + 1 : 0;
6742 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
6743 *params
= shader
->translated_source() ?
6744 shader
->translated_source()->size() + 1 : 0;
6749 glGetShaderiv(shader
->service_id(), pname
, params
);
6752 error::Error
GLES2DecoderImpl::HandleGetShaderSource(
6753 uint32 immediate_data_size
, const cmds::GetShaderSource
& c
) {
6754 GLuint shader_id
= c
.shader
;
6755 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6756 Bucket
* bucket
= CreateBucket(bucket_id
);
6757 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
6758 if (!shader
|| !shader
->source()) {
6760 return error::kNoError
;
6762 bucket
->SetFromString(shader
->source()->c_str());
6763 return error::kNoError
;
6766 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6767 uint32 immediate_data_size
,
6768 const cmds::GetTranslatedShaderSourceANGLE
& c
) {
6769 GLuint shader_id
= c
.shader
;
6770 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6771 Bucket
* bucket
= CreateBucket(bucket_id
);
6772 Shader
* shader
= GetShaderInfoNotProgram(
6773 shader_id
, "glGetTranslatedShaderSourceANGLE");
6776 return error::kNoError
;
6779 bucket
->SetFromString(shader
->translated_source() ?
6780 shader
->translated_source()->c_str() : NULL
);
6781 return error::kNoError
;
6784 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
6785 uint32 immediate_data_size
, const cmds::GetProgramInfoLog
& c
) {
6786 GLuint program_id
= c
.program
;
6787 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6788 Bucket
* bucket
= CreateBucket(bucket_id
);
6789 Program
* program
= GetProgramInfoNotShader(
6790 program_id
, "glGetProgramInfoLog");
6791 if (!program
|| !program
->log_info()) {
6792 bucket
->SetFromString("");
6793 return error::kNoError
;
6795 bucket
->SetFromString(program
->log_info()->c_str());
6796 return error::kNoError
;
6799 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
6800 uint32 immediate_data_size
, const cmds::GetShaderInfoLog
& c
) {
6801 GLuint shader_id
= c
.shader
;
6802 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
6803 Bucket
* bucket
= CreateBucket(bucket_id
);
6804 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
6805 if (!shader
|| !shader
->log_info()) {
6806 bucket
->SetFromString("");
6807 return error::kNoError
;
6809 bucket
->SetFromString(shader
->log_info()->c_str());
6810 return error::kNoError
;
6813 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
6814 return state_
.GetEnabled(cap
);
6817 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
6818 const Buffer
* buffer
= GetBuffer(client_id
);
6819 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
6822 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
6823 const Framebuffer
* framebuffer
=
6824 GetFramebuffer(client_id
);
6825 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
6828 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
6829 // IsProgram is true for programs as soon as they are created, until they are
6830 // deleted and no longer in use.
6831 const Program
* program
= GetProgram(client_id
);
6832 return program
!= NULL
&& !program
->IsDeleted();
6835 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
6836 const Renderbuffer
* renderbuffer
=
6837 GetRenderbuffer(client_id
);
6838 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
6841 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
6842 // IsShader is true for shaders as soon as they are created, until they
6843 // are deleted and not attached to any programs.
6844 const Shader
* shader
= GetShader(client_id
);
6845 return shader
!= NULL
&& !shader
->IsDeleted();
6848 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
6849 const TextureRef
* texture_ref
= GetTexture(client_id
);
6850 return texture_ref
&& texture_ref
->texture()->IsValid();
6853 void GLES2DecoderImpl::DoAttachShader(
6854 GLuint program_client_id
, GLint shader_client_id
) {
6855 Program
* program
= GetProgramInfoNotShader(
6856 program_client_id
, "glAttachShader");
6860 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
6864 if (!program
->AttachShader(shader_manager(), shader
)) {
6866 GL_INVALID_OPERATION
,
6868 "can not attach more than one shader of the same type.");
6871 glAttachShader(program
->service_id(), shader
->service_id());
6874 void GLES2DecoderImpl::DoDetachShader(
6875 GLuint program_client_id
, GLint shader_client_id
) {
6876 Program
* program
= GetProgramInfoNotShader(
6877 program_client_id
, "glDetachShader");
6881 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
6885 if (!program
->DetachShader(shader_manager(), shader
)) {
6887 GL_INVALID_OPERATION
,
6888 "glDetachShader", "shader not attached to program");
6891 glDetachShader(program
->service_id(), shader
->service_id());
6894 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
6895 Program
* program
= GetProgramInfoNotShader(
6896 program_client_id
, "glValidateProgram");
6900 program
->Validate();
6903 void GLES2DecoderImpl::GetVertexAttribHelper(
6904 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
6906 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
6907 Buffer
* buffer
= attrib
->buffer();
6908 if (buffer
&& !buffer
->IsDeleted()) {
6910 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
6911 *params
= client_id
;
6915 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
6916 *params
= attrib
->enabled();
6918 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
6919 *params
= attrib
->size();
6921 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
6922 *params
= attrib
->gl_stride();
6924 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
6925 *params
= attrib
->type();
6927 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
6928 *params
= attrib
->normalized();
6930 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
6931 *params
= attrib
->divisor();
6939 void GLES2DecoderImpl::DoGetTexParameterfv(
6940 GLenum target
, GLenum pname
, GLfloat
* params
) {
6941 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
6942 glGetTexParameterfv(target
, pname
, params
);
6945 void GLES2DecoderImpl::DoGetTexParameteriv(
6946 GLenum target
, GLenum pname
, GLint
* params
) {
6947 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
6948 glGetTexParameteriv(target
, pname
, params
);
6951 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6952 GLenum target
, GLenum pname
) {
6953 if (!workarounds().init_texture_max_anisotropy
)
6955 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
6956 !validators_
->texture_parameter
.IsValid(pname
)) {
6960 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
6964 GL_INVALID_OPERATION
,
6965 "glGetTexParamter{fi}v", "unknown texture for target");
6968 Texture
* texture
= texture_ref
->texture();
6969 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
6972 void GLES2DecoderImpl::DoGetVertexAttribfv(
6973 GLuint index
, GLenum pname
, GLfloat
* params
) {
6974 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
6977 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
6981 case GL_CURRENT_VERTEX_ATTRIB
: {
6982 const Vec4
& value
= state_
.attrib_values
[index
];
6983 params
[0] = value
.v
[0];
6984 params
[1] = value
.v
[1];
6985 params
[2] = value
.v
[2];
6986 params
[3] = value
.v
[3];
6991 GetVertexAttribHelper(attrib
, pname
, &value
);
6992 *params
= static_cast<GLfloat
>(value
);
6998 void GLES2DecoderImpl::DoGetVertexAttribiv(
6999 GLuint index
, GLenum pname
, GLint
* params
) {
7000 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7003 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7007 case GL_CURRENT_VERTEX_ATTRIB
: {
7008 const Vec4
& value
= state_
.attrib_values
[index
];
7009 params
[0] = static_cast<GLint
>(value
.v
[0]);
7010 params
[1] = static_cast<GLint
>(value
.v
[1]);
7011 params
[2] = static_cast<GLint
>(value
.v
[2]);
7012 params
[3] = static_cast<GLint
>(value
.v
[3]);
7016 GetVertexAttribHelper(attrib
, pname
, params
);
7021 bool GLES2DecoderImpl::SetVertexAttribValue(
7022 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7023 if (index
>= state_
.attrib_values
.size()) {
7024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7027 Vec4
& v
= state_
.attrib_values
[index
];
7035 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7036 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7037 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7038 glVertexAttrib1f(index
, v0
);
7042 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7043 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7044 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7045 glVertexAttrib2f(index
, v0
, v1
);
7049 void GLES2DecoderImpl::DoVertexAttrib3f(
7050 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7051 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7052 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7053 glVertexAttrib3f(index
, v0
, v1
, v2
);
7057 void GLES2DecoderImpl::DoVertexAttrib4f(
7058 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7059 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7060 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7061 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7065 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7066 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7067 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7068 glVertexAttrib1fv(index
, v
);
7072 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7073 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7074 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7075 glVertexAttrib2fv(index
, v
);
7079 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7080 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7081 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7082 glVertexAttrib3fv(index
, v
);
7086 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7087 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7088 glVertexAttrib4fv(index
, v
);
7092 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7093 uint32 immediate_data_size
, const cmds::VertexAttribPointer
& c
) {
7095 if (!state_
.bound_array_buffer
.get() ||
7096 state_
.bound_array_buffer
->IsDeleted()) {
7097 if (state_
.vertex_attrib_manager
.get() ==
7098 state_
.default_vertex_attrib_manager
.get()) {
7100 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7101 return error::kNoError
;
7102 } else if (c
.offset
!= 0) {
7105 "glVertexAttribPointer", "client side arrays are not allowed");
7106 return error::kNoError
;
7110 GLuint indx
= c
.indx
;
7111 GLint size
= c
.size
;
7112 GLenum type
= c
.type
;
7113 GLboolean normalized
= c
.normalized
;
7114 GLsizei stride
= c
.stride
;
7115 GLsizei offset
= c
.offset
;
7116 const void* ptr
= reinterpret_cast<const void*>(offset
);
7117 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7118 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7119 return error::kNoError
;
7121 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7123 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7124 return error::kNoError
;
7126 if (indx
>= group_
->max_vertex_attribs()) {
7128 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7129 return error::kNoError
;
7133 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7134 return error::kNoError
;
7138 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7139 return error::kNoError
;
7143 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7144 return error::kNoError
;
7146 GLsizei component_size
=
7147 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7148 if (offset
% component_size
> 0) {
7150 GL_INVALID_OPERATION
,
7151 "glVertexAttribPointer", "offset not valid for type");
7152 return error::kNoError
;
7154 if (stride
% component_size
> 0) {
7156 GL_INVALID_OPERATION
,
7157 "glVertexAttribPointer", "stride not valid for type");
7158 return error::kNoError
;
7160 state_
.vertex_attrib_manager
7161 ->SetAttribInfo(indx
,
7162 state_
.bound_array_buffer
.get(),
7167 stride
!= 0 ? stride
: component_size
* size
,
7169 if (type
!= GL_FIXED
) {
7170 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7172 return error::kNoError
;
7175 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7177 state_
.viewport_x
= x
;
7178 state_
.viewport_y
= y
;
7179 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7180 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7181 glViewport(x
, y
, width
, height
);
7184 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7185 uint32 immediate_data_size
, const cmds::VertexAttribDivisorANGLE
& c
) {
7186 if (!features().angle_instanced_arrays
) {
7188 GL_INVALID_OPERATION
,
7189 "glVertexAttribDivisorANGLE", "function not available");
7190 return error::kNoError
;
7192 GLuint index
= c
.index
;
7193 GLuint divisor
= c
.divisor
;
7194 if (index
>= group_
->max_vertex_attribs()) {
7197 "glVertexAttribDivisorANGLE", "index out of range");
7198 return error::kNoError
;
7201 state_
.vertex_attrib_manager
->SetDivisor(
7204 glVertexAttribDivisorANGLE(index
, divisor
);
7205 return error::kNoError
;
7208 template <typename pixel_data_type
>
7209 static void WriteAlphaData(
7210 void *pixels
, uint32 row_count
, uint32 channel_count
,
7211 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7212 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7213 DCHECK_GT(channel_count
, 0U);
7214 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7215 uint32 unpadded_row_size_in_elements
=
7216 unpadded_row_size
/ sizeof(pixel_data_type
);
7217 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7218 uint32 padded_row_size_in_elements
=
7219 padded_row_size
/ sizeof(pixel_data_type
);
7220 pixel_data_type
* dst
=
7221 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7222 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7223 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7224 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7227 dst
+= padded_row_size_in_elements
;
7231 void GLES2DecoderImpl::FinishReadPixels(
7232 const cmds::ReadPixels
& c
,
7234 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7235 GLsizei width
= c
.width
;
7236 GLsizei height
= c
.height
;
7237 GLenum format
= c
.format
;
7238 GLenum type
= c
.type
;
7239 typedef cmds::ReadPixels::Result Result
;
7241 Result
* result
= NULL
;
7242 if (c
.result_shm_id
!= 0) {
7243 result
= GetSharedMemoryAs
<Result
*>(
7244 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7247 glDeleteBuffersARB(1, &buffer
);
7252 GLES2Util::ComputeImageDataSizes(
7253 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7255 void* pixels
= GetSharedMemoryAs
<void*>(
7256 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7259 glDeleteBuffersARB(1, &buffer
);
7265 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7267 if (features().map_buffer_range
) {
7268 data
= glMapBufferRange(
7269 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7271 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7273 memcpy(pixels
, data
, pixels_size
);
7274 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7275 // have to restore the state.
7276 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7277 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7278 glDeleteBuffersARB(1, &buffer
);
7281 if (result
!= NULL
) {
7285 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7286 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7287 if ((channels_exist
& 0x0008) == 0 &&
7288 workarounds().clear_alpha_in_readpixels
) {
7289 // Set the alpha to 255 because some drivers are buggy in this regard.
7292 uint32 unpadded_row_size
;
7293 uint32 padded_row_size
;
7294 if (!GLES2Util::ComputeImageDataSizes(
7295 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7296 &unpadded_row_size
, &padded_row_size
)) {
7300 uint32 channel_count
= 0;
7301 uint32 alpha_channel
= 0;
7314 if (channel_count
> 0) {
7316 case GL_UNSIGNED_BYTE
:
7317 WriteAlphaData
<uint8
>(
7318 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7319 padded_row_size
, 0xFF);
7322 WriteAlphaData
<float>(
7323 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7324 padded_row_size
, 1.0f
);
7327 WriteAlphaData
<uint16
>(
7328 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7329 padded_row_size
, 0x3C00);
7337 error::Error
GLES2DecoderImpl::HandleReadPixels(
7338 uint32 immediate_data_size
, const cmds::ReadPixels
& c
) {
7339 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7340 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7341 if (fbo_error
!= error::kNoError
)
7345 GLsizei width
= c
.width
;
7346 GLsizei height
= c
.height
;
7347 GLenum format
= c
.format
;
7348 GLenum type
= c
.type
;
7349 GLboolean async
= c
.async
;
7350 if (width
< 0 || height
< 0) {
7351 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7352 return error::kNoError
;
7354 typedef cmds::ReadPixels::Result Result
;
7356 if (!GLES2Util::ComputeImageDataSizes(
7357 width
, height
, format
, type
, state_
.pack_alignment
, &pixels_size
,
7359 return error::kOutOfBounds
;
7361 void* pixels
= GetSharedMemoryAs
<void*>(
7362 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7364 return error::kOutOfBounds
;
7366 Result
* result
= NULL
;
7367 if (c
.result_shm_id
!= 0) {
7368 result
= GetSharedMemoryAs
<Result
*>(
7369 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7371 return error::kOutOfBounds
;
7375 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7376 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7377 return error::kNoError
;
7379 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7380 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7381 return error::kNoError
;
7383 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7384 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7385 // format and type are acceptable enums but not guaranteed to be supported
7386 // for this framebuffer. Have to ask gl if they are valid.
7387 GLint preferred_format
= 0;
7388 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7389 GLint preferred_type
= 0;
7390 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7391 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7392 type
!= static_cast<GLenum
>(preferred_type
)) {
7394 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7395 "with the current read framebuffer");
7396 return error::kNoError
;
7399 if (width
== 0 || height
== 0) {
7400 return error::kNoError
;
7403 // Get the size of the current fbo or backbuffer.
7404 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7408 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7410 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7411 return error::kNoError
;
7414 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7415 return error::kNoError
;
7418 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7420 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7422 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7423 // The user requested an out of range area. Get the results 1 line
7426 uint32 unpadded_row_size
;
7427 uint32 padded_row_size
;
7428 if (!GLES2Util::ComputeImageDataSizes(
7429 width
, 2, format
, type
, state_
.pack_alignment
, &temp_size
,
7430 &unpadded_row_size
, &padded_row_size
)) {
7432 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7433 return error::kNoError
;
7436 GLint dest_x_offset
= std::max(-x
, 0);
7437 uint32 dest_row_offset
;
7438 if (!GLES2Util::ComputeImageDataSizes(
7439 dest_x_offset
, 1, format
, type
, state_
.pack_alignment
, &dest_row_offset
,
7442 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7443 return error::kNoError
;
7446 // Copy each row into the larger dest rect.
7447 int8
* dst
= static_cast<int8
*>(pixels
);
7448 GLint read_x
= std::max(0, x
);
7449 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7450 GLint read_width
= read_end_x
- read_x
;
7451 for (GLint yy
= 0; yy
< height
; ++yy
) {
7455 memset(dst
, 0, unpadded_row_size
);
7457 // If the row is in range, copy it.
7458 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7460 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7462 dst
+= padded_row_size
;
7465 if (async
&& features().use_async_readpixels
) {
7467 glGenBuffersARB(1, &buffer
);
7468 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7469 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, GL_STREAM_READ
);
7470 GLenum error
= glGetError();
7471 if (error
== GL_NO_ERROR
) {
7472 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7473 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7474 new FenceCallback()));
7475 WaitForReadPixels(base::Bind(
7476 &GLES2DecoderImpl::FinishReadPixels
,
7477 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7478 <GLES2DecoderImpl
>(this),
7480 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7481 return error::kNoError
;
7483 // On error, unbind pack buffer and fall through to sync readpixels
7484 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7487 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7489 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7490 if (error
== GL_NO_ERROR
) {
7491 if (result
!= NULL
) {
7494 FinishReadPixels(c
, 0);
7497 return error::kNoError
;
7500 error::Error
GLES2DecoderImpl::HandlePixelStorei(
7501 uint32 immediate_data_size
, const cmds::PixelStorei
& c
) {
7502 GLenum pname
= c
.pname
;
7503 GLenum param
= c
.param
;
7504 if (!validators_
->pixel_store
.IsValid(pname
)) {
7505 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7506 return error::kNoError
;
7509 case GL_PACK_ALIGNMENT
:
7510 case GL_UNPACK_ALIGNMENT
:
7511 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7513 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7514 return error::kNoError
;
7517 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7518 unpack_flip_y_
= (param
!= 0);
7519 return error::kNoError
;
7520 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7521 unpack_premultiply_alpha_
= (param
!= 0);
7522 return error::kNoError
;
7523 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7524 unpack_unpremultiply_alpha_
= (param
!= 0);
7525 return error::kNoError
;
7529 glPixelStorei(pname
, param
);
7531 case GL_PACK_ALIGNMENT
:
7532 state_
.pack_alignment
= param
;
7534 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
7535 state_
.pack_reverse_row_order
= (param
!= 0);
7537 case GL_UNPACK_ALIGNMENT
:
7538 state_
.unpack_alignment
= param
;
7541 // Validation should have prevented us from getting here.
7545 return error::kNoError
;
7548 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7549 uint32 immediate_data_size
, const cmds::PostSubBufferCHROMIUM
& c
) {
7550 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7552 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7554 if (!supports_post_sub_buffer_
) {
7556 GL_INVALID_OPERATION
,
7557 "glPostSubBufferCHROMIUM", "command not supported by surface");
7558 return error::kNoError
;
7561 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7564 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
7565 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
7566 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
7567 is_offscreen
? offscreen_size_
: surface_
->GetSize());
7569 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
7570 return error::kNoError
;
7572 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
7573 return error::kLostContext
;
7577 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7578 uint32 immediate_data_size
,
7579 const cmds::ScheduleOverlayPlaneCHROMIUM
& c
) {
7580 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7581 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
7582 "glScheduleOverlayPlaneCHROMIUM",
7583 "function not implemented");
7584 return error::kNoError
;
7587 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
7588 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7589 const std::string
& name_str
) {
7590 if (!StringIsValidForGLES(name_str
.c_str())) {
7592 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
7593 return error::kNoError
;
7595 Program
* program
= GetProgramInfoNotShader(
7596 client_id
, "glGetAttribLocation");
7598 return error::kNoError
;
7600 if (!program
->IsValid()) {
7602 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
7603 return error::kNoError
;
7605 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7606 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7608 return error::kOutOfBounds
;
7610 // Require the client to init this incase the context is lost and we are no
7611 // longer executing commands.
7612 if (*location
!= -1) {
7613 return error::kGenericError
;
7615 *location
= program
->GetAttribLocation(name_str
);
7616 return error::kNoError
;
7619 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
7620 uint32 immediate_data_size
, const cmds::GetAttribLocation
& c
) {
7621 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7623 return error::kInvalidArguments
;
7625 std::string name_str
;
7626 if (!bucket
->GetAsString(&name_str
)) {
7627 return error::kInvalidArguments
;
7629 return GetAttribLocationHelper(
7630 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7633 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
7634 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
7635 const std::string
& name_str
) {
7636 if (!StringIsValidForGLES(name_str
.c_str())) {
7638 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
7639 return error::kNoError
;
7641 Program
* program
= GetProgramInfoNotShader(
7642 client_id
, "glGetUniformLocation");
7644 return error::kNoError
;
7646 if (!program
->IsValid()) {
7648 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
7649 return error::kNoError
;
7651 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
7652 location_shm_id
, location_shm_offset
, sizeof(GLint
));
7654 return error::kOutOfBounds
;
7656 // Require the client to init this incase the context is lost an we are no
7657 // longer executing commands.
7658 if (*location
!= -1) {
7659 return error::kGenericError
;
7661 *location
= program
->GetUniformFakeLocation(name_str
);
7662 return error::kNoError
;
7665 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
7666 uint32 immediate_data_size
, const cmds::GetUniformLocation
& c
) {
7667 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
7669 return error::kInvalidArguments
;
7671 std::string name_str
;
7672 if (!bucket
->GetAsString(&name_str
)) {
7673 return error::kInvalidArguments
;
7675 return GetUniformLocationHelper(
7676 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
7679 error::Error
GLES2DecoderImpl::HandleGetString(
7680 uint32 immediate_data_size
, const cmds::GetString
& c
) {
7681 GLenum name
= static_cast<GLenum
>(c
.name
);
7682 if (!validators_
->string_type
.IsValid(name
)) {
7683 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
7684 return error::kNoError
;
7686 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
7687 std::string extensions
;
7690 str
= "OpenGL ES 2.0 Chromium";
7692 case GL_SHADING_LANGUAGE_VERSION
:
7693 str
= "OpenGL ES GLSL ES 1.0 Chromium";
7697 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7698 // They are used by WEBGL_debug_renderer_info.
7699 if (!force_webgl_glsl_validation_
)
7704 // For WebGL contexts, strip out the OES derivatives and
7705 // EXT frag depth extensions if they have not been enabled.
7706 if (force_webgl_glsl_validation_
) {
7707 extensions
= feature_info_
->extensions();
7708 if (!derivatives_explicitly_enabled_
) {
7709 size_t offset
= extensions
.find(kOESDerivativeExtension
);
7710 if (std::string::npos
!= offset
) {
7711 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
7715 if (!frag_depth_explicitly_enabled_
) {
7716 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
7717 if (std::string::npos
!= offset
) {
7718 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
7722 if (!draw_buffers_explicitly_enabled_
) {
7723 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
7724 if (std::string::npos
!= offset
) {
7725 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
7729 if (!shader_texture_lod_explicitly_enabled_
) {
7730 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
7731 if (std::string::npos
!= offset
) {
7732 extensions
.replace(offset
,
7733 arraysize(kEXTShaderTextureLodExtension
),
7738 extensions
= feature_info_
->extensions().c_str();
7740 if (supports_post_sub_buffer_
)
7741 extensions
+= " GL_CHROMIUM_post_sub_buffer";
7742 str
= extensions
.c_str();
7748 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
7749 bucket
->SetFromString(str
);
7750 return error::kNoError
;
7753 error::Error
GLES2DecoderImpl::HandleBufferData(
7754 uint32 immediate_data_size
, const cmds::BufferData
& c
) {
7755 GLenum target
= static_cast<GLenum
>(c
.target
);
7756 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
7757 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
7758 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
7759 GLenum usage
= static_cast<GLenum
>(c
.usage
);
7760 const void* data
= NULL
;
7761 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
7762 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
7764 return error::kOutOfBounds
;
7767 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
7768 return error::kNoError
;
7771 void GLES2DecoderImpl::DoBufferSubData(
7772 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
7773 // Just delegate it. Some validation is actually done before this.
7774 buffer_manager()->ValidateAndDoBufferSubData(
7775 &state_
, target
, offset
, size
, data
);
7778 bool GLES2DecoderImpl::ClearLevel(
7779 unsigned service_id
,
7780 unsigned bind_target
,
7783 unsigned internal_format
,
7788 bool is_texture_immutable
) {
7789 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
7790 if (feature_info_
->feature_flags().angle_depth_texture
&&
7791 (channels
& GLES2Util::kDepth
) != 0) {
7792 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7793 // on depth formats.
7795 glGenFramebuffersEXT(1, &fb
);
7796 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
7798 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
7799 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
7800 GL_DEPTH_ATTACHMENT
;
7802 glFramebufferTexture2DEXT(
7803 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
7804 // ANGLE promises a depth only attachment ok.
7805 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
7806 GL_FRAMEBUFFER_COMPLETE
) {
7810 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, -1);
7811 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, -1);
7813 state_
.SetDeviceDepthMask(GL_TRUE
);
7814 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
7815 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
7817 RestoreClearState();
7819 glDeleteFramebuffersEXT(1, &fb
);
7820 Framebuffer
* framebuffer
=
7821 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
7822 GLuint fb_service_id
=
7823 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
7824 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
7828 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
7831 uint32 padded_row_size
;
7832 if (!GLES2Util::ComputeImageDataSizes(
7833 width
, height
, format
, type
, state_
.unpack_alignment
, &size
,
7834 NULL
, &padded_row_size
)) {
7838 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
7842 if (size
> kMaxZeroSize
) {
7843 if (kMaxZeroSize
< padded_row_size
) {
7844 // That'd be an awfully large texture.
7847 // We should never have a large total size with a zero row size.
7848 DCHECK_GT(padded_row_size
, 0U);
7849 tile_height
= kMaxZeroSize
/ padded_row_size
;
7850 if (!GLES2Util::ComputeImageDataSizes(
7851 width
, tile_height
, format
, type
, state_
.unpack_alignment
, &size
,
7856 tile_height
= height
;
7859 // Assumes the size has already been checked.
7860 scoped_ptr
<char[]> zero(new char[size
]);
7861 memset(zero
.get(), 0, size
);
7862 glBindTexture(bind_target
, service_id
);
7865 while (y
< height
) {
7866 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
7867 if (is_texture_immutable
|| h
!= height
) {
7868 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
7871 target
, level
, internal_format
, width
, h
, 0, format
, type
,
7876 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
7877 &state_
, bind_target
);
7878 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
7884 const int kS3TCBlockWidth
= 4;
7885 const int kS3TCBlockHeight
= 4;
7886 const int kS3TCDXT1BlockSize
= 8;
7887 const int kS3TCDXT3AndDXT5BlockSize
= 16;
7889 bool IsValidDXTSize(GLint level
, GLsizei size
) {
7890 return (size
== 1) ||
7891 (size
== 2) || !(size
% kS3TCBlockWidth
);
7894 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
7895 // Ensure that the size is a power of two
7896 return (size
& (size
- 1)) == 0;
7899 } // anonymous namespace.
7901 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7902 const char* function_name
,
7903 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
7904 unsigned int bytes_required
= 0;
7907 case GL_ATC_RGB_AMD
:
7908 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7909 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7910 case GL_ETC1_RGB8_OES
: {
7911 int num_blocks_across
=
7912 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7913 int num_blocks_down
=
7914 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7915 int num_blocks
= num_blocks_across
* num_blocks_down
;
7916 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
7919 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
7920 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
7921 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7922 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7923 int num_blocks_across
=
7924 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
7925 int num_blocks_down
=
7926 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
7927 int num_blocks
= num_blocks_across
* num_blocks_down
;
7928 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
7931 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
7932 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
7933 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
7936 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
7937 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
7938 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
7942 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
7946 if (size
!= bytes_required
) {
7948 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
7955 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7956 const char* function_name
,
7957 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
7959 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
7960 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
7961 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
7962 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
7963 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
7965 GL_INVALID_OPERATION
, function_name
,
7966 "width or height invalid for level");
7971 case GL_ATC_RGB_AMD
:
7972 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
7973 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
7974 case GL_ETC1_RGB8_OES
: {
7975 if (width
<= 0 || height
<= 0) {
7977 GL_INVALID_OPERATION
, function_name
,
7978 "width or height invalid for level");
7983 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
7984 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
7985 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
7986 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
7987 if (!IsValidPVRTCSize(level
, width
) ||
7988 !IsValidPVRTCSize(level
, height
)) {
7990 GL_INVALID_OPERATION
, function_name
,
7991 "width or height invalid for level");
8001 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8002 const char* function_name
,
8003 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8004 GLsizei width
, GLsizei height
, GLenum format
,
8006 if (xoffset
< 0 || yoffset
< 0) {
8008 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8013 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8014 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8015 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8016 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8017 const int kBlockWidth
= 4;
8018 const int kBlockHeight
= 4;
8019 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8021 GL_INVALID_OPERATION
, function_name
,
8022 "xoffset or yoffset not multiple of 4");
8025 GLsizei tex_width
= 0;
8026 GLsizei tex_height
= 0;
8027 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8028 width
- xoffset
> tex_width
||
8029 height
- yoffset
> tex_height
) {
8031 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8034 return ValidateCompressedTexDimensions(
8035 function_name
, level
, width
, height
, format
);
8037 case GL_ATC_RGB_AMD
:
8038 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8039 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8041 GL_INVALID_OPERATION
, function_name
,
8042 "not supported for ATC textures");
8045 case GL_ETC1_RGB8_OES
: {
8047 GL_INVALID_OPERATION
, function_name
,
8048 "not supported for ECT1_RGB8_OES textures");
8051 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8052 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8053 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8054 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8055 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8057 GL_INVALID_OPERATION
, function_name
,
8058 "xoffset and yoffset must be zero");
8061 GLsizei tex_width
= 0;
8062 GLsizei tex_height
= 0;
8063 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8064 width
!= tex_width
||
8065 height
!= tex_height
) {
8067 GL_INVALID_OPERATION
, function_name
,
8068 "dimensions must match existing texture level dimensions");
8071 return ValidateCompressedTexDimensions(
8072 function_name
, level
, width
, height
, format
);
8079 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8082 GLenum internal_format
,
8088 // TODO(gman): Validate image_size is correct for width, height and format.
8089 if (!validators_
->texture_target
.IsValid(target
)) {
8090 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8091 "glCompressedTexImage2D", target
, "target");
8092 return error::kNoError
;
8094 if (!validators_
->compressed_texture_format
.IsValid(
8096 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8097 "glCompressedTexImage2D", internal_format
, "internal_format");
8098 return error::kNoError
;
8100 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8104 "glCompressedTexImage2D", "dimensions out of range");
8105 return error::kNoError
;
8107 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8112 "glCompressedTexImage2D", "unknown texture target");
8113 return error::kNoError
;
8115 Texture
* texture
= texture_ref
->texture();
8116 if (texture
->IsImmutable()) {
8118 GL_INVALID_OPERATION
,
8119 "glCompressedTexImage2D", "texture is immutable");
8120 return error::kNoError
;
8123 if (!ValidateCompressedTexDimensions(
8124 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8125 !ValidateCompressedTexFuncData(
8126 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8127 return error::kNoError
;
8130 if (!EnsureGPUMemoryAvailable(image_size
)) {
8132 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8133 return error::kNoError
;
8136 if (texture
->IsAttachedToFramebuffer()) {
8137 framebuffer_state_
.clear_state_dirty
= true;
8140 scoped_ptr
<int8
[]> zero
;
8142 zero
.reset(new int8
[image_size
]);
8143 memset(zero
.get(), 0, image_size
);
8146 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8147 glCompressedTexImage2D(
8148 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8149 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8150 if (error
== GL_NO_ERROR
) {
8151 texture_manager()->SetLevelInfo(
8152 texture_ref
, target
, level
, internal_format
,
8153 width
, height
, 1, border
, 0, 0, true);
8155 return error::kNoError
;
8158 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8159 uint32 immediate_data_size
, const cmds::CompressedTexImage2D
& c
) {
8160 GLenum target
= static_cast<GLenum
>(c
.target
);
8161 GLint level
= static_cast<GLint
>(c
.level
);
8162 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8163 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8164 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8165 GLint border
= static_cast<GLint
>(c
.border
);
8166 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8167 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8168 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8169 const void* data
= NULL
;
8170 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8171 data
= GetSharedMemoryAs
<const void*>(
8172 data_shm_id
, data_shm_offset
, image_size
);
8174 return error::kOutOfBounds
;
8177 return DoCompressedTexImage2D(
8178 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8181 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8182 uint32 immediate_data_size
, const cmds::CompressedTexImage2DBucket
& c
) {
8183 GLenum target
= static_cast<GLenum
>(c
.target
);
8184 GLint level
= static_cast<GLint
>(c
.level
);
8185 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8186 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8187 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8188 GLint border
= static_cast<GLint
>(c
.border
);
8189 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8191 return error::kInvalidArguments
;
8193 uint32 data_size
= bucket
->size();
8194 GLsizei imageSize
= data_size
;
8195 const void* data
= bucket
->GetData(0, data_size
);
8197 return error::kInvalidArguments
;
8199 return DoCompressedTexImage2D(
8200 target
, level
, internal_format
, width
, height
, border
,
8204 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8205 uint32 immediate_data_size
,
8206 const cmds::CompressedTexSubImage2DBucket
& c
) {
8207 GLenum target
= static_cast<GLenum
>(c
.target
);
8208 GLint level
= static_cast<GLint
>(c
.level
);
8209 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8210 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8211 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8212 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8213 GLenum format
= static_cast<GLenum
>(c
.format
);
8214 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8216 return error::kInvalidArguments
;
8218 uint32 data_size
= bucket
->size();
8219 GLsizei imageSize
= data_size
;
8220 const void* data
= bucket
->GetData(0, data_size
);
8222 return error::kInvalidArguments
;
8224 if (!validators_
->texture_target
.IsValid(target
)) {
8226 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8227 return error::kNoError
;
8229 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8230 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8231 "glCompressedTexSubImage2D", format
, "format");
8232 return error::kNoError
;
8236 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8237 return error::kNoError
;
8241 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8242 return error::kNoError
;
8244 if (imageSize
< 0) {
8246 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8247 return error::kNoError
;
8249 DoCompressedTexSubImage2D(
8250 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8251 return error::kNoError
;
8254 error::Error
GLES2DecoderImpl::HandleTexImage2D(
8255 uint32 immediate_data_size
, const cmds::TexImage2D
& c
) {
8256 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8257 "width", c
.width
, "height", c
.height
);
8258 // Set as failed for now, but if it successed, this will be set to not failed.
8259 texture_state_
.tex_image_2d_failed
= true;
8260 GLenum target
= static_cast<GLenum
>(c
.target
);
8261 GLint level
= static_cast<GLint
>(c
.level
);
8262 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8263 // for internalformat.
8264 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8265 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8266 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8267 GLint border
= static_cast<GLint
>(c
.border
);
8268 GLenum format
= static_cast<GLenum
>(c
.format
);
8269 GLenum type
= static_cast<GLenum
>(c
.type
);
8270 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8271 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8273 if (!GLES2Util::ComputeImageDataSizes(
8274 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
8276 return error::kOutOfBounds
;
8278 const void* pixels
= NULL
;
8279 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8280 pixels
= GetSharedMemoryAs
<const void*>(
8281 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8283 return error::kOutOfBounds
;
8287 TextureManager::DoTextImage2DArguments args
= {
8288 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8289 pixels
, pixels_size
};
8290 texture_manager()->ValidateAndDoTexImage2D(
8291 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8292 return error::kNoError
;
8295 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8304 const void * data
) {
8305 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8309 GL_INVALID_OPERATION
,
8310 "glCompressedTexSubImage2D", "unknown texture for target");
8313 Texture
* texture
= texture_ref
->texture();
8315 GLenum internal_format
= 0;
8316 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
8318 GL_INVALID_OPERATION
,
8319 "glCompressedTexSubImage2D", "level does not exist.");
8322 if (internal_format
!= format
) {
8324 GL_INVALID_OPERATION
,
8325 "glCompressedTexSubImage2D", "format does not match internal format.");
8328 if (!texture
->ValidForTexture(
8329 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8331 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8335 if (!ValidateCompressedTexFuncData(
8336 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8337 !ValidateCompressedTexSubDimensions(
8338 "glCompressedTexSubImage2D",
8339 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8344 // Note: There is no need to deal with texture cleared tracking here
8345 // because the validation above means you can only get here if the level
8346 // is already a matching compressed format and in that case
8347 // CompressedTexImage2D already cleared the texture.
8348 glCompressedTexSubImage2D(
8349 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8353 GLint start
, GLint range
, GLint sourceRange
,
8354 GLint
* out_start
, GLint
* out_range
) {
8361 GLint end
= start
+ range
;
8362 if (end
> sourceRange
) {
8363 range
-= end
- sourceRange
;
8369 void GLES2DecoderImpl::DoCopyTexImage2D(
8372 GLenum internal_format
,
8378 DCHECK(!ShouldDeferReads());
8379 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8383 GL_INVALID_OPERATION
,
8384 "glCopyTexImage2D", "unknown texture for target");
8387 Texture
* texture
= texture_ref
->texture();
8388 if (texture
->IsImmutable()) {
8390 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8393 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8396 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8399 if (!texture_manager()->ValidateFormatAndTypeCombination(
8400 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
8401 GL_UNSIGNED_BYTE
)) {
8405 // Check we have compatible formats.
8406 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8407 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8408 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
8410 if ((channels_needed
& channels_exist
) != channels_needed
) {
8412 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
8416 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8418 GL_INVALID_OPERATION
,
8419 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8423 uint32 estimated_size
= 0;
8424 if (!GLES2Util::ComputeImageDataSizes(
8425 width
, height
, internal_format
, GL_UNSIGNED_BYTE
, state_
.unpack_alignment
,
8426 &estimated_size
, NULL
, NULL
)) {
8428 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
8432 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
8433 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
8437 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8441 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8442 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8443 gfx::Size size
= GetBoundReadFrameBufferSize();
8445 if (texture
->IsAttachedToFramebuffer()) {
8446 framebuffer_state_
.clear_state_dirty
= true;
8449 // Clip to size to source dimensions
8452 GLint copyWidth
= 0;
8453 GLint copyHeight
= 0;
8454 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8455 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8459 copyWidth
!= width
||
8460 copyHeight
!= height
) {
8461 // some part was clipped so clear the texture.
8463 texture
->service_id(), texture
->target(),
8464 target
, level
, internal_format
, internal_format
, GL_UNSIGNED_BYTE
,
8465 width
, height
, texture
->IsImmutable())) {
8467 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
8470 if (copyHeight
> 0 && copyWidth
> 0) {
8471 GLint dx
= copyX
- x
;
8472 GLint dy
= copyY
- y
;
8475 ScopedModifyPixels
modify(texture_ref
);
8476 glCopyTexSubImage2D(target
, level
,
8477 destX
, destY
, copyX
, copyY
,
8478 copyWidth
, copyHeight
);
8481 ScopedModifyPixels
modify(texture_ref
);
8482 glCopyTexImage2D(target
, level
, internal_format
,
8483 copyX
, copyY
, copyWidth
, copyHeight
, border
);
8485 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8486 if (error
== GL_NO_ERROR
) {
8487 texture_manager()->SetLevelInfo(
8488 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
8489 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
8493 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8502 DCHECK(!ShouldDeferReads());
8503 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8507 GL_INVALID_OPERATION
,
8508 "glCopyTexSubImage2D", "unknown texture for target");
8511 Texture
* texture
= texture_ref
->texture();
8514 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
8515 !texture
->ValidForTexture(
8516 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8518 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
8521 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8523 GL_INVALID_OPERATION
,
8524 "glCopyTexSubImage2D", "async upload pending for texture");
8528 // Check we have compatible formats.
8529 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8530 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8531 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
8533 if (!channels_needed
||
8534 (channels_needed
& channels_exist
) != channels_needed
) {
8536 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
8540 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8542 GL_INVALID_OPERATION
,
8543 "glCopySubImage2D", "can not be used with depth or stencil textures");
8547 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8551 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8552 gfx::Size size
= GetBoundReadFrameBufferSize();
8555 GLint copyWidth
= 0;
8556 GLint copyHeight
= 0;
8557 Clip(x
, width
, size
.width(), ©X
, ©Width
);
8558 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
8560 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, level
)) {
8562 GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D", "dimensions too big");
8568 copyWidth
!= width
||
8569 copyHeight
!= height
) {
8570 // some part was clipped so clear the sub rect.
8571 uint32 pixels_size
= 0;
8572 if (!GLES2Util::ComputeImageDataSizes(
8573 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8576 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
8579 scoped_ptr
<char[]> zero(new char[pixels_size
]);
8580 memset(zero
.get(), 0, pixels_size
);
8581 ScopedModifyPixels
modify(texture_ref
);
8583 target
, level
, xoffset
, yoffset
, width
, height
,
8584 format
, type
, zero
.get());
8587 if (copyHeight
> 0 && copyWidth
> 0) {
8588 GLint dx
= copyX
- x
;
8589 GLint dy
= copyY
- y
;
8590 GLint destX
= xoffset
+ dx
;
8591 GLint destY
= yoffset
+ dy
;
8592 ScopedModifyPixels
modify(texture_ref
);
8593 glCopyTexSubImage2D(target
, level
,
8594 destX
, destY
, copyX
, copyY
,
8595 copyWidth
, copyHeight
);
8599 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8600 error::Error
* error
,
8601 const char* function_name
,
8610 const void * data
) {
8611 (*error
) = error::kNoError
;
8612 if (!validators_
->texture_target
.IsValid(target
)) {
8613 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
8617 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
8621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
8624 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8628 GL_INVALID_OPERATION
,
8629 function_name
, "unknown texture for target");
8632 Texture
* texture
= texture_ref
->texture();
8633 GLenum current_type
= 0;
8634 GLenum internal_format
= 0;
8635 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
8637 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
8640 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
8641 function_name
, format
, type
, internal_format
, level
)) {
8644 if (type
!= current_type
) {
8646 GL_INVALID_OPERATION
,
8647 function_name
, "type does not match type of texture.");
8650 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
8652 GL_INVALID_OPERATION
,
8653 function_name
, "async upload pending for texture");
8656 if (!texture
->ValidForTexture(
8657 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8658 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
8661 if ((GLES2Util::GetChannelsForFormat(format
) &
8662 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
8664 GL_INVALID_OPERATION
,
8665 function_name
, "can not supply data for depth or stencil textures");
8669 (*error
) = error::kOutOfBounds
;
8675 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
8684 const void * data
) {
8685 error::Error error
= error::kNoError
;
8686 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
8687 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
8690 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8692 Texture
* texture
= texture_ref
->texture();
8693 GLsizei tex_width
= 0;
8694 GLsizei tex_height
= 0;
8695 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
8697 if (xoffset
!= 0 || yoffset
!= 0 ||
8698 width
!= tex_width
|| height
!= tex_height
) {
8699 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
8702 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
8703 return error::kNoError
;
8705 ScopedTextureUploadTimer
timer(&texture_state_
);
8707 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8708 return error::kNoError
;
8711 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
8712 !texture
->IsImmutable()) {
8713 ScopedTextureUploadTimer
timer(&texture_state_
);
8714 GLenum internal_format
;
8716 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
8717 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8720 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
8722 ScopedTextureUploadTimer
timer(&texture_state_
);
8724 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
8726 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
8727 return error::kNoError
;
8730 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(
8731 uint32 immediate_data_size
, const cmds::TexSubImage2D
& c
) {
8732 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8733 "width", c
.width
, "height", c
.height
);
8734 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
8735 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
8736 return error::kNoError
;
8738 GLenum target
= static_cast<GLenum
>(c
.target
);
8739 GLint level
= static_cast<GLint
>(c
.level
);
8740 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8741 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8742 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8743 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8744 GLenum format
= static_cast<GLenum
>(c
.format
);
8745 GLenum type
= static_cast<GLenum
>(c
.type
);
8747 if (!GLES2Util::ComputeImageDataSizes(
8748 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
8750 return error::kOutOfBounds
;
8752 const void* pixels
= GetSharedMemoryAs
<const void*>(
8753 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
8754 return DoTexSubImage2D(
8755 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
8758 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8759 uint32 immediate_data_size
, const cmds::GetVertexAttribPointerv
& c
) {
8760 GLuint index
= static_cast<GLuint
>(c
.index
);
8761 GLenum pname
= static_cast<GLenum
>(c
.pname
);
8762 typedef cmds::GetVertexAttribPointerv::Result Result
;
8763 Result
* result
= GetSharedMemoryAs
<Result
*>(
8764 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
8766 return error::kOutOfBounds
;
8768 // Check that the client initialized the result.
8769 if (result
->size
!= 0) {
8770 return error::kInvalidArguments
;
8772 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
8773 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8774 "glGetVertexAttribPointerv", pname
, "pname");
8775 return error::kNoError
;
8777 if (index
>= group_
->max_vertex_attribs()) {
8779 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
8780 return error::kNoError
;
8782 result
->SetNumResults(1);
8783 *result
->GetData() =
8784 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
8785 return error::kNoError
;
8788 bool GLES2DecoderImpl::GetUniformSetup(
8789 GLuint program_id
, GLint fake_location
,
8790 uint32 shm_id
, uint32 shm_offset
,
8791 error::Error
* error
, GLint
* real_location
,
8792 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
8795 DCHECK(result_pointer
);
8796 DCHECK(result_type
);
8797 DCHECK(real_location
);
8798 *error
= error::kNoError
;
8799 // Make sure we have enough room for the result on failure.
8800 SizedResult
<GLint
>* result
;
8801 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8802 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
8804 *error
= error::kOutOfBounds
;
8807 *result_pointer
= result
;
8808 // Set the result size to 0 so the client does not have to check for success.
8809 result
->SetNumResults(0);
8810 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
8814 if (!program
->IsValid()) {
8815 // Program was not linked successfully. (ie, glLinkProgram)
8817 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
8820 *service_id
= program
->service_id();
8821 GLint array_index
= -1;
8822 const Program::UniformInfo
* uniform_info
=
8823 program
->GetUniformInfoByFakeLocation(
8824 fake_location
, real_location
, &array_index
);
8825 if (!uniform_info
) {
8826 // No such location.
8828 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
8831 GLenum type
= uniform_info
->type
;
8832 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
8834 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
8837 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
8838 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
8840 *error
= error::kOutOfBounds
;
8843 result
->size
= size
;
8844 *result_type
= type
;
8848 error::Error
GLES2DecoderImpl::HandleGetUniformiv(
8849 uint32 immediate_data_size
, const cmds::GetUniformiv
& c
) {
8850 GLuint program
= c
.program
;
8851 GLint fake_location
= c
.location
;
8854 GLint real_location
= -1;
8857 if (GetUniformSetup(
8858 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8859 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
8861 service_id
, real_location
,
8862 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
8867 error::Error
GLES2DecoderImpl::HandleGetUniformfv(
8868 uint32 immediate_data_size
, const cmds::GetUniformfv
& c
) {
8869 GLuint program
= c
.program
;
8870 GLint fake_location
= c
.location
;
8872 GLint real_location
= -1;
8874 typedef cmds::GetUniformfv::Result Result
;
8877 if (GetUniformSetup(
8878 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
8879 &error
, &real_location
, &service_id
,
8880 reinterpret_cast<void**>(&result
), &result_type
)) {
8881 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
8882 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
8883 GLsizei num_values
= result
->GetNumResults();
8884 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
8885 glGetUniformiv(service_id
, real_location
, temp
.get());
8886 GLfloat
* dst
= result
->GetData();
8887 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
8888 dst
[ii
] = (temp
[ii
] != 0);
8891 glGetUniformfv(service_id
, real_location
, result
->GetData());
8897 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8898 uint32 immediate_data_size
, const cmds::GetShaderPrecisionFormat
& c
) {
8899 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
8900 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
8901 typedef cmds::GetShaderPrecisionFormat::Result Result
;
8902 Result
* result
= GetSharedMemoryAs
<Result
*>(
8903 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8905 return error::kOutOfBounds
;
8907 // Check that the client initialized the result.
8908 if (result
->success
!= 0) {
8909 return error::kInvalidArguments
;
8911 if (!validators_
->shader_type
.IsValid(shader_type
)) {
8912 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8913 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
8914 return error::kNoError
;
8916 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
8917 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8918 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
8919 return error::kNoError
;
8922 result
->success
= 1; // true
8924 GLint range
[2] = { 0, 0 };
8925 GLint precision
= 0;
8926 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
8928 result
->min_range
= range
[0];
8929 result
->max_range
= range
[1];
8930 result
->precision
= precision
;
8932 return error::kNoError
;
8935 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
8936 uint32 immediate_data_size
, const cmds::GetAttachedShaders
& c
) {
8937 uint32 result_size
= c
.result_size
;
8938 GLuint program_id
= static_cast<GLuint
>(c
.program
);
8939 Program
* program
= GetProgramInfoNotShader(
8940 program_id
, "glGetAttachedShaders");
8942 return error::kNoError
;
8944 typedef cmds::GetAttachedShaders::Result Result
;
8945 uint32 max_count
= Result::ComputeMaxResults(result_size
);
8946 Result
* result
= GetSharedMemoryAs
<Result
*>(
8947 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
8949 return error::kOutOfBounds
;
8951 // Check that the client initialized the result.
8952 if (result
->size
!= 0) {
8953 return error::kInvalidArguments
;
8956 glGetAttachedShaders(
8957 program
->service_id(), max_count
, &count
, result
->GetData());
8958 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
8959 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
8960 &result
->GetData()[ii
])) {
8962 return error::kGenericError
;
8965 result
->SetNumResults(count
);
8966 return error::kNoError
;
8969 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
8970 uint32 immediate_data_size
, const cmds::GetActiveUniform
& c
) {
8971 GLuint program_id
= c
.program
;
8972 GLuint index
= c
.index
;
8973 uint32 name_bucket_id
= c
.name_bucket_id
;
8974 typedef cmds::GetActiveUniform::Result Result
;
8975 Result
* result
= GetSharedMemoryAs
<Result
*>(
8976 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8978 return error::kOutOfBounds
;
8980 // Check that the client initialized the result.
8981 if (result
->success
!= 0) {
8982 return error::kInvalidArguments
;
8984 Program
* program
= GetProgramInfoNotShader(
8985 program_id
, "glGetActiveUniform");
8987 return error::kNoError
;
8989 const Program::UniformInfo
* uniform_info
=
8990 program
->GetUniformInfo(index
);
8991 if (!uniform_info
) {
8993 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
8994 return error::kNoError
;
8996 result
->success
= 1; // true.
8997 result
->size
= uniform_info
->size
;
8998 result
->type
= uniform_info
->type
;
8999 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9000 bucket
->SetFromString(uniform_info
->name
.c_str());
9001 return error::kNoError
;
9004 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(
9005 uint32 immediate_data_size
, const cmds::GetActiveAttrib
& c
) {
9006 GLuint program_id
= c
.program
;
9007 GLuint index
= c
.index
;
9008 uint32 name_bucket_id
= c
.name_bucket_id
;
9009 typedef cmds::GetActiveAttrib::Result Result
;
9010 Result
* result
= GetSharedMemoryAs
<Result
*>(
9011 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9013 return error::kOutOfBounds
;
9015 // Check that the client initialized the result.
9016 if (result
->success
!= 0) {
9017 return error::kInvalidArguments
;
9019 Program
* program
= GetProgramInfoNotShader(
9020 program_id
, "glGetActiveAttrib");
9022 return error::kNoError
;
9024 const Program::VertexAttrib
* attrib_info
=
9025 program
->GetAttribInfo(index
);
9028 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9029 return error::kNoError
;
9031 result
->success
= 1; // true.
9032 result
->size
= attrib_info
->size
;
9033 result
->type
= attrib_info
->type
;
9034 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9035 bucket
->SetFromString(attrib_info
->name
.c_str());
9036 return error::kNoError
;
9039 error::Error
GLES2DecoderImpl::HandleShaderBinary(
9040 uint32 immediate_data_size
, const cmds::ShaderBinary
& c
) {
9041 #if 1 // No binary shader support.
9042 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
9043 return error::kNoError
;
9045 GLsizei n
= static_cast<GLsizei
>(c
.n
);
9047 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
9048 return error::kNoError
;
9050 GLsizei length
= static_cast<GLsizei
>(c
.length
);
9052 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
9053 return error::kNoError
;
9056 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
9057 return error::kOutOfBounds
;
9059 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
9060 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
9061 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
9062 const void* binary
= GetSharedMemoryAs
<const void*>(
9063 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
9064 if (shaders
== NULL
|| binary
== NULL
) {
9065 return error::kOutOfBounds
;
9067 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9068 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9069 Shader
* shader
= GetShader(shaders
[ii
]);
9071 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
9072 return error::kNoError
;
9074 service_ids
[ii
] = shader
->service_id();
9076 // TODO(gman): call glShaderBinary
9077 return error::kNoError
;
9081 void GLES2DecoderImpl::DoSwapBuffers() {
9082 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9084 int this_frame_number
= frame_number_
++;
9085 // TRACE_EVENT for gpu tests:
9086 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9087 TRACE_EVENT_SCOPE_THREAD
,
9088 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9089 "width", (is_offscreen
? offscreen_size_
.width() :
9090 surface_
->GetSize().width()));
9091 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9092 "offscreen", is_offscreen
,
9093 "frame", this_frame_number
);
9095 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9099 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9102 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9103 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9104 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9107 // If offscreen then don't actually SwapBuffers to the display. Just copy
9108 // the rendered frame to another frame buffer.
9110 TRACE_EVENT2("gpu", "Offscreen",
9111 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
9112 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
9113 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9114 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9116 if (workarounds().needs_offscreen_buffer_workaround
) {
9117 offscreen_saved_frame_buffer_
->Create();
9121 // Allocate the offscreen saved color texture.
9122 DCHECK(offscreen_saved_color_format_
);
9123 offscreen_saved_color_texture_
->AllocateStorage(
9124 offscreen_size_
, offscreen_saved_color_format_
, false);
9126 offscreen_saved_frame_buffer_
->AttachRenderTexture(
9127 offscreen_saved_color_texture_
.get());
9128 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
9129 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
9130 GL_FRAMEBUFFER_COMPLETE
) {
9131 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9132 << "because offscreen saved FBO was incomplete.";
9133 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9137 // Clear the offscreen color texture.
9138 // TODO(piman): Is this still necessary?
9140 ScopedFrameBufferBinder
binder(this,
9141 offscreen_saved_frame_buffer_
->id());
9142 glClearColor(0, 0, 0, 0);
9143 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
9144 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
9145 glClear(GL_COLOR_BUFFER_BIT
);
9146 RestoreClearState();
9150 UpdateParentTextureInfo();
9153 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
9155 ScopedGLErrorSuppressor
suppressor(
9156 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9158 if (IsOffscreenBufferMultisampled()) {
9159 // For multisampled buffers, resolve the frame buffer.
9160 ScopedResolvedFrameBufferBinder
binder(this, true, false);
9162 ScopedFrameBufferBinder
binder(this,
9163 offscreen_target_frame_buffer_
->id());
9165 if (offscreen_target_buffer_preserved_
) {
9166 // Copy the target frame buffer to the saved offscreen texture.
9167 offscreen_saved_color_texture_
->Copy(
9168 offscreen_saved_color_texture_
->size(),
9169 offscreen_saved_color_format_
);
9171 // Flip the textures in the parent context via the texture manager.
9172 if (!!offscreen_saved_color_texture_info_
.get())
9173 offscreen_saved_color_texture_info_
->texture()->
9174 SetServiceId(offscreen_target_color_texture_
->id());
9176 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
9177 offscreen_target_frame_buffer_
->AttachRenderTexture(
9178 offscreen_target_color_texture_
.get());
9181 // Ensure the side effects of the copy are visible to the parent
9182 // context. There is no need to do this for ANGLE because it uses a
9183 // single D3D device for all contexts.
9184 if (!feature_info_
->feature_flags().is_angle
)
9188 if (!surface_
->SwapBuffers()) {
9189 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
9190 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9195 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9196 uint32 immediate_data_size
, const cmds::EnableFeatureCHROMIUM
& c
) {
9197 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9198 if (!bucket
|| bucket
->size() == 0) {
9199 return error::kInvalidArguments
;
9201 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
9202 Result
* result
= GetSharedMemoryAs
<Result
*>(
9203 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9205 return error::kOutOfBounds
;
9207 // Check that the client initialized the result.
9209 return error::kInvalidArguments
;
9211 std::string feature_str
;
9212 if (!bucket
->GetAsString(&feature_str
)) {
9213 return error::kInvalidArguments
;
9216 // TODO(gman): make this some kind of table to function pointer thingy.
9217 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9218 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9219 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
9220 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9221 // TODO(gman): decide how to remove the need for this const_cast.
9222 // I could make validators_ non const but that seems bad as this is the only
9223 // place it is needed. I could make some special friend class of validators
9224 // just to allow this to set them. That seems silly. I could refactor this
9225 // code to use the extension mechanism or the initialization attributes to
9226 // turn this feature on. Given that the only real point of this is to make
9227 // the conformance tests pass and given that there is lots of real work that
9228 // needs to be done it seems like refactoring for one to one of those
9229 // methods is a very low priority.
9230 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
9231 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
9232 force_webgl_glsl_validation_
= true;
9233 InitializeShaderTranslator();
9235 return error::kNoError
;
9238 *result
= 1; // true.
9239 return error::kNoError
;
9242 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9243 uint32 immediate_data_size
,
9244 const cmds::GetRequestableExtensionsCHROMIUM
& c
) {
9245 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9246 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
9247 info
->Initialize(disallowed_features_
);
9248 bucket
->SetFromString(info
->extensions().c_str());
9249 return error::kNoError
;
9252 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9253 uint32 immediate_data_size
, const cmds::RequestExtensionCHROMIUM
& c
) {
9254 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9255 if (!bucket
|| bucket
->size() == 0) {
9256 return error::kInvalidArguments
;
9258 std::string feature_str
;
9259 if (!bucket
->GetAsString(&feature_str
)) {
9260 return error::kInvalidArguments
;
9263 bool desire_webgl_glsl_validation
=
9264 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
9265 bool desire_standard_derivatives
= false;
9266 bool desire_frag_depth
= false;
9267 bool desire_draw_buffers
= false;
9268 bool desire_shader_texture_lod
= false;
9269 if (force_webgl_glsl_validation_
) {
9270 desire_standard_derivatives
=
9271 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
9273 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
9274 desire_draw_buffers
=
9275 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
9276 desire_shader_texture_lod
=
9277 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
9280 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
9281 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
9282 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
9283 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
9284 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
9285 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
9286 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
9287 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
9288 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
9289 InitializeShaderTranslator();
9292 UpdateCapabilities();
9294 return error::kNoError
;
9297 error::Error
GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9298 uint32 immediate_data_size
, const cmds::GetMultipleIntegervCHROMIUM
& c
) {
9299 GLuint count
= c
.count
;
9301 if (!SafeMultiplyUint32(count
, sizeof(GLenum
), &pnames_size
)) {
9302 return error::kOutOfBounds
;
9304 const GLenum
* pnames
= GetSharedMemoryAs
<const GLenum
*>(
9305 c
.pnames_shm_id
, c
.pnames_shm_offset
, pnames_size
);
9306 if (pnames
== NULL
) {
9307 return error::kOutOfBounds
;
9310 // We have to copy them since we use them twice so the client
9311 // can't change them between the time we validate them and the time we use
9313 scoped_ptr
<GLenum
[]> enums(new GLenum
[count
]);
9314 memcpy(enums
.get(), pnames
, pnames_size
);
9316 // Count up the space needed for the result.
9317 uint32 num_results
= 0;
9318 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9319 uint32 num
= util_
.GLGetNumValuesReturned(enums
[ii
]);
9321 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9322 "glGetMultipleCHROMIUM", enums
[ii
], "pname");
9323 return error::kNoError
;
9325 // Num will never be more than 4.
9327 if (!SafeAddUint32(num_results
, num
, &num_results
)) {
9328 return error::kOutOfBounds
;
9332 uint32 result_size
= 0;
9333 if (!SafeMultiplyUint32(num_results
, sizeof(GLint
), &result_size
)) {
9334 return error::kOutOfBounds
;
9337 if (result_size
!= static_cast<uint32
>(c
.size
)) {
9340 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9341 return error::kNoError
;
9344 GLint
* results
= GetSharedMemoryAs
<GLint
*>(
9345 c
.results_shm_id
, c
.results_shm_offset
, result_size
);
9346 if (results
== NULL
) {
9347 return error::kOutOfBounds
;
9350 // Check the results have been cleared in case the context was lost.
9351 for (uint32 ii
= 0; ii
< num_results
; ++ii
) {
9353 return error::kInvalidArguments
;
9358 GLint
* start
= results
;
9359 for (GLuint ii
= 0; ii
< count
; ++ii
) {
9360 GLsizei num_written
= 0;
9361 if (!state_
.GetStateAsGLint(enums
[ii
], results
, &num_written
) &&
9362 !GetHelper(enums
[ii
], results
, &num_written
)) {
9363 DoGetIntegerv(enums
[ii
], results
);
9365 results
+= num_written
;
9368 // Just to verify. Should this be a DCHECK?
9369 if (static_cast<uint32
>(results
- start
) != num_results
) {
9370 return error::kOutOfBounds
;
9373 return error::kNoError
;
9376 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9377 uint32 immediate_data_size
, const cmds::GetProgramInfoCHROMIUM
& c
) {
9378 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9379 uint32 bucket_id
= c
.bucket_id
;
9380 Bucket
* bucket
= CreateBucket(bucket_id
);
9381 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
9382 Program
* program
= NULL
;
9383 program
= GetProgram(program_id
);
9384 if (!program
|| !program
->IsValid()) {
9385 return error::kNoError
;
9387 program
->GetProgramInfo(program_manager(), bucket
);
9388 return error::kNoError
;
9391 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
9392 switch (reset_status_
) {
9394 // TODO(kbr): improve the precision of the error code in this case.
9395 // Consider delegating to context for error code if MakeCurrent fails.
9396 return error::kUnknown
;
9397 case GL_GUILTY_CONTEXT_RESET_ARB
:
9398 return error::kGuilty
;
9399 case GL_INNOCENT_CONTEXT_RESET_ARB
:
9400 return error::kInnocent
;
9401 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
9402 return error::kUnknown
;
9406 return error::kUnknown
;
9409 bool GLES2DecoderImpl::WasContextLost() {
9410 if (reset_status_
!= GL_NO_ERROR
) {
9413 if (context_
->WasAllocatedUsingRobustnessExtension()) {
9414 GLenum status
= GL_NO_ERROR
;
9415 if (has_robustness_extension_
)
9416 status
= glGetGraphicsResetStatusARB();
9417 if (status
!= GL_NO_ERROR
) {
9418 // The graphics card was reset. Signal a lost context to the application.
9419 reset_status_
= status
;
9420 reset_by_robustness_extension_
= true;
9421 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
9422 << " context lost via ARB/EXT_robustness. Reset status = "
9423 << GLES2Util::GetStringEnum(status
);
9430 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9431 return WasContextLost() && reset_by_robustness_extension_
;
9434 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
9435 // Only loses the context once.
9436 if (reset_status_
!= GL_NO_ERROR
) {
9440 // Marks this context as lost.
9441 reset_status_
= reset_status
;
9442 current_decoder_error_
= error::kLostContext
;
9445 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9446 uint32 immediate_data_size
, const cmds::InsertSyncPointCHROMIUM
& c
) {
9447 return error::kUnknownCommand
;
9450 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9451 uint32 immediate_data_size
, const cmds::WaitSyncPointCHROMIUM
& c
) {
9452 group_
->mailbox_manager()->PullTextureUpdates();
9453 if (wait_sync_point_callback_
.is_null())
9454 return error::kNoError
;
9456 return wait_sync_point_callback_
.Run(c
.sync_point
) ?
9457 error::kNoError
: error::kDeferCommandUntilLater
;
9460 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9461 uint32 immediate_data_size
, const cmds::DiscardBackbufferCHROMIUM
& c
) {
9462 if (surface_
->DeferDraws())
9463 return error::kDeferCommandUntilLater
;
9464 if (!surface_
->SetBackbufferAllocation(false))
9465 return error::kLostContext
;
9466 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
9467 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
9468 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
9469 return error::kNoError
;
9472 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9473 GLsizei n
, const GLuint
* client_ids
) {
9474 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9475 if (query_manager_
->GetQuery(client_ids
[ii
])) {
9479 query_manager_
->GenQueries(n
, client_ids
);
9483 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9484 GLsizei n
, const GLuint
* client_ids
) {
9485 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9486 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
9487 if (query
&& !query
->IsDeleted()) {
9488 ContextState::QueryMap::iterator it
=
9489 state_
.current_queries
.find(query
->target());
9490 if (it
!= state_
.current_queries
.end())
9491 state_
.current_queries
.erase(it
);
9493 query
->Destroy(true);
9495 query_manager_
->RemoveQuery(client_ids
[ii
]);
9499 bool GLES2DecoderImpl::ProcessPendingQueries() {
9500 if (query_manager_
.get() == NULL
) {
9503 if (!query_manager_
->ProcessPendingQueries()) {
9504 current_decoder_error_
= error::kOutOfBounds
;
9506 return query_manager_
->HavePendingQueries();
9509 // Note that if there are no pending readpixels right now,
9510 // this function will call the callback immediately.
9511 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
9512 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
9513 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
9519 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9520 while (!pending_readpixel_fences_
.empty() &&
9521 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
9522 std::vector
<base::Closure
> callbacks
=
9523 pending_readpixel_fences_
.front()->callbacks
;
9524 pending_readpixel_fences_
.pop();
9525 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
9531 bool GLES2DecoderImpl::HasMoreIdleWork() {
9532 return !pending_readpixel_fences_
.empty() ||
9533 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
9536 void GLES2DecoderImpl::PerformIdleWork() {
9537 ProcessPendingReadPixels();
9538 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
9540 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
9541 ProcessFinishedAsyncTransfers();
9544 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(
9545 uint32 immediate_data_size
, const cmds::BeginQueryEXT
& c
) {
9546 GLenum target
= static_cast<GLenum
>(c
.target
);
9547 GLuint client_id
= static_cast<GLuint
>(c
.id
);
9548 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
9549 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
9552 case GL_COMMANDS_ISSUED_CHROMIUM
:
9553 case GL_LATENCY_QUERY_CHROMIUM
:
9554 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
9555 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
9556 case GL_GET_ERROR_QUERY_CHROMIUM
:
9558 case GL_COMMANDS_COMPLETED_CHROMIUM
:
9559 if (!features().chromium_sync_query
) {
9561 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9562 "not enabled for commands completed queries");
9563 return error::kNoError
;
9567 if (!features().occlusion_query_boolean
) {
9569 GL_INVALID_OPERATION
, "glBeginQueryEXT",
9570 "not enabled for occlusion queries");
9571 return error::kNoError
;
9576 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
9578 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
9579 return error::kNoError
;
9582 if (client_id
== 0) {
9583 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
9584 return error::kNoError
;
9587 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
9589 if (!query_manager_
->IsValidQuery(client_id
)) {
9590 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9592 "id not made by glGenQueriesEXT");
9593 return error::kNoError
;
9595 query
= query_manager_
->CreateQuery(
9596 target
, client_id
, sync_shm_id
, sync_shm_offset
);
9599 if (query
->target() != target
) {
9601 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
9602 return error::kNoError
;
9603 } else if (query
->shm_id() != sync_shm_id
||
9604 query
->shm_offset() != sync_shm_offset
) {
9605 DLOG(ERROR
) << "Shared memory used by query not the same as before";
9606 return error::kInvalidArguments
;
9609 if (!query_manager_
->BeginQuery(query
)) {
9610 return error::kOutOfBounds
;
9613 state_
.current_queries
[target
] = query
;
9614 return error::kNoError
;
9617 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(
9618 uint32 immediate_data_size
, const cmds::EndQueryEXT
& c
) {
9619 GLenum target
= static_cast<GLenum
>(c
.target
);
9620 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
9621 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
9623 if (it
== state_
.current_queries
.end()) {
9625 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
9626 return error::kNoError
;
9629 QueryManager::Query
* query
= it
->second
.get();
9630 if (!query_manager_
->EndQuery(query
, submit_count
)) {
9631 return error::kOutOfBounds
;
9634 query_manager_
->ProcessPendingTransferQueries();
9636 state_
.current_queries
.erase(it
);
9637 return error::kNoError
;
9640 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9641 GLsizei n
, const GLuint
* client_ids
) {
9642 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9643 if (GetVertexAttribManager(client_ids
[ii
])) {
9648 if (!features().native_vertex_array_object
) {
9650 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9651 CreateVertexAttribManager(client_ids
[ii
], 0, true);
9654 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9656 glGenVertexArraysOES(n
, service_ids
.get());
9657 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9658 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
9665 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9666 GLsizei n
, const GLuint
* client_ids
) {
9667 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9668 VertexAttribManager
* vao
=
9669 GetVertexAttribManager(client_ids
[ii
]);
9670 if (vao
&& !vao
->IsDeleted()) {
9671 if (state_
.vertex_attrib_manager
.get() == vao
) {
9672 DoBindVertexArrayOES(0);
9674 RemoveVertexAttribManager(client_ids
[ii
]);
9679 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
9680 VertexAttribManager
* vao
= NULL
;
9681 if (client_id
!= 0) {
9682 vao
= GetVertexAttribManager(client_id
);
9684 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9685 // only allows names that have been previously generated. As such, we do
9686 // not generate new names here.
9688 GL_INVALID_OPERATION
,
9689 "glBindVertexArrayOES", "bad vertex array id.");
9690 current_decoder_error_
= error::kNoError
;
9694 vao
= state_
.default_vertex_attrib_manager
.get();
9697 // Only set the VAO state if it's changed
9698 if (state_
.vertex_attrib_manager
.get() != vao
) {
9699 state_
.vertex_attrib_manager
= vao
;
9700 if (!features().native_vertex_array_object
) {
9701 EmulateVertexArrayState();
9703 GLuint service_id
= vao
->service_id();
9704 glBindVertexArrayOES(service_id
);
9709 // Used when OES_vertex_array_object isn't natively supported
9710 void GLES2DecoderImpl::EmulateVertexArrayState() {
9711 // Setup the Vertex attribute state
9712 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
9713 RestoreStateForAttrib(vv
, true);
9716 // Setup the element buffer
9717 Buffer
* element_array_buffer
=
9718 state_
.vertex_attrib_manager
->element_array_buffer();
9719 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
9720 element_array_buffer
? element_array_buffer
->service_id() : 0);
9723 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
9724 const VertexAttribManager
* vao
=
9725 GetVertexAttribManager(client_id
);
9726 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
9729 #if defined(OS_MACOSX)
9730 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
9731 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
9733 if (it
!= texture_to_io_surface_map_
.end()) {
9734 // Found a previous IOSurface bound to this texture; release it.
9735 IOSurfaceRef surface
= it
->second
;
9737 texture_to_io_surface_map_
.erase(it
);
9742 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9743 GLenum target
, GLsizei width
, GLsizei height
,
9744 GLuint io_surface_id
, GLuint plane
) {
9745 #if defined(OS_MACOSX)
9746 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
9748 GL_INVALID_OPERATION
,
9749 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9753 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
9754 // This might be supported in the future, and if we could require
9755 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9756 // could delete a lot of code. For now, perform strict validation so we
9757 // know what's going on.
9759 GL_INVALID_OPERATION
,
9760 "glTexImageIOSurface2DCHROMIUM",
9761 "requires TEXTURE_RECTANGLE_ARB target");
9765 // Default target might be conceptually valid, but disallow it to avoid
9767 TextureRef
* texture_ref
=
9768 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
9771 GL_INVALID_OPERATION
,
9772 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9776 // Look up the new IOSurface. Note that because of asynchrony
9777 // between processes this might fail; during live resizing the
9778 // plugin process might allocate and release an IOSurface before
9779 // this process gets a chance to look it up. Hold on to any old
9780 // IOSurface in this case.
9781 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
9784 GL_INVALID_OPERATION
,
9785 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9789 // Release any IOSurface previously bound to this texture.
9790 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
9792 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9793 texture_to_io_surface_map_
.insert(
9794 std::make_pair(texture_ref
->service_id(), surface
));
9796 CGLContextObj context
=
9797 static_cast<CGLContextObj
>(context_
->GetHandle());
9799 CGLError err
= CGLTexImageIOSurface2D(
9806 GL_UNSIGNED_INT_8_8_8_8_REV
,
9810 if (err
!= kCGLNoError
) {
9812 GL_INVALID_OPERATION
,
9813 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9817 texture_manager()->SetLevelInfo(
9818 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
9819 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
9822 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9823 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9827 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
9828 switch (internalformat
) {
9839 case GL_LUMINANCE8_ALPHA8_EXT
:
9840 return GL_LUMINANCE_ALPHA
;
9841 case GL_LUMINANCE8_EXT
:
9842 return GL_LUMINANCE
;
9845 case GL_RGBA32F_EXT
:
9849 case GL_ALPHA32F_EXT
:
9851 case GL_LUMINANCE32F_EXT
:
9852 return GL_LUMINANCE
;
9853 case GL_LUMINANCE_ALPHA32F_EXT
:
9854 return GL_LUMINANCE_ALPHA
;
9855 case GL_RGBA16F_EXT
:
9859 case GL_ALPHA16F_EXT
:
9861 case GL_LUMINANCE16F_EXT
:
9862 return GL_LUMINANCE
;
9863 case GL_LUMINANCE_ALPHA16F_EXT
:
9864 return GL_LUMINANCE_ALPHA
;
9872 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9873 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
9874 GLenum internal_format
, GLenum dest_type
) {
9875 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9877 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
9878 TextureRef
* source_texture_ref
= GetTexture(source_id
);
9880 if (!source_texture_ref
|| !dest_texture_ref
) {
9882 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
9886 if (GL_TEXTURE_2D
!= target
) {
9888 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
9892 Texture
* source_texture
= source_texture_ref
->texture();
9893 Texture
* dest_texture
= dest_texture_ref
->texture();
9894 if (dest_texture
->target() != GL_TEXTURE_2D
||
9895 (source_texture
->target() != GL_TEXTURE_2D
&&
9896 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
9897 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
9898 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9899 "glCopyTextureCHROMIUM",
9900 "invalid texture target binding");
9904 int source_width
, source_height
, dest_width
, dest_height
;
9906 gfx::GLImage
* image
=
9907 source_texture
->GetLevelImage(source_texture
->target(), 0);
9909 gfx::Size size
= image
->GetSize();
9910 source_width
= size
.width();
9911 source_height
= size
.height();
9912 if (source_width
<= 0 || source_height
<= 0) {
9915 "glCopyTextureChromium", "invalid image size");
9919 if (!source_texture
->GetLevelSize(
9920 source_texture
->target(), 0, &source_width
, &source_height
)) {
9921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9922 "glCopyTextureChromium",
9923 "source texture has no level 0");
9927 // Check that this type of texture is allowed.
9928 if (!texture_manager()->ValidForTarget(
9929 source_texture
->target(), level
, source_width
, source_height
, 1)) {
9931 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
9936 // Clear the source texture if necessary.
9937 if (!texture_manager()->ClearTextureLevel(
9938 this, source_texture_ref
, source_texture
->target(), 0)) {
9940 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
9944 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9945 // needed because it takes 10s of milliseconds to initialize.
9946 if (!copy_texture_CHROMIUM_
.get()) {
9947 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9948 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
9949 copy_texture_CHROMIUM_
->Initialize(this);
9950 RestoreCurrentFramebufferBindings();
9951 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
9955 GLenum dest_type_previous
;
9956 GLenum dest_internal_format
;
9957 bool dest_level_defined
= dest_texture
->GetLevelSize(
9958 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
9960 if (dest_level_defined
) {
9961 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
9962 &dest_internal_format
);
9965 // Resize the destination texture to the dimensions of the source texture.
9966 if (!dest_level_defined
|| dest_width
!= source_width
||
9967 dest_height
!= source_height
||
9968 dest_internal_format
!= internal_format
||
9969 dest_type_previous
!= dest_type
) {
9970 // Ensure that the glTexImage2D succeeds.
9971 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9972 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
9974 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
9975 0, internal_format
, dest_type
, NULL
);
9976 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9977 if (error
!= GL_NO_ERROR
) {
9978 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
9982 texture_manager()->SetLevelInfo(
9983 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
9984 source_height
, 1, 0, internal_format
, dest_type
, true);
9986 texture_manager()->SetLevelCleared(
9987 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
9990 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
9991 ScopedModifyPixels
modify(dest_texture_ref
);
9993 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9994 // before presenting.
9995 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
9996 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9997 // instead of using default matrix crbug.com/226218.
9998 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
9999 0.0f
, 1.0f
, 0.0f
, 0.0f
,
10000 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10001 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10002 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
10004 source_texture
->target(),
10005 dest_texture
->target(),
10006 source_texture
->service_id(),
10007 dest_texture
->service_id(), level
,
10008 source_width
, source_height
,
10010 unpack_premultiply_alpha_
,
10011 unpack_unpremultiply_alpha_
,
10014 copy_texture_CHROMIUM_
->DoCopyTexture(
10016 source_texture
->target(),
10017 dest_texture
->target(),
10018 source_texture
->service_id(),
10019 dest_texture
->service_id(), level
,
10020 source_width
, source_height
,
10022 unpack_premultiply_alpha_
,
10023 unpack_unpremultiply_alpha_
);
10026 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
10029 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
10030 switch (internalformat
) {
10032 return GL_UNSIGNED_SHORT_5_6_5
;
10034 return GL_UNSIGNED_SHORT_4_4_4_4
;
10036 return GL_UNSIGNED_SHORT_5_5_5_1
;
10038 return GL_UNSIGNED_BYTE
;
10040 return GL_UNSIGNED_BYTE
;
10041 case GL_LUMINANCE8_ALPHA8_EXT
:
10042 return GL_UNSIGNED_BYTE
;
10043 case GL_LUMINANCE8_EXT
:
10044 return GL_UNSIGNED_BYTE
;
10045 case GL_ALPHA8_EXT
:
10046 return GL_UNSIGNED_BYTE
;
10047 case GL_RGBA32F_EXT
:
10049 case GL_RGB32F_EXT
:
10051 case GL_ALPHA32F_EXT
:
10053 case GL_LUMINANCE32F_EXT
:
10055 case GL_LUMINANCE_ALPHA32F_EXT
:
10057 case GL_RGBA16F_EXT
:
10058 return GL_HALF_FLOAT_OES
;
10059 case GL_RGB16F_EXT
:
10060 return GL_HALF_FLOAT_OES
;
10061 case GL_ALPHA16F_EXT
:
10062 return GL_HALF_FLOAT_OES
;
10063 case GL_LUMINANCE16F_EXT
:
10064 return GL_HALF_FLOAT_OES
;
10065 case GL_LUMINANCE_ALPHA16F_EXT
:
10066 return GL_HALF_FLOAT_OES
;
10068 return GL_UNSIGNED_BYTE
;
10074 void GLES2DecoderImpl::DoTexStorage2DEXT(
10077 GLenum internal_format
,
10080 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10081 "width", width
, "height", height
);
10082 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
10083 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
10088 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10090 if (!texture_ref
) {
10091 LOCAL_SET_GL_ERROR(
10092 GL_INVALID_OPERATION
,
10093 "glTexStorage2DEXT", "unknown texture for target");
10096 Texture
* texture
= texture_ref
->texture();
10097 if (texture
->IsAttachedToFramebuffer()) {
10098 framebuffer_state_
.clear_state_dirty
= true;
10100 if (texture
->IsImmutable()) {
10101 LOCAL_SET_GL_ERROR(
10102 GL_INVALID_OPERATION
,
10103 "glTexStorage2DEXT", "texture is immutable");
10107 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
10108 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
10111 GLsizei level_width
= width
;
10112 GLsizei level_height
= height
;
10113 uint32 estimated_size
= 0;
10114 for (int ii
= 0; ii
< levels
; ++ii
) {
10115 uint32 level_size
= 0;
10116 if (!GLES2Util::ComputeImageDataSizes(
10117 level_width
, level_height
, format
, type
, state_
.unpack_alignment
,
10118 &estimated_size
, NULL
, NULL
) ||
10119 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
10120 LOCAL_SET_GL_ERROR(
10121 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
10124 level_width
= std::max(1, level_width
>> 1);
10125 level_height
= std::max(1, level_height
>> 1);
10127 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10128 LOCAL_SET_GL_ERROR(
10129 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
10134 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10135 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
10136 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10137 if (error
== GL_NO_ERROR
) {
10138 GLsizei level_width
= width
;
10139 GLsizei level_height
= height
;
10140 for (int ii
= 0; ii
< levels
; ++ii
) {
10141 texture_manager()->SetLevelInfo(
10142 texture_ref
, target
, ii
, format
,
10143 level_width
, level_height
, 1, 0, format
, type
, false);
10144 level_width
= std::max(1, level_width
>> 1);
10145 level_height
= std::max(1, level_height
>> 1);
10147 texture
->SetImmutable(true);
10151 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10152 uint32 immediate_data_size
, const cmds::GenMailboxCHROMIUM
& c
) {
10153 return error::kUnknownCommand
;
10156 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
10157 const GLbyte
* data
) {
10158 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10159 "context", logger_
.GetLogPrefix(),
10160 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10162 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10164 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
10167 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
10168 GLenum target
, const GLbyte
* data
) {
10169 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10170 "context", logger_
.GetLogPrefix(),
10171 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10173 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
10177 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
10178 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
10179 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10180 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
10181 "mailbox that was not generated by "
10182 "GenMailboxCHROMIUM.";
10184 if (!texture_ref
) {
10185 LOCAL_SET_GL_ERROR(
10186 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
10190 Texture
* produced
= texture_manager()->Produce(texture_ref
);
10192 LOCAL_SET_GL_ERROR(
10193 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
10197 if (produced
->target() != target
) {
10198 LOCAL_SET_GL_ERROR(
10199 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
10203 group_
->mailbox_manager()->ProduceTexture(target
, mailbox
, produced
);
10206 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
10207 const GLbyte
* data
) {
10208 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10209 "context", logger_
.GetLogPrefix(),
10210 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10211 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10212 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10213 "mailbox that was not generated by "
10214 "GenMailboxCHROMIUM.";
10216 scoped_refptr
<TextureRef
> texture_ref
=
10217 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10218 if (!texture_ref
.get()) {
10219 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10220 "glConsumeTextureCHROMIUM",
10221 "unknown texture for target");
10224 GLuint client_id
= texture_ref
->client_id();
10226 LOCAL_SET_GL_ERROR(
10227 GL_INVALID_OPERATION
,
10228 "glConsumeTextureCHROMIUM", "unknown texture for target");
10231 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_OPERATION
,
10235 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10238 if (texture
->target() != target
) {
10239 LOCAL_SET_GL_ERROR(
10240 GL_INVALID_OPERATION
,
10241 "glConsumeTextureCHROMIUM", "invalid target");
10245 DeleteTexturesHelper(1, &client_id
);
10246 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10247 glBindTexture(target
, texture_ref
->service_id());
10249 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10250 unit
.bind_target
= target
;
10252 case GL_TEXTURE_2D
:
10253 unit
.bound_texture_2d
= texture_ref
;
10255 case GL_TEXTURE_CUBE_MAP
:
10256 unit
.bound_texture_cube_map
= texture_ref
;
10258 case GL_TEXTURE_EXTERNAL_OES
:
10259 unit
.bound_texture_external_oes
= texture_ref
;
10261 case GL_TEXTURE_RECTANGLE_ARB
:
10262 unit
.bound_texture_rectangle_arb
= texture_ref
;
10265 NOTREACHED(); // Validation should prevent us getting here.
10270 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10271 uint32_t immediate_data_size
,
10272 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
) {
10273 GLenum target
= static_cast<GLenum
>(c
.target
);
10274 uint32_t data_size
;
10275 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
10276 return error::kOutOfBounds
;
10278 if (data_size
> immediate_data_size
) {
10279 return error::kOutOfBounds
;
10281 const GLbyte
* mailbox
=
10282 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
10283 if (!validators_
->texture_bind_target
.IsValid(target
)) {
10284 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10285 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
10286 return error::kNoError
;
10288 if (mailbox
== NULL
) {
10289 return error::kOutOfBounds
;
10291 uint32_t client_id
= c
.client_id
;
10292 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
10293 return error::kNoError
;
10296 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
10297 const GLbyte
* data
, GLuint client_id
) {
10298 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10299 "context", logger_
.GetLogPrefix(),
10300 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10301 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10302 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10303 "passed a mailbox that was not "
10304 "generated by GenMailboxCHROMIUM.";
10306 TextureRef
* texture_ref
= GetTexture(client_id
);
10308 LOCAL_SET_GL_ERROR(
10309 GL_INVALID_OPERATION
,
10310 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10313 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(target
, mailbox
);
10315 LOCAL_SET_GL_ERROR(
10316 GL_INVALID_OPERATION
,
10317 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10320 if (texture
->target() != target
) {
10321 LOCAL_SET_GL_ERROR(
10322 GL_INVALID_OPERATION
,
10323 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10327 IdAllocatorInterface
* id_allocator
=
10328 group_
->GetIdAllocator(id_namespaces::kTextures
);
10329 id_allocator
->MarkAsUsed(client_id
);
10331 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10334 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10335 GLsizei length
, const GLchar
* marker
) {
10339 debug_marker_manager_
.SetMarker(
10340 length
? std::string(marker
, length
) : std::string(marker
));
10343 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10344 GLsizei length
, const GLchar
* marker
) {
10348 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
10349 debug_marker_manager_
.PushGroup(name
);
10350 gpu_tracer_
->Begin(name
, kTraceGroupMarker
);
10353 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10354 debug_marker_manager_
.PopGroup();
10355 gpu_tracer_
->End(kTraceGroupMarker
);
10358 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10359 GLenum target
, GLint image_id
) {
10360 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10362 if (target
== GL_TEXTURE_CUBE_MAP
) {
10363 LOCAL_SET_GL_ERROR(
10365 "glBindTexImage2DCHROMIUM", "invalid target");
10369 // Default target might be conceptually valid, but disallow it to avoid
10371 TextureRef
* texture_ref
=
10372 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10373 if (!texture_ref
) {
10374 LOCAL_SET_GL_ERROR(
10375 GL_INVALID_OPERATION
,
10376 "glBindTexImage2DCHROMIUM", "no texture bound");
10380 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10382 LOCAL_SET_GL_ERROR(
10383 GL_INVALID_OPERATION
,
10384 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10389 ScopedGLErrorSuppressor
suppressor(
10390 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10391 if (!gl_image
->BindTexImage(target
)) {
10392 LOCAL_SET_GL_ERROR(
10393 GL_INVALID_OPERATION
,
10394 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10399 gfx::Size size
= gl_image
->GetSize();
10400 texture_manager()->SetLevelInfo(
10401 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
10402 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
10403 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
10406 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10407 GLenum target
, GLint image_id
) {
10408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10410 // Default target might be conceptually valid, but disallow it to avoid
10412 TextureRef
* texture_ref
=
10413 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10414 if (!texture_ref
) {
10415 LOCAL_SET_GL_ERROR(
10416 GL_INVALID_OPERATION
,
10417 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10421 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
10423 LOCAL_SET_GL_ERROR(
10424 GL_INVALID_OPERATION
,
10425 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10429 // Do nothing when image is not currently bound.
10430 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
10434 ScopedGLErrorSuppressor
suppressor(
10435 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10436 gl_image
->ReleaseTexImage(target
);
10439 texture_manager()->SetLevelInfo(
10440 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
10441 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
10444 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10445 uint32 immediate_data_size
, const cmds::TraceBeginCHROMIUM
& c
) {
10446 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10447 if (!bucket
|| bucket
->size() == 0) {
10448 return error::kInvalidArguments
;
10450 std::string command_name
;
10451 if (!bucket
->GetAsString(&command_name
)) {
10452 return error::kInvalidArguments
;
10454 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name
.c_str(), this);
10455 if (!gpu_tracer_
->Begin(command_name
, kTraceCHROMIUM
)) {
10456 LOCAL_SET_GL_ERROR(
10457 GL_INVALID_OPERATION
,
10458 "glTraceBeginCHROMIUM", "unable to create begin trace");
10459 return error::kNoError
;
10461 return error::kNoError
;
10464 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10465 if (gpu_tracer_
->CurrentName().empty()) {
10466 LOCAL_SET_GL_ERROR(
10467 GL_INVALID_OPERATION
,
10468 "glTraceEndCHROMIUM", "no trace begin found");
10471 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_
->CurrentName().c_str(), this);
10472 gpu_tracer_
->End(kTraceCHROMIUM
);
10475 void GLES2DecoderImpl::DoDrawBuffersEXT(
10476 GLsizei count
, const GLenum
* bufs
) {
10477 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
10478 LOCAL_SET_GL_ERROR(
10480 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10484 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
10486 for (GLsizei i
= 0; i
< count
; ++i
) {
10487 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
10488 bufs
[i
] != GL_NONE
) {
10489 LOCAL_SET_GL_ERROR(
10490 GL_INVALID_OPERATION
,
10491 "glDrawBuffersEXT",
10492 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10496 glDrawBuffersARB(count
, bufs
);
10497 framebuffer
->SetDrawBuffers(count
, bufs
);
10498 } else { // backbuffer
10500 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
10501 LOCAL_SET_GL_ERROR(
10502 GL_INVALID_OPERATION
,
10503 "glDrawBuffersEXT",
10504 "more than one buffer or bufs not GL_NONE or GL_BACK");
10507 GLenum mapped_buf
= bufs
[0];
10508 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10509 bufs
[0] == GL_BACK
) {
10510 mapped_buf
= GL_COLOR_ATTACHMENT0
;
10512 glDrawBuffersARB(count
, &mapped_buf
);
10513 group_
->set_draw_buffer(bufs
[0]);
10517 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
10518 group_
->LoseContexts(other
);
10519 reset_status_
= current
;
10520 current_decoder_error_
= error::kLostContext
;
10523 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10524 const char* function_name
,
10525 TextureRef
* texture_ref
,
10528 const void * data
) {
10529 // We only support async uploads to 2D textures for now.
10530 if (GL_TEXTURE_2D
!= target
) {
10531 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10534 // We only support uploads to level zero for now.
10536 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
10539 // A transfer buffer must be bound, even for asyncTexImage2D.
10540 if (data
== NULL
) {
10541 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
10544 // We only support one async transfer in progress.
10545 if (!texture_ref
||
10546 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10547 LOCAL_SET_GL_ERROR(
10548 GL_INVALID_OPERATION
,
10549 function_name
, "transfer already in progress");
10555 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10556 uint32 async_upload_token
,
10557 uint32 sync_data_shm_id
,
10558 uint32 sync_data_shm_offset
) {
10559 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
10560 if (!buffer
|| !buffer
->GetDataAddress(sync_data_shm_offset
,
10561 sizeof(AsyncUploadSync
)))
10562 return base::Closure();
10564 AsyncMemoryParams
mem_params(buffer
,
10565 sync_data_shm_offset
,
10566 sizeof(AsyncUploadSync
));
10568 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
10569 new AsyncUploadTokenCompletionObserver(async_upload_token
));
10572 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
10573 base::Unretained(GetAsyncPixelTransferManager()),
10578 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10579 uint32 immediate_data_size
, const cmds::AsyncTexImage2DCHROMIUM
& c
) {
10580 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10581 GLenum target
= static_cast<GLenum
>(c
.target
);
10582 GLint level
= static_cast<GLint
>(c
.level
);
10583 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10584 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10585 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10586 GLint border
= static_cast<GLint
>(c
.border
);
10587 GLenum format
= static_cast<GLenum
>(c
.format
);
10588 GLenum type
= static_cast<GLenum
>(c
.type
);
10589 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10590 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10591 uint32 pixels_size
;
10592 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10593 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10594 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10596 base::ScopedClosureRunner scoped_completion_callback
;
10597 if (async_upload_token
) {
10598 base::Closure completion_closure
=
10599 AsyncUploadTokenCompletionClosure(async_upload_token
,
10601 sync_data_shm_offset
);
10602 if (completion_closure
.is_null())
10603 return error::kInvalidArguments
;
10605 scoped_completion_callback
.Reset(completion_closure
);
10608 // TODO(epenner): Move this and copies of this memory validation
10609 // into ValidateTexImage2D step.
10610 if (!GLES2Util::ComputeImageDataSizes(
10611 width
, height
, format
, type
, state_
.unpack_alignment
, &pixels_size
, NULL
,
10613 return error::kOutOfBounds
;
10615 const void* pixels
= NULL
;
10616 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10617 pixels
= GetSharedMemoryAs
<const void*>(
10618 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10620 return error::kOutOfBounds
;
10624 TextureManager::DoTextImage2DArguments args
= {
10625 target
, level
, internal_format
, width
, height
, border
, format
, type
,
10626 pixels
, pixels_size
};
10627 TextureRef
* texture_ref
;
10628 // All the normal glTexSubImage2D validation.
10629 if (!texture_manager()->ValidateTexImage2D(
10630 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
10631 return error::kNoError
;
10634 // Extra async validation.
10635 Texture
* texture
= texture_ref
->texture();
10636 if (!ValidateAsyncTransfer(
10637 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10638 return error::kNoError
;
10640 // Don't allow async redefinition of a textures.
10641 if (texture
->IsDefined()) {
10642 LOCAL_SET_GL_ERROR(
10643 GL_INVALID_OPERATION
,
10644 "glAsyncTexImage2DCHROMIUM", "already defined");
10645 return error::kNoError
;
10648 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
10649 LOCAL_SET_GL_ERROR(
10650 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
10651 return error::kNoError
;
10654 // Setup the parameters.
10655 AsyncTexImage2DParams tex_params
= {
10656 target
, level
, static_cast<GLenum
>(internal_format
),
10657 width
, height
, border
, format
, type
};
10658 AsyncMemoryParams
mem_params(
10659 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
10661 // Set up the async state if needed, and make the texture
10662 // immutable so the async state stays valid. The level info
10663 // is set up lazily when the transfer completes.
10664 AsyncPixelTransferDelegate
* delegate
=
10665 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
10667 texture
->SetImmutable(true);
10669 delegate
->AsyncTexImage2D(
10672 base::Bind(&TextureManager::SetLevelInfoFromParams
,
10673 // The callback is only invoked if the transfer delegate still
10674 // exists, which implies through manager->texture_ref->state
10675 // ownership that both of these pointers are valid.
10676 base::Unretained(texture_manager()),
10677 base::Unretained(texture_ref
),
10679 return error::kNoError
;
10682 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10683 uint32 immediate_data_size
, const cmds::AsyncTexSubImage2DCHROMIUM
& c
) {
10684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10685 GLenum target
= static_cast<GLenum
>(c
.target
);
10686 GLint level
= static_cast<GLint
>(c
.level
);
10687 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10688 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10689 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10690 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10691 GLenum format
= static_cast<GLenum
>(c
.format
);
10692 GLenum type
= static_cast<GLenum
>(c
.type
);
10693 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
10694 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
10695 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10697 base::ScopedClosureRunner scoped_completion_callback
;
10698 if (async_upload_token
) {
10699 base::Closure completion_closure
=
10700 AsyncUploadTokenCompletionClosure(async_upload_token
,
10702 sync_data_shm_offset
);
10703 if (completion_closure
.is_null())
10704 return error::kInvalidArguments
;
10706 scoped_completion_callback
.Reset(completion_closure
);
10709 // TODO(epenner): Move this and copies of this memory validation
10710 // into ValidateTexSubImage2D step.
10712 if (!GLES2Util::ComputeImageDataSizes(
10713 width
, height
, format
, type
, state_
.unpack_alignment
, &data_size
,
10715 return error::kOutOfBounds
;
10717 const void* pixels
= GetSharedMemoryAs
<const void*>(
10718 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
10720 // All the normal glTexSubImage2D validation.
10721 error::Error error
= error::kNoError
;
10722 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
10723 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
10727 // Extra async validation.
10728 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10730 Texture
* texture
= texture_ref
->texture();
10731 if (!ValidateAsyncTransfer(
10732 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
10733 return error::kNoError
;
10735 // Guarantee async textures are always 'cleared' as follows:
10736 // - AsyncTexImage2D can not redefine an existing texture
10737 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10738 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10739 // - Textures become immutable after an async call.
10740 // This way we know in all cases that an async texture is always clear.
10741 if (!texture
->SafeToRenderFrom()) {
10742 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10744 LOCAL_SET_GL_ERROR(
10746 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10747 return error::kNoError
;
10751 // Setup the parameters.
10752 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
10753 width
, height
, format
, type
};
10754 AsyncMemoryParams
mem_params(
10755 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
10756 AsyncPixelTransferDelegate
* delegate
=
10757 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10759 // TODO(epenner): We may want to enforce exclusive use
10760 // of async APIs in which case this should become an error,
10761 // (the texture should have been async defined).
10762 AsyncTexImage2DParams define_params
= {target
, level
,
10764 texture
->GetLevelSize(target
, level
, &define_params
.width
,
10765 &define_params
.height
);
10766 texture
->GetLevelType(target
, level
, &define_params
.type
,
10767 &define_params
.internal_format
);
10768 // Set up the async state if needed, and make the texture
10769 // immutable so the async state stays valid.
10770 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
10771 texture_ref
, define_params
);
10772 texture
->SetImmutable(true);
10775 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
10776 return error::kNoError
;
10779 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10780 uint32 immediate_data_size
, const cmds::WaitAsyncTexImage2DCHROMIUM
& c
) {
10781 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10782 GLenum target
= static_cast<GLenum
>(c
.target
);
10784 if (GL_TEXTURE_2D
!= target
) {
10785 LOCAL_SET_GL_ERROR(
10786 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
10787 return error::kNoError
;
10789 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10791 if (!texture_ref
) {
10792 LOCAL_SET_GL_ERROR(
10793 GL_INVALID_OPERATION
,
10794 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10795 return error::kNoError
;
10797 AsyncPixelTransferDelegate
* delegate
=
10798 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
10800 LOCAL_SET_GL_ERROR(
10801 GL_INVALID_OPERATION
,
10802 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10803 return error::kNoError
;
10805 delegate
->WaitForTransferCompletion();
10806 ProcessFinishedAsyncTransfers();
10807 return error::kNoError
;
10810 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10811 uint32 immediate_data_size
, const cmds::WaitAllAsyncTexImage2DCHROMIUM
& c
) {
10812 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10814 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10815 ProcessFinishedAsyncTransfers();
10816 return error::kNoError
;
10819 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10820 TextureRef
* texture_ref
) {
10821 Texture
* texture
= texture_ref
->texture();
10822 DoDidUseTexImageIfNeeded(texture
, texture
->target());
10825 void GLES2DecoderImpl::OnOutOfMemoryError() {
10826 if (lose_context_when_out_of_memory_
) {
10827 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10828 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB
);
10832 // Include the auto-generated part of this file. We split this because it means
10833 // we can easily edit the non-auto generated parts right here in this file
10834 // instead of having to edit some template or the code generator.
10835 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10837 } // namespace gles2