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"
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.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 "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
77 #include "base/win/win_util.h"
85 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
91 0.0f
, 1.0f
, 0.0f
, 0.0f
,
92 0.0f
, 0.0f
, 1.0f
, 0.0f
,
93 0.0f
, 0.0f
, 0.0f
, 1.0f
};
95 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
98 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
101 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
102 GLenum precision_type
,
103 GLint
* range
, GLint
* precision
) {
104 switch (precision_type
) {
108 // These values are for a 32-bit twos-complement integer format.
114 case GL_MEDIUM_FLOAT
:
116 // These values are for an IEEE single-precision floating-point format.
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
127 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 glGetShaderPrecisionFormat(shader_type
, precision_type
,
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range
[0] = abs(range
[0]);
143 range
[1] = abs(range
[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
148 if (precision_type
== GL_HIGH_FLOAT
&&
149 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
157 static gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
158 switch (plane_transform
) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
160 return gfx::OVERLAY_TRANSFORM_NONE
;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
172 return gfx::OVERLAY_TRANSFORM_INVALID
;
178 class GLES2DecoderImpl
;
180 // Local versions of the SET_GL_ERROR macros
181 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
182 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
183 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
184 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
185 function_name, value, label)
186 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
187 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
188 function_name, pname)
189 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
190 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
192 #define LOCAL_PEEK_GL_ERROR(function_name) \
193 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
194 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
195 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
196 #define LOCAL_PERFORMANCE_WARNING(msg) \
197 PerformanceWarning(__FILE__, __LINE__, msg)
198 #define LOCAL_RENDER_WARNING(msg) \
199 RenderWarning(__FILE__, __LINE__, msg)
201 // Check that certain assumptions the code makes are true. There are places in
202 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
203 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
204 // a few others) are 32bits. If they are not 32bits the code will have to change
205 // to call those GL functions with service side memory and then copy the results
206 // to shared memory, converting the sizes.
207 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
208 "GLint should be the same size as uint32");
209 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
210 "GLsizei should be the same size as uint32");
211 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
212 "GLfloat should be the same size as float");
214 // TODO(kbr): the use of this anonymous namespace core dumps the
215 // linker on Mac OS X 10.6 when the symbol ordering file is used
218 // Returns the address of the first byte after a struct.
219 template <typename T
>
220 const void* AddressAfterStruct(const T
& pod
) {
221 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
224 // Returns the address of the frst byte after the struct or NULL if size >
225 // immediate_data_size.
226 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
227 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
229 uint32 immediate_data_size
) {
230 return (size
<= immediate_data_size
) ?
231 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
235 // Computes the data size for certain gl commands like glUniform.
236 bool ComputeDataSize(
239 unsigned int elements_per_unit
,
242 if (!SafeMultiplyUint32(count
, size
, &value
)) {
245 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
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
{
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 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
523 DCHECK(mem_params
.buffer().get());
524 void* data
= mem_params
.GetDataAddress();
525 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
526 sync
->SetAsyncUploadToken(async_upload_token_
);
530 ~AsyncUploadTokenCompletionObserver() override
{}
532 uint32 async_upload_token_
;
534 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
537 // } // anonymous namespace.
540 const unsigned int GLES2Decoder::kDefaultStencilMask
=
541 static_cast<unsigned int>(-1);
543 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
544 uint32
* service_texture_id
) {
548 GLES2Decoder::GLES2Decoder()
549 : initialized_(false),
551 log_commands_(false),
552 unsafe_es3_apis_enabled_(false) {
555 GLES2Decoder::~GLES2Decoder() {
558 void GLES2Decoder::BeginDecoding() {}
560 void GLES2Decoder::EndDecoding() {}
562 // This class implements GLES2Decoder so we don't have to expose all the GLES2
563 // cmd stuff to outside this class.
564 class GLES2DecoderImpl
: public GLES2Decoder
,
565 public FramebufferManager::TextureDetachObserver
,
566 public ErrorStateClient
{
568 explicit GLES2DecoderImpl(ContextGroup
* group
);
569 ~GLES2DecoderImpl() override
;
571 // Overridden from AsyncAPIInterface.
572 Error
DoCommand(unsigned int command
,
573 unsigned int arg_count
,
574 const void* args
) override
;
576 error::Error
DoCommands(unsigned int num_commands
,
579 int* entries_processed
) override
;
581 template <bool DebugImpl
>
582 error::Error
DoCommandsImpl(unsigned int num_commands
,
585 int* entries_processed
);
587 // Overridden from AsyncAPIInterface.
588 const char* GetCommandName(unsigned int command_id
) const override
;
590 // Overridden from GLES2Decoder.
591 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
592 const scoped_refptr
<gfx::GLContext
>& context
,
594 const gfx::Size
& offscreen_size
,
595 const DisallowedFeatures
& disallowed_features
,
596 const std::vector
<int32
>& attribs
) override
;
597 void Destroy(bool have_context
) override
;
598 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
599 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
600 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
601 void UpdateParentTextureInfo();
602 bool MakeCurrent() override
;
603 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
604 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
605 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
606 Capabilities
GetCapabilities() override
;
607 void RestoreState(const ContextState
* prev_state
) override
;
609 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
610 void RestoreAllTextureUnitBindings(
611 const ContextState
* prev_state
) const override
{
612 state_
.RestoreAllTextureUnitBindings(prev_state
);
614 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
615 state_
.RestoreActiveTextureUnitBinding(target
);
617 void RestoreBufferBindings() const override
{
618 state_
.RestoreBufferBindings();
620 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
621 void RestoreProgramBindings() const override
{
622 state_
.RestoreProgramBindings();
624 void RestoreTextureUnitBindings(unsigned unit
) const override
{
625 state_
.RestoreTextureUnitBindings(unit
, NULL
);
627 void RestoreFramebufferBindings() const override
;
628 void RestoreRenderbufferBindings() override
;
629 void RestoreTextureState(unsigned service_id
) const override
;
631 void ClearAllAttributes() const override
;
632 void RestoreAllAttributes() const override
;
634 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
635 VertexArrayManager
* GetVertexArrayManager() override
{
636 return vertex_array_manager_
.get();
638 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
640 ValuebufferManager
* GetValuebufferManager() override
{
641 return valuebuffer_manager();
644 bool ProcessPendingQueries(bool did_finish
) override
;
646 bool HasMoreIdleWork() override
;
647 void PerformIdleWork() override
;
649 void WaitForReadPixels(base::Closure callback
) override
;
651 void SetResizeCallback(
652 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
654 Logger
* GetLogger() override
;
656 void BeginDecoding() override
;
657 void EndDecoding() override
;
659 ErrorState
* GetErrorState() override
;
660 const ContextState
* GetContextState() override
{ return &state_
; }
662 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
663 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
665 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
666 void ResetAsyncPixelTransferManagerForTest() override
;
667 void SetAsyncPixelTransferManagerForTest(
668 AsyncPixelTransferManager
* manager
) override
;
669 void SetIgnoreCachedStateForTest(bool ignore
) override
;
670 void ProcessFinishedAsyncTransfers();
672 bool GetServiceTextureId(uint32 client_texture_id
,
673 uint32
* service_texture_id
) override
;
675 uint32
GetTextureUploadCount() override
;
676 base::TimeDelta
GetTotalTextureUploadTime() override
;
677 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
678 void AddProcessingCommandsTime(base::TimeDelta
) override
;
680 // Restores the current state to the user's settings.
681 void RestoreCurrentFramebufferBindings();
683 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
684 void ApplyDirtyState();
686 // These check the state of the currently bound framebuffer or the
687 // backbuffer if no framebuffer is bound.
688 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
689 // check with all attached and enabled color attachments.
690 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
691 bool BoundFramebufferHasDepthAttachment();
692 bool BoundFramebufferHasStencilAttachment();
694 error::ContextLostReason
GetContextLostReason() override
;
696 // Overridden from FramebufferManager::TextureDetachObserver:
697 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
699 // Overriden from ErrorStateClient.
700 void OnContextLostError() override
;
701 void OnOutOfMemoryError() override
;
703 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
704 void EnsureRenderbufferBound();
706 // Helpers to facilitate calling into compatible extensions.
707 static void RenderbufferStorageMultisampleHelper(
708 const FeatureInfo
* feature_info
,
711 GLenum internal_format
,
715 void BlitFramebufferHelper(GLint srcX0
,
727 friend class ScopedFrameBufferBinder
;
728 friend class ScopedResolvedFrameBufferBinder
;
729 friend class BackFramebuffer
;
731 // Initialize or re-initialize the shader translator.
732 bool InitializeShaderTranslator();
734 void UpdateCapabilities();
736 // Helpers for the glGen and glDelete functions.
737 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
738 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
739 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
740 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
741 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
742 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
743 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
744 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
745 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
746 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
747 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
748 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
749 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
750 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
752 // Helper for async upload token completion notification callback.
753 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
754 uint32 sync_data_shm_id
,
755 uint32 sync_data_shm_offset
);
760 void OnFboChanged() const;
761 void OnUseFramebuffer() const;
763 error::ContextLostReason
GetContextLostReasonFromResetStatus(
764 GLenum reset_status
) const;
766 // TODO(gman): Cache these pointers?
767 BufferManager
* buffer_manager() {
768 return group_
->buffer_manager();
771 RenderbufferManager
* renderbuffer_manager() {
772 return group_
->renderbuffer_manager();
775 FramebufferManager
* framebuffer_manager() {
776 return group_
->framebuffer_manager();
779 ValuebufferManager
* valuebuffer_manager() {
780 return group_
->valuebuffer_manager();
783 ProgramManager
* program_manager() {
784 return group_
->program_manager();
787 ShaderManager
* shader_manager() {
788 return group_
->shader_manager();
791 ShaderTranslatorCache
* shader_translator_cache() {
792 return group_
->shader_translator_cache();
795 const TextureManager
* texture_manager() const {
796 return group_
->texture_manager();
799 TextureManager
* texture_manager() {
800 return group_
->texture_manager();
803 MailboxManager
* mailbox_manager() {
804 return group_
->mailbox_manager();
807 ImageManager
* image_manager() { return image_manager_
.get(); }
809 VertexArrayManager
* vertex_array_manager() {
810 return vertex_array_manager_
.get();
813 MemoryTracker
* memory_tracker() {
814 return group_
->memory_tracker();
817 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
818 MemoryTracker
* tracker
= memory_tracker();
820 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
825 bool IsOffscreenBufferMultisampled() const {
826 return offscreen_target_samples_
> 1;
829 // Creates a Texture for the given texture.
830 TextureRef
* CreateTexture(
831 GLuint client_id
, GLuint service_id
) {
832 return texture_manager()->CreateTexture(client_id
, service_id
);
835 // Gets the texture info for the given texture. Returns NULL if none exists.
836 TextureRef
* GetTexture(GLuint client_id
) const {
837 return texture_manager()->GetTexture(client_id
);
840 // Deletes the texture info for the given texture.
841 void RemoveTexture(GLuint client_id
) {
842 texture_manager()->RemoveTexture(client_id
);
845 // Get the size (in pixels) of the currently bound frame buffer (either FBO
846 // or regular back buffer).
847 gfx::Size
GetBoundReadFrameBufferSize();
849 // Get the format of the currently bound frame buffer (either FBO or regular
851 GLenum
GetBoundReadFrameBufferTextureType();
852 GLenum
GetBoundReadFrameBufferInternalFormat();
853 GLenum
GetBoundDrawFrameBufferInternalFormat();
855 // Wrapper for CompressedTexImage2D commands.
856 error::Error
DoCompressedTexImage2D(
859 GLenum internal_format
,
866 // Wrapper for CompressedTexImage3D commands.
867 error::Error
DoCompressedTexImage3D(
870 GLenum internal_format
,
878 // Wrapper for CompressedTexSubImage2D.
879 void DoCompressedTexSubImage2D(
890 // Wrapper for CopyTexImage2D.
891 void DoCopyTexImage2D(
894 GLenum internal_format
,
901 // Wrapper for SwapBuffers.
902 void DoSwapBuffers();
904 // Wrapper for SwapInterval.
905 void DoSwapInterval(int interval
);
907 // Wrapper for CopyTexSubImage2D.
908 void DoCopyTexSubImage2D(
918 // Validation for TexSubImage2D.
919 bool ValidateTexSubImage2D(
921 const char* function_name
,
932 // Wrapper for TexSubImage2D.
933 error::Error
DoTexSubImage2D(
944 // Extra validation for async tex(Sub)Image2D.
945 bool ValidateAsyncTransfer(
946 const char* function_name
,
947 TextureRef
* texture_ref
,
952 // Wrapper for TexImageIOSurface2DCHROMIUM.
953 void DoTexImageIOSurface2DCHROMIUM(
957 GLuint io_surface_id
,
960 void DoCopyTextureCHROMIUM(GLenum target
,
963 GLenum internal_format
,
966 void DoCopySubTextureCHROMIUM(GLenum target
,
972 // Wrapper for TexStorage2DEXT.
973 void DoTexStorage2DEXT(
976 GLenum internal_format
,
980 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
981 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
983 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
984 GLenum target
, const GLbyte
* data
);
986 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
987 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
988 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
991 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
992 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
993 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
994 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
995 void DoUniformValueBufferCHROMIUM(GLint location
,
997 GLenum subscription
);
999 void DoBindTexImage2DCHROMIUM(
1002 void DoReleaseTexImage2DCHROMIUM(
1006 void DoTraceEndCHROMIUM(void);
1008 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1010 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1012 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1013 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1015 // Creates a Program for the given program.
1016 Program
* CreateProgram(
1017 GLuint client_id
, GLuint service_id
) {
1018 return program_manager()->CreateProgram(client_id
, service_id
);
1021 // Gets the program info for the given program. Returns NULL if none exists.
1022 Program
* GetProgram(GLuint client_id
) {
1023 return program_manager()->GetProgram(client_id
);
1027 void LogClientServiceMapping(
1028 const char* /* function_name */,
1029 GLuint
/* client_id */,
1030 GLuint
/* service_id */) {
1032 template<typename T
>
1033 void LogClientServiceForInfo(
1034 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1037 void LogClientServiceMapping(
1038 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1039 if (service_logging_
) {
1040 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1041 << ": client_id = " << client_id
1042 << ", service_id = " << service_id
;
1045 template<typename T
>
1046 void LogClientServiceForInfo(
1047 T
* info
, GLuint client_id
, const char* function_name
) {
1049 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1054 // Gets the program info for the given program. If it's not a program
1055 // generates a GL error. Returns NULL if not program.
1056 Program
* GetProgramInfoNotShader(
1057 GLuint client_id
, const char* function_name
) {
1058 Program
* program
= GetProgram(client_id
);
1060 if (GetShader(client_id
)) {
1062 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1067 LogClientServiceForInfo(program
, client_id
, function_name
);
1072 // Creates a Shader for the given shader.
1073 Shader
* CreateShader(
1076 GLenum shader_type
) {
1077 return shader_manager()->CreateShader(
1078 client_id
, service_id
, shader_type
);
1081 // Gets the shader info for the given shader. Returns NULL if none exists.
1082 Shader
* GetShader(GLuint client_id
) {
1083 return shader_manager()->GetShader(client_id
);
1086 // Gets the shader info for the given shader. If it's not a shader generates a
1087 // GL error. Returns NULL if not shader.
1088 Shader
* GetShaderInfoNotProgram(
1089 GLuint client_id
, const char* function_name
) {
1090 Shader
* shader
= GetShader(client_id
);
1092 if (GetProgram(client_id
)) {
1094 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1097 GL_INVALID_VALUE
, function_name
, "unknown shader");
1100 LogClientServiceForInfo(shader
, client_id
, function_name
);
1104 // Creates a buffer info for the given buffer.
1105 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1106 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1109 // Gets the buffer info for the given buffer.
1110 Buffer
* GetBuffer(GLuint client_id
) {
1111 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1115 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1116 // on glDeleteBuffers so we can make sure the user does not try to render
1117 // with deleted buffers.
1118 void RemoveBuffer(GLuint client_id
);
1120 // Creates a framebuffer info for the given framebuffer.
1121 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1122 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1125 // Gets the framebuffer info for the given framebuffer.
1126 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1127 return framebuffer_manager()->GetFramebuffer(client_id
);
1130 // Removes the framebuffer info for the given framebuffer.
1131 void RemoveFramebuffer(GLuint client_id
) {
1132 framebuffer_manager()->RemoveFramebuffer(client_id
);
1135 // Creates a renderbuffer info for the given renderbuffer.
1136 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1137 return renderbuffer_manager()->CreateRenderbuffer(
1138 client_id
, service_id
);
1141 // Gets the renderbuffer info for the given renderbuffer.
1142 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1143 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1146 // Removes the renderbuffer info for the given renderbuffer.
1147 void RemoveRenderbuffer(GLuint client_id
) {
1148 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1151 // Creates a valuebuffer info for the given valuebuffer.
1152 void CreateValuebuffer(GLuint client_id
) {
1153 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1156 // Gets the valuebuffer info for a given valuebuffer.
1157 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1158 return valuebuffer_manager()->GetValuebuffer(client_id
);
1161 // Removes the valuebuffer info for the given valuebuffer.
1162 void RemoveValuebuffer(GLuint client_id
) {
1163 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1166 // Gets the vertex attrib manager for the given vertex array.
1167 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1168 VertexAttribManager
* info
=
1169 vertex_array_manager()->GetVertexAttribManager(client_id
);
1173 // Removes the vertex attrib manager for the given vertex array.
1174 void RemoveVertexAttribManager(GLuint client_id
) {
1175 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1178 // Creates a vertex attrib manager for the given vertex array.
1179 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1182 bool client_visible
) {
1183 return vertex_array_manager()->CreateVertexAttribManager(
1184 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1187 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1188 void DoBindUniformLocationCHROMIUM(
1189 GLuint client_id
, GLint location
, const char* name
);
1191 error::Error
GetAttribLocationHelper(
1192 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1193 const std::string
& name_str
);
1195 error::Error
GetUniformLocationHelper(
1196 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1197 const std::string
& name_str
);
1199 error::Error
GetFragDataLocationHelper(
1200 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1201 const std::string
& name_str
);
1203 // Wrapper for glShaderSource.
1204 void DoShaderSource(
1205 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1207 // Wrapper for glTransformFeedbackVaryings.
1208 void DoTransformFeedbackVaryings(
1209 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1210 GLenum buffer_mode
);
1212 // Clear any textures used by the current program.
1213 bool ClearUnclearedTextures();
1215 // Clears any uncleared attachments attached to the given frame buffer.
1216 // Returns false if there was a generated GL error.
1217 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1219 // overridden from GLES2Decoder
1220 bool ClearLevel(Texture
* texture
,
1223 unsigned internal_format
,
1228 bool is_texture_immutable
) override
;
1230 // Restore all GL state that affects clearing.
1231 void RestoreClearState();
1233 // Remembers the state of some capabilities.
1234 // Returns: true if glEnable/glDisable should actually be called.
1235 bool SetCapabilityState(GLenum cap
, bool enabled
);
1237 // Check that the currently bound framebuffers are valid.
1238 // Generates GL error if not.
1239 bool CheckBoundFramebuffersValid(const char* func_name
);
1241 // Check that the currently bound read framebuffer has a color image
1242 // attached. Generates GL error if not.
1243 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1245 // Check that the currently bound read framebuffer's color image
1246 // isn't the target texture of the glCopyTex{Sub}Image2D.
1247 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1249 // Check if a framebuffer meets our requirements.
1250 bool CheckFramebufferValid(
1251 Framebuffer
* framebuffer
,
1253 const char* func_name
);
1255 // Check if the current valuebuffer exists and is valid. If not generates
1256 // the appropriate GL error. Returns true if the current valuebuffer is in
1258 bool CheckCurrentValuebuffer(const char* function_name
);
1260 // Check if the current valuebuffer exists and is valiud and that the
1261 // value buffer is actually subscribed to the given subscription
1262 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1263 const char* function_name
);
1265 // Check if the location can be used for the given subscription target. If not
1266 // generates the appropriate GL error. Returns true if the location is usable
1267 bool CheckSubscriptionTarget(GLint location
,
1268 GLenum subscription
,
1269 const char* function_name
);
1271 // Checks if the current program exists and is valid. If not generates the
1272 // appropriate GL error. Returns true if the current program is in a usable
1274 bool CheckCurrentProgram(const char* function_name
);
1276 // Checks if the current program exists and is valid and that location is not
1277 // -1. If the current program is not valid generates the appropriate GL
1278 // error. Returns true if the current program is in a usable state and
1279 // location is not -1.
1280 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1282 // Checks if the current program samples a texture that is also the color
1283 // image of the current bound framebuffer, i.e., the source and destination
1284 // of the draw operation are the same.
1285 bool CheckDrawingFeedbackLoops();
1287 // Checks if |api_type| is valid for the given uniform
1288 // If the api type is not valid generates the appropriate GL
1289 // error. Returns true if |api_type| is valid for the uniform
1290 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1291 const char* function_name
,
1292 Program::UniformApiType api_type
);
1294 // Gets the type of a uniform for a location in the current program. Sets GL
1295 // errors if the current program is not valid. Returns true if the current
1296 // program is valid and the location exists. Adjusts count so it
1297 // does not overflow the uniform.
1298 bool PrepForSetUniformByLocation(GLint fake_location
,
1299 const char* function_name
,
1300 Program::UniformApiType api_type
,
1301 GLint
* real_location
,
1305 // Gets the service id for any simulated backbuffer fbo.
1306 GLuint
GetBackbufferServiceId() const;
1308 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1309 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1311 // Helper for glGetVertexAttrib
1312 void GetVertexAttribHelper(
1313 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1315 // Wrapper for glActiveTexture
1316 void DoActiveTexture(GLenum texture_unit
);
1318 // Wrapper for glAttachShader
1319 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1321 // Wrapper for glBindBuffer since we need to track the current targets.
1322 void DoBindBuffer(GLenum target
, GLuint buffer
);
1324 // Wrapper for glBindFramebuffer since we need to track the current targets.
1325 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1327 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1328 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1330 // Wrapper for glBindTexture since we need to track the current targets.
1331 void DoBindTexture(GLenum target
, GLuint texture
);
1333 // Wrapper for glBindVertexArrayOES
1334 void DoBindVertexArrayOES(GLuint array
);
1335 void EmulateVertexArrayState();
1337 // Wrapper for glBlitFramebufferCHROMIUM.
1338 void DoBlitFramebufferCHROMIUM(
1339 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1340 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1341 GLbitfield mask
, GLenum filter
);
1343 // Wrapper for glBufferSubData.
1344 void DoBufferSubData(
1345 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1347 // Wrapper for glCheckFramebufferStatus
1348 GLenum
DoCheckFramebufferStatus(GLenum target
);
1350 // Wrapper for glClear
1351 error::Error
DoClear(GLbitfield mask
);
1353 // Wrappers for various state.
1354 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1355 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1357 // Wrapper for glCompileShader.
1358 void DoCompileShader(GLuint shader
);
1360 // Wrapper for glDetachShader
1361 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1363 // Wrapper for glDisable
1364 void DoDisable(GLenum cap
);
1366 // Wrapper for glDisableVertexAttribArray.
1367 void DoDisableVertexAttribArray(GLuint index
);
1369 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1371 void DoDiscardFramebufferEXT(GLenum target
,
1372 GLsizei numAttachments
,
1373 const GLenum
* attachments
);
1375 // Wrapper for glEnable
1376 void DoEnable(GLenum cap
);
1378 // Wrapper for glEnableVertexAttribArray.
1379 void DoEnableVertexAttribArray(GLuint index
);
1381 // Wrapper for glFinish.
1384 // Wrapper for glFlush.
1387 // Wrapper for glFramebufferRenderbufffer.
1388 void DoFramebufferRenderbuffer(
1389 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1390 GLuint renderbuffer
);
1392 // Wrapper for glFramebufferTexture2D.
1393 void DoFramebufferTexture2D(
1394 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1397 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1398 void DoFramebufferTexture2DMultisample(
1399 GLenum target
, GLenum attachment
, GLenum textarget
,
1400 GLuint texture
, GLint level
, GLsizei samples
);
1402 // Common implementation for both DoFramebufferTexture2D wrappers.
1403 void DoFramebufferTexture2DCommon(const char* name
,
1404 GLenum target
, GLenum attachment
, GLenum textarget
,
1405 GLuint texture
, GLint level
, GLsizei samples
);
1407 // Wrapper for glFramebufferTextureLayer.
1408 void DoFramebufferTextureLayer(
1409 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1412 // Wrapper for glGenerateMipmap
1413 void DoGenerateMipmap(GLenum target
);
1415 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1416 // to account for different pname values defined in different extension
1418 GLenum
AdjustGetPname(GLenum pname
);
1420 // Wrapper for DoGetBooleanv.
1421 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1423 // Wrapper for DoGetFloatv.
1424 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1426 // Wrapper for glGetFramebufferAttachmentParameteriv.
1427 void DoGetFramebufferAttachmentParameteriv(
1428 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1430 // Wrapper for glGetInteger64v.
1431 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1433 // Wrapper for glGetIntegerv.
1434 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1436 // Gets the max value in a range in a buffer.
1437 GLuint
DoGetMaxValueInBufferCHROMIUM(
1438 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1440 // Wrapper for glGetBufferParameteriv.
1441 void DoGetBufferParameteriv(
1442 GLenum target
, GLenum pname
, GLint
* params
);
1444 // Wrapper for glGetProgramiv.
1445 void DoGetProgramiv(
1446 GLuint program_id
, GLenum pname
, GLint
* params
);
1448 // Wrapper for glRenderbufferParameteriv.
1449 void DoGetRenderbufferParameteriv(
1450 GLenum target
, GLenum pname
, GLint
* params
);
1452 // Wrapper for glGetShaderiv
1453 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1455 // Wrappers for glGetTexParameter.
1456 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1457 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1458 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1460 // Wrappers for glGetVertexAttrib.
1461 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1462 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1464 // Wrappers for glIsXXX functions.
1465 bool DoIsEnabled(GLenum cap
);
1466 bool DoIsBuffer(GLuint client_id
);
1467 bool DoIsFramebuffer(GLuint client_id
);
1468 bool DoIsProgram(GLuint client_id
);
1469 bool DoIsRenderbuffer(GLuint client_id
);
1470 bool DoIsShader(GLuint client_id
);
1471 bool DoIsTexture(GLuint client_id
);
1472 bool DoIsVertexArrayOES(GLuint client_id
);
1474 // Wrapper for glLinkProgram
1475 void DoLinkProgram(GLuint program
);
1477 // Wrapper for glRenderbufferStorage.
1478 void DoRenderbufferStorage(
1479 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1481 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1482 void DoRenderbufferStorageMultisampleCHROMIUM(
1483 GLenum target
, GLsizei samples
, GLenum internalformat
,
1484 GLsizei width
, GLsizei height
);
1486 // Handler for glRenderbufferStorageMultisampleEXT
1487 // (multisampled_render_to_texture).
1488 void DoRenderbufferStorageMultisampleEXT(
1489 GLenum target
, GLsizei samples
, GLenum internalformat
,
1490 GLsizei width
, GLsizei height
);
1492 // Common validation for multisample extensions.
1493 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1494 GLenum internalformat
,
1498 // Verifies that the currently bound multisample renderbuffer is valid
1499 // Very slow! Only done on platforms with driver bugs that return invalid
1500 // buffers under memory pressure
1501 bool VerifyMultisampleRenderbufferIntegrity(
1502 GLuint renderbuffer
, GLenum format
);
1504 // Wrapper for glReleaseShaderCompiler.
1505 void DoReleaseShaderCompiler() { }
1507 // Wrappers for glSamplerParameter*v functions.
1508 void DoSamplerParameterfv(
1509 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1510 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1512 // Wrappers for glTexParameter functions.
1513 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1514 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1515 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1516 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1518 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1519 // spec only these 2 functions can be used to set sampler uniforms.
1520 void DoUniform1i(GLint fake_location
, GLint v0
);
1521 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1522 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1523 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1524 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1526 // Wrappers for glUniformfv because some drivers don't correctly accept
1528 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1529 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1530 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1531 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1533 void DoUniformMatrix2fv(
1534 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1535 const GLfloat
* value
);
1536 void DoUniformMatrix3fv(
1537 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1538 const GLfloat
* value
);
1539 void DoUniformMatrix4fv(
1540 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1541 const GLfloat
* value
);
1543 bool SetVertexAttribValue(
1544 const char* function_name
, GLuint index
, const GLfloat
* value
);
1546 // Wrappers for glVertexAttrib??
1547 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1548 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1549 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1550 void DoVertexAttrib4f(
1551 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1552 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1553 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1554 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1555 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1557 // Wrapper for glViewport
1558 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1560 // Wrapper for glUseProgram
1561 void DoUseProgram(GLuint program
);
1563 // Wrapper for glValidateProgram.
1564 void DoValidateProgram(GLuint program_client_id
);
1566 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1567 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1568 void DoPopGroupMarkerEXT(void);
1570 // Gets the number of values that will be returned by glGetXXX. Returns
1571 // false if pname is unknown.
1572 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1574 // Checks if the current program and vertex attributes are valid for drawing.
1576 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1579 // Returns true if successful, simulated will be true if attrib0 was
1581 bool SimulateAttrib0(
1582 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1583 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1585 // If an image is bound to texture, this will call Will/DidUseTexImage
1587 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1588 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1590 // Returns false if textures were replaced.
1591 bool PrepareTexturesForRender();
1592 void RestoreStateForTextures();
1594 // Returns true if GL_FIXED attribs were simulated.
1595 bool SimulateFixedAttribs(
1596 const char* function_name
,
1597 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1598 void RestoreStateForSimulatedFixedAttribs();
1600 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1601 // cases (primcount is always 1 for non-instanced).
1602 error::Error
DoDrawArrays(
1603 const char* function_name
,
1604 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1606 error::Error
DoDrawElements(
1607 const char* function_name
,
1608 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1609 int32 offset
, GLsizei primcount
);
1611 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1612 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1613 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1616 return GL_TEXTURE_2D
;
1617 case GL_SAMPLER_CUBE
:
1618 return GL_TEXTURE_CUBE_MAP
;
1619 case GL_SAMPLER_EXTERNAL_OES
:
1620 return GL_TEXTURE_EXTERNAL_OES
;
1621 case GL_SAMPLER_2D_RECT_ARB
:
1622 return GL_TEXTURE_RECTANGLE_ARB
;
1629 // Gets the framebuffer info for a particular target.
1630 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1631 Framebuffer
* framebuffer
= NULL
;
1633 case GL_FRAMEBUFFER
:
1634 case GL_DRAW_FRAMEBUFFER_EXT
:
1635 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1637 case GL_READ_FRAMEBUFFER_EXT
:
1638 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1647 Renderbuffer
* GetRenderbufferInfoForTarget(
1649 Renderbuffer
* renderbuffer
= NULL
;
1651 case GL_RENDERBUFFER
:
1652 renderbuffer
= state_
.bound_renderbuffer
.get();
1658 return renderbuffer
;
1661 // Validates the program and location for a glGetUniform call and returns
1662 // a SizeResult setup to receive the result. Returns true if glGetUniform
1663 // should be called.
1664 bool GetUniformSetup(GLuint program
,
1665 GLint fake_location
,
1668 error::Error
* error
,
1669 GLint
* real_location
,
1672 GLenum
* result_type
,
1673 GLsizei
* result_size
);
1675 bool WasContextLost() const override
;
1676 bool WasContextLostByRobustnessExtension() const override
;
1677 void MarkContextLost(error::ContextLostReason reason
) override
;
1678 bool CheckResetStatus();
1680 #if defined(OS_MACOSX)
1681 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1684 bool ValidateCompressedTexDimensions(
1685 const char* function_name
, GLenum target
, GLint level
,
1686 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1687 bool ValidateCompressedTexFuncData(
1688 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1689 GLenum format
, GLsizei size
);
1690 bool ValidateCompressedTexSubDimensions(
1691 const char* function_name
,
1692 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1693 GLsizei width
, GLsizei height
, GLenum format
,
1695 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1697 TextureRef
* source_texture_ref
,
1698 TextureRef
* dest_texture_ref
,
1699 GLenum dest_internal_format
);
1701 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1702 void PerformanceWarning(
1703 const char* filename
, int line
, const std::string
& msg
);
1705 const FeatureInfo::FeatureFlags
& features() const {
1706 return feature_info_
->feature_flags();
1709 const FeatureInfo::Workarounds
& workarounds() const {
1710 return feature_info_
->workarounds();
1713 bool ShouldDeferDraws() {
1714 return !offscreen_target_frame_buffer_
.get() &&
1715 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1716 surface_
->DeferDraws();
1719 bool ShouldDeferReads() {
1720 return !offscreen_target_frame_buffer_
.get() &&
1721 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1722 surface_
->DeferDraws();
1725 bool IsRobustnessSupported() {
1726 return has_robustness_extension_
&&
1727 context_
->WasAllocatedUsingRobustnessExtension();
1730 error::Error
WillAccessBoundFramebufferForDraw() {
1731 if (ShouldDeferDraws())
1732 return error::kDeferCommandUntilLater
;
1733 if (!offscreen_target_frame_buffer_
.get() &&
1734 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1735 !surface_
->SetBackbufferAllocation(true))
1736 return error::kLostContext
;
1737 return error::kNoError
;
1740 error::Error
WillAccessBoundFramebufferForRead() {
1741 if (ShouldDeferReads())
1742 return error::kDeferCommandUntilLater
;
1743 if (!offscreen_target_frame_buffer_
.get() &&
1744 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1745 !surface_
->SetBackbufferAllocation(true))
1746 return error::kLostContext
;
1747 return error::kNoError
;
1750 // Set remaining commands to process to 0 to force DoCommands to return
1751 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1752 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1754 void ProcessPendingReadPixels();
1755 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1757 // Generate a member function prototype for each command in an automated and
1759 #define GLES2_CMD_OP(name) \
1760 Error Handle##name(uint32 immediate_data_size, const void* data);
1762 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1766 // The GL context this decoder renders to on behalf of the client.
1767 scoped_refptr
<gfx::GLSurface
> surface_
;
1768 scoped_refptr
<gfx::GLContext
> context_
;
1770 // The ContextGroup for this decoder uses to track resources.
1771 scoped_refptr
<ContextGroup
> group_
;
1773 DebugMarkerManager debug_marker_manager_
;
1776 // All the state for this context.
1777 ContextState state_
;
1779 // Current width and height of the offscreen frame buffer.
1780 gfx::Size offscreen_size_
;
1782 // Util to help with GL.
1785 // unpack flip y as last set by glPixelStorei
1786 bool unpack_flip_y_
;
1788 // unpack (un)premultiply alpha as last set by glPixelStorei
1789 bool unpack_premultiply_alpha_
;
1790 bool unpack_unpremultiply_alpha_
;
1792 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1793 GLuint attrib_0_buffer_id_
;
1795 // The value currently in attrib_0.
1796 Vec4 attrib_0_value_
;
1798 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1799 bool attrib_0_buffer_matches_value_
;
1801 // The size of attrib 0.
1802 GLsizei attrib_0_size_
;
1804 // The buffer used to simulate GL_FIXED attribs.
1805 GLuint fixed_attrib_buffer_id_
;
1807 // The size of fiixed attrib buffer.
1808 GLsizei fixed_attrib_buffer_size_
;
1810 // The offscreen frame buffer that the client renders to. With EGL, the
1811 // depth and stencil buffers are separate. With regular GL there is a single
1812 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1813 // offscreen_target_stencil_render_buffer_ is unused.
1814 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1815 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1816 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1817 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1818 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1819 GLenum offscreen_target_color_format_
;
1820 GLenum offscreen_target_depth_format_
;
1821 GLenum offscreen_target_stencil_format_
;
1822 GLsizei offscreen_target_samples_
;
1823 GLboolean offscreen_target_buffer_preserved_
;
1825 // The copy that is saved when SwapBuffers is called.
1826 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1827 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1828 scoped_refptr
<TextureRef
>
1829 offscreen_saved_color_texture_info_
;
1831 // The copy that is used as the destination for multi-sample resolves.
1832 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1833 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1834 GLenum offscreen_saved_color_format_
;
1836 scoped_ptr
<QueryManager
> query_manager_
;
1838 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1840 scoped_ptr
<ImageManager
> image_manager_
;
1842 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1844 WaitSyncPointCallback wait_sync_point_callback_
;
1846 ShaderCacheCallback shader_cache_callback_
;
1848 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1850 // The format of the back buffer_
1851 GLenum back_buffer_color_format_
;
1852 bool back_buffer_has_depth_
;
1853 bool back_buffer_has_stencil_
;
1857 // Backbuffer attachments that are currently undefined.
1858 uint32 backbuffer_needs_clear_bits_
;
1860 // The current decoder error communicates the decoder error through command
1861 // processing functions that do not return the error value. Should be set only
1862 // if not returning an error.
1863 error::Error current_decoder_error_
;
1865 bool use_shader_translator_
;
1866 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1867 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1869 DisallowedFeatures disallowed_features_
;
1871 // Cached from ContextGroup
1872 const Validators
* validators_
;
1873 scoped_refptr
<FeatureInfo
> feature_info_
;
1877 // Number of commands remaining to be processed in DoCommands().
1878 int commands_to_process_
;
1880 bool has_robustness_extension_
;
1881 error::ContextLostReason context_lost_reason_
;
1882 bool context_was_lost_
;
1883 bool reset_by_robustness_extension_
;
1884 bool supports_post_sub_buffer_
;
1886 // These flags are used to override the state of the shared feature_info_
1887 // member. Because the same FeatureInfo instance may be shared among many
1888 // contexts, the assumptions on the availablity of extensions in WebGL
1889 // contexts may be broken. These flags override the shared state to preserve
1891 bool force_webgl_glsl_validation_
;
1892 bool derivatives_explicitly_enabled_
;
1893 bool frag_depth_explicitly_enabled_
;
1894 bool draw_buffers_explicitly_enabled_
;
1895 bool shader_texture_lod_explicitly_enabled_
;
1897 bool compile_shader_always_succeeds_
;
1899 // An optional behaviour to lose the context and group when OOM.
1900 bool lose_context_when_out_of_memory_
;
1903 bool service_logging_
;
1905 #if defined(OS_MACOSX)
1906 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1907 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1910 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1911 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1913 // Cached values of the currently assigned viewport dimensions.
1914 GLsizei viewport_max_width_
;
1915 GLsizei viewport_max_height_
;
1917 // Command buffer stats.
1918 base::TimeDelta total_processing_commands_time_
;
1920 // States related to each manager.
1921 DecoderTextureState texture_state_
;
1922 DecoderFramebufferState framebuffer_state_
;
1924 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1925 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1926 const unsigned char* cb_command_trace_category_
;
1927 const unsigned char* gpu_decoder_category_
;
1928 int gpu_trace_level_
;
1929 bool gpu_trace_commands_
;
1930 bool gpu_debug_commands_
;
1932 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1934 // Used to validate multisample renderbuffers if needed
1935 GLuint validation_texture_
;
1936 GLuint validation_fbo_multisample_
;
1937 GLuint validation_fbo_
;
1939 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1940 uint32 immediate_data_size
,
1943 // A struct to hold info about each command.
1944 struct CommandInfo
{
1945 CmdHandler cmd_handler
;
1946 uint8 arg_flags
; // How to handle the arguments for this command
1947 uint8 cmd_flags
; // How to handle this command
1948 uint16 arg_count
; // How many arguments are expected for this command.
1951 // A table of CommandInfo for all the commands.
1952 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1954 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1957 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1958 #define GLES2_CMD_OP(name) \
1960 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1961 cmds::name::cmd_flags, \
1962 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1965 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1969 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1970 const char* function_name
, ErrorState
* error_state
)
1971 : function_name_(function_name
),
1972 error_state_(error_state
) {
1973 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1976 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1977 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1980 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1981 TextureUnit
& info
= state
->texture_units
[0];
1983 scoped_refptr
<TextureRef
> texture_ref
;
1986 texture_ref
= info
.bound_texture_2d
;
1988 case GL_TEXTURE_CUBE_MAP
:
1989 texture_ref
= info
.bound_texture_cube_map
;
1991 case GL_TEXTURE_EXTERNAL_OES
:
1992 texture_ref
= info
.bound_texture_external_oes
;
1994 case GL_TEXTURE_RECTANGLE_ARB
:
1995 texture_ref
= info
.bound_texture_rectangle_arb
;
2001 if (texture_ref
.get()) {
2002 last_id
= texture_ref
->service_id();
2007 glBindTexture(target
, last_id
);
2008 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2011 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2016 ScopedGLErrorSuppressor
suppressor(
2017 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2019 // TODO(apatrick): Check if there are any other states that need to be reset
2020 // before binding a new texture.
2021 glActiveTexture(GL_TEXTURE0
);
2022 glBindTexture(target
, id
);
2025 ScopedTextureBinder::~ScopedTextureBinder() {
2026 ScopedGLErrorSuppressor
suppressor(
2027 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2028 RestoreCurrentTextureBindings(state_
, target_
);
2031 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2034 ScopedGLErrorSuppressor
suppressor(
2035 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2036 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2039 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2040 ScopedGLErrorSuppressor
suppressor(
2041 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2042 state_
->RestoreRenderbufferBindings();
2045 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2047 : decoder_(decoder
) {
2048 ScopedGLErrorSuppressor
suppressor(
2049 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2050 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2051 decoder
->OnFboChanged();
2054 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2055 ScopedGLErrorSuppressor
suppressor(
2056 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2057 decoder_
->RestoreCurrentFramebufferBindings();
2060 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2061 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2062 : decoder_(decoder
) {
2063 resolve_and_bind_
= (
2064 decoder_
->offscreen_target_frame_buffer_
.get() &&
2065 decoder_
->IsOffscreenBufferMultisampled() &&
2066 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2067 enforce_internal_framebuffer
));
2068 if (!resolve_and_bind_
)
2071 ScopedGLErrorSuppressor
suppressor(
2072 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2073 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2074 decoder_
->offscreen_target_frame_buffer_
->id());
2077 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2078 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2079 new BackFramebuffer(decoder_
));
2080 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2081 decoder_
->offscreen_resolved_color_texture_
.reset(
2082 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2083 decoder_
->offscreen_resolved_color_texture_
->Create();
2085 DCHECK(decoder_
->offscreen_saved_color_format_
);
2086 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2087 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2089 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2090 decoder_
->offscreen_resolved_color_texture_
.get());
2091 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2092 GL_FRAMEBUFFER_COMPLETE
) {
2093 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2094 << "because offscreen resolved FBO was incomplete.";
2098 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2100 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2102 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2103 const int width
= decoder_
->offscreen_size_
.width();
2104 const int height
= decoder_
->offscreen_size_
.height();
2105 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2106 decoder
->BlitFramebufferHelper(0,
2114 GL_COLOR_BUFFER_BIT
,
2116 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2119 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2120 if (!resolve_and_bind_
)
2123 ScopedGLErrorSuppressor
suppressor(
2124 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2125 decoder_
->RestoreCurrentFramebufferBindings();
2126 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2127 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2131 BackTexture::BackTexture(
2132 MemoryTracker
* memory_tracker
,
2133 ContextState
* state
)
2134 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2136 bytes_allocated_(0),
2140 BackTexture::~BackTexture() {
2141 // This does not destroy the render texture because that would require that
2142 // the associated GL context was current. Just check that it was explicitly
2147 void BackTexture::Create() {
2148 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2149 state_
->GetErrorState());
2151 glGenTextures(1, &id_
);
2152 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2153 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2154 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2155 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2156 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2158 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2159 // never called on an offscreen context, no data will ever be uploaded to the
2160 // saved offscreen color texture (it is deferred until to when SwapBuffers
2161 // is called). My idea is that some nvidia drivers might have a bug where
2162 // deleting a texture that has never been populated might cause a
2165 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2167 bytes_allocated_
= 16u * 16u * 4u;
2168 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2171 bool BackTexture::AllocateStorage(
2172 const gfx::Size
& size
, GLenum format
, bool zero
) {
2174 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2175 state_
->GetErrorState());
2176 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2177 uint32 image_size
= 0;
2178 GLES2Util::ComputeImageDataSizes(
2179 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2182 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2186 scoped_ptr
<char[]> zero_data
;
2188 zero_data
.reset(new char[image_size
]);
2189 memset(zero_data
.get(), 0, image_size
);
2192 glTexImage2D(GL_TEXTURE_2D
,
2204 bool success
= glGetError() == GL_NO_ERROR
;
2206 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2207 bytes_allocated_
= image_size
;
2208 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2213 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2215 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2216 state_
->GetErrorState());
2217 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2218 glCopyTexImage2D(GL_TEXTURE_2D
,
2227 void BackTexture::Destroy() {
2229 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2230 state_
->GetErrorState());
2231 glDeleteTextures(1, &id_
);
2234 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2235 bytes_allocated_
= 0;
2238 void BackTexture::Invalidate() {
2242 BackRenderbuffer::BackRenderbuffer(
2243 RenderbufferManager
* renderbuffer_manager
,
2244 MemoryTracker
* memory_tracker
,
2245 ContextState
* state
)
2246 : renderbuffer_manager_(renderbuffer_manager
),
2247 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2249 bytes_allocated_(0),
2253 BackRenderbuffer::~BackRenderbuffer() {
2254 // This does not destroy the render buffer because that would require that
2255 // the associated GL context was current. Just check that it was explicitly
2260 void BackRenderbuffer::Create() {
2261 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2262 state_
->GetErrorState());
2264 glGenRenderbuffersEXT(1, &id_
);
2267 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2268 const gfx::Size
& size
,
2271 ScopedGLErrorSuppressor
suppressor(
2272 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2273 ScopedRenderBufferBinder
binder(state_
, id_
);
2275 uint32 estimated_size
= 0;
2276 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2277 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2281 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2286 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2291 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2298 bool success
= glGetError() == GL_NO_ERROR
;
2300 // Mark the previously allocated bytes as free.
2301 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2302 bytes_allocated_
= estimated_size
;
2303 // Track the newly allocated bytes.
2304 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2309 void BackRenderbuffer::Destroy() {
2311 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2312 state_
->GetErrorState());
2313 glDeleteRenderbuffersEXT(1, &id_
);
2316 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2317 bytes_allocated_
= 0;
2320 void BackRenderbuffer::Invalidate() {
2324 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2325 : decoder_(decoder
),
2329 BackFramebuffer::~BackFramebuffer() {
2330 // This does not destroy the frame buffer because that would require that
2331 // the associated GL context was current. Just check that it was explicitly
2336 void BackFramebuffer::Create() {
2337 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2338 decoder_
->GetErrorState());
2340 glGenFramebuffersEXT(1, &id_
);
2343 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2345 ScopedGLErrorSuppressor
suppressor(
2346 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2347 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2348 GLuint attach_id
= texture
? texture
->id() : 0;
2349 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2350 GL_COLOR_ATTACHMENT0
,
2356 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2357 BackRenderbuffer
* render_buffer
) {
2359 ScopedGLErrorSuppressor
suppressor(
2360 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2361 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2362 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2363 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2369 void BackFramebuffer::Destroy() {
2371 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2372 decoder_
->GetErrorState());
2373 glDeleteFramebuffersEXT(1, &id_
);
2378 void BackFramebuffer::Invalidate() {
2382 GLenum
BackFramebuffer::CheckStatus() {
2384 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2385 decoder_
->GetErrorState());
2386 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2387 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2390 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2391 return new GLES2DecoderImpl(group
);
2394 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2397 logger_(&debug_marker_manager_
),
2398 state_(group_
->feature_info(), this, &logger_
),
2399 unpack_flip_y_(false),
2400 unpack_premultiply_alpha_(false),
2401 unpack_unpremultiply_alpha_(false),
2402 attrib_0_buffer_id_(0),
2403 attrib_0_buffer_matches_value_(true),
2405 fixed_attrib_buffer_id_(0),
2406 fixed_attrib_buffer_size_(0),
2407 offscreen_target_color_format_(0),
2408 offscreen_target_depth_format_(0),
2409 offscreen_target_stencil_format_(0),
2410 offscreen_target_samples_(0),
2411 offscreen_target_buffer_preserved_(true),
2412 offscreen_saved_color_format_(0),
2413 back_buffer_color_format_(0),
2414 back_buffer_has_depth_(false),
2415 back_buffer_has_stencil_(false),
2416 surfaceless_(false),
2417 backbuffer_needs_clear_bits_(0),
2418 current_decoder_error_(error::kNoError
),
2419 use_shader_translator_(true),
2420 validators_(group_
->feature_info()->validators()),
2421 feature_info_(group_
->feature_info()),
2423 has_robustness_extension_(false),
2424 context_lost_reason_(error::kUnknown
),
2425 context_was_lost_(false),
2426 reset_by_robustness_extension_(false),
2427 supports_post_sub_buffer_(false),
2428 force_webgl_glsl_validation_(false),
2429 derivatives_explicitly_enabled_(false),
2430 frag_depth_explicitly_enabled_(false),
2431 draw_buffers_explicitly_enabled_(false),
2432 shader_texture_lod_explicitly_enabled_(false),
2433 compile_shader_always_succeeds_(false),
2434 lose_context_when_out_of_memory_(false),
2435 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2436 switches::kEnableGPUServiceLoggingGPU
)),
2437 viewport_max_width_(0),
2438 viewport_max_height_(0),
2439 texture_state_(group_
->feature_info()
2441 .texsubimage2d_faster_than_teximage2d
),
2442 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2443 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2444 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2445 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2446 gpu_trace_level_(2),
2447 gpu_trace_commands_(false),
2448 gpu_debug_commands_(false),
2449 validation_texture_(0),
2450 validation_fbo_multisample_(0),
2451 validation_fbo_(0) {
2454 attrib_0_value_
.v
[0] = 0.0f
;
2455 attrib_0_value_
.v
[1] = 0.0f
;
2456 attrib_0_value_
.v
[2] = 0.0f
;
2457 attrib_0_value_
.v
[3] = 1.0f
;
2459 // The shader translator is used for WebGL even when running on EGL
2460 // because additional restrictions are needed (like only enabling
2461 // GL_OES_standard_derivatives on demand). It is used for the unit
2462 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2463 // the empty string to CompileShader and this is not a valid shader.
2464 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2465 base::CommandLine::ForCurrentProcess()->HasSwitch(
2466 switches::kDisableGLSLTranslator
)) {
2467 use_shader_translator_
= false;
2471 GLES2DecoderImpl::~GLES2DecoderImpl() {
2474 bool GLES2DecoderImpl::Initialize(
2475 const scoped_refptr
<gfx::GLSurface
>& surface
,
2476 const scoped_refptr
<gfx::GLContext
>& context
,
2478 const gfx::Size
& offscreen_size
,
2479 const DisallowedFeatures
& disallowed_features
,
2480 const std::vector
<int32
>& attribs
) {
2481 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2482 DCHECK(context
->IsCurrent(surface
.get()));
2483 DCHECK(!context_
.get());
2484 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2486 ContextCreationAttribHelper attrib_parser
;
2487 if (!attrib_parser
.Parse(attribs
))
2490 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2493 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2495 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2496 switches::kEnableGPUDebugging
)) {
2500 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2501 switches::kEnableGPUCommandLogging
)) {
2502 set_log_commands(true);
2505 compile_shader_always_succeeds_
=
2506 base::CommandLine::ForCurrentProcess()->HasSwitch(
2507 switches::kCompileShaderAlwaysSucceeds
);
2509 // Take ownership of the context and surface. The surface can be replaced with
2514 // Create GPU Tracer for timing values.
2515 gpu_tracer_
.reset(new GPUTracer(this));
2517 // Save the loseContextWhenOutOfMemory context creation attribute.
2518 lose_context_when_out_of_memory_
=
2519 attrib_parser
.lose_context_when_out_of_memory
;
2521 // If the failIfMajorPerformanceCaveat context creation attribute was true
2522 // and we are using a software renderer, fail.
2523 if (attrib_parser
.fail_if_major_perf_caveat
&&
2524 feature_info_
->feature_flags().is_swiftshader
) {
2525 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2530 if (!group_
->Initialize(this, disallowed_features
)) {
2531 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2532 << "failed to initialize.";
2533 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2539 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2540 switches::kEnableUnsafeES3APIs
) &&
2541 attrib_parser
.es3_context_required
&&
2542 feature_info_
->IsES3Capable()) {
2543 feature_info_
->EnableES3Validators();
2544 set_unsafe_es3_apis_enabled(true);
2547 disallowed_features_
= disallowed_features
;
2549 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2550 vertex_array_manager_
.reset(new VertexArrayManager());
2552 GLuint default_vertex_attrib_service_id
= 0;
2553 if (features().native_vertex_array_object
) {
2554 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2555 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2558 state_
.default_vertex_attrib_manager
=
2559 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2561 state_
.default_vertex_attrib_manager
->Initialize(
2562 group_
->max_vertex_attribs(),
2563 feature_info_
->workarounds().init_vertex_attributes
);
2565 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2566 DoBindVertexArrayOES(0);
2568 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2570 image_manager_
.reset(new ImageManager
);
2572 util_
.set_num_compressed_texture_formats(
2573 validators_
->compressed_texture_format
.GetValues().size());
2575 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2576 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2577 // OpenGL ES 2.0 does not have this issue.
2578 glEnableVertexAttribArray(0);
2580 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2581 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2582 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2583 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2584 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2586 state_
.texture_units
.resize(group_
->max_texture_units());
2587 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2588 glActiveTexture(GL_TEXTURE0
+ tt
);
2589 // We want the last bind to be 2D.
2591 if (features().oes_egl_image_external
) {
2592 ref
= texture_manager()->GetDefaultTextureInfo(
2593 GL_TEXTURE_EXTERNAL_OES
);
2594 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2595 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2597 if (features().arb_texture_rectangle
) {
2598 ref
= texture_manager()->GetDefaultTextureInfo(
2599 GL_TEXTURE_RECTANGLE_ARB
);
2600 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2601 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2603 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2604 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2605 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2606 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2607 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2608 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2610 glActiveTexture(GL_TEXTURE0
);
2614 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2615 features().chromium_framebuffer_multisample
) {
2616 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2617 // max_sample_count must be initialized to a sane value. If
2618 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2619 GLint max_sample_count
= 1;
2620 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2621 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2624 offscreen_target_samples_
= 1;
2626 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2628 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2629 const bool rgb8_supported
=
2630 context_
->HasExtension("GL_OES_rgb8_rgba8");
2631 // The only available default render buffer formats in GLES2 have very
2632 // little precision. Don't enable multisampling unless 8-bit render
2633 // buffer formats are available--instead fall back to 8-bit textures.
2634 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2635 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2638 offscreen_target_samples_
= 1;
2639 offscreen_target_color_format_
=
2640 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2645 // ANGLE only supports packed depth/stencil formats, so use it if it is
2647 const bool depth24_stencil8_supported
=
2648 feature_info_
->feature_flags().packed_depth24_stencil8
;
2649 VLOG(1) << "GL_OES_packed_depth_stencil "
2650 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2651 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2652 depth24_stencil8_supported
) {
2653 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2654 offscreen_target_stencil_format_
= 0;
2656 // It may be the case that this depth/stencil combination is not
2657 // supported, but this will be checked later by CheckFramebufferStatus.
2658 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2659 GL_DEPTH_COMPONENT16
: 0;
2660 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2661 GL_STENCIL_INDEX8
: 0;
2664 offscreen_target_color_format_
=
2665 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2669 // If depth is requested at all, use the packed depth stencil format if
2670 // it's available, as some desktop GL drivers don't support any non-packed
2671 // formats for depth attachments.
2672 const bool depth24_stencil8_supported
=
2673 feature_info_
->feature_flags().packed_depth24_stencil8
;
2674 VLOG(1) << "GL_EXT_packed_depth_stencil "
2675 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2677 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2678 depth24_stencil8_supported
) {
2679 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2680 offscreen_target_stencil_format_
= 0;
2682 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2683 GL_DEPTH_COMPONENT
: 0;
2684 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2685 GL_STENCIL_INDEX
: 0;
2689 offscreen_saved_color_format_
=
2690 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2694 // Create the target frame buffer. This is the one that the client renders
2696 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2697 offscreen_target_frame_buffer_
->Create();
2698 // Due to GLES2 format limitations, either the color texture (for
2699 // non-multisampling) or the color render buffer (for multisampling) will be
2700 // attached to the offscreen frame buffer. The render buffer has more
2701 // limited formats available to it, but the texture can't do multisampling.
2702 if (IsOffscreenBufferMultisampled()) {
2703 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2704 renderbuffer_manager(), memory_tracker(), &state_
));
2705 offscreen_target_color_render_buffer_
->Create();
2707 offscreen_target_color_texture_
.reset(new BackTexture(
2708 memory_tracker(), &state_
));
2709 offscreen_target_color_texture_
->Create();
2711 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2712 renderbuffer_manager(), memory_tracker(), &state_
));
2713 offscreen_target_depth_render_buffer_
->Create();
2714 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2715 renderbuffer_manager(), memory_tracker(), &state_
));
2716 offscreen_target_stencil_render_buffer_
->Create();
2718 // Create the saved offscreen texture. The target frame buffer is copied
2719 // here when SwapBuffers is called.
2720 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2721 offscreen_saved_frame_buffer_
->Create();
2723 offscreen_saved_color_texture_
.reset(new BackTexture(
2724 memory_tracker(), &state_
));
2725 offscreen_saved_color_texture_
->Create();
2727 // Allocate the render buffers at their initial size and check the status
2728 // of the frame buffers is okay.
2729 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2730 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2735 state_
.viewport_width
= offscreen_size
.width();
2736 state_
.viewport_height
= offscreen_size
.height();
2738 // Allocate the offscreen saved color texture.
2739 DCHECK(offscreen_saved_color_format_
);
2740 offscreen_saved_color_texture_
->AllocateStorage(
2741 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2743 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2744 offscreen_saved_color_texture_
.get());
2745 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2746 GL_FRAMEBUFFER_COMPLETE
) {
2747 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2752 // Bind to the new default frame buffer (the offscreen target frame buffer).
2753 // This should now be associated with ID zero.
2754 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2756 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2757 // These are NOT if the back buffer has these proprorties. They are
2758 // if we want the command buffer to enforce them regardless of what
2759 // the real backbuffer is assuming the real back buffer gives us more than
2760 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2761 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2762 // can't do anything about that.
2764 if (!surfaceless_
) {
2765 GLint alpha_bits
= 0;
2766 GLint depth_bits
= 0;
2767 GLint stencil_bits
= 0;
2769 bool default_fb
= (GetBackbufferServiceId() == 0);
2771 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2772 glGetFramebufferAttachmentParameterivEXT(
2774 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2775 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2776 glGetFramebufferAttachmentParameterivEXT(
2778 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2779 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2780 glGetFramebufferAttachmentParameterivEXT(
2782 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2783 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2785 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2786 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2787 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2790 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2791 // the user requested RGB then RGB. If the user did not specify a
2792 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2793 back_buffer_color_format_
=
2794 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2795 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2796 back_buffer_has_stencil_
=
2797 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2800 state_
.viewport_width
= surface
->GetSize().width();
2801 state_
.viewport_height
= surface
->GetSize().height();
2804 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2805 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2806 // isn't well documented; it was discovered in the Khronos OpenGL ES
2807 // mailing list archives. It also implicitly enables the desktop GL
2808 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2809 // variable in fragment shaders.
2810 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2811 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2812 glEnable(GL_POINT_SPRITE
);
2815 has_robustness_extension_
=
2816 context
->HasExtension("GL_ARB_robustness") ||
2817 context
->HasExtension("GL_KHR_robustness") ||
2818 context
->HasExtension("GL_EXT_robustness");
2820 if (!InitializeShaderTranslator()) {
2824 GLint viewport_params
[4] = { 0 };
2825 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2826 viewport_max_width_
= viewport_params
[0];
2827 viewport_max_height_
= viewport_params
[1];
2829 state_
.scissor_width
= state_
.viewport_width
;
2830 state_
.scissor_height
= state_
.viewport_height
;
2832 // Set all the default state because some GL drivers get it wrong.
2833 state_
.InitCapabilities(NULL
);
2834 state_
.InitState(NULL
);
2835 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2837 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2838 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2839 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2840 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2841 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2843 bool call_gl_clear
= !surfaceless_
;
2844 #if defined(OS_ANDROID)
2845 // Temporary workaround for Android WebView because this clear ignores the
2846 // clip and corrupts that external UI of the App. Not calling glClear is ok
2847 // because the system already clears the buffer before each draw. Proper
2848 // fix might be setting the scissor clip properly before initialize. See
2849 // crbug.com/259023 for details.
2850 call_gl_clear
= surface_
->GetHandle();
2852 if (call_gl_clear
) {
2853 // Clear the backbuffer.
2854 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2857 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2858 if (feature_info_
->workarounds()
2859 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2860 !surface
->IsOffscreen())
2861 supports_post_sub_buffer_
= false;
2863 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2864 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2867 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2868 context_
->SetUnbindFboOnMakeCurrent();
2871 // Only compositor contexts are known to use only the subset of GL
2872 // that can be safely migrated between the iGPU and the dGPU. Mark
2873 // those contexts as safe to forcibly transition between the GPUs.
2874 // http://crbug.com/180876, http://crbug.com/227228
2876 context_
->SetSafeToForceGpuSwitch();
2878 async_pixel_transfer_manager_
.reset(
2879 AsyncPixelTransferManager::Create(context
.get()));
2880 async_pixel_transfer_manager_
->Initialize(texture_manager());
2882 if (workarounds().gl_clear_broken
) {
2883 DCHECK(!clear_framebuffer_blit_
.get());
2884 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2885 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2886 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2890 framebuffer_manager()->AddObserver(this);
2895 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2896 DCHECK(initialized());
2899 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2900 Capabilities::ShaderPrecision
* shader_precision
) {
2901 GLint range
[2] = {0, 0};
2902 GLint precision
= 0;
2903 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2904 shader_precision
->min_range
= range
[0];
2905 shader_precision
->max_range
= range
[1];
2906 shader_precision
->precision
= precision
;
2908 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2909 &caps
.max_combined_texture_image_units
);
2910 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2911 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2912 &caps
.max_fragment_uniform_vectors
);
2913 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2914 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2915 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2916 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2917 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2918 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2919 &caps
.max_vertex_texture_image_units
);
2920 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2921 &caps
.max_vertex_uniform_vectors
);
2922 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2923 &caps
.num_compressed_texture_formats
);
2924 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2925 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2926 &caps
.bind_generates_resource_chromium
);
2927 if (unsafe_es3_apis_enabled()) {
2928 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2929 // but for now we clamp them to 32-bit max.
2930 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
2931 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
2932 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
2933 DoGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
2934 &caps
.max_combined_fragment_uniform_components
);
2935 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
2936 &caps
.max_combined_uniform_blocks
);
2937 DoGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
2938 &caps
.max_combined_vertex_uniform_components
);
2939 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
2940 DoGetIntegerv(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
2941 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
2942 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
2943 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
2944 &caps
.max_fragment_input_components
);
2945 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
2946 &caps
.max_fragment_uniform_blocks
);
2947 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
2948 &caps
.max_fragment_uniform_components
);
2949 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
2950 &caps
.max_program_texel_offset
);
2951 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
2952 DoGetIntegerv(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
2953 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
2954 &caps
.max_transform_feedback_interleaved_components
);
2955 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
2956 &caps
.max_transform_feedback_separate_attribs
);
2957 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
2958 &caps
.max_transform_feedback_separate_components
);
2959 DoGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
2960 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
2961 &caps
.max_uniform_buffer_bindings
);
2962 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
2963 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
2964 &caps
.max_vertex_output_components
);
2965 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
2966 &caps
.max_vertex_uniform_blocks
);
2967 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
2968 &caps
.max_vertex_uniform_components
);
2969 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
2970 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
2971 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
2972 &caps
.num_program_binary_formats
);
2973 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
2974 &caps
.uniform_buffer_offset_alignment
);
2975 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
2976 caps
.major_version
= 3;
2977 caps
.minor_version
= 0;
2980 caps
.egl_image_external
=
2981 feature_info_
->feature_flags().oes_egl_image_external
;
2982 caps
.texture_format_atc
=
2983 feature_info_
->feature_flags().ext_texture_format_atc
;
2984 caps
.texture_format_bgra8888
=
2985 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2986 caps
.texture_format_dxt1
=
2987 feature_info_
->feature_flags().ext_texture_format_dxt1
;
2988 caps
.texture_format_dxt5
=
2989 feature_info_
->feature_flags().ext_texture_format_dxt5
;
2990 caps
.texture_format_etc1
=
2991 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2992 caps
.texture_format_etc1_npot
=
2993 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2994 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2995 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2996 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2997 caps
.discard_framebuffer
=
2998 feature_info_
->feature_flags().ext_discard_framebuffer
;
2999 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3001 #if defined(OS_MACOSX)
3002 // This is unconditionally true on mac, no need to test for it at runtime.
3003 caps
.iosurface
= true;
3006 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3009 caps
.blend_equation_advanced
=
3010 feature_info_
->feature_flags().blend_equation_advanced
;
3011 caps
.blend_equation_advanced_coherent
=
3012 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3013 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3017 void GLES2DecoderImpl::UpdateCapabilities() {
3018 util_
.set_num_compressed_texture_formats(
3019 validators_
->compressed_texture_format
.GetValues().size());
3020 util_
.set_num_shader_binary_formats(
3021 validators_
->shader_binary_format
.GetValues().size());
3024 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3025 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3027 if (!use_shader_translator_
) {
3030 ShBuiltInResources resources
;
3031 ShInitBuiltInResources(&resources
);
3032 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3033 resources
.MaxVertexUniformVectors
=
3034 group_
->max_vertex_uniform_vectors();
3035 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3036 resources
.MaxVertexTextureImageUnits
=
3037 group_
->max_vertex_texture_image_units();
3038 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3039 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3040 resources
.MaxFragmentUniformVectors
=
3041 group_
->max_fragment_uniform_vectors();
3042 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3043 resources
.MaxExpressionComplexity
= 256;
3044 resources
.MaxCallStackDepth
= 256;
3046 GLint range
[2] = { 0, 0 };
3047 GLint precision
= 0;
3048 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3050 resources
.FragmentPrecisionHigh
=
3051 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3053 if (force_webgl_glsl_validation_
) {
3054 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3055 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3056 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3057 if (!draw_buffers_explicitly_enabled_
)
3058 resources
.MaxDrawBuffers
= 1;
3059 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3060 resources
.NV_draw_buffers
=
3061 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3063 resources
.OES_standard_derivatives
=
3064 features().oes_standard_derivatives
? 1 : 0;
3065 resources
.ARB_texture_rectangle
=
3066 features().arb_texture_rectangle
? 1 : 0;
3067 resources
.OES_EGL_image_external
=
3068 features().oes_egl_image_external
? 1 : 0;
3069 resources
.EXT_draw_buffers
=
3070 features().ext_draw_buffers
? 1 : 0;
3071 resources
.EXT_frag_depth
=
3072 features().ext_frag_depth
? 1 : 0;
3073 resources
.EXT_shader_texture_lod
=
3074 features().ext_shader_texture_lod
? 1 : 0;
3075 resources
.NV_draw_buffers
=
3076 features().nv_draw_buffers
? 1 : 0;
3079 ShShaderSpec shader_spec
;
3080 if (force_webgl_glsl_validation_
) {
3081 shader_spec
= unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3083 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3086 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3087 features().enable_shader_name_hashing
)
3088 resources
.HashFunction
= &CityHash64
;
3090 resources
.HashFunction
= NULL
;
3091 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3092 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3093 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3094 int driver_bug_workarounds
= 0;
3095 if (workarounds().needs_glsl_built_in_function_emulation
)
3096 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3097 if (workarounds().init_gl_position_in_vertex_shader
)
3098 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3099 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3100 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3101 if (workarounds().init_varyings_without_static_use
)
3102 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3103 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3104 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3105 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3106 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3107 if (workarounds().regenerate_struct_names
)
3108 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3110 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3111 switches::kEmulateShaderPrecision
))
3112 resources
.WEBGL_debug_shader_precision
= true;
3114 vertex_translator_
= shader_translator_cache()->GetTranslator(
3118 implementation_type
,
3119 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3120 if (!vertex_translator_
.get()) {
3121 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3126 fragment_translator_
= shader_translator_cache()->GetTranslator(
3130 implementation_type
,
3131 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3132 if (!fragment_translator_
.get()) {
3133 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3140 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3141 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3142 if (GetBuffer(client_ids
[ii
])) {
3146 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3147 glGenBuffersARB(n
, service_ids
.get());
3148 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3149 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3154 bool GLES2DecoderImpl::GenFramebuffersHelper(
3155 GLsizei n
, const GLuint
* client_ids
) {
3156 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3157 if (GetFramebuffer(client_ids
[ii
])) {
3161 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3162 glGenFramebuffersEXT(n
, service_ids
.get());
3163 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3164 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3169 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3170 GLsizei n
, const GLuint
* client_ids
) {
3171 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3172 if (GetRenderbuffer(client_ids
[ii
])) {
3176 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3177 glGenRenderbuffersEXT(n
, service_ids
.get());
3178 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3179 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3184 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3185 const GLuint
* client_ids
) {
3186 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3187 if (GetValuebuffer(client_ids
[ii
])) {
3191 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3192 CreateValuebuffer(client_ids
[ii
]);
3197 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3198 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3199 if (GetTexture(client_ids
[ii
])) {
3203 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3204 glGenTextures(n
, service_ids
.get());
3205 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3206 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3211 void GLES2DecoderImpl::DeleteBuffersHelper(
3212 GLsizei n
, const GLuint
* client_ids
) {
3213 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3214 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3215 if (buffer
&& !buffer
->IsDeleted()) {
3216 buffer
->RemoveMappedRange();
3217 state_
.vertex_attrib_manager
->Unbind(buffer
);
3218 if (state_
.bound_array_buffer
.get() == buffer
) {
3219 state_
.bound_array_buffer
= NULL
;
3221 RemoveBuffer(client_ids
[ii
]);
3226 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3227 GLsizei n
, const GLuint
* client_ids
) {
3228 bool supports_separate_framebuffer_binds
=
3229 features().chromium_framebuffer_multisample
;
3231 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3232 Framebuffer
* framebuffer
=
3233 GetFramebuffer(client_ids
[ii
]);
3234 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3235 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3236 GLenum target
= supports_separate_framebuffer_binds
?
3237 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3239 // Unbind attachments on FBO before deletion.
3240 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3241 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3243 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3244 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3245 framebuffer_state_
.clear_state_dirty
= true;
3247 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3248 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3249 GLenum target
= supports_separate_framebuffer_binds
?
3250 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3251 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3254 RemoveFramebuffer(client_ids
[ii
]);
3259 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3260 GLsizei n
, const GLuint
* client_ids
) {
3261 bool supports_separate_framebuffer_binds
=
3262 features().chromium_framebuffer_multisample
;
3263 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3264 Renderbuffer
* renderbuffer
=
3265 GetRenderbuffer(client_ids
[ii
]);
3266 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3267 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3268 state_
.bound_renderbuffer
= NULL
;
3270 // Unbind from current framebuffers.
3271 if (supports_separate_framebuffer_binds
) {
3272 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3273 framebuffer_state_
.bound_read_framebuffer
3274 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3276 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3277 framebuffer_state_
.bound_draw_framebuffer
3278 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3281 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3282 framebuffer_state_
.bound_draw_framebuffer
3283 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3286 framebuffer_state_
.clear_state_dirty
= true;
3287 RemoveRenderbuffer(client_ids
[ii
]);
3292 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3294 const GLuint
* client_ids
) {
3295 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3296 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3298 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3299 state_
.bound_valuebuffer
= NULL
;
3301 RemoveValuebuffer(client_ids
[ii
]);
3306 void GLES2DecoderImpl::DeleteTexturesHelper(
3307 GLsizei n
, const GLuint
* client_ids
) {
3308 bool supports_separate_framebuffer_binds
=
3309 features().chromium_framebuffer_multisample
;
3310 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3311 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3313 Texture
* texture
= texture_ref
->texture();
3314 if (texture
->IsAttachedToFramebuffer()) {
3315 framebuffer_state_
.clear_state_dirty
= true;
3317 // Unbind texture_ref from texture_ref units.
3318 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3319 state_
.texture_units
[jj
].Unbind(texture_ref
);
3321 // Unbind from current framebuffers.
3322 if (supports_separate_framebuffer_binds
) {
3323 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3324 framebuffer_state_
.bound_read_framebuffer
3325 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3327 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3328 framebuffer_state_
.bound_draw_framebuffer
3329 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3332 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3333 framebuffer_state_
.bound_draw_framebuffer
3334 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3337 #if defined(OS_MACOSX)
3338 GLuint service_id
= texture
->service_id();
3339 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3340 ReleaseIOSurfaceForTexture(service_id
);
3343 RemoveTexture(client_ids
[ii
]);
3348 // } // anonymous namespace
3350 bool GLES2DecoderImpl::MakeCurrent() {
3351 if (!context_
.get())
3354 if (WasContextLost()) {
3355 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3359 if (!context_
->MakeCurrent(surface_
.get())) {
3360 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3361 MarkContextLost(error::kMakeCurrentFailed
);
3362 group_
->LoseContexts(error::kUnknown
);
3366 if (CheckResetStatus()) {
3368 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3369 group_
->LoseContexts(error::kUnknown
);
3373 ProcessFinishedAsyncTransfers();
3375 // Rebind the FBO if it was unbound by the context.
3376 if (workarounds().unbind_fbo_on_context_switch
)
3377 RestoreFramebufferBindings();
3379 framebuffer_state_
.clear_state_dirty
= true;
3384 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3385 ProcessPendingReadPixels();
3386 if (engine() && query_manager_
.get())
3387 query_manager_
->ProcessPendingTransferQueries();
3389 // TODO(epenner): Is there a better place to do this?
3390 // This needs to occur before we execute any batch of commands
3391 // from the client, as the client may have recieved an async
3392 // completion while issuing those commands.
3393 // "DidFlushStart" would be ideal if we had such a callback.
3394 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3397 static void RebindCurrentFramebuffer(
3399 Framebuffer
* framebuffer
,
3400 GLuint back_buffer_service_id
) {
3401 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3403 if (framebuffer_id
== 0) {
3404 framebuffer_id
= back_buffer_service_id
;
3407 glBindFramebufferEXT(target
, framebuffer_id
);
3410 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3411 framebuffer_state_
.clear_state_dirty
= true;
3413 if (!features().chromium_framebuffer_multisample
) {
3414 RebindCurrentFramebuffer(
3416 framebuffer_state_
.bound_draw_framebuffer
.get(),
3417 GetBackbufferServiceId());
3419 RebindCurrentFramebuffer(
3420 GL_READ_FRAMEBUFFER_EXT
,
3421 framebuffer_state_
.bound_read_framebuffer
.get(),
3422 GetBackbufferServiceId());
3423 RebindCurrentFramebuffer(
3424 GL_DRAW_FRAMEBUFFER_EXT
,
3425 framebuffer_state_
.bound_draw_framebuffer
.get(),
3426 GetBackbufferServiceId());
3431 bool GLES2DecoderImpl::CheckFramebufferValid(
3432 Framebuffer
* framebuffer
,
3433 GLenum target
, const char* func_name
) {
3437 if (backbuffer_needs_clear_bits_
) {
3438 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3439 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3440 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3442 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3443 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3445 state_
.SetDeviceDepthMask(GL_TRUE
);
3446 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3447 bool reset_draw_buffer
= false;
3448 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3449 group_
->draw_buffer() == GL_NONE
) {
3450 reset_draw_buffer
= true;
3451 GLenum buf
= GL_BACK
;
3452 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3453 buf
= GL_COLOR_ATTACHMENT0
;
3454 glDrawBuffersARB(1, &buf
);
3456 glClear(backbuffer_needs_clear_bits_
);
3457 if (reset_draw_buffer
) {
3458 GLenum buf
= GL_NONE
;
3459 glDrawBuffersARB(1, &buf
);
3461 backbuffer_needs_clear_bits_
= 0;
3462 RestoreClearState();
3467 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3471 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3472 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3474 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3478 // Are all the attachments cleared?
3479 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3480 texture_manager()->HaveUnclearedMips()) {
3481 if (!framebuffer
->IsCleared()) {
3482 // Can we clear them?
3483 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3484 GL_FRAMEBUFFER_COMPLETE
) {
3486 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3487 "framebuffer incomplete (clear)");
3490 ClearUnclearedAttachments(target
, framebuffer
);
3494 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3495 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3496 GL_FRAMEBUFFER_COMPLETE
) {
3498 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3499 "framebuffer incomplete (check)");
3502 framebuffer_manager()->MarkAsComplete(framebuffer
);
3505 // NOTE: At this point we don't know if the framebuffer is complete but
3506 // we DO know that everything that needs to be cleared has been cleared.
3510 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3511 if (!features().chromium_framebuffer_multisample
) {
3512 bool valid
= CheckFramebufferValid(
3513 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3521 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3522 GL_DRAW_FRAMEBUFFER_EXT
,
3524 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3525 GL_READ_FRAMEBUFFER_EXT
,
3529 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3530 const char* func_name
) {
3531 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3532 framebuffer_state_
.bound_read_framebuffer
.get() :
3533 framebuffer_state_
.bound_draw_framebuffer
.get();
3536 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3538 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3544 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3545 TextureRef
* texture
, GLint level
) {
3546 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3547 framebuffer_state_
.bound_read_framebuffer
.get() :
3548 framebuffer_state_
.bound_draw_framebuffer
.get();
3551 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3552 GL_COLOR_ATTACHMENT0
);
3555 return attachment
->FormsFeedbackLoop(texture
, level
);
3558 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3559 Framebuffer
* framebuffer
=
3560 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3561 if (framebuffer
!= NULL
) {
3562 const Framebuffer::Attachment
* attachment
=
3563 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3565 return gfx::Size(attachment
->width(), attachment
->height());
3567 return gfx::Size(0, 0);
3568 } else if (offscreen_target_frame_buffer_
.get()) {
3569 return offscreen_size_
;
3571 return surface_
->GetSize();
3575 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3576 Framebuffer
* framebuffer
=
3577 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3578 if (framebuffer
!= NULL
) {
3579 return framebuffer
->GetColorAttachmentTextureType();
3581 return GL_UNSIGNED_BYTE
;
3585 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3586 Framebuffer
* framebuffer
=
3587 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3588 if (framebuffer
!= NULL
) {
3589 return framebuffer
->GetColorAttachmentFormat();
3590 } else if (offscreen_target_frame_buffer_
.get()) {
3591 return offscreen_target_color_format_
;
3593 return back_buffer_color_format_
;
3597 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3598 Framebuffer
* framebuffer
=
3599 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3600 if (framebuffer
!= NULL
) {
3601 return framebuffer
->GetColorAttachmentFormat();
3602 } else if (offscreen_target_frame_buffer_
.get()) {
3603 return offscreen_target_color_format_
;
3605 return back_buffer_color_format_
;
3609 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3610 if (!offscreen_saved_color_texture_info_
.get())
3612 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3613 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3614 texture_manager()->SetLevelInfo(
3615 offscreen_saved_color_texture_info_
.get(),
3619 offscreen_size_
.width(),
3620 offscreen_size_
.height(),
3626 texture_manager()->SetParameteri(
3627 "UpdateParentTextureInfo",
3629 offscreen_saved_color_texture_info_
.get(),
3630 GL_TEXTURE_MAG_FILTER
,
3632 texture_manager()->SetParameteri(
3633 "UpdateParentTextureInfo",
3635 offscreen_saved_color_texture_info_
.get(),
3636 GL_TEXTURE_MIN_FILTER
,
3638 texture_manager()->SetParameteri(
3639 "UpdateParentTextureInfo",
3641 offscreen_saved_color_texture_info_
.get(),
3644 texture_manager()->SetParameteri(
3645 "UpdateParentTextureInfo",
3647 offscreen_saved_color_texture_info_
.get(),
3650 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3652 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3655 void GLES2DecoderImpl::SetResizeCallback(
3656 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3657 resize_callback_
= callback
;
3660 Logger
* GLES2DecoderImpl::GetLogger() {
3664 void GLES2DecoderImpl::BeginDecoding() {
3665 gpu_tracer_
->BeginDecoding();
3666 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3667 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3668 (*cb_command_trace_category_
!= 0);
3671 void GLES2DecoderImpl::EndDecoding() {
3672 gpu_tracer_
->EndDecoding();
3675 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3676 return state_
.GetErrorState();
3679 void GLES2DecoderImpl::SetShaderCacheCallback(
3680 const ShaderCacheCallback
& callback
) {
3681 shader_cache_callback_
= callback
;
3684 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3685 const WaitSyncPointCallback
& callback
) {
3686 wait_sync_point_callback_
= callback
;
3689 AsyncPixelTransferManager
*
3690 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3691 return async_pixel_transfer_manager_
.get();
3694 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3695 async_pixel_transfer_manager_
.reset();
3698 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3699 AsyncPixelTransferManager
* manager
) {
3700 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3703 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3704 uint32
* service_texture_id
) {
3705 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3707 *service_texture_id
= texture_ref
->service_id();
3713 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3714 return texture_state_
.texture_upload_count
+
3715 async_pixel_transfer_manager_
->GetTextureUploadCount();
3718 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3719 return texture_state_
.total_texture_upload_time
+
3720 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3723 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3724 return total_processing_commands_time_
;
3727 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3728 total_processing_commands_time_
+= time
;
3731 void GLES2DecoderImpl::Destroy(bool have_context
) {
3735 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3737 // Unbind everything.
3738 state_
.vertex_attrib_manager
= NULL
;
3739 state_
.default_vertex_attrib_manager
= NULL
;
3740 state_
.texture_units
.clear();
3741 state_
.bound_array_buffer
= NULL
;
3742 state_
.current_queries
.clear();
3743 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3744 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3745 state_
.bound_renderbuffer
= NULL
;
3746 state_
.bound_valuebuffer
= NULL
;
3748 if (offscreen_saved_color_texture_info_
.get()) {
3749 DCHECK(offscreen_target_color_texture_
);
3750 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3751 offscreen_saved_color_texture_
->id());
3752 offscreen_saved_color_texture_
->Invalidate();
3753 offscreen_saved_color_texture_info_
= NULL
;
3756 if (copy_texture_CHROMIUM_
.get()) {
3757 copy_texture_CHROMIUM_
->Destroy();
3758 copy_texture_CHROMIUM_
.reset();
3761 clear_framebuffer_blit_
.reset();
3763 if (state_
.current_program
.get()) {
3764 program_manager()->UnuseProgram(shader_manager(),
3765 state_
.current_program
.get());
3768 if (attrib_0_buffer_id_
) {
3769 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3771 if (fixed_attrib_buffer_id_
) {
3772 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3775 if (validation_texture_
) {
3776 glDeleteTextures(1, &validation_texture_
);
3777 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3778 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3781 if (offscreen_target_frame_buffer_
.get())
3782 offscreen_target_frame_buffer_
->Destroy();
3783 if (offscreen_target_color_texture_
.get())
3784 offscreen_target_color_texture_
->Destroy();
3785 if (offscreen_target_color_render_buffer_
.get())
3786 offscreen_target_color_render_buffer_
->Destroy();
3787 if (offscreen_target_depth_render_buffer_
.get())
3788 offscreen_target_depth_render_buffer_
->Destroy();
3789 if (offscreen_target_stencil_render_buffer_
.get())
3790 offscreen_target_stencil_render_buffer_
->Destroy();
3791 if (offscreen_saved_frame_buffer_
.get())
3792 offscreen_saved_frame_buffer_
->Destroy();
3793 if (offscreen_saved_color_texture_
.get())
3794 offscreen_saved_color_texture_
->Destroy();
3795 if (offscreen_resolved_frame_buffer_
.get())
3796 offscreen_resolved_frame_buffer_
->Destroy();
3797 if (offscreen_resolved_color_texture_
.get())
3798 offscreen_resolved_color_texture_
->Destroy();
3800 if (offscreen_target_frame_buffer_
.get())
3801 offscreen_target_frame_buffer_
->Invalidate();
3802 if (offscreen_target_color_texture_
.get())
3803 offscreen_target_color_texture_
->Invalidate();
3804 if (offscreen_target_color_render_buffer_
.get())
3805 offscreen_target_color_render_buffer_
->Invalidate();
3806 if (offscreen_target_depth_render_buffer_
.get())
3807 offscreen_target_depth_render_buffer_
->Invalidate();
3808 if (offscreen_target_stencil_render_buffer_
.get())
3809 offscreen_target_stencil_render_buffer_
->Invalidate();
3810 if (offscreen_saved_frame_buffer_
.get())
3811 offscreen_saved_frame_buffer_
->Invalidate();
3812 if (offscreen_saved_color_texture_
.get())
3813 offscreen_saved_color_texture_
->Invalidate();
3814 if (offscreen_resolved_frame_buffer_
.get())
3815 offscreen_resolved_frame_buffer_
->Invalidate();
3816 if (offscreen_resolved_color_texture_
.get())
3817 offscreen_resolved_color_texture_
->Invalidate();
3820 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3821 // Otherwise, we can leak objects. http://crbug.com/258772.
3822 // state_.current_program must be reset before group_ is reset because
3823 // the later deletes the ProgramManager object that referred by
3824 // state_.current_program object.
3825 state_
.current_program
= NULL
;
3827 copy_texture_CHROMIUM_
.reset();
3828 clear_framebuffer_blit_
.reset();
3830 if (query_manager_
.get()) {
3831 query_manager_
->Destroy(have_context
);
3832 query_manager_
.reset();
3835 if (vertex_array_manager_
.get()) {
3836 vertex_array_manager_
->Destroy(have_context
);
3837 vertex_array_manager_
.reset();
3840 if (image_manager_
.get()) {
3841 image_manager_
->Destroy(have_context
);
3842 image_manager_
.reset();
3845 offscreen_target_frame_buffer_
.reset();
3846 offscreen_target_color_texture_
.reset();
3847 offscreen_target_color_render_buffer_
.reset();
3848 offscreen_target_depth_render_buffer_
.reset();
3849 offscreen_target_stencil_render_buffer_
.reset();
3850 offscreen_saved_frame_buffer_
.reset();
3851 offscreen_saved_color_texture_
.reset();
3852 offscreen_resolved_frame_buffer_
.reset();
3853 offscreen_resolved_color_texture_
.reset();
3855 // Need to release these before releasing |group_| which may own the
3856 // ShaderTranslatorCache.
3857 fragment_translator_
= NULL
;
3858 vertex_translator_
= NULL
;
3860 // Should destroy the transfer manager before the texture manager held
3861 // by the context group.
3862 async_pixel_transfer_manager_
.reset();
3864 // Destroy the GPU Tracer which may own some in process GPU Timings.
3866 gpu_tracer_
->Destroy(have_context
);
3867 gpu_tracer_
.reset();
3871 framebuffer_manager()->RemoveObserver(this);
3872 group_
->Destroy(this, have_context
);
3876 if (context_
.get()) {
3877 context_
->ReleaseCurrent(NULL
);
3881 #if defined(OS_MACOSX)
3882 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3883 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3884 CFRelease(it
->second
);
3886 texture_to_io_surface_map_
.clear();
3890 void GLES2DecoderImpl::SetSurface(
3891 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3892 DCHECK(context_
->IsCurrent(NULL
));
3893 DCHECK(surface_
.get());
3895 RestoreCurrentFramebufferBindings();
3898 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3899 if (!offscreen_saved_color_texture_
.get()) {
3900 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3903 if (!offscreen_saved_color_texture_info_
.get()) {
3904 GLuint service_id
= offscreen_saved_color_texture_
->id();
3905 offscreen_saved_color_texture_info_
= TextureRef::Create(
3906 texture_manager(), 0, service_id
);
3907 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3909 UpdateParentTextureInfo();
3911 mailbox_manager()->ProduceTexture(
3912 mailbox
, offscreen_saved_color_texture_info_
->texture());
3915 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3916 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3917 if (!is_offscreen
) {
3918 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3919 << " with an onscreen framebuffer.";
3923 if (offscreen_size_
== size
)
3926 offscreen_size_
= size
;
3927 int w
= offscreen_size_
.width();
3928 int h
= offscreen_size_
.height();
3929 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3930 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3931 << "to allocate storage due to excessive dimensions.";
3935 // Reallocate the offscreen target buffers.
3936 DCHECK(offscreen_target_color_format_
);
3937 if (IsOffscreenBufferMultisampled()) {
3938 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3939 feature_info_
.get(),
3941 offscreen_target_color_format_
,
3942 offscreen_target_samples_
)) {
3943 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3944 << "to allocate storage for offscreen target color buffer.";
3948 if (!offscreen_target_color_texture_
->AllocateStorage(
3949 offscreen_size_
, offscreen_target_color_format_
, false)) {
3950 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3951 << "to allocate storage for offscreen target color texture.";
3955 if (offscreen_target_depth_format_
&&
3956 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3957 feature_info_
.get(),
3959 offscreen_target_depth_format_
,
3960 offscreen_target_samples_
)) {
3961 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3962 << "to allocate storage for offscreen target depth buffer.";
3965 if (offscreen_target_stencil_format_
&&
3966 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3967 feature_info_
.get(),
3969 offscreen_target_stencil_format_
,
3970 offscreen_target_samples_
)) {
3971 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3972 << "to allocate storage for offscreen target stencil buffer.";
3976 // Attach the offscreen target buffers to the target frame buffer.
3977 if (IsOffscreenBufferMultisampled()) {
3978 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3979 GL_COLOR_ATTACHMENT0
,
3980 offscreen_target_color_render_buffer_
.get());
3982 offscreen_target_frame_buffer_
->AttachRenderTexture(
3983 offscreen_target_color_texture_
.get());
3985 if (offscreen_target_depth_format_
) {
3986 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3987 GL_DEPTH_ATTACHMENT
,
3988 offscreen_target_depth_render_buffer_
.get());
3990 const bool packed_depth_stencil
=
3991 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3992 if (packed_depth_stencil
) {
3993 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3994 GL_STENCIL_ATTACHMENT
,
3995 offscreen_target_depth_render_buffer_
.get());
3996 } else if (offscreen_target_stencil_format_
) {
3997 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3998 GL_STENCIL_ATTACHMENT
,
3999 offscreen_target_stencil_render_buffer_
.get());
4002 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4003 GL_FRAMEBUFFER_COMPLETE
) {
4004 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4005 << "because offscreen FBO was incomplete.";
4009 // Clear the target frame buffer.
4011 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4012 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4013 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4014 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4016 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4017 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4019 state_
.SetDeviceDepthMask(GL_TRUE
);
4020 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4021 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4022 RestoreClearState();
4025 // Destroy the offscreen resolved framebuffers.
4026 if (offscreen_resolved_frame_buffer_
.get())
4027 offscreen_resolved_frame_buffer_
->Destroy();
4028 if (offscreen_resolved_color_texture_
.get())
4029 offscreen_resolved_color_texture_
->Destroy();
4030 offscreen_resolved_color_texture_
.reset();
4031 offscreen_resolved_frame_buffer_
.reset();
4036 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4037 const void* cmd_data
) {
4038 const gles2::cmds::ResizeCHROMIUM
& c
=
4039 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4040 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4041 return error::kDeferCommandUntilLater
;
4043 GLuint width
= static_cast<GLuint
>(c
.width
);
4044 GLuint height
= static_cast<GLuint
>(c
.height
);
4045 GLfloat scale_factor
= c
.scale_factor
;
4046 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4048 width
= std::max(1U, width
);
4049 height
= std::max(1U, height
);
4051 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4052 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4053 // Make sure that we are done drawing to the back buffer before resizing.
4056 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4058 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4059 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4060 << "ResizeOffscreenFrameBuffer failed.";
4061 return error::kLostContext
;
4065 if (!resize_callback_
.is_null()) {
4066 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4067 DCHECK(context_
->IsCurrent(surface_
.get()));
4068 if (!context_
->IsCurrent(surface_
.get())) {
4069 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4070 << "current after resize callback.";
4071 return error::kLostContext
;
4075 return error::kNoError
;
4078 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4079 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4080 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4082 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4085 // Decode a command, and call the corresponding GL functions.
4086 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4087 // of commands at once, and is now only used for tests that need to track
4088 // individual commands.
4089 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4090 unsigned int arg_count
,
4091 const void* cmd_data
) {
4092 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4095 // Decode multiple commands, and call the corresponding GL functions.
4096 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4097 // changed by a (malicious) client at any time, so if validation has to happen,
4098 // it should operate on a copy of them.
4099 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4100 // interest of performance in this critical execution loop.
4101 template <bool DebugImpl
>
4102 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4105 int* entries_processed
) {
4106 commands_to_process_
= num_commands
;
4107 error::Error result
= error::kNoError
;
4108 const CommandBufferEntry
* cmd_data
=
4109 static_cast<const CommandBufferEntry
*>(buffer
);
4110 int process_pos
= 0;
4111 unsigned int command
= 0;
4113 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4114 commands_to_process_
--) {
4115 const unsigned int size
= cmd_data
->value_header
.size
;
4116 command
= cmd_data
->value_header
.command
;
4119 result
= error::kInvalidSize
;
4123 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4124 result
= error::kOutOfBounds
;
4129 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4130 GetCommandName(command
));
4132 if (log_commands()) {
4133 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4134 << "cmd: " << GetCommandName(command
);
4138 const unsigned int arg_count
= size
- 1;
4139 unsigned int command_index
= command
- kStartPoint
- 1;
4140 if (command_index
< arraysize(command_info
)) {
4141 const CommandInfo
& info
= command_info
[command_index
];
4142 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4143 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4144 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4145 bool doing_gpu_trace
= false;
4146 if (DebugImpl
&& gpu_trace_commands_
) {
4147 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4148 doing_gpu_trace
= true;
4149 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4150 GetCommandName(command
),
4155 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4156 sizeof(CommandBufferEntry
); // NOLINT
4158 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4160 if (DebugImpl
&& doing_gpu_trace
)
4161 gpu_tracer_
->End(kTraceDecoder
);
4163 if (DebugImpl
&& debug()) {
4165 while ((error
= glGetError()) != GL_NO_ERROR
) {
4166 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4167 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4168 << " : " << GetCommandName(command
);
4169 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4173 result
= error::kInvalidArguments
;
4176 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4180 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4181 GetCommandName(command
));
4184 if (result
== error::kNoError
&&
4185 current_decoder_error_
!= error::kNoError
) {
4186 result
= current_decoder_error_
;
4187 current_decoder_error_
= error::kNoError
;
4190 if (result
!= error::kDeferCommandUntilLater
) {
4191 process_pos
+= size
;
4196 if (entries_processed
)
4197 *entries_processed
= process_pos
;
4199 if (error::IsError(result
)) {
4200 LOG(ERROR
) << "Error: " << result
<< " for Command "
4201 << GetCommandName(command
);
4207 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4210 int* entries_processed
) {
4211 if (gpu_debug_commands_
) {
4212 return DoCommandsImpl
<true>(
4213 num_commands
, buffer
, num_entries
, entries_processed
);
4215 return DoCommandsImpl
<false>(
4216 num_commands
, buffer
, num_entries
, entries_processed
);
4220 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4221 buffer_manager()->RemoveBuffer(client_id
);
4224 void GLES2DecoderImpl::DoFinish() {
4226 ProcessPendingReadPixels();
4227 ProcessPendingQueries(true);
4230 void GLES2DecoderImpl::DoFlush() {
4232 ProcessPendingQueries(false);
4235 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4236 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4237 if (texture_index
>= state_
.texture_units
.size()) {
4238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4239 "glActiveTexture", texture_unit
, "texture_unit");
4242 state_
.active_texture_unit
= texture_index
;
4243 glActiveTexture(texture_unit
);
4246 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4247 Buffer
* buffer
= NULL
;
4248 GLuint service_id
= 0;
4249 if (client_id
!= 0) {
4250 buffer
= GetBuffer(client_id
);
4252 if (!group_
->bind_generates_resource()) {
4253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4255 "id not generated by glGenBuffers");
4259 // It's a new id so make a buffer buffer for it.
4260 glGenBuffersARB(1, &service_id
);
4261 CreateBuffer(client_id
, service_id
);
4262 buffer
= GetBuffer(client_id
);
4265 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4267 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4269 GL_INVALID_OPERATION
,
4270 "glBindBuffer", "buffer bound to more than 1 target");
4273 service_id
= buffer
->service_id();
4276 case GL_ARRAY_BUFFER
:
4277 state_
.bound_array_buffer
= buffer
;
4279 case GL_ELEMENT_ARRAY_BUFFER
:
4280 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
4283 NOTREACHED(); // Validation should prevent us getting here.
4286 glBindBuffer(target
, service_id
);
4289 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4290 bool all_draw_buffers
) {
4291 Framebuffer
* framebuffer
=
4292 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4293 if (!all_draw_buffers
|| !framebuffer
) {
4294 return (GLES2Util::GetChannelsForFormat(
4295 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4297 return framebuffer
->HasAlphaMRT();
4300 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4301 Framebuffer
* framebuffer
=
4302 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4304 return framebuffer
->HasDepthAttachment();
4306 if (offscreen_target_frame_buffer_
.get()) {
4307 return offscreen_target_depth_format_
!= 0;
4309 return back_buffer_has_depth_
;
4312 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4313 Framebuffer
* framebuffer
=
4314 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4316 return framebuffer
->HasStencilAttachment();
4318 if (offscreen_target_frame_buffer_
.get()) {
4319 return offscreen_target_stencil_format_
!= 0 ||
4320 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4322 return back_buffer_has_stencil_
;
4325 void GLES2DecoderImpl::ApplyDirtyState() {
4326 if (framebuffer_state_
.clear_state_dirty
) {
4327 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4328 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4329 state_
.color_mask_green
,
4330 state_
.color_mask_blue
,
4331 state_
.color_mask_alpha
&& have_alpha
);
4333 bool have_depth
= BoundFramebufferHasDepthAttachment();
4334 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4336 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4337 state_
.SetDeviceStencilMaskSeparate(
4338 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4339 state_
.SetDeviceStencilMaskSeparate(
4340 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4342 state_
.SetDeviceCapabilityState(
4343 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4344 state_
.SetDeviceCapabilityState(
4345 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4346 framebuffer_state_
.clear_state_dirty
= false;
4350 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4351 return (offscreen_target_frame_buffer_
.get())
4352 ? offscreen_target_frame_buffer_
->id()
4353 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4356 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4357 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4358 "context", logger_
.GetLogPrefix());
4359 // Restore the Framebuffer first because of bugs in Intel drivers.
4360 // Intel drivers incorrectly clip the viewport settings to
4361 // the size of the current framebuffer object.
4362 RestoreFramebufferBindings();
4363 state_
.RestoreState(prev_state
);
4366 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4368 framebuffer_state_
.bound_draw_framebuffer
.get()
4369 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4370 : GetBackbufferServiceId();
4371 if (!features().chromium_framebuffer_multisample
) {
4372 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4374 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4375 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4376 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4377 : GetBackbufferServiceId();
4378 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4383 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4384 state_
.RestoreRenderbufferBindings();
4387 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4388 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4390 GLenum target
= texture
->target();
4391 glBindTexture(target
, service_id
);
4393 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4395 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4397 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4399 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4400 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4404 void GLES2DecoderImpl::ClearAllAttributes() const {
4405 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4407 if (feature_info_
->feature_flags().native_vertex_array_object
)
4408 glBindVertexArrayOES(0);
4410 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4411 if (i
!= 0) // Never disable attribute 0
4412 glDisableVertexAttribArray(i
);
4413 if (features().angle_instanced_arrays
)
4414 glVertexAttribDivisorANGLE(i
, 0);
4418 void GLES2DecoderImpl::RestoreAllAttributes() const {
4419 state_
.RestoreVertexAttribs();
4422 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4423 state_
.SetIgnoreCachedStateForTest(ignore
);
4426 void GLES2DecoderImpl::OnFboChanged() const {
4427 if (workarounds().restore_scissor_on_fbo_change
)
4428 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4430 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4431 GLint bound_fbo_unsigned
= -1;
4432 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4433 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4434 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4435 surface_
->NotifyWasBound();
4439 // Called after the FBO is checked for completeness.
4440 void GLES2DecoderImpl::OnUseFramebuffer() const {
4441 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4442 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4443 // The driver forgets the correct scissor when modifying the FBO binding.
4444 glScissor(state_
.scissor_x
,
4446 state_
.scissor_width
,
4447 state_
.scissor_height
);
4449 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4450 // it's unclear how this bug works.
4455 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4456 Framebuffer
* framebuffer
= NULL
;
4457 GLuint service_id
= 0;
4458 if (client_id
!= 0) {
4459 framebuffer
= GetFramebuffer(client_id
);
4461 if (!group_
->bind_generates_resource()) {
4462 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4463 "glBindFramebuffer",
4464 "id not generated by glGenFramebuffers");
4468 // It's a new id so make a framebuffer framebuffer for it.
4469 glGenFramebuffersEXT(1, &service_id
);
4470 CreateFramebuffer(client_id
, service_id
);
4471 framebuffer
= GetFramebuffer(client_id
);
4473 service_id
= framebuffer
->service_id();
4475 framebuffer
->MarkAsValid();
4477 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4479 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4480 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4483 // vmiura: This looks like dup code
4484 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4485 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4488 framebuffer_state_
.clear_state_dirty
= true;
4490 // If we are rendering to the backbuffer get the FBO id for any simulated
4492 if (framebuffer
== NULL
) {
4493 service_id
= GetBackbufferServiceId();
4496 glBindFramebufferEXT(target
, service_id
);
4500 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4501 Renderbuffer
* renderbuffer
= NULL
;
4502 GLuint service_id
= 0;
4503 if (client_id
!= 0) {
4504 renderbuffer
= GetRenderbuffer(client_id
);
4505 if (!renderbuffer
) {
4506 if (!group_
->bind_generates_resource()) {
4507 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4508 "glBindRenderbuffer",
4509 "id not generated by glGenRenderbuffers");
4513 // It's a new id so make a renderbuffer for it.
4514 glGenRenderbuffersEXT(1, &service_id
);
4515 CreateRenderbuffer(client_id
, service_id
);
4516 renderbuffer
= GetRenderbuffer(client_id
);
4518 service_id
= renderbuffer
->service_id();
4520 renderbuffer
->MarkAsValid();
4522 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4523 state_
.bound_renderbuffer
= renderbuffer
;
4524 state_
.bound_renderbuffer_valid
= true;
4525 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4528 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4529 TextureRef
* texture_ref
= NULL
;
4530 GLuint service_id
= 0;
4531 if (client_id
!= 0) {
4532 texture_ref
= GetTexture(client_id
);
4534 if (!group_
->bind_generates_resource()) {
4535 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4537 "id not generated by glGenTextures");
4541 // It's a new id so make a texture texture for it.
4542 glGenTextures(1, &service_id
);
4543 DCHECK_NE(0u, service_id
);
4544 CreateTexture(client_id
, service_id
);
4545 texture_ref
= GetTexture(client_id
);
4548 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4551 // Check the texture exists
4553 Texture
* texture
= texture_ref
->texture();
4554 // Check that we are not trying to bind it to a different target.
4555 if (texture
->target() != 0 && texture
->target() != target
) {
4556 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4558 "texture bound to more than 1 target.");
4561 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4562 if (texture
->target() == 0) {
4563 texture_manager()->SetTarget(texture_ref
, target
);
4565 glBindTexture(target
, texture
->service_id());
4567 glBindTexture(target
, 0);
4570 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4571 unit
.bind_target
= target
;
4574 unit
.bound_texture_2d
= texture_ref
;
4576 case GL_TEXTURE_CUBE_MAP
:
4577 unit
.bound_texture_cube_map
= texture_ref
;
4579 case GL_TEXTURE_EXTERNAL_OES
:
4580 unit
.bound_texture_external_oes
= texture_ref
;
4582 case GL_TEXTURE_RECTANGLE_ARB
:
4583 unit
.bound_texture_rectangle_arb
= texture_ref
;
4586 unit
.bound_texture_3d
= texture_ref
;
4588 case GL_TEXTURE_2D_ARRAY
:
4589 unit
.bound_texture_2d_array
= texture_ref
;
4592 NOTREACHED(); // Validation should prevent us getting here.
4597 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4598 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4600 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4601 glDisableVertexAttribArray(index
);
4606 "glDisableVertexAttribArray", "index out of range");
4610 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4611 GLsizei numAttachments
,
4612 const GLenum
* attachments
) {
4613 if (workarounds().disable_discard_framebuffer
)
4616 Framebuffer
* framebuffer
=
4617 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4619 // Validates the attachments. If one of them fails
4620 // the whole command fails.
4621 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4623 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4625 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4626 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4627 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4632 // Marks each one of them as not cleared
4633 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4635 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4640 switch (attachments
[i
]) {
4642 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4645 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4646 case GL_STENCIL_EXT
:
4647 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4656 // If the default framebuffer is bound but we are still rendering to an
4657 // FBO, translate attachment names that refer to default framebuffer
4658 // channels to corresponding framebuffer attachments.
4659 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4660 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4661 GLenum attachment
= attachments
[i
];
4662 if (!framebuffer
&& GetBackbufferServiceId()) {
4663 switch (attachment
) {
4665 attachment
= GL_COLOR_ATTACHMENT0
;
4668 attachment
= GL_DEPTH_ATTACHMENT
;
4670 case GL_STENCIL_EXT
:
4671 attachment
= GL_STENCIL_ATTACHMENT
;
4678 translated_attachments
[i
] = attachment
;
4681 ScopedRenderTo
do_render(framebuffer
);
4682 if (feature_info_
->gl_version_info().is_es3
) {
4683 glInvalidateFramebuffer(
4684 target
, numAttachments
, translated_attachments
.get());
4686 glDiscardFramebufferEXT(
4687 target
, numAttachments
, translated_attachments
.get());
4691 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4692 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4693 glEnableVertexAttribArray(index
);
4696 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4700 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4701 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4704 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4706 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4710 if (target
== GL_TEXTURE_CUBE_MAP
) {
4711 for (int i
= 0; i
< 6; ++i
) {
4712 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4713 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4715 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4720 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4722 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4727 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4728 // Workaround for Mac driver bug. In the large scheme of things setting
4729 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4730 // hit so there's probably no need to make this conditional. The bug appears
4731 // to be that if the filtering mode is set to something that doesn't require
4732 // mipmaps for rendering, or is never set to something other than the default,
4733 // then glGenerateMipmap misbehaves.
4734 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4735 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4737 glGenerateMipmapEXT(target
);
4738 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4739 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4740 texture_ref
->texture()->min_filter());
4742 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4743 if (error
== GL_NO_ERROR
) {
4744 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4748 bool GLES2DecoderImpl::GetHelper(
4749 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4750 DCHECK(num_written
);
4751 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4753 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4755 // Return the GL implementation's preferred format and (see below type)
4756 // if we have the GL extension that exposes this. This allows the GPU
4757 // client to use the implementation's preferred format for glReadPixels
4758 // for optimisation.
4760 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4761 // case when requested on integer/floating point buffers but which is
4762 // acceptable on GLES2 and with the GL_OES_read_format extension.
4764 // Therefore if an error occurs we swallow the error and use the
4765 // internal implementation.
4767 if (context_
->HasExtension("GL_OES_read_format")) {
4768 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4770 glGetIntegerv(pname
, params
);
4771 if (glGetError() == GL_NO_ERROR
)
4774 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4775 GetBoundReadFrameBufferInternalFormat());
4778 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4781 if (context_
->HasExtension("GL_OES_read_format")) {
4782 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4784 glGetIntegerv(pname
, params
);
4785 if (glGetError() == GL_NO_ERROR
)
4788 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4789 GetBoundReadFrameBufferInternalFormat(),
4790 GetBoundReadFrameBufferTextureType());
4793 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4796 *params
= group_
->max_fragment_uniform_vectors();
4799 case GL_MAX_VARYING_VECTORS
:
4802 *params
= group_
->max_varying_vectors();
4805 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4808 *params
= group_
->max_vertex_uniform_vectors();
4814 case GL_MAX_VIEWPORT_DIMS
:
4815 if (offscreen_target_frame_buffer_
.get()) {
4818 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4819 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4824 case GL_MAX_SAMPLES
:
4827 params
[0] = renderbuffer_manager()->max_samples();
4830 case GL_MAX_RENDERBUFFER_SIZE
:
4833 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4836 case GL_MAX_TEXTURE_SIZE
:
4839 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4842 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4845 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4848 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4851 params
[0] = group_
->max_color_attachments();
4854 case GL_MAX_DRAW_BUFFERS_ARB
:
4857 params
[0] = group_
->max_draw_buffers();
4864 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4865 Framebuffer
* framebuffer
=
4866 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4868 glGetFramebufferAttachmentParameterivEXT(
4869 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
4870 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
4872 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
4875 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4878 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4885 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4886 Framebuffer
* framebuffer
=
4887 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4889 glGetFramebufferAttachmentParameterivEXT(
4890 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
4891 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
4893 v
= (back_buffer_has_depth_
? 24 : 0);
4896 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4898 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4907 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4908 Framebuffer
* framebuffer
=
4909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4911 GLenum framebuffer_enum
= 0;
4914 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
4917 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
4920 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
4923 glGetFramebufferAttachmentParameterivEXT(
4924 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
4929 glGetIntegerv(pname
, &v
);
4934 case GL_STENCIL_BITS
:
4938 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4939 Framebuffer
* framebuffer
=
4940 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4942 glGetFramebufferAttachmentParameterivEXT(
4943 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
4944 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
4946 v
= (back_buffer_has_stencil_
? 8 : 0);
4949 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4951 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4954 case GL_COMPRESSED_TEXTURE_FORMATS
:
4955 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4957 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4958 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4962 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4965 *params
= validators_
->compressed_texture_format
.GetValues().size();
4968 case GL_NUM_SHADER_BINARY_FORMATS
:
4971 *params
= validators_
->shader_binary_format
.GetValues().size();
4974 case GL_SHADER_BINARY_FORMATS
:
4975 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4977 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4978 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4982 case GL_SHADER_COMPILER
:
4988 case GL_ARRAY_BUFFER_BINDING
:
4991 if (state_
.bound_array_buffer
.get()) {
4992 GLuint client_id
= 0;
4993 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4995 *params
= client_id
;
5001 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5004 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
5005 GLuint client_id
= 0;
5006 buffer_manager()->GetClientId(
5007 state_
.vertex_attrib_manager
->element_array_buffer()->
5008 service_id(), &client_id
);
5009 *params
= client_id
;
5015 case GL_FRAMEBUFFER_BINDING
:
5016 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5019 Framebuffer
* framebuffer
=
5020 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5022 GLuint client_id
= 0;
5023 framebuffer_manager()->GetClientId(
5024 framebuffer
->service_id(), &client_id
);
5025 *params
= client_id
;
5031 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5034 Framebuffer
* framebuffer
=
5035 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
5037 GLuint client_id
= 0;
5038 framebuffer_manager()->GetClientId(
5039 framebuffer
->service_id(), &client_id
);
5040 *params
= client_id
;
5046 case GL_RENDERBUFFER_BINDING
:
5049 Renderbuffer
* renderbuffer
=
5050 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5052 *params
= renderbuffer
->client_id();
5058 case GL_CURRENT_PROGRAM
:
5061 if (state_
.current_program
.get()) {
5062 GLuint client_id
= 0;
5063 program_manager()->GetClientId(
5064 state_
.current_program
->service_id(), &client_id
);
5065 *params
= client_id
;
5071 case GL_VERTEX_ARRAY_BINDING_OES
:
5074 if (state_
.vertex_attrib_manager
.get() !=
5075 state_
.default_vertex_attrib_manager
.get()) {
5076 GLuint client_id
= 0;
5077 vertex_array_manager_
->GetClientId(
5078 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5079 *params
= client_id
;
5085 case GL_TEXTURE_BINDING_2D
:
5088 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5089 if (unit
.bound_texture_2d
.get()) {
5090 *params
= unit
.bound_texture_2d
->client_id();
5096 case GL_TEXTURE_BINDING_CUBE_MAP
:
5099 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5100 if (unit
.bound_texture_cube_map
.get()) {
5101 *params
= unit
.bound_texture_cube_map
->client_id();
5107 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5110 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5111 if (unit
.bound_texture_external_oes
.get()) {
5112 *params
= unit
.bound_texture_external_oes
->client_id();
5118 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5121 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5122 if (unit
.bound_texture_rectangle_arb
.get()) {
5123 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5129 case GL_UNPACK_FLIP_Y_CHROMIUM
:
5132 params
[0] = unpack_flip_y_
;
5135 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
5138 params
[0] = unpack_premultiply_alpha_
;
5141 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
5144 params
[0] = unpack_unpremultiply_alpha_
;
5147 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5150 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5154 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5155 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5158 Framebuffer
* framebuffer
=
5159 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5161 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5162 } else { // backbuffer
5163 if (pname
== GL_DRAW_BUFFER0_ARB
)
5164 params
[0] = group_
->draw_buffer();
5166 params
[0] = GL_NONE
;
5171 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5176 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5177 GLenum pname
, GLsizei
* num_values
) {
5178 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5181 return GetHelper(pname
, NULL
, num_values
);
5184 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5185 if (GL_MAX_SAMPLES
== pname
&&
5186 features().use_img_for_multisampled_render_to_texture
) {
5187 return GL_MAX_SAMPLES_IMG
;
5192 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5194 GLsizei num_written
= 0;
5195 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5196 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5197 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5198 GetHelper(pname
, values
.get(), &num_written
);
5200 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5201 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5204 pname
= AdjustGetPname(pname
);
5205 glGetBooleanv(pname
, params
);
5209 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5211 GLsizei num_written
= 0;
5212 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5213 if (GetHelper(pname
, NULL
, &num_written
)) {
5214 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5215 GetHelper(pname
, values
.get(), &num_written
);
5216 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5217 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5220 pname
= AdjustGetPname(pname
);
5221 glGetFloatv(pname
, params
);
5226 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5228 pname
= AdjustGetPname(pname
);
5229 glGetInteger64v(pname
, params
);
5232 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5234 GLsizei num_written
;
5235 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5236 !GetHelper(pname
, params
, &num_written
)) {
5237 pname
= AdjustGetPname(pname
);
5238 glGetIntegerv(pname
, params
);
5242 void GLES2DecoderImpl::DoGetProgramiv(
5243 GLuint program_id
, GLenum pname
, GLint
* params
) {
5244 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5248 program
->GetProgramiv(pname
, params
);
5251 void GLES2DecoderImpl::DoGetBufferParameteriv(
5252 GLenum target
, GLenum pname
, GLint
* params
) {
5253 // Just delegate it. Some validation is actually done before this.
5254 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5255 &state_
, target
, pname
, params
);
5258 void GLES2DecoderImpl::DoBindAttribLocation(
5259 GLuint program_id
, GLuint index
, const char* name
) {
5260 if (!StringIsValidForGLES(name
)) {
5262 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5265 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5267 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5270 if (index
>= group_
->max_vertex_attribs()) {
5272 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5275 Program
* program
= GetProgramInfoNotShader(
5276 program_id
, "glBindAttribLocation");
5280 // At this point, the program's shaders may not be translated yet,
5281 // therefore, we may not find the hashed attribute name.
5282 // glBindAttribLocation call with original name is useless.
5283 // So instead, we should simply cache the binding, and then call
5284 // Program::ExecuteBindAttribLocationCalls() right before link.
5285 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5286 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5287 glBindAttribLocation(program
->service_id(), index
, name
);
5290 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5291 uint32 immediate_data_size
,
5292 const void* cmd_data
) {
5293 const gles2::cmds::BindAttribLocationBucket
& c
=
5294 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5295 GLuint program
= static_cast<GLuint
>(c
.program
);
5296 GLuint index
= static_cast<GLuint
>(c
.index
);
5297 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5298 if (!bucket
|| bucket
->size() == 0) {
5299 return error::kInvalidArguments
;
5301 std::string name_str
;
5302 if (!bucket
->GetAsString(&name_str
)) {
5303 return error::kInvalidArguments
;
5305 DoBindAttribLocation(program
, index
, name_str
.c_str());
5306 return error::kNoError
;
5309 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5310 GLuint program_id
, GLint location
, const char* name
) {
5311 if (!StringIsValidForGLES(name
)) {
5314 "glBindUniformLocationCHROMIUM", "Invalid character");
5317 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5319 GL_INVALID_OPERATION
,
5320 "glBindUniformLocationCHROMIUM", "reserved prefix");
5323 if (location
< 0 || static_cast<uint32
>(location
) >=
5324 (group_
->max_fragment_uniform_vectors() +
5325 group_
->max_vertex_uniform_vectors()) * 4) {
5328 "glBindUniformLocationCHROMIUM", "location out of range");
5331 Program
* program
= GetProgramInfoNotShader(
5332 program_id
, "glBindUniformLocationCHROMIUM");
5336 if (!program
->SetUniformLocationBinding(name
, location
)) {
5339 "glBindUniformLocationCHROMIUM", "location out of range");
5343 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5344 uint32 immediate_data_size
,
5345 const void* cmd_data
) {
5346 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5347 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5349 GLuint program
= static_cast<GLuint
>(c
.program
);
5350 GLint location
= static_cast<GLint
>(c
.location
);
5351 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5352 if (!bucket
|| bucket
->size() == 0) {
5353 return error::kInvalidArguments
;
5355 std::string name_str
;
5356 if (!bucket
->GetAsString(&name_str
)) {
5357 return error::kInvalidArguments
;
5359 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5360 return error::kNoError
;
5363 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5364 const void* cmd_data
) {
5365 const gles2::cmds::DeleteShader
& c
=
5366 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5367 GLuint client_id
= c
.shader
;
5369 Shader
* shader
= GetShader(client_id
);
5371 if (!shader
->IsDeleted()) {
5372 shader_manager()->Delete(shader
);
5375 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5378 return error::kNoError
;
5381 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5382 const void* cmd_data
) {
5383 const gles2::cmds::DeleteProgram
& c
=
5384 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5385 GLuint client_id
= c
.program
;
5387 Program
* program
= GetProgram(client_id
);
5389 if (!program
->IsDeleted()) {
5390 program_manager()->MarkAsDeleted(shader_manager(), program
);
5394 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5397 return error::kNoError
;
5400 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5401 DCHECK(!ShouldDeferDraws());
5402 if (CheckBoundFramebuffersValid("glClear")) {
5404 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5405 if (workarounds().gl_clear_broken
) {
5406 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5408 if (!BoundFramebufferHasDepthAttachment())
5409 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5410 if (!BoundFramebufferHasStencilAttachment())
5411 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5412 clear_framebuffer_blit_
->ClearFramebuffer(
5413 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5414 state_
.color_clear_green
, state_
.color_clear_blue
,
5415 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5416 return error::kNoError
;
5420 return error::kNoError
;
5423 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5424 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5425 GLuint client_renderbuffer_id
) {
5426 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5429 GL_INVALID_OPERATION
,
5430 "glFramebufferRenderbuffer", "no framebuffer bound");
5433 GLuint service_id
= 0;
5434 Renderbuffer
* renderbuffer
= NULL
;
5435 if (client_renderbuffer_id
) {
5436 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5437 if (!renderbuffer
) {
5439 GL_INVALID_OPERATION
,
5440 "glFramebufferRenderbuffer", "unknown renderbuffer");
5443 service_id
= renderbuffer
->service_id();
5445 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5446 glFramebufferRenderbufferEXT(
5447 target
, attachment
, renderbuffertarget
, service_id
);
5448 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5449 if (error
== GL_NO_ERROR
) {
5450 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5452 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5453 framebuffer_state_
.clear_state_dirty
= true;
5458 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5459 if (SetCapabilityState(cap
, false)) {
5464 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5465 if (SetCapabilityState(cap
, true)) {
5470 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5471 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5472 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5473 glDepthRange(znear
, zfar
);
5476 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5477 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5478 state_
.sample_coverage_invert
= (invert
!= 0);
5479 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5482 // Assumes framebuffer is complete.
5483 void GLES2DecoderImpl::ClearUnclearedAttachments(
5484 GLenum target
, Framebuffer
* framebuffer
) {
5485 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5486 // bind this to the DRAW point, clear then bind back to READ
5487 // TODO(gman): I don't think there is any guarantee that an FBO that
5488 // is complete on the READ attachment will be complete as a DRAW
5490 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5491 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5493 GLbitfield clear_bits
= 0;
5494 if (framebuffer
->HasUnclearedColorAttachments()) {
5497 (GLES2Util::GetChannelsForFormat(
5498 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5500 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5501 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5502 if (feature_info_
->feature_flags().ext_draw_buffers
)
5503 framebuffer
->PrepareDrawBuffersForClear();
5506 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5507 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5509 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5510 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5511 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5514 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5515 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5517 state_
.SetDeviceDepthMask(GL_TRUE
);
5518 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5521 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5522 glClear(clear_bits
);
5524 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5525 feature_info_
->feature_flags().ext_draw_buffers
)
5526 framebuffer
->RestoreDrawBuffersAfterClear();
5528 framebuffer_manager()->MarkAttachmentsAsCleared(
5529 framebuffer
, renderbuffer_manager(), texture_manager());
5531 RestoreClearState();
5533 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5534 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5535 Framebuffer
* draw_framebuffer
=
5536 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5537 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5538 GetBackbufferServiceId();
5539 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5543 void GLES2DecoderImpl::RestoreClearState() {
5544 framebuffer_state_
.clear_state_dirty
= true;
5546 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5547 state_
.color_clear_alpha
);
5548 glClearStencil(state_
.stencil_clear
);
5549 glClearDepth(state_
.depth_clear
);
5550 if (state_
.enable_flags
.scissor_test
) {
5551 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5555 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5556 Framebuffer
* framebuffer
=
5557 GetFramebufferInfoForTarget(target
);
5559 return GL_FRAMEBUFFER_COMPLETE
;
5561 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5562 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5563 return completeness
;
5565 return framebuffer
->GetStatus(texture_manager(), target
);
5568 void GLES2DecoderImpl::DoFramebufferTexture2D(
5569 GLenum target
, GLenum attachment
, GLenum textarget
,
5570 GLuint client_texture_id
, GLint level
) {
5571 DoFramebufferTexture2DCommon(
5572 "glFramebufferTexture2D", target
, attachment
,
5573 textarget
, client_texture_id
, level
, 0);
5576 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5577 GLenum target
, GLenum attachment
, GLenum textarget
,
5578 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5579 DoFramebufferTexture2DCommon(
5580 "glFramebufferTexture2DMultisample", target
, attachment
,
5581 textarget
, client_texture_id
, level
, samples
);
5584 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5585 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5586 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5587 if (samples
> renderbuffer_manager()->max_samples()) {
5590 "glFramebufferTexture2DMultisample", "samples too large");
5593 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5596 GL_INVALID_OPERATION
,
5597 name
, "no framebuffer bound.");
5600 GLuint service_id
= 0;
5601 TextureRef
* texture_ref
= NULL
;
5602 if (client_texture_id
) {
5603 texture_ref
= GetTexture(client_texture_id
);
5606 GL_INVALID_OPERATION
,
5607 name
, "unknown texture_ref");
5610 service_id
= texture_ref
->service_id();
5613 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5616 name
, "level out of range");
5621 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5623 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5625 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5627 if (features().use_img_for_multisampled_render_to_texture
) {
5628 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5629 service_id
, level
, samples
);
5631 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5632 service_id
, level
, samples
);
5635 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5636 if (error
== GL_NO_ERROR
) {
5637 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5640 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5641 framebuffer_state_
.clear_state_dirty
= true;
5645 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5650 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5651 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5652 GLint level
, GLint layer
) {
5653 // TODO(zmo): Unsafe ES3 API, missing states update.
5654 GLuint service_id
= 0;
5655 TextureRef
* texture_ref
= NULL
;
5656 if (client_texture_id
) {
5657 texture_ref
= GetTexture(client_texture_id
);
5660 GL_INVALID_OPERATION
,
5661 "glFramebufferTextureLayer", "unknown texture_ref");
5664 service_id
= texture_ref
->service_id();
5666 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5669 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5670 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5671 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5674 GL_INVALID_OPERATION
,
5675 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5678 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5679 const Framebuffer::Attachment
* attachment_object
=
5680 framebuffer
->GetAttachment(attachment
);
5681 *params
= attachment_object
? attachment_object
->object_name() : 0;
5683 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5684 features().use_img_for_multisampled_render_to_texture
) {
5685 pname
= GL_TEXTURE_SAMPLES_IMG
;
5687 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5691 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5692 GLenum target
, GLenum pname
, GLint
* params
) {
5693 Renderbuffer
* renderbuffer
=
5694 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5695 if (!renderbuffer
) {
5697 GL_INVALID_OPERATION
,
5698 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5702 EnsureRenderbufferBound();
5704 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5705 *params
= renderbuffer
->internal_format();
5707 case GL_RENDERBUFFER_WIDTH
:
5708 *params
= renderbuffer
->width();
5710 case GL_RENDERBUFFER_HEIGHT
:
5711 *params
= renderbuffer
->height();
5713 case GL_RENDERBUFFER_SAMPLES_EXT
:
5714 if (features().use_img_for_multisampled_render_to_texture
) {
5715 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5718 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5722 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5727 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5728 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5729 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5730 GLbitfield mask
, GLenum filter
) {
5731 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5733 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5737 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5738 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5739 BlitFramebufferHelper(
5740 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5741 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5742 state_
.enable_flags
.scissor_test
);
5745 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5746 if (!state_
.bound_renderbuffer_valid
) {
5747 state_
.bound_renderbuffer_valid
= true;
5748 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5749 state_
.bound_renderbuffer
.get()
5750 ? state_
.bound_renderbuffer
->service_id()
5755 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5756 const FeatureInfo
* feature_info
,
5759 GLenum internal_format
,
5762 // TODO(sievers): This could be resolved at the GL binding level, but the
5763 // binding process is currently a bit too 'brute force'.
5764 if (feature_info
->gl_version_info().is_angle
) {
5765 glRenderbufferStorageMultisampleANGLE(
5766 target
, samples
, internal_format
, width
, height
);
5767 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5768 glRenderbufferStorageMultisample(
5769 target
, samples
, internal_format
, width
, height
);
5771 glRenderbufferStorageMultisampleEXT(
5772 target
, samples
, internal_format
, width
, height
);
5776 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5786 // TODO(sievers): This could be resolved at the GL binding level, but the
5787 // binding process is currently a bit too 'brute force'.
5788 if (feature_info_
->gl_version_info().is_angle
) {
5789 glBlitFramebufferANGLE(
5790 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5791 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5793 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5795 glBlitFramebufferEXT(
5796 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5800 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5802 GLenum internalformat
,
5805 if (samples
> renderbuffer_manager()->max_samples()) {
5808 "glRenderbufferStorageMultisample", "samples too large");
5812 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5813 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5816 "glRenderbufferStorageMultisample", "dimensions too large");
5820 uint32 estimated_size
= 0;
5821 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5822 width
, height
, samples
, internalformat
, &estimated_size
)) {
5825 "glRenderbufferStorageMultisample", "dimensions too large");
5829 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5832 "glRenderbufferStorageMultisample", "out of memory");
5839 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5840 GLenum target
, GLsizei samples
, GLenum internalformat
,
5841 GLsizei width
, GLsizei height
) {
5842 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5843 if (!renderbuffer
) {
5844 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5845 "glRenderbufferStorageMultisampleCHROMIUM",
5846 "no renderbuffer bound");
5850 if (!ValidateRenderbufferStorageMultisample(
5851 samples
, internalformat
, width
, height
)) {
5855 EnsureRenderbufferBound();
5856 GLenum impl_format
=
5857 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5859 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5860 "glRenderbufferStorageMultisampleCHROMIUM");
5861 RenderbufferStorageMultisampleHelper(
5862 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5864 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5865 if (error
== GL_NO_ERROR
) {
5866 if (workarounds().validate_multisample_buffer_allocation
) {
5867 if (!VerifyMultisampleRenderbufferIntegrity(
5868 renderbuffer
->service_id(), impl_format
)) {
5871 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5876 // TODO(gman): If renderbuffers tracked which framebuffers they were
5877 // attached to we could just mark those framebuffers as not complete.
5878 framebuffer_manager()->IncFramebufferStateChangeCount();
5879 renderbuffer_manager()->SetInfo(
5880 renderbuffer
, samples
, internalformat
, width
, height
);
5884 // This is the handler for multisampled_render_to_texture extensions.
5885 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5886 GLenum target
, GLsizei samples
, GLenum internalformat
,
5887 GLsizei width
, GLsizei height
) {
5888 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5889 if (!renderbuffer
) {
5890 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5891 "glRenderbufferStorageMultisampleEXT",
5892 "no renderbuffer bound");
5896 if (!ValidateRenderbufferStorageMultisample(
5897 samples
, internalformat
, width
, height
)) {
5901 EnsureRenderbufferBound();
5902 GLenum impl_format
=
5903 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5905 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5906 if (features().use_img_for_multisampled_render_to_texture
) {
5907 glRenderbufferStorageMultisampleIMG(
5908 target
, samples
, impl_format
, width
, height
);
5910 glRenderbufferStorageMultisampleEXT(
5911 target
, samples
, impl_format
, width
, height
);
5913 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5914 if (error
== GL_NO_ERROR
) {
5915 // TODO(gman): If renderbuffers tracked which framebuffers they were
5916 // attached to we could just mark those framebuffers as not complete.
5917 framebuffer_manager()->IncFramebufferStateChangeCount();
5918 renderbuffer_manager()->SetInfo(
5919 renderbuffer
, samples
, internalformat
, width
, height
);
5923 // This function validates the allocation of a multisampled renderbuffer
5924 // by clearing it to a key color, blitting the contents to a texture, and
5925 // reading back the color to ensure it matches the key.
5926 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5927 GLuint renderbuffer
, GLenum format
) {
5929 // Only validate color buffers.
5930 // These formats have been selected because they are very common or are known
5931 // to be used by the WebGL backbuffer. If problems are observed with other
5932 // color formats they can be added here.
5943 GLint draw_framebuffer
, read_framebuffer
;
5945 // Cache framebuffer and texture bindings.
5946 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5947 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5949 if (!validation_texture_
) {
5950 GLint bound_texture
;
5951 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5953 // Create additional resources needed for the verification.
5954 glGenTextures(1, &validation_texture_
);
5955 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5956 glGenFramebuffersEXT(1, &validation_fbo_
);
5958 // Texture only needs to be 1x1.
5959 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5960 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5961 GL_UNSIGNED_BYTE
, NULL
);
5963 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5964 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5965 GL_TEXTURE_2D
, validation_texture_
, 0);
5967 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5970 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5971 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5972 GL_RENDERBUFFER
, renderbuffer
);
5974 // Cache current state and reset it to the values we require.
5975 GLboolean scissor_enabled
= false;
5976 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5977 if (scissor_enabled
)
5978 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5980 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5981 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5982 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5984 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5985 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5986 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5988 // Clear the buffer to the desired key color.
5989 glClear(GL_COLOR_BUFFER_BIT
);
5991 // Blit from the multisample buffer to a standard texture.
5992 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5993 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5995 BlitFramebufferHelper(
5996 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5998 // Read a pixel from the buffer.
5999 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6001 unsigned char pixel
[3] = {0, 0, 0};
6002 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6004 // Detach the renderbuffer.
6005 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6006 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6007 GL_RENDERBUFFER
, 0);
6009 // Restore cached state.
6010 if (scissor_enabled
)
6011 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6013 state_
.SetDeviceColorMask(
6014 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6015 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6016 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6017 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6019 // Return true if the pixel matched the desired key color.
6020 return (pixel
[0] == 0xFF &&
6025 void GLES2DecoderImpl::DoRenderbufferStorage(
6026 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6027 Renderbuffer
* renderbuffer
=
6028 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6029 if (!renderbuffer
) {
6031 GL_INVALID_OPERATION
,
6032 "glRenderbufferStorage", "no renderbuffer bound");
6036 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6037 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6039 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6043 uint32 estimated_size
= 0;
6044 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6045 width
, height
, 1, internalformat
, &estimated_size
)) {
6047 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6051 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6053 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6057 EnsureRenderbufferBound();
6058 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6059 glRenderbufferStorageEXT(
6061 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6065 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6066 if (error
== GL_NO_ERROR
) {
6067 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6068 // we could just mark those framebuffers as not complete.
6069 framebuffer_manager()->IncFramebufferStateChangeCount();
6070 renderbuffer_manager()->SetInfo(
6071 renderbuffer
, 1, internalformat
, width
, height
);
6075 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6076 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6077 Program
* program
= GetProgramInfoNotShader(
6078 program_id
, "glLinkProgram");
6083 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6084 if (program
->Link(shader_manager(),
6085 workarounds().count_all_in_varyings_packing
?
6086 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6087 shader_cache_callback_
)) {
6088 if (program
== state_
.current_program
.get()) {
6089 if (workarounds().use_current_program_after_successful_link
)
6090 glUseProgram(program
->service_id());
6091 if (workarounds().clear_uniforms_before_first_program_use
)
6092 program_manager()->ClearUniforms(program
);
6096 // LinkProgram can be very slow. Exit command processing to allow for
6097 // context preemption and GPU watchdog checks.
6098 ExitCommandProcessingEarly();
6101 void GLES2DecoderImpl::DoSamplerParameterfv(
6102 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6104 glSamplerParameterf(sampler
, pname
, params
[0]);
6107 void GLES2DecoderImpl::DoSamplerParameteriv(
6108 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6110 glSamplerParameteri(sampler
, pname
, params
[0]);
6113 void GLES2DecoderImpl::DoTexParameterf(
6114 GLenum target
, GLenum pname
, GLfloat param
) {
6115 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6118 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6122 texture_manager()->SetParameterf(
6123 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6126 void GLES2DecoderImpl::DoTexParameteri(
6127 GLenum target
, GLenum pname
, GLint param
) {
6128 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6131 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6135 texture_manager()->SetParameteri(
6136 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6139 void GLES2DecoderImpl::DoTexParameterfv(
6140 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6141 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6144 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6148 texture_manager()->SetParameterf(
6149 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6152 void GLES2DecoderImpl::DoTexParameteriv(
6153 GLenum target
, GLenum pname
, const GLint
* params
) {
6154 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6158 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6162 texture_manager()->SetParameteri(
6163 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6166 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6167 if (!state_
.bound_valuebuffer
.get()) {
6168 // There is no valuebuffer bound
6169 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6170 "no valuebuffer in use");
6176 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6177 GLenum subscription
,
6178 const char* function_name
) {
6179 if (!CheckCurrentValuebuffer(function_name
)) {
6182 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6183 // The valuebuffer is not subscribed to the target
6184 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6185 "valuebuffer is not subscribed");
6191 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6192 GLenum subscription
,
6193 const char* function_name
) {
6194 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6197 GLint real_location
= -1;
6198 GLint array_index
= -1;
6199 const Program::UniformInfo
* info
=
6200 state_
.current_program
->GetUniformInfoByFakeLocation(
6201 location
, &real_location
, &array_index
);
6203 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6206 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6207 info
->accepts_api_type
) == 0) {
6208 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6209 "wrong type for subscription");
6215 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6216 if (!state_
.current_program
.get()) {
6217 // The program does not exist.
6219 GL_INVALID_OPERATION
, function_name
, "no program in use");
6222 if (!state_
.current_program
->InUse()) {
6224 GL_INVALID_OPERATION
, function_name
, "program not linked");
6230 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6231 GLint location
, const char* function_name
) {
6232 if (!CheckCurrentProgram(function_name
)) {
6235 return location
!= -1;
6238 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6239 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6242 const Framebuffer::Attachment
* attachment
=
6243 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6247 DCHECK(state_
.current_program
.get());
6248 const Program::SamplerIndices
& sampler_indices
=
6249 state_
.current_program
->sampler_indices();
6250 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6251 const Program::UniformInfo
* uniform_info
=
6252 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6253 DCHECK(uniform_info
);
6254 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6256 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6257 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6258 if (texture_unit_index
>= state_
.texture_units
.size())
6260 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6261 TextureRef
* texture_ref
=
6262 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6263 if (attachment
->IsTexture(texture_ref
))
6270 bool GLES2DecoderImpl::CheckUniformForApiType(
6271 const Program::UniformInfo
* info
,
6272 const char* function_name
,
6273 Program::UniformApiType api_type
) {
6275 if ((api_type
& info
->accepts_api_type
) == 0) {
6276 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6277 "wrong uniform function for type");
6283 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6284 GLint fake_location
,
6285 const char* function_name
,
6286 Program::UniformApiType api_type
,
6287 GLint
* real_location
,
6292 DCHECK(real_location
);
6294 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6297 GLint array_index
= -1;
6298 const Program::UniformInfo
* info
=
6299 state_
.current_program
->GetUniformInfoByFakeLocation(
6300 fake_location
, real_location
, &array_index
);
6303 GL_INVALID_OPERATION
, function_name
, "unknown location");
6306 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6309 if (*count
> 1 && !info
->is_array
) {
6311 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6314 *count
= std::min(info
->size
- array_index
, *count
);
6322 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6325 GLint real_location
= -1;
6326 if (!PrepForSetUniformByLocation(fake_location
,
6328 Program::kUniform1i
,
6334 if (!state_
.current_program
->SetSamplers(
6335 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6337 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6340 glUniform1i(real_location
, v0
);
6343 void GLES2DecoderImpl::DoUniform1iv(
6344 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6346 GLint real_location
= -1;
6347 if (!PrepForSetUniformByLocation(fake_location
,
6349 Program::kUniform1i
,
6355 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6356 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6357 if (!state_
.current_program
->SetSamplers(
6358 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6360 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6364 glUniform1iv(real_location
, count
, value
);
6367 void GLES2DecoderImpl::DoUniform1fv(
6368 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6370 GLint real_location
= -1;
6371 if (!PrepForSetUniformByLocation(fake_location
,
6373 Program::kUniform1f
,
6379 if (type
== GL_BOOL
) {
6380 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6381 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6382 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6384 DoUniform1iv(real_location
, count
, temp
.get());
6386 glUniform1fv(real_location
, count
, value
);
6390 void GLES2DecoderImpl::DoUniform2fv(
6391 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6393 GLint real_location
= -1;
6394 if (!PrepForSetUniformByLocation(fake_location
,
6396 Program::kUniform2f
,
6402 if (type
== GL_BOOL_VEC2
) {
6403 GLsizei num_values
= count
* 2;
6404 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6405 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6406 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6408 glUniform2iv(real_location
, count
, temp
.get());
6410 glUniform2fv(real_location
, count
, value
);
6414 void GLES2DecoderImpl::DoUniform3fv(
6415 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6417 GLint real_location
= -1;
6418 if (!PrepForSetUniformByLocation(fake_location
,
6420 Program::kUniform3f
,
6426 if (type
== GL_BOOL_VEC3
) {
6427 GLsizei num_values
= count
* 3;
6428 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6429 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6430 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6432 glUniform3iv(real_location
, count
, temp
.get());
6434 glUniform3fv(real_location
, count
, value
);
6438 void GLES2DecoderImpl::DoUniform4fv(
6439 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6441 GLint real_location
= -1;
6442 if (!PrepForSetUniformByLocation(fake_location
,
6444 Program::kUniform4f
,
6450 if (type
== GL_BOOL_VEC4
) {
6451 GLsizei num_values
= count
* 4;
6452 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6453 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6454 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6456 glUniform4iv(real_location
, count
, temp
.get());
6458 glUniform4fv(real_location
, count
, value
);
6462 void GLES2DecoderImpl::DoUniform2iv(
6463 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6465 GLint real_location
= -1;
6466 if (!PrepForSetUniformByLocation(fake_location
,
6468 Program::kUniform2i
,
6474 glUniform2iv(real_location
, count
, value
);
6477 void GLES2DecoderImpl::DoUniform3iv(
6478 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6480 GLint real_location
= -1;
6481 if (!PrepForSetUniformByLocation(fake_location
,
6483 Program::kUniform3i
,
6489 glUniform3iv(real_location
, count
, value
);
6492 void GLES2DecoderImpl::DoUniform4iv(
6493 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6495 GLint real_location
= -1;
6496 if (!PrepForSetUniformByLocation(fake_location
,
6498 Program::kUniform4i
,
6504 glUniform4iv(real_location
, count
, value
);
6507 void GLES2DecoderImpl::DoUniformMatrix2fv(
6508 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6509 const GLfloat
* value
) {
6511 GLint real_location
= -1;
6512 if (!PrepForSetUniformByLocation(fake_location
,
6513 "glUniformMatrix2fv",
6514 Program::kUniformMatrix2f
,
6520 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6523 void GLES2DecoderImpl::DoUniformMatrix3fv(
6524 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6525 const GLfloat
* value
) {
6527 GLint real_location
= -1;
6528 if (!PrepForSetUniformByLocation(fake_location
,
6529 "glUniformMatrix3fv",
6530 Program::kUniformMatrix3f
,
6536 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6539 void GLES2DecoderImpl::DoUniformMatrix4fv(
6540 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6541 const GLfloat
* value
) {
6543 GLint real_location
= -1;
6544 if (!PrepForSetUniformByLocation(fake_location
,
6545 "glUniformMatrix4fv",
6546 Program::kUniformMatrix4f
,
6552 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6555 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6556 GLuint service_id
= 0;
6557 Program
* program
= NULL
;
6559 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6563 if (!program
->IsValid()) {
6564 // Program was not linked successfully. (ie, glLinkProgram)
6566 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6569 service_id
= program
->service_id();
6571 if (state_
.current_program
.get()) {
6572 program_manager()->UnuseProgram(shader_manager(),
6573 state_
.current_program
.get());
6575 state_
.current_program
= program
;
6576 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6577 glUseProgram(service_id
);
6578 if (state_
.current_program
.get()) {
6579 program_manager()->UseProgram(state_
.current_program
.get());
6580 if (workarounds().clear_uniforms_before_first_program_use
)
6581 program_manager()->ClearUniforms(program
);
6585 void GLES2DecoderImpl::RenderWarning(
6586 const char* filename
, int line
, const std::string
& msg
) {
6587 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6590 void GLES2DecoderImpl::PerformanceWarning(
6591 const char* filename
, int line
, const std::string
& msg
) {
6592 logger_
.LogMessage(filename
, line
,
6593 std::string("PERFORMANCE WARNING: ") + msg
);
6596 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6597 Texture
* texture
, GLenum textarget
) {
6598 // Image is already in use if texture is attached to a framebuffer.
6599 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6600 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6602 ScopedGLErrorSuppressor
suppressor(
6603 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6605 glBindTexture(textarget
, texture
->service_id());
6606 image
->WillUseTexImage();
6607 RestoreCurrentTextureBindings(&state_
, textarget
);
6612 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6613 Texture
* texture
, GLenum textarget
) {
6614 // Image is still in use if texture is attached to a framebuffer.
6615 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6616 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6618 ScopedGLErrorSuppressor
suppressor(
6619 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6621 glBindTexture(textarget
, texture
->service_id());
6622 image
->DidUseTexImage();
6623 RestoreCurrentTextureBindings(&state_
, textarget
);
6628 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6629 DCHECK(state_
.current_program
.get());
6630 if (!texture_manager()->HaveUnrenderableTextures() &&
6631 !texture_manager()->HaveImages()) {
6635 bool textures_set
= false;
6636 const Program::SamplerIndices
& sampler_indices
=
6637 state_
.current_program
->sampler_indices();
6638 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6639 const Program::UniformInfo
* uniform_info
=
6640 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6641 DCHECK(uniform_info
);
6642 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6643 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6644 if (texture_unit_index
< state_
.texture_units
.size()) {
6645 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6646 TextureRef
* texture_ref
=
6647 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6648 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6649 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6650 textures_set
= true;
6651 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6654 texture_manager()->black_texture_id(uniform_info
->type
));
6656 LOCAL_RENDER_WARNING(
6657 std::string("there is no texture bound to the unit ") +
6658 base::IntToString(texture_unit_index
));
6660 LOCAL_RENDER_WARNING(
6661 std::string("texture bound to texture unit ") +
6662 base::IntToString(texture_unit_index
) +
6663 " is not renderable. It maybe non-power-of-2 and have"
6664 " incompatible texture filtering.");
6669 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6670 Texture
* texture
= texture_ref
->texture();
6671 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6672 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6673 ScopedGLErrorSuppressor
suppressor(
6674 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6675 textures_set
= true;
6676 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6677 image
->WillUseTexImage();
6682 // else: should this be an error?
6685 return !textures_set
;
6688 void GLES2DecoderImpl::RestoreStateForTextures() {
6689 DCHECK(state_
.current_program
.get());
6690 const Program::SamplerIndices
& sampler_indices
=
6691 state_
.current_program
->sampler_indices();
6692 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6693 const Program::UniformInfo
* uniform_info
=
6694 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6695 DCHECK(uniform_info
);
6696 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6697 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6698 if (texture_unit_index
< state_
.texture_units
.size()) {
6699 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6700 TextureRef
* texture_ref
=
6701 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6702 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6703 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6704 // Get the texture_ref info that was previously bound here.
6705 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6706 ? texture_unit
.bound_texture_2d
.get()
6707 : texture_unit
.bound_texture_cube_map
.get();
6708 glBindTexture(texture_unit
.bind_target
,
6709 texture_ref
? texture_ref
->service_id() : 0);
6713 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6714 Texture
* texture
= texture_ref
->texture();
6715 gfx::GLImage
* image
=
6716 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6717 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6718 ScopedGLErrorSuppressor
suppressor(
6719 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6720 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6721 image
->DidUseTexImage();
6728 // Set the active texture back to whatever the user had it as.
6729 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6732 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6733 // Only check if there are some uncleared textures.
6734 if (!texture_manager()->HaveUnsafeTextures()) {
6738 // 1: Check all textures we are about to render with.
6739 if (state_
.current_program
.get()) {
6740 const Program::SamplerIndices
& sampler_indices
=
6741 state_
.current_program
->sampler_indices();
6742 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6743 const Program::UniformInfo
* uniform_info
=
6744 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6745 DCHECK(uniform_info
);
6746 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6747 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6748 if (texture_unit_index
< state_
.texture_units
.size()) {
6749 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6750 TextureRef
* texture_ref
=
6751 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6752 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6753 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6764 bool GLES2DecoderImpl::IsDrawValid(
6765 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6766 GLsizei primcount
) {
6767 DCHECK(instanced
|| primcount
== 1);
6769 // NOTE: We specifically do not check current_program->IsValid() because
6770 // it could never be invalid since glUseProgram would have failed. While
6771 // glLinkProgram could later mark the program as invalid the previous
6772 // valid program will still function if it is still the current program.
6773 if (!state_
.current_program
.get()) {
6774 // The program does not exist.
6775 // But GL says no ERROR.
6776 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6780 if (CheckDrawingFeedbackLoops()) {
6782 GL_INVALID_OPERATION
, function_name
,
6783 "Source and destination textures of the draw are the same.");
6787 return state_
.vertex_attrib_manager
6788 ->ValidateBindings(function_name
,
6790 feature_info_
.get(),
6791 state_
.current_program
.get(),
6792 max_vertex_accessed
,
6797 bool GLES2DecoderImpl::SimulateAttrib0(
6798 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6802 if (feature_info_
->gl_version_info().BehavesLikeGLES())
6805 const VertexAttrib
* attrib
=
6806 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6807 // If it's enabled or it's not used then we don't need to do anything.
6808 bool attrib_0_used
=
6809 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6810 if (attrib
->enabled() && attrib_0_used
) {
6814 // Make a buffer with a single repeated vec4 value enough to
6815 // simulate the constant value that is supposed to be here.
6816 // This is required to emulate GLES2 on GL.
6817 GLuint num_vertices
= max_vertex_accessed
+ 1;
6818 uint32 size_needed
= 0;
6820 if (num_vertices
== 0 ||
6821 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6822 size_needed
> 0x7FFFFFFFU
) {
6823 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6827 LOCAL_PERFORMANCE_WARNING(
6828 "Attribute 0 is disabled. This has signficant performance penalty");
6830 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6831 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6833 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6835 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6836 GLenum error
= glGetError();
6837 if (error
!= GL_NO_ERROR
) {
6839 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6844 const Vec4
& value
= state_
.attrib_values
[0];
6847 (!attrib_0_buffer_matches_value_
||
6848 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6849 value
.v
[1] != attrib_0_value_
.v
[1] ||
6850 value
.v
[2] != attrib_0_value_
.v
[2] ||
6851 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6852 std::vector
<Vec4
> temp(num_vertices
, value
);
6853 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6854 attrib_0_buffer_matches_value_
= true;
6855 attrib_0_value_
= value
;
6856 attrib_0_size_
= size_needed
;
6859 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6861 if (attrib
->divisor())
6862 glVertexAttribDivisorANGLE(0, 0);
6868 void GLES2DecoderImpl::RestoreStateForAttrib(
6869 GLuint attrib_index
, bool restore_array_binding
) {
6870 const VertexAttrib
* attrib
=
6871 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6872 if (restore_array_binding
) {
6873 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6874 Buffer
* buffer
= attrib
->buffer();
6875 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6876 glVertexAttribPointer(
6877 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6878 attrib
->gl_stride(), ptr
);
6880 if (attrib
->divisor())
6881 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6883 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6884 state_
.bound_array_buffer
->service_id() : 0);
6886 // Never touch vertex attribute 0's state (in particular, never
6887 // disable it) when running on desktop GL because it will never be
6889 if (attrib_index
!= 0 ||
6890 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6891 if (attrib
->enabled()) {
6892 glEnableVertexAttribArray(attrib_index
);
6894 glDisableVertexAttribArray(attrib_index
);
6899 bool GLES2DecoderImpl::SimulateFixedAttribs(
6900 const char* function_name
,
6901 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6904 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6907 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6911 LOCAL_PERFORMANCE_WARNING(
6912 "GL_FIXED attributes have a signficant performance penalty");
6914 // NOTE: we could be smart and try to check if a buffer is used
6915 // twice in 2 different attribs, find the overlapping parts and therefore
6916 // duplicate the minimum amount of data but this whole code path is not meant
6917 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6918 // tests so we just add to the buffer attrib used.
6920 GLuint elements_needed
= 0;
6921 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6922 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6923 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6924 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6925 const VertexAttrib
* attrib
= *it
;
6926 const Program::VertexAttrib
* attrib_info
=
6927 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6928 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6929 max_vertex_accessed
);
6930 GLuint num_vertices
= max_accessed
+ 1;
6931 if (num_vertices
== 0) {
6933 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6937 attrib
->CanAccess(max_accessed
) &&
6938 attrib
->type() == GL_FIXED
) {
6939 uint32 elements_used
= 0;
6940 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6941 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6943 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6949 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6950 uint32 size_needed
= 0;
6951 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6952 size_needed
> 0x7FFFFFFFU
) {
6954 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6958 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6960 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6961 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6962 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6963 GLenum error
= glGetError();
6964 if (error
!= GL_NO_ERROR
) {
6966 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6971 // Copy the elements and convert to float
6972 GLintptr offset
= 0;
6973 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6974 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6975 const VertexAttrib
* attrib
= *it
;
6976 const Program::VertexAttrib
* attrib_info
=
6977 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6978 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6979 max_vertex_accessed
);
6980 GLuint num_vertices
= max_accessed
+ 1;
6981 if (num_vertices
== 0) {
6983 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6987 attrib
->CanAccess(max_accessed
) &&
6988 attrib
->type() == GL_FIXED
) {
6989 int num_elements
= attrib
->size() * num_vertices
;
6990 const int src_size
= num_elements
* sizeof(int32
);
6991 const int dst_size
= num_elements
* sizeof(float);
6992 scoped_ptr
<float[]> data(new float[num_elements
]);
6993 const int32
* src
= reinterpret_cast<const int32
*>(
6994 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
6995 const int32
* end
= src
+ num_elements
;
6996 float* dst
= data
.get();
6997 while (src
!= end
) {
6998 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7000 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7001 glVertexAttribPointer(
7002 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7003 reinterpret_cast<GLvoid
*>(offset
));
7011 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7012 // There's no need to call glVertexAttribPointer because we shadow all the
7013 // settings and passing GL_FIXED to it will not work.
7016 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7020 error::Error
GLES2DecoderImpl::DoDrawArrays(
7021 const char* function_name
,
7026 GLsizei primcount
) {
7027 error::Error error
= WillAccessBoundFramebufferForDraw();
7028 if (error
!= error::kNoError
)
7030 if (!validators_
->draw_mode
.IsValid(mode
)) {
7031 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7032 return error::kNoError
;
7035 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7036 return error::kNoError
;
7038 if (primcount
< 0) {
7039 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7040 return error::kNoError
;
7042 if (!CheckBoundFramebuffersValid(function_name
)) {
7043 return error::kNoError
;
7045 // We have to check this here because the prototype for glDrawArrays
7046 // is GLint not GLsizei.
7048 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7049 return error::kNoError
;
7052 if (count
== 0 || primcount
== 0) {
7053 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7054 return error::kNoError
;
7057 GLuint max_vertex_accessed
= first
+ count
- 1;
7058 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7059 if (!ClearUnclearedTextures()) {
7060 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7061 return error::kNoError
;
7063 bool simulated_attrib_0
= false;
7064 if (!SimulateAttrib0(
7065 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7066 return error::kNoError
;
7068 bool simulated_fixed_attribs
= false;
7069 if (SimulateFixedAttribs(
7070 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7072 bool textures_set
= !PrepareTexturesForRender();
7074 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7076 glDrawArrays(mode
, first
, count
);
7078 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7081 RestoreStateForTextures();
7083 if (simulated_fixed_attribs
) {
7084 RestoreStateForSimulatedFixedAttribs();
7087 if (simulated_attrib_0
) {
7088 // We don't have to restore attrib 0 generic data at the end of this
7089 // function even if it is simulated. This is because we will simulate
7090 // it in each draw call, and attrib 0 generic data queries use cached
7091 // values instead of passing down to the underlying driver.
7092 RestoreStateForAttrib(0, false);
7095 return error::kNoError
;
7098 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7099 const void* cmd_data
) {
7100 // TODO(zmo): crbug.com/481184
7101 // On Desktop GL with versions lower than 4.3, we need to emulate
7102 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7103 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7104 return DoDrawArrays("glDrawArrays",
7106 static_cast<GLenum
>(c
.mode
),
7107 static_cast<GLint
>(c
.first
),
7108 static_cast<GLsizei
>(c
.count
),
7112 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7113 uint32 immediate_data_size
,
7114 const void* cmd_data
) {
7115 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7116 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7117 if (!features().angle_instanced_arrays
) {
7119 GL_INVALID_OPERATION
,
7120 "glDrawArraysInstancedANGLE", "function not available");
7121 return error::kNoError
;
7123 return DoDrawArrays("glDrawArraysIntancedANGLE",
7125 static_cast<GLenum
>(c
.mode
),
7126 static_cast<GLint
>(c
.first
),
7127 static_cast<GLsizei
>(c
.count
),
7128 static_cast<GLsizei
>(c
.primcount
));
7131 error::Error
GLES2DecoderImpl::DoDrawElements(
7132 const char* function_name
,
7138 GLsizei primcount
) {
7139 error::Error error
= WillAccessBoundFramebufferForDraw();
7140 if (error
!= error::kNoError
)
7142 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7144 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7145 return error::kNoError
;
7149 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7150 return error::kNoError
;
7153 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7154 return error::kNoError
;
7156 if (!validators_
->draw_mode
.IsValid(mode
)) {
7157 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7158 return error::kNoError
;
7160 if (!validators_
->index_type
.IsValid(type
)) {
7161 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7162 return error::kNoError
;
7164 if (primcount
< 0) {
7165 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7166 return error::kNoError
;
7169 if (!CheckBoundFramebuffersValid(function_name
)) {
7170 return error::kNoError
;
7173 if (count
== 0 || primcount
== 0) {
7174 return error::kNoError
;
7177 GLuint max_vertex_accessed
;
7178 Buffer
* element_array_buffer
=
7179 state_
.vertex_attrib_manager
->element_array_buffer();
7181 if (!element_array_buffer
->GetMaxValueForRange(
7182 offset
, count
, type
, &max_vertex_accessed
)) {
7184 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7185 return error::kNoError
;
7188 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7189 if (!ClearUnclearedTextures()) {
7190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7191 return error::kNoError
;
7193 bool simulated_attrib_0
= false;
7194 if (!SimulateAttrib0(
7195 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7196 return error::kNoError
;
7198 bool simulated_fixed_attribs
= false;
7199 if (SimulateFixedAttribs(
7200 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7202 bool textures_set
= !PrepareTexturesForRender();
7204 // TODO(gman): Refactor to hide these details in BufferManager or
7205 // VertexAttribManager.
7206 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7207 bool used_client_side_array
= false;
7208 if (element_array_buffer
->IsClientSideArray()) {
7209 used_client_side_array
= true;
7210 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7211 indices
= element_array_buffer
->GetRange(offset
, 0);
7214 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7216 glDrawElements(mode
, count
, type
, indices
);
7218 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7221 if (used_client_side_array
) {
7222 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7223 element_array_buffer
->service_id());
7227 RestoreStateForTextures();
7229 if (simulated_fixed_attribs
) {
7230 RestoreStateForSimulatedFixedAttribs();
7233 if (simulated_attrib_0
) {
7234 // We don't have to restore attrib 0 generic data at the end of this
7235 // function even if it is simulated. This is because we will simulate
7236 // it in each draw call, and attrib 0 generic data queries use cached
7237 // values instead of passing down to the underlying driver.
7238 RestoreStateForAttrib(0, false);
7241 return error::kNoError
;
7244 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7245 const void* cmd_data
) {
7246 // TODO(zmo): crbug.com/481184
7247 // On Desktop GL with versions lower than 4.3, we need to emulate
7248 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7249 const gles2::cmds::DrawElements
& c
=
7250 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7251 return DoDrawElements("glDrawElements",
7253 static_cast<GLenum
>(c
.mode
),
7254 static_cast<GLsizei
>(c
.count
),
7255 static_cast<GLenum
>(c
.type
),
7256 static_cast<int32
>(c
.index_offset
),
7260 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7261 uint32 immediate_data_size
,
7262 const void* cmd_data
) {
7263 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7264 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7265 if (!features().angle_instanced_arrays
) {
7267 GL_INVALID_OPERATION
,
7268 "glDrawElementsInstancedANGLE", "function not available");
7269 return error::kNoError
;
7271 return DoDrawElements("glDrawElementsInstancedANGLE",
7273 static_cast<GLenum
>(c
.mode
),
7274 static_cast<GLsizei
>(c
.count
),
7275 static_cast<GLenum
>(c
.type
),
7276 static_cast<int32
>(c
.index_offset
),
7277 static_cast<GLsizei
>(c
.primcount
));
7280 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7281 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7282 GLuint max_vertex_accessed
= 0;
7283 Buffer
* buffer
= GetBuffer(buffer_id
);
7285 // TODO(gman): Should this be a GL error or a command buffer error?
7287 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7289 if (!buffer
->GetMaxValueForRange(
7290 offset
, count
, type
, &max_vertex_accessed
)) {
7291 // TODO(gman): Should this be a GL error or a command buffer error?
7293 GL_INVALID_OPERATION
,
7294 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7297 return max_vertex_accessed
;
7300 void GLES2DecoderImpl::DoShaderSource(
7301 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7303 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7304 if (length
&& length
[ii
] > 0)
7305 str
.append(data
[ii
], length
[ii
]);
7307 str
.append(data
[ii
]);
7309 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7313 // Note: We don't actually call glShaderSource here. We wait until
7314 // we actually compile the shader.
7315 shader
->set_source(str
);
7318 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7319 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7320 GLenum buffer_mode
) {
7321 Program
* program
= GetProgramInfoNotShader(
7322 client_program_id
, "glTransformFeedbackVaryings");
7326 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7327 glTransformFeedbackVaryings(
7328 program
->service_id(), count
, varyings
, buffer_mode
);
7331 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7332 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7333 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7338 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7339 if (use_shader_translator_
) {
7340 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7341 vertex_translator_
: fragment_translator_
;
7344 const Shader::TranslatedShaderSourceType source_type
=
7345 feature_info_
->feature_flags().angle_translated_shader_source
?
7346 Shader::kANGLE
: Shader::kGL
;
7347 shader
->RequestCompile(translator
, source_type
);
7350 void GLES2DecoderImpl::DoGetShaderiv(
7351 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7352 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7357 // Compile now for statuses that require it.
7359 case GL_COMPILE_STATUS
:
7360 case GL_INFO_LOG_LENGTH
:
7361 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7362 shader
->DoCompile();
7370 case GL_SHADER_SOURCE_LENGTH
:
7371 *params
= shader
->source().size();
7375 case GL_COMPILE_STATUS
:
7376 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7378 case GL_INFO_LOG_LENGTH
:
7379 *params
= shader
->log_info().size();
7383 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7384 *params
= shader
->translated_source().size();
7391 glGetShaderiv(shader
->service_id(), pname
, params
);
7394 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7395 const void* cmd_data
) {
7396 const gles2::cmds::GetShaderSource
& c
=
7397 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7398 GLuint shader_id
= c
.shader
;
7399 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7400 Bucket
* bucket
= CreateBucket(bucket_id
);
7401 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7402 if (!shader
|| shader
->source().empty()) {
7404 return error::kNoError
;
7406 bucket
->SetFromString(shader
->source().c_str());
7407 return error::kNoError
;
7410 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7411 uint32 immediate_data_size
,
7412 const void* cmd_data
) {
7413 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7414 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7416 GLuint shader_id
= c
.shader
;
7417 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7418 Bucket
* bucket
= CreateBucket(bucket_id
);
7419 Shader
* shader
= GetShaderInfoNotProgram(
7420 shader_id
, "glGetTranslatedShaderSourceANGLE");
7423 return error::kNoError
;
7426 // Make sure translator has been utilized in compile.
7427 shader
->DoCompile();
7429 bucket
->SetFromString(shader
->translated_source().c_str());
7430 return error::kNoError
;
7433 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7434 uint32 immediate_data_size
,
7435 const void* cmd_data
) {
7436 const gles2::cmds::GetProgramInfoLog
& c
=
7437 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7438 GLuint program_id
= c
.program
;
7439 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7440 Bucket
* bucket
= CreateBucket(bucket_id
);
7441 Program
* program
= GetProgramInfoNotShader(
7442 program_id
, "glGetProgramInfoLog");
7443 if (!program
|| !program
->log_info()) {
7444 bucket
->SetFromString("");
7445 return error::kNoError
;
7447 bucket
->SetFromString(program
->log_info()->c_str());
7448 return error::kNoError
;
7451 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7452 uint32 immediate_data_size
,
7453 const void* cmd_data
) {
7454 const gles2::cmds::GetShaderInfoLog
& c
=
7455 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7456 GLuint shader_id
= c
.shader
;
7457 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7458 Bucket
* bucket
= CreateBucket(bucket_id
);
7459 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7461 bucket
->SetFromString("");
7462 return error::kNoError
;
7465 // Shader must be compiled in order to get the info log.
7466 shader
->DoCompile();
7468 bucket
->SetFromString(shader
->log_info().c_str());
7469 return error::kNoError
;
7472 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7473 return state_
.GetEnabled(cap
);
7476 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7477 const Buffer
* buffer
= GetBuffer(client_id
);
7478 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7481 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7482 const Framebuffer
* framebuffer
=
7483 GetFramebuffer(client_id
);
7484 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7487 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7488 // IsProgram is true for programs as soon as they are created, until they are
7489 // deleted and no longer in use.
7490 const Program
* program
= GetProgram(client_id
);
7491 return program
!= NULL
&& !program
->IsDeleted();
7494 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7495 const Renderbuffer
* renderbuffer
=
7496 GetRenderbuffer(client_id
);
7497 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7500 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7501 // IsShader is true for shaders as soon as they are created, until they
7502 // are deleted and not attached to any programs.
7503 const Shader
* shader
= GetShader(client_id
);
7504 return shader
!= NULL
&& !shader
->IsDeleted();
7507 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7508 const TextureRef
* texture_ref
= GetTexture(client_id
);
7509 return texture_ref
&& texture_ref
->texture()->IsValid();
7512 void GLES2DecoderImpl::DoAttachShader(
7513 GLuint program_client_id
, GLint shader_client_id
) {
7514 Program
* program
= GetProgramInfoNotShader(
7515 program_client_id
, "glAttachShader");
7519 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7523 if (!program
->AttachShader(shader_manager(), shader
)) {
7525 GL_INVALID_OPERATION
,
7527 "can not attach more than one shader of the same type.");
7530 glAttachShader(program
->service_id(), shader
->service_id());
7533 void GLES2DecoderImpl::DoDetachShader(
7534 GLuint program_client_id
, GLint shader_client_id
) {
7535 Program
* program
= GetProgramInfoNotShader(
7536 program_client_id
, "glDetachShader");
7540 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7544 if (!program
->DetachShader(shader_manager(), shader
)) {
7546 GL_INVALID_OPERATION
,
7547 "glDetachShader", "shader not attached to program");
7550 glDetachShader(program
->service_id(), shader
->service_id());
7553 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7554 Program
* program
= GetProgramInfoNotShader(
7555 program_client_id
, "glValidateProgram");
7559 program
->Validate();
7562 void GLES2DecoderImpl::GetVertexAttribHelper(
7563 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7565 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7566 Buffer
* buffer
= attrib
->buffer();
7567 if (buffer
&& !buffer
->IsDeleted()) {
7569 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7570 *params
= client_id
;
7574 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7575 *params
= attrib
->enabled();
7577 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7578 *params
= attrib
->size();
7580 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7581 *params
= attrib
->gl_stride();
7583 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7584 *params
= attrib
->type();
7586 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7587 *params
= attrib
->normalized();
7589 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7590 *params
= attrib
->divisor();
7598 void GLES2DecoderImpl::DoGetTexParameterfv(
7599 GLenum target
, GLenum pname
, GLfloat
* params
) {
7600 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7601 glGetTexParameterfv(target
, pname
, params
);
7604 void GLES2DecoderImpl::DoGetTexParameteriv(
7605 GLenum target
, GLenum pname
, GLint
* params
) {
7606 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7607 glGetTexParameteriv(target
, pname
, params
);
7610 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7611 GLenum target
, GLenum pname
) {
7612 if (!workarounds().init_texture_max_anisotropy
)
7614 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7615 !validators_
->texture_parameter
.IsValid(pname
)) {
7619 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7623 GL_INVALID_OPERATION
,
7624 "glGetTexParamter{fi}v", "unknown texture for target");
7627 Texture
* texture
= texture_ref
->texture();
7628 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7631 void GLES2DecoderImpl::DoGetVertexAttribfv(
7632 GLuint index
, GLenum pname
, GLfloat
* params
) {
7633 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7636 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7640 case GL_CURRENT_VERTEX_ATTRIB
: {
7641 const Vec4
& value
= state_
.attrib_values
[index
];
7642 params
[0] = value
.v
[0];
7643 params
[1] = value
.v
[1];
7644 params
[2] = value
.v
[2];
7645 params
[3] = value
.v
[3];
7650 GetVertexAttribHelper(attrib
, pname
, &value
);
7651 *params
= static_cast<GLfloat
>(value
);
7657 void GLES2DecoderImpl::DoGetVertexAttribiv(
7658 GLuint index
, GLenum pname
, GLint
* params
) {
7659 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7662 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7666 case GL_CURRENT_VERTEX_ATTRIB
: {
7667 const Vec4
& value
= state_
.attrib_values
[index
];
7668 params
[0] = static_cast<GLint
>(value
.v
[0]);
7669 params
[1] = static_cast<GLint
>(value
.v
[1]);
7670 params
[2] = static_cast<GLint
>(value
.v
[2]);
7671 params
[3] = static_cast<GLint
>(value
.v
[3]);
7675 GetVertexAttribHelper(attrib
, pname
, params
);
7680 bool GLES2DecoderImpl::SetVertexAttribValue(
7681 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7682 if (index
>= state_
.attrib_values
.size()) {
7683 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7686 Vec4
& v
= state_
.attrib_values
[index
];
7694 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7695 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7696 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7697 glVertexAttrib1f(index
, v0
);
7701 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7702 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7703 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7704 glVertexAttrib2f(index
, v0
, v1
);
7708 void GLES2DecoderImpl::DoVertexAttrib3f(
7709 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7710 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7711 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7712 glVertexAttrib3f(index
, v0
, v1
, v2
);
7716 void GLES2DecoderImpl::DoVertexAttrib4f(
7717 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7718 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7719 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7720 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7724 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7725 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7726 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7727 glVertexAttrib1fv(index
, v
);
7731 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7732 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7733 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7734 glVertexAttrib2fv(index
, v
);
7738 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7739 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7740 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7741 glVertexAttrib3fv(index
, v
);
7745 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7746 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7747 glVertexAttrib4fv(index
, v
);
7751 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7752 uint32 immediate_data_size
,
7753 const void* cmd_data
) {
7754 if (!unsafe_es3_apis_enabled())
7755 return error::kUnknownCommand
;
7756 const gles2::cmds::VertexAttribIPointer
& c
=
7757 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7759 if (!state_
.bound_array_buffer
.get() ||
7760 state_
.bound_array_buffer
->IsDeleted()) {
7761 if (state_
.vertex_attrib_manager
.get() ==
7762 state_
.default_vertex_attrib_manager
.get()) {
7764 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
7765 return error::kNoError
;
7766 } else if (c
.offset
!= 0) {
7769 "glVertexAttribIPointer", "client side arrays are not allowed");
7770 return error::kNoError
;
7774 GLuint indx
= c
.indx
;
7775 GLint size
= c
.size
;
7776 GLenum type
= c
.type
;
7777 GLsizei stride
= c
.stride
;
7778 GLsizei offset
= c
.offset
;
7779 const void* ptr
= reinterpret_cast<const void*>(offset
);
7780 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
7781 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
7782 return error::kNoError
;
7784 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7786 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7787 return error::kNoError
;
7789 if (indx
>= group_
->max_vertex_attribs()) {
7791 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
7792 return error::kNoError
;
7796 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
7797 return error::kNoError
;
7801 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
7802 return error::kNoError
;
7806 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
7807 return error::kNoError
;
7809 GLsizei component_size
=
7810 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7811 // component_size must be a power of two to use & as optimized modulo.
7812 DCHECK(GLES2Util::IsPOT(component_size
));
7813 if (offset
& (component_size
- 1)) {
7815 GL_INVALID_OPERATION
,
7816 "glVertexAttribIPointer", "offset not valid for type");
7817 return error::kNoError
;
7819 if (stride
& (component_size
- 1)) {
7821 GL_INVALID_OPERATION
,
7822 "glVertexAttribIPointer", "stride not valid for type");
7823 return error::kNoError
;
7825 state_
.vertex_attrib_manager
7826 ->SetAttribInfo(indx
,
7827 state_
.bound_array_buffer
.get(),
7832 stride
!= 0 ? stride
: component_size
* size
,
7834 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7835 return error::kNoError
;
7838 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7839 uint32 immediate_data_size
,
7840 const void* cmd_data
) {
7841 const gles2::cmds::VertexAttribPointer
& c
=
7842 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7844 if (!state_
.bound_array_buffer
.get() ||
7845 state_
.bound_array_buffer
->IsDeleted()) {
7846 if (state_
.vertex_attrib_manager
.get() ==
7847 state_
.default_vertex_attrib_manager
.get()) {
7849 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7850 return error::kNoError
;
7851 } else if (c
.offset
!= 0) {
7854 "glVertexAttribPointer", "client side arrays are not allowed");
7855 return error::kNoError
;
7859 GLuint indx
= c
.indx
;
7860 GLint size
= c
.size
;
7861 GLenum type
= c
.type
;
7862 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
7863 GLsizei stride
= c
.stride
;
7864 GLsizei offset
= c
.offset
;
7865 const void* ptr
= reinterpret_cast<const void*>(offset
);
7866 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7867 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7868 return error::kNoError
;
7870 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7872 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7873 return error::kNoError
;
7875 if (indx
>= group_
->max_vertex_attribs()) {
7877 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7878 return error::kNoError
;
7882 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7883 return error::kNoError
;
7887 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7888 return error::kNoError
;
7892 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7893 return error::kNoError
;
7895 GLsizei component_size
=
7896 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7897 // component_size must be a power of two to use & as optimized modulo.
7898 DCHECK(GLES2Util::IsPOT(component_size
));
7899 if (offset
& (component_size
- 1)) {
7901 GL_INVALID_OPERATION
,
7902 "glVertexAttribPointer", "offset not valid for type");
7903 return error::kNoError
;
7905 if (stride
& (component_size
- 1)) {
7907 GL_INVALID_OPERATION
,
7908 "glVertexAttribPointer", "stride not valid for type");
7909 return error::kNoError
;
7911 state_
.vertex_attrib_manager
7912 ->SetAttribInfo(indx
,
7913 state_
.bound_array_buffer
.get(),
7918 stride
!= 0 ? stride
: component_size
* size
,
7920 if (type
!= GL_FIXED
) {
7921 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7923 return error::kNoError
;
7926 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7928 state_
.viewport_x
= x
;
7929 state_
.viewport_y
= y
;
7930 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7931 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7932 glViewport(x
, y
, width
, height
);
7935 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7936 uint32 immediate_data_size
,
7937 const void* cmd_data
) {
7938 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7939 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7940 if (!features().angle_instanced_arrays
) {
7942 GL_INVALID_OPERATION
,
7943 "glVertexAttribDivisorANGLE", "function not available");
7944 return error::kNoError
;
7946 GLuint index
= c
.index
;
7947 GLuint divisor
= c
.divisor
;
7948 if (index
>= group_
->max_vertex_attribs()) {
7951 "glVertexAttribDivisorANGLE", "index out of range");
7952 return error::kNoError
;
7955 state_
.vertex_attrib_manager
->SetDivisor(
7958 glVertexAttribDivisorANGLE(index
, divisor
);
7959 return error::kNoError
;
7962 template <typename pixel_data_type
>
7963 static void WriteAlphaData(
7964 void* pixels
, uint32 row_count
, uint32 channel_count
,
7965 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7966 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7967 DCHECK_GT(channel_count
, 0U);
7968 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7969 uint32 unpadded_row_size_in_elements
=
7970 unpadded_row_size
/ sizeof(pixel_data_type
);
7971 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7972 uint32 padded_row_size_in_elements
=
7973 padded_row_size
/ sizeof(pixel_data_type
);
7974 pixel_data_type
* dst
=
7975 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7976 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7977 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7978 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7981 dst
+= padded_row_size_in_elements
;
7985 void GLES2DecoderImpl::FinishReadPixels(
7986 const cmds::ReadPixels
& c
,
7988 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7989 GLsizei width
= c
.width
;
7990 GLsizei height
= c
.height
;
7991 GLenum format
= c
.format
;
7992 GLenum type
= c
.type
;
7993 typedef cmds::ReadPixels::Result Result
;
7995 Result
* result
= NULL
;
7996 if (c
.result_shm_id
!= 0) {
7997 result
= GetSharedMemoryAs
<Result
*>(
7998 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8001 glDeleteBuffersARB(1, &buffer
);
8006 GLES2Util::ComputeImageDataSizes(
8007 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8009 void* pixels
= GetSharedMemoryAs
<void*>(
8010 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8013 glDeleteBuffersARB(1, &buffer
);
8019 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8021 if (features().map_buffer_range
) {
8022 data
= glMapBufferRange(
8023 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8025 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8028 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8029 "Unable to map memory for readback.");
8032 memcpy(pixels
, data
, pixels_size
);
8033 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8034 // have to restore the state.
8035 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8036 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8037 glDeleteBuffersARB(1, &buffer
);
8040 if (result
!= NULL
) {
8044 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8045 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8046 if ((channels_exist
& 0x0008) == 0 &&
8047 workarounds().clear_alpha_in_readpixels
) {
8048 // Set the alpha to 255 because some drivers are buggy in this regard.
8051 uint32 unpadded_row_size
;
8052 uint32 padded_row_size
;
8053 if (!GLES2Util::ComputeImageDataSizes(
8054 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8055 &unpadded_row_size
, &padded_row_size
)) {
8059 uint32 channel_count
= 0;
8060 uint32 alpha_channel
= 0;
8073 if (channel_count
> 0) {
8075 case GL_UNSIGNED_BYTE
:
8076 WriteAlphaData
<uint8
>(
8077 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8078 padded_row_size
, 0xFF);
8081 WriteAlphaData
<float>(
8082 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8083 padded_row_size
, 1.0f
);
8086 WriteAlphaData
<uint16
>(
8087 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8088 padded_row_size
, 0x3C00);
8095 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8096 const void* cmd_data
) {
8097 const gles2::cmds::ReadPixels
& c
=
8098 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8099 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8100 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8101 if (fbo_error
!= error::kNoError
)
8105 GLsizei width
= c
.width
;
8106 GLsizei height
= c
.height
;
8107 GLenum format
= c
.format
;
8108 GLenum type
= c
.type
;
8109 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8110 if (width
< 0 || height
< 0) {
8111 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8112 return error::kNoError
;
8114 typedef cmds::ReadPixels::Result Result
;
8116 if (!GLES2Util::ComputeImageDataSizes(
8117 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8119 return error::kOutOfBounds
;
8121 void* pixels
= GetSharedMemoryAs
<void*>(
8122 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8124 return error::kOutOfBounds
;
8126 Result
* result
= NULL
;
8127 if (c
.result_shm_id
!= 0) {
8128 result
= GetSharedMemoryAs
<Result
*>(
8129 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8131 return error::kOutOfBounds
;
8135 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8136 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8137 return error::kNoError
;
8139 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8140 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8141 return error::kNoError
;
8143 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8144 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8145 // format and type are acceptable enums but not guaranteed to be supported
8146 // for this framebuffer. Have to ask gl if they are valid.
8147 GLint preferred_format
= 0;
8148 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8149 GLint preferred_type
= 0;
8150 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8151 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8152 type
!= static_cast<GLenum
>(preferred_type
)) {
8154 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8155 "with the current read framebuffer");
8156 return error::kNoError
;
8159 if (width
== 0 || height
== 0) {
8160 return error::kNoError
;
8163 // Get the size of the current fbo or backbuffer.
8164 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8168 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8170 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8171 return error::kNoError
;
8174 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8175 return error::kNoError
;
8178 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8179 return error::kNoError
;
8182 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8184 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8186 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8187 // The user requested an out of range area. Get the results 1 line
8190 uint32 unpadded_row_size
;
8191 uint32 padded_row_size
;
8192 if (!GLES2Util::ComputeImageDataSizes(
8193 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8194 &unpadded_row_size
, &padded_row_size
)) {
8196 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8197 return error::kNoError
;
8200 GLint dest_x_offset
= std::max(-x
, 0);
8201 uint32 dest_row_offset
;
8202 if (!GLES2Util::ComputeImageDataSizes(
8203 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8204 &dest_row_offset
, NULL
, NULL
)) {
8206 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8207 return error::kNoError
;
8210 // Copy each row into the larger dest rect.
8211 int8
* dst
= static_cast<int8
*>(pixels
);
8212 GLint read_x
= std::max(0, x
);
8213 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8214 GLint read_width
= read_end_x
- read_x
;
8215 for (GLint yy
= 0; yy
< height
; ++yy
) {
8219 memset(dst
, 0, unpadded_row_size
);
8221 // If the row is in range, copy it.
8222 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8224 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8226 dst
+= padded_row_size
;
8229 if (async
&& features().use_async_readpixels
) {
8231 glGenBuffersARB(1, &buffer
);
8232 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8233 // For ANGLE client version 2, GL_STREAM_READ is not available.
8234 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8235 GL_STATIC_DRAW
: GL_STREAM_READ
;
8236 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8237 GLenum error
= glGetError();
8238 if (error
== GL_NO_ERROR
) {
8239 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8240 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8241 new FenceCallback()));
8242 WaitForReadPixels(base::Bind(
8243 &GLES2DecoderImpl::FinishReadPixels
,
8244 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8245 <GLES2DecoderImpl
>(this),
8247 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8248 return error::kNoError
;
8250 // On error, unbind pack buffer and fall through to sync readpixels
8251 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8252 glDeleteBuffersARB(1, &buffer
);
8255 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8257 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8258 if (error
== GL_NO_ERROR
) {
8259 if (result
!= NULL
) {
8262 FinishReadPixels(c
, 0);
8265 return error::kNoError
;
8268 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8269 const void* cmd_data
) {
8270 const gles2::cmds::PixelStorei
& c
=
8271 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8272 GLenum pname
= c
.pname
;
8273 GLenum param
= c
.param
;
8274 if (!validators_
->pixel_store
.IsValid(pname
)) {
8275 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8276 return error::kNoError
;
8279 case GL_PACK_ALIGNMENT
:
8280 case GL_UNPACK_ALIGNMENT
:
8281 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8283 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8284 return error::kNoError
;
8287 case GL_UNPACK_FLIP_Y_CHROMIUM
:
8288 unpack_flip_y_
= (param
!= 0);
8289 return error::kNoError
;
8290 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
8291 unpack_premultiply_alpha_
= (param
!= 0);
8292 return error::kNoError
;
8293 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
8294 unpack_unpremultiply_alpha_
= (param
!= 0);
8295 return error::kNoError
;
8299 glPixelStorei(pname
, param
);
8301 case GL_PACK_ALIGNMENT
:
8302 state_
.pack_alignment
= param
;
8304 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8305 state_
.pack_reverse_row_order
= (param
!= 0);
8307 case GL_UNPACK_ALIGNMENT
:
8308 state_
.unpack_alignment
= param
;
8311 // Validation should have prevented us from getting here.
8315 return error::kNoError
;
8318 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8319 uint32 immediate_data_size
,
8320 const void* cmd_data
) {
8321 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8322 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8323 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8325 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8327 if (!supports_post_sub_buffer_
) {
8329 GL_INVALID_OPERATION
,
8330 "glPostSubBufferCHROMIUM", "command not supported by surface");
8331 return error::kNoError
;
8334 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8337 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8338 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8339 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8340 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8342 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8343 return error::kNoError
;
8345 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8346 return error::kLostContext
;
8350 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8351 uint32 immediate_data_size
,
8352 const void* cmd_data
) {
8353 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8354 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8355 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8357 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8358 "glScheduleOverlayPlaneCHROMIUM",
8360 return error::kNoError
;
8362 gfx::GLImage
* image
=
8363 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8365 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8366 "glScheduleOverlayPlaneCHROMIUM",
8367 "unsupported texture format");
8368 return error::kNoError
;
8370 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8371 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8372 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8373 "glScheduleOverlayPlaneCHROMIUM",
8374 "invalid transform enum");
8375 return error::kNoError
;
8377 if (!surface_
->ScheduleOverlayPlane(
8381 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8382 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8383 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8384 "glScheduleOverlayPlaneCHROMIUM",
8385 "failed to schedule overlay");
8387 return error::kNoError
;
8390 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8391 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8392 const std::string
& name_str
) {
8393 if (!StringIsValidForGLES(name_str
.c_str())) {
8395 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8396 return error::kNoError
;
8398 Program
* program
= GetProgramInfoNotShader(
8399 client_id
, "glGetAttribLocation");
8401 return error::kNoError
;
8403 if (!program
->IsValid()) {
8405 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8406 return error::kNoError
;
8408 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8409 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8411 return error::kOutOfBounds
;
8413 // Require the client to init this incase the context is lost and we are no
8414 // longer executing commands.
8415 if (*location
!= -1) {
8416 return error::kGenericError
;
8418 *location
= program
->GetAttribLocation(name_str
);
8419 return error::kNoError
;
8422 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8423 uint32 immediate_data_size
,
8424 const void* cmd_data
) {
8425 const gles2::cmds::GetAttribLocation
& c
=
8426 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8427 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8429 return error::kInvalidArguments
;
8431 std::string name_str
;
8432 if (!bucket
->GetAsString(&name_str
)) {
8433 return error::kInvalidArguments
;
8435 return GetAttribLocationHelper(
8436 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8439 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8440 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8441 const std::string
& name_str
) {
8442 if (!StringIsValidForGLES(name_str
.c_str())) {
8444 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8445 return error::kNoError
;
8447 Program
* program
= GetProgramInfoNotShader(
8448 client_id
, "glGetUniformLocation");
8450 return error::kNoError
;
8452 if (!program
->IsValid()) {
8454 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8455 return error::kNoError
;
8457 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8458 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8460 return error::kOutOfBounds
;
8462 // Require the client to init this incase the context is lost an we are no
8463 // longer executing commands.
8464 if (*location
!= -1) {
8465 return error::kGenericError
;
8467 *location
= program
->GetUniformFakeLocation(name_str
);
8468 return error::kNoError
;
8471 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8472 uint32 immediate_data_size
,
8473 const void* cmd_data
) {
8474 const gles2::cmds::GetUniformLocation
& c
=
8475 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8476 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8478 return error::kInvalidArguments
;
8480 std::string name_str
;
8481 if (!bucket
->GetAsString(&name_str
)) {
8482 return error::kInvalidArguments
;
8484 return GetUniformLocationHelper(
8485 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8488 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8489 uint32 immediate_data_size
,
8490 const void* cmd_data
) {
8491 if (!unsafe_es3_apis_enabled())
8492 return error::kUnknownCommand
;
8493 const gles2::cmds::GetUniformIndices
& c
=
8494 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8495 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8497 return error::kInvalidArguments
;
8500 std::vector
<char*> names
;
8501 std::vector
<GLint
> len
;
8502 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8503 return error::kInvalidArguments
;
8505 typedef cmds::GetUniformIndices::Result Result
;
8506 Result
* result
= GetSharedMemoryAs
<Result
*>(
8507 c
.indices_shm_id
, c
.indices_shm_offset
,
8508 Result::ComputeSize(static_cast<size_t>(count
)));
8509 GLuint
* indices
= result
? result
->GetData() : NULL
;
8510 if (indices
== NULL
) {
8511 return error::kOutOfBounds
;
8513 // Check that the client initialized the result.
8514 if (result
->size
!= 0) {
8515 return error::kInvalidArguments
;
8517 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8519 return error::kNoError
;
8521 GLuint service_id
= program
->service_id();
8522 GLint link_status
= GL_FALSE
;
8523 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8524 if (link_status
!= GL_TRUE
) {
8525 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8526 "glGetUniformIndices", "program not linked");
8527 return error::kNoError
;
8529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8530 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8531 GLenum error
= glGetError();
8532 if (error
== GL_NO_ERROR
) {
8533 result
->SetNumResults(count
);
8535 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8537 return error::kNoError
;
8540 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8541 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8542 const std::string
& name_str
) {
8543 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8544 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8546 return error::kOutOfBounds
;
8548 // Require the client to init this incase the context is lost and we are no
8549 // longer executing commands.
8550 if (*location
!= -1) {
8551 return error::kGenericError
;
8553 Program
* program
= GetProgramInfoNotShader(
8554 client_id
, "glGetFragDataLocation");
8556 return error::kNoError
;
8558 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8559 return error::kNoError
;
8562 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8563 uint32 immediate_data_size
,
8564 const void* cmd_data
) {
8565 if (!unsafe_es3_apis_enabled())
8566 return error::kUnknownCommand
;
8567 const gles2::cmds::GetFragDataLocation
& c
=
8568 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8569 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8571 return error::kInvalidArguments
;
8573 std::string name_str
;
8574 if (!bucket
->GetAsString(&name_str
)) {
8575 return error::kInvalidArguments
;
8577 return GetFragDataLocationHelper(
8578 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8581 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8582 uint32 immediate_data_size
, const void* cmd_data
) {
8583 if (!unsafe_es3_apis_enabled())
8584 return error::kUnknownCommand
;
8585 const gles2::cmds::GetUniformBlockIndex
& c
=
8586 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8587 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8589 return error::kInvalidArguments
;
8591 std::string name_str
;
8592 if (!bucket
->GetAsString(&name_str
)) {
8593 return error::kInvalidArguments
;
8595 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8596 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8598 return error::kOutOfBounds
;
8600 // Require the client to init this in case the context is lost and we are no
8601 // longer executing commands.
8602 if (*index
!= GL_INVALID_INDEX
) {
8603 return error::kGenericError
;
8605 Program
* program
= GetProgramInfoNotShader(
8606 c
.program
, "glGetUniformBlockIndex");
8608 return error::kNoError
;
8610 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8611 return error::kNoError
;
8614 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8615 const void* cmd_data
) {
8616 const gles2::cmds::GetString
& c
=
8617 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8618 GLenum name
= static_cast<GLenum
>(c
.name
);
8619 if (!validators_
->string_type
.IsValid(name
)) {
8620 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8621 return error::kNoError
;
8624 const char* str
= nullptr;
8625 std::string extensions
;
8628 str
= "OpenGL ES 2.0 Chromium";
8630 case GL_SHADING_LANGUAGE_VERSION
:
8631 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8635 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8636 // They are used by WEBGL_debug_renderer_info.
8637 if (!force_webgl_glsl_validation_
)
8640 str
= reinterpret_cast<const char*>(glGetString(name
));
8644 // For WebGL contexts, strip out the OES derivatives and
8645 // EXT frag depth extensions if they have not been enabled.
8646 if (force_webgl_glsl_validation_
) {
8647 extensions
= feature_info_
->extensions();
8648 if (!derivatives_explicitly_enabled_
) {
8649 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8650 if (std::string::npos
!= offset
) {
8651 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8655 if (!frag_depth_explicitly_enabled_
) {
8656 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8657 if (std::string::npos
!= offset
) {
8658 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8662 if (!draw_buffers_explicitly_enabled_
) {
8663 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8664 if (std::string::npos
!= offset
) {
8665 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8669 if (!shader_texture_lod_explicitly_enabled_
) {
8670 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8671 if (std::string::npos
!= offset
) {
8672 extensions
.replace(offset
,
8673 arraysize(kEXTShaderTextureLodExtension
),
8678 extensions
= feature_info_
->extensions().c_str();
8680 if (supports_post_sub_buffer_
)
8681 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8682 str
= extensions
.c_str();
8686 str
= reinterpret_cast<const char*>(glGetString(name
));
8689 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8690 bucket
->SetFromString(str
);
8691 return error::kNoError
;
8694 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8695 const void* cmd_data
) {
8696 const gles2::cmds::BufferData
& c
=
8697 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8698 GLenum target
= static_cast<GLenum
>(c
.target
);
8699 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8700 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8701 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8702 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8703 const void* data
= NULL
;
8704 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8705 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8707 return error::kOutOfBounds
;
8710 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8711 return error::kNoError
;
8714 void GLES2DecoderImpl::DoBufferSubData(
8715 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8716 // Just delegate it. Some validation is actually done before this.
8717 buffer_manager()->ValidateAndDoBufferSubData(
8718 &state_
, target
, offset
, size
, data
);
8721 bool GLES2DecoderImpl::ClearLevel(
8725 unsigned internal_format
,
8730 bool is_texture_immutable
) {
8731 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8732 if (feature_info_
->feature_flags().angle_depth_texture
&&
8733 (channels
& GLES2Util::kDepth
) != 0) {
8734 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8735 // on depth formats.
8737 glGenFramebuffersEXT(1, &fb
);
8738 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8740 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8741 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8742 GL_DEPTH_ATTACHMENT
;
8744 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8745 texture
->service_id(), level
);
8746 // ANGLE promises a depth only attachment ok.
8747 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8748 GL_FRAMEBUFFER_COMPLETE
) {
8752 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8753 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8755 state_
.SetDeviceDepthMask(GL_TRUE
);
8756 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8757 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8759 RestoreClearState();
8761 glDeleteFramebuffersEXT(1, &fb
);
8762 Framebuffer
* framebuffer
=
8763 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8764 GLuint fb_service_id
=
8765 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8766 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8770 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8773 uint32 padded_row_size
;
8774 if (!GLES2Util::ComputeImageDataSizes(
8775 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8776 NULL
, &padded_row_size
)) {
8780 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8784 if (size
> kMaxZeroSize
) {
8785 if (kMaxZeroSize
< padded_row_size
) {
8786 // That'd be an awfully large texture.
8789 // We should never have a large total size with a zero row size.
8790 DCHECK_GT(padded_row_size
, 0U);
8791 tile_height
= kMaxZeroSize
/ padded_row_size
;
8792 if (!GLES2Util::ComputeImageDataSizes(
8793 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8798 tile_height
= height
;
8801 // Assumes the size has already been checked.
8802 scoped_ptr
<char[]> zero(new char[size
]);
8803 memset(zero
.get(), 0, size
);
8804 glBindTexture(texture
->target(), texture
->service_id());
8806 bool has_images
= texture
->HasImages();
8808 while (y
< height
) {
8809 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8810 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8811 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8814 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8819 TextureRef
* bound_texture
=
8820 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8821 glBindTexture(texture
->target(),
8822 bound_texture
? bound_texture
->service_id() : 0);
8828 const int kS3TCBlockWidth
= 4;
8829 const int kS3TCBlockHeight
= 4;
8830 const int kS3TCDXT1BlockSize
= 8;
8831 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8832 const int kEACAndETC2BlockSize
= 4;
8834 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8835 return (size
== 1) ||
8836 (size
== 2) || !(size
% kS3TCBlockWidth
);
8839 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8840 return GLES2Util::IsPOT(size
);
8843 } // anonymous namespace.
8845 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8846 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
8847 GLenum format
, GLsizei size
) {
8848 base::CheckedNumeric
<GLsizei
> bytes_required(0);
8851 case GL_ATC_RGB_AMD
:
8852 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8853 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8854 case GL_ETC1_RGB8_OES
:
8856 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8858 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8859 bytes_required
*= kS3TCDXT1BlockSize
;
8861 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8862 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8863 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8864 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
8866 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8868 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8869 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
8871 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8872 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8873 bytes_required
= std::max(width
, 8);
8874 bytes_required
*= std::max(height
, 8);
8875 bytes_required
*= 4;
8876 bytes_required
+= 7;
8877 bytes_required
/= 8;
8879 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8880 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
8881 bytes_required
= std::max(width
, 16);
8882 bytes_required
*= std::max(height
, 8);
8883 bytes_required
*= 2;
8884 bytes_required
+= 7;
8885 bytes_required
/= 8;
8889 case GL_COMPRESSED_R11_EAC
:
8890 case GL_COMPRESSED_SIGNED_R11_EAC
:
8891 case GL_COMPRESSED_RGB8_ETC2
:
8892 case GL_COMPRESSED_SRGB8_ETC2
:
8893 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8894 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8896 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8898 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8899 bytes_required
*= 8;
8900 bytes_required
*= depth
;
8902 case GL_COMPRESSED_RG11_EAC
:
8903 case GL_COMPRESSED_SIGNED_RG11_EAC
:
8904 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
8905 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
8907 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8909 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8910 bytes_required
*= 16;
8911 bytes_required
*= depth
;
8914 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8918 if (!bytes_required
.IsValid() || size
!= bytes_required
.ValueOrDefault(0)) {
8920 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8927 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8928 const char* function_name
, GLenum target
, GLint level
,
8929 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
8931 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8932 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8933 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8934 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
8935 DCHECK_EQ(1, depth
); // 2D formats.
8936 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8938 GL_INVALID_OPERATION
, function_name
,
8939 "width or height invalid for level");
8943 case GL_ATC_RGB_AMD
:
8944 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8945 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8946 case GL_ETC1_RGB8_OES
:
8947 DCHECK_EQ(1, depth
); // 2D formats.
8948 if (width
<= 0 || height
<= 0) {
8950 GL_INVALID_OPERATION
, function_name
,
8951 "width or height invalid for level");
8955 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8956 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8957 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8958 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
8959 DCHECK_EQ(1, depth
); // 2D formats.
8960 if (!IsValidPVRTCSize(level
, width
) ||
8961 !IsValidPVRTCSize(level
, height
)) {
8963 GL_INVALID_OPERATION
, function_name
,
8964 "width or height invalid for level");
8970 case GL_COMPRESSED_R11_EAC
:
8971 case GL_COMPRESSED_SIGNED_R11_EAC
:
8972 case GL_COMPRESSED_RG11_EAC
:
8973 case GL_COMPRESSED_SIGNED_RG11_EAC
:
8974 case GL_COMPRESSED_RGB8_ETC2
:
8975 case GL_COMPRESSED_SRGB8_ETC2
:
8976 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8977 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8978 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
8979 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
8980 if (width
<= 0 || height
<= 0 || depth
<= 0) {
8982 GL_INVALID_OPERATION
, function_name
,
8983 "width, height, or depth invalid");
8986 if (target
!= GL_TEXTURE_2D_ARRAY
) {
8988 GL_INVALID_OPERATION
, function_name
,
8989 "target invalid for format");
8998 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8999 const char* function_name
,
9000 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
9001 GLsizei width
, GLsizei height
, GLenum format
,
9003 if (xoffset
< 0 || yoffset
< 0) {
9005 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
9010 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9011 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9012 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9013 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9014 const int kBlockWidth
= 4;
9015 const int kBlockHeight
= 4;
9016 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9018 GL_INVALID_OPERATION
, function_name
,
9019 "xoffset or yoffset not multiple of 4");
9022 GLsizei tex_width
= 0;
9023 GLsizei tex_height
= 0;
9024 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
9025 width
- xoffset
> tex_width
||
9026 height
- yoffset
> tex_height
) {
9028 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9031 return ValidateCompressedTexDimensions(
9032 function_name
, target
, level
, width
, height
, 1, format
);
9034 case GL_ATC_RGB_AMD
:
9035 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9036 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9038 GL_INVALID_OPERATION
, function_name
,
9039 "not supported for ATC textures");
9042 case GL_ETC1_RGB8_OES
: {
9044 GL_INVALID_OPERATION
, function_name
,
9045 "not supported for ECT1_RGB8_OES textures");
9048 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9049 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9050 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9051 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9052 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9054 GL_INVALID_OPERATION
, function_name
,
9055 "xoffset and yoffset must be zero");
9058 GLsizei tex_width
= 0;
9059 GLsizei tex_height
= 0;
9060 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
9061 width
!= tex_width
||
9062 height
!= tex_height
) {
9064 GL_INVALID_OPERATION
, function_name
,
9065 "dimensions must match existing texture level dimensions");
9068 return ValidateCompressedTexDimensions(
9069 function_name
, target
, level
, width
, height
, 1, format
);
9076 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9079 GLenum internal_format
,
9085 if (!validators_
->texture_target
.IsValid(target
)) {
9086 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9087 "glCompressedTexImage2D", target
, "target");
9088 return error::kNoError
;
9090 if (!validators_
->compressed_texture_format
.IsValid(
9092 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9093 "glCompressedTexImage2D", internal_format
, "internal_format");
9094 return error::kNoError
;
9096 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9100 "glCompressedTexImage2D", "dimensions out of range");
9101 return error::kNoError
;
9103 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9108 "glCompressedTexImage2D", "unknown texture target");
9109 return error::kNoError
;
9111 Texture
* texture
= texture_ref
->texture();
9112 if (texture
->IsImmutable()) {
9114 GL_INVALID_OPERATION
,
9115 "glCompressedTexImage2D", "texture is immutable");
9116 return error::kNoError
;
9119 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9120 width
, height
, 1, internal_format
) ||
9121 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9122 1, internal_format
, image_size
)) {
9123 return error::kNoError
;
9126 if (!EnsureGPUMemoryAvailable(image_size
)) {
9128 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9129 return error::kNoError
;
9132 if (texture
->IsAttachedToFramebuffer()) {
9133 framebuffer_state_
.clear_state_dirty
= true;
9136 scoped_ptr
<int8
[]> zero
;
9138 zero
.reset(new int8
[image_size
]);
9139 memset(zero
.get(), 0, image_size
);
9142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9143 glCompressedTexImage2D(
9144 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9145 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9146 if (error
== GL_NO_ERROR
) {
9147 texture_manager()->SetLevelInfo(
9148 texture_ref
, target
, level
, internal_format
,
9149 width
, height
, 1, border
, 0, 0, true);
9152 // This may be a slow command. Exit command processing to allow for
9153 // context preemption and GPU watchdog checks.
9154 ExitCommandProcessingEarly();
9155 return error::kNoError
;
9158 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9159 uint32 immediate_data_size
,
9160 const void* cmd_data
) {
9161 const gles2::cmds::CompressedTexImage2D
& c
=
9162 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9163 GLenum target
= static_cast<GLenum
>(c
.target
);
9164 GLint level
= static_cast<GLint
>(c
.level
);
9165 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9166 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9167 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9168 GLint border
= static_cast<GLint
>(c
.border
);
9169 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9170 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9171 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9172 const void* data
= NULL
;
9173 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9174 data
= GetSharedMemoryAs
<const void*>(
9175 data_shm_id
, data_shm_offset
, image_size
);
9177 return error::kOutOfBounds
;
9180 return DoCompressedTexImage2D(
9181 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9184 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9185 uint32 immediate_data_size
,
9186 const void* cmd_data
) {
9187 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9188 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9189 GLenum target
= static_cast<GLenum
>(c
.target
);
9190 GLint level
= static_cast<GLint
>(c
.level
);
9191 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9192 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9193 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9194 GLint border
= static_cast<GLint
>(c
.border
);
9195 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9197 return error::kInvalidArguments
;
9199 uint32 data_size
= bucket
->size();
9200 GLsizei imageSize
= data_size
;
9201 const void* data
= bucket
->GetData(0, data_size
);
9203 return error::kInvalidArguments
;
9205 return DoCompressedTexImage2D(
9206 target
, level
, internal_format
, width
, height
, border
,
9210 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9211 uint32 immediate_data_size
,
9212 const void* cmd_data
) {
9213 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9214 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9215 GLenum target
= static_cast<GLenum
>(c
.target
);
9216 GLint level
= static_cast<GLint
>(c
.level
);
9217 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9218 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9219 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9220 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9221 GLenum format
= static_cast<GLenum
>(c
.format
);
9222 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9224 return error::kInvalidArguments
;
9226 uint32 data_size
= bucket
->size();
9227 GLsizei imageSize
= data_size
;
9228 const void* data
= bucket
->GetData(0, data_size
);
9230 return error::kInvalidArguments
;
9232 if (!validators_
->texture_target
.IsValid(target
)) {
9234 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9235 return error::kNoError
;
9237 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9239 "glCompressedTexSubImage2D", format
, "format");
9240 return error::kNoError
;
9244 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9245 return error::kNoError
;
9249 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9250 return error::kNoError
;
9252 if (imageSize
< 0) {
9254 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9255 return error::kNoError
;
9257 DoCompressedTexSubImage2D(
9258 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9259 return error::kNoError
;
9262 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9265 GLenum internal_format
,
9272 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9274 "glCompressedTexImage3D", target
, "target");
9275 return error::kNoError
;
9277 if (!validators_
->compressed_texture_format
.IsValid(
9279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9280 "glCompressedTexImage3D", internal_format
, "internal_format");
9281 return error::kNoError
;
9283 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9287 "glCompressedTexImage3D", "dimensions out of range");
9288 return error::kNoError
;
9290 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9295 "glCompressedTexImage3D", "unknown texture target");
9296 return error::kNoError
;
9298 Texture
* texture
= texture_ref
->texture();
9299 if (texture
->IsImmutable()) {
9301 GL_INVALID_OPERATION
,
9302 "glCompressedTexImage3D", "texture is immutable");
9303 return error::kNoError
;
9306 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9307 width
, height
, depth
, internal_format
) ||
9308 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9309 depth
, internal_format
, image_size
)) {
9310 return error::kNoError
;
9313 if (!EnsureGPUMemoryAvailable(image_size
)) {
9315 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9316 return error::kNoError
;
9319 if (texture
->IsAttachedToFramebuffer()) {
9320 framebuffer_state_
.clear_state_dirty
= true;
9323 scoped_ptr
<int8
[]> zero
;
9325 zero
.reset(new int8
[image_size
]);
9326 memset(zero
.get(), 0, image_size
);
9329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9330 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9331 border
, image_size
, data
);
9332 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9333 if (error
== GL_NO_ERROR
) {
9334 texture_manager()->SetLevelInfo(
9335 texture_ref
, target
, level
, internal_format
,
9336 width
, height
, depth
, border
, 0, 0, true);
9339 // This may be a slow command. Exit command processing to allow for
9340 // context preemption and GPU watchdog checks.
9341 ExitCommandProcessingEarly();
9342 return error::kNoError
;
9345 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9346 uint32 immediate_data_size
, const void* cmd_data
) {
9347 if (!unsafe_es3_apis_enabled())
9348 return error::kUnknownCommand
;
9350 const gles2::cmds::CompressedTexImage3D
& c
=
9351 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9352 GLenum target
= static_cast<GLenum
>(c
.target
);
9353 GLint level
= static_cast<GLint
>(c
.level
);
9354 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9355 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9356 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9357 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9358 GLint border
= static_cast<GLint
>(c
.border
);
9359 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9360 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9361 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9362 const void* data
= NULL
;
9363 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9364 data
= GetSharedMemoryAs
<const void*>(
9365 data_shm_id
, data_shm_offset
, image_size
);
9367 return error::kOutOfBounds
;
9370 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9371 depth
, border
, image_size
, data
);
9374 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9375 uint32 immediate_data_size
, const void* cmd_data
) {
9376 if (!unsafe_es3_apis_enabled())
9377 return error::kUnknownCommand
;
9379 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9380 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9381 GLenum target
= static_cast<GLenum
>(c
.target
);
9382 GLint level
= static_cast<GLint
>(c
.level
);
9383 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9384 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9385 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9386 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9387 GLint border
= static_cast<GLint
>(c
.border
);
9388 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9390 return error::kInvalidArguments
;
9392 uint32 data_size
= bucket
->size();
9393 GLsizei imageSize
= data_size
;
9394 const void* data
= bucket
->GetData(0, data_size
);
9396 return error::kInvalidArguments
;
9398 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9399 depth
, border
, imageSize
, data
);
9402 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9403 const void* cmd_data
) {
9404 const gles2::cmds::TexImage2D
& c
=
9405 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9406 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9407 "width", c
.width
, "height", c
.height
);
9408 // Set as failed for now, but if it successed, this will be set to not failed.
9409 texture_state_
.tex_image_2d_failed
= true;
9410 GLenum target
= static_cast<GLenum
>(c
.target
);
9411 GLint level
= static_cast<GLint
>(c
.level
);
9412 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9413 // for internalformat.
9414 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9415 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9416 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9417 GLint border
= static_cast<GLint
>(c
.border
);
9418 GLenum format
= static_cast<GLenum
>(c
.format
);
9419 GLenum type
= static_cast<GLenum
>(c
.type
);
9420 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9421 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9423 if (!GLES2Util::ComputeImageDataSizes(
9424 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9426 return error::kOutOfBounds
;
9428 const void* pixels
= NULL
;
9429 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9430 pixels
= GetSharedMemoryAs
<const void*>(
9431 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9433 return error::kOutOfBounds
;
9437 // For testing only. Allows us to stress the ability to respond to OOM errors.
9438 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9439 (width
* height
>= 4096 * 4096)) {
9442 "glTexImage2D", "synthetic out of memory");
9443 return error::kNoError
;
9446 TextureManager::DoTextImage2DArguments args
= {
9447 target
, level
, internal_format
, width
, height
, border
, format
, type
,
9448 pixels
, pixels_size
};
9449 texture_manager()->ValidateAndDoTexImage2D(
9450 &texture_state_
, &state_
, &framebuffer_state_
, args
);
9452 // This may be a slow command. Exit command processing to allow for
9453 // context preemption and GPU watchdog checks.
9454 ExitCommandProcessingEarly();
9455 return error::kNoError
;
9458 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9459 const void* cmd_data
) {
9460 // TODO(zmo): Unsafe ES3 API.
9461 if (!unsafe_es3_apis_enabled())
9462 return error::kUnknownCommand
;
9464 const gles2::cmds::TexImage3D
& c
=
9465 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9466 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9467 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9468 GLenum target
= static_cast<GLenum
>(c
.target
);
9469 GLint level
= static_cast<GLint
>(c
.level
);
9470 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9471 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9472 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9473 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9474 GLint border
= static_cast<GLint
>(c
.border
);
9475 GLenum format
= static_cast<GLenum
>(c
.format
);
9476 GLenum type
= static_cast<GLenum
>(c
.type
);
9477 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9478 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9480 if (!GLES2Util::ComputeImageDataSizes(
9481 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9483 return error::kOutOfBounds
;
9485 const void* pixels
= NULL
;
9486 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9487 pixels
= GetSharedMemoryAs
<const void*>(
9488 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9490 return error::kOutOfBounds
;
9494 glTexImage3D(target
, level
, internal_format
, width
, height
, depth
, border
,
9495 format
, type
, pixels
);
9497 // This may be a slow command. Exit command processing to allow for
9498 // context preemption and GPU watchdog checks.
9499 ExitCommandProcessingEarly();
9500 return error::kNoError
;
9503 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9512 const void * data
) {
9513 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9517 GL_INVALID_OPERATION
,
9518 "glCompressedTexSubImage2D", "unknown texture for target");
9521 Texture
* texture
= texture_ref
->texture();
9523 GLenum internal_format
= 0;
9524 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9526 GL_INVALID_OPERATION
,
9527 "glCompressedTexSubImage2D", "level does not exist.");
9530 if (internal_format
!= format
) {
9532 GL_INVALID_OPERATION
,
9533 "glCompressedTexSubImage2D", "format does not match internal format.");
9536 if (!texture
->ValidForTexture(
9537 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9539 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9543 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9544 width
, height
, 1, format
, image_size
) ||
9545 !ValidateCompressedTexSubDimensions(
9546 "glCompressedTexSubImage2D",
9547 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
9552 // Note: There is no need to deal with texture cleared tracking here
9553 // because the validation above means you can only get here if the level
9554 // is already a matching compressed format and in that case
9555 // CompressedTexImage2D already cleared the texture.
9556 glCompressedTexSubImage2D(
9557 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9559 // This may be a slow command. Exit command processing to allow for
9560 // context preemption and GPU watchdog checks.
9561 ExitCommandProcessingEarly();
9565 GLint start
, GLint range
, GLint sourceRange
,
9566 GLint
* out_start
, GLint
* out_range
) {
9573 GLint end
= start
+ range
;
9574 if (end
> sourceRange
) {
9575 range
-= end
- sourceRange
;
9581 void GLES2DecoderImpl::DoCopyTexImage2D(
9584 GLenum internal_format
,
9590 DCHECK(!ShouldDeferReads());
9591 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9595 GL_INVALID_OPERATION
,
9596 "glCopyTexImage2D", "unknown texture for target");
9599 Texture
* texture
= texture_ref
->texture();
9600 if (texture
->IsImmutable()) {
9602 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9605 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9608 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9611 if (!texture_manager()->ValidateFormatAndTypeCombination(
9612 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9613 GL_UNSIGNED_BYTE
)) {
9617 // Check we have compatible formats.
9618 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9619 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9620 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9622 if ((channels_needed
& channels_exist
) != channels_needed
) {
9624 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9628 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9630 GL_INVALID_OPERATION
,
9631 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9635 uint32 estimated_size
= 0;
9636 if (!GLES2Util::ComputeImageDataSizes(
9637 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9638 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9640 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9644 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9645 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9649 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9653 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9655 GL_INVALID_OPERATION
,
9656 "glCopyTexImage2D", "source and destination textures are the same");
9660 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9664 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9665 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9666 gfx::Size size
= GetBoundReadFrameBufferSize();
9668 if (texture
->IsAttachedToFramebuffer()) {
9669 framebuffer_state_
.clear_state_dirty
= true;
9672 // Clip to size to source dimensions
9675 GLint copyWidth
= 0;
9676 GLint copyHeight
= 0;
9677 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9678 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9682 copyWidth
!= width
||
9683 copyHeight
!= height
) {
9684 // some part was clipped so clear the texture.
9685 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9686 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9688 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9691 if (copyHeight
> 0 && copyWidth
> 0) {
9692 GLint dx
= copyX
- x
;
9693 GLint dy
= copyY
- y
;
9696 ScopedModifyPixels
modify(texture_ref
);
9697 glCopyTexSubImage2D(target
, level
,
9698 destX
, destY
, copyX
, copyY
,
9699 copyWidth
, copyHeight
);
9702 ScopedModifyPixels
modify(texture_ref
);
9703 glCopyTexImage2D(target
, level
, internal_format
,
9704 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9706 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9707 if (error
== GL_NO_ERROR
) {
9708 texture_manager()->SetLevelInfo(
9709 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
9710 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
9713 // This may be a slow command. Exit command processing to allow for
9714 // context preemption and GPU watchdog checks.
9715 ExitCommandProcessingEarly();
9718 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9727 DCHECK(!ShouldDeferReads());
9728 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9732 GL_INVALID_OPERATION
,
9733 "glCopyTexSubImage2D", "unknown texture for target");
9736 Texture
* texture
= texture_ref
->texture();
9739 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
9740 !texture
->ValidForTexture(
9741 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9743 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
9746 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9748 GL_INVALID_OPERATION
,
9749 "glCopyTexSubImage2D", "async upload pending for texture");
9753 // Check we have compatible formats.
9754 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9755 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9756 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
9758 if (!channels_needed
||
9759 (channels_needed
& channels_exist
) != channels_needed
) {
9761 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
9765 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9767 GL_INVALID_OPERATION
,
9768 "glCopySubImage2D", "can not be used with depth or stencil textures");
9772 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9776 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9778 GL_INVALID_OPERATION
,
9779 "glCopyTexSubImage2D", "source and destination textures are the same");
9783 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9787 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9788 gfx::Size size
= GetBoundReadFrameBufferSize();
9791 GLint copyWidth
= 0;
9792 GLint copyHeight
= 0;
9793 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9794 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9796 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
9797 height
!= size
.height()) {
9798 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
9800 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
9801 "dimensions too big");
9805 // Write all pixels in below.
9806 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9811 copyWidth
!= width
||
9812 copyHeight
!= height
) {
9813 // some part was clipped so clear the sub rect.
9814 uint32 pixels_size
= 0;
9815 if (!GLES2Util::ComputeImageDataSizes(
9816 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9819 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
9822 scoped_ptr
<char[]> zero(new char[pixels_size
]);
9823 memset(zero
.get(), 0, pixels_size
);
9824 ScopedModifyPixels
modify(texture_ref
);
9826 target
, level
, xoffset
, yoffset
, width
, height
,
9827 format
, type
, zero
.get());
9830 if (copyHeight
> 0 && copyWidth
> 0) {
9831 GLint dx
= copyX
- x
;
9832 GLint dy
= copyY
- y
;
9833 GLint destX
= xoffset
+ dx
;
9834 GLint destY
= yoffset
+ dy
;
9835 ScopedModifyPixels
modify(texture_ref
);
9836 glCopyTexSubImage2D(target
, level
,
9837 destX
, destY
, copyX
, copyY
,
9838 copyWidth
, copyHeight
);
9841 // This may be a slow command. Exit command processing to allow for
9842 // context preemption and GPU watchdog checks.
9843 ExitCommandProcessingEarly();
9846 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9847 error::Error
* error
,
9848 const char* function_name
,
9857 const void * data
) {
9858 (*error
) = error::kNoError
;
9859 if (!validators_
->texture_target
.IsValid(target
)) {
9860 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
9864 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
9868 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
9871 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9875 GL_INVALID_OPERATION
,
9876 function_name
, "unknown texture for target");
9879 Texture
* texture
= texture_ref
->texture();
9880 GLenum current_type
= 0;
9881 GLenum internal_format
= 0;
9882 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
9884 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
9887 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
9888 function_name
, format
, type
, internal_format
, level
)) {
9891 if (type
!= current_type
) {
9893 GL_INVALID_OPERATION
,
9894 function_name
, "type does not match type of texture.");
9897 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9899 GL_INVALID_OPERATION
,
9900 function_name
, "async upload pending for texture");
9903 if (!texture
->ValidForTexture(
9904 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9905 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
9908 if ((GLES2Util::GetChannelsForFormat(format
) &
9909 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9911 GL_INVALID_OPERATION
,
9912 function_name
, "can not supply data for depth or stencil textures");
9916 (*error
) = error::kOutOfBounds
;
9922 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
9931 const void * data
) {
9932 error::Error error
= error::kNoError
;
9933 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
9934 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
9937 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9939 Texture
* texture
= texture_ref
->texture();
9940 GLsizei tex_width
= 0;
9941 GLsizei tex_height
= 0;
9942 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
9944 if (xoffset
!= 0 || yoffset
!= 0 ||
9945 width
!= tex_width
|| height
!= tex_height
) {
9946 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
9949 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
9950 return error::kNoError
;
9952 ScopedTextureUploadTimer
timer(&texture_state_
);
9954 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9955 return error::kNoError
;
9958 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
9959 !texture
->IsImmutable() &&
9960 !texture
->HasImages()) {
9961 ScopedTextureUploadTimer
timer(&texture_state_
);
9962 GLenum internal_format
;
9964 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
9965 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9968 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
9970 ScopedTextureUploadTimer
timer(&texture_state_
);
9972 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9974 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9976 // This may be a slow command. Exit command processing to allow for
9977 // context preemption and GPU watchdog checks.
9978 ExitCommandProcessingEarly();
9979 return error::kNoError
;
9982 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
9983 const void* cmd_data
) {
9984 const gles2::cmds::TexSubImage2D
& c
=
9985 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
9986 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9987 "width", c
.width
, "height", c
.height
);
9988 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
9989 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
9990 return error::kNoError
;
9992 GLenum target
= static_cast<GLenum
>(c
.target
);
9993 GLint level
= static_cast<GLint
>(c
.level
);
9994 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9995 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9996 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9997 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9998 GLenum format
= static_cast<GLenum
>(c
.format
);
9999 GLenum type
= static_cast<GLenum
>(c
.type
);
10001 if (!GLES2Util::ComputeImageDataSizes(
10002 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10004 return error::kOutOfBounds
;
10006 const void* pixels
= GetSharedMemoryAs
<const void*>(
10007 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10008 return DoTexSubImage2D(
10009 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10012 // TODO(zmo): Remove the below stub once we add the real function binding.
10013 // Currently it's missing due to a gmock limitation.
10014 static void glTexSubImage3D(
10015 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
10016 GLsizei height
, GLsizei width
, GLsizei depth
, GLenum format
, GLenum type
,
10017 const void* pixels
) {
10021 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10022 const void* cmd_data
) {
10023 // TODO(zmo): Unsafe ES3 API.
10024 if (!unsafe_es3_apis_enabled())
10025 return error::kUnknownCommand
;
10027 const gles2::cmds::TexSubImage3D
& c
=
10028 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10029 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10030 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10031 GLenum target
= static_cast<GLenum
>(c
.target
);
10032 GLint level
= static_cast<GLint
>(c
.level
);
10033 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10034 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10035 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10036 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10037 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10038 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10039 GLenum format
= static_cast<GLenum
>(c
.format
);
10040 GLenum type
= static_cast<GLenum
>(c
.type
);
10042 if (!GLES2Util::ComputeImageDataSizes(
10043 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10045 return error::kOutOfBounds
;
10047 const void* pixels
= GetSharedMemoryAs
<const void*>(
10048 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10049 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10050 depth
, format
, type
, pixels
);
10051 return error::kNoError
;
10054 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10055 uint32 immediate_data_size
,
10056 const void* cmd_data
) {
10057 const gles2::cmds::GetVertexAttribPointerv
& c
=
10058 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10059 GLuint index
= static_cast<GLuint
>(c
.index
);
10060 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10061 typedef cmds::GetVertexAttribPointerv::Result Result
;
10062 Result
* result
= GetSharedMemoryAs
<Result
*>(
10063 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10065 return error::kOutOfBounds
;
10067 // Check that the client initialized the result.
10068 if (result
->size
!= 0) {
10069 return error::kInvalidArguments
;
10071 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10072 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10073 "glGetVertexAttribPointerv", pname
, "pname");
10074 return error::kNoError
;
10076 if (index
>= group_
->max_vertex_attribs()) {
10077 LOCAL_SET_GL_ERROR(
10078 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10079 return error::kNoError
;
10081 result
->SetNumResults(1);
10082 *result
->GetData() =
10083 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10084 return error::kNoError
;
10087 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10088 GLint fake_location
,
10091 error::Error
* error
,
10092 GLint
* real_location
,
10093 GLuint
* service_id
,
10094 void** result_pointer
,
10095 GLenum
* result_type
,
10096 GLsizei
* result_size
) {
10098 DCHECK(service_id
);
10099 DCHECK(result_pointer
);
10100 DCHECK(result_type
);
10101 DCHECK(real_location
);
10102 *error
= error::kNoError
;
10103 // Make sure we have enough room for the result on failure.
10104 SizedResult
<GLint
>* result
;
10105 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
10106 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
10108 *error
= error::kOutOfBounds
;
10111 *result_pointer
= result
;
10112 // Set the result size to 0 so the client does not have to check for success.
10113 result
->SetNumResults(0);
10114 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10118 if (!program
->IsValid()) {
10119 // Program was not linked successfully. (ie, glLinkProgram)
10120 LOCAL_SET_GL_ERROR(
10121 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10124 *service_id
= program
->service_id();
10125 GLint array_index
= -1;
10126 const Program::UniformInfo
* uniform_info
=
10127 program
->GetUniformInfoByFakeLocation(
10128 fake_location
, real_location
, &array_index
);
10129 if (!uniform_info
) {
10130 // No such location.
10131 LOCAL_SET_GL_ERROR(
10132 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10135 GLenum type
= uniform_info
->type
;
10136 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
10138 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10141 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
10142 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
10144 *error
= error::kOutOfBounds
;
10147 result
->size
= size
;
10148 *result_size
= size
;
10149 *result_type
= type
;
10153 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10154 const void* cmd_data
) {
10155 const gles2::cmds::GetUniformiv
& c
=
10156 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10157 GLuint program
= c
.program
;
10158 GLint fake_location
= c
.location
;
10160 GLenum result_type
;
10161 GLsizei result_size
;
10162 GLint real_location
= -1;
10165 if (GetUniformSetup(program
, fake_location
, c
.params_shm_id
,
10166 c
.params_shm_offset
, &error
, &real_location
, &service_id
,
10167 &result
, &result_type
, &result_size
)) {
10169 service_id
, real_location
,
10170 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
10175 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10176 const void* cmd_data
) {
10177 const gles2::cmds::GetUniformfv
& c
=
10178 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10179 GLuint program
= c
.program
;
10180 GLint fake_location
= c
.location
;
10182 GLint real_location
= -1;
10184 typedef cmds::GetUniformfv::Result Result
;
10186 GLenum result_type
;
10187 GLsizei result_size
;
10188 if (GetUniformSetup(program
, fake_location
, c
.params_shm_id
,
10189 c
.params_shm_offset
, &error
, &real_location
, &service_id
,
10190 reinterpret_cast<void**>(&result
), &result_type
,
10192 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10193 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10194 GLsizei num_values
= result_size
/ sizeof(Result::Type
);
10195 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10196 glGetUniformiv(service_id
, real_location
, temp
.get());
10197 GLfloat
* dst
= result
->GetData();
10198 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10199 dst
[ii
] = (temp
[ii
] != 0);
10202 glGetUniformfv(service_id
, real_location
, result
->GetData());
10208 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10209 uint32 immediate_data_size
,
10210 const void* cmd_data
) {
10211 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10212 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10213 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10214 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10215 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10216 Result
* result
= GetSharedMemoryAs
<Result
*>(
10217 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10219 return error::kOutOfBounds
;
10221 // Check that the client initialized the result.
10222 if (result
->success
!= 0) {
10223 return error::kInvalidArguments
;
10225 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10226 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10227 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10228 return error::kNoError
;
10230 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10231 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10232 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10233 return error::kNoError
;
10236 result
->success
= 1; // true
10238 GLint range
[2] = { 0, 0 };
10239 GLint precision
= 0;
10240 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10242 result
->min_range
= range
[0];
10243 result
->max_range
= range
[1];
10244 result
->precision
= precision
;
10246 return error::kNoError
;
10249 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10250 uint32 immediate_data_size
,
10251 const void* cmd_data
) {
10252 const gles2::cmds::GetAttachedShaders
& c
=
10253 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10254 uint32 result_size
= c
.result_size
;
10255 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10256 Program
* program
= GetProgramInfoNotShader(
10257 program_id
, "glGetAttachedShaders");
10259 return error::kNoError
;
10261 typedef cmds::GetAttachedShaders::Result Result
;
10262 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10263 Result
* result
= GetSharedMemoryAs
<Result
*>(
10264 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10266 return error::kOutOfBounds
;
10268 // Check that the client initialized the result.
10269 if (result
->size
!= 0) {
10270 return error::kInvalidArguments
;
10273 glGetAttachedShaders(
10274 program
->service_id(), max_count
, &count
, result
->GetData());
10275 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10276 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10277 &result
->GetData()[ii
])) {
10279 return error::kGenericError
;
10282 result
->SetNumResults(count
);
10283 return error::kNoError
;
10286 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10287 uint32 immediate_data_size
,
10288 const void* cmd_data
) {
10289 const gles2::cmds::GetActiveUniform
& c
=
10290 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10291 GLuint program_id
= c
.program
;
10292 GLuint index
= c
.index
;
10293 uint32 name_bucket_id
= c
.name_bucket_id
;
10294 typedef cmds::GetActiveUniform::Result Result
;
10295 Result
* result
= GetSharedMemoryAs
<Result
*>(
10296 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10298 return error::kOutOfBounds
;
10300 // Check that the client initialized the result.
10301 if (result
->success
!= 0) {
10302 return error::kInvalidArguments
;
10304 Program
* program
= GetProgramInfoNotShader(
10305 program_id
, "glGetActiveUniform");
10307 return error::kNoError
;
10309 const Program::UniformInfo
* uniform_info
=
10310 program
->GetUniformInfo(index
);
10311 if (!uniform_info
) {
10312 LOCAL_SET_GL_ERROR(
10313 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10314 return error::kNoError
;
10316 result
->success
= 1; // true.
10317 result
->size
= uniform_info
->size
;
10318 result
->type
= uniform_info
->type
;
10319 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10320 bucket
->SetFromString(uniform_info
->name
.c_str());
10321 return error::kNoError
;
10324 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10325 uint32 immediate_data_size
, const void* cmd_data
) {
10326 if (!unsafe_es3_apis_enabled())
10327 return error::kUnknownCommand
;
10328 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10329 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10330 GLuint program_id
= c
.program
;
10331 GLuint index
= static_cast<GLuint
>(c
.index
);
10332 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10333 Program
* program
= GetProgramInfoNotShader(
10334 program_id
, "glGetActiveUniformBlockiv");
10336 return error::kNoError
;
10338 GLuint service_id
= program
->service_id();
10339 GLint link_status
= GL_FALSE
;
10340 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10341 if (link_status
!= GL_TRUE
) {
10342 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10343 "glGetActiveActiveUniformBlockiv", "program not linked");
10344 return error::kNoError
;
10346 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10347 GLsizei num_values
= 1;
10348 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10350 glGetActiveUniformBlockiv(
10351 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10352 GLenum error
= glGetError();
10353 if (error
!= GL_NO_ERROR
) {
10354 // Assume this will the same error if calling with pname.
10355 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10356 return error::kNoError
;
10358 num_values
= static_cast<GLsizei
>(num
);
10360 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10361 Result
* result
= GetSharedMemoryAs
<Result
*>(
10362 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10363 GLint
* params
= result
? result
->GetData() : NULL
;
10364 if (params
== NULL
) {
10365 return error::kOutOfBounds
;
10367 // Check that the client initialized the result.
10368 if (result
->size
!= 0) {
10369 return error::kInvalidArguments
;
10371 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10372 GLenum error
= glGetError();
10373 if (error
== GL_NO_ERROR
) {
10374 result
->SetNumResults(num_values
);
10376 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10378 return error::kNoError
;
10381 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10382 uint32 immediate_data_size
, const void* cmd_data
) {
10383 if (!unsafe_es3_apis_enabled())
10384 return error::kUnknownCommand
;
10385 const gles2::cmds::GetActiveUniformBlockName
& c
=
10386 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10387 GLuint program_id
= c
.program
;
10388 GLuint index
= c
.index
;
10389 uint32 name_bucket_id
= c
.name_bucket_id
;
10390 typedef cmds::GetActiveUniformBlockName::Result Result
;
10391 Result
* result
= GetSharedMemoryAs
<Result
*>(
10392 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10394 return error::kOutOfBounds
;
10396 // Check that the client initialized the result.
10397 if (*result
!= 0) {
10398 return error::kInvalidArguments
;
10400 Program
* program
= GetProgramInfoNotShader(
10401 program_id
, "glGetActiveUniformBlockName");
10403 return error::kNoError
;
10405 GLuint service_id
= program
->service_id();
10406 GLint link_status
= GL_FALSE
;
10407 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10408 if (link_status
!= GL_TRUE
) {
10409 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10410 "glGetActiveActiveUniformBlockName", "program not linked");
10411 return error::kNoError
;
10413 GLint max_length
= 0;
10415 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10416 // Increase one so &buffer[0] is always valid.
10417 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10418 std::vector
<char> buffer(buf_size
);
10419 GLsizei length
= 0;
10420 glGetActiveUniformBlockName(
10421 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10424 return error::kNoError
;
10427 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10428 DCHECK_GT(buf_size
, length
);
10429 DCHECK_EQ(0, buffer
[length
]);
10430 bucket
->SetFromString(&buffer
[0]);
10431 return error::kNoError
;
10434 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10435 uint32 immediate_data_size
, const void* cmd_data
) {
10436 if (!unsafe_es3_apis_enabled())
10437 return error::kUnknownCommand
;
10438 const gles2::cmds::GetActiveUniformsiv
& c
=
10439 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10440 GLuint program_id
= c
.program
;
10441 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10442 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10444 return error::kInvalidArguments
;
10446 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10447 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10448 typedef cmds::GetActiveUniformsiv::Result Result
;
10449 Result
* result
= GetSharedMemoryAs
<Result
*>(
10450 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10451 GLint
* params
= result
? result
->GetData() : NULL
;
10452 if (params
== NULL
) {
10453 return error::kOutOfBounds
;
10455 // Check that the client initialized the result.
10456 if (result
->size
!= 0) {
10457 return error::kInvalidArguments
;
10459 Program
* program
= GetProgramInfoNotShader(
10460 program_id
, "glGetActiveUniformsiv");
10462 return error::kNoError
;
10464 GLuint service_id
= program
->service_id();
10465 GLint link_status
= GL_FALSE
;
10466 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10467 if (link_status
!= GL_TRUE
) {
10468 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10469 "glGetActiveUniformsiv", "program not linked");
10470 return error::kNoError
;
10472 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10473 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10474 GLenum error
= glGetError();
10475 if (error
== GL_NO_ERROR
) {
10476 result
->SetNumResults(count
);
10478 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10480 return error::kNoError
;
10483 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10484 const void* cmd_data
) {
10485 const gles2::cmds::GetActiveAttrib
& c
=
10486 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10487 GLuint program_id
= c
.program
;
10488 GLuint index
= c
.index
;
10489 uint32 name_bucket_id
= c
.name_bucket_id
;
10490 typedef cmds::GetActiveAttrib::Result Result
;
10491 Result
* result
= GetSharedMemoryAs
<Result
*>(
10492 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10494 return error::kOutOfBounds
;
10496 // Check that the client initialized the result.
10497 if (result
->success
!= 0) {
10498 return error::kInvalidArguments
;
10500 Program
* program
= GetProgramInfoNotShader(
10501 program_id
, "glGetActiveAttrib");
10503 return error::kNoError
;
10505 const Program::VertexAttrib
* attrib_info
=
10506 program
->GetAttribInfo(index
);
10507 if (!attrib_info
) {
10508 LOCAL_SET_GL_ERROR(
10509 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10510 return error::kNoError
;
10512 result
->success
= 1; // true.
10513 result
->size
= attrib_info
->size
;
10514 result
->type
= attrib_info
->type
;
10515 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10516 bucket
->SetFromString(attrib_info
->name
.c_str());
10517 return error::kNoError
;
10520 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10521 const void* cmd_data
) {
10522 #if 1 // No binary shader support.
10523 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10524 return error::kNoError
;
10526 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10528 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10529 return error::kNoError
;
10531 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10533 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10534 return error::kNoError
;
10537 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10538 return error::kOutOfBounds
;
10540 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10541 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10542 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10543 const void* binary
= GetSharedMemoryAs
<const void*>(
10544 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10545 if (shaders
== NULL
|| binary
== NULL
) {
10546 return error::kOutOfBounds
;
10548 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10549 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10550 Shader
* shader
= GetShader(shaders
[ii
]);
10552 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10553 return error::kNoError
;
10555 service_ids
[ii
] = shader
->service_id();
10557 // TODO(gman): call glShaderBinary
10558 return error::kNoError
;
10562 void GLES2DecoderImpl::DoSwapBuffers() {
10563 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10565 int this_frame_number
= frame_number_
++;
10566 // TRACE_EVENT for gpu tests:
10567 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10568 TRACE_EVENT_SCOPE_THREAD
,
10569 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10570 "width", (is_offscreen
? offscreen_size_
.width() :
10571 surface_
->GetSize().width()));
10572 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10573 "offscreen", is_offscreen
,
10574 "frame", this_frame_number
);
10576 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10579 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10580 "gpu_toplevel", "SwapBuffer");
10583 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10586 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10587 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10588 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10591 // If offscreen then don't actually SwapBuffers to the display. Just copy
10592 // the rendered frame to another frame buffer.
10593 if (is_offscreen
) {
10594 TRACE_EVENT2("gpu", "Offscreen",
10595 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10596 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10597 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10598 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10600 if (workarounds().needs_offscreen_buffer_workaround
) {
10601 offscreen_saved_frame_buffer_
->Create();
10605 // Allocate the offscreen saved color texture.
10606 DCHECK(offscreen_saved_color_format_
);
10607 offscreen_saved_color_texture_
->AllocateStorage(
10608 offscreen_size_
, offscreen_saved_color_format_
, false);
10610 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10611 offscreen_saved_color_texture_
.get());
10612 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10613 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10614 GL_FRAMEBUFFER_COMPLETE
) {
10615 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10616 << "because offscreen saved FBO was incomplete.";
10617 MarkContextLost(error::kUnknown
);
10618 group_
->LoseContexts(error::kUnknown
);
10622 // Clear the offscreen color texture.
10623 // TODO(piman): Is this still necessary?
10625 ScopedFrameBufferBinder
binder(this,
10626 offscreen_saved_frame_buffer_
->id());
10627 glClearColor(0, 0, 0, 0);
10628 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10629 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10630 glClear(GL_COLOR_BUFFER_BIT
);
10631 RestoreClearState();
10635 UpdateParentTextureInfo();
10638 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10640 ScopedGLErrorSuppressor
suppressor(
10641 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10643 if (IsOffscreenBufferMultisampled()) {
10644 // For multisampled buffers, resolve the frame buffer.
10645 ScopedResolvedFrameBufferBinder
binder(this, true, false);
10647 ScopedFrameBufferBinder
binder(this,
10648 offscreen_target_frame_buffer_
->id());
10650 if (offscreen_target_buffer_preserved_
) {
10651 // Copy the target frame buffer to the saved offscreen texture.
10652 offscreen_saved_color_texture_
->Copy(
10653 offscreen_saved_color_texture_
->size(),
10654 offscreen_saved_color_format_
);
10656 // Flip the textures in the parent context via the texture manager.
10657 if (!!offscreen_saved_color_texture_info_
.get())
10658 offscreen_saved_color_texture_info_
->texture()->
10659 SetServiceId(offscreen_target_color_texture_
->id());
10661 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
10662 offscreen_target_frame_buffer_
->AttachRenderTexture(
10663 offscreen_target_color_texture_
.get());
10666 // Ensure the side effects of the copy are visible to the parent
10667 // context. There is no need to do this for ANGLE because it uses a
10668 // single D3D device for all contexts.
10669 if (!feature_info_
->gl_version_info().is_angle
)
10673 if (!surface_
->SwapBuffers()) {
10674 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
10675 if (!CheckResetStatus()) {
10676 MarkContextLost(error::kUnknown
);
10677 group_
->LoseContexts(error::kUnknown
);
10682 // This may be a slow command. Exit command processing to allow for
10683 // context preemption and GPU watchdog checks.
10684 ExitCommandProcessingEarly();
10687 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
10688 context_
->SetSwapInterval(interval
);
10691 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10692 uint32 immediate_data_size
,
10693 const void* cmd_data
) {
10694 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
10695 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
10696 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10697 if (!bucket
|| bucket
->size() == 0) {
10698 return error::kInvalidArguments
;
10700 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
10701 Result
* result
= GetSharedMemoryAs
<Result
*>(
10702 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10704 return error::kOutOfBounds
;
10706 // Check that the client initialized the result.
10707 if (*result
!= 0) {
10708 return error::kInvalidArguments
;
10710 std::string feature_str
;
10711 if (!bucket
->GetAsString(&feature_str
)) {
10712 return error::kInvalidArguments
;
10715 // TODO(gman): make this some kind of table to function pointer thingy.
10716 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10717 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10718 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
10719 buffer_manager()->set_allow_fixed_attribs(true);
10720 // TODO(gman): decide how to remove the need for this const_cast.
10721 // I could make validators_ non const but that seems bad as this is the only
10722 // place it is needed. I could make some special friend class of validators
10723 // just to allow this to set them. That seems silly. I could refactor this
10724 // code to use the extension mechanism or the initialization attributes to
10725 // turn this feature on. Given that the only real point of this is to make
10726 // the conformance tests pass and given that there is lots of real work that
10727 // needs to be done it seems like refactoring for one to one of those
10728 // methods is a very low priority.
10729 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
10730 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
10731 force_webgl_glsl_validation_
= true;
10732 InitializeShaderTranslator();
10734 return error::kNoError
;
10737 *result
= 1; // true.
10738 return error::kNoError
;
10741 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10742 uint32 immediate_data_size
,
10743 const void* cmd_data
) {
10744 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
10745 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
10747 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
10748 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
10749 info
->Initialize(disallowed_features_
);
10750 bucket
->SetFromString(info
->extensions().c_str());
10751 return error::kNoError
;
10754 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10755 uint32 immediate_data_size
,
10756 const void* cmd_data
) {
10757 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
10758 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
10759 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10760 if (!bucket
|| bucket
->size() == 0) {
10761 return error::kInvalidArguments
;
10763 std::string feature_str
;
10764 if (!bucket
->GetAsString(&feature_str
)) {
10765 return error::kInvalidArguments
;
10768 bool desire_webgl_glsl_validation
=
10769 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
10770 bool desire_standard_derivatives
= false;
10771 bool desire_frag_depth
= false;
10772 bool desire_draw_buffers
= false;
10773 bool desire_shader_texture_lod
= false;
10774 if (force_webgl_glsl_validation_
) {
10775 desire_standard_derivatives
=
10776 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
10777 desire_frag_depth
=
10778 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
10779 desire_draw_buffers
=
10780 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
10781 desire_shader_texture_lod
=
10782 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
10785 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
10786 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
10787 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
10788 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
10789 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
10790 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
10791 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
10792 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
10793 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
10794 InitializeShaderTranslator();
10797 UpdateCapabilities();
10799 return error::kNoError
;
10802 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10803 uint32 immediate_data_size
,
10804 const void* cmd_data
) {
10805 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
10806 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
10807 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10808 uint32 bucket_id
= c
.bucket_id
;
10809 Bucket
* bucket
= CreateBucket(bucket_id
);
10810 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
10811 Program
* program
= NULL
;
10812 program
= GetProgram(program_id
);
10813 if (!program
|| !program
->IsValid()) {
10814 return error::kNoError
;
10816 program
->GetProgramInfo(program_manager(), bucket
);
10817 return error::kNoError
;
10820 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10821 uint32 immediate_data_size
, const void* cmd_data
) {
10822 if (!unsafe_es3_apis_enabled())
10823 return error::kUnknownCommand
;
10824 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
10825 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
10826 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10827 uint32 bucket_id
= c
.bucket_id
;
10828 Bucket
* bucket
= CreateBucket(bucket_id
);
10829 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
10830 Program
* program
= NULL
;
10831 program
= GetProgram(program_id
);
10832 if (!program
|| !program
->IsValid()) {
10833 return error::kNoError
;
10835 program
->GetUniformBlocks(bucket
);
10836 return error::kNoError
;
10839 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10840 uint32 immediate_data_size
, const void* cmd_data
) {
10841 if (!unsafe_es3_apis_enabled())
10842 return error::kUnknownCommand
;
10843 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
10844 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
10845 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10846 uint32 bucket_id
= c
.bucket_id
;
10847 Bucket
* bucket
= CreateBucket(bucket_id
);
10848 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
10849 Program
* program
= NULL
;
10850 program
= GetProgram(program_id
);
10851 if (!program
|| !program
->IsValid()) {
10852 return error::kNoError
;
10854 program
->GetUniformsES3(bucket
);
10855 return error::kNoError
;
10858 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10859 uint32 immediate_data_size
,
10860 const void* cmd_data
) {
10861 if (!unsafe_es3_apis_enabled())
10862 return error::kUnknownCommand
;
10863 const gles2::cmds::GetTransformFeedbackVarying
& c
=
10864 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
10865 GLuint program_id
= c
.program
;
10866 GLuint index
= c
.index
;
10867 uint32 name_bucket_id
= c
.name_bucket_id
;
10868 typedef cmds::GetTransformFeedbackVarying::Result Result
;
10869 Result
* result
= GetSharedMemoryAs
<Result
*>(
10870 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10872 return error::kOutOfBounds
;
10874 // Check that the client initialized the result.
10875 if (result
->success
!= 0) {
10876 return error::kInvalidArguments
;
10878 Program
* program
= GetProgramInfoNotShader(
10879 program_id
, "glGetTransformFeedbackVarying");
10881 return error::kNoError
;
10883 GLuint service_id
= program
->service_id();
10884 GLint link_status
= GL_FALSE
;
10885 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10886 if (link_status
!= GL_TRUE
) {
10887 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10888 "glGetTransformFeedbackVarying", "program not linked");
10889 return error::kNoError
;
10891 GLint max_length
= 0;
10893 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
10894 max_length
= std::max(1, max_length
);
10895 std::vector
<char> buffer(max_length
);
10896 GLsizei length
= 0;
10899 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10900 glGetTransformFeedbackVarying(
10901 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
10902 GLenum error
= glGetError();
10903 if (error
!= GL_NO_ERROR
) {
10904 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
10905 return error::kNoError
;
10907 result
->success
= 1; // true.
10908 result
->size
= static_cast<int32_t>(size
);
10909 result
->type
= static_cast<uint32_t>(type
);
10910 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10911 DCHECK(length
>= 0 && length
< max_length
);
10912 buffer
[length
] = '\0'; // Just to be safe.
10913 bucket
->SetFromString(&buffer
[0]);
10914 return error::kNoError
;
10917 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10918 uint32 immediate_data_size
, const void* cmd_data
) {
10919 if (!unsafe_es3_apis_enabled())
10920 return error::kUnknownCommand
;
10921 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
10922 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
10924 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10925 uint32 bucket_id
= c
.bucket_id
;
10926 Bucket
* bucket
= CreateBucket(bucket_id
);
10927 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
10928 Program
* program
= NULL
;
10929 program
= GetProgram(program_id
);
10930 if (!program
|| !program
->IsValid()) {
10931 return error::kNoError
;
10933 program
->GetTransformFeedbackVaryings(bucket
);
10934 return error::kNoError
;
10937 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
10938 return context_lost_reason_
;
10941 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
10942 GLenum reset_status
) const {
10943 switch (reset_status
) {
10945 // TODO(kbr): improve the precision of the error code in this case.
10946 // Consider delegating to context for error code if MakeCurrent fails.
10947 return error::kUnknown
;
10948 case GL_GUILTY_CONTEXT_RESET_ARB
:
10949 return error::kGuilty
;
10950 case GL_INNOCENT_CONTEXT_RESET_ARB
:
10951 return error::kInnocent
;
10952 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
10953 return error::kUnknown
;
10957 return error::kUnknown
;
10960 bool GLES2DecoderImpl::WasContextLost() const {
10961 return context_was_lost_
;
10964 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
10965 return WasContextLost() && reset_by_robustness_extension_
;
10968 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
10969 // Only lose the context once.
10970 if (WasContextLost())
10973 // Don't make GL calls in here, the context might not be current.
10974 context_lost_reason_
= reason
;
10975 current_decoder_error_
= error::kLostContext
;
10976 context_was_lost_
= true;
10978 // Some D3D drivers cannot recover from device lost in the GPU process
10979 // sandbox. Allow a new GPU process to launch.
10980 if (workarounds().exit_on_context_lost
) {
10981 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
10982 << " a D3D device in the Chrome GPU process sandbox.";
10983 #if defined(OS_WIN)
10984 base::win::SetShouldCrashOnProcessDetach(false);
10990 bool GLES2DecoderImpl::CheckResetStatus() {
10991 DCHECK(!WasContextLost());
10992 DCHECK(context_
->IsCurrent(NULL
));
10994 if (IsRobustnessSupported()) {
10995 // If the reason for the call was a GL error, we can try to determine the
10996 // reset status more accurately.
10997 GLenum driver_status
= glGetGraphicsResetStatusARB();
10998 if (driver_status
== GL_NO_ERROR
)
11001 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11002 << " context lost via ARB/EXT_robustness. Reset status = "
11003 << GLES2Util::GetStringEnum(driver_status
);
11005 // Don't pretend we know which client was responsible.
11006 if (workarounds().use_virtualized_gl_contexts
)
11007 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11009 switch (driver_status
) {
11010 case GL_GUILTY_CONTEXT_RESET_ARB
:
11011 MarkContextLost(error::kGuilty
);
11013 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11014 MarkContextLost(error::kInnocent
);
11016 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11017 MarkContextLost(error::kUnknown
);
11023 reset_by_robustness_extension_
= true;
11029 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11030 uint32 immediate_data_size
,
11031 const void* cmd_data
) {
11032 return error::kUnknownCommand
;
11035 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11036 uint32 immediate_data_size
,
11037 const void* cmd_data
) {
11038 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11039 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11040 uint32 sync_point
= c
.sync_point
;
11041 if (wait_sync_point_callback_
.is_null())
11042 return error::kNoError
;
11044 return wait_sync_point_callback_
.Run(sync_point
) ?
11045 error::kNoError
: error::kDeferCommandUntilLater
;
11048 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11049 uint32 immediate_data_size
,
11050 const void* cmd_data
) {
11051 if (surface_
->DeferDraws())
11052 return error::kDeferCommandUntilLater
;
11053 if (!surface_
->SetBackbufferAllocation(false))
11054 return error::kLostContext
;
11055 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11056 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11057 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11058 return error::kNoError
;
11061 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11062 GLsizei n
, const GLuint
* client_ids
) {
11063 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11064 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11068 query_manager_
->GenQueries(n
, client_ids
);
11072 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11073 GLsizei n
, const GLuint
* client_ids
) {
11074 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11075 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
11076 if (query
&& !query
->IsDeleted()) {
11077 ContextState::QueryMap::iterator it
=
11078 state_
.current_queries
.find(query
->target());
11079 if (it
!= state_
.current_queries
.end())
11080 state_
.current_queries
.erase(it
);
11082 query
->Destroy(true);
11084 query_manager_
->RemoveQuery(client_ids
[ii
]);
11088 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11089 if (query_manager_
.get() == NULL
) {
11092 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11093 current_decoder_error_
= error::kOutOfBounds
;
11095 return query_manager_
->HavePendingQueries();
11098 // Note that if there are no pending readpixels right now,
11099 // this function will call the callback immediately.
11100 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11101 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11102 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11108 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11109 while (!pending_readpixel_fences_
.empty() &&
11110 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
11111 std::vector
<base::Closure
> callbacks
=
11112 pending_readpixel_fences_
.front()->callbacks
;
11113 pending_readpixel_fences_
.pop();
11114 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11115 callbacks
[i
].Run();
11120 bool GLES2DecoderImpl::HasMoreIdleWork() {
11121 return !pending_readpixel_fences_
.empty() ||
11122 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11125 void GLES2DecoderImpl::PerformIdleWork() {
11126 ProcessPendingReadPixels();
11127 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11129 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11130 ProcessFinishedAsyncTransfers();
11133 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11134 const void* cmd_data
) {
11135 const gles2::cmds::BeginQueryEXT
& c
=
11136 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11137 GLenum target
= static_cast<GLenum
>(c
.target
);
11138 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11139 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11140 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11143 case GL_COMMANDS_ISSUED_CHROMIUM
:
11144 case GL_LATENCY_QUERY_CHROMIUM
:
11145 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11146 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11147 case GL_GET_ERROR_QUERY_CHROMIUM
:
11149 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11150 if (!features().chromium_sync_query
) {
11151 LOCAL_SET_GL_ERROR(
11152 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11153 "not enabled for commands completed queries");
11154 return error::kNoError
;
11158 if (!features().occlusion_query_boolean
) {
11159 LOCAL_SET_GL_ERROR(
11160 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11161 "not enabled for occlusion queries");
11162 return error::kNoError
;
11167 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
11168 LOCAL_SET_GL_ERROR(
11169 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11170 return error::kNoError
;
11173 if (client_id
== 0) {
11174 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11175 return error::kNoError
;
11178 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11180 if (!query_manager_
->IsValidQuery(client_id
)) {
11181 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11183 "id not made by glGenQueriesEXT");
11184 return error::kNoError
;
11186 query
= query_manager_
->CreateQuery(
11187 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11190 if (query
->target() != target
) {
11191 LOCAL_SET_GL_ERROR(
11192 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11193 return error::kNoError
;
11194 } else if (query
->shm_id() != sync_shm_id
||
11195 query
->shm_offset() != sync_shm_offset
) {
11196 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11197 return error::kInvalidArguments
;
11200 if (!query_manager_
->BeginQuery(query
)) {
11201 return error::kOutOfBounds
;
11204 state_
.current_queries
[target
] = query
;
11205 return error::kNoError
;
11208 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11209 const void* cmd_data
) {
11210 const gles2::cmds::EndQueryEXT
& c
=
11211 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11212 GLenum target
= static_cast<GLenum
>(c
.target
);
11213 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11214 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
11216 if (it
== state_
.current_queries
.end()) {
11217 LOCAL_SET_GL_ERROR(
11218 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11219 return error::kNoError
;
11222 QueryManager::Query
* query
= it
->second
.get();
11223 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11224 return error::kOutOfBounds
;
11227 query_manager_
->ProcessPendingTransferQueries();
11229 state_
.current_queries
.erase(it
);
11230 return error::kNoError
;
11233 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11234 GLsizei n
, const GLuint
* client_ids
) {
11235 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11236 if (GetVertexAttribManager(client_ids
[ii
])) {
11241 if (!features().native_vertex_array_object
) {
11243 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11244 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11247 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11249 glGenVertexArraysOES(n
, service_ids
.get());
11250 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11251 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11258 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11259 GLsizei n
, const GLuint
* client_ids
) {
11260 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11261 VertexAttribManager
* vao
=
11262 GetVertexAttribManager(client_ids
[ii
]);
11263 if (vao
&& !vao
->IsDeleted()) {
11264 if (state_
.vertex_attrib_manager
.get() == vao
) {
11265 DoBindVertexArrayOES(0);
11267 RemoveVertexAttribManager(client_ids
[ii
]);
11272 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11273 VertexAttribManager
* vao
= NULL
;
11274 if (client_id
!= 0) {
11275 vao
= GetVertexAttribManager(client_id
);
11277 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11278 // only allows names that have been previously generated. As such, we do
11279 // not generate new names here.
11280 LOCAL_SET_GL_ERROR(
11281 GL_INVALID_OPERATION
,
11282 "glBindVertexArrayOES", "bad vertex array id.");
11283 current_decoder_error_
= error::kNoError
;
11287 vao
= state_
.default_vertex_attrib_manager
.get();
11290 // Only set the VAO state if it's changed
11291 if (state_
.vertex_attrib_manager
.get() != vao
) {
11292 state_
.vertex_attrib_manager
= vao
;
11293 if (!features().native_vertex_array_object
) {
11294 EmulateVertexArrayState();
11296 GLuint service_id
= vao
->service_id();
11297 glBindVertexArrayOES(service_id
);
11302 // Used when OES_vertex_array_object isn't natively supported
11303 void GLES2DecoderImpl::EmulateVertexArrayState() {
11304 // Setup the Vertex attribute state
11305 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11306 RestoreStateForAttrib(vv
, true);
11309 // Setup the element buffer
11310 Buffer
* element_array_buffer
=
11311 state_
.vertex_attrib_manager
->element_array_buffer();
11312 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11313 element_array_buffer
? element_array_buffer
->service_id() : 0);
11316 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11317 const VertexAttribManager
* vao
=
11318 GetVertexAttribManager(client_id
);
11319 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11322 #if defined(OS_MACOSX)
11323 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11324 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11326 if (it
!= texture_to_io_surface_map_
.end()) {
11327 // Found a previous IOSurface bound to this texture; release it.
11328 IOSurfaceRef surface
= it
->second
;
11329 CFRelease(surface
);
11330 texture_to_io_surface_map_
.erase(it
);
11335 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11336 GLenum target
, GLsizei width
, GLsizei height
,
11337 GLuint io_surface_id
, GLuint plane
) {
11338 #if defined(OS_MACOSX)
11339 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11340 LOCAL_SET_GL_ERROR(
11341 GL_INVALID_OPERATION
,
11342 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11346 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11347 // This might be supported in the future, and if we could require
11348 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11349 // could delete a lot of code. For now, perform strict validation so we
11350 // know what's going on.
11351 LOCAL_SET_GL_ERROR(
11352 GL_INVALID_OPERATION
,
11353 "glTexImageIOSurface2DCHROMIUM",
11354 "requires TEXTURE_RECTANGLE_ARB target");
11358 // Default target might be conceptually valid, but disallow it to avoid
11360 TextureRef
* texture_ref
=
11361 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11362 if (!texture_ref
) {
11363 LOCAL_SET_GL_ERROR(
11364 GL_INVALID_OPERATION
,
11365 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11369 // Look up the new IOSurface. Note that because of asynchrony
11370 // between processes this might fail; during live resizing the
11371 // plugin process might allocate and release an IOSurface before
11372 // this process gets a chance to look it up. Hold on to any old
11373 // IOSurface in this case.
11374 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11376 LOCAL_SET_GL_ERROR(
11377 GL_INVALID_OPERATION
,
11378 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11382 // Release any IOSurface previously bound to this texture.
11383 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11385 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11386 texture_to_io_surface_map_
.insert(
11387 std::make_pair(texture_ref
->service_id(), surface
));
11389 CGLContextObj context
=
11390 static_cast<CGLContextObj
>(context_
->GetHandle());
11392 CGLError err
= CGLTexImageIOSurface2D(
11399 GL_UNSIGNED_INT_8_8_8_8_REV
,
11403 if (err
!= kCGLNoError
) {
11404 LOCAL_SET_GL_ERROR(
11405 GL_INVALID_OPERATION
,
11406 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11410 texture_manager()->SetLevelInfo(
11411 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
11412 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
11415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11416 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11420 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11421 switch (internalformat
) {
11432 case GL_LUMINANCE8_ALPHA8_EXT
:
11433 return GL_LUMINANCE_ALPHA
;
11434 case GL_LUMINANCE8_EXT
:
11435 return GL_LUMINANCE
;
11436 case GL_ALPHA8_EXT
:
11438 case GL_RGBA32F_EXT
:
11440 case GL_RGB32F_EXT
:
11442 case GL_ALPHA32F_EXT
:
11444 case GL_LUMINANCE32F_EXT
:
11445 return GL_LUMINANCE
;
11446 case GL_LUMINANCE_ALPHA32F_EXT
:
11447 return GL_LUMINANCE_ALPHA
;
11448 case GL_RGBA16F_EXT
:
11450 case GL_RGB16F_EXT
:
11452 case GL_ALPHA16F_EXT
:
11454 case GL_LUMINANCE16F_EXT
:
11455 return GL_LUMINANCE
;
11456 case GL_LUMINANCE_ALPHA16F_EXT
:
11457 return GL_LUMINANCE_ALPHA
;
11459 return GL_BGRA_EXT
;
11460 case GL_SRGB8_ALPHA8_EXT
:
11461 return GL_SRGB_ALPHA_EXT
;
11467 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11468 const char* function_name
,
11470 TextureRef
* source_texture_ref
,
11471 TextureRef
* dest_texture_ref
,
11472 GLenum dest_internal_format
) {
11473 if (!source_texture_ref
|| !dest_texture_ref
) {
11474 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
11478 if (GL_TEXTURE_2D
!= target
) {
11479 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11480 "invalid texture target");
11484 Texture
* source_texture
= source_texture_ref
->texture();
11485 Texture
* dest_texture
= dest_texture_ref
->texture();
11486 if (source_texture
== dest_texture
) {
11487 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11488 "source and destination textures are the same");
11492 if (dest_texture
->target() != GL_TEXTURE_2D
||
11493 (source_texture
->target() != GL_TEXTURE_2D
&&
11494 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
11495 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
11496 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11497 "invalid texture target binding");
11501 GLenum source_type
= 0;
11502 GLenum source_internal_format
= 0;
11503 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11504 &source_internal_format
);
11506 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11507 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11508 // renderable on some platforms.
11509 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
11510 dest_internal_format
== GL_RGBA
||
11511 dest_internal_format
== GL_BGRA_EXT
;
11512 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11513 source_internal_format
== GL_RGB
||
11514 source_internal_format
== GL_RGBA
||
11515 source_internal_format
== GL_LUMINANCE
||
11516 source_internal_format
== GL_LUMINANCE_ALPHA
||
11517 source_internal_format
== GL_BGRA_EXT
;
11518 if (!valid_source_format
|| !valid_dest_format
) {
11519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11520 "invalid internal format");
11526 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target
,
11529 GLenum internal_format
,
11530 GLenum dest_type
) {
11531 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11533 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11534 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11535 Texture
* source_texture
= source_texture_ref
->texture();
11536 Texture
* dest_texture
= dest_texture_ref
->texture();
11537 int source_width
= 0;
11538 int source_height
= 0;
11539 gfx::GLImage
* image
=
11540 source_texture
->GetLevelImage(source_texture
->target(), 0);
11542 gfx::Size size
= image
->GetSize();
11543 source_width
= size
.width();
11544 source_height
= size
.height();
11545 if (source_width
<= 0 || source_height
<= 0) {
11546 LOCAL_SET_GL_ERROR(
11548 "glCopyTextureChromium", "invalid image size");
11552 if (!source_texture
->GetLevelSize(
11553 source_texture
->target(), 0, &source_width
, &source_height
)) {
11554 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
11555 "glCopyTextureChromium",
11556 "source texture has no level 0");
11560 // Check that this type of texture is allowed.
11561 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11562 source_width
, source_height
, 1)) {
11563 LOCAL_SET_GL_ERROR(
11564 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11569 GLenum source_type
= 0;
11570 GLenum source_internal_format
= 0;
11571 source_texture
->GetLevelType(
11572 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11574 if (dest_texture
->IsImmutable()) {
11575 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
11576 "texture is immutable");
11580 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
11581 source_texture_ref
, dest_texture_ref
,
11582 internal_format
)) {
11586 // Clear the source texture if necessary.
11587 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11588 source_texture
->target(), 0)) {
11589 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
11590 "dimensions too big");
11594 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11595 // needed because it takes 10s of milliseconds to initialize.
11596 if (!copy_texture_CHROMIUM_
.get()) {
11597 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11598 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11599 copy_texture_CHROMIUM_
->Initialize(this);
11600 RestoreCurrentFramebufferBindings();
11601 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11605 GLenum dest_type_previous
= dest_type
;
11606 GLenum dest_internal_format
= internal_format
;
11607 int dest_width
= 0;
11608 int dest_height
= 0;
11609 bool dest_level_defined
=
11610 dest_texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
);
11612 if (dest_level_defined
) {
11613 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
11614 &dest_internal_format
);
11617 // Resize the destination texture to the dimensions of the source texture.
11618 if (!dest_level_defined
|| dest_width
!= source_width
||
11619 dest_height
!= source_height
||
11620 dest_internal_format
!= internal_format
||
11621 dest_type_previous
!= dest_type
) {
11622 // Ensure that the glTexImage2D succeeds.
11623 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11624 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11625 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
11626 0, internal_format
, dest_type
, NULL
);
11627 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11628 if (error
!= GL_NO_ERROR
) {
11629 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11633 texture_manager()->SetLevelInfo(
11634 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
11635 source_height
, 1, 0, internal_format
, dest_type
, true);
11637 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11641 ScopedModifyPixels
modify(dest_texture_ref
);
11643 // Try using GLImage::CopyTexImage when possible.
11644 bool unpack_premultiply_alpha_change
=
11645 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11646 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
11647 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11648 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11652 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11654 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11655 // before presenting.
11656 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11657 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11658 // instead of using kIdentityMatrix crbug.com/226218.
11659 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
11660 this, source_texture
->target(), source_texture
->service_id(),
11661 dest_texture
->service_id(), source_width
, source_height
, unpack_flip_y_
,
11662 unpack_premultiply_alpha_
, unpack_unpremultiply_alpha_
,
11665 copy_texture_CHROMIUM_
->DoCopyTexture(
11666 this, source_texture
->target(), source_texture
->service_id(),
11667 source_internal_format
, dest_texture
->service_id(), internal_format
,
11668 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11669 unpack_unpremultiply_alpha_
);
11672 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11675 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target
,
11680 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11682 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11683 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11684 Texture
* source_texture
= source_texture_ref
->texture();
11685 Texture
* dest_texture
= dest_texture_ref
->texture();
11686 int source_width
= 0;
11687 int source_height
= 0;
11688 gfx::GLImage
* image
=
11689 source_texture
->GetLevelImage(source_texture
->target(), 0);
11691 gfx::Size size
= image
->GetSize();
11692 source_width
= size
.width();
11693 source_height
= size
.height();
11694 if (source_width
<= 0 || source_height
<= 0) {
11695 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11696 "invalid image size");
11700 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11701 &source_width
, &source_height
)) {
11702 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11703 "source texture has no level 0");
11707 // Check that this type of texture is allowed.
11708 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11709 source_width
, source_height
, 1)) {
11710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11711 "source texture bad dimensions");
11716 GLenum source_type
= 0;
11717 GLenum source_internal_format
= 0;
11718 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11719 &source_internal_format
);
11720 GLenum dest_type
= 0;
11721 GLenum dest_internal_format
= 0;
11722 bool dest_level_defined
= dest_texture
->GetLevelType(
11723 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
11724 if (!dest_level_defined
) {
11725 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
11726 "destination texture is not defined");
11729 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
11730 yoffset
, source_width
, source_height
,
11732 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11733 "destination texture bad dimensions.");
11737 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
11738 source_texture_ref
, dest_texture_ref
,
11739 dest_internal_format
)) {
11743 // Clear the source texture if necessary.
11744 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11745 source_texture
->target(), 0)) {
11746 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11747 "source texture dimensions too big");
11751 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11752 // needed because it takes 10s of milliseconds to initialize.
11753 if (!copy_texture_CHROMIUM_
.get()) {
11754 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11755 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11756 copy_texture_CHROMIUM_
->Initialize(this);
11757 RestoreCurrentFramebufferBindings();
11758 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
11762 int dest_width
= 0;
11763 int dest_height
= 0;
11765 dest_texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
);
11767 if (xoffset
!= 0 || yoffset
!= 0 || source_width
!= dest_width
||
11768 source_height
!= dest_height
) {
11769 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
11771 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11772 "destination texture dimensions too big");
11776 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11780 ScopedModifyPixels
modify(dest_texture_ref
);
11782 // Try using GLImage::CopyTexSubImage when possible.
11783 bool unpack_premultiply_alpha_change
=
11784 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11785 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&&
11786 !xoffset
&& !yoffset
) {
11787 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11788 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11792 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11794 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11795 // before presenting.
11796 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11797 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11798 // instead of using kIdentityMatrix crbug.com/226218.
11799 copy_texture_CHROMIUM_
->DoCopySubTextureWithTransform(
11800 this, source_texture
->target(), source_texture
->service_id(),
11801 dest_texture
->service_id(), xoffset
, yoffset
, dest_width
, dest_height
,
11802 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11803 unpack_unpremultiply_alpha_
, kIdentityMatrix
);
11805 copy_texture_CHROMIUM_
->DoCopySubTexture(
11806 this, source_texture
->target(), source_texture
->service_id(),
11807 source_internal_format
, dest_texture
->service_id(),
11808 dest_internal_format
, xoffset
, yoffset
, dest_width
, dest_height
,
11809 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11810 unpack_unpremultiply_alpha_
);
11813 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11816 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
11817 switch (internalformat
) {
11819 return GL_UNSIGNED_SHORT_5_6_5
;
11821 return GL_UNSIGNED_SHORT_4_4_4_4
;
11823 return GL_UNSIGNED_SHORT_5_5_5_1
;
11825 return GL_UNSIGNED_BYTE
;
11827 return GL_UNSIGNED_BYTE
;
11828 case GL_LUMINANCE8_ALPHA8_EXT
:
11829 return GL_UNSIGNED_BYTE
;
11830 case GL_LUMINANCE8_EXT
:
11831 return GL_UNSIGNED_BYTE
;
11832 case GL_ALPHA8_EXT
:
11833 return GL_UNSIGNED_BYTE
;
11834 case GL_RGBA32F_EXT
:
11836 case GL_RGB32F_EXT
:
11838 case GL_ALPHA32F_EXT
:
11840 case GL_LUMINANCE32F_EXT
:
11842 case GL_LUMINANCE_ALPHA32F_EXT
:
11844 case GL_RGBA16F_EXT
:
11845 return GL_HALF_FLOAT_OES
;
11846 case GL_RGB16F_EXT
:
11847 return GL_HALF_FLOAT_OES
;
11848 case GL_ALPHA16F_EXT
:
11849 return GL_HALF_FLOAT_OES
;
11850 case GL_LUMINANCE16F_EXT
:
11851 return GL_HALF_FLOAT_OES
;
11852 case GL_LUMINANCE_ALPHA16F_EXT
:
11853 return GL_HALF_FLOAT_OES
;
11855 return GL_UNSIGNED_BYTE
;
11861 void GLES2DecoderImpl::DoTexStorage2DEXT(
11864 GLenum internal_format
,
11867 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11868 "width", width
, "height", height
);
11869 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
11870 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
11871 LOCAL_SET_GL_ERROR(
11872 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
11875 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11877 if (!texture_ref
) {
11878 LOCAL_SET_GL_ERROR(
11879 GL_INVALID_OPERATION
,
11880 "glTexStorage2DEXT", "unknown texture for target");
11883 Texture
* texture
= texture_ref
->texture();
11884 if (texture
->IsAttachedToFramebuffer()) {
11885 framebuffer_state_
.clear_state_dirty
= true;
11887 if (texture
->IsImmutable()) {
11888 LOCAL_SET_GL_ERROR(
11889 GL_INVALID_OPERATION
,
11890 "glTexStorage2DEXT", "texture is immutable");
11894 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
11895 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
11898 GLsizei level_width
= width
;
11899 GLsizei level_height
= height
;
11900 uint32 estimated_size
= 0;
11901 for (int ii
= 0; ii
< levels
; ++ii
) {
11902 uint32 level_size
= 0;
11903 if (!GLES2Util::ComputeImageDataSizes(
11904 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
11905 &estimated_size
, NULL
, NULL
) ||
11906 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
11907 LOCAL_SET_GL_ERROR(
11908 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
11911 level_width
= std::max(1, level_width
>> 1);
11912 level_height
= std::max(1, level_height
>> 1);
11914 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
11915 LOCAL_SET_GL_ERROR(
11916 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
11921 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11922 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
11923 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11924 if (error
== GL_NO_ERROR
) {
11925 GLsizei level_width
= width
;
11926 GLsizei level_height
= height
;
11927 for (int ii
= 0; ii
< levels
; ++ii
) {
11928 texture_manager()->SetLevelInfo(
11929 texture_ref
, target
, ii
, format
,
11930 level_width
, level_height
, 1, 0, format
, type
, false);
11931 level_width
= std::max(1, level_width
>> 1);
11932 level_height
= std::max(1, level_height
>> 1);
11934 texture
->SetImmutable(true);
11938 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11939 uint32 immediate_data_size
,
11940 const void* cmd_data
) {
11941 return error::kUnknownCommand
;
11944 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
11945 const GLbyte
* data
) {
11946 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11947 "context", logger_
.GetLogPrefix(),
11948 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11950 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11952 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
11955 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
11956 GLenum target
, const GLbyte
* data
) {
11957 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11958 "context", logger_
.GetLogPrefix(),
11959 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11961 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
11965 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
11966 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
11967 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11968 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
11969 "mailbox that was not generated by "
11970 "GenMailboxCHROMIUM.";
11972 if (!texture_ref
) {
11973 LOCAL_SET_GL_ERROR(
11974 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
11978 Texture
* produced
= texture_manager()->Produce(texture_ref
);
11980 LOCAL_SET_GL_ERROR(
11981 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
11985 if (produced
->target() != target
) {
11986 LOCAL_SET_GL_ERROR(
11987 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
11991 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
11994 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
11995 const GLbyte
* data
) {
11996 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11997 "context", logger_
.GetLogPrefix(),
11998 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11999 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12000 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12001 "mailbox that was not generated by "
12002 "GenMailboxCHROMIUM.";
12004 scoped_refptr
<TextureRef
> texture_ref
=
12005 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12006 if (!texture_ref
.get()) {
12007 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12008 "glConsumeTextureCHROMIUM",
12009 "unknown texture for target");
12012 GLuint client_id
= texture_ref
->client_id();
12014 LOCAL_SET_GL_ERROR(
12015 GL_INVALID_OPERATION
,
12016 "glConsumeTextureCHROMIUM", "unknown texture for target");
12019 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12021 LOCAL_SET_GL_ERROR(
12022 GL_INVALID_OPERATION
,
12023 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12026 if (texture
->target() != target
) {
12027 LOCAL_SET_GL_ERROR(
12028 GL_INVALID_OPERATION
,
12029 "glConsumeTextureCHROMIUM", "invalid target");
12033 DeleteTexturesHelper(1, &client_id
);
12034 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12035 glBindTexture(target
, texture_ref
->service_id());
12037 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
12038 unit
.bind_target
= target
;
12040 case GL_TEXTURE_2D
:
12041 unit
.bound_texture_2d
= texture_ref
;
12043 case GL_TEXTURE_CUBE_MAP
:
12044 unit
.bound_texture_cube_map
= texture_ref
;
12046 case GL_TEXTURE_EXTERNAL_OES
:
12047 unit
.bound_texture_external_oes
= texture_ref
;
12049 case GL_TEXTURE_RECTANGLE_ARB
:
12050 unit
.bound_texture_rectangle_arb
= texture_ref
;
12053 NOTREACHED(); // Validation should prevent us getting here.
12058 void GLES2DecoderImpl::EnsureTextureForClientId(
12060 GLuint client_id
) {
12061 TextureRef
* texture_ref
= GetTexture(client_id
);
12062 if (!texture_ref
) {
12064 glGenTextures(1, &service_id
);
12065 DCHECK_NE(0u, service_id
);
12066 texture_ref
= CreateTexture(client_id
, service_id
);
12067 texture_manager()->SetTarget(texture_ref
, target
);
12068 glBindTexture(target
, service_id
);
12069 RestoreCurrentTextureBindings(&state_
, target
);
12073 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12074 // provided is associated with a service_id/TextureRef for consistency, even if
12075 // the resulting texture is incomplete.
12076 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12077 uint32_t immediate_data_size
,
12078 const void* cmd_data
) {
12079 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
12081 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
12083 GLenum target
= static_cast<GLenum
>(c
.target
);
12084 uint32_t data_size
;
12085 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
12086 return error::kOutOfBounds
;
12088 if (data_size
> immediate_data_size
) {
12089 return error::kOutOfBounds
;
12091 const GLbyte
* mailbox
=
12092 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
12093 if (!validators_
->texture_bind_target
.IsValid(target
)) {
12094 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12095 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
12096 return error::kNoError
;
12098 if (mailbox
== NULL
) {
12099 return error::kOutOfBounds
;
12101 uint32_t client_id
= c
.client_id
;
12102 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
12103 return error::kNoError
;
12106 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
12107 const GLbyte
* data
, GLuint client_id
) {
12108 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12109 "context", logger_
.GetLogPrefix(),
12110 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12111 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12112 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12113 "passed a mailbox that was not "
12114 "generated by GenMailboxCHROMIUM.";
12116 TextureRef
* texture_ref
= GetTexture(client_id
);
12118 // No need to call EnsureTextureForClientId here, the client_id already has
12119 // an associated texture.
12120 LOCAL_SET_GL_ERROR(
12121 GL_INVALID_OPERATION
,
12122 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12125 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12127 EnsureTextureForClientId(target
, client_id
);
12128 LOCAL_SET_GL_ERROR(
12129 GL_INVALID_OPERATION
,
12130 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12134 if (texture
->target() != target
) {
12135 EnsureTextureForClientId(target
, client_id
);
12136 LOCAL_SET_GL_ERROR(
12137 GL_INVALID_OPERATION
,
12138 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12142 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12145 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
12146 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
12147 return valuebuffer
&& valuebuffer
->IsValid();
12150 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
12151 GLuint client_id
) {
12152 Valuebuffer
* valuebuffer
= NULL
;
12153 if (client_id
!= 0) {
12154 valuebuffer
= GetValuebuffer(client_id
);
12155 if (!valuebuffer
) {
12156 if (!group_
->bind_generates_resource()) {
12157 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
12158 "id not generated by glBindValuebufferCHROMIUM");
12162 // It's a new id so make a valuebuffer for it.
12163 CreateValuebuffer(client_id
);
12164 valuebuffer
= GetValuebuffer(client_id
);
12166 valuebuffer
->MarkAsValid();
12168 state_
.bound_valuebuffer
= valuebuffer
;
12171 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
12172 GLenum subscription
) {
12173 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12176 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
12179 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
12180 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12183 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
12186 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
12188 GLenum subscription
) {
12189 if (!CheckCurrentValuebufferForSubscription(
12190 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
12193 if (!CheckSubscriptionTarget(location
, subscription
,
12194 "glPopulateSubscribedValuesCHROMIUM")) {
12197 const ValueState
* state
=
12198 state_
.bound_valuebuffer
.get()->GetState(subscription
);
12200 switch (subscription
) {
12201 case GL_MOUSE_POSITION_CHROMIUM
:
12202 DoUniform2iv(location
, 1, state
->int_value
);
12205 NOTREACHED() << "Unhandled uniform subscription target "
12212 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12213 GLsizei length
, const GLchar
* marker
) {
12217 debug_marker_manager_
.SetMarker(
12218 length
? std::string(marker
, length
) : std::string(marker
));
12221 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12222 GLsizei length
, const GLchar
* marker
) {
12226 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
12227 debug_marker_manager_
.PushGroup(name
);
12228 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
12229 kTraceGroupMarker
);
12232 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12233 debug_marker_manager_
.PopGroup();
12234 gpu_tracer_
->End(kTraceGroupMarker
);
12237 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12238 GLenum target
, GLint image_id
) {
12239 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12241 if (target
== GL_TEXTURE_CUBE_MAP
) {
12242 LOCAL_SET_GL_ERROR(
12244 "glBindTexImage2DCHROMIUM", "invalid target");
12248 // Default target might be conceptually valid, but disallow it to avoid
12250 TextureRef
* texture_ref
=
12251 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12252 if (!texture_ref
) {
12253 LOCAL_SET_GL_ERROR(
12254 GL_INVALID_OPERATION
,
12255 "glBindTexImage2DCHROMIUM", "no texture bound");
12259 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12261 LOCAL_SET_GL_ERROR(
12262 GL_INVALID_OPERATION
,
12263 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12268 ScopedGLErrorSuppressor
suppressor(
12269 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12270 if (!gl_image
->BindTexImage(target
)) {
12271 LOCAL_SET_GL_ERROR(
12272 GL_INVALID_OPERATION
,
12273 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12278 gfx::Size size
= gl_image
->GetSize();
12279 texture_manager()->SetLevelInfo(
12280 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
12281 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
12282 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
12285 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12286 GLenum target
, GLint image_id
) {
12287 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12289 // Default target might be conceptually valid, but disallow it to avoid
12291 TextureRef
* texture_ref
=
12292 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12293 if (!texture_ref
) {
12294 LOCAL_SET_GL_ERROR(
12295 GL_INVALID_OPERATION
,
12296 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12300 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12302 LOCAL_SET_GL_ERROR(
12303 GL_INVALID_OPERATION
,
12304 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12308 // Do nothing when image is not currently bound.
12309 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
12313 ScopedGLErrorSuppressor
suppressor(
12314 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12315 gl_image
->ReleaseTexImage(target
);
12318 texture_manager()->SetLevelInfo(
12319 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
12320 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
12323 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12324 uint32 immediate_data_size
,
12325 const void* cmd_data
) {
12326 const gles2::cmds::TraceBeginCHROMIUM
& c
=
12327 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
12328 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
12329 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
12330 if (!category_bucket
|| category_bucket
->size() == 0 ||
12331 !name_bucket
|| name_bucket
->size() == 0) {
12332 return error::kInvalidArguments
;
12335 std::string category_name
;
12336 std::string trace_name
;
12337 if (!category_bucket
->GetAsString(&category_name
) ||
12338 !name_bucket
->GetAsString(&trace_name
)) {
12339 return error::kInvalidArguments
;
12342 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
12343 LOCAL_SET_GL_ERROR(
12344 GL_INVALID_OPERATION
,
12345 "glTraceBeginCHROMIUM", "unable to create begin trace");
12346 return error::kNoError
;
12348 return error::kNoError
;
12351 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12352 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
12353 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12354 "glTraceEndCHROMIUM", "no trace begin found");
12359 void GLES2DecoderImpl::DoDrawBuffersEXT(
12360 GLsizei count
, const GLenum
* bufs
) {
12361 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
12362 LOCAL_SET_GL_ERROR(
12364 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12368 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
12370 for (GLsizei i
= 0; i
< count
; ++i
) {
12371 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
12372 bufs
[i
] != GL_NONE
) {
12373 LOCAL_SET_GL_ERROR(
12374 GL_INVALID_OPERATION
,
12375 "glDrawBuffersEXT",
12376 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12380 glDrawBuffersARB(count
, bufs
);
12381 framebuffer
->SetDrawBuffers(count
, bufs
);
12382 } else { // backbuffer
12384 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
12385 LOCAL_SET_GL_ERROR(
12386 GL_INVALID_OPERATION
,
12387 "glDrawBuffersEXT",
12388 "more than one buffer or bufs not GL_NONE or GL_BACK");
12391 GLenum mapped_buf
= bufs
[0];
12392 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12393 bufs
[0] == GL_BACK
) {
12394 mapped_buf
= GL_COLOR_ATTACHMENT0
;
12396 glDrawBuffersARB(count
, &mapped_buf
);
12397 group_
->set_draw_buffer(bufs
[0]);
12401 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
12402 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
12403 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
12404 reset_by_robustness_extension_
= true;
12407 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
12408 const GLfloat
* matrix
) {
12409 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12410 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12411 if (!features().chromium_path_rendering
) {
12412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12413 "glMatrixLoadfCHROMIUM",
12414 "function not available");
12418 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12419 ? state_
.projection_matrix
12420 : state_
.modelview_matrix
;
12421 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
12422 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12423 // since the values of the _NV and _CHROMIUM tokens match.
12424 glMatrixLoadfEXT(matrix_mode
, matrix
);
12427 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
12428 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12429 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12431 if (!features().chromium_path_rendering
) {
12432 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12433 "glMatrixLoadIdentityCHROMIUM",
12434 "function not available");
12438 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12439 ? state_
.projection_matrix
12440 : state_
.modelview_matrix
;
12441 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
12442 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12443 // since the values of the _NV and _CHROMIUM tokens match.
12444 glMatrixLoadIdentityEXT(matrix_mode
);
12447 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12448 const char* function_name
,
12449 TextureRef
* texture_ref
,
12452 const void * data
) {
12453 // We only support async uploads to 2D textures for now.
12454 if (GL_TEXTURE_2D
!= target
) {
12455 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
12458 // We only support uploads to level zero for now.
12460 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
12463 // A transfer buffer must be bound, even for asyncTexImage2D.
12464 if (data
== NULL
) {
12465 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
12468 // We only support one async transfer in progress.
12469 if (!texture_ref
||
12470 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
12471 LOCAL_SET_GL_ERROR(
12472 GL_INVALID_OPERATION
,
12473 function_name
, "transfer already in progress");
12479 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12480 uint32 async_upload_token
,
12481 uint32 sync_data_shm_id
,
12482 uint32 sync_data_shm_offset
) {
12483 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
12484 if (!buffer
.get() ||
12485 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
12486 return base::Closure();
12488 AsyncMemoryParams
mem_params(buffer
,
12489 sync_data_shm_offset
,
12490 sizeof(AsyncUploadSync
));
12492 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
12493 new AsyncUploadTokenCompletionObserver(async_upload_token
));
12496 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
12497 base::Unretained(GetAsyncPixelTransferManager()),
12502 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12503 uint32 immediate_data_size
,
12504 const void* cmd_data
) {
12505 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
12506 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
12507 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12508 GLenum target
= static_cast<GLenum
>(c
.target
);
12509 GLint level
= static_cast<GLint
>(c
.level
);
12510 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
12511 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12512 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12513 GLint border
= static_cast<GLint
>(c
.border
);
12514 GLenum format
= static_cast<GLenum
>(c
.format
);
12515 GLenum type
= static_cast<GLenum
>(c
.type
);
12516 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
12517 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
12518 uint32 pixels_size
;
12519 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12520 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12521 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12523 base::ScopedClosureRunner scoped_completion_callback
;
12524 if (async_upload_token
) {
12525 base::Closure completion_closure
=
12526 AsyncUploadTokenCompletionClosure(async_upload_token
,
12528 sync_data_shm_offset
);
12529 if (completion_closure
.is_null())
12530 return error::kInvalidArguments
;
12532 scoped_completion_callback
.Reset(completion_closure
);
12535 // TODO(epenner): Move this and copies of this memory validation
12536 // into ValidateTexImage2D step.
12537 if (!GLES2Util::ComputeImageDataSizes(
12538 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
12540 return error::kOutOfBounds
;
12542 const void* pixels
= NULL
;
12543 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
12544 pixels
= GetSharedMemoryAs
<const void*>(
12545 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
12547 return error::kOutOfBounds
;
12551 TextureManager::DoTextImage2DArguments args
= {
12552 target
, level
, internal_format
, width
, height
, border
, format
, type
,
12553 pixels
, pixels_size
};
12554 TextureRef
* texture_ref
;
12555 // All the normal glTexSubImage2D validation.
12556 if (!texture_manager()->ValidateTexImage2D(
12557 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
12558 return error::kNoError
;
12561 // Extra async validation.
12562 Texture
* texture
= texture_ref
->texture();
12563 if (!ValidateAsyncTransfer(
12564 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12565 return error::kNoError
;
12567 // Don't allow async redefinition of a textures.
12568 if (texture
->IsDefined()) {
12569 LOCAL_SET_GL_ERROR(
12570 GL_INVALID_OPERATION
,
12571 "glAsyncTexImage2DCHROMIUM", "already defined");
12572 return error::kNoError
;
12575 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
12576 LOCAL_SET_GL_ERROR(
12577 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
12578 return error::kNoError
;
12581 // Setup the parameters.
12582 AsyncTexImage2DParams tex_params
= {
12583 target
, level
, static_cast<GLenum
>(internal_format
),
12584 width
, height
, border
, format
, type
};
12585 AsyncMemoryParams
mem_params(
12586 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
12588 // Set up the async state if needed, and make the texture
12589 // immutable so the async state stays valid. The level info
12590 // is set up lazily when the transfer completes.
12591 AsyncPixelTransferDelegate
* delegate
=
12592 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
12594 texture
->SetImmutable(true);
12596 delegate
->AsyncTexImage2D(
12599 base::Bind(&TextureManager::SetLevelInfoFromParams
,
12600 // The callback is only invoked if the transfer delegate still
12601 // exists, which implies through manager->texture_ref->state
12602 // ownership that both of these pointers are valid.
12603 base::Unretained(texture_manager()),
12604 base::Unretained(texture_ref
),
12606 return error::kNoError
;
12609 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12610 uint32 immediate_data_size
,
12611 const void* cmd_data
) {
12612 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
12613 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
12614 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12615 GLenum target
= static_cast<GLenum
>(c
.target
);
12616 GLint level
= static_cast<GLint
>(c
.level
);
12617 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
12618 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
12619 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12620 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12621 GLenum format
= static_cast<GLenum
>(c
.format
);
12622 GLenum type
= static_cast<GLenum
>(c
.type
);
12623 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12624 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12625 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12627 base::ScopedClosureRunner scoped_completion_callback
;
12628 if (async_upload_token
) {
12629 base::Closure completion_closure
=
12630 AsyncUploadTokenCompletionClosure(async_upload_token
,
12632 sync_data_shm_offset
);
12633 if (completion_closure
.is_null())
12634 return error::kInvalidArguments
;
12636 scoped_completion_callback
.Reset(completion_closure
);
12639 // TODO(epenner): Move this and copies of this memory validation
12640 // into ValidateTexSubImage2D step.
12642 if (!GLES2Util::ComputeImageDataSizes(
12643 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
12645 return error::kOutOfBounds
;
12647 const void* pixels
= GetSharedMemoryAs
<const void*>(
12648 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
12650 // All the normal glTexSubImage2D validation.
12651 error::Error error
= error::kNoError
;
12652 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
12653 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
12657 // Extra async validation.
12658 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12660 Texture
* texture
= texture_ref
->texture();
12661 if (!ValidateAsyncTransfer(
12662 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12663 return error::kNoError
;
12665 // Guarantee async textures are always 'cleared' as follows:
12666 // - AsyncTexImage2D can not redefine an existing texture
12667 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12668 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12669 // - Textures become immutable after an async call.
12670 // This way we know in all cases that an async texture is always clear.
12671 if (!texture
->SafeToRenderFrom()) {
12672 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
12674 LOCAL_SET_GL_ERROR(
12676 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12677 return error::kNoError
;
12681 // Setup the parameters.
12682 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
12683 width
, height
, format
, type
};
12684 AsyncMemoryParams
mem_params(
12685 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
12686 AsyncPixelTransferDelegate
* delegate
=
12687 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12689 // TODO(epenner): We may want to enforce exclusive use
12690 // of async APIs in which case this should become an error,
12691 // (the texture should have been async defined).
12692 AsyncTexImage2DParams define_params
= {target
, level
,
12694 texture
->GetLevelSize(target
, level
, &define_params
.width
,
12695 &define_params
.height
);
12696 texture
->GetLevelType(target
, level
, &define_params
.type
,
12697 &define_params
.internal_format
);
12698 // Set up the async state if needed, and make the texture
12699 // immutable so the async state stays valid.
12700 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
12701 texture_ref
, define_params
);
12702 texture
->SetImmutable(true);
12705 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
12706 return error::kNoError
;
12709 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12710 uint32 immediate_data_size
,
12711 const void* cmd_data
) {
12712 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
12713 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
12714 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12715 GLenum target
= static_cast<GLenum
>(c
.target
);
12717 if (GL_TEXTURE_2D
!= target
) {
12718 LOCAL_SET_GL_ERROR(
12719 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
12720 return error::kNoError
;
12722 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12724 if (!texture_ref
) {
12725 LOCAL_SET_GL_ERROR(
12726 GL_INVALID_OPERATION
,
12727 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12728 return error::kNoError
;
12730 AsyncPixelTransferDelegate
* delegate
=
12731 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12733 LOCAL_SET_GL_ERROR(
12734 GL_INVALID_OPERATION
,
12735 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12736 return error::kNoError
;
12738 delegate
->WaitForTransferCompletion();
12739 ProcessFinishedAsyncTransfers();
12740 return error::kNoError
;
12743 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12744 uint32 immediate_data_size
,
12745 const void* data
) {
12746 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12748 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12749 ProcessFinishedAsyncTransfers();
12750 return error::kNoError
;
12753 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
12754 uint32_t immediate_data_size
, const void* cmd_data
) {
12755 if (!unsafe_es3_apis_enabled())
12756 return error::kUnknownCommand
;
12757 const gles2::cmds::UniformBlockBinding
& c
=
12758 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
12759 GLuint client_id
= c
.program
;
12760 GLuint index
= static_cast<GLuint
>(c
.index
);
12761 GLuint binding
= static_cast<GLuint
>(c
.binding
);
12762 Program
* program
= GetProgramInfoNotShader(
12763 client_id
, "glUniformBlockBinding");
12765 return error::kNoError
;
12767 GLuint service_id
= program
->service_id();
12768 glUniformBlockBinding(service_id
, index
, binding
);
12769 return error::kNoError
;
12772 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
12773 uint32_t immediate_data_size
, const void* cmd_data
) {
12774 if (!unsafe_es3_apis_enabled())
12775 return error::kUnknownCommand
;
12776 const gles2::cmds::ClientWaitSync
& c
=
12777 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
12778 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12779 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12780 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12781 typedef cmds::ClientWaitSync::Result Result
;
12782 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
12783 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
12785 return error::kOutOfBounds
;
12787 if (*result_dst
!= GL_WAIT_FAILED
) {
12788 return error::kInvalidArguments
;
12790 GLsync service_sync
= 0;
12791 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12792 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
12793 return error::kNoError
;
12795 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
12796 return error::kNoError
;
12799 error::Error
GLES2DecoderImpl::HandleWaitSync(
12800 uint32_t immediate_data_size
, const void* cmd_data
) {
12801 if (!unsafe_es3_apis_enabled())
12802 return error::kUnknownCommand
;
12803 const gles2::cmds::WaitSync
& c
=
12804 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
12805 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12806 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12807 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12808 GLsync service_sync
= 0;
12809 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12810 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
12811 return error::kNoError
;
12813 glWaitSync(service_sync
, flags
, timeout
);
12814 return error::kNoError
;
12817 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
12818 uint32_t immediate_data_size
, const void* cmd_data
) {
12819 if (!unsafe_es3_apis_enabled()) {
12820 return error::kUnknownCommand
;
12822 const gles2::cmds::MapBufferRange
& c
=
12823 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
12824 GLenum target
= static_cast<GLenum
>(c
.target
);
12825 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
12826 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
12827 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
12829 typedef cmds::MapBufferRange::Result Result
;
12830 Result
* result
= GetSharedMemoryAs
<Result
*>(
12831 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
12833 return error::kOutOfBounds
;
12835 if (*result
!= 0) {
12837 return error::kInvalidArguments
;
12840 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
12842 return error::kOutOfBounds
;
12845 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
12846 if ((access
& mask
) == mask
) {
12847 // TODO(zmo): To be on the safe side, always map
12848 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
12849 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
12850 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
12852 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
12853 // undefined behaviors.
12854 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
12855 if ((access
& mask
) == mask
) {
12856 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
12857 "incompatible access bits");
12858 return error::kNoError
;
12860 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
12861 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
12862 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
12863 access
= (access
| GL_MAP_READ_BIT
);
12865 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
12866 if (ptr
== nullptr) {
12867 return error::kNoError
;
12869 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
12871 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
12872 GetSharedMemoryBuffer(c
.data_shm_id
));
12873 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
12874 memcpy(mem
, ptr
, size
);
12877 return error::kNoError
;
12880 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
12881 uint32_t immediate_data_size
, const void* cmd_data
) {
12882 if (!unsafe_es3_apis_enabled()) {
12883 return error::kUnknownCommand
;
12885 const gles2::cmds::UnmapBuffer
& c
=
12886 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
12887 GLenum target
= static_cast<GLenum
>(c
.target
);
12889 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
12891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
12892 return error::kNoError
;
12894 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
12895 if (!mapped_range
) {
12896 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
12897 "buffer is unmapped");
12898 return error::kNoError
;
12900 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
12901 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
12902 GL_MAP_FLUSH_EXPLICIT_BIT
) {
12903 // If we don't need to write back, or explict flush is required, no copying
12906 void* mem
= mapped_range
->GetShmPointer();
12908 return error::kOutOfBounds
;
12910 DCHECK(mapped_range
->pointer
);
12911 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
12913 buffer
->RemoveMappedRange();
12914 GLboolean rt
= glUnmapBuffer(target
);
12915 if (rt
== GL_FALSE
) {
12916 // At this point, we have already done the necessary validation, so
12917 // GL_FALSE indicates data corruption.
12918 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
12919 // the second unmap could still return GL_FALSE. For now, we simply lose
12920 // the contexts in the share group.
12921 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
12922 // Need to lose current context before broadcasting!
12923 MarkContextLost(error::kGuilty
);
12924 group_
->LoseContexts(error::kInnocent
);
12925 return error::kLostContext
;
12927 return error::kNoError
;
12930 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12931 TextureRef
* texture_ref
) {
12932 Texture
* texture
= texture_ref
->texture();
12933 DoDidUseTexImageIfNeeded(texture
, texture
->target());
12936 // Note that GL_LOST_CONTEXT is specific to GLES.
12937 // For desktop GL we have to query the reset status proactively.
12938 void GLES2DecoderImpl::OnContextLostError() {
12939 if (!WasContextLost()) {
12940 // Need to lose current context before broadcasting!
12941 CheckResetStatus();
12942 group_
->LoseContexts(error::kUnknown
);
12943 reset_by_robustness_extension_
= true;
12947 void GLES2DecoderImpl::OnOutOfMemoryError() {
12948 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
12949 error::ContextLostReason other
= error::kOutOfMemory
;
12950 if (CheckResetStatus()) {
12951 other
= error::kUnknown
;
12953 // Need to lose current context before broadcasting!
12954 MarkContextLost(error::kOutOfMemory
);
12956 group_
->LoseContexts(other
);
12960 // Include the auto-generated part of this file. We split this because it means
12961 // we can easily edit the non-auto generated parts right here in this file
12962 // instead of having to edit some template or the code generator.
12963 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12965 } // namespace gles2