1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/float_util.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_split.h"
25 #include "base/trace_event/trace_event.h"
26 #include "base/trace_event/trace_event_synthetic_delay.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
45 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
46 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
47 #include "gpu/command_buffer/service/gpu_state_tracer.h"
48 #include "gpu/command_buffer/service/gpu_switches.h"
49 #include "gpu/command_buffer/service/gpu_tracer.h"
50 #include "gpu/command_buffer/service/image_manager.h"
51 #include "gpu/command_buffer/service/mailbox_manager.h"
52 #include "gpu/command_buffer/service/memory_tracking.h"
53 #include "gpu/command_buffer/service/program_manager.h"
54 #include "gpu/command_buffer/service/query_manager.h"
55 #include "gpu/command_buffer/service/renderbuffer_manager.h"
56 #include "gpu/command_buffer/service/shader_manager.h"
57 #include "gpu/command_buffer/service/shader_translator.h"
58 #include "gpu/command_buffer/service/shader_translator_cache.h"
59 #include "gpu/command_buffer/service/texture_manager.h"
60 #include "gpu/command_buffer/service/valuebuffer_manager.h"
61 #include "gpu/command_buffer/service/vertex_array_manager.h"
62 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
63 #include "third_party/smhasher/src/City.h"
64 #include "ui/gl/gl_fence.h"
65 #include "ui/gl/gl_image.h"
66 #include "ui/gl/gl_implementation.h"
67 #include "ui/gl/gl_surface.h"
69 #if defined(OS_MACOSX)
70 #include <IOSurface/IOSurfaceAPI.h>
71 // Note that this must be included after gl_bindings.h to avoid conflicts.
72 #include <OpenGL/CGLIOSurface.h>
76 #include "base/win/win_util.h"
84 static const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
85 static const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
86 static const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
87 static const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
89 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
92 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
95 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
96 GLenum precision_type
,
97 GLint
*range
, GLint
*precision
) {
98 switch (precision_type
) {
102 // These values are for a 32-bit twos-complement integer format.
108 case GL_MEDIUM_FLOAT
:
110 // These values are for an IEEE single-precision floating-point format.
120 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
121 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
122 // This function is sometimes defined even though it's really just
123 // a stub, so we need to set range and precision as if it weren't
124 // defined before calling it.
125 // On Mac OS with some GPUs, calling this generates a
126 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
128 glGetShaderPrecisionFormat(shader_type
, precision_type
,
131 // TODO(brianderson): Make the following official workarounds.
133 // Some drivers have bugs where they report the ranges as a negative number.
134 // Taking the absolute value here shouldn't hurt because negative numbers
135 // aren't expected anyway.
136 range
[0] = abs(range
[0]);
137 range
[1] = abs(range
[1]);
139 // If the driver reports a precision for highp float that isn't actually
140 // highp, don't pretend like it's supported because shader compilation will
142 if (precision_type
== GL_HIGH_FLOAT
&&
143 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
151 static gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
152 switch (plane_transform
) {
153 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
154 return gfx::OVERLAY_TRANSFORM_NONE
;
155 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
156 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
157 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
158 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
159 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
161 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
163 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
164 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
166 return gfx::OVERLAY_TRANSFORM_INVALID
;
172 class GLES2DecoderImpl
;
174 // Local versions of the SET_GL_ERROR macros
175 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
176 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
177 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
178 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
179 function_name, value, label)
180 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
181 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
182 function_name, pname)
183 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
184 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
186 #define LOCAL_PEEK_GL_ERROR(function_name) \
187 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
188 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
189 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
190 #define LOCAL_PERFORMANCE_WARNING(msg) \
191 PerformanceWarning(__FILE__, __LINE__, msg)
192 #define LOCAL_RENDER_WARNING(msg) \
193 RenderWarning(__FILE__, __LINE__, msg)
195 // Check that certain assumptions the code makes are true. There are places in
196 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
197 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
198 // a few others) are 32bits. If they are not 32bits the code will have to change
199 // to call those GL functions with service side memory and then copy the results
200 // to shared memory, converting the sizes.
201 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
202 "GLint should be the same size as uint32");
203 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
204 "GLsizei should be the same size as uint32");
205 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
206 "GLfloat should be the same size as float");
208 // TODO(kbr): the use of this anonymous namespace core dumps the
209 // linker on Mac OS X 10.6 when the symbol ordering file is used
212 // Returns the address of the first byte after a struct.
213 template <typename T
>
214 const void* AddressAfterStruct(const T
& pod
) {
215 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
218 // Returns the address of the frst byte after the struct or NULL if size >
219 // immediate_data_size.
220 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
221 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
223 uint32 immediate_data_size
) {
224 return (size
<= immediate_data_size
) ?
225 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
229 // Computes the data size for certain gl commands like glUniform.
230 bool ComputeDataSize(
233 unsigned int elements_per_unit
,
236 if (!SafeMultiplyUint32(count
, size
, &value
)) {
239 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
246 // Return true if a character belongs to the ASCII subset as defined in
247 // GLSL ES 1.0 spec section 3.1.
248 static bool CharacterIsValidForGLES(unsigned char c
) {
249 // Printing characters are valid except " $ ` @ \ ' DEL.
250 if (c
>= 32 && c
<= 126 &&
259 // Horizontal tab, line feed, vertical tab, form feed, carriage return
261 if (c
>= 9 && c
<= 13) {
268 static bool StringIsValidForGLES(const char* str
) {
269 for (; *str
; ++str
) {
270 if (!CharacterIsValidForGLES(*str
)) {
277 // This class prevents any GL errors that occur when it is in scope from
278 // being reported to the client.
279 class ScopedGLErrorSuppressor
{
281 explicit ScopedGLErrorSuppressor(
282 const char* function_name
, ErrorState
* error_state
);
283 ~ScopedGLErrorSuppressor();
285 const char* function_name_
;
286 ErrorState
* error_state_
;
287 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
290 // Temporarily changes a decoder's bound texture and restore it when this
291 // object goes out of scope. Also temporarily switches to using active texture
292 // unit zero in case the client has changed that to something invalid.
293 class ScopedTextureBinder
{
295 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
296 ~ScopedTextureBinder();
299 ContextState
* state_
;
301 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
304 // Temporarily changes a decoder's bound render buffer and restore it when this
305 // object goes out of scope.
306 class ScopedRenderBufferBinder
{
308 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
309 ~ScopedRenderBufferBinder();
312 ContextState
* state_
;
313 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
316 // Temporarily changes a decoder's bound frame buffer and restore it when this
317 // object goes out of scope.
318 class ScopedFrameBufferBinder
{
320 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
321 ~ScopedFrameBufferBinder();
324 GLES2DecoderImpl
* decoder_
;
325 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
328 // Temporarily changes a decoder's bound frame buffer to a resolved version of
329 // the multisampled offscreen render buffer if that buffer is multisampled, and,
330 // if it is bound or enforce_internal_framebuffer is true. If internal is
331 // true, the resolved framebuffer is not visible to the parent.
332 class ScopedResolvedFrameBufferBinder
{
334 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
335 bool enforce_internal_framebuffer
,
337 ~ScopedResolvedFrameBufferBinder();
340 GLES2DecoderImpl
* decoder_
;
341 bool resolve_and_bind_
;
342 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
345 class ScopedModifyPixels
{
347 explicit ScopedModifyPixels(TextureRef
* ref
);
348 ~ScopedModifyPixels();
354 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
356 ref_
->texture()->OnWillModifyPixels();
359 ScopedModifyPixels::~ScopedModifyPixels() {
361 ref_
->texture()->OnDidModifyPixels();
364 class ScopedRenderTo
{
366 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
370 const Framebuffer
* framebuffer_
;
373 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
374 : framebuffer_(framebuffer
) {
376 framebuffer_
->OnWillRenderTo();
379 ScopedRenderTo::~ScopedRenderTo() {
381 framebuffer_
->OnDidRenderTo();
384 // Encapsulates an OpenGL texture.
387 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
390 // Create a new render texture.
393 // Set the initial size and format of a render texture or resize it.
394 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
396 // Copy the contents of the currently bound frame buffer.
397 void Copy(const gfx::Size
& size
, GLenum format
);
399 // Destroy the render texture. This must be explicitly called before
400 // destroying this object.
403 // Invalidate the texture. This can be used when a context is lost and it is
404 // not possible to make it current in order to free the resource.
411 gfx::Size
size() const {
416 MemoryTypeTracker memory_tracker_
;
417 ContextState
* state_
;
418 size_t bytes_allocated_
;
421 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
424 // Encapsulates an OpenGL render buffer of any format.
425 class BackRenderbuffer
{
427 explicit BackRenderbuffer(
428 RenderbufferManager
* renderbuffer_manager
,
429 MemoryTracker
* memory_tracker
,
430 ContextState
* state
);
433 // Create a new render buffer.
436 // Set the initial size and format of a render buffer or resize it.
437 bool AllocateStorage(const FeatureInfo
* feature_info
,
438 const gfx::Size
& size
,
442 // Destroy the render buffer. This must be explicitly called before destroying
446 // Invalidate the render buffer. This can be used when a context is lost and
447 // it is not possible to make it current in order to free the resource.
455 RenderbufferManager
* renderbuffer_manager_
;
456 MemoryTypeTracker memory_tracker_
;
457 ContextState
* state_
;
458 size_t bytes_allocated_
;
460 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
463 // Encapsulates an OpenGL frame buffer.
464 class BackFramebuffer
{
466 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
469 // Create a new frame buffer.
472 // Attach a color render buffer to a frame buffer.
473 void AttachRenderTexture(BackTexture
* texture
);
475 // Attach a render buffer to a frame buffer. Note that this unbinds any
476 // currently bound frame buffer.
477 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
479 // Destroy the frame buffer. This must be explicitly called before destroying
483 // Invalidate the frame buffer. This can be used when a context is lost and it
484 // is not possible to make it current in order to free the resource.
487 // See glCheckFramebufferStatusEXT.
488 GLenum
CheckStatus();
495 GLES2DecoderImpl
* decoder_
;
497 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
500 struct FenceCallback
{
501 explicit FenceCallback()
502 : fence(gfx::GLFence::Create()) {
505 std::vector
<base::Closure
> callbacks
;
506 scoped_ptr
<gfx::GLFence
> fence
;
509 class AsyncUploadTokenCompletionObserver
510 : public AsyncPixelTransferCompletionObserver
{
512 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
513 : async_upload_token_(async_upload_token
) {
516 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
517 DCHECK(mem_params
.buffer().get());
518 void* data
= mem_params
.GetDataAddress();
519 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
520 sync
->SetAsyncUploadToken(async_upload_token_
);
524 ~AsyncUploadTokenCompletionObserver() override
{}
526 uint32 async_upload_token_
;
528 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
531 // } // anonymous namespace.
534 const unsigned int GLES2Decoder::kDefaultStencilMask
=
535 static_cast<unsigned int>(-1);
537 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
538 uint32
* service_texture_id
) {
542 GLES2Decoder::GLES2Decoder()
543 : initialized_(false),
545 log_commands_(false),
546 unsafe_es3_apis_enabled_(false) {
549 GLES2Decoder::~GLES2Decoder() {
552 void GLES2Decoder::BeginDecoding() {}
554 void GLES2Decoder::EndDecoding() {}
556 // This class implements GLES2Decoder so we don't have to expose all the GLES2
557 // cmd stuff to outside this class.
558 class GLES2DecoderImpl
: public GLES2Decoder
,
559 public FramebufferManager::TextureDetachObserver
,
560 public ErrorStateClient
{
562 explicit GLES2DecoderImpl(ContextGroup
* group
);
563 ~GLES2DecoderImpl() override
;
565 // Overridden from AsyncAPIInterface.
566 Error
DoCommand(unsigned int command
,
567 unsigned int arg_count
,
568 const void* args
) override
;
570 error::Error
DoCommands(unsigned int num_commands
,
573 int* entries_processed
) override
;
575 template <bool DebugImpl
>
576 error::Error
DoCommandsImpl(unsigned int num_commands
,
579 int* entries_processed
);
581 // Overridden from AsyncAPIInterface.
582 const char* GetCommandName(unsigned int command_id
) const override
;
584 // Overridden from GLES2Decoder.
585 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
586 const scoped_refptr
<gfx::GLContext
>& context
,
588 const gfx::Size
& size
,
589 const DisallowedFeatures
& disallowed_features
,
590 const std::vector
<int32
>& attribs
) override
;
591 void Destroy(bool have_context
) override
;
592 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
593 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
594 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
595 void UpdateParentTextureInfo();
596 bool MakeCurrent() override
;
597 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
598 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
599 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
600 Capabilities
GetCapabilities() override
;
601 void RestoreState(const ContextState
* prev_state
) override
;
603 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
604 void RestoreAllTextureUnitBindings(
605 const ContextState
* prev_state
) const override
{
606 state_
.RestoreAllTextureUnitBindings(prev_state
);
608 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
609 state_
.RestoreActiveTextureUnitBinding(target
);
611 void RestoreBufferBindings() const override
{
612 state_
.RestoreBufferBindings();
614 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
615 void RestoreProgramBindings() const override
{
616 state_
.RestoreProgramBindings();
618 void RestoreTextureUnitBindings(unsigned unit
) const override
{
619 state_
.RestoreTextureUnitBindings(unit
, NULL
);
621 void RestoreFramebufferBindings() const override
;
622 void RestoreRenderbufferBindings() override
;
623 void RestoreTextureState(unsigned service_id
) const override
;
625 void ClearAllAttributes() const override
;
626 void RestoreAllAttributes() const override
;
628 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
629 VertexArrayManager
* GetVertexArrayManager() override
{
630 return vertex_array_manager_
.get();
632 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
634 ValuebufferManager
* GetValuebufferManager() override
{
635 return valuebuffer_manager();
638 bool ProcessPendingQueries(bool did_finish
) override
;
640 bool HasMoreIdleWork() override
;
641 void PerformIdleWork() override
;
643 void WaitForReadPixels(base::Closure callback
) override
;
645 void SetResizeCallback(
646 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
648 Logger
* GetLogger() override
;
650 void BeginDecoding() override
;
651 void EndDecoding() override
;
653 ErrorState
* GetErrorState() override
;
654 const ContextState
* GetContextState() override
{ return &state_
; }
656 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
657 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
659 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
660 void ResetAsyncPixelTransferManagerForTest() override
;
661 void SetAsyncPixelTransferManagerForTest(
662 AsyncPixelTransferManager
* manager
) override
;
663 void SetIgnoreCachedStateForTest(bool ignore
) override
;
664 void ProcessFinishedAsyncTransfers();
666 bool GetServiceTextureId(uint32 client_texture_id
,
667 uint32
* service_texture_id
) override
;
669 uint32
GetTextureUploadCount() override
;
670 base::TimeDelta
GetTotalTextureUploadTime() override
;
671 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
672 void AddProcessingCommandsTime(base::TimeDelta
) override
;
674 // Restores the current state to the user's settings.
675 void RestoreCurrentFramebufferBindings();
677 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
678 void ApplyDirtyState();
680 // These check the state of the currently bound framebuffer or the
681 // backbuffer if no framebuffer is bound.
682 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
683 // check with all attached and enabled color attachments.
684 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
685 bool BoundFramebufferHasDepthAttachment();
686 bool BoundFramebufferHasStencilAttachment();
688 error::ContextLostReason
GetContextLostReason() override
;
690 // Overridden from FramebufferManager::TextureDetachObserver:
691 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
693 // Overriden from ErrorStateClient.
694 void OnContextLostError() override
;
695 void OnOutOfMemoryError() override
;
697 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
698 void EnsureRenderbufferBound();
700 // Helpers to facilitate calling into compatible extensions.
701 static void RenderbufferStorageMultisampleHelper(
702 const FeatureInfo
* feature_info
,
705 GLenum internal_format
,
709 void BlitFramebufferHelper(GLint srcX0
,
721 friend class ScopedFrameBufferBinder
;
722 friend class ScopedResolvedFrameBufferBinder
;
723 friend class BackFramebuffer
;
725 // Initialize or re-initialize the shader translator.
726 bool InitializeShaderTranslator();
728 void UpdateCapabilities();
730 // Helpers for the glGen and glDelete functions.
731 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
732 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
733 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
734 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
735 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
736 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
737 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
738 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
739 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
740 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
741 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
742 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
743 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
744 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
746 // Helper for async upload token completion notification callback.
747 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
748 uint32 sync_data_shm_id
,
749 uint32 sync_data_shm_offset
);
754 void OnFboChanged() const;
755 void OnUseFramebuffer() const;
757 // TODO(gman): Cache these pointers?
758 BufferManager
* buffer_manager() {
759 return group_
->buffer_manager();
762 RenderbufferManager
* renderbuffer_manager() {
763 return group_
->renderbuffer_manager();
766 FramebufferManager
* framebuffer_manager() {
767 return group_
->framebuffer_manager();
770 ValuebufferManager
* valuebuffer_manager() {
771 return group_
->valuebuffer_manager();
774 ProgramManager
* program_manager() {
775 return group_
->program_manager();
778 ShaderManager
* shader_manager() {
779 return group_
->shader_manager();
782 ShaderTranslatorCache
* shader_translator_cache() {
783 return group_
->shader_translator_cache();
786 const TextureManager
* texture_manager() const {
787 return group_
->texture_manager();
790 TextureManager
* texture_manager() {
791 return group_
->texture_manager();
794 MailboxManager
* mailbox_manager() {
795 return group_
->mailbox_manager();
798 ImageManager
* image_manager() { return image_manager_
.get(); }
800 VertexArrayManager
* vertex_array_manager() {
801 return vertex_array_manager_
.get();
804 MemoryTracker
* memory_tracker() {
805 return group_
->memory_tracker();
808 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
809 MemoryTracker
* tracker
= memory_tracker();
811 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
816 bool IsOffscreenBufferMultisampled() const {
817 return offscreen_target_samples_
> 1;
820 // Creates a Texture for the given texture.
821 TextureRef
* CreateTexture(
822 GLuint client_id
, GLuint service_id
) {
823 return texture_manager()->CreateTexture(client_id
, service_id
);
826 // Gets the texture info for the given texture. Returns NULL if none exists.
827 TextureRef
* GetTexture(GLuint client_id
) const {
828 return texture_manager()->GetTexture(client_id
);
831 // Deletes the texture info for the given texture.
832 void RemoveTexture(GLuint client_id
) {
833 texture_manager()->RemoveTexture(client_id
);
836 // Get the size (in pixels) of the currently bound frame buffer (either FBO
837 // or regular back buffer).
838 gfx::Size
GetBoundReadFrameBufferSize();
840 // Get the format of the currently bound frame buffer (either FBO or regular
842 GLenum
GetBoundReadFrameBufferTextureType();
843 GLenum
GetBoundReadFrameBufferInternalFormat();
844 GLenum
GetBoundDrawFrameBufferInternalFormat();
846 // Wrapper for CompressedTexImage2D commands.
847 error::Error
DoCompressedTexImage2D(
850 GLenum internal_format
,
857 // Wrapper for CompressedTexSubImage2D.
858 void DoCompressedTexSubImage2D(
869 // Wrapper for CopyTexImage2D.
870 void DoCopyTexImage2D(
873 GLenum internal_format
,
880 // Wrapper for SwapBuffers.
881 void DoSwapBuffers();
883 // Wrapper for SwapInterval.
884 void DoSwapInterval(int interval
);
886 // Wrapper for CopyTexSubImage2D.
887 void DoCopyTexSubImage2D(
897 // Validation for TexSubImage2D.
898 bool ValidateTexSubImage2D(
900 const char* function_name
,
911 // Wrapper for TexSubImage2D.
912 error::Error
DoTexSubImage2D(
923 // Extra validation for async tex(Sub)Image2D.
924 bool ValidateAsyncTransfer(
925 const char* function_name
,
926 TextureRef
* texture_ref
,
931 // Wrapper for TexImageIOSurface2DCHROMIUM.
932 void DoTexImageIOSurface2DCHROMIUM(
936 GLuint io_surface_id
,
939 void DoCopyTextureCHROMIUM(
944 GLenum internal_format
,
947 // Wrapper for TexStorage2DEXT.
948 void DoTexStorage2DEXT(
951 GLenum internal_format
,
955 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
956 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
958 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
959 GLenum target
, const GLbyte
* data
);
961 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
962 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
965 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
966 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
967 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
968 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
969 void DoUniformValueBufferCHROMIUM(GLint location
,
971 GLenum subscription
);
973 void DoBindTexImage2DCHROMIUM(
976 void DoReleaseTexImage2DCHROMIUM(
980 void DoTraceEndCHROMIUM(void);
982 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
984 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
986 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
987 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
989 // Creates a Program for the given program.
990 Program
* CreateProgram(
991 GLuint client_id
, GLuint service_id
) {
992 return program_manager()->CreateProgram(client_id
, service_id
);
995 // Gets the program info for the given program. Returns NULL if none exists.
996 Program
* GetProgram(GLuint client_id
) {
997 return program_manager()->GetProgram(client_id
);
1001 void LogClientServiceMapping(
1002 const char* /* function_name */,
1003 GLuint
/* client_id */,
1004 GLuint
/* service_id */) {
1006 template<typename T
>
1007 void LogClientServiceForInfo(
1008 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1011 void LogClientServiceMapping(
1012 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1013 if (service_logging_
) {
1014 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1015 << ": client_id = " << client_id
1016 << ", service_id = " << service_id
;
1019 template<typename T
>
1020 void LogClientServiceForInfo(
1021 T
* info
, GLuint client_id
, const char* function_name
) {
1023 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1028 // Gets the program info for the given program. If it's not a program
1029 // generates a GL error. Returns NULL if not program.
1030 Program
* GetProgramInfoNotShader(
1031 GLuint client_id
, const char* function_name
) {
1032 Program
* program
= GetProgram(client_id
);
1034 if (GetShader(client_id
)) {
1036 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1038 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1041 LogClientServiceForInfo(program
, client_id
, function_name
);
1046 // Creates a Shader for the given shader.
1047 Shader
* CreateShader(
1050 GLenum shader_type
) {
1051 return shader_manager()->CreateShader(
1052 client_id
, service_id
, shader_type
);
1055 // Gets the shader info for the given shader. Returns NULL if none exists.
1056 Shader
* GetShader(GLuint client_id
) {
1057 return shader_manager()->GetShader(client_id
);
1060 // Gets the shader info for the given shader. If it's not a shader generates a
1061 // GL error. Returns NULL if not shader.
1062 Shader
* GetShaderInfoNotProgram(
1063 GLuint client_id
, const char* function_name
) {
1064 Shader
* shader
= GetShader(client_id
);
1066 if (GetProgram(client_id
)) {
1068 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1071 GL_INVALID_VALUE
, function_name
, "unknown shader");
1074 LogClientServiceForInfo(shader
, client_id
, function_name
);
1078 // Creates a buffer info for the given buffer.
1079 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1080 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1083 // Gets the buffer info for the given buffer.
1084 Buffer
* GetBuffer(GLuint client_id
) {
1085 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1089 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1090 // on glDeleteBuffers so we can make sure the user does not try to render
1091 // with deleted buffers.
1092 void RemoveBuffer(GLuint client_id
);
1094 // Creates a framebuffer info for the given framebuffer.
1095 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1096 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1099 // Gets the framebuffer info for the given framebuffer.
1100 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1101 return framebuffer_manager()->GetFramebuffer(client_id
);
1104 // Removes the framebuffer info for the given framebuffer.
1105 void RemoveFramebuffer(GLuint client_id
) {
1106 framebuffer_manager()->RemoveFramebuffer(client_id
);
1109 // Creates a renderbuffer info for the given renderbuffer.
1110 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1111 return renderbuffer_manager()->CreateRenderbuffer(
1112 client_id
, service_id
);
1115 // Gets the renderbuffer info for the given renderbuffer.
1116 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1117 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1120 // Removes the renderbuffer info for the given renderbuffer.
1121 void RemoveRenderbuffer(GLuint client_id
) {
1122 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1125 // Creates a valuebuffer info for the given valuebuffer.
1126 void CreateValuebuffer(GLuint client_id
) {
1127 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1130 // Gets the valuebuffer info for a given valuebuffer.
1131 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1132 return valuebuffer_manager()->GetValuebuffer(client_id
);
1135 // Removes the valuebuffer info for the given valuebuffer.
1136 void RemoveValuebuffer(GLuint client_id
) {
1137 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1140 // Gets the vertex attrib manager for the given vertex array.
1141 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1142 VertexAttribManager
* info
=
1143 vertex_array_manager()->GetVertexAttribManager(client_id
);
1147 // Removes the vertex attrib manager for the given vertex array.
1148 void RemoveVertexAttribManager(GLuint client_id
) {
1149 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1152 // Creates a vertex attrib manager for the given vertex array.
1153 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1156 bool client_visible
) {
1157 return vertex_array_manager()->CreateVertexAttribManager(
1158 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1161 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1162 void DoBindUniformLocationCHROMIUM(
1163 GLuint client_id
, GLint location
, const char* name
);
1165 error::Error
GetAttribLocationHelper(
1166 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1167 const std::string
& name_str
);
1169 error::Error
GetUniformLocationHelper(
1170 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1171 const std::string
& name_str
);
1173 error::Error
GetFragDataLocationHelper(
1174 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1175 const std::string
& name_str
);
1177 // Wrapper for glShaderSource.
1178 void DoShaderSource(
1179 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1181 // Wrapper for glTransformFeedbackVaryings.
1182 void DoTransformFeedbackVaryings(
1183 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1184 GLenum buffer_mode
);
1186 // Clear any textures used by the current program.
1187 bool ClearUnclearedTextures();
1189 // Clears any uncleared attachments attached to the given frame buffer.
1190 // Returns false if there was a generated GL error.
1191 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1193 // overridden from GLES2Decoder
1194 bool ClearLevel(Texture
* texture
,
1197 unsigned internal_format
,
1202 bool is_texture_immutable
) override
;
1204 // Restore all GL state that affects clearing.
1205 void RestoreClearState();
1207 // Remembers the state of some capabilities.
1208 // Returns: true if glEnable/glDisable should actually be called.
1209 bool SetCapabilityState(GLenum cap
, bool enabled
);
1211 // Check that the currently bound framebuffers are valid.
1212 // Generates GL error if not.
1213 bool CheckBoundFramebuffersValid(const char* func_name
);
1215 // Check that the currently bound read framebuffer has a color image
1216 // attached. Generates GL error if not.
1217 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1219 // Check that the currently bound read framebuffer's color image
1220 // isn't the target texture of the glCopyTex{Sub}Image2D.
1221 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1223 // Check if a framebuffer meets our requirements.
1224 bool CheckFramebufferValid(
1225 Framebuffer
* framebuffer
,
1227 const char* func_name
);
1229 // Check if the current valuebuffer exists and is valid. If not generates
1230 // the appropriate GL error. Returns true if the current valuebuffer is in
1232 bool CheckCurrentValuebuffer(const char* function_name
);
1234 // Check if the current valuebuffer exists and is valiud and that the
1235 // value buffer is actually subscribed to the given subscription
1236 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1237 const char* function_name
);
1239 // Check if the location can be used for the given subscription target. If not
1240 // generates the appropriate GL error. Returns true if the location is usable
1241 bool CheckSubscriptionTarget(GLint location
,
1242 GLenum subscription
,
1243 const char* function_name
);
1245 // Checks if the current program exists and is valid. If not generates the
1246 // appropriate GL error. Returns true if the current program is in a usable
1248 bool CheckCurrentProgram(const char* function_name
);
1250 // Checks if the current program exists and is valid and that location is not
1251 // -1. If the current program is not valid generates the appropriate GL
1252 // error. Returns true if the current program is in a usable state and
1253 // location is not -1.
1254 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1256 // Checks if the current program samples a texture that is also the color
1257 // image of the current bound framebuffer, i.e., the source and destination
1258 // of the draw operation are the same.
1259 bool CheckDrawingFeedbackLoops();
1261 // Checks if |api_type| is valid for the given uniform
1262 // If the api type is not valid generates the appropriate GL
1263 // error. Returns true if |api_type| is valid for the uniform
1264 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1265 const char* function_name
,
1266 Program::UniformApiType api_type
);
1268 // Gets the type of a uniform for a location in the current program. Sets GL
1269 // errors if the current program is not valid. Returns true if the current
1270 // program is valid and the location exists. Adjusts count so it
1271 // does not overflow the uniform.
1272 bool PrepForSetUniformByLocation(GLint fake_location
,
1273 const char* function_name
,
1274 Program::UniformApiType api_type
,
1275 GLint
* real_location
,
1279 // Gets the service id for any simulated backbuffer fbo.
1280 GLuint
GetBackbufferServiceId() const;
1282 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1283 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1285 // Helper for glGetVertexAttrib
1286 void GetVertexAttribHelper(
1287 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1289 // Wrapper for glActiveTexture
1290 void DoActiveTexture(GLenum texture_unit
);
1292 // Wrapper for glAttachShader
1293 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1295 // Wrapper for glBindBuffer since we need to track the current targets.
1296 void DoBindBuffer(GLenum target
, GLuint buffer
);
1298 // Wrapper for glBindFramebuffer since we need to track the current targets.
1299 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1301 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1302 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1304 // Wrapper for glBindTexture since we need to track the current targets.
1305 void DoBindTexture(GLenum target
, GLuint texture
);
1307 // Wrapper for glBindVertexArrayOES
1308 void DoBindVertexArrayOES(GLuint array
);
1309 void EmulateVertexArrayState();
1311 // Wrapper for glBlitFramebufferCHROMIUM.
1312 void DoBlitFramebufferCHROMIUM(
1313 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1314 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1315 GLbitfield mask
, GLenum filter
);
1317 // Wrapper for glBufferSubData.
1318 void DoBufferSubData(
1319 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1321 // Wrapper for glCheckFramebufferStatus
1322 GLenum
DoCheckFramebufferStatus(GLenum target
);
1324 // Wrapper for glClear
1325 error::Error
DoClear(GLbitfield mask
);
1327 // Wrappers for various state.
1328 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1329 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1331 // Wrapper for glCompileShader.
1332 void DoCompileShader(GLuint shader
);
1334 // Wrapper for glDetachShader
1335 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1337 // Wrapper for glDisable
1338 void DoDisable(GLenum cap
);
1340 // Wrapper for glDisableVertexAttribArray.
1341 void DoDisableVertexAttribArray(GLuint index
);
1343 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1345 void DoDiscardFramebufferEXT(GLenum target
,
1346 GLsizei numAttachments
,
1347 const GLenum
* attachments
);
1349 // Wrapper for glEnable
1350 void DoEnable(GLenum cap
);
1352 // Wrapper for glEnableVertexAttribArray.
1353 void DoEnableVertexAttribArray(GLuint index
);
1355 // Wrapper for glFinish.
1358 // Wrapper for glFlush.
1361 // Wrapper for glFramebufferRenderbufffer.
1362 void DoFramebufferRenderbuffer(
1363 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1364 GLuint renderbuffer
);
1366 // Wrapper for glFramebufferTexture2D.
1367 void DoFramebufferTexture2D(
1368 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1371 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1372 void DoFramebufferTexture2DMultisample(
1373 GLenum target
, GLenum attachment
, GLenum textarget
,
1374 GLuint texture
, GLint level
, GLsizei samples
);
1376 // Common implementation for both DoFramebufferTexture2D wrappers.
1377 void DoFramebufferTexture2DCommon(const char* name
,
1378 GLenum target
, GLenum attachment
, GLenum textarget
,
1379 GLuint texture
, GLint level
, GLsizei samples
);
1381 // Wrapper for glFramebufferTextureLayer.
1382 void DoFramebufferTextureLayer(
1383 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1386 // Wrapper for glGenerateMipmap
1387 void DoGenerateMipmap(GLenum target
);
1389 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1390 // to account for different pname values defined in different extension
1392 GLenum
AdjustGetPname(GLenum pname
);
1394 // Wrapper for DoGetBooleanv.
1395 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1397 // Wrapper for DoGetFloatv.
1398 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1400 // Wrapper for glGetFramebufferAttachmentParameteriv.
1401 void DoGetFramebufferAttachmentParameteriv(
1402 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1404 // Wrapper for glGetIntegerv.
1405 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1407 // Gets the max value in a range in a buffer.
1408 GLuint
DoGetMaxValueInBufferCHROMIUM(
1409 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1411 // Wrapper for glGetBufferParameteriv.
1412 void DoGetBufferParameteriv(
1413 GLenum target
, GLenum pname
, GLint
* params
);
1415 // Wrapper for glGetProgramiv.
1416 void DoGetProgramiv(
1417 GLuint program_id
, GLenum pname
, GLint
* params
);
1419 // Wrapper for glRenderbufferParameteriv.
1420 void DoGetRenderbufferParameteriv(
1421 GLenum target
, GLenum pname
, GLint
* params
);
1423 // Wrapper for glGetShaderiv
1424 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1426 // Wrappers for glGetTexParameter.
1427 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1428 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1429 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1431 // Wrappers for glGetVertexAttrib.
1432 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1433 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1435 // Wrappers for glIsXXX functions.
1436 bool DoIsEnabled(GLenum cap
);
1437 bool DoIsBuffer(GLuint client_id
);
1438 bool DoIsFramebuffer(GLuint client_id
);
1439 bool DoIsProgram(GLuint client_id
);
1440 bool DoIsRenderbuffer(GLuint client_id
);
1441 bool DoIsShader(GLuint client_id
);
1442 bool DoIsTexture(GLuint client_id
);
1443 bool DoIsVertexArrayOES(GLuint client_id
);
1445 // Wrapper for glLinkProgram
1446 void DoLinkProgram(GLuint program
);
1448 // Wrapper for glRenderbufferStorage.
1449 void DoRenderbufferStorage(
1450 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1452 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1453 void DoRenderbufferStorageMultisampleCHROMIUM(
1454 GLenum target
, GLsizei samples
, GLenum internalformat
,
1455 GLsizei width
, GLsizei height
);
1457 // Handler for glRenderbufferStorageMultisampleEXT
1458 // (multisampled_render_to_texture).
1459 void DoRenderbufferStorageMultisampleEXT(
1460 GLenum target
, GLsizei samples
, GLenum internalformat
,
1461 GLsizei width
, GLsizei height
);
1463 // Common validation for multisample extensions.
1464 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1465 GLenum internalformat
,
1469 // Verifies that the currently bound multisample renderbuffer is valid
1470 // Very slow! Only done on platforms with driver bugs that return invalid
1471 // buffers under memory pressure
1472 bool VerifyMultisampleRenderbufferIntegrity(
1473 GLuint renderbuffer
, GLenum format
);
1475 // Wrapper for glReleaseShaderCompiler.
1476 void DoReleaseShaderCompiler() { }
1478 // Wrappers for glSamplerParameter*v functions.
1479 void DoSamplerParameterfv(
1480 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1481 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1483 // Wrappers for glTexParameter functions.
1484 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1485 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1486 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1487 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1489 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1490 // spec only these 2 functions can be used to set sampler uniforms.
1491 void DoUniform1i(GLint fake_location
, GLint v0
);
1492 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1493 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1494 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1495 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1497 // Wrappers for glUniformfv because some drivers don't correctly accept
1499 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1500 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1501 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1502 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1504 void DoUniformMatrix2fv(
1505 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1506 const GLfloat
* value
);
1507 void DoUniformMatrix3fv(
1508 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1509 const GLfloat
* value
);
1510 void DoUniformMatrix4fv(
1511 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1512 const GLfloat
* value
);
1514 bool SetVertexAttribValue(
1515 const char* function_name
, GLuint index
, const GLfloat
* value
);
1517 // Wrappers for glVertexAttrib??
1518 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1519 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1520 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1521 void DoVertexAttrib4f(
1522 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1523 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1524 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1525 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1526 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1528 // Wrapper for glViewport
1529 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1531 // Wrapper for glUseProgram
1532 void DoUseProgram(GLuint program
);
1534 // Wrapper for glValidateProgram.
1535 void DoValidateProgram(GLuint program_client_id
);
1537 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1538 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1539 void DoPopGroupMarkerEXT(void);
1541 // Gets the number of values that will be returned by glGetXXX. Returns
1542 // false if pname is unknown.
1543 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1545 // Checks if the current program and vertex attributes are valid for drawing.
1547 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1550 // Returns true if successful, simulated will be true if attrib0 was
1552 bool SimulateAttrib0(
1553 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1554 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1556 // If an image is bound to texture, this will call Will/DidUseTexImage
1558 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1559 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1561 // Returns false if textures were replaced.
1562 bool PrepareTexturesForRender();
1563 void RestoreStateForTextures();
1565 // Returns true if GL_FIXED attribs were simulated.
1566 bool SimulateFixedAttribs(
1567 const char* function_name
,
1568 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1569 void RestoreStateForSimulatedFixedAttribs();
1571 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1572 // cases (primcount is always 1 for non-instanced).
1573 error::Error
DoDrawArrays(
1574 const char* function_name
,
1575 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1577 error::Error
DoDrawElements(
1578 const char* function_name
,
1579 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1580 int32 offset
, GLsizei primcount
);
1582 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1583 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1584 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1587 return GL_TEXTURE_2D
;
1588 case GL_SAMPLER_CUBE
:
1589 return GL_TEXTURE_CUBE_MAP
;
1590 case GL_SAMPLER_EXTERNAL_OES
:
1591 return GL_TEXTURE_EXTERNAL_OES
;
1592 case GL_SAMPLER_2D_RECT_ARB
:
1593 return GL_TEXTURE_RECTANGLE_ARB
;
1600 // Gets the framebuffer info for a particular target.
1601 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1602 Framebuffer
* framebuffer
= NULL
;
1604 case GL_FRAMEBUFFER
:
1605 case GL_DRAW_FRAMEBUFFER_EXT
:
1606 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1608 case GL_READ_FRAMEBUFFER_EXT
:
1609 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1618 Renderbuffer
* GetRenderbufferInfoForTarget(
1620 Renderbuffer
* renderbuffer
= NULL
;
1622 case GL_RENDERBUFFER
:
1623 renderbuffer
= state_
.bound_renderbuffer
.get();
1629 return renderbuffer
;
1632 // Validates the program and location for a glGetUniform call and returns
1633 // a SizeResult setup to receive the result. Returns true if glGetUniform
1634 // should be called.
1635 bool GetUniformSetup(
1636 GLuint program
, GLint fake_location
,
1637 uint32 shm_id
, uint32 shm_offset
,
1638 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1639 void** result
, GLenum
* result_type
);
1641 void MaybeExitOnContextLost();
1642 bool WasContextLost() override
;
1643 bool WasContextLostByRobustnessExtension() override
;
1644 void LoseContext(uint32 reset_status
) override
;
1646 #if defined(OS_MACOSX)
1647 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1650 bool ValidateCompressedTexDimensions(
1651 const char* function_name
,
1652 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1653 bool ValidateCompressedTexFuncData(
1654 const char* function_name
,
1655 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1656 bool ValidateCompressedTexSubDimensions(
1657 const char* function_name
,
1658 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1659 GLsizei width
, GLsizei height
, GLenum format
,
1662 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1663 void PerformanceWarning(
1664 const char* filename
, int line
, const std::string
& msg
);
1666 const FeatureInfo::FeatureFlags
& features() const {
1667 return feature_info_
->feature_flags();
1670 const FeatureInfo::Workarounds
& workarounds() const {
1671 return feature_info_
->workarounds();
1674 bool ShouldDeferDraws() {
1675 return !offscreen_target_frame_buffer_
.get() &&
1676 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1677 surface_
->DeferDraws();
1680 bool ShouldDeferReads() {
1681 return !offscreen_target_frame_buffer_
.get() &&
1682 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1683 surface_
->DeferDraws();
1686 bool IsRobustnessSupported() {
1687 return has_robustness_extension_
&&
1688 context_
->WasAllocatedUsingRobustnessExtension();
1691 error::Error
WillAccessBoundFramebufferForDraw() {
1692 if (ShouldDeferDraws())
1693 return error::kDeferCommandUntilLater
;
1694 if (!offscreen_target_frame_buffer_
.get() &&
1695 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1696 !surface_
->SetBackbufferAllocation(true))
1697 return error::kLostContext
;
1698 return error::kNoError
;
1701 error::Error
WillAccessBoundFramebufferForRead() {
1702 if (ShouldDeferReads())
1703 return error::kDeferCommandUntilLater
;
1704 if (!offscreen_target_frame_buffer_
.get() &&
1705 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1706 !surface_
->SetBackbufferAllocation(true))
1707 return error::kLostContext
;
1708 return error::kNoError
;
1711 // Set remaining commands to process to 0 to force DoCommands to return
1712 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1713 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1715 void ProcessPendingReadPixels();
1716 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1718 // Generate a member function prototype for each command in an automated and
1720 #define GLES2_CMD_OP(name) \
1721 Error Handle##name(uint32 immediate_data_size, const void* data);
1723 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1727 // The GL context this decoder renders to on behalf of the client.
1728 scoped_refptr
<gfx::GLSurface
> surface_
;
1729 scoped_refptr
<gfx::GLContext
> context_
;
1731 // The ContextGroup for this decoder uses to track resources.
1732 scoped_refptr
<ContextGroup
> group_
;
1734 DebugMarkerManager debug_marker_manager_
;
1737 // All the state for this context.
1738 ContextState state_
;
1740 // Current width and height of the offscreen frame buffer.
1741 gfx::Size offscreen_size_
;
1743 // Util to help with GL.
1746 // unpack flip y as last set by glPixelStorei
1747 bool unpack_flip_y_
;
1749 // unpack (un)premultiply alpha as last set by glPixelStorei
1750 bool unpack_premultiply_alpha_
;
1751 bool unpack_unpremultiply_alpha_
;
1753 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1754 GLuint attrib_0_buffer_id_
;
1756 // The value currently in attrib_0.
1757 Vec4 attrib_0_value_
;
1759 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1760 bool attrib_0_buffer_matches_value_
;
1762 // The size of attrib 0.
1763 GLsizei attrib_0_size_
;
1765 // The buffer used to simulate GL_FIXED attribs.
1766 GLuint fixed_attrib_buffer_id_
;
1768 // The size of fiixed attrib buffer.
1769 GLsizei fixed_attrib_buffer_size_
;
1771 // The offscreen frame buffer that the client renders to. With EGL, the
1772 // depth and stencil buffers are separate. With regular GL there is a single
1773 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1774 // offscreen_target_stencil_render_buffer_ is unused.
1775 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1776 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1777 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1778 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1779 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1780 GLenum offscreen_target_color_format_
;
1781 GLenum offscreen_target_depth_format_
;
1782 GLenum offscreen_target_stencil_format_
;
1783 GLsizei offscreen_target_samples_
;
1784 GLboolean offscreen_target_buffer_preserved_
;
1786 // The copy that is saved when SwapBuffers is called.
1787 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1788 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1789 scoped_refptr
<TextureRef
>
1790 offscreen_saved_color_texture_info_
;
1792 // The copy that is used as the destination for multi-sample resolves.
1793 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1794 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1795 GLenum offscreen_saved_color_format_
;
1797 scoped_ptr
<QueryManager
> query_manager_
;
1799 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1801 scoped_ptr
<ImageManager
> image_manager_
;
1803 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1805 WaitSyncPointCallback wait_sync_point_callback_
;
1807 ShaderCacheCallback shader_cache_callback_
;
1809 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1811 // The format of the back buffer_
1812 GLenum back_buffer_color_format_
;
1813 bool back_buffer_has_depth_
;
1814 bool back_buffer_has_stencil_
;
1818 // Backbuffer attachments that are currently undefined.
1819 uint32 backbuffer_needs_clear_bits_
;
1821 // The current decoder error communicates the decoder error through command
1822 // processing functions that do not return the error value. Should be set only
1823 // if not returning an error.
1824 error::Error current_decoder_error_
;
1826 bool use_shader_translator_
;
1827 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1828 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1830 DisallowedFeatures disallowed_features_
;
1832 // Cached from ContextGroup
1833 const Validators
* validators_
;
1834 scoped_refptr
<FeatureInfo
> feature_info_
;
1838 // Number of commands remaining to be processed in DoCommands().
1839 int commands_to_process_
;
1841 bool has_robustness_extension_
;
1842 GLenum reset_status_
;
1843 bool reset_by_robustness_extension_
;
1844 bool supports_post_sub_buffer_
;
1846 // These flags are used to override the state of the shared feature_info_
1847 // member. Because the same FeatureInfo instance may be shared among many
1848 // contexts, the assumptions on the availablity of extensions in WebGL
1849 // contexts may be broken. These flags override the shared state to preserve
1851 bool force_webgl_glsl_validation_
;
1852 bool derivatives_explicitly_enabled_
;
1853 bool frag_depth_explicitly_enabled_
;
1854 bool draw_buffers_explicitly_enabled_
;
1855 bool shader_texture_lod_explicitly_enabled_
;
1857 bool compile_shader_always_succeeds_
;
1859 // An optional behaviour to lose the context and group when OOM.
1860 bool lose_context_when_out_of_memory_
;
1863 bool service_logging_
;
1865 #if defined(OS_MACOSX)
1866 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1867 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1870 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1871 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1873 // Cached values of the currently assigned viewport dimensions.
1874 GLsizei viewport_max_width_
;
1875 GLsizei viewport_max_height_
;
1877 // Command buffer stats.
1878 base::TimeDelta total_processing_commands_time_
;
1880 // States related to each manager.
1881 DecoderTextureState texture_state_
;
1882 DecoderFramebufferState framebuffer_state_
;
1884 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1885 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1886 const unsigned char* cb_command_trace_category_
;
1887 const unsigned char* gpu_decoder_category_
;
1888 int gpu_trace_level_
;
1889 bool gpu_trace_commands_
;
1890 bool gpu_debug_commands_
;
1892 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1894 // Used to validate multisample renderbuffers if needed
1895 GLuint validation_texture_
;
1896 GLuint validation_fbo_multisample_
;
1897 GLuint validation_fbo_
;
1899 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1900 uint32 immediate_data_size
,
1903 // A struct to hold info about each command.
1904 struct CommandInfo
{
1905 CmdHandler cmd_handler
;
1906 uint8 arg_flags
; // How to handle the arguments for this command
1907 uint8 cmd_flags
; // How to handle this command
1908 uint16 arg_count
; // How many arguments are expected for this command.
1911 // A table of CommandInfo for all the commands.
1912 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1914 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1917 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1918 #define GLES2_CMD_OP(name) \
1920 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1921 cmds::name::cmd_flags, \
1922 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1925 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1929 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1930 const char* function_name
, ErrorState
* error_state
)
1931 : function_name_(function_name
),
1932 error_state_(error_state
) {
1933 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1936 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1937 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1940 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1941 TextureUnit
& info
= state
->texture_units
[0];
1943 scoped_refptr
<TextureRef
> texture_ref
;
1946 texture_ref
= info
.bound_texture_2d
;
1948 case GL_TEXTURE_CUBE_MAP
:
1949 texture_ref
= info
.bound_texture_cube_map
;
1951 case GL_TEXTURE_EXTERNAL_OES
:
1952 texture_ref
= info
.bound_texture_external_oes
;
1954 case GL_TEXTURE_RECTANGLE_ARB
:
1955 texture_ref
= info
.bound_texture_rectangle_arb
;
1961 if (texture_ref
.get()) {
1962 last_id
= texture_ref
->service_id();
1967 glBindTexture(target
, last_id
);
1968 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1971 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1976 ScopedGLErrorSuppressor
suppressor(
1977 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1979 // TODO(apatrick): Check if there are any other states that need to be reset
1980 // before binding a new texture.
1981 glActiveTexture(GL_TEXTURE0
);
1982 glBindTexture(target
, id
);
1985 ScopedTextureBinder::~ScopedTextureBinder() {
1986 ScopedGLErrorSuppressor
suppressor(
1987 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1988 RestoreCurrentTextureBindings(state_
, target_
);
1991 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1994 ScopedGLErrorSuppressor
suppressor(
1995 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1996 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1999 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2000 ScopedGLErrorSuppressor
suppressor(
2001 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2002 state_
->RestoreRenderbufferBindings();
2005 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2007 : decoder_(decoder
) {
2008 ScopedGLErrorSuppressor
suppressor(
2009 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2010 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2011 decoder
->OnFboChanged();
2014 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2015 ScopedGLErrorSuppressor
suppressor(
2016 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2017 decoder_
->RestoreCurrentFramebufferBindings();
2020 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2021 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2022 : decoder_(decoder
) {
2023 resolve_and_bind_
= (
2024 decoder_
->offscreen_target_frame_buffer_
.get() &&
2025 decoder_
->IsOffscreenBufferMultisampled() &&
2026 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2027 enforce_internal_framebuffer
));
2028 if (!resolve_and_bind_
)
2031 ScopedGLErrorSuppressor
suppressor(
2032 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2033 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2034 decoder_
->offscreen_target_frame_buffer_
->id());
2037 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2038 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2039 new BackFramebuffer(decoder_
));
2040 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2041 decoder_
->offscreen_resolved_color_texture_
.reset(
2042 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2043 decoder_
->offscreen_resolved_color_texture_
->Create();
2045 DCHECK(decoder_
->offscreen_saved_color_format_
);
2046 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2047 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2049 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2050 decoder_
->offscreen_resolved_color_texture_
.get());
2051 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2052 GL_FRAMEBUFFER_COMPLETE
) {
2053 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2054 << "because offscreen resolved FBO was incomplete.";
2058 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2060 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2062 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2063 const int width
= decoder_
->offscreen_size_
.width();
2064 const int height
= decoder_
->offscreen_size_
.height();
2065 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2066 decoder
->BlitFramebufferHelper(0,
2074 GL_COLOR_BUFFER_BIT
,
2076 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2079 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2080 if (!resolve_and_bind_
)
2083 ScopedGLErrorSuppressor
suppressor(
2084 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2085 decoder_
->RestoreCurrentFramebufferBindings();
2086 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2087 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2091 BackTexture::BackTexture(
2092 MemoryTracker
* memory_tracker
,
2093 ContextState
* state
)
2094 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2096 bytes_allocated_(0),
2100 BackTexture::~BackTexture() {
2101 // This does not destroy the render texture because that would require that
2102 // the associated GL context was current. Just check that it was explicitly
2107 void BackTexture::Create() {
2108 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2109 state_
->GetErrorState());
2111 glGenTextures(1, &id_
);
2112 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2113 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2114 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2115 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2116 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2118 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2119 // never called on an offscreen context, no data will ever be uploaded to the
2120 // saved offscreen color texture (it is deferred until to when SwapBuffers
2121 // is called). My idea is that some nvidia drivers might have a bug where
2122 // deleting a texture that has never been populated might cause a
2125 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2127 bytes_allocated_
= 16u * 16u * 4u;
2128 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2131 bool BackTexture::AllocateStorage(
2132 const gfx::Size
& size
, GLenum format
, bool zero
) {
2134 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2135 state_
->GetErrorState());
2136 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2137 uint32 image_size
= 0;
2138 GLES2Util::ComputeImageDataSizes(
2139 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2142 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2146 scoped_ptr
<char[]> zero_data
;
2148 zero_data
.reset(new char[image_size
]);
2149 memset(zero_data
.get(), 0, image_size
);
2152 glTexImage2D(GL_TEXTURE_2D
,
2164 bool success
= glGetError() == GL_NO_ERROR
;
2166 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2167 bytes_allocated_
= image_size
;
2168 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2173 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2175 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2176 state_
->GetErrorState());
2177 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2178 glCopyTexImage2D(GL_TEXTURE_2D
,
2187 void BackTexture::Destroy() {
2189 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2190 state_
->GetErrorState());
2191 glDeleteTextures(1, &id_
);
2194 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2195 bytes_allocated_
= 0;
2198 void BackTexture::Invalidate() {
2202 BackRenderbuffer::BackRenderbuffer(
2203 RenderbufferManager
* renderbuffer_manager
,
2204 MemoryTracker
* memory_tracker
,
2205 ContextState
* state
)
2206 : renderbuffer_manager_(renderbuffer_manager
),
2207 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2209 bytes_allocated_(0),
2213 BackRenderbuffer::~BackRenderbuffer() {
2214 // This does not destroy the render buffer because that would require that
2215 // the associated GL context was current. Just check that it was explicitly
2220 void BackRenderbuffer::Create() {
2221 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2222 state_
->GetErrorState());
2224 glGenRenderbuffersEXT(1, &id_
);
2227 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2228 const gfx::Size
& size
,
2231 ScopedGLErrorSuppressor
suppressor(
2232 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2233 ScopedRenderBufferBinder
binder(state_
, id_
);
2235 uint32 estimated_size
= 0;
2236 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2237 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2241 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2246 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2251 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2258 bool success
= glGetError() == GL_NO_ERROR
;
2260 // Mark the previously allocated bytes as free.
2261 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2262 bytes_allocated_
= estimated_size
;
2263 // Track the newly allocated bytes.
2264 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2269 void BackRenderbuffer::Destroy() {
2271 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2272 state_
->GetErrorState());
2273 glDeleteRenderbuffersEXT(1, &id_
);
2276 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2277 bytes_allocated_
= 0;
2280 void BackRenderbuffer::Invalidate() {
2284 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2285 : decoder_(decoder
),
2289 BackFramebuffer::~BackFramebuffer() {
2290 // This does not destroy the frame buffer because that would require that
2291 // the associated GL context was current. Just check that it was explicitly
2296 void BackFramebuffer::Create() {
2297 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2298 decoder_
->GetErrorState());
2300 glGenFramebuffersEXT(1, &id_
);
2303 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2305 ScopedGLErrorSuppressor
suppressor(
2306 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2307 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2308 GLuint attach_id
= texture
? texture
->id() : 0;
2309 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2310 GL_COLOR_ATTACHMENT0
,
2316 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2317 BackRenderbuffer
* render_buffer
) {
2319 ScopedGLErrorSuppressor
suppressor(
2320 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2321 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2322 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2323 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2329 void BackFramebuffer::Destroy() {
2331 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2332 decoder_
->GetErrorState());
2333 glDeleteFramebuffersEXT(1, &id_
);
2338 void BackFramebuffer::Invalidate() {
2342 GLenum
BackFramebuffer::CheckStatus() {
2344 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2345 decoder_
->GetErrorState());
2346 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2347 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2350 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2351 return new GLES2DecoderImpl(group
);
2354 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2357 logger_(&debug_marker_manager_
),
2358 state_(group_
->feature_info(), this, &logger_
),
2359 unpack_flip_y_(false),
2360 unpack_premultiply_alpha_(false),
2361 unpack_unpremultiply_alpha_(false),
2362 attrib_0_buffer_id_(0),
2363 attrib_0_buffer_matches_value_(true),
2365 fixed_attrib_buffer_id_(0),
2366 fixed_attrib_buffer_size_(0),
2367 offscreen_target_color_format_(0),
2368 offscreen_target_depth_format_(0),
2369 offscreen_target_stencil_format_(0),
2370 offscreen_target_samples_(0),
2371 offscreen_target_buffer_preserved_(true),
2372 offscreen_saved_color_format_(0),
2373 back_buffer_color_format_(0),
2374 back_buffer_has_depth_(false),
2375 back_buffer_has_stencil_(false),
2376 surfaceless_(false),
2377 backbuffer_needs_clear_bits_(0),
2378 current_decoder_error_(error::kNoError
),
2379 use_shader_translator_(true),
2380 validators_(group_
->feature_info()->validators()),
2381 feature_info_(group_
->feature_info()),
2383 has_robustness_extension_(false),
2384 reset_status_(GL_NO_ERROR
),
2385 reset_by_robustness_extension_(false),
2386 supports_post_sub_buffer_(false),
2387 force_webgl_glsl_validation_(false),
2388 derivatives_explicitly_enabled_(false),
2389 frag_depth_explicitly_enabled_(false),
2390 draw_buffers_explicitly_enabled_(false),
2391 shader_texture_lod_explicitly_enabled_(false),
2392 compile_shader_always_succeeds_(false),
2393 lose_context_when_out_of_memory_(false),
2394 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2395 switches::kEnableGPUServiceLoggingGPU
)),
2396 viewport_max_width_(0),
2397 viewport_max_height_(0),
2398 texture_state_(group_
->feature_info()
2400 .texsubimage2d_faster_than_teximage2d
),
2401 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2402 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2403 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2404 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2405 gpu_trace_level_(2),
2406 gpu_trace_commands_(false),
2407 gpu_debug_commands_(false),
2408 validation_texture_(0),
2409 validation_fbo_multisample_(0),
2410 validation_fbo_(0) {
2413 attrib_0_value_
.v
[0] = 0.0f
;
2414 attrib_0_value_
.v
[1] = 0.0f
;
2415 attrib_0_value_
.v
[2] = 0.0f
;
2416 attrib_0_value_
.v
[3] = 1.0f
;
2418 // The shader translator is used for WebGL even when running on EGL
2419 // because additional restrictions are needed (like only enabling
2420 // GL_OES_standard_derivatives on demand). It is used for the unit
2421 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2422 // the empty string to CompileShader and this is not a valid shader.
2423 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2424 base::CommandLine::ForCurrentProcess()->HasSwitch(
2425 switches::kDisableGLSLTranslator
)) {
2426 use_shader_translator_
= false;
2430 GLES2DecoderImpl::~GLES2DecoderImpl() {
2433 bool GLES2DecoderImpl::Initialize(
2434 const scoped_refptr
<gfx::GLSurface
>& surface
,
2435 const scoped_refptr
<gfx::GLContext
>& context
,
2437 const gfx::Size
& size
,
2438 const DisallowedFeatures
& disallowed_features
,
2439 const std::vector
<int32
>& attribs
) {
2440 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2441 DCHECK(context
->IsCurrent(surface
.get()));
2442 DCHECK(!context_
.get());
2444 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2447 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2449 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2450 switches::kEnableGPUDebugging
)) {
2454 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2455 switches::kEnableGPUCommandLogging
)) {
2456 set_log_commands(true);
2459 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2460 switches::kEnableUnsafeES3APIs
)) {
2461 set_unsafe_es3_apis_enabled(true);
2464 compile_shader_always_succeeds_
=
2465 base::CommandLine::ForCurrentProcess()->HasSwitch(
2466 switches::kCompileShaderAlwaysSucceeds
);
2468 // Take ownership of the context and surface. The surface can be replaced with
2473 ContextCreationAttribHelper attrib_parser
;
2474 if (!attrib_parser
.Parse(attribs
))
2477 // Create GPU Tracer for timing values.
2478 gpu_tracer_
.reset(new GPUTracer(this));
2480 // Save the loseContextWhenOutOfMemory context creation attribute.
2481 lose_context_when_out_of_memory_
=
2482 attrib_parser
.lose_context_when_out_of_memory
;
2484 // If the failIfMajorPerformanceCaveat context creation attribute was true
2485 // and we are using a software renderer, fail.
2486 if (attrib_parser
.fail_if_major_perf_caveat
&&
2487 feature_info_
->feature_flags().is_swiftshader
) {
2488 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2493 if (!group_
->Initialize(this, disallowed_features
)) {
2494 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2495 << "failed to initialize.";
2496 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2502 disallowed_features_
= disallowed_features
;
2504 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2505 vertex_array_manager_
.reset(new VertexArrayManager());
2507 GLuint default_vertex_attrib_service_id
= 0;
2508 if (features().native_vertex_array_object
) {
2509 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2510 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2513 state_
.default_vertex_attrib_manager
=
2514 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2516 state_
.default_vertex_attrib_manager
->Initialize(
2517 group_
->max_vertex_attribs(),
2518 feature_info_
->workarounds().init_vertex_attributes
);
2520 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2521 DoBindVertexArrayOES(0);
2523 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2525 image_manager_
.reset(new ImageManager
);
2527 util_
.set_num_compressed_texture_formats(
2528 validators_
->compressed_texture_format
.GetValues().size());
2530 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2531 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2532 // OpenGL ES 2.0 does not have this issue.
2533 glEnableVertexAttribArray(0);
2535 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2536 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2537 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2538 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2539 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2541 state_
.texture_units
.resize(group_
->max_texture_units());
2542 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2543 glActiveTexture(GL_TEXTURE0
+ tt
);
2544 // We want the last bind to be 2D.
2546 if (features().oes_egl_image_external
) {
2547 ref
= texture_manager()->GetDefaultTextureInfo(
2548 GL_TEXTURE_EXTERNAL_OES
);
2549 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2550 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2552 if (features().arb_texture_rectangle
) {
2553 ref
= texture_manager()->GetDefaultTextureInfo(
2554 GL_TEXTURE_RECTANGLE_ARB
);
2555 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2556 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2558 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2559 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2560 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2561 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2562 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2563 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2565 glActiveTexture(GL_TEXTURE0
);
2569 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2570 features().chromium_framebuffer_multisample
) {
2571 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2572 // max_sample_count must be initialized to a sane value. If
2573 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2574 GLint max_sample_count
= 1;
2575 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2576 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2579 offscreen_target_samples_
= 1;
2581 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2583 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2584 const bool rgb8_supported
=
2585 context_
->HasExtension("GL_OES_rgb8_rgba8");
2586 // The only available default render buffer formats in GLES2 have very
2587 // little precision. Don't enable multisampling unless 8-bit render
2588 // buffer formats are available--instead fall back to 8-bit textures.
2589 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2590 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2593 offscreen_target_samples_
= 1;
2594 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2598 // ANGLE only supports packed depth/stencil formats, so use it if it is
2600 const bool depth24_stencil8_supported
=
2601 feature_info_
->feature_flags().packed_depth24_stencil8
;
2602 VLOG(1) << "GL_OES_packed_depth_stencil "
2603 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2604 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2605 depth24_stencil8_supported
) {
2606 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2607 offscreen_target_stencil_format_
= 0;
2609 // It may be the case that this depth/stencil combination is not
2610 // supported, but this will be checked later by CheckFramebufferStatus.
2611 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2612 GL_DEPTH_COMPONENT16
: 0;
2613 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2614 GL_STENCIL_INDEX8
: 0;
2617 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2620 // If depth is requested at all, use the packed depth stencil format if
2621 // it's available, as some desktop GL drivers don't support any non-packed
2622 // formats for depth attachments.
2623 const bool depth24_stencil8_supported
=
2624 feature_info_
->feature_flags().packed_depth24_stencil8
;
2625 VLOG(1) << "GL_EXT_packed_depth_stencil "
2626 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2628 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2629 depth24_stencil8_supported
) {
2630 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2631 offscreen_target_stencil_format_
= 0;
2633 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2634 GL_DEPTH_COMPONENT
: 0;
2635 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2636 GL_STENCIL_INDEX
: 0;
2640 offscreen_saved_color_format_
= attrib_parser
.alpha_size
> 0 ?
2643 // Create the target frame buffer. This is the one that the client renders
2645 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2646 offscreen_target_frame_buffer_
->Create();
2647 // Due to GLES2 format limitations, either the color texture (for
2648 // non-multisampling) or the color render buffer (for multisampling) will be
2649 // attached to the offscreen frame buffer. The render buffer has more
2650 // limited formats available to it, but the texture can't do multisampling.
2651 if (IsOffscreenBufferMultisampled()) {
2652 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2653 renderbuffer_manager(), memory_tracker(), &state_
));
2654 offscreen_target_color_render_buffer_
->Create();
2656 offscreen_target_color_texture_
.reset(new BackTexture(
2657 memory_tracker(), &state_
));
2658 offscreen_target_color_texture_
->Create();
2660 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2661 renderbuffer_manager(), memory_tracker(), &state_
));
2662 offscreen_target_depth_render_buffer_
->Create();
2663 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2664 renderbuffer_manager(), memory_tracker(), &state_
));
2665 offscreen_target_stencil_render_buffer_
->Create();
2667 // Create the saved offscreen texture. The target frame buffer is copied
2668 // here when SwapBuffers is called.
2669 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2670 offscreen_saved_frame_buffer_
->Create();
2672 offscreen_saved_color_texture_
.reset(new BackTexture(
2673 memory_tracker(), &state_
));
2674 offscreen_saved_color_texture_
->Create();
2676 // Allocate the render buffers at their initial size and check the status
2677 // of the frame buffers is okay.
2678 if (!ResizeOffscreenFrameBuffer(size
)) {
2679 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2684 // Allocate the offscreen saved color texture.
2685 DCHECK(offscreen_saved_color_format_
);
2686 offscreen_saved_color_texture_
->AllocateStorage(
2687 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2689 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2690 offscreen_saved_color_texture_
.get());
2691 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2692 GL_FRAMEBUFFER_COMPLETE
) {
2693 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2698 // Bind to the new default frame buffer (the offscreen target frame buffer).
2699 // This should now be associated with ID zero.
2700 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2702 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2703 // These are NOT if the back buffer has these proprorties. They are
2704 // if we want the command buffer to enforce them regardless of what
2705 // the real backbuffer is assuming the real back buffer gives us more than
2706 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2707 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2708 // can't do anything about that.
2710 if (!surfaceless_
) {
2712 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2713 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2714 // the user requested RGB then RGB. If the user did not specify a
2715 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2716 back_buffer_color_format_
=
2717 (attrib_parser
.alpha_size
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2718 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2719 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && v
> 0;
2720 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2721 back_buffer_has_stencil_
= attrib_parser
.stencil_size
!= 0 && v
> 0;
2725 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2726 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2727 // isn't well documented; it was discovered in the Khronos OpenGL ES
2728 // mailing list archives. It also implicitly enables the desktop GL
2729 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2730 // variable in fragment shaders.
2731 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2732 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2733 glEnable(GL_POINT_SPRITE
);
2736 has_robustness_extension_
=
2737 context
->HasExtension("GL_ARB_robustness") ||
2738 context
->HasExtension("GL_KHR_robustness") ||
2739 context
->HasExtension("GL_EXT_robustness");
2741 if (!InitializeShaderTranslator()) {
2745 state_
.viewport_width
= size
.width();
2746 state_
.viewport_height
= size
.height();
2748 GLint viewport_params
[4] = { 0 };
2749 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2750 viewport_max_width_
= viewport_params
[0];
2751 viewport_max_height_
= viewport_params
[1];
2753 state_
.scissor_width
= state_
.viewport_width
;
2754 state_
.scissor_height
= state_
.viewport_height
;
2756 // Set all the default state because some GL drivers get it wrong.
2757 state_
.InitCapabilities(NULL
);
2758 state_
.InitState(NULL
);
2759 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2761 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2762 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2763 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2764 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2765 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2767 bool call_gl_clear
= !surfaceless_
;
2768 #if defined(OS_ANDROID)
2769 // Temporary workaround for Android WebView because this clear ignores the
2770 // clip and corrupts that external UI of the App. Not calling glClear is ok
2771 // because the system already clears the buffer before each draw. Proper
2772 // fix might be setting the scissor clip properly before initialize. See
2773 // crbug.com/259023 for details.
2774 call_gl_clear
= surface_
->GetHandle();
2776 if (call_gl_clear
) {
2777 // Clear the backbuffer.
2778 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2781 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2782 if (feature_info_
->workarounds()
2783 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2784 !surface
->IsOffscreen())
2785 supports_post_sub_buffer_
= false;
2787 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2788 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2791 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2792 context_
->SetUnbindFboOnMakeCurrent();
2795 // Only compositor contexts are known to use only the subset of GL
2796 // that can be safely migrated between the iGPU and the dGPU. Mark
2797 // those contexts as safe to forcibly transition between the GPUs.
2798 // http://crbug.com/180876, http://crbug.com/227228
2800 context_
->SetSafeToForceGpuSwitch();
2802 async_pixel_transfer_manager_
.reset(
2803 AsyncPixelTransferManager::Create(context
.get()));
2804 async_pixel_transfer_manager_
->Initialize(texture_manager());
2806 if (workarounds().gl_clear_broken
) {
2807 DCHECK(!clear_framebuffer_blit_
.get());
2808 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2809 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2810 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2814 framebuffer_manager()->AddObserver(this);
2819 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2820 DCHECK(initialized());
2823 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2824 Capabilities::ShaderPrecision
* shader_precision
) {
2825 GLint range
[2] = {0, 0};
2826 GLint precision
= 0;
2827 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2828 shader_precision
->min_range
= range
[0];
2829 shader_precision
->max_range
= range
[1];
2830 shader_precision
->precision
= precision
;
2832 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2833 &caps
.max_combined_texture_image_units
);
2834 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2835 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2836 &caps
.max_fragment_uniform_vectors
);
2837 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2838 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2839 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2840 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2841 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2842 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2843 &caps
.max_vertex_texture_image_units
);
2844 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2845 &caps
.max_vertex_uniform_vectors
);
2846 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2847 &caps
.num_compressed_texture_formats
);
2848 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2849 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2850 &caps
.bind_generates_resource_chromium
);
2851 if (unsafe_es3_apis_enabled()) {
2852 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
2853 &caps
.max_transform_feedback_separate_attribs
);
2854 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
2855 &caps
.max_uniform_buffer_bindings
);
2856 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
2857 &caps
.uniform_buffer_offset_alignment
);
2860 caps
.egl_image_external
=
2861 feature_info_
->feature_flags().oes_egl_image_external
;
2862 caps
.texture_format_atc
=
2863 feature_info_
->feature_flags().ext_texture_format_atc
;
2864 caps
.texture_format_bgra8888
=
2865 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2866 caps
.texture_format_dxt1
=
2867 feature_info_
->feature_flags().ext_texture_format_dxt1
;
2868 caps
.texture_format_dxt5
=
2869 feature_info_
->feature_flags().ext_texture_format_dxt5
;
2870 caps
.texture_format_etc1
=
2871 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2872 caps
.texture_format_etc1_npot
=
2873 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2874 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2875 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2876 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2877 caps
.discard_framebuffer
=
2878 feature_info_
->feature_flags().ext_discard_framebuffer
;
2879 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2881 #if defined(OS_MACOSX)
2882 // This is unconditionally true on mac, no need to test for it at runtime.
2883 caps
.iosurface
= true;
2886 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2889 caps
.blend_equation_advanced
=
2890 feature_info_
->feature_flags().blend_equation_advanced
;
2891 caps
.blend_equation_advanced_coherent
=
2892 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
2893 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
2897 void GLES2DecoderImpl::UpdateCapabilities() {
2898 util_
.set_num_compressed_texture_formats(
2899 validators_
->compressed_texture_format
.GetValues().size());
2900 util_
.set_num_shader_binary_formats(
2901 validators_
->shader_binary_format
.GetValues().size());
2904 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2905 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2907 if (!use_shader_translator_
) {
2910 ShBuiltInResources resources
;
2911 ShInitBuiltInResources(&resources
);
2912 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2913 resources
.MaxVertexUniformVectors
=
2914 group_
->max_vertex_uniform_vectors();
2915 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2916 resources
.MaxVertexTextureImageUnits
=
2917 group_
->max_vertex_texture_image_units();
2918 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2919 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2920 resources
.MaxFragmentUniformVectors
=
2921 group_
->max_fragment_uniform_vectors();
2922 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2923 resources
.MaxExpressionComplexity
= 256;
2924 resources
.MaxCallStackDepth
= 256;
2926 GLint range
[2] = { 0, 0 };
2927 GLint precision
= 0;
2928 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2930 resources
.FragmentPrecisionHigh
=
2931 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2933 if (force_webgl_glsl_validation_
) {
2934 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2935 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2936 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2937 if (!draw_buffers_explicitly_enabled_
)
2938 resources
.MaxDrawBuffers
= 1;
2939 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2940 resources
.NV_draw_buffers
=
2941 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
2943 resources
.OES_standard_derivatives
=
2944 features().oes_standard_derivatives
? 1 : 0;
2945 resources
.ARB_texture_rectangle
=
2946 features().arb_texture_rectangle
? 1 : 0;
2947 resources
.OES_EGL_image_external
=
2948 features().oes_egl_image_external
? 1 : 0;
2949 resources
.EXT_draw_buffers
=
2950 features().ext_draw_buffers
? 1 : 0;
2951 resources
.EXT_frag_depth
=
2952 features().ext_frag_depth
? 1 : 0;
2953 resources
.EXT_shader_texture_lod
=
2954 features().ext_shader_texture_lod
? 1 : 0;
2955 resources
.NV_draw_buffers
=
2956 features().nv_draw_buffers
? 1 : 0;
2959 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2961 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2962 resources
.HashFunction
= &CityHash64
;
2964 resources
.HashFunction
= NULL
;
2965 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2966 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2967 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2968 int driver_bug_workarounds
= 0;
2969 if (workarounds().needs_glsl_built_in_function_emulation
)
2970 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2971 if (workarounds().init_gl_position_in_vertex_shader
)
2972 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2973 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2974 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2975 if (workarounds().init_varyings_without_static_use
)
2976 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2977 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2978 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2979 if (workarounds().scalarize_vec_and_mat_constructor_args
)
2980 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
2981 if (workarounds().regenerate_struct_names
)
2982 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
2984 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2985 switches::kEmulateShaderPrecision
))
2986 resources
.WEBGL_debug_shader_precision
= true;
2988 vertex_translator_
= shader_translator_cache()->GetTranslator(
2992 implementation_type
,
2993 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2994 if (!vertex_translator_
.get()) {
2995 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3000 fragment_translator_
= shader_translator_cache()->GetTranslator(
3004 implementation_type
,
3005 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3006 if (!fragment_translator_
.get()) {
3007 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3014 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3015 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3016 if (GetBuffer(client_ids
[ii
])) {
3020 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3021 glGenBuffersARB(n
, service_ids
.get());
3022 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3023 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3028 bool GLES2DecoderImpl::GenFramebuffersHelper(
3029 GLsizei n
, const GLuint
* client_ids
) {
3030 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3031 if (GetFramebuffer(client_ids
[ii
])) {
3035 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3036 glGenFramebuffersEXT(n
, service_ids
.get());
3037 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3038 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3043 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3044 GLsizei n
, const GLuint
* client_ids
) {
3045 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3046 if (GetRenderbuffer(client_ids
[ii
])) {
3050 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3051 glGenRenderbuffersEXT(n
, service_ids
.get());
3052 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3053 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3058 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3059 const GLuint
* client_ids
) {
3060 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3061 if (GetValuebuffer(client_ids
[ii
])) {
3065 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3066 CreateValuebuffer(client_ids
[ii
]);
3071 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3072 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3073 if (GetTexture(client_ids
[ii
])) {
3077 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3078 glGenTextures(n
, service_ids
.get());
3079 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3080 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3085 void GLES2DecoderImpl::DeleteBuffersHelper(
3086 GLsizei n
, const GLuint
* client_ids
) {
3087 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3088 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3089 if (buffer
&& !buffer
->IsDeleted()) {
3090 state_
.vertex_attrib_manager
->Unbind(buffer
);
3091 if (state_
.bound_array_buffer
.get() == buffer
) {
3092 state_
.bound_array_buffer
= NULL
;
3094 RemoveBuffer(client_ids
[ii
]);
3099 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3100 GLsizei n
, const GLuint
* client_ids
) {
3101 bool supports_separate_framebuffer_binds
=
3102 features().chromium_framebuffer_multisample
;
3104 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3105 Framebuffer
* framebuffer
=
3106 GetFramebuffer(client_ids
[ii
]);
3107 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3108 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3109 GLenum target
= supports_separate_framebuffer_binds
?
3110 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3112 // Unbind attachments on FBO before deletion.
3113 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3114 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3116 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3117 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3118 framebuffer_state_
.clear_state_dirty
= true;
3120 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3121 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3122 GLenum target
= supports_separate_framebuffer_binds
?
3123 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3124 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3127 RemoveFramebuffer(client_ids
[ii
]);
3132 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3133 GLsizei n
, const GLuint
* client_ids
) {
3134 bool supports_separate_framebuffer_binds
=
3135 features().chromium_framebuffer_multisample
;
3136 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3137 Renderbuffer
* renderbuffer
=
3138 GetRenderbuffer(client_ids
[ii
]);
3139 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3140 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3141 state_
.bound_renderbuffer
= NULL
;
3143 // Unbind from current framebuffers.
3144 if (supports_separate_framebuffer_binds
) {
3145 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3146 framebuffer_state_
.bound_read_framebuffer
3147 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3149 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3150 framebuffer_state_
.bound_draw_framebuffer
3151 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3154 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3155 framebuffer_state_
.bound_draw_framebuffer
3156 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3159 framebuffer_state_
.clear_state_dirty
= true;
3160 RemoveRenderbuffer(client_ids
[ii
]);
3165 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3167 const GLuint
* client_ids
) {
3168 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3169 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3171 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3172 state_
.bound_valuebuffer
= NULL
;
3174 RemoveValuebuffer(client_ids
[ii
]);
3179 void GLES2DecoderImpl::DeleteTexturesHelper(
3180 GLsizei n
, const GLuint
* client_ids
) {
3181 bool supports_separate_framebuffer_binds
=
3182 features().chromium_framebuffer_multisample
;
3183 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3184 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3186 Texture
* texture
= texture_ref
->texture();
3187 if (texture
->IsAttachedToFramebuffer()) {
3188 framebuffer_state_
.clear_state_dirty
= true;
3190 // Unbind texture_ref from texture_ref units.
3191 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3192 state_
.texture_units
[jj
].Unbind(texture_ref
);
3194 // Unbind from current framebuffers.
3195 if (supports_separate_framebuffer_binds
) {
3196 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3197 framebuffer_state_
.bound_read_framebuffer
3198 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3200 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3201 framebuffer_state_
.bound_draw_framebuffer
3202 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3205 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3206 framebuffer_state_
.bound_draw_framebuffer
3207 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3210 #if defined(OS_MACOSX)
3211 GLuint service_id
= texture
->service_id();
3212 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3213 ReleaseIOSurfaceForTexture(service_id
);
3216 RemoveTexture(client_ids
[ii
]);
3221 // } // anonymous namespace
3223 bool GLES2DecoderImpl::MakeCurrent() {
3224 if (!context_
.get())
3227 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3228 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3230 MaybeExitOnContextLost();
3235 ProcessFinishedAsyncTransfers();
3237 // Rebind the FBO if it was unbound by the context.
3238 if (workarounds().unbind_fbo_on_context_switch
)
3239 RestoreFramebufferBindings();
3241 framebuffer_state_
.clear_state_dirty
= true;
3246 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3247 ProcessPendingReadPixels();
3248 if (engine() && query_manager_
.get())
3249 query_manager_
->ProcessPendingTransferQueries();
3251 // TODO(epenner): Is there a better place to do this?
3252 // This needs to occur before we execute any batch of commands
3253 // from the client, as the client may have recieved an async
3254 // completion while issuing those commands.
3255 // "DidFlushStart" would be ideal if we had such a callback.
3256 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3259 static void RebindCurrentFramebuffer(
3261 Framebuffer
* framebuffer
,
3262 GLuint back_buffer_service_id
) {
3263 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3265 if (framebuffer_id
== 0) {
3266 framebuffer_id
= back_buffer_service_id
;
3269 glBindFramebufferEXT(target
, framebuffer_id
);
3272 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3273 framebuffer_state_
.clear_state_dirty
= true;
3275 if (!features().chromium_framebuffer_multisample
) {
3276 RebindCurrentFramebuffer(
3278 framebuffer_state_
.bound_draw_framebuffer
.get(),
3279 GetBackbufferServiceId());
3281 RebindCurrentFramebuffer(
3282 GL_READ_FRAMEBUFFER_EXT
,
3283 framebuffer_state_
.bound_read_framebuffer
.get(),
3284 GetBackbufferServiceId());
3285 RebindCurrentFramebuffer(
3286 GL_DRAW_FRAMEBUFFER_EXT
,
3287 framebuffer_state_
.bound_draw_framebuffer
.get(),
3288 GetBackbufferServiceId());
3293 bool GLES2DecoderImpl::CheckFramebufferValid(
3294 Framebuffer
* framebuffer
,
3295 GLenum target
, const char* func_name
) {
3299 if (backbuffer_needs_clear_bits_
) {
3300 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3301 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3302 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3304 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3305 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3307 state_
.SetDeviceDepthMask(GL_TRUE
);
3308 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3309 bool reset_draw_buffer
= false;
3310 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3311 group_
->draw_buffer() == GL_NONE
) {
3312 reset_draw_buffer
= true;
3313 GLenum buf
= GL_BACK
;
3314 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3315 buf
= GL_COLOR_ATTACHMENT0
;
3316 glDrawBuffersARB(1, &buf
);
3318 glClear(backbuffer_needs_clear_bits_
);
3319 if (reset_draw_buffer
) {
3320 GLenum buf
= GL_NONE
;
3321 glDrawBuffersARB(1, &buf
);
3323 backbuffer_needs_clear_bits_
= 0;
3324 RestoreClearState();
3329 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3333 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3334 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3336 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3340 // Are all the attachments cleared?
3341 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3342 texture_manager()->HaveUnclearedMips()) {
3343 if (!framebuffer
->IsCleared()) {
3344 // Can we clear them?
3345 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3346 GL_FRAMEBUFFER_COMPLETE
) {
3348 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3349 "framebuffer incomplete (clear)");
3352 ClearUnclearedAttachments(target
, framebuffer
);
3356 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3357 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3358 GL_FRAMEBUFFER_COMPLETE
) {
3360 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3361 "framebuffer incomplete (check)");
3364 framebuffer_manager()->MarkAsComplete(framebuffer
);
3367 // NOTE: At this point we don't know if the framebuffer is complete but
3368 // we DO know that everything that needs to be cleared has been cleared.
3372 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3373 if (!features().chromium_framebuffer_multisample
) {
3374 bool valid
= CheckFramebufferValid(
3375 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3383 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3384 GL_DRAW_FRAMEBUFFER_EXT
,
3386 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3387 GL_READ_FRAMEBUFFER_EXT
,
3391 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3392 const char* func_name
) {
3393 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3394 framebuffer_state_
.bound_read_framebuffer
.get() :
3395 framebuffer_state_
.bound_draw_framebuffer
.get();
3398 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3400 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3406 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3407 TextureRef
* texture
, GLint level
) {
3408 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3409 framebuffer_state_
.bound_read_framebuffer
.get() :
3410 framebuffer_state_
.bound_draw_framebuffer
.get();
3413 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3414 GL_COLOR_ATTACHMENT0
);
3417 return attachment
->FormsFeedbackLoop(texture
, level
);
3420 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3421 Framebuffer
* framebuffer
=
3422 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3423 if (framebuffer
!= NULL
) {
3424 const Framebuffer::Attachment
* attachment
=
3425 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3427 return gfx::Size(attachment
->width(), attachment
->height());
3429 return gfx::Size(0, 0);
3430 } else if (offscreen_target_frame_buffer_
.get()) {
3431 return offscreen_size_
;
3433 return surface_
->GetSize();
3437 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3438 Framebuffer
* framebuffer
=
3439 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3440 if (framebuffer
!= NULL
) {
3441 return framebuffer
->GetColorAttachmentTextureType();
3443 return GL_UNSIGNED_BYTE
;
3447 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3448 Framebuffer
* framebuffer
=
3449 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3450 if (framebuffer
!= NULL
) {
3451 return framebuffer
->GetColorAttachmentFormat();
3452 } else if (offscreen_target_frame_buffer_
.get()) {
3453 return offscreen_target_color_format_
;
3455 return back_buffer_color_format_
;
3459 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3460 Framebuffer
* framebuffer
=
3461 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3462 if (framebuffer
!= NULL
) {
3463 return framebuffer
->GetColorAttachmentFormat();
3464 } else if (offscreen_target_frame_buffer_
.get()) {
3465 return offscreen_target_color_format_
;
3467 return back_buffer_color_format_
;
3471 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3472 if (!offscreen_saved_color_texture_info_
.get())
3474 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3475 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3476 texture_manager()->SetLevelInfo(
3477 offscreen_saved_color_texture_info_
.get(),
3481 offscreen_size_
.width(),
3482 offscreen_size_
.height(),
3488 texture_manager()->SetParameteri(
3489 "UpdateParentTextureInfo",
3491 offscreen_saved_color_texture_info_
.get(),
3492 GL_TEXTURE_MAG_FILTER
,
3494 texture_manager()->SetParameteri(
3495 "UpdateParentTextureInfo",
3497 offscreen_saved_color_texture_info_
.get(),
3498 GL_TEXTURE_MIN_FILTER
,
3500 texture_manager()->SetParameteri(
3501 "UpdateParentTextureInfo",
3503 offscreen_saved_color_texture_info_
.get(),
3506 texture_manager()->SetParameteri(
3507 "UpdateParentTextureInfo",
3509 offscreen_saved_color_texture_info_
.get(),
3512 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3514 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3517 void GLES2DecoderImpl::SetResizeCallback(
3518 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3519 resize_callback_
= callback
;
3522 Logger
* GLES2DecoderImpl::GetLogger() {
3526 void GLES2DecoderImpl::BeginDecoding() {
3527 gpu_tracer_
->BeginDecoding();
3528 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3529 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3530 (*cb_command_trace_category_
!= 0);
3533 void GLES2DecoderImpl::EndDecoding() {
3534 gpu_tracer_
->EndDecoding();
3537 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3538 return state_
.GetErrorState();
3541 void GLES2DecoderImpl::SetShaderCacheCallback(
3542 const ShaderCacheCallback
& callback
) {
3543 shader_cache_callback_
= callback
;
3546 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3547 const WaitSyncPointCallback
& callback
) {
3548 wait_sync_point_callback_
= callback
;
3551 AsyncPixelTransferManager
*
3552 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3553 return async_pixel_transfer_manager_
.get();
3556 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3557 async_pixel_transfer_manager_
.reset();
3560 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3561 AsyncPixelTransferManager
* manager
) {
3562 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3565 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3566 uint32
* service_texture_id
) {
3567 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3569 *service_texture_id
= texture_ref
->service_id();
3575 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3576 return texture_state_
.texture_upload_count
+
3577 async_pixel_transfer_manager_
->GetTextureUploadCount();
3580 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3581 return texture_state_
.total_texture_upload_time
+
3582 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3585 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3586 return total_processing_commands_time_
;
3589 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3590 total_processing_commands_time_
+= time
;
3593 void GLES2DecoderImpl::Destroy(bool have_context
) {
3597 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3599 // Unbind everything.
3600 state_
.vertex_attrib_manager
= NULL
;
3601 state_
.default_vertex_attrib_manager
= NULL
;
3602 state_
.texture_units
.clear();
3603 state_
.bound_array_buffer
= NULL
;
3604 state_
.current_queries
.clear();
3605 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3606 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3607 state_
.bound_renderbuffer
= NULL
;
3608 state_
.bound_valuebuffer
= NULL
;
3610 if (offscreen_saved_color_texture_info_
.get()) {
3611 DCHECK(offscreen_target_color_texture_
);
3612 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3613 offscreen_saved_color_texture_
->id());
3614 offscreen_saved_color_texture_
->Invalidate();
3615 offscreen_saved_color_texture_info_
= NULL
;
3618 if (copy_texture_CHROMIUM_
.get()) {
3619 copy_texture_CHROMIUM_
->Destroy();
3620 copy_texture_CHROMIUM_
.reset();
3623 clear_framebuffer_blit_
.reset();
3625 if (state_
.current_program
.get()) {
3626 program_manager()->UnuseProgram(shader_manager(),
3627 state_
.current_program
.get());
3630 if (attrib_0_buffer_id_
) {
3631 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3633 if (fixed_attrib_buffer_id_
) {
3634 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3637 if (validation_texture_
) {
3638 glDeleteTextures(1, &validation_texture_
);
3639 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3640 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3643 if (offscreen_target_frame_buffer_
.get())
3644 offscreen_target_frame_buffer_
->Destroy();
3645 if (offscreen_target_color_texture_
.get())
3646 offscreen_target_color_texture_
->Destroy();
3647 if (offscreen_target_color_render_buffer_
.get())
3648 offscreen_target_color_render_buffer_
->Destroy();
3649 if (offscreen_target_depth_render_buffer_
.get())
3650 offscreen_target_depth_render_buffer_
->Destroy();
3651 if (offscreen_target_stencil_render_buffer_
.get())
3652 offscreen_target_stencil_render_buffer_
->Destroy();
3653 if (offscreen_saved_frame_buffer_
.get())
3654 offscreen_saved_frame_buffer_
->Destroy();
3655 if (offscreen_saved_color_texture_
.get())
3656 offscreen_saved_color_texture_
->Destroy();
3657 if (offscreen_resolved_frame_buffer_
.get())
3658 offscreen_resolved_frame_buffer_
->Destroy();
3659 if (offscreen_resolved_color_texture_
.get())
3660 offscreen_resolved_color_texture_
->Destroy();
3662 if (offscreen_target_frame_buffer_
.get())
3663 offscreen_target_frame_buffer_
->Invalidate();
3664 if (offscreen_target_color_texture_
.get())
3665 offscreen_target_color_texture_
->Invalidate();
3666 if (offscreen_target_color_render_buffer_
.get())
3667 offscreen_target_color_render_buffer_
->Invalidate();
3668 if (offscreen_target_depth_render_buffer_
.get())
3669 offscreen_target_depth_render_buffer_
->Invalidate();
3670 if (offscreen_target_stencil_render_buffer_
.get())
3671 offscreen_target_stencil_render_buffer_
->Invalidate();
3672 if (offscreen_saved_frame_buffer_
.get())
3673 offscreen_saved_frame_buffer_
->Invalidate();
3674 if (offscreen_saved_color_texture_
.get())
3675 offscreen_saved_color_texture_
->Invalidate();
3676 if (offscreen_resolved_frame_buffer_
.get())
3677 offscreen_resolved_frame_buffer_
->Invalidate();
3678 if (offscreen_resolved_color_texture_
.get())
3679 offscreen_resolved_color_texture_
->Invalidate();
3682 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3683 // Otherwise, we can leak objects. http://crbug.com/258772.
3684 // state_.current_program must be reset before group_ is reset because
3685 // the later deletes the ProgramManager object that referred by
3686 // state_.current_program object.
3687 state_
.current_program
= NULL
;
3689 copy_texture_CHROMIUM_
.reset();
3690 clear_framebuffer_blit_
.reset();
3692 if (query_manager_
.get()) {
3693 query_manager_
->Destroy(have_context
);
3694 query_manager_
.reset();
3697 if (vertex_array_manager_
.get()) {
3698 vertex_array_manager_
->Destroy(have_context
);
3699 vertex_array_manager_
.reset();
3702 if (image_manager_
.get()) {
3703 image_manager_
->Destroy(have_context
);
3704 image_manager_
.reset();
3707 offscreen_target_frame_buffer_
.reset();
3708 offscreen_target_color_texture_
.reset();
3709 offscreen_target_color_render_buffer_
.reset();
3710 offscreen_target_depth_render_buffer_
.reset();
3711 offscreen_target_stencil_render_buffer_
.reset();
3712 offscreen_saved_frame_buffer_
.reset();
3713 offscreen_saved_color_texture_
.reset();
3714 offscreen_resolved_frame_buffer_
.reset();
3715 offscreen_resolved_color_texture_
.reset();
3717 // Need to release these before releasing |group_| which may own the
3718 // ShaderTranslatorCache.
3719 fragment_translator_
= NULL
;
3720 vertex_translator_
= NULL
;
3722 // Should destroy the transfer manager before the texture manager held
3723 // by the context group.
3724 async_pixel_transfer_manager_
.reset();
3727 framebuffer_manager()->RemoveObserver(this);
3728 group_
->Destroy(this, have_context
);
3732 if (context_
.get()) {
3733 context_
->ReleaseCurrent(NULL
);
3737 #if defined(OS_MACOSX)
3738 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3739 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3740 CFRelease(it
->second
);
3742 texture_to_io_surface_map_
.clear();
3746 void GLES2DecoderImpl::SetSurface(
3747 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3748 DCHECK(context_
->IsCurrent(NULL
));
3749 DCHECK(surface_
.get());
3751 RestoreCurrentFramebufferBindings();
3754 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3755 if (!offscreen_saved_color_texture_
.get()) {
3756 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3759 if (!offscreen_saved_color_texture_info_
.get()) {
3760 GLuint service_id
= offscreen_saved_color_texture_
->id();
3761 offscreen_saved_color_texture_info_
= TextureRef::Create(
3762 texture_manager(), 0, service_id
);
3763 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3765 UpdateParentTextureInfo();
3767 mailbox_manager()->ProduceTexture(
3768 mailbox
, offscreen_saved_color_texture_info_
->texture());
3771 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3772 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3773 if (!is_offscreen
) {
3774 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3775 << " with an onscreen framebuffer.";
3779 if (offscreen_size_
== size
)
3782 offscreen_size_
= size
;
3783 int w
= offscreen_size_
.width();
3784 int h
= offscreen_size_
.height();
3785 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3786 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3787 << "to allocate storage due to excessive dimensions.";
3791 // Reallocate the offscreen target buffers.
3792 DCHECK(offscreen_target_color_format_
);
3793 if (IsOffscreenBufferMultisampled()) {
3794 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3795 feature_info_
.get(),
3797 offscreen_target_color_format_
,
3798 offscreen_target_samples_
)) {
3799 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3800 << "to allocate storage for offscreen target color buffer.";
3804 if (!offscreen_target_color_texture_
->AllocateStorage(
3805 offscreen_size_
, offscreen_target_color_format_
, false)) {
3806 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3807 << "to allocate storage for offscreen target color texture.";
3811 if (offscreen_target_depth_format_
&&
3812 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3813 feature_info_
.get(),
3815 offscreen_target_depth_format_
,
3816 offscreen_target_samples_
)) {
3817 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3818 << "to allocate storage for offscreen target depth buffer.";
3821 if (offscreen_target_stencil_format_
&&
3822 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3823 feature_info_
.get(),
3825 offscreen_target_stencil_format_
,
3826 offscreen_target_samples_
)) {
3827 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3828 << "to allocate storage for offscreen target stencil buffer.";
3832 // Attach the offscreen target buffers to the target frame buffer.
3833 if (IsOffscreenBufferMultisampled()) {
3834 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3835 GL_COLOR_ATTACHMENT0
,
3836 offscreen_target_color_render_buffer_
.get());
3838 offscreen_target_frame_buffer_
->AttachRenderTexture(
3839 offscreen_target_color_texture_
.get());
3841 if (offscreen_target_depth_format_
) {
3842 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3843 GL_DEPTH_ATTACHMENT
,
3844 offscreen_target_depth_render_buffer_
.get());
3846 const bool packed_depth_stencil
=
3847 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3848 if (packed_depth_stencil
) {
3849 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3850 GL_STENCIL_ATTACHMENT
,
3851 offscreen_target_depth_render_buffer_
.get());
3852 } else if (offscreen_target_stencil_format_
) {
3853 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3854 GL_STENCIL_ATTACHMENT
,
3855 offscreen_target_stencil_render_buffer_
.get());
3858 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3859 GL_FRAMEBUFFER_COMPLETE
) {
3860 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3861 << "because offscreen FBO was incomplete.";
3865 // Clear the target frame buffer.
3867 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3868 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3869 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3870 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3872 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3873 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3875 state_
.SetDeviceDepthMask(GL_TRUE
);
3876 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3877 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3878 RestoreClearState();
3881 // Destroy the offscreen resolved framebuffers.
3882 if (offscreen_resolved_frame_buffer_
.get())
3883 offscreen_resolved_frame_buffer_
->Destroy();
3884 if (offscreen_resolved_color_texture_
.get())
3885 offscreen_resolved_color_texture_
->Destroy();
3886 offscreen_resolved_color_texture_
.reset();
3887 offscreen_resolved_frame_buffer_
.reset();
3892 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
3893 const void* cmd_data
) {
3894 const gles2::cmds::ResizeCHROMIUM
& c
=
3895 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
3896 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3897 return error::kDeferCommandUntilLater
;
3899 GLuint width
= static_cast<GLuint
>(c
.width
);
3900 GLuint height
= static_cast<GLuint
>(c
.height
);
3901 GLfloat scale_factor
= c
.scale_factor
;
3902 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3904 width
= std::max(1U, width
);
3905 height
= std::max(1U, height
);
3907 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3908 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3909 // Make sure that we are done drawing to the back buffer before resizing.
3912 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3914 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3915 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3916 << "ResizeOffscreenFrameBuffer failed.";
3917 return error::kLostContext
;
3921 if (!resize_callback_
.is_null()) {
3922 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3923 DCHECK(context_
->IsCurrent(surface_
.get()));
3924 if (!context_
->IsCurrent(surface_
.get())) {
3925 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3926 << "current after resize callback.";
3927 return error::kLostContext
;
3931 return error::kNoError
;
3934 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3935 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3936 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3938 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3941 // Decode a command, and call the corresponding GL functions.
3942 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3943 // of commands at once, and is now only used for tests that need to track
3944 // individual commands.
3945 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
3946 unsigned int arg_count
,
3947 const void* cmd_data
) {
3948 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
3951 // Decode multiple commands, and call the corresponding GL functions.
3952 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3953 // changed by a (malicious) client at any time, so if validation has to happen,
3954 // it should operate on a copy of them.
3955 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3956 // interest of performance in this critical execution loop.
3957 template <bool DebugImpl
>
3958 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
3961 int* entries_processed
) {
3962 commands_to_process_
= num_commands
;
3963 error::Error result
= error::kNoError
;
3964 const CommandBufferEntry
* cmd_data
=
3965 static_cast<const CommandBufferEntry
*>(buffer
);
3966 int process_pos
= 0;
3967 unsigned int command
= 0;
3969 while (process_pos
< num_entries
&& result
== error::kNoError
&&
3970 commands_to_process_
--) {
3971 const unsigned int size
= cmd_data
->value_header
.size
;
3972 command
= cmd_data
->value_header
.command
;
3975 result
= error::kInvalidSize
;
3979 if (static_cast<int>(size
) + process_pos
> num_entries
) {
3980 result
= error::kOutOfBounds
;
3985 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3986 GetCommandName(command
));
3988 if (log_commands()) {
3989 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
3990 << "cmd: " << GetCommandName(command
);
3994 const unsigned int arg_count
= size
- 1;
3995 unsigned int command_index
= command
- kStartPoint
- 1;
3996 if (command_index
< arraysize(command_info
)) {
3997 const CommandInfo
& info
= command_info
[command_index
];
3998 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3999 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4000 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4001 bool doing_gpu_trace
= false;
4002 if (DebugImpl
&& gpu_trace_commands_
) {
4003 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4004 doing_gpu_trace
= true;
4005 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4006 GetCommandName(command
),
4011 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4012 sizeof(CommandBufferEntry
); // NOLINT
4014 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4016 if (DebugImpl
&& doing_gpu_trace
)
4017 gpu_tracer_
->End(kTraceDecoder
);
4019 if (DebugImpl
&& debug()) {
4021 while ((error
= glGetError()) != GL_NO_ERROR
) {
4022 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4023 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4024 << " : " << GetCommandName(command
);
4025 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4029 result
= error::kInvalidArguments
;
4032 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4036 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4037 GetCommandName(command
));
4040 if (result
== error::kNoError
&&
4041 current_decoder_error_
!= error::kNoError
) {
4042 result
= current_decoder_error_
;
4043 current_decoder_error_
= error::kNoError
;
4046 if (result
!= error::kDeferCommandUntilLater
) {
4047 process_pos
+= size
;
4052 if (entries_processed
)
4053 *entries_processed
= process_pos
;
4055 if (error::IsError(result
)) {
4056 LOG(ERROR
) << "Error: " << result
<< " for Command "
4057 << GetCommandName(command
);
4063 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4066 int* entries_processed
) {
4067 if (gpu_debug_commands_
) {
4068 return DoCommandsImpl
<true>(
4069 num_commands
, buffer
, num_entries
, entries_processed
);
4071 return DoCommandsImpl
<false>(
4072 num_commands
, buffer
, num_entries
, entries_processed
);
4076 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4077 buffer_manager()->RemoveBuffer(client_id
);
4080 void GLES2DecoderImpl::DoFinish() {
4082 ProcessPendingReadPixels();
4083 ProcessPendingQueries(true);
4086 void GLES2DecoderImpl::DoFlush() {
4088 ProcessPendingQueries(false);
4091 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4092 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4093 if (texture_index
>= state_
.texture_units
.size()) {
4094 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4095 "glActiveTexture", texture_unit
, "texture_unit");
4098 state_
.active_texture_unit
= texture_index
;
4099 glActiveTexture(texture_unit
);
4102 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4103 Buffer
* buffer
= NULL
;
4104 GLuint service_id
= 0;
4105 if (client_id
!= 0) {
4106 buffer
= GetBuffer(client_id
);
4108 if (!group_
->bind_generates_resource()) {
4109 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4111 "id not generated by glGenBuffers");
4115 // It's a new id so make a buffer buffer for it.
4116 glGenBuffersARB(1, &service_id
);
4117 CreateBuffer(client_id
, service_id
);
4118 buffer
= GetBuffer(client_id
);
4121 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4123 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4125 GL_INVALID_OPERATION
,
4126 "glBindBuffer", "buffer bound to more than 1 target");
4129 service_id
= buffer
->service_id();
4132 case GL_ARRAY_BUFFER
:
4133 state_
.bound_array_buffer
= buffer
;
4135 case GL_ELEMENT_ARRAY_BUFFER
:
4136 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
4139 NOTREACHED(); // Validation should prevent us getting here.
4142 glBindBuffer(target
, service_id
);
4145 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4146 bool all_draw_buffers
) {
4147 Framebuffer
* framebuffer
=
4148 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4149 if (!all_draw_buffers
|| !framebuffer
) {
4150 return (GLES2Util::GetChannelsForFormat(
4151 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4153 return framebuffer
->HasAlphaMRT();
4156 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4157 Framebuffer
* framebuffer
=
4158 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4160 return framebuffer
->HasDepthAttachment();
4162 if (offscreen_target_frame_buffer_
.get()) {
4163 return offscreen_target_depth_format_
!= 0;
4165 return back_buffer_has_depth_
;
4168 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4169 Framebuffer
* framebuffer
=
4170 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4172 return framebuffer
->HasStencilAttachment();
4174 if (offscreen_target_frame_buffer_
.get()) {
4175 return offscreen_target_stencil_format_
!= 0 ||
4176 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4178 return back_buffer_has_stencil_
;
4181 void GLES2DecoderImpl::ApplyDirtyState() {
4182 if (framebuffer_state_
.clear_state_dirty
) {
4183 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4184 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4185 state_
.color_mask_green
,
4186 state_
.color_mask_blue
,
4187 state_
.color_mask_alpha
&& have_alpha
);
4189 bool have_depth
= BoundFramebufferHasDepthAttachment();
4190 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4192 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4193 state_
.SetDeviceStencilMaskSeparate(
4194 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4195 state_
.SetDeviceStencilMaskSeparate(
4196 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4198 state_
.SetDeviceCapabilityState(
4199 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4200 state_
.SetDeviceCapabilityState(
4201 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4202 framebuffer_state_
.clear_state_dirty
= false;
4206 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4207 return (offscreen_target_frame_buffer_
.get())
4208 ? offscreen_target_frame_buffer_
->id()
4209 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4212 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4213 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4214 "context", logger_
.GetLogPrefix());
4215 // Restore the Framebuffer first because of bugs in Intel drivers.
4216 // Intel drivers incorrectly clip the viewport settings to
4217 // the size of the current framebuffer object.
4218 RestoreFramebufferBindings();
4219 state_
.RestoreState(prev_state
);
4222 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4224 framebuffer_state_
.bound_draw_framebuffer
.get()
4225 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4226 : GetBackbufferServiceId();
4227 if (!features().chromium_framebuffer_multisample
) {
4228 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4230 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4231 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4232 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4233 : GetBackbufferServiceId();
4234 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4239 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4240 state_
.RestoreRenderbufferBindings();
4243 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4244 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4246 GLenum target
= texture
->target();
4247 glBindTexture(target
, service_id
);
4249 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4251 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4253 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4255 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4256 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4260 void GLES2DecoderImpl::ClearAllAttributes() const {
4261 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4263 if (feature_info_
->feature_flags().native_vertex_array_object
)
4264 glBindVertexArrayOES(0);
4266 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4267 if (i
!= 0) // Never disable attribute 0
4268 glDisableVertexAttribArray(i
);
4269 if(features().angle_instanced_arrays
)
4270 glVertexAttribDivisorANGLE(i
, 0);
4274 void GLES2DecoderImpl::RestoreAllAttributes() const {
4275 state_
.RestoreVertexAttribs();
4278 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4279 state_
.SetIgnoreCachedStateForTest(ignore
);
4282 void GLES2DecoderImpl::OnFboChanged() const {
4283 if (workarounds().restore_scissor_on_fbo_change
)
4284 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
4286 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4287 GLint bound_fbo_unsigned
= -1;
4288 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4289 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4290 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4291 surface_
->NotifyWasBound();
4295 // Called after the FBO is checked for completeness.
4296 void GLES2DecoderImpl::OnUseFramebuffer() const {
4297 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
4298 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
4299 // The driver forgets the correct scissor when modifying the FBO binding.
4300 glScissor(state_
.scissor_x
,
4302 state_
.scissor_width
,
4303 state_
.scissor_height
);
4305 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4306 // it's unclear how this bug works.
4311 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4312 Framebuffer
* framebuffer
= NULL
;
4313 GLuint service_id
= 0;
4314 if (client_id
!= 0) {
4315 framebuffer
= GetFramebuffer(client_id
);
4317 if (!group_
->bind_generates_resource()) {
4318 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4319 "glBindFramebuffer",
4320 "id not generated by glGenFramebuffers");
4324 // It's a new id so make a framebuffer framebuffer for it.
4325 glGenFramebuffersEXT(1, &service_id
);
4326 CreateFramebuffer(client_id
, service_id
);
4327 framebuffer
= GetFramebuffer(client_id
);
4329 service_id
= framebuffer
->service_id();
4331 framebuffer
->MarkAsValid();
4333 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4335 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4336 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4339 // vmiura: This looks like dup code
4340 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4341 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4344 framebuffer_state_
.clear_state_dirty
= true;
4346 // If we are rendering to the backbuffer get the FBO id for any simulated
4348 if (framebuffer
== NULL
) {
4349 service_id
= GetBackbufferServiceId();
4352 glBindFramebufferEXT(target
, service_id
);
4356 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4357 Renderbuffer
* renderbuffer
= NULL
;
4358 GLuint service_id
= 0;
4359 if (client_id
!= 0) {
4360 renderbuffer
= GetRenderbuffer(client_id
);
4361 if (!renderbuffer
) {
4362 if (!group_
->bind_generates_resource()) {
4363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4364 "glBindRenderbuffer",
4365 "id not generated by glGenRenderbuffers");
4369 // It's a new id so make a renderbuffer for it.
4370 glGenRenderbuffersEXT(1, &service_id
);
4371 CreateRenderbuffer(client_id
, service_id
);
4372 renderbuffer
= GetRenderbuffer(client_id
);
4374 service_id
= renderbuffer
->service_id();
4376 renderbuffer
->MarkAsValid();
4378 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4379 state_
.bound_renderbuffer
= renderbuffer
;
4380 state_
.bound_renderbuffer_valid
= true;
4381 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4384 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4385 TextureRef
* texture_ref
= NULL
;
4386 GLuint service_id
= 0;
4387 if (client_id
!= 0) {
4388 texture_ref
= GetTexture(client_id
);
4390 if (!group_
->bind_generates_resource()) {
4391 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4393 "id not generated by glGenTextures");
4397 // It's a new id so make a texture texture for it.
4398 glGenTextures(1, &service_id
);
4399 DCHECK_NE(0u, service_id
);
4400 CreateTexture(client_id
, service_id
);
4401 texture_ref
= GetTexture(client_id
);
4404 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4407 // Check the texture exists
4409 Texture
* texture
= texture_ref
->texture();
4410 // Check that we are not trying to bind it to a different target.
4411 if (texture
->target() != 0 && texture
->target() != target
) {
4412 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4414 "texture bound to more than 1 target.");
4417 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4418 if (texture
->target() == 0) {
4419 texture_manager()->SetTarget(texture_ref
, target
);
4421 glBindTexture(target
, texture
->service_id());
4423 glBindTexture(target
, 0);
4426 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4427 unit
.bind_target
= target
;
4430 unit
.bound_texture_2d
= texture_ref
;
4432 case GL_TEXTURE_CUBE_MAP
:
4433 unit
.bound_texture_cube_map
= texture_ref
;
4435 case GL_TEXTURE_EXTERNAL_OES
:
4436 unit
.bound_texture_external_oes
= texture_ref
;
4438 case GL_TEXTURE_RECTANGLE_ARB
:
4439 unit
.bound_texture_rectangle_arb
= texture_ref
;
4442 NOTREACHED(); // Validation should prevent us getting here.
4447 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4448 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4450 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4451 glDisableVertexAttribArray(index
);
4456 "glDisableVertexAttribArray", "index out of range");
4460 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4461 GLsizei numAttachments
,
4462 const GLenum
* attachments
) {
4463 Framebuffer
* framebuffer
=
4464 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4466 // Validates the attachments. If one of them fails
4467 // the whole command fails.
4468 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4470 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4472 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4473 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4474 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4479 // Marks each one of them as not cleared
4480 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4482 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4487 switch (attachments
[i
]) {
4489 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4492 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4493 case GL_STENCIL_EXT
:
4494 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4503 // If the default framebuffer is bound but we are still rendering to an
4504 // FBO, translate attachment names that refer to default framebuffer
4505 // channels to corresponding framebuffer attachments.
4506 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4507 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4508 GLenum attachment
= attachments
[i
];
4509 if (!framebuffer
&& GetBackbufferServiceId()) {
4510 switch (attachment
) {
4512 attachment
= GL_COLOR_ATTACHMENT0
;
4515 attachment
= GL_DEPTH_ATTACHMENT
;
4517 case GL_STENCIL_EXT
:
4518 attachment
= GL_STENCIL_ATTACHMENT
;
4525 translated_attachments
[i
] = attachment
;
4528 ScopedRenderTo
do_render(framebuffer
);
4529 if (feature_info_
->gl_version_info().is_es3
) {
4530 glInvalidateFramebuffer(
4531 target
, numAttachments
, translated_attachments
.get());
4533 glDiscardFramebufferEXT(
4534 target
, numAttachments
, translated_attachments
.get());
4538 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4539 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4540 glEnableVertexAttribArray(index
);
4543 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4547 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4548 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4551 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4553 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4557 if (target
== GL_TEXTURE_CUBE_MAP
) {
4558 for (int i
= 0; i
< 6; ++i
) {
4559 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4560 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4562 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4567 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4569 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4574 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4575 // Workaround for Mac driver bug. In the large scheme of things setting
4576 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4577 // hit so there's probably no need to make this conditional. The bug appears
4578 // to be that if the filtering mode is set to something that doesn't require
4579 // mipmaps for rendering, or is never set to something other than the default,
4580 // then glGenerateMipmap misbehaves.
4581 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4582 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4584 glGenerateMipmapEXT(target
);
4585 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4586 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4587 texture_ref
->texture()->min_filter());
4589 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4590 if (error
== GL_NO_ERROR
) {
4591 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4595 bool GLES2DecoderImpl::GetHelper(
4596 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4597 DCHECK(num_written
);
4598 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4600 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4602 // Return the GL implementation's preferred format and (see below type)
4603 // if we have the GL extension that exposes this. This allows the GPU
4604 // client to use the implementation's preferred format for glReadPixels
4605 // for optimisation.
4607 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4608 // case when requested on integer/floating point buffers but which is
4609 // acceptable on GLES2 and with the GL_OES_read_format extension.
4611 // Therefore if an error occurs we swallow the error and use the
4612 // internal implementation.
4614 if (context_
->HasExtension("GL_OES_read_format")) {
4615 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4617 glGetIntegerv(pname
, params
);
4618 if (glGetError() == GL_NO_ERROR
)
4621 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4622 GetBoundReadFrameBufferInternalFormat());
4625 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4628 if (context_
->HasExtension("GL_OES_read_format")) {
4629 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4631 glGetIntegerv(pname
, params
);
4632 if (glGetError() == GL_NO_ERROR
)
4635 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4636 GetBoundReadFrameBufferInternalFormat(),
4637 GetBoundReadFrameBufferTextureType());
4640 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4643 *params
= group_
->max_fragment_uniform_vectors();
4646 case GL_MAX_VARYING_VECTORS
:
4649 *params
= group_
->max_varying_vectors();
4652 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4655 *params
= group_
->max_vertex_uniform_vectors();
4661 case GL_MAX_VIEWPORT_DIMS
:
4662 if (offscreen_target_frame_buffer_
.get()) {
4665 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4666 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4671 case GL_MAX_SAMPLES
:
4674 params
[0] = renderbuffer_manager()->max_samples();
4677 case GL_MAX_RENDERBUFFER_SIZE
:
4680 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4683 case GL_MAX_TEXTURE_SIZE
:
4686 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4689 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4692 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4695 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4698 params
[0] = group_
->max_color_attachments();
4701 case GL_MAX_DRAW_BUFFERS_ARB
:
4704 params
[0] = group_
->max_draw_buffers();
4711 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4712 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4719 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4720 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4723 case GL_STENCIL_BITS
:
4727 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4728 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4731 case GL_COMPRESSED_TEXTURE_FORMATS
:
4732 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4734 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4735 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4739 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4742 *params
= validators_
->compressed_texture_format
.GetValues().size();
4745 case GL_NUM_SHADER_BINARY_FORMATS
:
4748 *params
= validators_
->shader_binary_format
.GetValues().size();
4751 case GL_SHADER_BINARY_FORMATS
:
4752 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4754 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4755 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4759 case GL_SHADER_COMPILER
:
4765 case GL_ARRAY_BUFFER_BINDING
:
4768 if (state_
.bound_array_buffer
.get()) {
4769 GLuint client_id
= 0;
4770 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4772 *params
= client_id
;
4778 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4781 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4782 GLuint client_id
= 0;
4783 buffer_manager()->GetClientId(
4784 state_
.vertex_attrib_manager
->element_array_buffer()->
4785 service_id(), &client_id
);
4786 *params
= client_id
;
4792 case GL_FRAMEBUFFER_BINDING
:
4793 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4796 Framebuffer
* framebuffer
=
4797 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4799 GLuint client_id
= 0;
4800 framebuffer_manager()->GetClientId(
4801 framebuffer
->service_id(), &client_id
);
4802 *params
= client_id
;
4808 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4811 Framebuffer
* framebuffer
=
4812 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4814 GLuint client_id
= 0;
4815 framebuffer_manager()->GetClientId(
4816 framebuffer
->service_id(), &client_id
);
4817 *params
= client_id
;
4823 case GL_RENDERBUFFER_BINDING
:
4826 Renderbuffer
* renderbuffer
=
4827 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4829 *params
= renderbuffer
->client_id();
4835 case GL_CURRENT_PROGRAM
:
4838 if (state_
.current_program
.get()) {
4839 GLuint client_id
= 0;
4840 program_manager()->GetClientId(
4841 state_
.current_program
->service_id(), &client_id
);
4842 *params
= client_id
;
4848 case GL_VERTEX_ARRAY_BINDING_OES
:
4851 if (state_
.vertex_attrib_manager
.get() !=
4852 state_
.default_vertex_attrib_manager
.get()) {
4853 GLuint client_id
= 0;
4854 vertex_array_manager_
->GetClientId(
4855 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4856 *params
= client_id
;
4862 case GL_TEXTURE_BINDING_2D
:
4865 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4866 if (unit
.bound_texture_2d
.get()) {
4867 *params
= unit
.bound_texture_2d
->client_id();
4873 case GL_TEXTURE_BINDING_CUBE_MAP
:
4876 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4877 if (unit
.bound_texture_cube_map
.get()) {
4878 *params
= unit
.bound_texture_cube_map
->client_id();
4884 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4887 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4888 if (unit
.bound_texture_external_oes
.get()) {
4889 *params
= unit
.bound_texture_external_oes
->client_id();
4895 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4898 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4899 if (unit
.bound_texture_rectangle_arb
.get()) {
4900 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4906 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4909 params
[0] = unpack_flip_y_
;
4912 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4915 params
[0] = unpack_premultiply_alpha_
;
4918 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4921 params
[0] = unpack_unpremultiply_alpha_
;
4924 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4927 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4931 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4932 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4935 Framebuffer
* framebuffer
=
4936 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4938 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4939 } else { // backbuffer
4940 if (pname
== GL_DRAW_BUFFER0_ARB
)
4941 params
[0] = group_
->draw_buffer();
4943 params
[0] = GL_NONE
;
4948 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4953 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4954 GLenum pname
, GLsizei
* num_values
) {
4955 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4958 return GetHelper(pname
, NULL
, num_values
);
4961 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4962 if (GL_MAX_SAMPLES
== pname
&&
4963 features().use_img_for_multisampled_render_to_texture
) {
4964 return GL_MAX_SAMPLES_IMG
;
4969 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4971 GLsizei num_written
= 0;
4972 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4973 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4974 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4975 GetHelper(pname
, values
.get(), &num_written
);
4977 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4978 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4981 pname
= AdjustGetPname(pname
);
4982 glGetBooleanv(pname
, params
);
4986 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4988 GLsizei num_written
= 0;
4989 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4990 if (GetHelper(pname
, NULL
, &num_written
)) {
4991 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4992 GetHelper(pname
, values
.get(), &num_written
);
4993 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4994 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4997 pname
= AdjustGetPname(pname
);
4998 glGetFloatv(pname
, params
);
5003 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5005 GLsizei num_written
;
5006 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5007 !GetHelper(pname
, params
, &num_written
)) {
5008 pname
= AdjustGetPname(pname
);
5009 glGetIntegerv(pname
, params
);
5013 void GLES2DecoderImpl::DoGetProgramiv(
5014 GLuint program_id
, GLenum pname
, GLint
* params
) {
5015 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5019 program
->GetProgramiv(pname
, params
);
5022 void GLES2DecoderImpl::DoGetBufferParameteriv(
5023 GLenum target
, GLenum pname
, GLint
* params
) {
5024 // Just delegate it. Some validation is actually done before this.
5025 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5026 &state_
, target
, pname
, params
);
5029 void GLES2DecoderImpl::DoBindAttribLocation(
5030 GLuint program_id
, GLuint index
, const char* name
) {
5031 if (!StringIsValidForGLES(name
)) {
5033 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5036 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5038 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5041 if (index
>= group_
->max_vertex_attribs()) {
5043 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5046 Program
* program
= GetProgramInfoNotShader(
5047 program_id
, "glBindAttribLocation");
5051 // At this point, the program's shaders may not be translated yet,
5052 // therefore, we may not find the hashed attribute name.
5053 // glBindAttribLocation call with original name is useless.
5054 // So instead, we should simply cache the binding, and then call
5055 // Program::ExecuteBindAttribLocationCalls() right before link.
5056 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5057 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5058 glBindAttribLocation(program
->service_id(), index
, name
);
5061 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5062 uint32 immediate_data_size
,
5063 const void* cmd_data
) {
5064 const gles2::cmds::BindAttribLocationBucket
& c
=
5065 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5066 GLuint program
= static_cast<GLuint
>(c
.program
);
5067 GLuint index
= static_cast<GLuint
>(c
.index
);
5068 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5069 if (!bucket
|| bucket
->size() == 0) {
5070 return error::kInvalidArguments
;
5072 std::string name_str
;
5073 if (!bucket
->GetAsString(&name_str
)) {
5074 return error::kInvalidArguments
;
5076 DoBindAttribLocation(program
, index
, name_str
.c_str());
5077 return error::kNoError
;
5080 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5081 GLuint program_id
, GLint location
, const char* name
) {
5082 if (!StringIsValidForGLES(name
)) {
5085 "glBindUniformLocationCHROMIUM", "Invalid character");
5088 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5090 GL_INVALID_OPERATION
,
5091 "glBindUniformLocationCHROMIUM", "reserved prefix");
5094 if (location
< 0 || static_cast<uint32
>(location
) >=
5095 (group_
->max_fragment_uniform_vectors() +
5096 group_
->max_vertex_uniform_vectors()) * 4) {
5099 "glBindUniformLocationCHROMIUM", "location out of range");
5102 Program
* program
= GetProgramInfoNotShader(
5103 program_id
, "glBindUniformLocationCHROMIUM");
5107 if (!program
->SetUniformLocationBinding(name
, location
)) {
5110 "glBindUniformLocationCHROMIUM", "location out of range");
5114 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5115 uint32 immediate_data_size
,
5116 const void* cmd_data
) {
5117 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5118 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5120 GLuint program
= static_cast<GLuint
>(c
.program
);
5121 GLint location
= static_cast<GLint
>(c
.location
);
5122 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5123 if (!bucket
|| bucket
->size() == 0) {
5124 return error::kInvalidArguments
;
5126 std::string name_str
;
5127 if (!bucket
->GetAsString(&name_str
)) {
5128 return error::kInvalidArguments
;
5130 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5131 return error::kNoError
;
5134 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5135 const void* cmd_data
) {
5136 const gles2::cmds::DeleteShader
& c
=
5137 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5138 GLuint client_id
= c
.shader
;
5140 Shader
* shader
= GetShader(client_id
);
5142 if (!shader
->IsDeleted()) {
5143 shader_manager()->Delete(shader
);
5146 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5149 return error::kNoError
;
5152 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5153 const void* cmd_data
) {
5154 const gles2::cmds::DeleteProgram
& c
=
5155 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5156 GLuint client_id
= c
.program
;
5158 Program
* program
= GetProgram(client_id
);
5160 if (!program
->IsDeleted()) {
5161 program_manager()->MarkAsDeleted(shader_manager(), program
);
5165 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5168 return error::kNoError
;
5171 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5172 DCHECK(!ShouldDeferDraws());
5173 if (CheckBoundFramebuffersValid("glClear")) {
5175 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5176 if (workarounds().gl_clear_broken
) {
5177 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5179 if (!BoundFramebufferHasDepthAttachment())
5180 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5181 if (!BoundFramebufferHasStencilAttachment())
5182 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5183 clear_framebuffer_blit_
->ClearFramebuffer(
5184 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5185 state_
.color_clear_green
, state_
.color_clear_blue
,
5186 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5187 return error::kNoError
;
5191 return error::kNoError
;
5194 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5195 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5196 GLuint client_renderbuffer_id
) {
5197 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5200 GL_INVALID_OPERATION
,
5201 "glFramebufferRenderbuffer", "no framebuffer bound");
5204 GLuint service_id
= 0;
5205 Renderbuffer
* renderbuffer
= NULL
;
5206 if (client_renderbuffer_id
) {
5207 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5208 if (!renderbuffer
) {
5210 GL_INVALID_OPERATION
,
5211 "glFramebufferRenderbuffer", "unknown renderbuffer");
5214 service_id
= renderbuffer
->service_id();
5216 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5217 glFramebufferRenderbufferEXT(
5218 target
, attachment
, renderbuffertarget
, service_id
);
5219 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5220 if (error
== GL_NO_ERROR
) {
5221 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5223 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5224 framebuffer_state_
.clear_state_dirty
= true;
5229 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5230 if (SetCapabilityState(cap
, false)) {
5235 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5236 if (SetCapabilityState(cap
, true)) {
5241 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5242 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5243 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5244 glDepthRange(znear
, zfar
);
5247 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5248 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5249 state_
.sample_coverage_invert
= (invert
!= 0);
5250 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5253 // Assumes framebuffer is complete.
5254 void GLES2DecoderImpl::ClearUnclearedAttachments(
5255 GLenum target
, Framebuffer
* framebuffer
) {
5256 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5257 // bind this to the DRAW point, clear then bind back to READ
5258 // TODO(gman): I don't think there is any guarantee that an FBO that
5259 // is complete on the READ attachment will be complete as a DRAW
5261 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5262 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5264 GLbitfield clear_bits
= 0;
5265 if (framebuffer
->HasUnclearedColorAttachments()) {
5268 (GLES2Util::GetChannelsForFormat(
5269 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5271 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5272 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5273 if (feature_info_
->feature_flags().ext_draw_buffers
)
5274 framebuffer
->PrepareDrawBuffersForClear();
5277 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5278 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5280 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5281 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5282 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5285 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5286 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5288 state_
.SetDeviceDepthMask(GL_TRUE
);
5289 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5292 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5293 glClear(clear_bits
);
5295 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5296 feature_info_
->feature_flags().ext_draw_buffers
)
5297 framebuffer
->RestoreDrawBuffersAfterClear();
5299 framebuffer_manager()->MarkAttachmentsAsCleared(
5300 framebuffer
, renderbuffer_manager(), texture_manager());
5302 RestoreClearState();
5304 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5305 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5306 Framebuffer
* draw_framebuffer
=
5307 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5308 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5309 GetBackbufferServiceId();
5310 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5314 void GLES2DecoderImpl::RestoreClearState() {
5315 framebuffer_state_
.clear_state_dirty
= true;
5317 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5318 state_
.color_clear_alpha
);
5319 glClearStencil(state_
.stencil_clear
);
5320 glClearDepth(state_
.depth_clear
);
5321 if (state_
.enable_flags
.scissor_test
) {
5322 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5326 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5327 Framebuffer
* framebuffer
=
5328 GetFramebufferInfoForTarget(target
);
5330 return GL_FRAMEBUFFER_COMPLETE
;
5332 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5333 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5334 return completeness
;
5336 return framebuffer
->GetStatus(texture_manager(), target
);
5339 void GLES2DecoderImpl::DoFramebufferTexture2D(
5340 GLenum target
, GLenum attachment
, GLenum textarget
,
5341 GLuint client_texture_id
, GLint level
) {
5342 DoFramebufferTexture2DCommon(
5343 "glFramebufferTexture2D", target
, attachment
,
5344 textarget
, client_texture_id
, level
, 0);
5347 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5348 GLenum target
, GLenum attachment
, GLenum textarget
,
5349 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5350 DoFramebufferTexture2DCommon(
5351 "glFramebufferTexture2DMultisample", target
, attachment
,
5352 textarget
, client_texture_id
, level
, samples
);
5355 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5356 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5357 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5358 if (samples
> renderbuffer_manager()->max_samples()) {
5361 "glFramebufferTexture2DMultisample", "samples too large");
5364 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5367 GL_INVALID_OPERATION
,
5368 name
, "no framebuffer bound.");
5371 GLuint service_id
= 0;
5372 TextureRef
* texture_ref
= NULL
;
5373 if (client_texture_id
) {
5374 texture_ref
= GetTexture(client_texture_id
);
5377 GL_INVALID_OPERATION
,
5378 name
, "unknown texture_ref");
5381 service_id
= texture_ref
->service_id();
5384 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5387 name
, "level out of range");
5392 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5394 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5396 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5398 if (features().use_img_for_multisampled_render_to_texture
) {
5399 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5400 service_id
, level
, samples
);
5402 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5403 service_id
, level
, samples
);
5406 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5407 if (error
== GL_NO_ERROR
) {
5408 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5411 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5412 framebuffer_state_
.clear_state_dirty
= true;
5416 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5421 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5422 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5423 GLint level
, GLint layer
) {
5424 // TODO(zmo): Unsafe ES3 API, missing states update.
5425 GLuint service_id
= 0;
5426 TextureRef
* texture_ref
= NULL
;
5427 if (client_texture_id
) {
5428 texture_ref
= GetTexture(client_texture_id
);
5431 GL_INVALID_OPERATION
,
5432 "glFramebufferTextureLayer", "unknown texture_ref");
5435 service_id
= texture_ref
->service_id();
5437 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5440 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5441 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5442 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5445 GL_INVALID_OPERATION
,
5446 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5449 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5450 const Framebuffer::Attachment
* attachment_object
=
5451 framebuffer
->GetAttachment(attachment
);
5452 *params
= attachment_object
? attachment_object
->object_name() : 0;
5454 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5455 features().use_img_for_multisampled_render_to_texture
) {
5456 pname
= GL_TEXTURE_SAMPLES_IMG
;
5458 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5462 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5463 GLenum target
, GLenum pname
, GLint
* params
) {
5464 Renderbuffer
* renderbuffer
=
5465 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5466 if (!renderbuffer
) {
5468 GL_INVALID_OPERATION
,
5469 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5473 EnsureRenderbufferBound();
5475 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5476 *params
= renderbuffer
->internal_format();
5478 case GL_RENDERBUFFER_WIDTH
:
5479 *params
= renderbuffer
->width();
5481 case GL_RENDERBUFFER_HEIGHT
:
5482 *params
= renderbuffer
->height();
5484 case GL_RENDERBUFFER_SAMPLES_EXT
:
5485 if (features().use_img_for_multisampled_render_to_texture
) {
5486 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5489 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5493 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5498 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5499 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5500 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5501 GLbitfield mask
, GLenum filter
) {
5502 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5504 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5508 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5509 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5510 BlitFramebufferHelper(
5511 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5512 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5513 state_
.enable_flags
.scissor_test
);
5516 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5517 if (!state_
.bound_renderbuffer_valid
) {
5518 state_
.bound_renderbuffer_valid
= true;
5519 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5520 state_
.bound_renderbuffer
.get()
5521 ? state_
.bound_renderbuffer
->service_id()
5526 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5527 const FeatureInfo
* feature_info
,
5530 GLenum internal_format
,
5533 // TODO(sievers): This could be resolved at the GL binding level, but the
5534 // binding process is currently a bit too 'brute force'.
5535 if (feature_info
->gl_version_info().is_angle
) {
5536 glRenderbufferStorageMultisampleANGLE(
5537 target
, samples
, internal_format
, width
, height
);
5538 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5539 glRenderbufferStorageMultisample(
5540 target
, samples
, internal_format
, width
, height
);
5542 glRenderbufferStorageMultisampleEXT(
5543 target
, samples
, internal_format
, width
, height
);
5547 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5557 // TODO(sievers): This could be resolved at the GL binding level, but the
5558 // binding process is currently a bit too 'brute force'.
5559 if (feature_info_
->gl_version_info().is_angle
) {
5560 glBlitFramebufferANGLE(
5561 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5562 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5564 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5566 glBlitFramebufferEXT(
5567 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5571 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5573 GLenum internalformat
,
5576 if (samples
> renderbuffer_manager()->max_samples()) {
5579 "glRenderbufferStorageMultisample", "samples too large");
5583 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5584 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5587 "glRenderbufferStorageMultisample", "dimensions too large");
5591 uint32 estimated_size
= 0;
5592 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5593 width
, height
, samples
, internalformat
, &estimated_size
)) {
5596 "glRenderbufferStorageMultisample", "dimensions too large");
5600 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5603 "glRenderbufferStorageMultisample", "out of memory");
5610 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5611 GLenum target
, GLsizei samples
, GLenum internalformat
,
5612 GLsizei width
, GLsizei height
) {
5613 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5614 if (!renderbuffer
) {
5615 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5616 "glRenderbufferStorageMultisampleCHROMIUM",
5617 "no renderbuffer bound");
5621 if (!ValidateRenderbufferStorageMultisample(
5622 samples
, internalformat
, width
, height
)) {
5626 EnsureRenderbufferBound();
5627 GLenum impl_format
=
5628 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5630 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5631 "glRenderbufferStorageMultisampleCHROMIUM");
5632 RenderbufferStorageMultisampleHelper(
5633 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5635 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5636 if (error
== GL_NO_ERROR
) {
5638 if (workarounds().validate_multisample_buffer_allocation
) {
5639 if (!VerifyMultisampleRenderbufferIntegrity(
5640 renderbuffer
->service_id(), impl_format
)) {
5643 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5648 // TODO(gman): If renderbuffers tracked which framebuffers they were
5649 // attached to we could just mark those framebuffers as not complete.
5650 framebuffer_manager()->IncFramebufferStateChangeCount();
5651 renderbuffer_manager()->SetInfo(
5652 renderbuffer
, samples
, internalformat
, width
, height
);
5656 // This is the handler for multisampled_render_to_texture extensions.
5657 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5658 GLenum target
, GLsizei samples
, GLenum internalformat
,
5659 GLsizei width
, GLsizei height
) {
5660 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5661 if (!renderbuffer
) {
5662 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5663 "glRenderbufferStorageMultisampleEXT",
5664 "no renderbuffer bound");
5668 if (!ValidateRenderbufferStorageMultisample(
5669 samples
, internalformat
, width
, height
)) {
5673 EnsureRenderbufferBound();
5674 GLenum impl_format
=
5675 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5677 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5678 if (features().use_img_for_multisampled_render_to_texture
) {
5679 glRenderbufferStorageMultisampleIMG(
5680 target
, samples
, impl_format
, width
, height
);
5682 glRenderbufferStorageMultisampleEXT(
5683 target
, samples
, impl_format
, width
, height
);
5685 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5686 if (error
== GL_NO_ERROR
) {
5687 // TODO(gman): If renderbuffers tracked which framebuffers they were
5688 // attached to we could just mark those framebuffers as not complete.
5689 framebuffer_manager()->IncFramebufferStateChangeCount();
5690 renderbuffer_manager()->SetInfo(
5691 renderbuffer
, samples
, internalformat
, width
, height
);
5695 // This function validates the allocation of a multisampled renderbuffer
5696 // by clearing it to a key color, blitting the contents to a texture, and
5697 // reading back the color to ensure it matches the key.
5698 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5699 GLuint renderbuffer
, GLenum format
) {
5701 // Only validate color buffers.
5702 // These formats have been selected because they are very common or are known
5703 // to be used by the WebGL backbuffer. If problems are observed with other
5704 // color formats they can be added here.
5715 GLint draw_framebuffer
, read_framebuffer
;
5717 // Cache framebuffer and texture bindings.
5718 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5719 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5721 if (!validation_texture_
) {
5722 GLint bound_texture
;
5723 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5725 // Create additional resources needed for the verification.
5726 glGenTextures(1, &validation_texture_
);
5727 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5728 glGenFramebuffersEXT(1, &validation_fbo_
);
5730 // Texture only needs to be 1x1.
5731 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5732 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5733 GL_UNSIGNED_BYTE
, NULL
);
5735 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5736 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5737 GL_TEXTURE_2D
, validation_texture_
, 0);
5739 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5742 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5743 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5744 GL_RENDERBUFFER
, renderbuffer
);
5746 // Cache current state and reset it to the values we require.
5747 GLboolean scissor_enabled
= false;
5748 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5749 if (scissor_enabled
)
5750 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5752 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5753 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5754 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5756 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5757 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5758 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5760 // Clear the buffer to the desired key color.
5761 glClear(GL_COLOR_BUFFER_BIT
);
5763 // Blit from the multisample buffer to a standard texture.
5764 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5765 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5767 BlitFramebufferHelper(
5768 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5770 // Read a pixel from the buffer.
5771 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5773 unsigned char pixel
[3] = {0, 0, 0};
5774 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5776 // Detach the renderbuffer.
5777 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5778 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5779 GL_RENDERBUFFER
, 0);
5781 // Restore cached state.
5782 if (scissor_enabled
)
5783 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5785 state_
.SetDeviceColorMask(
5786 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5787 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5788 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5789 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5791 // Return true if the pixel matched the desired key color.
5792 return (pixel
[0] == 0xFF &&
5797 void GLES2DecoderImpl::DoRenderbufferStorage(
5798 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5799 Renderbuffer
* renderbuffer
=
5800 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5801 if (!renderbuffer
) {
5803 GL_INVALID_OPERATION
,
5804 "glRenderbufferStorage", "no renderbuffer bound");
5808 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5809 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5811 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5815 uint32 estimated_size
= 0;
5816 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5817 width
, height
, 1, internalformat
, &estimated_size
)) {
5819 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5823 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5825 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5829 EnsureRenderbufferBound();
5830 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5831 glRenderbufferStorageEXT(
5833 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5837 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5838 if (error
== GL_NO_ERROR
) {
5839 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5840 // we could just mark those framebuffers as not complete.
5841 framebuffer_manager()->IncFramebufferStateChangeCount();
5842 renderbuffer_manager()->SetInfo(
5843 renderbuffer
, 1, internalformat
, width
, height
);
5847 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5848 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5849 Program
* program
= GetProgramInfoNotShader(
5850 program_id
, "glLinkProgram");
5855 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5856 if (program
->Link(shader_manager(),
5857 workarounds().count_all_in_varyings_packing
?
5858 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5859 shader_cache_callback_
)) {
5860 if (program
== state_
.current_program
.get()) {
5861 if (workarounds().use_current_program_after_successful_link
)
5862 glUseProgram(program
->service_id());
5863 if (workarounds().clear_uniforms_before_first_program_use
)
5864 program_manager()->ClearUniforms(program
);
5868 // LinkProgram can be very slow. Exit command processing to allow for
5869 // context preemption and GPU watchdog checks.
5870 ExitCommandProcessingEarly();
5873 void GLES2DecoderImpl::DoSamplerParameterfv(
5874 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
5876 glSamplerParameterf(sampler
, pname
, params
[0]);
5879 void GLES2DecoderImpl::DoSamplerParameteriv(
5880 GLuint sampler
, GLenum pname
, const GLint
* params
) {
5882 glSamplerParameteri(sampler
, pname
, params
[0]);
5885 void GLES2DecoderImpl::DoTexParameterf(
5886 GLenum target
, GLenum pname
, GLfloat param
) {
5887 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5890 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5894 texture_manager()->SetParameterf(
5895 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5898 void GLES2DecoderImpl::DoTexParameteri(
5899 GLenum target
, GLenum pname
, GLint param
) {
5900 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5903 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5907 texture_manager()->SetParameteri(
5908 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5911 void GLES2DecoderImpl::DoTexParameterfv(
5912 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5913 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5916 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5920 texture_manager()->SetParameterf(
5921 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5924 void GLES2DecoderImpl::DoTexParameteriv(
5925 GLenum target
, GLenum pname
, const GLint
* params
) {
5926 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5930 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5934 texture_manager()->SetParameteri(
5935 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5938 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
5939 if (!state_
.bound_valuebuffer
.get()) {
5940 // There is no valuebuffer bound
5941 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5942 "no valuebuffer in use");
5948 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
5949 GLenum subscription
,
5950 const char* function_name
) {
5951 if (!CheckCurrentValuebuffer(function_name
)) {
5954 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
5955 // The valuebuffer is not subscribed to the target
5956 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5957 "valuebuffer is not subscribed");
5963 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
5964 GLenum subscription
,
5965 const char* function_name
) {
5966 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
5969 GLint real_location
= -1;
5970 GLint array_index
= -1;
5971 const Program::UniformInfo
* info
=
5972 state_
.current_program
->GetUniformInfoByFakeLocation(
5973 location
, &real_location
, &array_index
);
5975 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
5978 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
5979 info
->accepts_api_type
) == 0) {
5980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5981 "wrong type for subscription");
5987 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5988 if (!state_
.current_program
.get()) {
5989 // The program does not exist.
5991 GL_INVALID_OPERATION
, function_name
, "no program in use");
5994 if (!state_
.current_program
->InUse()) {
5996 GL_INVALID_OPERATION
, function_name
, "program not linked");
6002 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6003 GLint location
, const char* function_name
) {
6004 if (!CheckCurrentProgram(function_name
)) {
6007 return location
!= -1;
6010 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6011 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6014 const Framebuffer::Attachment
* attachment
=
6015 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6019 DCHECK(state_
.current_program
.get());
6020 const Program::SamplerIndices
& sampler_indices
=
6021 state_
.current_program
->sampler_indices();
6022 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6023 const Program::UniformInfo
* uniform_info
=
6024 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6025 DCHECK(uniform_info
);
6026 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6028 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6029 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6030 if (texture_unit_index
>= state_
.texture_units
.size())
6032 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6033 TextureRef
* texture_ref
=
6034 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6035 if (attachment
->IsTexture(texture_ref
))
6042 bool GLES2DecoderImpl::CheckUniformForApiType(
6043 const Program::UniformInfo
* info
,
6044 const char* function_name
,
6045 Program::UniformApiType api_type
) {
6047 if ((api_type
& info
->accepts_api_type
) == 0) {
6048 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6049 "wrong uniform function for type");
6055 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6056 GLint fake_location
,
6057 const char* function_name
,
6058 Program::UniformApiType api_type
,
6059 GLint
* real_location
,
6064 DCHECK(real_location
);
6066 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6069 GLint array_index
= -1;
6070 const Program::UniformInfo
* info
=
6071 state_
.current_program
->GetUniformInfoByFakeLocation(
6072 fake_location
, real_location
, &array_index
);
6075 GL_INVALID_OPERATION
, function_name
, "unknown location");
6078 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6081 if (*count
> 1 && !info
->is_array
) {
6083 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6086 *count
= std::min(info
->size
- array_index
, *count
);
6094 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6097 GLint real_location
= -1;
6098 if (!PrepForSetUniformByLocation(fake_location
,
6100 Program::kUniform1i
,
6106 if (!state_
.current_program
->SetSamplers(
6107 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6109 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6112 glUniform1i(real_location
, v0
);
6115 void GLES2DecoderImpl::DoUniform1iv(
6116 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6118 GLint real_location
= -1;
6119 if (!PrepForSetUniformByLocation(fake_location
,
6121 Program::kUniform1i
,
6127 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6128 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6129 if (!state_
.current_program
->SetSamplers(
6130 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6132 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6136 glUniform1iv(real_location
, count
, value
);
6139 void GLES2DecoderImpl::DoUniform1fv(
6140 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6142 GLint real_location
= -1;
6143 if (!PrepForSetUniformByLocation(fake_location
,
6145 Program::kUniform1f
,
6151 if (type
== GL_BOOL
) {
6152 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6153 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6154 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6156 DoUniform1iv(real_location
, count
, temp
.get());
6158 glUniform1fv(real_location
, count
, value
);
6162 void GLES2DecoderImpl::DoUniform2fv(
6163 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6165 GLint real_location
= -1;
6166 if (!PrepForSetUniformByLocation(fake_location
,
6168 Program::kUniform2f
,
6174 if (type
== GL_BOOL_VEC2
) {
6175 GLsizei num_values
= count
* 2;
6176 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6177 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6178 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6180 glUniform2iv(real_location
, count
, temp
.get());
6182 glUniform2fv(real_location
, count
, value
);
6186 void GLES2DecoderImpl::DoUniform3fv(
6187 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6189 GLint real_location
= -1;
6190 if (!PrepForSetUniformByLocation(fake_location
,
6192 Program::kUniform3f
,
6198 if (type
== GL_BOOL_VEC3
) {
6199 GLsizei num_values
= count
* 3;
6200 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6201 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6202 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6204 glUniform3iv(real_location
, count
, temp
.get());
6206 glUniform3fv(real_location
, count
, value
);
6210 void GLES2DecoderImpl::DoUniform4fv(
6211 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6213 GLint real_location
= -1;
6214 if (!PrepForSetUniformByLocation(fake_location
,
6216 Program::kUniform4f
,
6222 if (type
== GL_BOOL_VEC4
) {
6223 GLsizei num_values
= count
* 4;
6224 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6225 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6226 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6228 glUniform4iv(real_location
, count
, temp
.get());
6230 glUniform4fv(real_location
, count
, value
);
6234 void GLES2DecoderImpl::DoUniform2iv(
6235 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6237 GLint real_location
= -1;
6238 if (!PrepForSetUniformByLocation(fake_location
,
6240 Program::kUniform2i
,
6246 glUniform2iv(real_location
, count
, value
);
6249 void GLES2DecoderImpl::DoUniform3iv(
6250 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6252 GLint real_location
= -1;
6253 if (!PrepForSetUniformByLocation(fake_location
,
6255 Program::kUniform3i
,
6261 glUniform3iv(real_location
, count
, value
);
6264 void GLES2DecoderImpl::DoUniform4iv(
6265 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6267 GLint real_location
= -1;
6268 if (!PrepForSetUniformByLocation(fake_location
,
6270 Program::kUniform4i
,
6276 glUniform4iv(real_location
, count
, value
);
6279 void GLES2DecoderImpl::DoUniformMatrix2fv(
6280 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6281 const GLfloat
* value
) {
6283 GLint real_location
= -1;
6284 if (!PrepForSetUniformByLocation(fake_location
,
6285 "glUniformMatrix2fv",
6286 Program::kUniformMatrix2f
,
6292 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6295 void GLES2DecoderImpl::DoUniformMatrix3fv(
6296 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6297 const GLfloat
* value
) {
6299 GLint real_location
= -1;
6300 if (!PrepForSetUniformByLocation(fake_location
,
6301 "glUniformMatrix3fv",
6302 Program::kUniformMatrix3f
,
6308 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6311 void GLES2DecoderImpl::DoUniformMatrix4fv(
6312 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6313 const GLfloat
* value
) {
6315 GLint real_location
= -1;
6316 if (!PrepForSetUniformByLocation(fake_location
,
6317 "glUniformMatrix4fv",
6318 Program::kUniformMatrix4f
,
6324 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6327 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6328 GLuint service_id
= 0;
6329 Program
* program
= NULL
;
6331 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6335 if (!program
->IsValid()) {
6336 // Program was not linked successfully. (ie, glLinkProgram)
6338 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6341 service_id
= program
->service_id();
6343 if (state_
.current_program
.get()) {
6344 program_manager()->UnuseProgram(shader_manager(),
6345 state_
.current_program
.get());
6347 state_
.current_program
= program
;
6348 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6349 glUseProgram(service_id
);
6350 if (state_
.current_program
.get()) {
6351 program_manager()->UseProgram(state_
.current_program
.get());
6352 if (workarounds().clear_uniforms_before_first_program_use
)
6353 program_manager()->ClearUniforms(program
);
6357 void GLES2DecoderImpl::RenderWarning(
6358 const char* filename
, int line
, const std::string
& msg
) {
6359 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6362 void GLES2DecoderImpl::PerformanceWarning(
6363 const char* filename
, int line
, const std::string
& msg
) {
6364 logger_
.LogMessage(filename
, line
,
6365 std::string("PERFORMANCE WARNING: ") + msg
);
6368 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6369 Texture
* texture
, GLenum textarget
) {
6370 // Image is already in use if texture is attached to a framebuffer.
6371 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6372 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6374 ScopedGLErrorSuppressor
suppressor(
6375 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6377 glBindTexture(textarget
, texture
->service_id());
6378 image
->WillUseTexImage();
6379 RestoreCurrentTextureBindings(&state_
, textarget
);
6384 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6385 Texture
* texture
, GLenum textarget
) {
6386 // Image is still in use if texture is attached to a framebuffer.
6387 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6388 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6390 ScopedGLErrorSuppressor
suppressor(
6391 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6393 glBindTexture(textarget
, texture
->service_id());
6394 image
->DidUseTexImage();
6395 RestoreCurrentTextureBindings(&state_
, textarget
);
6400 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6401 DCHECK(state_
.current_program
.get());
6402 if (!texture_manager()->HaveUnrenderableTextures() &&
6403 !texture_manager()->HaveImages()) {
6407 bool textures_set
= false;
6408 const Program::SamplerIndices
& sampler_indices
=
6409 state_
.current_program
->sampler_indices();
6410 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6411 const Program::UniformInfo
* uniform_info
=
6412 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6413 DCHECK(uniform_info
);
6414 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6415 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6416 if (texture_unit_index
< state_
.texture_units
.size()) {
6417 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6418 TextureRef
* texture_ref
=
6419 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6420 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6421 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6422 textures_set
= true;
6423 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6426 texture_manager()->black_texture_id(uniform_info
->type
));
6428 LOCAL_RENDER_WARNING(
6429 std::string("there is no texture bound to the unit ") +
6430 base::IntToString(texture_unit_index
));
6432 LOCAL_RENDER_WARNING(
6433 std::string("texture bound to texture unit ") +
6434 base::IntToString(texture_unit_index
) +
6435 " is not renderable. It maybe non-power-of-2 and have"
6436 " incompatible texture filtering.");
6441 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6442 Texture
* texture
= texture_ref
->texture();
6443 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6444 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6445 ScopedGLErrorSuppressor
suppressor(
6446 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6447 textures_set
= true;
6448 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6449 image
->WillUseTexImage();
6454 // else: should this be an error?
6457 return !textures_set
;
6460 void GLES2DecoderImpl::RestoreStateForTextures() {
6461 DCHECK(state_
.current_program
.get());
6462 const Program::SamplerIndices
& sampler_indices
=
6463 state_
.current_program
->sampler_indices();
6464 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6465 const Program::UniformInfo
* uniform_info
=
6466 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6467 DCHECK(uniform_info
);
6468 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6469 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6470 if (texture_unit_index
< state_
.texture_units
.size()) {
6471 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6472 TextureRef
* texture_ref
=
6473 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6474 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6475 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6476 // Get the texture_ref info that was previously bound here.
6477 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6478 ? texture_unit
.bound_texture_2d
.get()
6479 : texture_unit
.bound_texture_cube_map
.get();
6480 glBindTexture(texture_unit
.bind_target
,
6481 texture_ref
? texture_ref
->service_id() : 0);
6485 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6486 Texture
* texture
= texture_ref
->texture();
6487 gfx::GLImage
* image
=
6488 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6489 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6490 ScopedGLErrorSuppressor
suppressor(
6491 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6492 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6493 image
->DidUseTexImage();
6500 // Set the active texture back to whatever the user had it as.
6501 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6504 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6505 // Only check if there are some uncleared textures.
6506 if (!texture_manager()->HaveUnsafeTextures()) {
6510 // 1: Check all textures we are about to render with.
6511 if (state_
.current_program
.get()) {
6512 const Program::SamplerIndices
& sampler_indices
=
6513 state_
.current_program
->sampler_indices();
6514 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6515 const Program::UniformInfo
* uniform_info
=
6516 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6517 DCHECK(uniform_info
);
6518 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6519 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6520 if (texture_unit_index
< state_
.texture_units
.size()) {
6521 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6522 TextureRef
* texture_ref
=
6523 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6524 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6525 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6536 bool GLES2DecoderImpl::IsDrawValid(
6537 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6538 GLsizei primcount
) {
6539 DCHECK(instanced
|| primcount
== 1);
6541 // NOTE: We specifically do not check current_program->IsValid() because
6542 // it could never be invalid since glUseProgram would have failed. While
6543 // glLinkProgram could later mark the program as invalid the previous
6544 // valid program will still function if it is still the current program.
6545 if (!state_
.current_program
.get()) {
6546 // The program does not exist.
6547 // But GL says no ERROR.
6548 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6552 if (CheckDrawingFeedbackLoops()) {
6554 GL_INVALID_OPERATION
, function_name
,
6555 "Source and destination textures of the draw are the same.");
6559 return state_
.vertex_attrib_manager
6560 ->ValidateBindings(function_name
,
6562 feature_info_
.get(),
6563 state_
.current_program
.get(),
6564 max_vertex_accessed
,
6569 bool GLES2DecoderImpl::SimulateAttrib0(
6570 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6574 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6577 const VertexAttrib
* attrib
=
6578 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6579 // If it's enabled or it's not used then we don't need to do anything.
6580 bool attrib_0_used
=
6581 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6582 if (attrib
->enabled() && attrib_0_used
) {
6586 // Make a buffer with a single repeated vec4 value enough to
6587 // simulate the constant value that is supposed to be here.
6588 // This is required to emulate GLES2 on GL.
6589 GLuint num_vertices
= max_vertex_accessed
+ 1;
6590 uint32 size_needed
= 0;
6592 if (num_vertices
== 0 ||
6593 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6594 size_needed
> 0x7FFFFFFFU
) {
6595 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6599 LOCAL_PERFORMANCE_WARNING(
6600 "Attribute 0 is disabled. This has signficant performance penalty");
6602 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6603 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6605 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6607 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6608 GLenum error
= glGetError();
6609 if (error
!= GL_NO_ERROR
) {
6611 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6616 const Vec4
& value
= state_
.attrib_values
[0];
6619 (!attrib_0_buffer_matches_value_
||
6620 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6621 value
.v
[1] != attrib_0_value_
.v
[1] ||
6622 value
.v
[2] != attrib_0_value_
.v
[2] ||
6623 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6624 std::vector
<Vec4
> temp(num_vertices
, value
);
6625 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6626 attrib_0_buffer_matches_value_
= true;
6627 attrib_0_value_
= value
;
6628 attrib_0_size_
= size_needed
;
6631 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6633 if (attrib
->divisor())
6634 glVertexAttribDivisorANGLE(0, 0);
6640 void GLES2DecoderImpl::RestoreStateForAttrib(
6641 GLuint attrib_index
, bool restore_array_binding
) {
6642 const VertexAttrib
* attrib
=
6643 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6644 if (restore_array_binding
) {
6645 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6646 Buffer
* buffer
= attrib
->buffer();
6647 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6648 glVertexAttribPointer(
6649 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6650 attrib
->gl_stride(), ptr
);
6652 if (attrib
->divisor())
6653 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6655 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6656 state_
.bound_array_buffer
->service_id() : 0);
6658 // Never touch vertex attribute 0's state (in particular, never
6659 // disable it) when running on desktop GL because it will never be
6661 if (attrib_index
!= 0 ||
6662 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6663 if (attrib
->enabled()) {
6664 glEnableVertexAttribArray(attrib_index
);
6666 glDisableVertexAttribArray(attrib_index
);
6671 bool GLES2DecoderImpl::SimulateFixedAttribs(
6672 const char* function_name
,
6673 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6676 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6679 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6683 LOCAL_PERFORMANCE_WARNING(
6684 "GL_FIXED attributes have a signficant performance penalty");
6686 // NOTE: we could be smart and try to check if a buffer is used
6687 // twice in 2 different attribs, find the overlapping parts and therefore
6688 // duplicate the minimum amount of data but this whole code path is not meant
6689 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6690 // tests so we just add to the buffer attrib used.
6692 GLuint elements_needed
= 0;
6693 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6694 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6695 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6696 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6697 const VertexAttrib
* attrib
= *it
;
6698 const Program::VertexAttrib
* attrib_info
=
6699 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6700 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6701 max_vertex_accessed
);
6702 GLuint num_vertices
= max_accessed
+ 1;
6703 if (num_vertices
== 0) {
6705 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6709 attrib
->CanAccess(max_accessed
) &&
6710 attrib
->type() == GL_FIXED
) {
6711 uint32 elements_used
= 0;
6712 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6713 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6715 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6721 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6722 uint32 size_needed
= 0;
6723 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6724 size_needed
> 0x7FFFFFFFU
) {
6726 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6730 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6732 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6733 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6734 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6735 GLenum error
= glGetError();
6736 if (error
!= GL_NO_ERROR
) {
6738 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6743 // Copy the elements and convert to float
6744 GLintptr offset
= 0;
6745 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6746 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6747 const VertexAttrib
* attrib
= *it
;
6748 const Program::VertexAttrib
* attrib_info
=
6749 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6750 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6751 max_vertex_accessed
);
6752 GLuint num_vertices
= max_accessed
+ 1;
6753 if (num_vertices
== 0) {
6755 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6759 attrib
->CanAccess(max_accessed
) &&
6760 attrib
->type() == GL_FIXED
) {
6761 int num_elements
= attrib
->size() * num_vertices
;
6762 const int src_size
= num_elements
* sizeof(int32
);
6763 const int dst_size
= num_elements
* sizeof(float);
6764 scoped_ptr
<float[]> data(new float[num_elements
]);
6765 const int32
* src
= reinterpret_cast<const int32
*>(
6766 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
6767 const int32
* end
= src
+ num_elements
;
6768 float* dst
= data
.get();
6769 while (src
!= end
) {
6770 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6772 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
6773 glVertexAttribPointer(
6774 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6775 reinterpret_cast<GLvoid
*>(offset
));
6783 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6784 // There's no need to call glVertexAttribPointer because we shadow all the
6785 // settings and passing GL_FIXED to it will not work.
6788 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6792 error::Error
GLES2DecoderImpl::DoDrawArrays(
6793 const char* function_name
,
6798 GLsizei primcount
) {
6799 error::Error error
= WillAccessBoundFramebufferForDraw();
6800 if (error
!= error::kNoError
)
6802 if (!validators_
->draw_mode
.IsValid(mode
)) {
6803 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6804 return error::kNoError
;
6807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6808 return error::kNoError
;
6810 if (primcount
< 0) {
6811 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6812 return error::kNoError
;
6814 if (!CheckBoundFramebuffersValid(function_name
)) {
6815 return error::kNoError
;
6817 // We have to check this here because the prototype for glDrawArrays
6818 // is GLint not GLsizei.
6820 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6821 return error::kNoError
;
6824 if (count
== 0 || primcount
== 0) {
6825 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6826 return error::kNoError
;
6829 GLuint max_vertex_accessed
= first
+ count
- 1;
6830 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6831 if (!ClearUnclearedTextures()) {
6832 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6833 return error::kNoError
;
6835 bool simulated_attrib_0
= false;
6836 if (!SimulateAttrib0(
6837 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6838 return error::kNoError
;
6840 bool simulated_fixed_attribs
= false;
6841 if (SimulateFixedAttribs(
6842 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6844 bool textures_set
= !PrepareTexturesForRender();
6846 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6848 glDrawArrays(mode
, first
, count
);
6850 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6853 RestoreStateForTextures();
6855 if (simulated_fixed_attribs
) {
6856 RestoreStateForSimulatedFixedAttribs();
6859 if (simulated_attrib_0
) {
6860 // We don't have to restore attrib 0 generic data at the end of this
6861 // function even if it is simulated. This is because we will simulate
6862 // it in each draw call, and attrib 0 generic data queries use cached
6863 // values instead of passing down to the underlying driver.
6864 RestoreStateForAttrib(0, false);
6867 return error::kNoError
;
6870 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
6871 const void* cmd_data
) {
6872 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
6873 return DoDrawArrays("glDrawArrays",
6875 static_cast<GLenum
>(c
.mode
),
6876 static_cast<GLint
>(c
.first
),
6877 static_cast<GLsizei
>(c
.count
),
6881 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6882 uint32 immediate_data_size
,
6883 const void* cmd_data
) {
6884 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
6885 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
6886 if (!features().angle_instanced_arrays
) {
6888 GL_INVALID_OPERATION
,
6889 "glDrawArraysInstancedANGLE", "function not available");
6890 return error::kNoError
;
6892 return DoDrawArrays("glDrawArraysIntancedANGLE",
6894 static_cast<GLenum
>(c
.mode
),
6895 static_cast<GLint
>(c
.first
),
6896 static_cast<GLsizei
>(c
.count
),
6897 static_cast<GLsizei
>(c
.primcount
));
6900 error::Error
GLES2DecoderImpl::DoDrawElements(
6901 const char* function_name
,
6907 GLsizei primcount
) {
6908 error::Error error
= WillAccessBoundFramebufferForDraw();
6909 if (error
!= error::kNoError
)
6911 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6913 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6914 return error::kNoError
;
6918 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6919 return error::kNoError
;
6922 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6923 return error::kNoError
;
6925 if (!validators_
->draw_mode
.IsValid(mode
)) {
6926 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6927 return error::kNoError
;
6929 if (!validators_
->index_type
.IsValid(type
)) {
6930 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6931 return error::kNoError
;
6933 if (primcount
< 0) {
6934 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6935 return error::kNoError
;
6938 if (!CheckBoundFramebuffersValid(function_name
)) {
6939 return error::kNoError
;
6942 if (count
== 0 || primcount
== 0) {
6943 return error::kNoError
;
6946 GLuint max_vertex_accessed
;
6947 Buffer
* element_array_buffer
=
6948 state_
.vertex_attrib_manager
->element_array_buffer();
6950 if (!element_array_buffer
->GetMaxValueForRange(
6951 offset
, count
, type
, &max_vertex_accessed
)) {
6953 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6954 return error::kNoError
;
6957 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6958 if (!ClearUnclearedTextures()) {
6959 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6960 return error::kNoError
;
6962 bool simulated_attrib_0
= false;
6963 if (!SimulateAttrib0(
6964 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6965 return error::kNoError
;
6967 bool simulated_fixed_attribs
= false;
6968 if (SimulateFixedAttribs(
6969 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6971 bool textures_set
= !PrepareTexturesForRender();
6973 // TODO(gman): Refactor to hide these details in BufferManager or
6974 // VertexAttribManager.
6975 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6976 bool used_client_side_array
= false;
6977 if (element_array_buffer
->IsClientSideArray()) {
6978 used_client_side_array
= true;
6979 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6980 indices
= element_array_buffer
->GetRange(offset
, 0);
6983 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6985 glDrawElements(mode
, count
, type
, indices
);
6987 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6990 if (used_client_side_array
) {
6991 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6992 element_array_buffer
->service_id());
6996 RestoreStateForTextures();
6998 if (simulated_fixed_attribs
) {
6999 RestoreStateForSimulatedFixedAttribs();
7002 if (simulated_attrib_0
) {
7003 // We don't have to restore attrib 0 generic data at the end of this
7004 // function even if it is simulated. This is because we will simulate
7005 // it in each draw call, and attrib 0 generic data queries use cached
7006 // values instead of passing down to the underlying driver.
7007 RestoreStateForAttrib(0, false);
7010 return error::kNoError
;
7013 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7014 const void* cmd_data
) {
7015 const gles2::cmds::DrawElements
& c
=
7016 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7017 return DoDrawElements("glDrawElements",
7019 static_cast<GLenum
>(c
.mode
),
7020 static_cast<GLsizei
>(c
.count
),
7021 static_cast<GLenum
>(c
.type
),
7022 static_cast<int32
>(c
.index_offset
),
7026 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7027 uint32 immediate_data_size
,
7028 const void* cmd_data
) {
7029 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7030 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7031 if (!features().angle_instanced_arrays
) {
7033 GL_INVALID_OPERATION
,
7034 "glDrawElementsInstancedANGLE", "function not available");
7035 return error::kNoError
;
7037 return DoDrawElements("glDrawElementsInstancedANGLE",
7039 static_cast<GLenum
>(c
.mode
),
7040 static_cast<GLsizei
>(c
.count
),
7041 static_cast<GLenum
>(c
.type
),
7042 static_cast<int32
>(c
.index_offset
),
7043 static_cast<GLsizei
>(c
.primcount
));
7046 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7047 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7048 GLuint max_vertex_accessed
= 0;
7049 Buffer
* buffer
= GetBuffer(buffer_id
);
7051 // TODO(gman): Should this be a GL error or a command buffer error?
7053 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7055 if (!buffer
->GetMaxValueForRange(
7056 offset
, count
, type
, &max_vertex_accessed
)) {
7057 // TODO(gman): Should this be a GL error or a command buffer error?
7059 GL_INVALID_OPERATION
,
7060 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7063 return max_vertex_accessed
;
7066 void GLES2DecoderImpl::DoShaderSource(
7067 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7069 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7070 if (length
&& length
[ii
] > 0)
7071 str
.append(data
[ii
], length
[ii
]);
7073 str
.append(data
[ii
]);
7075 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7079 // Note: We don't actually call glShaderSource here. We wait until
7080 // we actually compile the shader.
7081 shader
->set_source(str
);
7084 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7085 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7086 GLenum buffer_mode
) {
7087 Program
* program
= GetProgramInfoNotShader(
7088 client_program_id
, "glTransformFeedbackVaryings");
7092 glTransformFeedbackVaryings(
7093 program
->service_id(), count
, varyings
, buffer_mode
);
7096 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7097 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7098 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7103 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7104 if (use_shader_translator_
) {
7105 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7106 vertex_translator_
: fragment_translator_
;
7109 const Shader::TranslatedShaderSourceType source_type
=
7110 feature_info_
->feature_flags().angle_translated_shader_source
?
7111 Shader::kANGLE
: Shader::kGL
;
7112 shader
->RequestCompile(translator
, source_type
);
7115 void GLES2DecoderImpl::DoGetShaderiv(
7116 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7117 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7122 // Compile now for statuses that require it.
7124 case GL_COMPILE_STATUS
:
7125 case GL_INFO_LOG_LENGTH
:
7126 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7127 shader
->DoCompile();
7135 case GL_SHADER_SOURCE_LENGTH
:
7136 *params
= shader
->source().size();
7140 case GL_COMPILE_STATUS
:
7141 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7143 case GL_INFO_LOG_LENGTH
:
7144 *params
= shader
->log_info().size();
7148 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7149 *params
= shader
->translated_source().size();
7156 glGetShaderiv(shader
->service_id(), pname
, params
);
7159 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7160 const void* cmd_data
) {
7161 const gles2::cmds::GetShaderSource
& c
=
7162 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7163 GLuint shader_id
= c
.shader
;
7164 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7165 Bucket
* bucket
= CreateBucket(bucket_id
);
7166 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7167 if (!shader
|| shader
->source().empty()) {
7169 return error::kNoError
;
7171 bucket
->SetFromString(shader
->source().c_str());
7172 return error::kNoError
;
7175 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7176 uint32 immediate_data_size
,
7177 const void* cmd_data
) {
7178 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7179 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7181 GLuint shader_id
= c
.shader
;
7182 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7183 Bucket
* bucket
= CreateBucket(bucket_id
);
7184 Shader
* shader
= GetShaderInfoNotProgram(
7185 shader_id
, "glGetTranslatedShaderSourceANGLE");
7188 return error::kNoError
;
7191 // Make sure translator has been utilized in compile.
7192 shader
->DoCompile();
7194 bucket
->SetFromString(shader
->translated_source().c_str());
7195 return error::kNoError
;
7198 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7199 uint32 immediate_data_size
,
7200 const void* cmd_data
) {
7201 const gles2::cmds::GetProgramInfoLog
& c
=
7202 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7203 GLuint program_id
= c
.program
;
7204 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7205 Bucket
* bucket
= CreateBucket(bucket_id
);
7206 Program
* program
= GetProgramInfoNotShader(
7207 program_id
, "glGetProgramInfoLog");
7208 if (!program
|| !program
->log_info()) {
7209 bucket
->SetFromString("");
7210 return error::kNoError
;
7212 bucket
->SetFromString(program
->log_info()->c_str());
7213 return error::kNoError
;
7216 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7217 uint32 immediate_data_size
,
7218 const void* cmd_data
) {
7219 const gles2::cmds::GetShaderInfoLog
& c
=
7220 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7221 GLuint shader_id
= c
.shader
;
7222 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7223 Bucket
* bucket
= CreateBucket(bucket_id
);
7224 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7226 bucket
->SetFromString("");
7227 return error::kNoError
;
7230 // Shader must be compiled in order to get the info log.
7231 shader
->DoCompile();
7233 bucket
->SetFromString(shader
->log_info().c_str());
7234 return error::kNoError
;
7237 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7238 return state_
.GetEnabled(cap
);
7241 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7242 const Buffer
* buffer
= GetBuffer(client_id
);
7243 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7246 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7247 const Framebuffer
* framebuffer
=
7248 GetFramebuffer(client_id
);
7249 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7252 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7253 // IsProgram is true for programs as soon as they are created, until they are
7254 // deleted and no longer in use.
7255 const Program
* program
= GetProgram(client_id
);
7256 return program
!= NULL
&& !program
->IsDeleted();
7259 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7260 const Renderbuffer
* renderbuffer
=
7261 GetRenderbuffer(client_id
);
7262 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7265 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7266 // IsShader is true for shaders as soon as they are created, until they
7267 // are deleted and not attached to any programs.
7268 const Shader
* shader
= GetShader(client_id
);
7269 return shader
!= NULL
&& !shader
->IsDeleted();
7272 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7273 const TextureRef
* texture_ref
= GetTexture(client_id
);
7274 return texture_ref
&& texture_ref
->texture()->IsValid();
7277 void GLES2DecoderImpl::DoAttachShader(
7278 GLuint program_client_id
, GLint shader_client_id
) {
7279 Program
* program
= GetProgramInfoNotShader(
7280 program_client_id
, "glAttachShader");
7284 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7288 if (!program
->AttachShader(shader_manager(), shader
)) {
7290 GL_INVALID_OPERATION
,
7292 "can not attach more than one shader of the same type.");
7295 glAttachShader(program
->service_id(), shader
->service_id());
7298 void GLES2DecoderImpl::DoDetachShader(
7299 GLuint program_client_id
, GLint shader_client_id
) {
7300 Program
* program
= GetProgramInfoNotShader(
7301 program_client_id
, "glDetachShader");
7305 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7309 if (!program
->DetachShader(shader_manager(), shader
)) {
7311 GL_INVALID_OPERATION
,
7312 "glDetachShader", "shader not attached to program");
7315 glDetachShader(program
->service_id(), shader
->service_id());
7318 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7319 Program
* program
= GetProgramInfoNotShader(
7320 program_client_id
, "glValidateProgram");
7324 program
->Validate();
7327 void GLES2DecoderImpl::GetVertexAttribHelper(
7328 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7330 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7331 Buffer
* buffer
= attrib
->buffer();
7332 if (buffer
&& !buffer
->IsDeleted()) {
7334 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7335 *params
= client_id
;
7339 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7340 *params
= attrib
->enabled();
7342 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7343 *params
= attrib
->size();
7345 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7346 *params
= attrib
->gl_stride();
7348 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7349 *params
= attrib
->type();
7351 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7352 *params
= attrib
->normalized();
7354 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7355 *params
= attrib
->divisor();
7363 void GLES2DecoderImpl::DoGetTexParameterfv(
7364 GLenum target
, GLenum pname
, GLfloat
* params
) {
7365 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7366 glGetTexParameterfv(target
, pname
, params
);
7369 void GLES2DecoderImpl::DoGetTexParameteriv(
7370 GLenum target
, GLenum pname
, GLint
* params
) {
7371 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7372 glGetTexParameteriv(target
, pname
, params
);
7375 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7376 GLenum target
, GLenum pname
) {
7377 if (!workarounds().init_texture_max_anisotropy
)
7379 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7380 !validators_
->texture_parameter
.IsValid(pname
)) {
7384 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7388 GL_INVALID_OPERATION
,
7389 "glGetTexParamter{fi}v", "unknown texture for target");
7392 Texture
* texture
= texture_ref
->texture();
7393 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7396 void GLES2DecoderImpl::DoGetVertexAttribfv(
7397 GLuint index
, GLenum pname
, GLfloat
* params
) {
7398 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7401 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7405 case GL_CURRENT_VERTEX_ATTRIB
: {
7406 const Vec4
& value
= state_
.attrib_values
[index
];
7407 params
[0] = value
.v
[0];
7408 params
[1] = value
.v
[1];
7409 params
[2] = value
.v
[2];
7410 params
[3] = value
.v
[3];
7415 GetVertexAttribHelper(attrib
, pname
, &value
);
7416 *params
= static_cast<GLfloat
>(value
);
7422 void GLES2DecoderImpl::DoGetVertexAttribiv(
7423 GLuint index
, GLenum pname
, GLint
* params
) {
7424 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7427 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7431 case GL_CURRENT_VERTEX_ATTRIB
: {
7432 const Vec4
& value
= state_
.attrib_values
[index
];
7433 params
[0] = static_cast<GLint
>(value
.v
[0]);
7434 params
[1] = static_cast<GLint
>(value
.v
[1]);
7435 params
[2] = static_cast<GLint
>(value
.v
[2]);
7436 params
[3] = static_cast<GLint
>(value
.v
[3]);
7440 GetVertexAttribHelper(attrib
, pname
, params
);
7445 bool GLES2DecoderImpl::SetVertexAttribValue(
7446 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7447 if (index
>= state_
.attrib_values
.size()) {
7448 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7451 Vec4
& v
= state_
.attrib_values
[index
];
7459 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7460 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7461 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7462 glVertexAttrib1f(index
, v0
);
7466 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7467 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7468 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7469 glVertexAttrib2f(index
, v0
, v1
);
7473 void GLES2DecoderImpl::DoVertexAttrib3f(
7474 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7475 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7476 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7477 glVertexAttrib3f(index
, v0
, v1
, v2
);
7481 void GLES2DecoderImpl::DoVertexAttrib4f(
7482 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7483 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7484 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7485 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7489 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7490 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7491 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7492 glVertexAttrib1fv(index
, v
);
7496 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7497 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7498 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7499 glVertexAttrib2fv(index
, v
);
7503 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7504 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7505 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7506 glVertexAttrib3fv(index
, v
);
7510 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7511 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7512 glVertexAttrib4fv(index
, v
);
7516 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7517 uint32 immediate_data_size
,
7518 const void* cmd_data
) {
7519 // TODO(zmo): Unsafe ES3 API, missing states update.
7520 if (!unsafe_es3_apis_enabled())
7521 return error::kUnknownCommand
;
7522 const gles2::cmds::VertexAttribIPointer
& c
=
7523 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7524 GLuint indx
= c
.indx
;
7525 GLint size
= c
.size
;
7526 GLenum type
= c
.type
;
7527 GLsizei stride
= c
.stride
;
7528 GLsizei offset
= c
.offset
;
7529 const void* ptr
= reinterpret_cast<const void*>(offset
);
7530 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7531 return error::kNoError
;
7534 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7535 uint32 immediate_data_size
,
7536 const void* cmd_data
) {
7537 const gles2::cmds::VertexAttribPointer
& c
=
7538 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7540 if (!state_
.bound_array_buffer
.get() ||
7541 state_
.bound_array_buffer
->IsDeleted()) {
7542 if (state_
.vertex_attrib_manager
.get() ==
7543 state_
.default_vertex_attrib_manager
.get()) {
7545 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7546 return error::kNoError
;
7547 } else if (c
.offset
!= 0) {
7550 "glVertexAttribPointer", "client side arrays are not allowed");
7551 return error::kNoError
;
7555 GLuint indx
= c
.indx
;
7556 GLint size
= c
.size
;
7557 GLenum type
= c
.type
;
7558 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
7559 GLsizei stride
= c
.stride
;
7560 GLsizei offset
= c
.offset
;
7561 const void* ptr
= reinterpret_cast<const void*>(offset
);
7562 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7563 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7564 return error::kNoError
;
7566 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7568 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7569 return error::kNoError
;
7571 if (indx
>= group_
->max_vertex_attribs()) {
7573 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7574 return error::kNoError
;
7578 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7579 return error::kNoError
;
7583 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7584 return error::kNoError
;
7588 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7589 return error::kNoError
;
7591 GLsizei component_size
=
7592 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7593 // component_size must be a power of two to use & as optimized modulo.
7594 DCHECK(GLES2Util::IsPOT(component_size
));
7595 if (offset
& (component_size
- 1)) {
7597 GL_INVALID_OPERATION
,
7598 "glVertexAttribPointer", "offset not valid for type");
7599 return error::kNoError
;
7601 if (stride
& (component_size
- 1)) {
7603 GL_INVALID_OPERATION
,
7604 "glVertexAttribPointer", "stride not valid for type");
7605 return error::kNoError
;
7607 state_
.vertex_attrib_manager
7608 ->SetAttribInfo(indx
,
7609 state_
.bound_array_buffer
.get(),
7614 stride
!= 0 ? stride
: component_size
* size
,
7616 if (type
!= GL_FIXED
) {
7617 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7619 return error::kNoError
;
7622 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7624 state_
.viewport_x
= x
;
7625 state_
.viewport_y
= y
;
7626 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7627 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7628 glViewport(x
, y
, width
, height
);
7631 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7632 uint32 immediate_data_size
,
7633 const void* cmd_data
) {
7634 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7635 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7636 if (!features().angle_instanced_arrays
) {
7638 GL_INVALID_OPERATION
,
7639 "glVertexAttribDivisorANGLE", "function not available");
7640 return error::kNoError
;
7642 GLuint index
= c
.index
;
7643 GLuint divisor
= c
.divisor
;
7644 if (index
>= group_
->max_vertex_attribs()) {
7647 "glVertexAttribDivisorANGLE", "index out of range");
7648 return error::kNoError
;
7651 state_
.vertex_attrib_manager
->SetDivisor(
7654 glVertexAttribDivisorANGLE(index
, divisor
);
7655 return error::kNoError
;
7658 template <typename pixel_data_type
>
7659 static void WriteAlphaData(
7660 void *pixels
, uint32 row_count
, uint32 channel_count
,
7661 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7662 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7663 DCHECK_GT(channel_count
, 0U);
7664 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7665 uint32 unpadded_row_size_in_elements
=
7666 unpadded_row_size
/ sizeof(pixel_data_type
);
7667 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7668 uint32 padded_row_size_in_elements
=
7669 padded_row_size
/ sizeof(pixel_data_type
);
7670 pixel_data_type
* dst
=
7671 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7672 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7673 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7674 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7677 dst
+= padded_row_size_in_elements
;
7681 void GLES2DecoderImpl::FinishReadPixels(
7682 const cmds::ReadPixels
& c
,
7684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7685 GLsizei width
= c
.width
;
7686 GLsizei height
= c
.height
;
7687 GLenum format
= c
.format
;
7688 GLenum type
= c
.type
;
7689 typedef cmds::ReadPixels::Result Result
;
7691 Result
* result
= NULL
;
7692 if (c
.result_shm_id
!= 0) {
7693 result
= GetSharedMemoryAs
<Result
*>(
7694 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7697 glDeleteBuffersARB(1, &buffer
);
7702 GLES2Util::ComputeImageDataSizes(
7703 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7705 void* pixels
= GetSharedMemoryAs
<void*>(
7706 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7709 glDeleteBuffersARB(1, &buffer
);
7715 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7717 if (features().map_buffer_range
) {
7718 data
= glMapBufferRange(
7719 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7721 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7724 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
7725 "Unable to map memory for readback.");
7728 memcpy(pixels
, data
, pixels_size
);
7729 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7730 // have to restore the state.
7731 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7732 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7733 glDeleteBuffersARB(1, &buffer
);
7736 if (result
!= NULL
) {
7740 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7741 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7742 if ((channels_exist
& 0x0008) == 0 &&
7743 workarounds().clear_alpha_in_readpixels
) {
7744 // Set the alpha to 255 because some drivers are buggy in this regard.
7747 uint32 unpadded_row_size
;
7748 uint32 padded_row_size
;
7749 if (!GLES2Util::ComputeImageDataSizes(
7750 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
7751 &unpadded_row_size
, &padded_row_size
)) {
7755 uint32 channel_count
= 0;
7756 uint32 alpha_channel
= 0;
7769 if (channel_count
> 0) {
7771 case GL_UNSIGNED_BYTE
:
7772 WriteAlphaData
<uint8
>(
7773 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7774 padded_row_size
, 0xFF);
7777 WriteAlphaData
<float>(
7778 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7779 padded_row_size
, 1.0f
);
7782 WriteAlphaData
<uint16
>(
7783 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7784 padded_row_size
, 0x3C00);
7791 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
7792 const void* cmd_data
) {
7793 const gles2::cmds::ReadPixels
& c
=
7794 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
7795 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7796 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7797 if (fbo_error
!= error::kNoError
)
7801 GLsizei width
= c
.width
;
7802 GLsizei height
= c
.height
;
7803 GLenum format
= c
.format
;
7804 GLenum type
= c
.type
;
7805 GLboolean async
= static_cast<GLboolean
>(c
.async
);
7806 if (width
< 0 || height
< 0) {
7807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7808 return error::kNoError
;
7810 typedef cmds::ReadPixels::Result Result
;
7812 if (!GLES2Util::ComputeImageDataSizes(
7813 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7815 return error::kOutOfBounds
;
7817 void* pixels
= GetSharedMemoryAs
<void*>(
7818 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7820 return error::kOutOfBounds
;
7822 Result
* result
= NULL
;
7823 if (c
.result_shm_id
!= 0) {
7824 result
= GetSharedMemoryAs
<Result
*>(
7825 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7827 return error::kOutOfBounds
;
7831 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7832 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7833 return error::kNoError
;
7835 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7836 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7837 return error::kNoError
;
7839 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7840 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7841 // format and type are acceptable enums but not guaranteed to be supported
7842 // for this framebuffer. Have to ask gl if they are valid.
7843 GLint preferred_format
= 0;
7844 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7845 GLint preferred_type
= 0;
7846 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7847 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7848 type
!= static_cast<GLenum
>(preferred_type
)) {
7850 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7851 "with the current read framebuffer");
7852 return error::kNoError
;
7855 if (width
== 0 || height
== 0) {
7856 return error::kNoError
;
7859 // Get the size of the current fbo or backbuffer.
7860 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7864 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7866 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7867 return error::kNoError
;
7870 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7871 return error::kNoError
;
7874 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7875 return error::kNoError
;
7878 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7880 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7882 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7883 // The user requested an out of range area. Get the results 1 line
7886 uint32 unpadded_row_size
;
7887 uint32 padded_row_size
;
7888 if (!GLES2Util::ComputeImageDataSizes(
7889 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
7890 &unpadded_row_size
, &padded_row_size
)) {
7892 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7893 return error::kNoError
;
7896 GLint dest_x_offset
= std::max(-x
, 0);
7897 uint32 dest_row_offset
;
7898 if (!GLES2Util::ComputeImageDataSizes(
7899 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
7900 &dest_row_offset
, NULL
, NULL
)) {
7902 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7903 return error::kNoError
;
7906 // Copy each row into the larger dest rect.
7907 int8
* dst
= static_cast<int8
*>(pixels
);
7908 GLint read_x
= std::max(0, x
);
7909 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7910 GLint read_width
= read_end_x
- read_x
;
7911 for (GLint yy
= 0; yy
< height
; ++yy
) {
7915 memset(dst
, 0, unpadded_row_size
);
7917 // If the row is in range, copy it.
7918 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7920 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7922 dst
+= padded_row_size
;
7925 if (async
&& features().use_async_readpixels
) {
7927 glGenBuffersARB(1, &buffer
);
7928 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7929 // For ANGLE client version 2, GL_STREAM_READ is not available.
7930 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
7931 GL_STATIC_DRAW
: GL_STREAM_READ
;
7932 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
7933 GLenum error
= glGetError();
7934 if (error
== GL_NO_ERROR
) {
7935 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7936 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7937 new FenceCallback()));
7938 WaitForReadPixels(base::Bind(
7939 &GLES2DecoderImpl::FinishReadPixels
,
7940 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7941 <GLES2DecoderImpl
>(this),
7943 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7944 return error::kNoError
;
7946 // On error, unbind pack buffer and fall through to sync readpixels
7947 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7948 glDeleteBuffersARB(1, &buffer
);
7951 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7953 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7954 if (error
== GL_NO_ERROR
) {
7955 if (result
!= NULL
) {
7958 FinishReadPixels(c
, 0);
7961 return error::kNoError
;
7964 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
7965 const void* cmd_data
) {
7966 const gles2::cmds::PixelStorei
& c
=
7967 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
7968 GLenum pname
= c
.pname
;
7969 GLenum param
= c
.param
;
7970 if (!validators_
->pixel_store
.IsValid(pname
)) {
7971 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7972 return error::kNoError
;
7975 case GL_PACK_ALIGNMENT
:
7976 case GL_UNPACK_ALIGNMENT
:
7977 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7979 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7980 return error::kNoError
;
7983 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7984 unpack_flip_y_
= (param
!= 0);
7985 return error::kNoError
;
7986 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7987 unpack_premultiply_alpha_
= (param
!= 0);
7988 return error::kNoError
;
7989 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7990 unpack_unpremultiply_alpha_
= (param
!= 0);
7991 return error::kNoError
;
7995 glPixelStorei(pname
, param
);
7997 case GL_PACK_ALIGNMENT
:
7998 state_
.pack_alignment
= param
;
8000 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8001 state_
.pack_reverse_row_order
= (param
!= 0);
8003 case GL_UNPACK_ALIGNMENT
:
8004 state_
.unpack_alignment
= param
;
8007 // Validation should have prevented us from getting here.
8011 return error::kNoError
;
8014 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8015 uint32 immediate_data_size
,
8016 const void* cmd_data
) {
8017 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8018 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8021 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8023 if (!supports_post_sub_buffer_
) {
8025 GL_INVALID_OPERATION
,
8026 "glPostSubBufferCHROMIUM", "command not supported by surface");
8027 return error::kNoError
;
8030 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8033 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8034 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8035 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8036 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8038 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8039 return error::kNoError
;
8041 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8042 return error::kLostContext
;
8046 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8047 uint32 immediate_data_size
,
8048 const void* cmd_data
) {
8049 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8050 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8051 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8053 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8054 "glScheduleOverlayPlaneCHROMIUM",
8056 return error::kNoError
;
8058 gfx::GLImage
* image
=
8059 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8061 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8062 "glScheduleOverlayPlaneCHROMIUM",
8063 "unsupported texture format");
8064 return error::kNoError
;
8066 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8067 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8068 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8069 "glScheduleOverlayPlaneCHROMIUM",
8070 "invalid transform enum");
8071 return error::kNoError
;
8073 if (!surface_
->ScheduleOverlayPlane(
8077 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8078 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8079 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8080 "glScheduleOverlayPlaneCHROMIUM",
8081 "failed to schedule overlay");
8083 return error::kNoError
;
8086 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8087 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8088 const std::string
& name_str
) {
8089 if (!StringIsValidForGLES(name_str
.c_str())) {
8091 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8092 return error::kNoError
;
8094 Program
* program
= GetProgramInfoNotShader(
8095 client_id
, "glGetAttribLocation");
8097 return error::kNoError
;
8099 if (!program
->IsValid()) {
8101 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8102 return error::kNoError
;
8104 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8105 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8107 return error::kOutOfBounds
;
8109 // Require the client to init this incase the context is lost and we are no
8110 // longer executing commands.
8111 if (*location
!= -1) {
8112 return error::kGenericError
;
8114 *location
= program
->GetAttribLocation(name_str
);
8115 return error::kNoError
;
8118 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8119 uint32 immediate_data_size
,
8120 const void* cmd_data
) {
8121 const gles2::cmds::GetAttribLocation
& c
=
8122 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8123 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8125 return error::kInvalidArguments
;
8127 std::string name_str
;
8128 if (!bucket
->GetAsString(&name_str
)) {
8129 return error::kInvalidArguments
;
8131 return GetAttribLocationHelper(
8132 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8135 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8136 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8137 const std::string
& name_str
) {
8138 if (!StringIsValidForGLES(name_str
.c_str())) {
8140 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8141 return error::kNoError
;
8143 Program
* program
= GetProgramInfoNotShader(
8144 client_id
, "glGetUniformLocation");
8146 return error::kNoError
;
8148 if (!program
->IsValid()) {
8150 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8151 return error::kNoError
;
8153 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8154 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8156 return error::kOutOfBounds
;
8158 // Require the client to init this incase the context is lost an we are no
8159 // longer executing commands.
8160 if (*location
!= -1) {
8161 return error::kGenericError
;
8163 *location
= program
->GetUniformFakeLocation(name_str
);
8164 return error::kNoError
;
8167 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8168 uint32 immediate_data_size
,
8169 const void* cmd_data
) {
8170 const gles2::cmds::GetUniformLocation
& c
=
8171 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8172 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8174 return error::kInvalidArguments
;
8176 std::string name_str
;
8177 if (!bucket
->GetAsString(&name_str
)) {
8178 return error::kInvalidArguments
;
8180 return GetUniformLocationHelper(
8181 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8184 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8185 uint32 immediate_data_size
,
8186 const void* cmd_data
) {
8187 if (!unsafe_es3_apis_enabled())
8188 return error::kUnknownCommand
;
8189 const gles2::cmds::GetUniformIndices
& c
=
8190 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8191 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8193 return error::kInvalidArguments
;
8196 std::vector
<char*> names
;
8197 std::vector
<GLint
> len
;
8198 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8199 return error::kInvalidArguments
;
8201 typedef cmds::GetUniformIndices::Result Result
;
8202 Result
* result
= GetSharedMemoryAs
<Result
*>(
8203 c
.indices_shm_id
, c
.indices_shm_offset
,
8204 Result::ComputeSize(static_cast<size_t>(count
)));
8205 GLuint
* indices
= result
? result
->GetData() : NULL
;
8206 if (indices
== NULL
) {
8207 return error::kOutOfBounds
;
8209 // Check that the client initialized the result.
8210 if (result
->size
!= 0) {
8211 return error::kInvalidArguments
;
8213 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8215 return error::kNoError
;
8217 GLuint service_id
= program
->service_id();
8218 GLint link_status
= GL_FALSE
;
8219 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8220 if (link_status
!= GL_TRUE
) {
8221 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8222 "glGetUniformIndices", "program not linked");
8223 return error::kNoError
;
8225 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8226 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8227 GLenum error
= glGetError();
8228 if (error
== GL_NO_ERROR
) {
8229 result
->SetNumResults(count
);
8231 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8233 return error::kNoError
;
8236 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8237 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8238 const std::string
& name_str
) {
8239 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8240 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8242 return error::kOutOfBounds
;
8244 // Require the client to init this incase the context is lost and we are no
8245 // longer executing commands.
8246 if (*location
!= -1) {
8247 return error::kGenericError
;
8249 Program
* program
= GetProgramInfoNotShader(
8250 client_id
, "glGetFragDataLocation");
8252 return error::kNoError
;
8254 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8255 return error::kNoError
;
8258 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8259 uint32 immediate_data_size
,
8260 const void* cmd_data
) {
8261 if (!unsafe_es3_apis_enabled())
8262 return error::kUnknownCommand
;
8263 const gles2::cmds::GetFragDataLocation
& c
=
8264 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8265 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8267 return error::kInvalidArguments
;
8269 std::string name_str
;
8270 if (!bucket
->GetAsString(&name_str
)) {
8271 return error::kInvalidArguments
;
8273 return GetFragDataLocationHelper(
8274 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8277 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8278 uint32 immediate_data_size
, const void* cmd_data
) {
8279 if (!unsafe_es3_apis_enabled())
8280 return error::kUnknownCommand
;
8281 const gles2::cmds::GetUniformBlockIndex
& c
=
8282 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8283 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8285 return error::kInvalidArguments
;
8287 std::string name_str
;
8288 if (!bucket
->GetAsString(&name_str
)) {
8289 return error::kInvalidArguments
;
8291 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8292 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8294 return error::kOutOfBounds
;
8296 // Require the client to init this in case the context is lost and we are no
8297 // longer executing commands.
8298 if (*index
!= GL_INVALID_INDEX
) {
8299 return error::kGenericError
;
8301 Program
* program
= GetProgramInfoNotShader(
8302 c
.program
, "glGetUniformBlockIndex");
8304 return error::kNoError
;
8306 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8307 return error::kNoError
;
8310 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8311 const void* cmd_data
) {
8312 const gles2::cmds::GetString
& c
=
8313 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8314 GLenum name
= static_cast<GLenum
>(c
.name
);
8315 if (!validators_
->string_type
.IsValid(name
)) {
8316 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8317 return error::kNoError
;
8319 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
8320 std::string extensions
;
8323 str
= "OpenGL ES 2.0 Chromium";
8325 case GL_SHADING_LANGUAGE_VERSION
:
8326 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8330 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8331 // They are used by WEBGL_debug_renderer_info.
8332 if (!force_webgl_glsl_validation_
)
8337 // For WebGL contexts, strip out the OES derivatives and
8338 // EXT frag depth extensions if they have not been enabled.
8339 if (force_webgl_glsl_validation_
) {
8340 extensions
= feature_info_
->extensions();
8341 if (!derivatives_explicitly_enabled_
) {
8342 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8343 if (std::string::npos
!= offset
) {
8344 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8348 if (!frag_depth_explicitly_enabled_
) {
8349 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8350 if (std::string::npos
!= offset
) {
8351 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8355 if (!draw_buffers_explicitly_enabled_
) {
8356 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8357 if (std::string::npos
!= offset
) {
8358 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8362 if (!shader_texture_lod_explicitly_enabled_
) {
8363 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8364 if (std::string::npos
!= offset
) {
8365 extensions
.replace(offset
,
8366 arraysize(kEXTShaderTextureLodExtension
),
8371 extensions
= feature_info_
->extensions().c_str();
8373 if (supports_post_sub_buffer_
)
8374 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8375 str
= extensions
.c_str();
8381 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8382 bucket
->SetFromString(str
);
8383 return error::kNoError
;
8386 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8387 const void* cmd_data
) {
8388 const gles2::cmds::BufferData
& c
=
8389 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8390 GLenum target
= static_cast<GLenum
>(c
.target
);
8391 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8392 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8393 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8394 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8395 const void* data
= NULL
;
8396 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8397 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8399 return error::kOutOfBounds
;
8402 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8403 return error::kNoError
;
8406 void GLES2DecoderImpl::DoBufferSubData(
8407 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8408 // Just delegate it. Some validation is actually done before this.
8409 buffer_manager()->ValidateAndDoBufferSubData(
8410 &state_
, target
, offset
, size
, data
);
8413 bool GLES2DecoderImpl::ClearLevel(
8417 unsigned internal_format
,
8422 bool is_texture_immutable
) {
8423 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8424 if (feature_info_
->feature_flags().angle_depth_texture
&&
8425 (channels
& GLES2Util::kDepth
) != 0) {
8426 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8427 // on depth formats.
8429 glGenFramebuffersEXT(1, &fb
);
8430 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8432 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8433 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8434 GL_DEPTH_ATTACHMENT
;
8436 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8437 texture
->service_id(), level
);
8438 // ANGLE promises a depth only attachment ok.
8439 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8440 GL_FRAMEBUFFER_COMPLETE
) {
8444 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8445 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8447 state_
.SetDeviceDepthMask(GL_TRUE
);
8448 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8449 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8451 RestoreClearState();
8453 glDeleteFramebuffersEXT(1, &fb
);
8454 Framebuffer
* framebuffer
=
8455 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8456 GLuint fb_service_id
=
8457 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8458 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8462 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8465 uint32 padded_row_size
;
8466 if (!GLES2Util::ComputeImageDataSizes(
8467 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8468 NULL
, &padded_row_size
)) {
8472 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8476 if (size
> kMaxZeroSize
) {
8477 if (kMaxZeroSize
< padded_row_size
) {
8478 // That'd be an awfully large texture.
8481 // We should never have a large total size with a zero row size.
8482 DCHECK_GT(padded_row_size
, 0U);
8483 tile_height
= kMaxZeroSize
/ padded_row_size
;
8484 if (!GLES2Util::ComputeImageDataSizes(
8485 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8490 tile_height
= height
;
8493 // Assumes the size has already been checked.
8494 scoped_ptr
<char[]> zero(new char[size
]);
8495 memset(zero
.get(), 0, size
);
8496 glBindTexture(texture
->target(), texture
->service_id());
8498 bool has_images
= texture
->HasImages();
8500 while (y
< height
) {
8501 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8502 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8503 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8506 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8511 TextureRef
* bound_texture
=
8512 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8513 glBindTexture(texture
->target(),
8514 bound_texture
? bound_texture
->service_id() : 0);
8520 const int kS3TCBlockWidth
= 4;
8521 const int kS3TCBlockHeight
= 4;
8522 const int kS3TCDXT1BlockSize
= 8;
8523 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8525 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8526 return (size
== 1) ||
8527 (size
== 2) || !(size
% kS3TCBlockWidth
);
8530 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8531 return GLES2Util::IsPOT(size
);
8534 } // anonymous namespace.
8536 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8537 const char* function_name
,
8538 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
8539 unsigned int bytes_required
= 0;
8542 case GL_ATC_RGB_AMD
:
8543 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8544 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8545 case GL_ETC1_RGB8_OES
: {
8546 int num_blocks_across
=
8547 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8548 int num_blocks_down
=
8549 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8550 int num_blocks
= num_blocks_across
* num_blocks_down
;
8551 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
8554 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8555 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8556 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8557 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8558 int num_blocks_across
=
8559 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8560 int num_blocks_down
=
8561 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8562 int num_blocks
= num_blocks_across
* num_blocks_down
;
8563 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
8566 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8567 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
8568 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
8571 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8572 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8573 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
8577 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8581 if (size
!= bytes_required
) {
8583 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8590 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8591 const char* function_name
,
8592 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
8594 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8595 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8596 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8597 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8598 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8600 GL_INVALID_OPERATION
, function_name
,
8601 "width or height invalid for level");
8606 case GL_ATC_RGB_AMD
:
8607 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8608 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8609 case GL_ETC1_RGB8_OES
: {
8610 if (width
<= 0 || height
<= 0) {
8612 GL_INVALID_OPERATION
, function_name
,
8613 "width or height invalid for level");
8618 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8619 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8620 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8621 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8622 if (!IsValidPVRTCSize(level
, width
) ||
8623 !IsValidPVRTCSize(level
, height
)) {
8625 GL_INVALID_OPERATION
, function_name
,
8626 "width or height invalid for level");
8636 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8637 const char* function_name
,
8638 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8639 GLsizei width
, GLsizei height
, GLenum format
,
8641 if (xoffset
< 0 || yoffset
< 0) {
8643 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8648 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8649 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8650 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8651 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8652 const int kBlockWidth
= 4;
8653 const int kBlockHeight
= 4;
8654 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8656 GL_INVALID_OPERATION
, function_name
,
8657 "xoffset or yoffset not multiple of 4");
8660 GLsizei tex_width
= 0;
8661 GLsizei tex_height
= 0;
8662 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8663 width
- xoffset
> tex_width
||
8664 height
- yoffset
> tex_height
) {
8666 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8669 return ValidateCompressedTexDimensions(
8670 function_name
, level
, width
, height
, format
);
8672 case GL_ATC_RGB_AMD
:
8673 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8674 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8676 GL_INVALID_OPERATION
, function_name
,
8677 "not supported for ATC textures");
8680 case GL_ETC1_RGB8_OES
: {
8682 GL_INVALID_OPERATION
, function_name
,
8683 "not supported for ECT1_RGB8_OES textures");
8686 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8687 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8688 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8689 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8690 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8692 GL_INVALID_OPERATION
, function_name
,
8693 "xoffset and yoffset must be zero");
8696 GLsizei tex_width
= 0;
8697 GLsizei tex_height
= 0;
8698 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8699 width
!= tex_width
||
8700 height
!= tex_height
) {
8702 GL_INVALID_OPERATION
, function_name
,
8703 "dimensions must match existing texture level dimensions");
8706 return ValidateCompressedTexDimensions(
8707 function_name
, level
, width
, height
, format
);
8714 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8717 GLenum internal_format
,
8723 // TODO(gman): Validate image_size is correct for width, height and format.
8724 if (!validators_
->texture_target
.IsValid(target
)) {
8725 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8726 "glCompressedTexImage2D", target
, "target");
8727 return error::kNoError
;
8729 if (!validators_
->compressed_texture_format
.IsValid(
8731 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8732 "glCompressedTexImage2D", internal_format
, "internal_format");
8733 return error::kNoError
;
8735 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8739 "glCompressedTexImage2D", "dimensions out of range");
8740 return error::kNoError
;
8742 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8747 "glCompressedTexImage2D", "unknown texture target");
8748 return error::kNoError
;
8750 Texture
* texture
= texture_ref
->texture();
8751 if (texture
->IsImmutable()) {
8753 GL_INVALID_OPERATION
,
8754 "glCompressedTexImage2D", "texture is immutable");
8755 return error::kNoError
;
8758 if (!ValidateCompressedTexDimensions(
8759 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8760 !ValidateCompressedTexFuncData(
8761 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8762 return error::kNoError
;
8765 if (!EnsureGPUMemoryAvailable(image_size
)) {
8767 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8768 return error::kNoError
;
8771 if (texture
->IsAttachedToFramebuffer()) {
8772 framebuffer_state_
.clear_state_dirty
= true;
8775 scoped_ptr
<int8
[]> zero
;
8777 zero
.reset(new int8
[image_size
]);
8778 memset(zero
.get(), 0, image_size
);
8781 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8782 glCompressedTexImage2D(
8783 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8784 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8785 if (error
== GL_NO_ERROR
) {
8786 texture_manager()->SetLevelInfo(
8787 texture_ref
, target
, level
, internal_format
,
8788 width
, height
, 1, border
, 0, 0, true);
8791 // This may be a slow command. Exit command processing to allow for
8792 // context preemption and GPU watchdog checks.
8793 ExitCommandProcessingEarly();
8794 return error::kNoError
;
8797 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8798 uint32 immediate_data_size
,
8799 const void* cmd_data
) {
8800 const gles2::cmds::CompressedTexImage2D
& c
=
8801 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
8802 GLenum target
= static_cast<GLenum
>(c
.target
);
8803 GLint level
= static_cast<GLint
>(c
.level
);
8804 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8805 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8806 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8807 GLint border
= static_cast<GLint
>(c
.border
);
8808 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8809 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8810 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8811 const void* data
= NULL
;
8812 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8813 data
= GetSharedMemoryAs
<const void*>(
8814 data_shm_id
, data_shm_offset
, image_size
);
8816 return error::kOutOfBounds
;
8819 return DoCompressedTexImage2D(
8820 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8823 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8824 uint32 immediate_data_size
,
8825 const void* cmd_data
) {
8826 const gles2::cmds::CompressedTexImage2DBucket
& c
=
8827 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
8828 GLenum target
= static_cast<GLenum
>(c
.target
);
8829 GLint level
= static_cast<GLint
>(c
.level
);
8830 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8831 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8832 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8833 GLint border
= static_cast<GLint
>(c
.border
);
8834 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8836 return error::kInvalidArguments
;
8838 uint32 data_size
= bucket
->size();
8839 GLsizei imageSize
= data_size
;
8840 const void* data
= bucket
->GetData(0, data_size
);
8842 return error::kInvalidArguments
;
8844 return DoCompressedTexImage2D(
8845 target
, level
, internal_format
, width
, height
, border
,
8849 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8850 uint32 immediate_data_size
,
8851 const void* cmd_data
) {
8852 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
8853 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
8854 GLenum target
= static_cast<GLenum
>(c
.target
);
8855 GLint level
= static_cast<GLint
>(c
.level
);
8856 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8857 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8858 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8859 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8860 GLenum format
= static_cast<GLenum
>(c
.format
);
8861 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8863 return error::kInvalidArguments
;
8865 uint32 data_size
= bucket
->size();
8866 GLsizei imageSize
= data_size
;
8867 const void* data
= bucket
->GetData(0, data_size
);
8869 return error::kInvalidArguments
;
8871 if (!validators_
->texture_target
.IsValid(target
)) {
8873 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8874 return error::kNoError
;
8876 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8877 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8878 "glCompressedTexSubImage2D", format
, "format");
8879 return error::kNoError
;
8883 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8884 return error::kNoError
;
8888 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8889 return error::kNoError
;
8891 if (imageSize
< 0) {
8893 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8894 return error::kNoError
;
8896 DoCompressedTexSubImage2D(
8897 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8898 return error::kNoError
;
8901 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
8902 const void* cmd_data
) {
8903 const gles2::cmds::TexImage2D
& c
=
8904 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
8905 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8906 "width", c
.width
, "height", c
.height
);
8907 // Set as failed for now, but if it successed, this will be set to not failed.
8908 texture_state_
.tex_image_2d_failed
= true;
8909 GLenum target
= static_cast<GLenum
>(c
.target
);
8910 GLint level
= static_cast<GLint
>(c
.level
);
8911 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8912 // for internalformat.
8913 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8914 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8915 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8916 GLint border
= static_cast<GLint
>(c
.border
);
8917 GLenum format
= static_cast<GLenum
>(c
.format
);
8918 GLenum type
= static_cast<GLenum
>(c
.type
);
8919 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8920 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8922 if (!GLES2Util::ComputeImageDataSizes(
8923 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8925 return error::kOutOfBounds
;
8927 const void* pixels
= NULL
;
8928 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8929 pixels
= GetSharedMemoryAs
<const void*>(
8930 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8932 return error::kOutOfBounds
;
8936 TextureManager::DoTextImage2DArguments args
= {
8937 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8938 pixels
, pixels_size
};
8939 texture_manager()->ValidateAndDoTexImage2D(
8940 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8942 // This may be a slow command. Exit command processing to allow for
8943 // context preemption and GPU watchdog checks.
8944 ExitCommandProcessingEarly();
8945 return error::kNoError
;
8948 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
8949 const void* cmd_data
) {
8950 // TODO(zmo): Unsafe ES3 API.
8951 if (!unsafe_es3_apis_enabled())
8952 return error::kUnknownCommand
;
8954 const gles2::cmds::TexImage3D
& c
=
8955 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
8956 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
8957 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
8958 GLenum target
= static_cast<GLenum
>(c
.target
);
8959 GLint level
= static_cast<GLint
>(c
.level
);
8960 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8961 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8962 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8963 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
8964 GLint border
= static_cast<GLint
>(c
.border
);
8965 GLenum format
= static_cast<GLenum
>(c
.format
);
8966 GLenum type
= static_cast<GLenum
>(c
.type
);
8967 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8968 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8970 if (!GLES2Util::ComputeImageDataSizes(
8971 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8973 return error::kOutOfBounds
;
8975 const void* pixels
= NULL
;
8976 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8977 pixels
= GetSharedMemoryAs
<const void*>(
8978 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8980 return error::kOutOfBounds
;
8984 glTexImage3D(target
, level
, internal_format
, width
, height
, depth
, border
,
8985 format
, type
, pixels
);
8987 // This may be a slow command. Exit command processing to allow for
8988 // context preemption and GPU watchdog checks.
8989 ExitCommandProcessingEarly();
8990 return error::kNoError
;
8993 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9002 const void * data
) {
9003 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9007 GL_INVALID_OPERATION
,
9008 "glCompressedTexSubImage2D", "unknown texture for target");
9011 Texture
* texture
= texture_ref
->texture();
9013 GLenum internal_format
= 0;
9014 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9016 GL_INVALID_OPERATION
,
9017 "glCompressedTexSubImage2D", "level does not exist.");
9020 if (internal_format
!= format
) {
9022 GL_INVALID_OPERATION
,
9023 "glCompressedTexSubImage2D", "format does not match internal format.");
9026 if (!texture
->ValidForTexture(
9027 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9029 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9033 if (!ValidateCompressedTexFuncData(
9034 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
9035 !ValidateCompressedTexSubDimensions(
9036 "glCompressedTexSubImage2D",
9037 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
9042 // Note: There is no need to deal with texture cleared tracking here
9043 // because the validation above means you can only get here if the level
9044 // is already a matching compressed format and in that case
9045 // CompressedTexImage2D already cleared the texture.
9046 glCompressedTexSubImage2D(
9047 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9049 // This may be a slow command. Exit command processing to allow for
9050 // context preemption and GPU watchdog checks.
9051 ExitCommandProcessingEarly();
9055 GLint start
, GLint range
, GLint sourceRange
,
9056 GLint
* out_start
, GLint
* out_range
) {
9063 GLint end
= start
+ range
;
9064 if (end
> sourceRange
) {
9065 range
-= end
- sourceRange
;
9071 void GLES2DecoderImpl::DoCopyTexImage2D(
9074 GLenum internal_format
,
9080 DCHECK(!ShouldDeferReads());
9081 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9085 GL_INVALID_OPERATION
,
9086 "glCopyTexImage2D", "unknown texture for target");
9089 Texture
* texture
= texture_ref
->texture();
9090 if (texture
->IsImmutable()) {
9092 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9095 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9098 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9101 if (!texture_manager()->ValidateFormatAndTypeCombination(
9102 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9103 GL_UNSIGNED_BYTE
)) {
9107 // Check we have compatible formats.
9108 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9109 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9110 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9112 if ((channels_needed
& channels_exist
) != channels_needed
) {
9114 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9118 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9120 GL_INVALID_OPERATION
,
9121 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9125 uint32 estimated_size
= 0;
9126 if (!GLES2Util::ComputeImageDataSizes(
9127 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9128 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9130 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9134 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9135 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9139 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9143 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9145 GL_INVALID_OPERATION
,
9146 "glCopyTexImage2D", "source and destination textures are the same");
9150 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9154 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9155 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9156 gfx::Size size
= GetBoundReadFrameBufferSize();
9158 if (texture
->IsAttachedToFramebuffer()) {
9159 framebuffer_state_
.clear_state_dirty
= true;
9162 // Clip to size to source dimensions
9165 GLint copyWidth
= 0;
9166 GLint copyHeight
= 0;
9167 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9168 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9172 copyWidth
!= width
||
9173 copyHeight
!= height
) {
9174 // some part was clipped so clear the texture.
9175 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9176 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9178 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9181 if (copyHeight
> 0 && copyWidth
> 0) {
9182 GLint dx
= copyX
- x
;
9183 GLint dy
= copyY
- y
;
9186 ScopedModifyPixels
modify(texture_ref
);
9187 glCopyTexSubImage2D(target
, level
,
9188 destX
, destY
, copyX
, copyY
,
9189 copyWidth
, copyHeight
);
9192 ScopedModifyPixels
modify(texture_ref
);
9193 glCopyTexImage2D(target
, level
, internal_format
,
9194 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9196 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9197 if (error
== GL_NO_ERROR
) {
9198 texture_manager()->SetLevelInfo(
9199 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
9200 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
9203 // This may be a slow command. Exit command processing to allow for
9204 // context preemption and GPU watchdog checks.
9205 ExitCommandProcessingEarly();
9208 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9217 DCHECK(!ShouldDeferReads());
9218 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9222 GL_INVALID_OPERATION
,
9223 "glCopyTexSubImage2D", "unknown texture for target");
9226 Texture
* texture
= texture_ref
->texture();
9229 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
9230 !texture
->ValidForTexture(
9231 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9233 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
9236 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9238 GL_INVALID_OPERATION
,
9239 "glCopyTexSubImage2D", "async upload pending for texture");
9243 // Check we have compatible formats.
9244 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9245 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9246 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
9248 if (!channels_needed
||
9249 (channels_needed
& channels_exist
) != channels_needed
) {
9251 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
9255 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9257 GL_INVALID_OPERATION
,
9258 "glCopySubImage2D", "can not be used with depth or stencil textures");
9262 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9266 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9268 GL_INVALID_OPERATION
,
9269 "glCopyTexSubImage2D", "source and destination textures are the same");
9273 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9277 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9278 gfx::Size size
= GetBoundReadFrameBufferSize();
9281 GLint copyWidth
= 0;
9282 GLint copyHeight
= 0;
9283 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9284 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9286 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
9287 height
!= size
.height()) {
9288 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
9290 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
9291 "dimensions too big");
9295 // Write all pixels in below.
9296 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9301 copyWidth
!= width
||
9302 copyHeight
!= height
) {
9303 // some part was clipped so clear the sub rect.
9304 uint32 pixels_size
= 0;
9305 if (!GLES2Util::ComputeImageDataSizes(
9306 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9309 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
9312 scoped_ptr
<char[]> zero(new char[pixels_size
]);
9313 memset(zero
.get(), 0, pixels_size
);
9314 ScopedModifyPixels
modify(texture_ref
);
9316 target
, level
, xoffset
, yoffset
, width
, height
,
9317 format
, type
, zero
.get());
9320 if (copyHeight
> 0 && copyWidth
> 0) {
9321 GLint dx
= copyX
- x
;
9322 GLint dy
= copyY
- y
;
9323 GLint destX
= xoffset
+ dx
;
9324 GLint destY
= yoffset
+ dy
;
9325 ScopedModifyPixels
modify(texture_ref
);
9326 glCopyTexSubImage2D(target
, level
,
9327 destX
, destY
, copyX
, copyY
,
9328 copyWidth
, copyHeight
);
9331 // This may be a slow command. Exit command processing to allow for
9332 // context preemption and GPU watchdog checks.
9333 ExitCommandProcessingEarly();
9336 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9337 error::Error
* error
,
9338 const char* function_name
,
9347 const void * data
) {
9348 (*error
) = error::kNoError
;
9349 if (!validators_
->texture_target
.IsValid(target
)) {
9350 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
9354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
9358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
9361 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9365 GL_INVALID_OPERATION
,
9366 function_name
, "unknown texture for target");
9369 Texture
* texture
= texture_ref
->texture();
9370 GLenum current_type
= 0;
9371 GLenum internal_format
= 0;
9372 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
9374 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
9377 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
9378 function_name
, format
, type
, internal_format
, level
)) {
9381 if (type
!= current_type
) {
9383 GL_INVALID_OPERATION
,
9384 function_name
, "type does not match type of texture.");
9387 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9389 GL_INVALID_OPERATION
,
9390 function_name
, "async upload pending for texture");
9393 if (!texture
->ValidForTexture(
9394 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9395 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
9398 if ((GLES2Util::GetChannelsForFormat(format
) &
9399 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9401 GL_INVALID_OPERATION
,
9402 function_name
, "can not supply data for depth or stencil textures");
9406 (*error
) = error::kOutOfBounds
;
9412 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
9421 const void * data
) {
9422 error::Error error
= error::kNoError
;
9423 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
9424 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
9427 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9429 Texture
* texture
= texture_ref
->texture();
9430 GLsizei tex_width
= 0;
9431 GLsizei tex_height
= 0;
9432 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
9434 if (xoffset
!= 0 || yoffset
!= 0 ||
9435 width
!= tex_width
|| height
!= tex_height
) {
9436 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
9439 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
9440 return error::kNoError
;
9442 ScopedTextureUploadTimer
timer(&texture_state_
);
9444 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9445 return error::kNoError
;
9448 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
9449 !texture
->IsImmutable() &&
9450 !texture
->HasImages()) {
9451 ScopedTextureUploadTimer
timer(&texture_state_
);
9452 GLenum internal_format
;
9454 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
9455 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9458 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
9460 ScopedTextureUploadTimer
timer(&texture_state_
);
9462 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9464 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9466 // This may be a slow command. Exit command processing to allow for
9467 // context preemption and GPU watchdog checks.
9468 ExitCommandProcessingEarly();
9469 return error::kNoError
;
9472 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
9473 const void* cmd_data
) {
9474 const gles2::cmds::TexSubImage2D
& c
=
9475 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
9476 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9477 "width", c
.width
, "height", c
.height
);
9478 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
9479 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
9480 return error::kNoError
;
9482 GLenum target
= static_cast<GLenum
>(c
.target
);
9483 GLint level
= static_cast<GLint
>(c
.level
);
9484 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9485 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9486 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9487 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9488 GLenum format
= static_cast<GLenum
>(c
.format
);
9489 GLenum type
= static_cast<GLenum
>(c
.type
);
9491 if (!GLES2Util::ComputeImageDataSizes(
9492 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
9494 return error::kOutOfBounds
;
9496 const void* pixels
= GetSharedMemoryAs
<const void*>(
9497 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9498 return DoTexSubImage2D(
9499 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
9502 // TODO(zmo): Remove the below stub once we add the real function binding.
9503 // Currently it's missing due to a gmock limitation.
9504 static void glTexSubImage3D(
9505 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9506 GLsizei height
, GLsizei width
, GLsizei depth
, GLenum format
, GLenum type
,
9507 const void* pixels
) {
9511 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
9512 const void* cmd_data
) {
9513 // TODO(zmo): Unsafe ES3 API.
9514 if (!unsafe_es3_apis_enabled())
9515 return error::kUnknownCommand
;
9517 const gles2::cmds::TexSubImage3D
& c
=
9518 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
9519 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9520 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9521 GLenum target
= static_cast<GLenum
>(c
.target
);
9522 GLint level
= static_cast<GLint
>(c
.level
);
9523 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9524 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9525 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9526 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9527 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9528 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9529 GLenum format
= static_cast<GLenum
>(c
.format
);
9530 GLenum type
= static_cast<GLenum
>(c
.type
);
9532 if (!GLES2Util::ComputeImageDataSizes(
9533 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
9535 return error::kOutOfBounds
;
9537 const void* pixels
= GetSharedMemoryAs
<const void*>(
9538 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9539 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
9540 depth
, format
, type
, pixels
);
9541 return error::kNoError
;
9544 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9545 uint32 immediate_data_size
,
9546 const void* cmd_data
) {
9547 const gles2::cmds::GetVertexAttribPointerv
& c
=
9548 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
9549 GLuint index
= static_cast<GLuint
>(c
.index
);
9550 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9551 typedef cmds::GetVertexAttribPointerv::Result Result
;
9552 Result
* result
= GetSharedMemoryAs
<Result
*>(
9553 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
9555 return error::kOutOfBounds
;
9557 // Check that the client initialized the result.
9558 if (result
->size
!= 0) {
9559 return error::kInvalidArguments
;
9561 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
9562 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9563 "glGetVertexAttribPointerv", pname
, "pname");
9564 return error::kNoError
;
9566 if (index
>= group_
->max_vertex_attribs()) {
9568 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
9569 return error::kNoError
;
9571 result
->SetNumResults(1);
9572 *result
->GetData() =
9573 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
9574 return error::kNoError
;
9577 bool GLES2DecoderImpl::GetUniformSetup(
9578 GLuint program_id
, GLint fake_location
,
9579 uint32 shm_id
, uint32 shm_offset
,
9580 error::Error
* error
, GLint
* real_location
,
9581 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
9584 DCHECK(result_pointer
);
9585 DCHECK(result_type
);
9586 DCHECK(real_location
);
9587 *error
= error::kNoError
;
9588 // Make sure we have enough room for the result on failure.
9589 SizedResult
<GLint
>* result
;
9590 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9591 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
9593 *error
= error::kOutOfBounds
;
9596 *result_pointer
= result
;
9597 // Set the result size to 0 so the client does not have to check for success.
9598 result
->SetNumResults(0);
9599 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
9603 if (!program
->IsValid()) {
9604 // Program was not linked successfully. (ie, glLinkProgram)
9606 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
9609 *service_id
= program
->service_id();
9610 GLint array_index
= -1;
9611 const Program::UniformInfo
* uniform_info
=
9612 program
->GetUniformInfoByFakeLocation(
9613 fake_location
, real_location
, &array_index
);
9614 if (!uniform_info
) {
9615 // No such location.
9617 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
9620 GLenum type
= uniform_info
->type
;
9621 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
9623 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
9626 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9627 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
9629 *error
= error::kOutOfBounds
;
9632 result
->size
= size
;
9633 *result_type
= type
;
9637 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
9638 const void* cmd_data
) {
9639 const gles2::cmds::GetUniformiv
& c
=
9640 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
9641 GLuint program
= c
.program
;
9642 GLint fake_location
= c
.location
;
9645 GLint real_location
= -1;
9648 if (GetUniformSetup(
9649 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9650 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
9652 service_id
, real_location
,
9653 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
9658 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
9659 const void* cmd_data
) {
9660 const gles2::cmds::GetUniformfv
& c
=
9661 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
9662 GLuint program
= c
.program
;
9663 GLint fake_location
= c
.location
;
9665 GLint real_location
= -1;
9667 typedef cmds::GetUniformfv::Result Result
;
9670 if (GetUniformSetup(
9671 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9672 &error
, &real_location
, &service_id
,
9673 reinterpret_cast<void**>(&result
), &result_type
)) {
9674 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
9675 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
9676 GLsizei num_values
= result
->GetNumResults();
9677 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
9678 glGetUniformiv(service_id
, real_location
, temp
.get());
9679 GLfloat
* dst
= result
->GetData();
9680 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
9681 dst
[ii
] = (temp
[ii
] != 0);
9684 glGetUniformfv(service_id
, real_location
, result
->GetData());
9690 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9691 uint32 immediate_data_size
,
9692 const void* cmd_data
) {
9693 const gles2::cmds::GetShaderPrecisionFormat
& c
=
9694 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
9695 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
9696 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
9697 typedef cmds::GetShaderPrecisionFormat::Result Result
;
9698 Result
* result
= GetSharedMemoryAs
<Result
*>(
9699 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9701 return error::kOutOfBounds
;
9703 // Check that the client initialized the result.
9704 if (result
->success
!= 0) {
9705 return error::kInvalidArguments
;
9707 if (!validators_
->shader_type
.IsValid(shader_type
)) {
9708 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9709 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
9710 return error::kNoError
;
9712 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
9713 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9714 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
9715 return error::kNoError
;
9718 result
->success
= 1; // true
9720 GLint range
[2] = { 0, 0 };
9721 GLint precision
= 0;
9722 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
9724 result
->min_range
= range
[0];
9725 result
->max_range
= range
[1];
9726 result
->precision
= precision
;
9728 return error::kNoError
;
9731 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
9732 uint32 immediate_data_size
,
9733 const void* cmd_data
) {
9734 const gles2::cmds::GetAttachedShaders
& c
=
9735 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
9736 uint32 result_size
= c
.result_size
;
9737 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9738 Program
* program
= GetProgramInfoNotShader(
9739 program_id
, "glGetAttachedShaders");
9741 return error::kNoError
;
9743 typedef cmds::GetAttachedShaders::Result Result
;
9744 uint32 max_count
= Result::ComputeMaxResults(result_size
);
9745 Result
* result
= GetSharedMemoryAs
<Result
*>(
9746 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
9748 return error::kOutOfBounds
;
9750 // Check that the client initialized the result.
9751 if (result
->size
!= 0) {
9752 return error::kInvalidArguments
;
9755 glGetAttachedShaders(
9756 program
->service_id(), max_count
, &count
, result
->GetData());
9757 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
9758 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
9759 &result
->GetData()[ii
])) {
9761 return error::kGenericError
;
9764 result
->SetNumResults(count
);
9765 return error::kNoError
;
9768 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
9769 uint32 immediate_data_size
,
9770 const void* cmd_data
) {
9771 const gles2::cmds::GetActiveUniform
& c
=
9772 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
9773 GLuint program_id
= c
.program
;
9774 GLuint index
= c
.index
;
9775 uint32 name_bucket_id
= c
.name_bucket_id
;
9776 typedef cmds::GetActiveUniform::Result Result
;
9777 Result
* result
= GetSharedMemoryAs
<Result
*>(
9778 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9780 return error::kOutOfBounds
;
9782 // Check that the client initialized the result.
9783 if (result
->success
!= 0) {
9784 return error::kInvalidArguments
;
9786 Program
* program
= GetProgramInfoNotShader(
9787 program_id
, "glGetActiveUniform");
9789 return error::kNoError
;
9791 const Program::UniformInfo
* uniform_info
=
9792 program
->GetUniformInfo(index
);
9793 if (!uniform_info
) {
9795 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
9796 return error::kNoError
;
9798 result
->success
= 1; // true.
9799 result
->size
= uniform_info
->size
;
9800 result
->type
= uniform_info
->type
;
9801 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9802 bucket
->SetFromString(uniform_info
->name
.c_str());
9803 return error::kNoError
;
9806 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
9807 uint32 immediate_data_size
, const void* cmd_data
) {
9808 if (!unsafe_es3_apis_enabled())
9809 return error::kUnknownCommand
;
9810 const gles2::cmds::GetActiveUniformBlockiv
& c
=
9811 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
9812 GLuint program_id
= c
.program
;
9813 GLuint index
= static_cast<GLuint
>(c
.index
);
9814 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9815 Program
* program
= GetProgramInfoNotShader(
9816 program_id
, "glGetActiveUniformBlockiv");
9818 return error::kNoError
;
9820 GLuint service_id
= program
->service_id();
9821 GLint link_status
= GL_FALSE
;
9822 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9823 if (link_status
!= GL_TRUE
) {
9824 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9825 "glGetActiveActiveUniformBlockiv", "program not linked");
9826 return error::kNoError
;
9828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
9829 GLsizei num_values
= 1;
9830 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
9832 glGetActiveUniformBlockiv(
9833 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
9834 GLenum error
= glGetError();
9835 if (error
!= GL_NO_ERROR
) {
9836 // Assume this will the same error if calling with pname.
9837 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
9838 return error::kNoError
;
9840 num_values
= static_cast<GLsizei
>(num
);
9842 typedef cmds::GetActiveUniformBlockiv::Result Result
;
9843 Result
* result
= GetSharedMemoryAs
<Result
*>(
9844 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
9845 GLint
* params
= result
? result
->GetData() : NULL
;
9846 if (params
== NULL
) {
9847 return error::kOutOfBounds
;
9849 // Check that the client initialized the result.
9850 if (result
->size
!= 0) {
9851 return error::kInvalidArguments
;
9853 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
9854 GLenum error
= glGetError();
9855 if (error
== GL_NO_ERROR
) {
9856 result
->SetNumResults(num_values
);
9858 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
9860 return error::kNoError
;
9863 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
9864 uint32 immediate_data_size
, const void* cmd_data
) {
9865 if (!unsafe_es3_apis_enabled())
9866 return error::kUnknownCommand
;
9867 const gles2::cmds::GetActiveUniformBlockName
& c
=
9868 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
9869 GLuint program_id
= c
.program
;
9870 GLuint index
= c
.index
;
9871 uint32 name_bucket_id
= c
.name_bucket_id
;
9872 typedef cmds::GetActiveUniformBlockName::Result Result
;
9873 Result
* result
= GetSharedMemoryAs
<Result
*>(
9874 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9876 return error::kOutOfBounds
;
9878 // Check that the client initialized the result.
9880 return error::kInvalidArguments
;
9882 Program
* program
= GetProgramInfoNotShader(
9883 program_id
, "glGetActiveUniformBlockName");
9885 return error::kNoError
;
9887 GLuint service_id
= program
->service_id();
9888 GLint link_status
= GL_FALSE
;
9889 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9890 if (link_status
!= GL_TRUE
) {
9891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9892 "glGetActiveActiveUniformBlockName", "program not linked");
9893 return error::kNoError
;
9895 GLint max_length
= 0;
9897 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
9898 // Increase one so &buffer[0] is always valid.
9899 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
9900 std::vector
<char> buffer(buf_size
);
9902 glGetActiveUniformBlockName(
9903 service_id
, index
, buf_size
, &length
, &buffer
[0]);
9906 return error::kNoError
;
9909 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9910 DCHECK_GT(buf_size
, length
);
9911 DCHECK_EQ(0, buffer
[length
]);
9912 bucket
->SetFromString(&buffer
[0]);
9913 return error::kNoError
;
9916 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
9917 uint32 immediate_data_size
, const void* cmd_data
) {
9918 if (!unsafe_es3_apis_enabled())
9919 return error::kUnknownCommand
;
9920 const gles2::cmds::GetActiveUniformsiv
& c
=
9921 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
9922 GLuint program_id
= c
.program
;
9923 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9924 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
9926 return error::kInvalidArguments
;
9928 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
9929 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
9930 typedef cmds::GetActiveUniformsiv::Result Result
;
9931 Result
* result
= GetSharedMemoryAs
<Result
*>(
9932 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
9933 GLint
* params
= result
? result
->GetData() : NULL
;
9934 if (params
== NULL
) {
9935 return error::kOutOfBounds
;
9937 // Check that the client initialized the result.
9938 if (result
->size
!= 0) {
9939 return error::kInvalidArguments
;
9941 Program
* program
= GetProgramInfoNotShader(
9942 program_id
, "glGetActiveUniformsiv");
9944 return error::kNoError
;
9946 GLuint service_id
= program
->service_id();
9947 GLint link_status
= GL_FALSE
;
9948 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9949 if (link_status
!= GL_TRUE
) {
9950 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9951 "glGetActiveUniformsiv", "program not linked");
9952 return error::kNoError
;
9954 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
9955 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
9956 GLenum error
= glGetError();
9957 if (error
== GL_NO_ERROR
) {
9958 result
->SetNumResults(count
);
9960 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
9962 return error::kNoError
;
9965 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
9966 const void* cmd_data
) {
9967 const gles2::cmds::GetActiveAttrib
& c
=
9968 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
9969 GLuint program_id
= c
.program
;
9970 GLuint index
= c
.index
;
9971 uint32 name_bucket_id
= c
.name_bucket_id
;
9972 typedef cmds::GetActiveAttrib::Result Result
;
9973 Result
* result
= GetSharedMemoryAs
<Result
*>(
9974 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9976 return error::kOutOfBounds
;
9978 // Check that the client initialized the result.
9979 if (result
->success
!= 0) {
9980 return error::kInvalidArguments
;
9982 Program
* program
= GetProgramInfoNotShader(
9983 program_id
, "glGetActiveAttrib");
9985 return error::kNoError
;
9987 const Program::VertexAttrib
* attrib_info
=
9988 program
->GetAttribInfo(index
);
9991 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9992 return error::kNoError
;
9994 result
->success
= 1; // true.
9995 result
->size
= attrib_info
->size
;
9996 result
->type
= attrib_info
->type
;
9997 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9998 bucket
->SetFromString(attrib_info
->name
.c_str());
9999 return error::kNoError
;
10002 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10003 const void* cmd_data
) {
10004 #if 1 // No binary shader support.
10005 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10006 return error::kNoError
;
10008 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10010 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10011 return error::kNoError
;
10013 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10016 return error::kNoError
;
10019 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10020 return error::kOutOfBounds
;
10022 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10023 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10024 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10025 const void* binary
= GetSharedMemoryAs
<const void*>(
10026 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10027 if (shaders
== NULL
|| binary
== NULL
) {
10028 return error::kOutOfBounds
;
10030 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10031 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10032 Shader
* shader
= GetShader(shaders
[ii
]);
10034 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10035 return error::kNoError
;
10037 service_ids
[ii
] = shader
->service_id();
10039 // TODO(gman): call glShaderBinary
10040 return error::kNoError
;
10044 void GLES2DecoderImpl::DoSwapBuffers() {
10045 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10047 int this_frame_number
= frame_number_
++;
10048 // TRACE_EVENT for gpu tests:
10049 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10050 TRACE_EVENT_SCOPE_THREAD
,
10051 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10052 "width", (is_offscreen
? offscreen_size_
.width() :
10053 surface_
->GetSize().width()));
10054 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10055 "offscreen", is_offscreen
,
10056 "frame", this_frame_number
);
10058 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10061 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10062 "gpu_toplevel", "SwapBuffer");
10065 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10068 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10069 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10070 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10073 // If offscreen then don't actually SwapBuffers to the display. Just copy
10074 // the rendered frame to another frame buffer.
10075 if (is_offscreen
) {
10076 TRACE_EVENT2("gpu", "Offscreen",
10077 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10078 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10079 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10080 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10082 if (workarounds().needs_offscreen_buffer_workaround
) {
10083 offscreen_saved_frame_buffer_
->Create();
10087 // Allocate the offscreen saved color texture.
10088 DCHECK(offscreen_saved_color_format_
);
10089 offscreen_saved_color_texture_
->AllocateStorage(
10090 offscreen_size_
, offscreen_saved_color_format_
, false);
10092 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10093 offscreen_saved_color_texture_
.get());
10094 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10095 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10096 GL_FRAMEBUFFER_COMPLETE
) {
10097 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10098 << "because offscreen saved FBO was incomplete.";
10099 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10103 // Clear the offscreen color texture.
10104 // TODO(piman): Is this still necessary?
10106 ScopedFrameBufferBinder
binder(this,
10107 offscreen_saved_frame_buffer_
->id());
10108 glClearColor(0, 0, 0, 0);
10109 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10110 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10111 glClear(GL_COLOR_BUFFER_BIT
);
10112 RestoreClearState();
10116 UpdateParentTextureInfo();
10119 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10121 ScopedGLErrorSuppressor
suppressor(
10122 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10124 if (IsOffscreenBufferMultisampled()) {
10125 // For multisampled buffers, resolve the frame buffer.
10126 ScopedResolvedFrameBufferBinder
binder(this, true, false);
10128 ScopedFrameBufferBinder
binder(this,
10129 offscreen_target_frame_buffer_
->id());
10131 if (offscreen_target_buffer_preserved_
) {
10132 // Copy the target frame buffer to the saved offscreen texture.
10133 offscreen_saved_color_texture_
->Copy(
10134 offscreen_saved_color_texture_
->size(),
10135 offscreen_saved_color_format_
);
10137 // Flip the textures in the parent context via the texture manager.
10138 if (!!offscreen_saved_color_texture_info_
.get())
10139 offscreen_saved_color_texture_info_
->texture()->
10140 SetServiceId(offscreen_target_color_texture_
->id());
10142 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
10143 offscreen_target_frame_buffer_
->AttachRenderTexture(
10144 offscreen_target_color_texture_
.get());
10147 // Ensure the side effects of the copy are visible to the parent
10148 // context. There is no need to do this for ANGLE because it uses a
10149 // single D3D device for all contexts.
10150 if (!feature_info_
->gl_version_info().is_angle
)
10154 if (!surface_
->SwapBuffers()) {
10155 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
10156 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10160 // This may be a slow command. Exit command processing to allow for
10161 // context preemption and GPU watchdog checks.
10162 ExitCommandProcessingEarly();
10165 void GLES2DecoderImpl::DoSwapInterval(int interval
)
10167 context_
->SetSwapInterval(interval
);
10170 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10171 uint32 immediate_data_size
,
10172 const void* cmd_data
) {
10173 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
10174 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
10175 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10176 if (!bucket
|| bucket
->size() == 0) {
10177 return error::kInvalidArguments
;
10179 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
10180 Result
* result
= GetSharedMemoryAs
<Result
*>(
10181 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10183 return error::kOutOfBounds
;
10185 // Check that the client initialized the result.
10186 if (*result
!= 0) {
10187 return error::kInvalidArguments
;
10189 std::string feature_str
;
10190 if (!bucket
->GetAsString(&feature_str
)) {
10191 return error::kInvalidArguments
;
10194 // TODO(gman): make this some kind of table to function pointer thingy.
10195 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10196 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10197 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
10198 buffer_manager()->set_allow_fixed_attribs(true);
10199 // TODO(gman): decide how to remove the need for this const_cast.
10200 // I could make validators_ non const but that seems bad as this is the only
10201 // place it is needed. I could make some special friend class of validators
10202 // just to allow this to set them. That seems silly. I could refactor this
10203 // code to use the extension mechanism or the initialization attributes to
10204 // turn this feature on. Given that the only real point of this is to make
10205 // the conformance tests pass and given that there is lots of real work that
10206 // needs to be done it seems like refactoring for one to one of those
10207 // methods is a very low priority.
10208 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
10209 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
10210 force_webgl_glsl_validation_
= true;
10211 InitializeShaderTranslator();
10213 return error::kNoError
;
10216 *result
= 1; // true.
10217 return error::kNoError
;
10220 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10221 uint32 immediate_data_size
,
10222 const void* cmd_data
) {
10223 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
10224 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
10226 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
10227 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
10228 info
->Initialize(disallowed_features_
);
10229 bucket
->SetFromString(info
->extensions().c_str());
10230 return error::kNoError
;
10233 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10234 uint32 immediate_data_size
,
10235 const void* cmd_data
) {
10236 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
10237 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
10238 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10239 if (!bucket
|| bucket
->size() == 0) {
10240 return error::kInvalidArguments
;
10242 std::string feature_str
;
10243 if (!bucket
->GetAsString(&feature_str
)) {
10244 return error::kInvalidArguments
;
10247 bool desire_webgl_glsl_validation
=
10248 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
10249 bool desire_standard_derivatives
= false;
10250 bool desire_frag_depth
= false;
10251 bool desire_draw_buffers
= false;
10252 bool desire_shader_texture_lod
= false;
10253 if (force_webgl_glsl_validation_
) {
10254 desire_standard_derivatives
=
10255 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
10256 desire_frag_depth
=
10257 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
10258 desire_draw_buffers
=
10259 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
10260 desire_shader_texture_lod
=
10261 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
10264 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
10265 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
10266 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
10267 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
10268 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
10269 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
10270 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
10271 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
10272 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
10273 InitializeShaderTranslator();
10276 UpdateCapabilities();
10278 return error::kNoError
;
10281 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10282 uint32 immediate_data_size
,
10283 const void* cmd_data
) {
10284 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
10285 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
10286 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10287 uint32 bucket_id
= c
.bucket_id
;
10288 Bucket
* bucket
= CreateBucket(bucket_id
);
10289 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
10290 Program
* program
= NULL
;
10291 program
= GetProgram(program_id
);
10292 if (!program
|| !program
->IsValid()) {
10293 return error::kNoError
;
10295 program
->GetProgramInfo(program_manager(), bucket
);
10296 return error::kNoError
;
10299 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10300 uint32 immediate_data_size
, const void* cmd_data
) {
10301 if (!unsafe_es3_apis_enabled())
10302 return error::kUnknownCommand
;
10303 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
10304 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
10305 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10306 uint32 bucket_id
= c
.bucket_id
;
10307 Bucket
* bucket
= CreateBucket(bucket_id
);
10308 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
10309 Program
* program
= NULL
;
10310 program
= GetProgram(program_id
);
10311 if (!program
|| !program
->IsValid()) {
10312 return error::kNoError
;
10314 program
->GetUniformBlocks(bucket
);
10315 return error::kNoError
;
10318 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10319 uint32 immediate_data_size
, const void* cmd_data
) {
10320 if (!unsafe_es3_apis_enabled())
10321 return error::kUnknownCommand
;
10322 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
10323 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
10324 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10325 uint32 bucket_id
= c
.bucket_id
;
10326 Bucket
* bucket
= CreateBucket(bucket_id
);
10327 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
10328 Program
* program
= NULL
;
10329 program
= GetProgram(program_id
);
10330 if (!program
|| !program
->IsValid()) {
10331 return error::kNoError
;
10333 program
->GetUniformsES3(bucket
);
10334 return error::kNoError
;
10337 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10338 uint32 immediate_data_size
,
10339 const void* cmd_data
) {
10340 if (!unsafe_es3_apis_enabled())
10341 return error::kUnknownCommand
;
10342 const gles2::cmds::GetTransformFeedbackVarying
& c
=
10343 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
10344 GLuint program_id
= c
.program
;
10345 GLuint index
= c
.index
;
10346 uint32 name_bucket_id
= c
.name_bucket_id
;
10347 typedef cmds::GetTransformFeedbackVarying::Result Result
;
10348 Result
* result
= GetSharedMemoryAs
<Result
*>(
10349 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10351 return error::kOutOfBounds
;
10353 // Check that the client initialized the result.
10354 if (result
->success
!= 0) {
10355 return error::kInvalidArguments
;
10357 Program
* program
= GetProgramInfoNotShader(
10358 program_id
, "glGetTransformFeedbackVarying");
10360 return error::kNoError
;
10362 GLuint service_id
= program
->service_id();
10363 GLint link_status
= GL_FALSE
;
10364 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10365 if (link_status
!= GL_TRUE
) {
10366 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10367 "glGetTransformFeedbackVarying", "program not linked");
10368 return error::kNoError
;
10370 GLint max_length
= 0;
10372 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
10373 max_length
= std::max(1, max_length
);
10374 std::vector
<char> buffer(max_length
);
10375 GLsizei length
= 0;
10378 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10379 glGetTransformFeedbackVarying(
10380 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
10381 GLenum error
= glGetError();
10382 if (error
!= GL_NO_ERROR
) {
10383 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
10384 return error::kNoError
;
10386 result
->success
= 1; // true.
10387 result
->size
= static_cast<int32_t>(size
);
10388 result
->type
= static_cast<uint32_t>(type
);
10389 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10390 DCHECK(length
>= 0 && length
< max_length
);
10391 buffer
[length
] = '\0'; // Just to be safe.
10392 bucket
->SetFromString(&buffer
[0]);
10393 return error::kNoError
;
10396 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10397 uint32 immediate_data_size
, const void* cmd_data
) {
10398 if (!unsafe_es3_apis_enabled())
10399 return error::kUnknownCommand
;
10400 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
10401 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
10403 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10404 uint32 bucket_id
= c
.bucket_id
;
10405 Bucket
* bucket
= CreateBucket(bucket_id
);
10406 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
10407 Program
* program
= NULL
;
10408 program
= GetProgram(program_id
);
10409 if (!program
|| !program
->IsValid()) {
10410 return error::kNoError
;
10412 program
->GetTransformFeedbackVaryings(bucket
);
10413 return error::kNoError
;
10416 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
10417 switch (reset_status_
) {
10419 // TODO(kbr): improve the precision of the error code in this case.
10420 // Consider delegating to context for error code if MakeCurrent fails.
10421 return error::kUnknown
;
10422 case GL_GUILTY_CONTEXT_RESET_ARB
:
10423 return error::kGuilty
;
10424 case GL_INNOCENT_CONTEXT_RESET_ARB
:
10425 return error::kInnocent
;
10426 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
10427 return error::kUnknown
;
10431 return error::kUnknown
;
10434 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10435 // Some D3D drivers cannot recover from device lost in the GPU process
10436 // sandbox. Allow a new GPU process to launch.
10437 if (workarounds().exit_on_context_lost
) {
10438 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
10439 << " a D3D device in the Chrome GPU process sandbox.";
10440 #if defined(OS_WIN)
10441 base::win::SetShouldCrashOnProcessDetach(false);
10447 bool GLES2DecoderImpl::WasContextLost() {
10448 if (reset_status_
!= GL_NO_ERROR
) {
10449 MaybeExitOnContextLost();
10452 if (IsRobustnessSupported()) {
10453 GLenum status
= glGetGraphicsResetStatusARB();
10454 if (status
!= GL_NO_ERROR
) {
10455 // The graphics card was reset. Signal a lost context to the application.
10456 reset_status_
= status
;
10457 reset_by_robustness_extension_
= true;
10458 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
10459 << " context lost via ARB/EXT_robustness. Reset status = "
10460 << GLES2Util::GetStringEnum(status
);
10461 MaybeExitOnContextLost();
10468 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10469 return WasContextLost() && reset_by_robustness_extension_
;
10472 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
10473 // Only loses the context once.
10474 if (reset_status_
!= GL_NO_ERROR
) {
10478 if (workarounds().use_virtualized_gl_contexts
) {
10479 // If the context is virtual, the real context being guilty does not ensure
10480 // that the virtual context is guilty.
10481 if (reset_status
== GL_GUILTY_CONTEXT_RESET_ARB
) {
10482 reset_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
10484 } else if (reset_status
== GL_UNKNOWN_CONTEXT_RESET_ARB
&&
10485 IsRobustnessSupported()) {
10486 // If the reason for the call was a GL error, we can try to determine the
10487 // reset status more accurately.
10488 GLenum driver_status
= glGetGraphicsResetStatusARB();
10489 if (driver_status
== GL_GUILTY_CONTEXT_RESET_ARB
||
10490 driver_status
== GL_INNOCENT_CONTEXT_RESET_ARB
) {
10491 reset_status
= driver_status
;
10495 // Marks this context as lost.
10496 reset_status_
= reset_status
;
10497 current_decoder_error_
= error::kLostContext
;
10500 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10501 uint32 immediate_data_size
,
10502 const void* cmd_data
) {
10503 return error::kUnknownCommand
;
10506 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10507 uint32 immediate_data_size
,
10508 const void* cmd_data
) {
10509 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
10510 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
10511 uint32 sync_point
= c
.sync_point
;
10512 if (wait_sync_point_callback_
.is_null())
10513 return error::kNoError
;
10515 return wait_sync_point_callback_
.Run(sync_point
) ?
10516 error::kNoError
: error::kDeferCommandUntilLater
;
10519 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10520 uint32 immediate_data_size
,
10521 const void* cmd_data
) {
10522 if (surface_
->DeferDraws())
10523 return error::kDeferCommandUntilLater
;
10524 if (!surface_
->SetBackbufferAllocation(false))
10525 return error::kLostContext
;
10526 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
10527 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
10528 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
10529 return error::kNoError
;
10532 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10533 GLsizei n
, const GLuint
* client_ids
) {
10534 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10535 if (query_manager_
->GetQuery(client_ids
[ii
])) {
10539 query_manager_
->GenQueries(n
, client_ids
);
10543 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10544 GLsizei n
, const GLuint
* client_ids
) {
10545 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10546 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
10547 if (query
&& !query
->IsDeleted()) {
10548 ContextState::QueryMap::iterator it
=
10549 state_
.current_queries
.find(query
->target());
10550 if (it
!= state_
.current_queries
.end())
10551 state_
.current_queries
.erase(it
);
10553 query
->Destroy(true);
10555 query_manager_
->RemoveQuery(client_ids
[ii
]);
10559 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
10560 if (query_manager_
.get() == NULL
) {
10563 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
10564 current_decoder_error_
= error::kOutOfBounds
;
10566 return query_manager_
->HavePendingQueries();
10569 // Note that if there are no pending readpixels right now,
10570 // this function will call the callback immediately.
10571 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
10572 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
10573 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
10579 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10580 while (!pending_readpixel_fences_
.empty() &&
10581 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
10582 std::vector
<base::Closure
> callbacks
=
10583 pending_readpixel_fences_
.front()->callbacks
;
10584 pending_readpixel_fences_
.pop();
10585 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
10586 callbacks
[i
].Run();
10591 bool GLES2DecoderImpl::HasMoreIdleWork() {
10592 return !pending_readpixel_fences_
.empty() ||
10593 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
10596 void GLES2DecoderImpl::PerformIdleWork() {
10597 ProcessPendingReadPixels();
10598 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
10600 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
10601 ProcessFinishedAsyncTransfers();
10604 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
10605 const void* cmd_data
) {
10606 const gles2::cmds::BeginQueryEXT
& c
=
10607 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
10608 GLenum target
= static_cast<GLenum
>(c
.target
);
10609 GLuint client_id
= static_cast<GLuint
>(c
.id
);
10610 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
10611 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10614 case GL_COMMANDS_ISSUED_CHROMIUM
:
10615 case GL_LATENCY_QUERY_CHROMIUM
:
10616 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
10617 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
10618 case GL_GET_ERROR_QUERY_CHROMIUM
:
10620 case GL_COMMANDS_COMPLETED_CHROMIUM
:
10621 if (!features().chromium_sync_query
) {
10622 LOCAL_SET_GL_ERROR(
10623 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10624 "not enabled for commands completed queries");
10625 return error::kNoError
;
10629 if (!features().occlusion_query_boolean
) {
10630 LOCAL_SET_GL_ERROR(
10631 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10632 "not enabled for occlusion queries");
10633 return error::kNoError
;
10638 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
10639 LOCAL_SET_GL_ERROR(
10640 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
10641 return error::kNoError
;
10644 if (client_id
== 0) {
10645 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
10646 return error::kNoError
;
10649 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
10651 if (!query_manager_
->IsValidQuery(client_id
)) {
10652 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10654 "id not made by glGenQueriesEXT");
10655 return error::kNoError
;
10657 query
= query_manager_
->CreateQuery(
10658 target
, client_id
, sync_shm_id
, sync_shm_offset
);
10661 if (query
->target() != target
) {
10662 LOCAL_SET_GL_ERROR(
10663 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
10664 return error::kNoError
;
10665 } else if (query
->shm_id() != sync_shm_id
||
10666 query
->shm_offset() != sync_shm_offset
) {
10667 DLOG(ERROR
) << "Shared memory used by query not the same as before";
10668 return error::kInvalidArguments
;
10671 if (!query_manager_
->BeginQuery(query
)) {
10672 return error::kOutOfBounds
;
10675 state_
.current_queries
[target
] = query
;
10676 return error::kNoError
;
10679 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
10680 const void* cmd_data
) {
10681 const gles2::cmds::EndQueryEXT
& c
=
10682 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
10683 GLenum target
= static_cast<GLenum
>(c
.target
);
10684 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
10685 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
10687 if (it
== state_
.current_queries
.end()) {
10688 LOCAL_SET_GL_ERROR(
10689 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
10690 return error::kNoError
;
10693 QueryManager::Query
* query
= it
->second
.get();
10694 if (!query_manager_
->EndQuery(query
, submit_count
)) {
10695 return error::kOutOfBounds
;
10698 query_manager_
->ProcessPendingTransferQueries();
10700 state_
.current_queries
.erase(it
);
10701 return error::kNoError
;
10704 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10705 GLsizei n
, const GLuint
* client_ids
) {
10706 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10707 if (GetVertexAttribManager(client_ids
[ii
])) {
10712 if (!features().native_vertex_array_object
) {
10714 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10715 CreateVertexAttribManager(client_ids
[ii
], 0, true);
10718 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10720 glGenVertexArraysOES(n
, service_ids
.get());
10721 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10722 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
10729 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10730 GLsizei n
, const GLuint
* client_ids
) {
10731 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10732 VertexAttribManager
* vao
=
10733 GetVertexAttribManager(client_ids
[ii
]);
10734 if (vao
&& !vao
->IsDeleted()) {
10735 if (state_
.vertex_attrib_manager
.get() == vao
) {
10736 DoBindVertexArrayOES(0);
10738 RemoveVertexAttribManager(client_ids
[ii
]);
10743 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
10744 VertexAttribManager
* vao
= NULL
;
10745 if (client_id
!= 0) {
10746 vao
= GetVertexAttribManager(client_id
);
10748 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10749 // only allows names that have been previously generated. As such, we do
10750 // not generate new names here.
10751 LOCAL_SET_GL_ERROR(
10752 GL_INVALID_OPERATION
,
10753 "glBindVertexArrayOES", "bad vertex array id.");
10754 current_decoder_error_
= error::kNoError
;
10758 vao
= state_
.default_vertex_attrib_manager
.get();
10761 // Only set the VAO state if it's changed
10762 if (state_
.vertex_attrib_manager
.get() != vao
) {
10763 state_
.vertex_attrib_manager
= vao
;
10764 if (!features().native_vertex_array_object
) {
10765 EmulateVertexArrayState();
10767 GLuint service_id
= vao
->service_id();
10768 glBindVertexArrayOES(service_id
);
10773 // Used when OES_vertex_array_object isn't natively supported
10774 void GLES2DecoderImpl::EmulateVertexArrayState() {
10775 // Setup the Vertex attribute state
10776 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
10777 RestoreStateForAttrib(vv
, true);
10780 // Setup the element buffer
10781 Buffer
* element_array_buffer
=
10782 state_
.vertex_attrib_manager
->element_array_buffer();
10783 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
10784 element_array_buffer
? element_array_buffer
->service_id() : 0);
10787 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
10788 const VertexAttribManager
* vao
=
10789 GetVertexAttribManager(client_id
);
10790 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
10793 #if defined(OS_MACOSX)
10794 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
10795 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
10797 if (it
!= texture_to_io_surface_map_
.end()) {
10798 // Found a previous IOSurface bound to this texture; release it.
10799 IOSurfaceRef surface
= it
->second
;
10800 CFRelease(surface
);
10801 texture_to_io_surface_map_
.erase(it
);
10806 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10807 GLenum target
, GLsizei width
, GLsizei height
,
10808 GLuint io_surface_id
, GLuint plane
) {
10809 #if defined(OS_MACOSX)
10810 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
10811 LOCAL_SET_GL_ERROR(
10812 GL_INVALID_OPERATION
,
10813 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10817 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
10818 // This might be supported in the future, and if we could require
10819 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10820 // could delete a lot of code. For now, perform strict validation so we
10821 // know what's going on.
10822 LOCAL_SET_GL_ERROR(
10823 GL_INVALID_OPERATION
,
10824 "glTexImageIOSurface2DCHROMIUM",
10825 "requires TEXTURE_RECTANGLE_ARB target");
10829 // Default target might be conceptually valid, but disallow it to avoid
10831 TextureRef
* texture_ref
=
10832 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10833 if (!texture_ref
) {
10834 LOCAL_SET_GL_ERROR(
10835 GL_INVALID_OPERATION
,
10836 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10840 // Look up the new IOSurface. Note that because of asynchrony
10841 // between processes this might fail; during live resizing the
10842 // plugin process might allocate and release an IOSurface before
10843 // this process gets a chance to look it up. Hold on to any old
10844 // IOSurface in this case.
10845 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
10847 LOCAL_SET_GL_ERROR(
10848 GL_INVALID_OPERATION
,
10849 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10853 // Release any IOSurface previously bound to this texture.
10854 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
10856 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10857 texture_to_io_surface_map_
.insert(
10858 std::make_pair(texture_ref
->service_id(), surface
));
10860 CGLContextObj context
=
10861 static_cast<CGLContextObj
>(context_
->GetHandle());
10863 CGLError err
= CGLTexImageIOSurface2D(
10870 GL_UNSIGNED_INT_8_8_8_8_REV
,
10874 if (err
!= kCGLNoError
) {
10875 LOCAL_SET_GL_ERROR(
10876 GL_INVALID_OPERATION
,
10877 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10881 texture_manager()->SetLevelInfo(
10882 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
10883 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
10886 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10887 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10891 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
10892 switch (internalformat
) {
10903 case GL_LUMINANCE8_ALPHA8_EXT
:
10904 return GL_LUMINANCE_ALPHA
;
10905 case GL_LUMINANCE8_EXT
:
10906 return GL_LUMINANCE
;
10907 case GL_ALPHA8_EXT
:
10909 case GL_RGBA32F_EXT
:
10911 case GL_RGB32F_EXT
:
10913 case GL_ALPHA32F_EXT
:
10915 case GL_LUMINANCE32F_EXT
:
10916 return GL_LUMINANCE
;
10917 case GL_LUMINANCE_ALPHA32F_EXT
:
10918 return GL_LUMINANCE_ALPHA
;
10919 case GL_RGBA16F_EXT
:
10921 case GL_RGB16F_EXT
:
10923 case GL_ALPHA16F_EXT
:
10925 case GL_LUMINANCE16F_EXT
:
10926 return GL_LUMINANCE
;
10927 case GL_LUMINANCE_ALPHA16F_EXT
:
10928 return GL_LUMINANCE_ALPHA
;
10930 return GL_BGRA_EXT
;
10931 case GL_SRGB8_ALPHA8_EXT
:
10932 return GL_SRGB_ALPHA_EXT
;
10938 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10939 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
10940 GLenum internal_format
, GLenum dest_type
) {
10941 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10943 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
10944 TextureRef
* source_texture_ref
= GetTexture(source_id
);
10946 if (!source_texture_ref
|| !dest_texture_ref
) {
10947 LOCAL_SET_GL_ERROR(
10948 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
10952 if (GL_TEXTURE_2D
!= target
) {
10953 LOCAL_SET_GL_ERROR(
10954 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
10958 Texture
* source_texture
= source_texture_ref
->texture();
10959 Texture
* dest_texture
= dest_texture_ref
->texture();
10960 if (dest_texture
->target() != GL_TEXTURE_2D
||
10961 (source_texture
->target() != GL_TEXTURE_2D
&&
10962 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
10963 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
10964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10965 "glCopyTextureCHROMIUM",
10966 "invalid texture target binding");
10970 int source_width
, source_height
, dest_width
, dest_height
;
10972 gfx::GLImage
* image
=
10973 source_texture
->GetLevelImage(source_texture
->target(), 0);
10975 gfx::Size size
= image
->GetSize();
10976 source_width
= size
.width();
10977 source_height
= size
.height();
10978 if (source_width
<= 0 || source_height
<= 0) {
10979 LOCAL_SET_GL_ERROR(
10981 "glCopyTextureChromium", "invalid image size");
10985 if (!source_texture
->GetLevelSize(
10986 source_texture
->target(), 0, &source_width
, &source_height
)) {
10987 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10988 "glCopyTextureChromium",
10989 "source texture has no level 0");
10993 // Check that this type of texture is allowed.
10994 if (!texture_manager()->ValidForTarget(
10995 source_texture
->target(), level
, source_width
, source_height
, 1)) {
10996 LOCAL_SET_GL_ERROR(
10997 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11002 // Clear the source texture if necessary.
11003 if (!texture_manager()->ClearTextureLevel(
11004 this, source_texture_ref
, source_texture
->target(), 0)) {
11005 LOCAL_SET_GL_ERROR(
11006 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
11010 GLenum source_type
= 0;
11011 GLenum source_internal_format
= 0;
11012 source_texture
->GetLevelType(
11013 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11015 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11016 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11017 // renderable on some platforms.
11018 bool valid_dest_format
= internal_format
== GL_RGB
||
11019 internal_format
== GL_RGBA
||
11020 internal_format
== GL_BGRA_EXT
;
11021 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11022 source_internal_format
== GL_RGB
||
11023 source_internal_format
== GL_RGBA
||
11024 source_internal_format
== GL_LUMINANCE
||
11025 source_internal_format
== GL_LUMINANCE_ALPHA
||
11026 source_internal_format
== GL_BGRA_EXT
;
11027 if (!valid_source_format
|| !valid_dest_format
) {
11028 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11029 "glCopyTextureCHROMIUM",
11030 "invalid internal format");
11034 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11035 // needed because it takes 10s of milliseconds to initialize.
11036 if (!copy_texture_CHROMIUM_
.get()) {
11037 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11038 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11039 copy_texture_CHROMIUM_
->Initialize(this);
11040 RestoreCurrentFramebufferBindings();
11041 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11045 GLenum dest_type_previous
= dest_type
;
11046 GLenum dest_internal_format
= internal_format
;
11047 bool dest_level_defined
= dest_texture
->GetLevelSize(
11048 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
11050 if (dest_level_defined
) {
11051 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
11052 &dest_internal_format
);
11055 // Resize the destination texture to the dimensions of the source texture.
11056 if (!dest_level_defined
|| dest_width
!= source_width
||
11057 dest_height
!= source_height
||
11058 dest_internal_format
!= internal_format
||
11059 dest_type_previous
!= dest_type
) {
11060 // Ensure that the glTexImage2D succeeds.
11061 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11062 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11064 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
11065 0, internal_format
, dest_type
, NULL
);
11066 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11067 if (error
!= GL_NO_ERROR
) {
11068 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11072 texture_manager()->SetLevelInfo(
11073 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
11074 source_height
, 1, 0, internal_format
, dest_type
, true);
11076 texture_manager()->SetLevelCleared(
11077 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
11080 ScopedModifyPixels
modify(dest_texture_ref
);
11082 // Try using GLImage::CopyTexImage when possible.
11083 bool unpack_premultiply_alpha_change
=
11084 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11085 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&& !level
) {
11086 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11087 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11091 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11093 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11094 // before presenting.
11095 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11096 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11097 // instead of using default matrix crbug.com/226218.
11098 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
11099 0.0f
, 1.0f
, 0.0f
, 0.0f
,
11100 0.0f
, 0.0f
, 1.0f
, 0.0f
,
11101 0.0f
, 0.0f
, 0.0f
, 1.0f
};
11102 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
11104 source_texture
->target(),
11105 source_texture
->service_id(),
11106 dest_texture
->service_id(),
11111 unpack_premultiply_alpha_
,
11112 unpack_unpremultiply_alpha_
,
11115 copy_texture_CHROMIUM_
->DoCopyTexture(this,
11116 source_texture
->target(),
11117 source_texture
->service_id(),
11118 source_internal_format
,
11119 dest_texture
->service_id(),
11125 unpack_premultiply_alpha_
,
11126 unpack_unpremultiply_alpha_
);
11129 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11132 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
11133 switch (internalformat
) {
11135 return GL_UNSIGNED_SHORT_5_6_5
;
11137 return GL_UNSIGNED_SHORT_4_4_4_4
;
11139 return GL_UNSIGNED_SHORT_5_5_5_1
;
11141 return GL_UNSIGNED_BYTE
;
11143 return GL_UNSIGNED_BYTE
;
11144 case GL_LUMINANCE8_ALPHA8_EXT
:
11145 return GL_UNSIGNED_BYTE
;
11146 case GL_LUMINANCE8_EXT
:
11147 return GL_UNSIGNED_BYTE
;
11148 case GL_ALPHA8_EXT
:
11149 return GL_UNSIGNED_BYTE
;
11150 case GL_RGBA32F_EXT
:
11152 case GL_RGB32F_EXT
:
11154 case GL_ALPHA32F_EXT
:
11156 case GL_LUMINANCE32F_EXT
:
11158 case GL_LUMINANCE_ALPHA32F_EXT
:
11160 case GL_RGBA16F_EXT
:
11161 return GL_HALF_FLOAT_OES
;
11162 case GL_RGB16F_EXT
:
11163 return GL_HALF_FLOAT_OES
;
11164 case GL_ALPHA16F_EXT
:
11165 return GL_HALF_FLOAT_OES
;
11166 case GL_LUMINANCE16F_EXT
:
11167 return GL_HALF_FLOAT_OES
;
11168 case GL_LUMINANCE_ALPHA16F_EXT
:
11169 return GL_HALF_FLOAT_OES
;
11171 return GL_UNSIGNED_BYTE
;
11177 void GLES2DecoderImpl::DoTexStorage2DEXT(
11180 GLenum internal_format
,
11183 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11184 "width", width
, "height", height
);
11185 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
11186 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
11187 LOCAL_SET_GL_ERROR(
11188 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
11191 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11193 if (!texture_ref
) {
11194 LOCAL_SET_GL_ERROR(
11195 GL_INVALID_OPERATION
,
11196 "glTexStorage2DEXT", "unknown texture for target");
11199 Texture
* texture
= texture_ref
->texture();
11200 if (texture
->IsAttachedToFramebuffer()) {
11201 framebuffer_state_
.clear_state_dirty
= true;
11203 if (texture
->IsImmutable()) {
11204 LOCAL_SET_GL_ERROR(
11205 GL_INVALID_OPERATION
,
11206 "glTexStorage2DEXT", "texture is immutable");
11210 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
11211 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
11214 GLsizei level_width
= width
;
11215 GLsizei level_height
= height
;
11216 uint32 estimated_size
= 0;
11217 for (int ii
= 0; ii
< levels
; ++ii
) {
11218 uint32 level_size
= 0;
11219 if (!GLES2Util::ComputeImageDataSizes(
11220 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
11221 &estimated_size
, NULL
, NULL
) ||
11222 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
11223 LOCAL_SET_GL_ERROR(
11224 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
11227 level_width
= std::max(1, level_width
>> 1);
11228 level_height
= std::max(1, level_height
>> 1);
11230 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
11231 LOCAL_SET_GL_ERROR(
11232 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
11237 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11238 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
11239 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11240 if (error
== GL_NO_ERROR
) {
11241 GLsizei level_width
= width
;
11242 GLsizei level_height
= height
;
11243 for (int ii
= 0; ii
< levels
; ++ii
) {
11244 texture_manager()->SetLevelInfo(
11245 texture_ref
, target
, ii
, format
,
11246 level_width
, level_height
, 1, 0, format
, type
, false);
11247 level_width
= std::max(1, level_width
>> 1);
11248 level_height
= std::max(1, level_height
>> 1);
11250 texture
->SetImmutable(true);
11254 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11255 uint32 immediate_data_size
,
11256 const void* cmd_data
) {
11257 return error::kUnknownCommand
;
11260 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
11261 const GLbyte
* data
) {
11262 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11263 "context", logger_
.GetLogPrefix(),
11264 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11266 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11268 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
11271 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
11272 GLenum target
, const GLbyte
* data
) {
11273 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11274 "context", logger_
.GetLogPrefix(),
11275 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11277 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
11281 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
11282 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
11283 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11284 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
11285 "mailbox that was not generated by "
11286 "GenMailboxCHROMIUM.";
11288 if (!texture_ref
) {
11289 LOCAL_SET_GL_ERROR(
11290 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
11294 Texture
* produced
= texture_manager()->Produce(texture_ref
);
11296 LOCAL_SET_GL_ERROR(
11297 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
11301 if (produced
->target() != target
) {
11302 LOCAL_SET_GL_ERROR(
11303 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
11307 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
11310 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
11311 const GLbyte
* data
) {
11312 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11313 "context", logger_
.GetLogPrefix(),
11314 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11315 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11316 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
11317 "mailbox that was not generated by "
11318 "GenMailboxCHROMIUM.";
11320 scoped_refptr
<TextureRef
> texture_ref
=
11321 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11322 if (!texture_ref
.get()) {
11323 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11324 "glConsumeTextureCHROMIUM",
11325 "unknown texture for target");
11328 GLuint client_id
= texture_ref
->client_id();
11330 LOCAL_SET_GL_ERROR(
11331 GL_INVALID_OPERATION
,
11332 "glConsumeTextureCHROMIUM", "unknown texture for target");
11335 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
11337 LOCAL_SET_GL_ERROR(
11338 GL_INVALID_OPERATION
,
11339 "glConsumeTextureCHROMIUM", "invalid mailbox name");
11342 if (texture
->target() != target
) {
11343 LOCAL_SET_GL_ERROR(
11344 GL_INVALID_OPERATION
,
11345 "glConsumeTextureCHROMIUM", "invalid target");
11349 DeleteTexturesHelper(1, &client_id
);
11350 texture_ref
= texture_manager()->Consume(client_id
, texture
);
11351 glBindTexture(target
, texture_ref
->service_id());
11353 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
11354 unit
.bind_target
= target
;
11356 case GL_TEXTURE_2D
:
11357 unit
.bound_texture_2d
= texture_ref
;
11359 case GL_TEXTURE_CUBE_MAP
:
11360 unit
.bound_texture_cube_map
= texture_ref
;
11362 case GL_TEXTURE_EXTERNAL_OES
:
11363 unit
.bound_texture_external_oes
= texture_ref
;
11365 case GL_TEXTURE_RECTANGLE_ARB
:
11366 unit
.bound_texture_rectangle_arb
= texture_ref
;
11369 NOTREACHED(); // Validation should prevent us getting here.
11374 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
11375 uint32_t immediate_data_size
,
11376 const void* cmd_data
) {
11377 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
11379 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
11381 GLenum target
= static_cast<GLenum
>(c
.target
);
11382 uint32_t data_size
;
11383 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
11384 return error::kOutOfBounds
;
11386 if (data_size
> immediate_data_size
) {
11387 return error::kOutOfBounds
;
11389 const GLbyte
* mailbox
=
11390 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
11391 if (!validators_
->texture_bind_target
.IsValid(target
)) {
11392 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11393 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
11394 return error::kNoError
;
11396 if (mailbox
== NULL
) {
11397 return error::kOutOfBounds
;
11399 uint32_t client_id
= c
.client_id
;
11400 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
11401 return error::kNoError
;
11404 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
11405 const GLbyte
* data
, GLuint client_id
) {
11406 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11407 "context", logger_
.GetLogPrefix(),
11408 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11409 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11410 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11411 "passed a mailbox that was not "
11412 "generated by GenMailboxCHROMIUM.";
11414 TextureRef
* texture_ref
= GetTexture(client_id
);
11416 LOCAL_SET_GL_ERROR(
11417 GL_INVALID_OPERATION
,
11418 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11421 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
11423 LOCAL_SET_GL_ERROR(
11424 GL_INVALID_OPERATION
,
11425 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11428 if (texture
->target() != target
) {
11429 LOCAL_SET_GL_ERROR(
11430 GL_INVALID_OPERATION
,
11431 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11435 texture_ref
= texture_manager()->Consume(client_id
, texture
);
11438 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
11439 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
11440 return valuebuffer
&& valuebuffer
->IsValid();
11443 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
11444 GLuint client_id
) {
11445 Valuebuffer
* valuebuffer
= NULL
;
11446 if (client_id
!= 0) {
11447 valuebuffer
= GetValuebuffer(client_id
);
11448 if (!valuebuffer
) {
11449 if (!group_
->bind_generates_resource()) {
11450 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
11451 "id not generated by glBindValuebufferCHROMIUM");
11455 // It's a new id so make a valuebuffer for it.
11456 CreateValuebuffer(client_id
);
11457 valuebuffer
= GetValuebuffer(client_id
);
11459 valuebuffer
->MarkAsValid();
11461 state_
.bound_valuebuffer
= valuebuffer
;
11464 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
11465 GLenum subscription
) {
11466 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11469 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
11472 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
11473 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11476 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
11479 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
11481 GLenum subscription
) {
11482 if (!CheckCurrentValuebufferForSubscription(
11483 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
11486 if (!CheckSubscriptionTarget(location
, subscription
,
11487 "glPopulateSubscribedValuesCHROMIUM")) {
11490 const ValueState
* state
=
11491 state_
.bound_valuebuffer
.get()->GetState(subscription
);
11493 switch (subscription
) {
11494 case GL_MOUSE_POSITION_CHROMIUM
:
11495 DoUniform2iv(location
, 1, state
->int_value
);
11498 NOTREACHED() << "Unhandled uniform subscription target "
11505 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11506 GLsizei length
, const GLchar
* marker
) {
11510 debug_marker_manager_
.SetMarker(
11511 length
? std::string(marker
, length
) : std::string(marker
));
11514 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11515 GLsizei length
, const GLchar
* marker
) {
11519 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
11520 debug_marker_manager_
.PushGroup(name
);
11521 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
11522 kTraceGroupMarker
);
11525 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11526 debug_marker_manager_
.PopGroup();
11527 gpu_tracer_
->End(kTraceGroupMarker
);
11530 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11531 GLenum target
, GLint image_id
) {
11532 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11534 if (target
== GL_TEXTURE_CUBE_MAP
) {
11535 LOCAL_SET_GL_ERROR(
11537 "glBindTexImage2DCHROMIUM", "invalid target");
11541 // Default target might be conceptually valid, but disallow it to avoid
11543 TextureRef
* texture_ref
=
11544 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11545 if (!texture_ref
) {
11546 LOCAL_SET_GL_ERROR(
11547 GL_INVALID_OPERATION
,
11548 "glBindTexImage2DCHROMIUM", "no texture bound");
11552 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11554 LOCAL_SET_GL_ERROR(
11555 GL_INVALID_OPERATION
,
11556 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11561 ScopedGLErrorSuppressor
suppressor(
11562 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11563 if (!gl_image
->BindTexImage(target
)) {
11564 LOCAL_SET_GL_ERROR(
11565 GL_INVALID_OPERATION
,
11566 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11571 gfx::Size size
= gl_image
->GetSize();
11572 texture_manager()->SetLevelInfo(
11573 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
11574 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
11575 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
11578 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11579 GLenum target
, GLint image_id
) {
11580 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11582 // Default target might be conceptually valid, but disallow it to avoid
11584 TextureRef
* texture_ref
=
11585 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11586 if (!texture_ref
) {
11587 LOCAL_SET_GL_ERROR(
11588 GL_INVALID_OPERATION
,
11589 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11593 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11595 LOCAL_SET_GL_ERROR(
11596 GL_INVALID_OPERATION
,
11597 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11601 // Do nothing when image is not currently bound.
11602 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
11606 ScopedGLErrorSuppressor
suppressor(
11607 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11608 gl_image
->ReleaseTexImage(target
);
11611 texture_manager()->SetLevelInfo(
11612 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
11613 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
11616 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11617 uint32 immediate_data_size
,
11618 const void* cmd_data
) {
11619 const gles2::cmds::TraceBeginCHROMIUM
& c
=
11620 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
11621 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
11622 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
11623 if (!category_bucket
|| category_bucket
->size() == 0 ||
11624 !name_bucket
|| name_bucket
->size() == 0) {
11625 return error::kInvalidArguments
;
11628 std::string category_name
;
11629 std::string trace_name
;
11630 if (!category_bucket
->GetAsString(&category_name
) ||
11631 !name_bucket
->GetAsString(&trace_name
)) {
11632 return error::kInvalidArguments
;
11635 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
11636 LOCAL_SET_GL_ERROR(
11637 GL_INVALID_OPERATION
,
11638 "glTraceBeginCHROMIUM", "unable to create begin trace");
11639 return error::kNoError
;
11641 return error::kNoError
;
11644 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11645 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
11646 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11647 "glTraceEndCHROMIUM", "no trace begin found");
11652 void GLES2DecoderImpl::DoDrawBuffersEXT(
11653 GLsizei count
, const GLenum
* bufs
) {
11654 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
11655 LOCAL_SET_GL_ERROR(
11657 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11661 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
11663 for (GLsizei i
= 0; i
< count
; ++i
) {
11664 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
11665 bufs
[i
] != GL_NONE
) {
11666 LOCAL_SET_GL_ERROR(
11667 GL_INVALID_OPERATION
,
11668 "glDrawBuffersEXT",
11669 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
11673 glDrawBuffersARB(count
, bufs
);
11674 framebuffer
->SetDrawBuffers(count
, bufs
);
11675 } else { // backbuffer
11677 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
11678 LOCAL_SET_GL_ERROR(
11679 GL_INVALID_OPERATION
,
11680 "glDrawBuffersEXT",
11681 "more than one buffer or bufs not GL_NONE or GL_BACK");
11684 GLenum mapped_buf
= bufs
[0];
11685 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
11686 bufs
[0] == GL_BACK
) {
11687 mapped_buf
= GL_COLOR_ATTACHMENT0
;
11689 glDrawBuffersARB(count
, &mapped_buf
);
11690 group_
->set_draw_buffer(bufs
[0]);
11694 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
11695 group_
->LoseContexts(other
);
11696 reset_status_
= current
;
11697 current_decoder_error_
= error::kLostContext
;
11700 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
11701 const GLfloat
* matrix
) {
11702 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
11703 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
11704 if (!features().chromium_path_rendering
) {
11705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11706 "glMatrixLoadfCHROMIUM",
11707 "function not available");
11711 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
11712 ? state_
.projection_matrix
11713 : state_
.modelview_matrix
;
11714 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
11715 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11716 // since the values of the _NV and _CHROMIUM tokens match.
11717 glMatrixLoadfEXT(matrix_mode
, matrix
);
11720 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
11721 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
11722 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
11724 if (!features().chromium_path_rendering
) {
11725 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11726 "glMatrixLoadIdentityCHROMIUM",
11727 "function not available");
11731 static GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
,
11732 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
, 0.0f
,
11733 0.0f
, 0.0f
, 0.0f
, 1.0f
};
11735 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
11736 ? state_
.projection_matrix
11737 : state_
.modelview_matrix
;
11738 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
11739 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11740 // since the values of the _NV and _CHROMIUM tokens match.
11741 glMatrixLoadIdentityEXT(matrix_mode
);
11744 bool GLES2DecoderImpl::ValidateAsyncTransfer(
11745 const char* function_name
,
11746 TextureRef
* texture_ref
,
11749 const void * data
) {
11750 // We only support async uploads to 2D textures for now.
11751 if (GL_TEXTURE_2D
!= target
) {
11752 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
11755 // We only support uploads to level zero for now.
11757 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
11760 // A transfer buffer must be bound, even for asyncTexImage2D.
11761 if (data
== NULL
) {
11762 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
11765 // We only support one async transfer in progress.
11766 if (!texture_ref
||
11767 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
11768 LOCAL_SET_GL_ERROR(
11769 GL_INVALID_OPERATION
,
11770 function_name
, "transfer already in progress");
11776 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11777 uint32 async_upload_token
,
11778 uint32 sync_data_shm_id
,
11779 uint32 sync_data_shm_offset
) {
11780 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
11781 if (!buffer
.get() ||
11782 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
11783 return base::Closure();
11785 AsyncMemoryParams
mem_params(buffer
,
11786 sync_data_shm_offset
,
11787 sizeof(AsyncUploadSync
));
11789 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
11790 new AsyncUploadTokenCompletionObserver(async_upload_token
));
11793 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
11794 base::Unretained(GetAsyncPixelTransferManager()),
11799 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11800 uint32 immediate_data_size
,
11801 const void* cmd_data
) {
11802 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
11803 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
11804 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11805 GLenum target
= static_cast<GLenum
>(c
.target
);
11806 GLint level
= static_cast<GLint
>(c
.level
);
11807 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
11808 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11809 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11810 GLint border
= static_cast<GLint
>(c
.border
);
11811 GLenum format
= static_cast<GLenum
>(c
.format
);
11812 GLenum type
= static_cast<GLenum
>(c
.type
);
11813 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
11814 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
11815 uint32 pixels_size
;
11816 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11817 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11818 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11820 base::ScopedClosureRunner scoped_completion_callback
;
11821 if (async_upload_token
) {
11822 base::Closure completion_closure
=
11823 AsyncUploadTokenCompletionClosure(async_upload_token
,
11825 sync_data_shm_offset
);
11826 if (completion_closure
.is_null())
11827 return error::kInvalidArguments
;
11829 scoped_completion_callback
.Reset(completion_closure
);
11832 // TODO(epenner): Move this and copies of this memory validation
11833 // into ValidateTexImage2D step.
11834 if (!GLES2Util::ComputeImageDataSizes(
11835 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
11837 return error::kOutOfBounds
;
11839 const void* pixels
= NULL
;
11840 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
11841 pixels
= GetSharedMemoryAs
<const void*>(
11842 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
11844 return error::kOutOfBounds
;
11848 TextureManager::DoTextImage2DArguments args
= {
11849 target
, level
, internal_format
, width
, height
, border
, format
, type
,
11850 pixels
, pixels_size
};
11851 TextureRef
* texture_ref
;
11852 // All the normal glTexSubImage2D validation.
11853 if (!texture_manager()->ValidateTexImage2D(
11854 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
11855 return error::kNoError
;
11858 // Extra async validation.
11859 Texture
* texture
= texture_ref
->texture();
11860 if (!ValidateAsyncTransfer(
11861 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11862 return error::kNoError
;
11864 // Don't allow async redefinition of a textures.
11865 if (texture
->IsDefined()) {
11866 LOCAL_SET_GL_ERROR(
11867 GL_INVALID_OPERATION
,
11868 "glAsyncTexImage2DCHROMIUM", "already defined");
11869 return error::kNoError
;
11872 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
11873 LOCAL_SET_GL_ERROR(
11874 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
11875 return error::kNoError
;
11878 // Setup the parameters.
11879 AsyncTexImage2DParams tex_params
= {
11880 target
, level
, static_cast<GLenum
>(internal_format
),
11881 width
, height
, border
, format
, type
};
11882 AsyncMemoryParams
mem_params(
11883 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
11885 // Set up the async state if needed, and make the texture
11886 // immutable so the async state stays valid. The level info
11887 // is set up lazily when the transfer completes.
11888 AsyncPixelTransferDelegate
* delegate
=
11889 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
11891 texture
->SetImmutable(true);
11893 delegate
->AsyncTexImage2D(
11896 base::Bind(&TextureManager::SetLevelInfoFromParams
,
11897 // The callback is only invoked if the transfer delegate still
11898 // exists, which implies through manager->texture_ref->state
11899 // ownership that both of these pointers are valid.
11900 base::Unretained(texture_manager()),
11901 base::Unretained(texture_ref
),
11903 return error::kNoError
;
11906 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11907 uint32 immediate_data_size
,
11908 const void* cmd_data
) {
11909 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
11910 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
11911 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11912 GLenum target
= static_cast<GLenum
>(c
.target
);
11913 GLint level
= static_cast<GLint
>(c
.level
);
11914 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11915 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11916 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11917 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11918 GLenum format
= static_cast<GLenum
>(c
.format
);
11919 GLenum type
= static_cast<GLenum
>(c
.type
);
11920 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11921 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11922 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11924 base::ScopedClosureRunner scoped_completion_callback
;
11925 if (async_upload_token
) {
11926 base::Closure completion_closure
=
11927 AsyncUploadTokenCompletionClosure(async_upload_token
,
11929 sync_data_shm_offset
);
11930 if (completion_closure
.is_null())
11931 return error::kInvalidArguments
;
11933 scoped_completion_callback
.Reset(completion_closure
);
11936 // TODO(epenner): Move this and copies of this memory validation
11937 // into ValidateTexSubImage2D step.
11939 if (!GLES2Util::ComputeImageDataSizes(
11940 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
11942 return error::kOutOfBounds
;
11944 const void* pixels
= GetSharedMemoryAs
<const void*>(
11945 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
11947 // All the normal glTexSubImage2D validation.
11948 error::Error error
= error::kNoError
;
11949 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
11950 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
11954 // Extra async validation.
11955 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11957 Texture
* texture
= texture_ref
->texture();
11958 if (!ValidateAsyncTransfer(
11959 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11960 return error::kNoError
;
11962 // Guarantee async textures are always 'cleared' as follows:
11963 // - AsyncTexImage2D can not redefine an existing texture
11964 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11965 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11966 // - Textures become immutable after an async call.
11967 // This way we know in all cases that an async texture is always clear.
11968 if (!texture
->SafeToRenderFrom()) {
11969 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
11971 LOCAL_SET_GL_ERROR(
11973 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11974 return error::kNoError
;
11978 // Setup the parameters.
11979 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
11980 width
, height
, format
, type
};
11981 AsyncMemoryParams
mem_params(
11982 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
11983 AsyncPixelTransferDelegate
* delegate
=
11984 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
11986 // TODO(epenner): We may want to enforce exclusive use
11987 // of async APIs in which case this should become an error,
11988 // (the texture should have been async defined).
11989 AsyncTexImage2DParams define_params
= {target
, level
,
11991 texture
->GetLevelSize(target
, level
, &define_params
.width
,
11992 &define_params
.height
);
11993 texture
->GetLevelType(target
, level
, &define_params
.type
,
11994 &define_params
.internal_format
);
11995 // Set up the async state if needed, and make the texture
11996 // immutable so the async state stays valid.
11997 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
11998 texture_ref
, define_params
);
11999 texture
->SetImmutable(true);
12002 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
12003 return error::kNoError
;
12006 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12007 uint32 immediate_data_size
,
12008 const void* cmd_data
) {
12009 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
12010 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
12011 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12012 GLenum target
= static_cast<GLenum
>(c
.target
);
12014 if (GL_TEXTURE_2D
!= target
) {
12015 LOCAL_SET_GL_ERROR(
12016 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
12017 return error::kNoError
;
12019 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12021 if (!texture_ref
) {
12022 LOCAL_SET_GL_ERROR(
12023 GL_INVALID_OPERATION
,
12024 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12025 return error::kNoError
;
12027 AsyncPixelTransferDelegate
* delegate
=
12028 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12030 LOCAL_SET_GL_ERROR(
12031 GL_INVALID_OPERATION
,
12032 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12033 return error::kNoError
;
12035 delegate
->WaitForTransferCompletion();
12036 ProcessFinishedAsyncTransfers();
12037 return error::kNoError
;
12040 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12041 uint32 immediate_data_size
,
12042 const void* data
) {
12043 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12045 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12046 ProcessFinishedAsyncTransfers();
12047 return error::kNoError
;
12050 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
12051 uint32_t immediate_data_size
, const void* cmd_data
) {
12052 if (!unsafe_es3_apis_enabled())
12053 return error::kUnknownCommand
;
12054 const gles2::cmds::UniformBlockBinding
& c
=
12055 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
12056 GLuint client_id
= c
.program
;
12057 GLuint index
= static_cast<GLuint
>(c
.index
);
12058 GLuint binding
= static_cast<GLuint
>(c
.binding
);
12059 Program
* program
= GetProgramInfoNotShader(
12060 client_id
, "glUniformBlockBinding");
12062 return error::kNoError
;
12064 GLuint service_id
= program
->service_id();
12065 glUniformBlockBinding(service_id
, index
, binding
);
12066 return error::kNoError
;
12069 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
12070 uint32_t immediate_data_size
, const void* cmd_data
) {
12071 if (!unsafe_es3_apis_enabled())
12072 return error::kUnknownCommand
;
12073 const gles2::cmds::ClientWaitSync
& c
=
12074 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
12075 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12076 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12077 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12078 typedef cmds::ClientWaitSync::Result Result
;
12079 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
12080 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
12082 return error::kOutOfBounds
;
12084 if (*result_dst
!= GL_WAIT_FAILED
) {
12085 return error::kInvalidArguments
;
12087 GLsync service_sync
= 0;
12088 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12089 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
12090 return error::kNoError
;
12092 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
12093 return error::kNoError
;
12096 error::Error
GLES2DecoderImpl::HandleWaitSync(
12097 uint32_t immediate_data_size
, const void* cmd_data
) {
12098 if (!unsafe_es3_apis_enabled())
12099 return error::kUnknownCommand
;
12100 const gles2::cmds::WaitSync
& c
=
12101 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
12102 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12103 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12104 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12105 GLsync service_sync
= 0;
12106 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12107 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
12108 return error::kNoError
;
12110 glWaitSync(service_sync
, flags
, timeout
);
12111 return error::kNoError
;
12114 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12115 TextureRef
* texture_ref
) {
12116 Texture
* texture
= texture_ref
->texture();
12117 DoDidUseTexImageIfNeeded(texture
, texture
->target());
12120 void GLES2DecoderImpl::OnContextLostError() {
12121 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
12124 void GLES2DecoderImpl::OnOutOfMemoryError() {
12125 if (lose_context_when_out_of_memory_
) {
12126 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
12130 // Include the auto-generated part of this file. We split this because it means
12131 // we can easily edit the non-auto generated parts right here in this file
12132 // instead of having to edit some template or the code generator.
12133 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12135 } // namespace gles2