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(unsigned service_id
,
1195 unsigned bind_target
,
1198 unsigned internal_format
,
1203 bool is_texture_immutable
) override
;
1205 // Restore all GL state that affects clearing.
1206 void RestoreClearState();
1208 // Remembers the state of some capabilities.
1209 // Returns: true if glEnable/glDisable should actually be called.
1210 bool SetCapabilityState(GLenum cap
, bool enabled
);
1212 // Check that the currently bound framebuffers are valid.
1213 // Generates GL error if not.
1214 bool CheckBoundFramebuffersValid(const char* func_name
);
1216 // Check that the currently bound read framebuffer has a color image
1217 // attached. Generates GL error if not.
1218 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1220 // Check that the currently bound read framebuffer's color image
1221 // isn't the target texture of the glCopyTex{Sub}Image2D.
1222 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1224 // Check if a framebuffer meets our requirements.
1225 bool CheckFramebufferValid(
1226 Framebuffer
* framebuffer
,
1228 const char* func_name
);
1230 // Check if the current valuebuffer exists and is valid. If not generates
1231 // the appropriate GL error. Returns true if the current valuebuffer is in
1233 bool CheckCurrentValuebuffer(const char* function_name
);
1235 // Check if the current valuebuffer exists and is valiud and that the
1236 // value buffer is actually subscribed to the given subscription
1237 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1238 const char* function_name
);
1240 // Check if the location can be used for the given subscription target. If not
1241 // generates the appropriate GL error. Returns true if the location is usable
1242 bool CheckSubscriptionTarget(GLint location
,
1243 GLenum subscription
,
1244 const char* function_name
);
1246 // Checks if the current program exists and is valid. If not generates the
1247 // appropriate GL error. Returns true if the current program is in a usable
1249 bool CheckCurrentProgram(const char* function_name
);
1251 // Checks if the current program exists and is valid and that location is not
1252 // -1. If the current program is not valid generates the appropriate GL
1253 // error. Returns true if the current program is in a usable state and
1254 // location is not -1.
1255 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1257 // Checks if the current program samples a texture that is also the color
1258 // image of the current bound framebuffer, i.e., the source and destination
1259 // of the draw operation are the same.
1260 bool CheckDrawingFeedbackLoops();
1262 // Checks if |api_type| is valid for the given uniform
1263 // If the api type is not valid generates the appropriate GL
1264 // error. Returns true if |api_type| is valid for the uniform
1265 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1266 const char* function_name
,
1267 Program::UniformApiType api_type
);
1269 // Gets the type of a uniform for a location in the current program. Sets GL
1270 // errors if the current program is not valid. Returns true if the current
1271 // program is valid and the location exists. Adjusts count so it
1272 // does not overflow the uniform.
1273 bool PrepForSetUniformByLocation(GLint fake_location
,
1274 const char* function_name
,
1275 Program::UniformApiType api_type
,
1276 GLint
* real_location
,
1280 // Gets the service id for any simulated backbuffer fbo.
1281 GLuint
GetBackbufferServiceId() const;
1283 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1284 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1286 // Helper for glGetVertexAttrib
1287 void GetVertexAttribHelper(
1288 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1290 // Wrapper for glActiveTexture
1291 void DoActiveTexture(GLenum texture_unit
);
1293 // Wrapper for glAttachShader
1294 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1296 // Wrapper for glBindBuffer since we need to track the current targets.
1297 void DoBindBuffer(GLenum target
, GLuint buffer
);
1299 // Wrapper for glBindFramebuffer since we need to track the current targets.
1300 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1302 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1303 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1305 // Wrapper for glBindTexture since we need to track the current targets.
1306 void DoBindTexture(GLenum target
, GLuint texture
);
1308 // Wrapper for glBindVertexArrayOES
1309 void DoBindVertexArrayOES(GLuint array
);
1310 void EmulateVertexArrayState();
1312 // Wrapper for glBlitFramebufferCHROMIUM.
1313 void DoBlitFramebufferCHROMIUM(
1314 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1315 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1316 GLbitfield mask
, GLenum filter
);
1318 // Wrapper for glBufferSubData.
1319 void DoBufferSubData(
1320 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1322 // Wrapper for glCheckFramebufferStatus
1323 GLenum
DoCheckFramebufferStatus(GLenum target
);
1325 // Wrapper for glClear
1326 error::Error
DoClear(GLbitfield mask
);
1328 // Wrappers for various state.
1329 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1330 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1332 // Wrapper for glCompileShader.
1333 void DoCompileShader(GLuint shader
);
1335 // Wrapper for glDetachShader
1336 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1338 // Wrapper for glDisable
1339 void DoDisable(GLenum cap
);
1341 // Wrapper for glDisableVertexAttribArray.
1342 void DoDisableVertexAttribArray(GLuint index
);
1344 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1346 void DoDiscardFramebufferEXT(GLenum target
,
1347 GLsizei numAttachments
,
1348 const GLenum
* attachments
);
1350 // Wrapper for glEnable
1351 void DoEnable(GLenum cap
);
1353 // Wrapper for glEnableVertexAttribArray.
1354 void DoEnableVertexAttribArray(GLuint index
);
1356 // Wrapper for glFinish.
1359 // Wrapper for glFlush.
1362 // Wrapper for glFramebufferRenderbufffer.
1363 void DoFramebufferRenderbuffer(
1364 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1365 GLuint renderbuffer
);
1367 // Wrapper for glFramebufferTexture2D.
1368 void DoFramebufferTexture2D(
1369 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1372 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1373 void DoFramebufferTexture2DMultisample(
1374 GLenum target
, GLenum attachment
, GLenum textarget
,
1375 GLuint texture
, GLint level
, GLsizei samples
);
1377 // Common implementation for both DoFramebufferTexture2D wrappers.
1378 void DoFramebufferTexture2DCommon(const char* name
,
1379 GLenum target
, GLenum attachment
, GLenum textarget
,
1380 GLuint texture
, GLint level
, GLsizei samples
);
1382 // Wrapper for glFramebufferTextureLayer.
1383 void DoFramebufferTextureLayer(
1384 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1387 // Wrapper for glGenerateMipmap
1388 void DoGenerateMipmap(GLenum target
);
1390 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1391 // to account for different pname values defined in different extension
1393 GLenum
AdjustGetPname(GLenum pname
);
1395 // Wrapper for DoGetBooleanv.
1396 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1398 // Wrapper for DoGetFloatv.
1399 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1401 // Wrapper for glGetFramebufferAttachmentParameteriv.
1402 void DoGetFramebufferAttachmentParameteriv(
1403 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1405 // Wrapper for glGetIntegerv.
1406 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1408 // Gets the max value in a range in a buffer.
1409 GLuint
DoGetMaxValueInBufferCHROMIUM(
1410 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1412 // Wrapper for glGetBufferParameteriv.
1413 void DoGetBufferParameteriv(
1414 GLenum target
, GLenum pname
, GLint
* params
);
1416 // Wrapper for glGetProgramiv.
1417 void DoGetProgramiv(
1418 GLuint program_id
, GLenum pname
, GLint
* params
);
1420 // Wrapper for glRenderbufferParameteriv.
1421 void DoGetRenderbufferParameteriv(
1422 GLenum target
, GLenum pname
, GLint
* params
);
1424 // Wrapper for glGetShaderiv
1425 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1427 // Wrappers for glGetTexParameter.
1428 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1429 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1430 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1432 // Wrappers for glGetVertexAttrib.
1433 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1434 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1436 // Wrappers for glIsXXX functions.
1437 bool DoIsEnabled(GLenum cap
);
1438 bool DoIsBuffer(GLuint client_id
);
1439 bool DoIsFramebuffer(GLuint client_id
);
1440 bool DoIsProgram(GLuint client_id
);
1441 bool DoIsRenderbuffer(GLuint client_id
);
1442 bool DoIsShader(GLuint client_id
);
1443 bool DoIsTexture(GLuint client_id
);
1444 bool DoIsVertexArrayOES(GLuint client_id
);
1446 // Wrapper for glLinkProgram
1447 void DoLinkProgram(GLuint program
);
1449 // Wrapper for glRenderbufferStorage.
1450 void DoRenderbufferStorage(
1451 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1453 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1454 void DoRenderbufferStorageMultisampleCHROMIUM(
1455 GLenum target
, GLsizei samples
, GLenum internalformat
,
1456 GLsizei width
, GLsizei height
);
1458 // Handler for glRenderbufferStorageMultisampleEXT
1459 // (multisampled_render_to_texture).
1460 void DoRenderbufferStorageMultisampleEXT(
1461 GLenum target
, GLsizei samples
, GLenum internalformat
,
1462 GLsizei width
, GLsizei height
);
1464 // Common validation for multisample extensions.
1465 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1466 GLenum internalformat
,
1470 // Verifies that the currently bound multisample renderbuffer is valid
1471 // Very slow! Only done on platforms with driver bugs that return invalid
1472 // buffers under memory pressure
1473 bool VerifyMultisampleRenderbufferIntegrity(
1474 GLuint renderbuffer
, GLenum format
);
1476 // Wrapper for glReleaseShaderCompiler.
1477 void DoReleaseShaderCompiler() { }
1479 // Wrappers for glSamplerParameter*v functions.
1480 void DoSamplerParameterfv(
1481 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1482 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1484 // Wrappers for glTexParameter functions.
1485 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1486 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1487 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1488 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1490 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1491 // spec only these 2 functions can be used to set sampler uniforms.
1492 void DoUniform1i(GLint fake_location
, GLint v0
);
1493 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1494 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1495 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1496 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1498 // Wrappers for glUniformfv because some drivers don't correctly accept
1500 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1501 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1502 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1503 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1505 void DoUniformMatrix2fv(
1506 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1507 const GLfloat
* value
);
1508 void DoUniformMatrix3fv(
1509 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1510 const GLfloat
* value
);
1511 void DoUniformMatrix4fv(
1512 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1513 const GLfloat
* value
);
1515 bool SetVertexAttribValue(
1516 const char* function_name
, GLuint index
, const GLfloat
* value
);
1518 // Wrappers for glVertexAttrib??
1519 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1520 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1521 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1522 void DoVertexAttrib4f(
1523 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1524 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1525 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1526 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1527 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1529 // Wrapper for glViewport
1530 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1532 // Wrapper for glUseProgram
1533 void DoUseProgram(GLuint program
);
1535 // Wrapper for glValidateProgram.
1536 void DoValidateProgram(GLuint program_client_id
);
1538 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1539 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1540 void DoPopGroupMarkerEXT(void);
1542 // Gets the number of values that will be returned by glGetXXX. Returns
1543 // false if pname is unknown.
1544 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1546 // Checks if the current program and vertex attributes are valid for drawing.
1548 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1551 // Returns true if successful, simulated will be true if attrib0 was
1553 bool SimulateAttrib0(
1554 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1555 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1557 // If an image is bound to texture, this will call Will/DidUseTexImage
1559 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1560 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1562 // Returns false if textures were replaced.
1563 bool PrepareTexturesForRender();
1564 void RestoreStateForTextures();
1566 // Returns true if GL_FIXED attribs were simulated.
1567 bool SimulateFixedAttribs(
1568 const char* function_name
,
1569 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1570 void RestoreStateForSimulatedFixedAttribs();
1572 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1573 // cases (primcount is always 1 for non-instanced).
1574 error::Error
DoDrawArrays(
1575 const char* function_name
,
1576 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1578 error::Error
DoDrawElements(
1579 const char* function_name
,
1580 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1581 int32 offset
, GLsizei primcount
);
1583 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1584 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1585 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1588 return GL_TEXTURE_2D
;
1589 case GL_SAMPLER_CUBE
:
1590 return GL_TEXTURE_CUBE_MAP
;
1591 case GL_SAMPLER_EXTERNAL_OES
:
1592 return GL_TEXTURE_EXTERNAL_OES
;
1593 case GL_SAMPLER_2D_RECT_ARB
:
1594 return GL_TEXTURE_RECTANGLE_ARB
;
1601 // Gets the framebuffer info for a particular target.
1602 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1603 Framebuffer
* framebuffer
= NULL
;
1605 case GL_FRAMEBUFFER
:
1606 case GL_DRAW_FRAMEBUFFER_EXT
:
1607 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1609 case GL_READ_FRAMEBUFFER_EXT
:
1610 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1619 Renderbuffer
* GetRenderbufferInfoForTarget(
1621 Renderbuffer
* renderbuffer
= NULL
;
1623 case GL_RENDERBUFFER
:
1624 renderbuffer
= state_
.bound_renderbuffer
.get();
1630 return renderbuffer
;
1633 // Validates the program and location for a glGetUniform call and returns
1634 // a SizeResult setup to receive the result. Returns true if glGetUniform
1635 // should be called.
1636 bool GetUniformSetup(
1637 GLuint program
, GLint fake_location
,
1638 uint32 shm_id
, uint32 shm_offset
,
1639 error::Error
* error
, GLint
* real_location
, GLuint
* service_id
,
1640 void** result
, GLenum
* result_type
);
1642 void MaybeExitOnContextLost();
1643 bool WasContextLost() override
;
1644 bool WasContextLostByRobustnessExtension() override
;
1645 void LoseContext(uint32 reset_status
) override
;
1647 #if defined(OS_MACOSX)
1648 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1651 bool ValidateCompressedTexDimensions(
1652 const char* function_name
,
1653 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1654 bool ValidateCompressedTexFuncData(
1655 const char* function_name
,
1656 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1657 bool ValidateCompressedTexSubDimensions(
1658 const char* function_name
,
1659 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1660 GLsizei width
, GLsizei height
, GLenum format
,
1663 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1664 void PerformanceWarning(
1665 const char* filename
, int line
, const std::string
& msg
);
1667 const FeatureInfo::FeatureFlags
& features() const {
1668 return feature_info_
->feature_flags();
1671 const FeatureInfo::Workarounds
& workarounds() const {
1672 return feature_info_
->workarounds();
1675 bool ShouldDeferDraws() {
1676 return !offscreen_target_frame_buffer_
.get() &&
1677 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1678 surface_
->DeferDraws();
1681 bool ShouldDeferReads() {
1682 return !offscreen_target_frame_buffer_
.get() &&
1683 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1684 surface_
->DeferDraws();
1687 error::Error
WillAccessBoundFramebufferForDraw() {
1688 if (ShouldDeferDraws())
1689 return error::kDeferCommandUntilLater
;
1690 if (!offscreen_target_frame_buffer_
.get() &&
1691 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1692 !surface_
->SetBackbufferAllocation(true))
1693 return error::kLostContext
;
1694 return error::kNoError
;
1697 error::Error
WillAccessBoundFramebufferForRead() {
1698 if (ShouldDeferReads())
1699 return error::kDeferCommandUntilLater
;
1700 if (!offscreen_target_frame_buffer_
.get() &&
1701 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1702 !surface_
->SetBackbufferAllocation(true))
1703 return error::kLostContext
;
1704 return error::kNoError
;
1707 // Set remaining commands to process to 0 to force DoCommands to return
1708 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1709 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1711 void ProcessPendingReadPixels();
1712 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1714 // Generate a member function prototype for each command in an automated and
1716 #define GLES2_CMD_OP(name) \
1717 Error Handle##name(uint32 immediate_data_size, const void* data);
1719 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1723 // The GL context this decoder renders to on behalf of the client.
1724 scoped_refptr
<gfx::GLSurface
> surface_
;
1725 scoped_refptr
<gfx::GLContext
> context_
;
1727 // The ContextGroup for this decoder uses to track resources.
1728 scoped_refptr
<ContextGroup
> group_
;
1730 DebugMarkerManager debug_marker_manager_
;
1733 // All the state for this context.
1734 ContextState state_
;
1736 // Current width and height of the offscreen frame buffer.
1737 gfx::Size offscreen_size_
;
1739 // Util to help with GL.
1742 // unpack flip y as last set by glPixelStorei
1743 bool unpack_flip_y_
;
1745 // unpack (un)premultiply alpha as last set by glPixelStorei
1746 bool unpack_premultiply_alpha_
;
1747 bool unpack_unpremultiply_alpha_
;
1749 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1750 GLuint attrib_0_buffer_id_
;
1752 // The value currently in attrib_0.
1753 Vec4 attrib_0_value_
;
1755 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1756 bool attrib_0_buffer_matches_value_
;
1758 // The size of attrib 0.
1759 GLsizei attrib_0_size_
;
1761 // The buffer used to simulate GL_FIXED attribs.
1762 GLuint fixed_attrib_buffer_id_
;
1764 // The size of fiixed attrib buffer.
1765 GLsizei fixed_attrib_buffer_size_
;
1767 // The offscreen frame buffer that the client renders to. With EGL, the
1768 // depth and stencil buffers are separate. With regular GL there is a single
1769 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1770 // offscreen_target_stencil_render_buffer_ is unused.
1771 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1772 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1773 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1774 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1775 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1776 GLenum offscreen_target_color_format_
;
1777 GLenum offscreen_target_depth_format_
;
1778 GLenum offscreen_target_stencil_format_
;
1779 GLsizei offscreen_target_samples_
;
1780 GLboolean offscreen_target_buffer_preserved_
;
1782 // The copy that is saved when SwapBuffers is called.
1783 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1784 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1785 scoped_refptr
<TextureRef
>
1786 offscreen_saved_color_texture_info_
;
1788 // The copy that is used as the destination for multi-sample resolves.
1789 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1790 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1791 GLenum offscreen_saved_color_format_
;
1793 scoped_ptr
<QueryManager
> query_manager_
;
1795 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1797 scoped_ptr
<ImageManager
> image_manager_
;
1799 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1801 WaitSyncPointCallback wait_sync_point_callback_
;
1803 ShaderCacheCallback shader_cache_callback_
;
1805 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1807 // The format of the back buffer_
1808 GLenum back_buffer_color_format_
;
1809 bool back_buffer_has_depth_
;
1810 bool back_buffer_has_stencil_
;
1814 // Backbuffer attachments that are currently undefined.
1815 uint32 backbuffer_needs_clear_bits_
;
1817 // The current decoder error communicates the decoder error through command
1818 // processing functions that do not return the error value. Should be set only
1819 // if not returning an error.
1820 error::Error current_decoder_error_
;
1822 bool use_shader_translator_
;
1823 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
1824 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
1826 DisallowedFeatures disallowed_features_
;
1828 // Cached from ContextGroup
1829 const Validators
* validators_
;
1830 scoped_refptr
<FeatureInfo
> feature_info_
;
1834 // Number of commands remaining to be processed in DoCommands().
1835 int commands_to_process_
;
1837 bool has_robustness_extension_
;
1838 GLenum reset_status_
;
1839 bool reset_by_robustness_extension_
;
1840 bool supports_post_sub_buffer_
;
1842 // These flags are used to override the state of the shared feature_info_
1843 // member. Because the same FeatureInfo instance may be shared among many
1844 // contexts, the assumptions on the availablity of extensions in WebGL
1845 // contexts may be broken. These flags override the shared state to preserve
1847 bool force_webgl_glsl_validation_
;
1848 bool derivatives_explicitly_enabled_
;
1849 bool frag_depth_explicitly_enabled_
;
1850 bool draw_buffers_explicitly_enabled_
;
1851 bool shader_texture_lod_explicitly_enabled_
;
1853 bool compile_shader_always_succeeds_
;
1855 // An optional behaviour to lose the context and group when OOM.
1856 bool lose_context_when_out_of_memory_
;
1859 bool service_logging_
;
1861 #if defined(OS_MACOSX)
1862 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1863 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1866 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1867 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1869 // Cached values of the currently assigned viewport dimensions.
1870 GLsizei viewport_max_width_
;
1871 GLsizei viewport_max_height_
;
1873 // Command buffer stats.
1874 base::TimeDelta total_processing_commands_time_
;
1876 // States related to each manager.
1877 DecoderTextureState texture_state_
;
1878 DecoderFramebufferState framebuffer_state_
;
1880 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1881 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1882 const unsigned char* cb_command_trace_category_
;
1883 const unsigned char* gpu_decoder_category_
;
1884 int gpu_trace_level_
;
1885 bool gpu_trace_commands_
;
1886 bool gpu_debug_commands_
;
1888 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1890 // Used to validate multisample renderbuffers if needed
1891 GLuint validation_texture_
;
1892 GLuint validation_fbo_multisample_
;
1893 GLuint validation_fbo_
;
1895 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1896 uint32 immediate_data_size
,
1899 // A struct to hold info about each command.
1900 struct CommandInfo
{
1901 CmdHandler cmd_handler
;
1902 uint8 arg_flags
; // How to handle the arguments for this command
1903 uint8 cmd_flags
; // How to handle this command
1904 uint16 arg_count
; // How many arguments are expected for this command.
1907 // A table of CommandInfo for all the commands.
1908 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1910 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1913 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1914 #define GLES2_CMD_OP(name) \
1916 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1917 cmds::name::cmd_flags, \
1918 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1921 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1925 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1926 const char* function_name
, ErrorState
* error_state
)
1927 : function_name_(function_name
),
1928 error_state_(error_state
) {
1929 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1932 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1933 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1936 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1937 TextureUnit
& info
= state
->texture_units
[0];
1939 scoped_refptr
<TextureRef
> texture_ref
;
1942 texture_ref
= info
.bound_texture_2d
;
1944 case GL_TEXTURE_CUBE_MAP
:
1945 texture_ref
= info
.bound_texture_cube_map
;
1947 case GL_TEXTURE_EXTERNAL_OES
:
1948 texture_ref
= info
.bound_texture_external_oes
;
1950 case GL_TEXTURE_RECTANGLE_ARB
:
1951 texture_ref
= info
.bound_texture_rectangle_arb
;
1957 if (texture_ref
.get()) {
1958 last_id
= texture_ref
->service_id();
1963 glBindTexture(target
, last_id
);
1964 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1967 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1972 ScopedGLErrorSuppressor
suppressor(
1973 "ScopedTextureBinder::ctor", state_
->GetErrorState());
1975 // TODO(apatrick): Check if there are any other states that need to be reset
1976 // before binding a new texture.
1977 glActiveTexture(GL_TEXTURE0
);
1978 glBindTexture(target
, id
);
1981 ScopedTextureBinder::~ScopedTextureBinder() {
1982 ScopedGLErrorSuppressor
suppressor(
1983 "ScopedTextureBinder::dtor", state_
->GetErrorState());
1984 RestoreCurrentTextureBindings(state_
, target_
);
1987 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
1990 ScopedGLErrorSuppressor
suppressor(
1991 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
1992 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
1995 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1996 ScopedGLErrorSuppressor
suppressor(
1997 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
1998 state_
->RestoreRenderbufferBindings();
2001 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2003 : decoder_(decoder
) {
2004 ScopedGLErrorSuppressor
suppressor(
2005 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2006 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2007 decoder
->OnFboChanged();
2010 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2011 ScopedGLErrorSuppressor
suppressor(
2012 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2013 decoder_
->RestoreCurrentFramebufferBindings();
2016 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2017 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2018 : decoder_(decoder
) {
2019 resolve_and_bind_
= (
2020 decoder_
->offscreen_target_frame_buffer_
.get() &&
2021 decoder_
->IsOffscreenBufferMultisampled() &&
2022 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2023 enforce_internal_framebuffer
));
2024 if (!resolve_and_bind_
)
2027 ScopedGLErrorSuppressor
suppressor(
2028 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2029 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2030 decoder_
->offscreen_target_frame_buffer_
->id());
2033 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2034 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2035 new BackFramebuffer(decoder_
));
2036 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2037 decoder_
->offscreen_resolved_color_texture_
.reset(
2038 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2039 decoder_
->offscreen_resolved_color_texture_
->Create();
2041 DCHECK(decoder_
->offscreen_saved_color_format_
);
2042 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2043 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2045 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2046 decoder_
->offscreen_resolved_color_texture_
.get());
2047 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2048 GL_FRAMEBUFFER_COMPLETE
) {
2049 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2050 << "because offscreen resolved FBO was incomplete.";
2054 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2056 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2058 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2059 const int width
= decoder_
->offscreen_size_
.width();
2060 const int height
= decoder_
->offscreen_size_
.height();
2061 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2062 decoder
->BlitFramebufferHelper(0,
2070 GL_COLOR_BUFFER_BIT
,
2072 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2075 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2076 if (!resolve_and_bind_
)
2079 ScopedGLErrorSuppressor
suppressor(
2080 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2081 decoder_
->RestoreCurrentFramebufferBindings();
2082 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2083 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2087 BackTexture::BackTexture(
2088 MemoryTracker
* memory_tracker
,
2089 ContextState
* state
)
2090 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2092 bytes_allocated_(0),
2096 BackTexture::~BackTexture() {
2097 // This does not destroy the render texture because that would require that
2098 // the associated GL context was current. Just check that it was explicitly
2103 void BackTexture::Create() {
2104 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2105 state_
->GetErrorState());
2107 glGenTextures(1, &id_
);
2108 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2109 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2110 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2111 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2112 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2114 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2115 // never called on an offscreen context, no data will ever be uploaded to the
2116 // saved offscreen color texture (it is deferred until to when SwapBuffers
2117 // is called). My idea is that some nvidia drivers might have a bug where
2118 // deleting a texture that has never been populated might cause a
2121 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2123 bytes_allocated_
= 16u * 16u * 4u;
2124 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2127 bool BackTexture::AllocateStorage(
2128 const gfx::Size
& size
, GLenum format
, bool zero
) {
2130 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2131 state_
->GetErrorState());
2132 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2133 uint32 image_size
= 0;
2134 GLES2Util::ComputeImageDataSizes(
2135 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2138 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2142 scoped_ptr
<char[]> zero_data
;
2144 zero_data
.reset(new char[image_size
]);
2145 memset(zero_data
.get(), 0, image_size
);
2148 glTexImage2D(GL_TEXTURE_2D
,
2160 bool success
= glGetError() == GL_NO_ERROR
;
2162 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2163 bytes_allocated_
= image_size
;
2164 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2169 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2171 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2172 state_
->GetErrorState());
2173 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2174 glCopyTexImage2D(GL_TEXTURE_2D
,
2183 void BackTexture::Destroy() {
2185 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2186 state_
->GetErrorState());
2187 glDeleteTextures(1, &id_
);
2190 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2191 bytes_allocated_
= 0;
2194 void BackTexture::Invalidate() {
2198 BackRenderbuffer::BackRenderbuffer(
2199 RenderbufferManager
* renderbuffer_manager
,
2200 MemoryTracker
* memory_tracker
,
2201 ContextState
* state
)
2202 : renderbuffer_manager_(renderbuffer_manager
),
2203 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2205 bytes_allocated_(0),
2209 BackRenderbuffer::~BackRenderbuffer() {
2210 // This does not destroy the render buffer because that would require that
2211 // the associated GL context was current. Just check that it was explicitly
2216 void BackRenderbuffer::Create() {
2217 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2218 state_
->GetErrorState());
2220 glGenRenderbuffersEXT(1, &id_
);
2223 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2224 const gfx::Size
& size
,
2227 ScopedGLErrorSuppressor
suppressor(
2228 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2229 ScopedRenderBufferBinder
binder(state_
, id_
);
2231 uint32 estimated_size
= 0;
2232 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2233 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2237 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2242 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2247 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2254 bool success
= glGetError() == GL_NO_ERROR
;
2256 // Mark the previously allocated bytes as free.
2257 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2258 bytes_allocated_
= estimated_size
;
2259 // Track the newly allocated bytes.
2260 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2265 void BackRenderbuffer::Destroy() {
2267 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2268 state_
->GetErrorState());
2269 glDeleteRenderbuffersEXT(1, &id_
);
2272 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2273 bytes_allocated_
= 0;
2276 void BackRenderbuffer::Invalidate() {
2280 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2281 : decoder_(decoder
),
2285 BackFramebuffer::~BackFramebuffer() {
2286 // This does not destroy the frame buffer because that would require that
2287 // the associated GL context was current. Just check that it was explicitly
2292 void BackFramebuffer::Create() {
2293 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2294 decoder_
->GetErrorState());
2296 glGenFramebuffersEXT(1, &id_
);
2299 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2301 ScopedGLErrorSuppressor
suppressor(
2302 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2303 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2304 GLuint attach_id
= texture
? texture
->id() : 0;
2305 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2306 GL_COLOR_ATTACHMENT0
,
2312 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2313 BackRenderbuffer
* render_buffer
) {
2315 ScopedGLErrorSuppressor
suppressor(
2316 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2317 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2318 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2319 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2325 void BackFramebuffer::Destroy() {
2327 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2328 decoder_
->GetErrorState());
2329 glDeleteFramebuffersEXT(1, &id_
);
2334 void BackFramebuffer::Invalidate() {
2338 GLenum
BackFramebuffer::CheckStatus() {
2340 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2341 decoder_
->GetErrorState());
2342 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2343 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2346 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2347 return new GLES2DecoderImpl(group
);
2350 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2353 logger_(&debug_marker_manager_
),
2354 state_(group_
->feature_info(), this, &logger_
),
2355 unpack_flip_y_(false),
2356 unpack_premultiply_alpha_(false),
2357 unpack_unpremultiply_alpha_(false),
2358 attrib_0_buffer_id_(0),
2359 attrib_0_buffer_matches_value_(true),
2361 fixed_attrib_buffer_id_(0),
2362 fixed_attrib_buffer_size_(0),
2363 offscreen_target_color_format_(0),
2364 offscreen_target_depth_format_(0),
2365 offscreen_target_stencil_format_(0),
2366 offscreen_target_samples_(0),
2367 offscreen_target_buffer_preserved_(true),
2368 offscreen_saved_color_format_(0),
2369 back_buffer_color_format_(0),
2370 back_buffer_has_depth_(false),
2371 back_buffer_has_stencil_(false),
2372 surfaceless_(false),
2373 backbuffer_needs_clear_bits_(0),
2374 current_decoder_error_(error::kNoError
),
2375 use_shader_translator_(true),
2376 validators_(group_
->feature_info()->validators()),
2377 feature_info_(group_
->feature_info()),
2379 has_robustness_extension_(false),
2380 reset_status_(GL_NO_ERROR
),
2381 reset_by_robustness_extension_(false),
2382 supports_post_sub_buffer_(false),
2383 force_webgl_glsl_validation_(false),
2384 derivatives_explicitly_enabled_(false),
2385 frag_depth_explicitly_enabled_(false),
2386 draw_buffers_explicitly_enabled_(false),
2387 shader_texture_lod_explicitly_enabled_(false),
2388 compile_shader_always_succeeds_(false),
2389 lose_context_when_out_of_memory_(false),
2390 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2391 switches::kEnableGPUServiceLoggingGPU
)),
2392 viewport_max_width_(0),
2393 viewport_max_height_(0),
2394 texture_state_(group_
->feature_info()
2396 .texsubimage2d_faster_than_teximage2d
),
2397 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2398 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2399 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2400 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2401 gpu_trace_level_(2),
2402 gpu_trace_commands_(false),
2403 gpu_debug_commands_(false),
2404 validation_texture_(0),
2405 validation_fbo_multisample_(0),
2406 validation_fbo_(0) {
2409 attrib_0_value_
.v
[0] = 0.0f
;
2410 attrib_0_value_
.v
[1] = 0.0f
;
2411 attrib_0_value_
.v
[2] = 0.0f
;
2412 attrib_0_value_
.v
[3] = 1.0f
;
2414 // The shader translator is used for WebGL even when running on EGL
2415 // because additional restrictions are needed (like only enabling
2416 // GL_OES_standard_derivatives on demand). It is used for the unit
2417 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2418 // the empty string to CompileShader and this is not a valid shader.
2419 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2420 base::CommandLine::ForCurrentProcess()->HasSwitch(
2421 switches::kDisableGLSLTranslator
)) {
2422 use_shader_translator_
= false;
2426 GLES2DecoderImpl::~GLES2DecoderImpl() {
2429 bool GLES2DecoderImpl::Initialize(
2430 const scoped_refptr
<gfx::GLSurface
>& surface
,
2431 const scoped_refptr
<gfx::GLContext
>& context
,
2433 const gfx::Size
& size
,
2434 const DisallowedFeatures
& disallowed_features
,
2435 const std::vector
<int32
>& attribs
) {
2436 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2437 DCHECK(context
->IsCurrent(surface
.get()));
2438 DCHECK(!context_
.get());
2440 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2443 gpu_tracer_
.reset(new GPUTracer(this));
2444 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2446 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2447 switches::kEnableGPUDebugging
)) {
2451 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2452 switches::kEnableGPUCommandLogging
)) {
2453 set_log_commands(true);
2456 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2457 switches::kEnableUnsafeES3APIs
)) {
2458 set_unsafe_es3_apis_enabled(true);
2461 compile_shader_always_succeeds_
=
2462 base::CommandLine::ForCurrentProcess()->HasSwitch(
2463 switches::kCompileShaderAlwaysSucceeds
);
2465 // Take ownership of the context and surface. The surface can be replaced with
2470 ContextCreationAttribHelper attrib_parser
;
2471 if (!attrib_parser
.Parse(attribs
))
2474 // Save the loseContextWhenOutOfMemory context creation attribute.
2475 lose_context_when_out_of_memory_
=
2476 attrib_parser
.lose_context_when_out_of_memory
;
2478 // If the failIfMajorPerformanceCaveat context creation attribute was true
2479 // and we are using a software renderer, fail.
2480 if (attrib_parser
.fail_if_major_perf_caveat
&&
2481 feature_info_
->feature_flags().is_swiftshader
) {
2482 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2487 if (!group_
->Initialize(this, disallowed_features
)) {
2488 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2489 << "failed to initialize.";
2490 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2496 disallowed_features_
= disallowed_features
;
2498 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2499 vertex_array_manager_
.reset(new VertexArrayManager());
2501 GLuint default_vertex_attrib_service_id
= 0;
2502 if (features().native_vertex_array_object
) {
2503 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2504 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2507 state_
.default_vertex_attrib_manager
=
2508 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2510 state_
.default_vertex_attrib_manager
->Initialize(
2511 group_
->max_vertex_attribs(),
2512 feature_info_
->workarounds().init_vertex_attributes
);
2514 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2515 DoBindVertexArrayOES(0);
2517 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2519 image_manager_
.reset(new ImageManager
);
2521 util_
.set_num_compressed_texture_formats(
2522 validators_
->compressed_texture_format
.GetValues().size());
2524 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2525 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2526 // OpenGL ES 2.0 does not have this issue.
2527 glEnableVertexAttribArray(0);
2529 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2530 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2531 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2532 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2533 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2535 state_
.texture_units
.resize(group_
->max_texture_units());
2536 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2537 glActiveTexture(GL_TEXTURE0
+ tt
);
2538 // We want the last bind to be 2D.
2540 if (features().oes_egl_image_external
) {
2541 ref
= texture_manager()->GetDefaultTextureInfo(
2542 GL_TEXTURE_EXTERNAL_OES
);
2543 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2544 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2546 if (features().arb_texture_rectangle
) {
2547 ref
= texture_manager()->GetDefaultTextureInfo(
2548 GL_TEXTURE_RECTANGLE_ARB
);
2549 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2550 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2552 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2553 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2554 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2555 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2556 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2557 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2559 glActiveTexture(GL_TEXTURE0
);
2563 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2564 features().chromium_framebuffer_multisample
) {
2565 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2566 // max_sample_count must be initialized to a sane value. If
2567 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2568 GLint max_sample_count
= 1;
2569 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2570 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2573 offscreen_target_samples_
= 1;
2575 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2577 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2578 const bool rgb8_supported
=
2579 context_
->HasExtension("GL_OES_rgb8_rgba8");
2580 // The only available default render buffer formats in GLES2 have very
2581 // little precision. Don't enable multisampling unless 8-bit render
2582 // buffer formats are available--instead fall back to 8-bit textures.
2583 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2584 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2587 offscreen_target_samples_
= 1;
2588 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2592 // ANGLE only supports packed depth/stencil formats, so use it if it is
2594 const bool depth24_stencil8_supported
=
2595 feature_info_
->feature_flags().packed_depth24_stencil8
;
2596 VLOG(1) << "GL_OES_packed_depth_stencil "
2597 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2598 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2599 depth24_stencil8_supported
) {
2600 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2601 offscreen_target_stencil_format_
= 0;
2603 // It may be the case that this depth/stencil combination is not
2604 // supported, but this will be checked later by CheckFramebufferStatus.
2605 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2606 GL_DEPTH_COMPONENT16
: 0;
2607 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2608 GL_STENCIL_INDEX8
: 0;
2611 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2614 // If depth is requested at all, use the packed depth stencil format if
2615 // it's available, as some desktop GL drivers don't support any non-packed
2616 // formats for depth attachments.
2617 const bool depth24_stencil8_supported
=
2618 feature_info_
->feature_flags().packed_depth24_stencil8
;
2619 VLOG(1) << "GL_EXT_packed_depth_stencil "
2620 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2622 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2623 depth24_stencil8_supported
) {
2624 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2625 offscreen_target_stencil_format_
= 0;
2627 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2628 GL_DEPTH_COMPONENT
: 0;
2629 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2630 GL_STENCIL_INDEX
: 0;
2634 offscreen_saved_color_format_
= attrib_parser
.alpha_size
> 0 ?
2637 // Create the target frame buffer. This is the one that the client renders
2639 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2640 offscreen_target_frame_buffer_
->Create();
2641 // Due to GLES2 format limitations, either the color texture (for
2642 // non-multisampling) or the color render buffer (for multisampling) will be
2643 // attached to the offscreen frame buffer. The render buffer has more
2644 // limited formats available to it, but the texture can't do multisampling.
2645 if (IsOffscreenBufferMultisampled()) {
2646 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2647 renderbuffer_manager(), memory_tracker(), &state_
));
2648 offscreen_target_color_render_buffer_
->Create();
2650 offscreen_target_color_texture_
.reset(new BackTexture(
2651 memory_tracker(), &state_
));
2652 offscreen_target_color_texture_
->Create();
2654 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2655 renderbuffer_manager(), memory_tracker(), &state_
));
2656 offscreen_target_depth_render_buffer_
->Create();
2657 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2658 renderbuffer_manager(), memory_tracker(), &state_
));
2659 offscreen_target_stencil_render_buffer_
->Create();
2661 // Create the saved offscreen texture. The target frame buffer is copied
2662 // here when SwapBuffers is called.
2663 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2664 offscreen_saved_frame_buffer_
->Create();
2666 offscreen_saved_color_texture_
.reset(new BackTexture(
2667 memory_tracker(), &state_
));
2668 offscreen_saved_color_texture_
->Create();
2670 // Allocate the render buffers at their initial size and check the status
2671 // of the frame buffers is okay.
2672 if (!ResizeOffscreenFrameBuffer(size
)) {
2673 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2678 // Allocate the offscreen saved color texture.
2679 DCHECK(offscreen_saved_color_format_
);
2680 offscreen_saved_color_texture_
->AllocateStorage(
2681 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2683 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2684 offscreen_saved_color_texture_
.get());
2685 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2686 GL_FRAMEBUFFER_COMPLETE
) {
2687 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2692 // Bind to the new default frame buffer (the offscreen target frame buffer).
2693 // This should now be associated with ID zero.
2694 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2696 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2697 // These are NOT if the back buffer has these proprorties. They are
2698 // if we want the command buffer to enforce them regardless of what
2699 // the real backbuffer is assuming the real back buffer gives us more than
2700 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2701 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2702 // can't do anything about that.
2704 if (!surfaceless_
) {
2706 glGetIntegerv(GL_ALPHA_BITS
, &v
);
2707 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2708 // the user requested RGB then RGB. If the user did not specify a
2709 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2710 back_buffer_color_format_
=
2711 (attrib_parser
.alpha_size
!= 0 && v
> 0) ? GL_RGBA
: GL_RGB
;
2712 glGetIntegerv(GL_DEPTH_BITS
, &v
);
2713 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && v
> 0;
2714 glGetIntegerv(GL_STENCIL_BITS
, &v
);
2715 back_buffer_has_stencil_
= attrib_parser
.stencil_size
!= 0 && v
> 0;
2719 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2720 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2721 // isn't well documented; it was discovered in the Khronos OpenGL ES
2722 // mailing list archives. It also implicitly enables the desktop GL
2723 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2724 // variable in fragment shaders.
2725 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2726 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2727 glEnable(GL_POINT_SPRITE
);
2730 has_robustness_extension_
=
2731 context
->HasExtension("GL_ARB_robustness") ||
2732 context
->HasExtension("GL_KHR_robustness") ||
2733 context
->HasExtension("GL_EXT_robustness");
2735 if (!InitializeShaderTranslator()) {
2739 state_
.viewport_width
= size
.width();
2740 state_
.viewport_height
= size
.height();
2742 GLint viewport_params
[4] = { 0 };
2743 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2744 viewport_max_width_
= viewport_params
[0];
2745 viewport_max_height_
= viewport_params
[1];
2747 state_
.scissor_width
= state_
.viewport_width
;
2748 state_
.scissor_height
= state_
.viewport_height
;
2750 // Set all the default state because some GL drivers get it wrong.
2751 state_
.InitCapabilities(NULL
);
2752 state_
.InitState(NULL
);
2753 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2755 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2756 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2757 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2758 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2759 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2761 bool call_gl_clear
= !surfaceless_
;
2762 #if defined(OS_ANDROID)
2763 // Temporary workaround for Android WebView because this clear ignores the
2764 // clip and corrupts that external UI of the App. Not calling glClear is ok
2765 // because the system already clears the buffer before each draw. Proper
2766 // fix might be setting the scissor clip properly before initialize. See
2767 // crbug.com/259023 for details.
2768 call_gl_clear
= surface_
->GetHandle();
2770 if (call_gl_clear
) {
2771 // Clear the backbuffer.
2772 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2775 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2776 if (feature_info_
->workarounds()
2777 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2778 !surface
->IsOffscreen())
2779 supports_post_sub_buffer_
= false;
2781 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2782 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2785 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2786 context_
->SetUnbindFboOnMakeCurrent();
2789 // Only compositor contexts are known to use only the subset of GL
2790 // that can be safely migrated between the iGPU and the dGPU. Mark
2791 // those contexts as safe to forcibly transition between the GPUs.
2792 // http://crbug.com/180876, http://crbug.com/227228
2794 context_
->SetSafeToForceGpuSwitch();
2796 async_pixel_transfer_manager_
.reset(
2797 AsyncPixelTransferManager::Create(context
.get()));
2798 async_pixel_transfer_manager_
->Initialize(texture_manager());
2800 if (workarounds().gl_clear_broken
) {
2801 DCHECK(!clear_framebuffer_blit_
.get());
2802 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2803 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2804 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2808 framebuffer_manager()->AddObserver(this);
2813 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2814 DCHECK(initialized());
2817 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2818 Capabilities::ShaderPrecision
* shader_precision
) {
2819 GLint range
[2] = {0, 0};
2820 GLint precision
= 0;
2821 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2822 shader_precision
->min_range
= range
[0];
2823 shader_precision
->max_range
= range
[1];
2824 shader_precision
->precision
= precision
;
2826 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2827 &caps
.max_combined_texture_image_units
);
2828 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2829 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2830 &caps
.max_fragment_uniform_vectors
);
2831 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2832 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2833 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2834 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2835 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2836 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2837 &caps
.max_vertex_texture_image_units
);
2838 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2839 &caps
.max_vertex_uniform_vectors
);
2840 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2841 &caps
.num_compressed_texture_formats
);
2842 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2843 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2844 &caps
.bind_generates_resource_chromium
);
2845 if (unsafe_es3_apis_enabled()) {
2846 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
2847 &caps
.max_transform_feedback_separate_attribs
);
2848 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
2849 &caps
.max_uniform_buffer_bindings
);
2850 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
2851 &caps
.uniform_buffer_offset_alignment
);
2854 caps
.egl_image_external
=
2855 feature_info_
->feature_flags().oes_egl_image_external
;
2856 caps
.texture_format_bgra8888
=
2857 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2858 caps
.texture_format_etc1
=
2859 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2860 caps
.texture_format_etc1_npot
=
2861 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2862 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2863 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2864 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2865 caps
.discard_framebuffer
=
2866 feature_info_
->feature_flags().ext_discard_framebuffer
;
2867 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2869 #if defined(OS_MACOSX)
2870 // This is unconditionally true on mac, no need to test for it at runtime.
2871 caps
.iosurface
= true;
2874 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2877 caps
.blend_equation_advanced
=
2878 feature_info_
->feature_flags().blend_equation_advanced
;
2879 caps
.blend_equation_advanced_coherent
=
2880 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
2881 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
2885 void GLES2DecoderImpl::UpdateCapabilities() {
2886 util_
.set_num_compressed_texture_formats(
2887 validators_
->compressed_texture_format
.GetValues().size());
2888 util_
.set_num_shader_binary_formats(
2889 validators_
->shader_binary_format
.GetValues().size());
2892 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2893 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2895 if (!use_shader_translator_
) {
2898 ShBuiltInResources resources
;
2899 ShInitBuiltInResources(&resources
);
2900 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2901 resources
.MaxVertexUniformVectors
=
2902 group_
->max_vertex_uniform_vectors();
2903 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2904 resources
.MaxVertexTextureImageUnits
=
2905 group_
->max_vertex_texture_image_units();
2906 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2907 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2908 resources
.MaxFragmentUniformVectors
=
2909 group_
->max_fragment_uniform_vectors();
2910 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2911 resources
.MaxExpressionComplexity
= 256;
2912 resources
.MaxCallStackDepth
= 256;
2914 GLint range
[2] = { 0, 0 };
2915 GLint precision
= 0;
2916 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2918 resources
.FragmentPrecisionHigh
=
2919 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2921 if (force_webgl_glsl_validation_
) {
2922 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2923 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2924 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2925 if (!draw_buffers_explicitly_enabled_
)
2926 resources
.MaxDrawBuffers
= 1;
2927 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2928 resources
.NV_draw_buffers
=
2929 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
2931 resources
.OES_standard_derivatives
=
2932 features().oes_standard_derivatives
? 1 : 0;
2933 resources
.ARB_texture_rectangle
=
2934 features().arb_texture_rectangle
? 1 : 0;
2935 resources
.OES_EGL_image_external
=
2936 features().oes_egl_image_external
? 1 : 0;
2937 resources
.EXT_draw_buffers
=
2938 features().ext_draw_buffers
? 1 : 0;
2939 resources
.EXT_frag_depth
=
2940 features().ext_frag_depth
? 1 : 0;
2941 resources
.EXT_shader_texture_lod
=
2942 features().ext_shader_texture_lod
? 1 : 0;
2943 resources
.NV_draw_buffers
=
2944 features().nv_draw_buffers
? 1 : 0;
2947 ShShaderSpec shader_spec
= force_webgl_glsl_validation_
? SH_WEBGL_SPEC
2949 if (shader_spec
== SH_WEBGL_SPEC
&& features().enable_shader_name_hashing
)
2950 resources
.HashFunction
= &CityHash64
;
2952 resources
.HashFunction
= NULL
;
2953 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
2954 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
2955 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
2956 int driver_bug_workarounds
= 0;
2957 if (workarounds().needs_glsl_built_in_function_emulation
)
2958 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
2959 if (workarounds().init_gl_position_in_vertex_shader
)
2960 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
2961 if (workarounds().unfold_short_circuit_as_ternary_operation
)
2962 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
2963 if (workarounds().init_varyings_without_static_use
)
2964 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
2965 if (workarounds().unroll_for_loop_with_sampler_array_index
)
2966 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
2967 if (workarounds().scalarize_vec_and_mat_constructor_args
)
2968 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
2969 if (workarounds().regenerate_struct_names
)
2970 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
2972 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2973 switches::kEmulateShaderPrecision
))
2974 resources
.WEBGL_debug_shader_precision
= true;
2976 vertex_translator_
= shader_translator_cache()->GetTranslator(
2980 implementation_type
,
2981 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2982 if (!vertex_translator_
.get()) {
2983 LOG(ERROR
) << "Could not initialize vertex shader translator.";
2988 fragment_translator_
= shader_translator_cache()->GetTranslator(
2992 implementation_type
,
2993 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
2994 if (!fragment_translator_
.get()) {
2995 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3002 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3003 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3004 if (GetBuffer(client_ids
[ii
])) {
3008 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3009 glGenBuffersARB(n
, service_ids
.get());
3010 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3011 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3016 bool GLES2DecoderImpl::GenFramebuffersHelper(
3017 GLsizei n
, const GLuint
* client_ids
) {
3018 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3019 if (GetFramebuffer(client_ids
[ii
])) {
3023 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3024 glGenFramebuffersEXT(n
, service_ids
.get());
3025 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3026 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3031 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3032 GLsizei n
, const GLuint
* client_ids
) {
3033 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3034 if (GetRenderbuffer(client_ids
[ii
])) {
3038 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3039 glGenRenderbuffersEXT(n
, service_ids
.get());
3040 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3041 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3046 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3047 const GLuint
* client_ids
) {
3048 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3049 if (GetValuebuffer(client_ids
[ii
])) {
3053 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3054 CreateValuebuffer(client_ids
[ii
]);
3059 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3060 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3061 if (GetTexture(client_ids
[ii
])) {
3065 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3066 glGenTextures(n
, service_ids
.get());
3067 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3068 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3073 void GLES2DecoderImpl::DeleteBuffersHelper(
3074 GLsizei n
, const GLuint
* client_ids
) {
3075 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3076 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3077 if (buffer
&& !buffer
->IsDeleted()) {
3078 state_
.vertex_attrib_manager
->Unbind(buffer
);
3079 if (state_
.bound_array_buffer
.get() == buffer
) {
3080 state_
.bound_array_buffer
= NULL
;
3082 RemoveBuffer(client_ids
[ii
]);
3087 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3088 GLsizei n
, const GLuint
* client_ids
) {
3089 bool supports_separate_framebuffer_binds
=
3090 features().chromium_framebuffer_multisample
;
3092 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3093 Framebuffer
* framebuffer
=
3094 GetFramebuffer(client_ids
[ii
]);
3095 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3096 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3097 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3098 framebuffer_state_
.clear_state_dirty
= true;
3099 GLenum target
= supports_separate_framebuffer_binds
?
3100 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3101 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3103 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3104 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3105 GLenum target
= supports_separate_framebuffer_binds
?
3106 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3107 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3110 RemoveFramebuffer(client_ids
[ii
]);
3115 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3116 GLsizei n
, const GLuint
* client_ids
) {
3117 bool supports_separate_framebuffer_binds
=
3118 features().chromium_framebuffer_multisample
;
3119 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3120 Renderbuffer
* renderbuffer
=
3121 GetRenderbuffer(client_ids
[ii
]);
3122 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3123 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3124 state_
.bound_renderbuffer
= NULL
;
3126 // Unbind from current framebuffers.
3127 if (supports_separate_framebuffer_binds
) {
3128 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3129 framebuffer_state_
.bound_read_framebuffer
3130 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3132 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3133 framebuffer_state_
.bound_draw_framebuffer
3134 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3137 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3138 framebuffer_state_
.bound_draw_framebuffer
3139 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3142 framebuffer_state_
.clear_state_dirty
= true;
3143 RemoveRenderbuffer(client_ids
[ii
]);
3148 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3150 const GLuint
* client_ids
) {
3151 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3152 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3154 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3155 state_
.bound_valuebuffer
= NULL
;
3157 RemoveValuebuffer(client_ids
[ii
]);
3162 void GLES2DecoderImpl::DeleteTexturesHelper(
3163 GLsizei n
, const GLuint
* client_ids
) {
3164 bool supports_separate_framebuffer_binds
=
3165 features().chromium_framebuffer_multisample
;
3166 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3167 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3169 Texture
* texture
= texture_ref
->texture();
3170 if (texture
->IsAttachedToFramebuffer()) {
3171 framebuffer_state_
.clear_state_dirty
= true;
3173 // Unbind texture_ref from texture_ref units.
3174 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3175 state_
.texture_units
[jj
].Unbind(texture_ref
);
3177 // Unbind from current framebuffers.
3178 if (supports_separate_framebuffer_binds
) {
3179 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3180 framebuffer_state_
.bound_read_framebuffer
3181 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3183 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3184 framebuffer_state_
.bound_draw_framebuffer
3185 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3188 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3189 framebuffer_state_
.bound_draw_framebuffer
3190 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3193 #if defined(OS_MACOSX)
3194 GLuint service_id
= texture
->service_id();
3195 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3196 ReleaseIOSurfaceForTexture(service_id
);
3199 RemoveTexture(client_ids
[ii
]);
3204 // } // anonymous namespace
3206 bool GLES2DecoderImpl::MakeCurrent() {
3207 if (!context_
.get())
3210 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3211 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3213 MaybeExitOnContextLost();
3218 ProcessFinishedAsyncTransfers();
3220 // Rebind the FBO if it was unbound by the context.
3221 if (workarounds().unbind_fbo_on_context_switch
)
3222 RestoreFramebufferBindings();
3224 framebuffer_state_
.clear_state_dirty
= true;
3229 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3230 ProcessPendingReadPixels();
3231 if (engine() && query_manager_
.get())
3232 query_manager_
->ProcessPendingTransferQueries();
3234 // TODO(epenner): Is there a better place to do this?
3235 // This needs to occur before we execute any batch of commands
3236 // from the client, as the client may have recieved an async
3237 // completion while issuing those commands.
3238 // "DidFlushStart" would be ideal if we had such a callback.
3239 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3242 static void RebindCurrentFramebuffer(
3244 Framebuffer
* framebuffer
,
3245 GLuint back_buffer_service_id
) {
3246 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3248 if (framebuffer_id
== 0) {
3249 framebuffer_id
= back_buffer_service_id
;
3252 glBindFramebufferEXT(target
, framebuffer_id
);
3255 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3256 framebuffer_state_
.clear_state_dirty
= true;
3258 if (!features().chromium_framebuffer_multisample
) {
3259 RebindCurrentFramebuffer(
3261 framebuffer_state_
.bound_draw_framebuffer
.get(),
3262 GetBackbufferServiceId());
3264 RebindCurrentFramebuffer(
3265 GL_READ_FRAMEBUFFER_EXT
,
3266 framebuffer_state_
.bound_read_framebuffer
.get(),
3267 GetBackbufferServiceId());
3268 RebindCurrentFramebuffer(
3269 GL_DRAW_FRAMEBUFFER_EXT
,
3270 framebuffer_state_
.bound_draw_framebuffer
.get(),
3271 GetBackbufferServiceId());
3276 bool GLES2DecoderImpl::CheckFramebufferValid(
3277 Framebuffer
* framebuffer
,
3278 GLenum target
, const char* func_name
) {
3282 if (backbuffer_needs_clear_bits_
) {
3283 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3284 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3285 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3287 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3288 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3290 state_
.SetDeviceDepthMask(GL_TRUE
);
3291 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3292 bool reset_draw_buffer
= false;
3293 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3294 group_
->draw_buffer() == GL_NONE
) {
3295 reset_draw_buffer
= true;
3296 GLenum buf
= GL_BACK
;
3297 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3298 buf
= GL_COLOR_ATTACHMENT0
;
3299 glDrawBuffersARB(1, &buf
);
3301 glClear(backbuffer_needs_clear_bits_
);
3302 if (reset_draw_buffer
) {
3303 GLenum buf
= GL_NONE
;
3304 glDrawBuffersARB(1, &buf
);
3306 backbuffer_needs_clear_bits_
= 0;
3307 RestoreClearState();
3312 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3316 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3317 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3319 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3323 // Are all the attachments cleared?
3324 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3325 texture_manager()->HaveUnclearedMips()) {
3326 if (!framebuffer
->IsCleared()) {
3327 // Can we clear them?
3328 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3329 GL_FRAMEBUFFER_COMPLETE
) {
3331 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3332 "framebuffer incomplete (clear)");
3335 ClearUnclearedAttachments(target
, framebuffer
);
3339 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3340 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3341 GL_FRAMEBUFFER_COMPLETE
) {
3343 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3344 "framebuffer incomplete (check)");
3347 framebuffer_manager()->MarkAsComplete(framebuffer
);
3350 // NOTE: At this point we don't know if the framebuffer is complete but
3351 // we DO know that everything that needs to be cleared has been cleared.
3355 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3356 if (!features().chromium_framebuffer_multisample
) {
3357 bool valid
= CheckFramebufferValid(
3358 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3366 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3367 GL_DRAW_FRAMEBUFFER_EXT
,
3369 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3370 GL_READ_FRAMEBUFFER_EXT
,
3374 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3375 const char* func_name
) {
3376 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3377 framebuffer_state_
.bound_read_framebuffer
.get() :
3378 framebuffer_state_
.bound_draw_framebuffer
.get();
3381 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3383 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3389 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3390 TextureRef
* texture
, GLint level
) {
3391 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3392 framebuffer_state_
.bound_read_framebuffer
.get() :
3393 framebuffer_state_
.bound_draw_framebuffer
.get();
3396 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3397 GL_COLOR_ATTACHMENT0
);
3400 return attachment
->FormsFeedbackLoop(texture
, level
);
3403 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3404 Framebuffer
* framebuffer
=
3405 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3406 if (framebuffer
!= NULL
) {
3407 const Framebuffer::Attachment
* attachment
=
3408 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3410 return gfx::Size(attachment
->width(), attachment
->height());
3412 return gfx::Size(0, 0);
3413 } else if (offscreen_target_frame_buffer_
.get()) {
3414 return offscreen_size_
;
3416 return surface_
->GetSize();
3420 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3421 Framebuffer
* framebuffer
=
3422 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3423 if (framebuffer
!= NULL
) {
3424 return framebuffer
->GetColorAttachmentTextureType();
3426 return GL_UNSIGNED_BYTE
;
3430 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3431 Framebuffer
* framebuffer
=
3432 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3433 if (framebuffer
!= NULL
) {
3434 return framebuffer
->GetColorAttachmentFormat();
3435 } else if (offscreen_target_frame_buffer_
.get()) {
3436 return offscreen_target_color_format_
;
3438 return back_buffer_color_format_
;
3442 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3443 Framebuffer
* framebuffer
=
3444 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3445 if (framebuffer
!= NULL
) {
3446 return framebuffer
->GetColorAttachmentFormat();
3447 } else if (offscreen_target_frame_buffer_
.get()) {
3448 return offscreen_target_color_format_
;
3450 return back_buffer_color_format_
;
3454 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3455 if (!offscreen_saved_color_texture_info_
.get())
3457 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3458 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3459 texture_manager()->SetLevelInfo(
3460 offscreen_saved_color_texture_info_
.get(),
3464 offscreen_size_
.width(),
3465 offscreen_size_
.height(),
3471 texture_manager()->SetParameteri(
3472 "UpdateParentTextureInfo",
3474 offscreen_saved_color_texture_info_
.get(),
3475 GL_TEXTURE_MAG_FILTER
,
3477 texture_manager()->SetParameteri(
3478 "UpdateParentTextureInfo",
3480 offscreen_saved_color_texture_info_
.get(),
3481 GL_TEXTURE_MIN_FILTER
,
3483 texture_manager()->SetParameteri(
3484 "UpdateParentTextureInfo",
3486 offscreen_saved_color_texture_info_
.get(),
3489 texture_manager()->SetParameteri(
3490 "UpdateParentTextureInfo",
3492 offscreen_saved_color_texture_info_
.get(),
3495 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3497 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3500 void GLES2DecoderImpl::SetResizeCallback(
3501 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3502 resize_callback_
= callback
;
3505 Logger
* GLES2DecoderImpl::GetLogger() {
3509 void GLES2DecoderImpl::BeginDecoding() {
3510 gpu_tracer_
->BeginDecoding();
3511 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3512 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3513 (*cb_command_trace_category_
!= 0);
3516 void GLES2DecoderImpl::EndDecoding() {
3517 gpu_tracer_
->EndDecoding();
3520 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3521 return state_
.GetErrorState();
3524 void GLES2DecoderImpl::SetShaderCacheCallback(
3525 const ShaderCacheCallback
& callback
) {
3526 shader_cache_callback_
= callback
;
3529 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3530 const WaitSyncPointCallback
& callback
) {
3531 wait_sync_point_callback_
= callback
;
3534 AsyncPixelTransferManager
*
3535 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3536 return async_pixel_transfer_manager_
.get();
3539 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3540 async_pixel_transfer_manager_
.reset();
3543 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3544 AsyncPixelTransferManager
* manager
) {
3545 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3548 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3549 uint32
* service_texture_id
) {
3550 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3552 *service_texture_id
= texture_ref
->service_id();
3558 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3559 return texture_state_
.texture_upload_count
+
3560 async_pixel_transfer_manager_
->GetTextureUploadCount();
3563 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3564 return texture_state_
.total_texture_upload_time
+
3565 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3568 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3569 return total_processing_commands_time_
;
3572 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3573 total_processing_commands_time_
+= time
;
3576 void GLES2DecoderImpl::Destroy(bool have_context
) {
3580 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3582 // Unbind everything.
3583 state_
.vertex_attrib_manager
= NULL
;
3584 state_
.default_vertex_attrib_manager
= NULL
;
3585 state_
.texture_units
.clear();
3586 state_
.bound_array_buffer
= NULL
;
3587 state_
.current_queries
.clear();
3588 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3589 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3590 state_
.bound_renderbuffer
= NULL
;
3591 state_
.bound_valuebuffer
= NULL
;
3593 if (offscreen_saved_color_texture_info_
.get()) {
3594 DCHECK(offscreen_target_color_texture_
);
3595 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3596 offscreen_saved_color_texture_
->id());
3597 offscreen_saved_color_texture_
->Invalidate();
3598 offscreen_saved_color_texture_info_
= NULL
;
3601 if (copy_texture_CHROMIUM_
.get()) {
3602 copy_texture_CHROMIUM_
->Destroy();
3603 copy_texture_CHROMIUM_
.reset();
3606 clear_framebuffer_blit_
.reset();
3608 if (state_
.current_program
.get()) {
3609 program_manager()->UnuseProgram(shader_manager(),
3610 state_
.current_program
.get());
3613 if (attrib_0_buffer_id_
) {
3614 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3616 if (fixed_attrib_buffer_id_
) {
3617 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3620 if (validation_texture_
) {
3621 glDeleteTextures(1, &validation_texture_
);
3622 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3623 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3626 if (offscreen_target_frame_buffer_
.get())
3627 offscreen_target_frame_buffer_
->Destroy();
3628 if (offscreen_target_color_texture_
.get())
3629 offscreen_target_color_texture_
->Destroy();
3630 if (offscreen_target_color_render_buffer_
.get())
3631 offscreen_target_color_render_buffer_
->Destroy();
3632 if (offscreen_target_depth_render_buffer_
.get())
3633 offscreen_target_depth_render_buffer_
->Destroy();
3634 if (offscreen_target_stencil_render_buffer_
.get())
3635 offscreen_target_stencil_render_buffer_
->Destroy();
3636 if (offscreen_saved_frame_buffer_
.get())
3637 offscreen_saved_frame_buffer_
->Destroy();
3638 if (offscreen_saved_color_texture_
.get())
3639 offscreen_saved_color_texture_
->Destroy();
3640 if (offscreen_resolved_frame_buffer_
.get())
3641 offscreen_resolved_frame_buffer_
->Destroy();
3642 if (offscreen_resolved_color_texture_
.get())
3643 offscreen_resolved_color_texture_
->Destroy();
3645 if (offscreen_target_frame_buffer_
.get())
3646 offscreen_target_frame_buffer_
->Invalidate();
3647 if (offscreen_target_color_texture_
.get())
3648 offscreen_target_color_texture_
->Invalidate();
3649 if (offscreen_target_color_render_buffer_
.get())
3650 offscreen_target_color_render_buffer_
->Invalidate();
3651 if (offscreen_target_depth_render_buffer_
.get())
3652 offscreen_target_depth_render_buffer_
->Invalidate();
3653 if (offscreen_target_stencil_render_buffer_
.get())
3654 offscreen_target_stencil_render_buffer_
->Invalidate();
3655 if (offscreen_saved_frame_buffer_
.get())
3656 offscreen_saved_frame_buffer_
->Invalidate();
3657 if (offscreen_saved_color_texture_
.get())
3658 offscreen_saved_color_texture_
->Invalidate();
3659 if (offscreen_resolved_frame_buffer_
.get())
3660 offscreen_resolved_frame_buffer_
->Invalidate();
3661 if (offscreen_resolved_color_texture_
.get())
3662 offscreen_resolved_color_texture_
->Invalidate();
3665 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3666 // Otherwise, we can leak objects. http://crbug.com/258772.
3667 // state_.current_program must be reset before group_ is reset because
3668 // the later deletes the ProgramManager object that referred by
3669 // state_.current_program object.
3670 state_
.current_program
= NULL
;
3672 copy_texture_CHROMIUM_
.reset();
3673 clear_framebuffer_blit_
.reset();
3675 if (query_manager_
.get()) {
3676 query_manager_
->Destroy(have_context
);
3677 query_manager_
.reset();
3680 if (vertex_array_manager_
.get()) {
3681 vertex_array_manager_
->Destroy(have_context
);
3682 vertex_array_manager_
.reset();
3685 if (image_manager_
.get()) {
3686 image_manager_
->Destroy(have_context
);
3687 image_manager_
.reset();
3690 offscreen_target_frame_buffer_
.reset();
3691 offscreen_target_color_texture_
.reset();
3692 offscreen_target_color_render_buffer_
.reset();
3693 offscreen_target_depth_render_buffer_
.reset();
3694 offscreen_target_stencil_render_buffer_
.reset();
3695 offscreen_saved_frame_buffer_
.reset();
3696 offscreen_saved_color_texture_
.reset();
3697 offscreen_resolved_frame_buffer_
.reset();
3698 offscreen_resolved_color_texture_
.reset();
3700 // Need to release these before releasing |group_| which may own the
3701 // ShaderTranslatorCache.
3702 fragment_translator_
= NULL
;
3703 vertex_translator_
= NULL
;
3705 // Should destroy the transfer manager before the texture manager held
3706 // by the context group.
3707 async_pixel_transfer_manager_
.reset();
3710 framebuffer_manager()->RemoveObserver(this);
3711 group_
->Destroy(this, have_context
);
3715 if (context_
.get()) {
3716 context_
->ReleaseCurrent(NULL
);
3720 #if defined(OS_MACOSX)
3721 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3722 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3723 CFRelease(it
->second
);
3725 texture_to_io_surface_map_
.clear();
3729 void GLES2DecoderImpl::SetSurface(
3730 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3731 DCHECK(context_
->IsCurrent(NULL
));
3732 DCHECK(surface_
.get());
3734 RestoreCurrentFramebufferBindings();
3737 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3738 if (!offscreen_saved_color_texture_
.get()) {
3739 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3742 if (!offscreen_saved_color_texture_info_
.get()) {
3743 GLuint service_id
= offscreen_saved_color_texture_
->id();
3744 offscreen_saved_color_texture_info_
= TextureRef::Create(
3745 texture_manager(), 0, service_id
);
3746 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3748 UpdateParentTextureInfo();
3750 mailbox_manager()->ProduceTexture(
3751 mailbox
, offscreen_saved_color_texture_info_
->texture());
3754 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3755 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3756 if (!is_offscreen
) {
3757 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3758 << " with an onscreen framebuffer.";
3762 if (offscreen_size_
== size
)
3765 offscreen_size_
= size
;
3766 int w
= offscreen_size_
.width();
3767 int h
= offscreen_size_
.height();
3768 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3769 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3770 << "to allocate storage due to excessive dimensions.";
3774 // Reallocate the offscreen target buffers.
3775 DCHECK(offscreen_target_color_format_
);
3776 if (IsOffscreenBufferMultisampled()) {
3777 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3778 feature_info_
.get(),
3780 offscreen_target_color_format_
,
3781 offscreen_target_samples_
)) {
3782 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3783 << "to allocate storage for offscreen target color buffer.";
3787 if (!offscreen_target_color_texture_
->AllocateStorage(
3788 offscreen_size_
, offscreen_target_color_format_
, false)) {
3789 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3790 << "to allocate storage for offscreen target color texture.";
3794 if (offscreen_target_depth_format_
&&
3795 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3796 feature_info_
.get(),
3798 offscreen_target_depth_format_
,
3799 offscreen_target_samples_
)) {
3800 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3801 << "to allocate storage for offscreen target depth buffer.";
3804 if (offscreen_target_stencil_format_
&&
3805 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3806 feature_info_
.get(),
3808 offscreen_target_stencil_format_
,
3809 offscreen_target_samples_
)) {
3810 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3811 << "to allocate storage for offscreen target stencil buffer.";
3815 // Attach the offscreen target buffers to the target frame buffer.
3816 if (IsOffscreenBufferMultisampled()) {
3817 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3818 GL_COLOR_ATTACHMENT0
,
3819 offscreen_target_color_render_buffer_
.get());
3821 offscreen_target_frame_buffer_
->AttachRenderTexture(
3822 offscreen_target_color_texture_
.get());
3824 if (offscreen_target_depth_format_
) {
3825 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3826 GL_DEPTH_ATTACHMENT
,
3827 offscreen_target_depth_render_buffer_
.get());
3829 const bool packed_depth_stencil
=
3830 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3831 if (packed_depth_stencil
) {
3832 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3833 GL_STENCIL_ATTACHMENT
,
3834 offscreen_target_depth_render_buffer_
.get());
3835 } else if (offscreen_target_stencil_format_
) {
3836 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3837 GL_STENCIL_ATTACHMENT
,
3838 offscreen_target_stencil_render_buffer_
.get());
3841 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3842 GL_FRAMEBUFFER_COMPLETE
) {
3843 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3844 << "because offscreen FBO was incomplete.";
3848 // Clear the target frame buffer.
3850 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3851 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3852 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3853 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3855 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3856 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3858 state_
.SetDeviceDepthMask(GL_TRUE
);
3859 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3860 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3861 RestoreClearState();
3864 // Destroy the offscreen resolved framebuffers.
3865 if (offscreen_resolved_frame_buffer_
.get())
3866 offscreen_resolved_frame_buffer_
->Destroy();
3867 if (offscreen_resolved_color_texture_
.get())
3868 offscreen_resolved_color_texture_
->Destroy();
3869 offscreen_resolved_color_texture_
.reset();
3870 offscreen_resolved_frame_buffer_
.reset();
3875 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
3876 const void* cmd_data
) {
3877 const gles2::cmds::ResizeCHROMIUM
& c
=
3878 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
3879 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3880 return error::kDeferCommandUntilLater
;
3882 GLuint width
= static_cast<GLuint
>(c
.width
);
3883 GLuint height
= static_cast<GLuint
>(c
.height
);
3884 GLfloat scale_factor
= c
.scale_factor
;
3885 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3887 width
= std::max(1U, width
);
3888 height
= std::max(1U, height
);
3890 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3891 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3892 // Make sure that we are done drawing to the back buffer before resizing.
3895 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3897 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3898 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3899 << "ResizeOffscreenFrameBuffer failed.";
3900 return error::kLostContext
;
3904 if (!resize_callback_
.is_null()) {
3905 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3906 DCHECK(context_
->IsCurrent(surface_
.get()));
3907 if (!context_
->IsCurrent(surface_
.get())) {
3908 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3909 << "current after resize callback.";
3910 return error::kLostContext
;
3914 return error::kNoError
;
3917 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3918 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3919 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
3921 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
3924 // Decode a command, and call the corresponding GL functions.
3925 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3926 // of commands at once, and is now only used for tests that need to track
3927 // individual commands.
3928 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
3929 unsigned int arg_count
,
3930 const void* cmd_data
) {
3931 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
3934 // Decode multiple commands, and call the corresponding GL functions.
3935 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3936 // changed by a (malicious) client at any time, so if validation has to happen,
3937 // it should operate on a copy of them.
3938 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3939 // interest of performance in this critical execution loop.
3940 template <bool DebugImpl
>
3941 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
3944 int* entries_processed
) {
3945 commands_to_process_
= num_commands
;
3946 error::Error result
= error::kNoError
;
3947 const CommandBufferEntry
* cmd_data
=
3948 static_cast<const CommandBufferEntry
*>(buffer
);
3949 int process_pos
= 0;
3950 unsigned int command
= 0;
3952 while (process_pos
< num_entries
&& result
== error::kNoError
&&
3953 commands_to_process_
--) {
3954 const unsigned int size
= cmd_data
->value_header
.size
;
3955 command
= cmd_data
->value_header
.command
;
3958 result
= error::kInvalidSize
;
3962 if (static_cast<int>(size
) + process_pos
> num_entries
) {
3963 result
= error::kOutOfBounds
;
3968 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3969 GetCommandName(command
));
3971 if (log_commands()) {
3972 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
3973 << "cmd: " << GetCommandName(command
);
3977 const unsigned int arg_count
= size
- 1;
3978 unsigned int command_index
= command
- kStartPoint
- 1;
3979 if (command_index
< arraysize(command_info
)) {
3980 const CommandInfo
& info
= command_info
[command_index
];
3981 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
3982 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
3983 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
3984 bool doing_gpu_trace
= false;
3985 if (DebugImpl
&& gpu_trace_commands_
) {
3986 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
3987 doing_gpu_trace
= true;
3988 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
3989 GetCommandName(command
),
3994 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
3995 sizeof(CommandBufferEntry
); // NOLINT
3997 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
3999 if (DebugImpl
&& doing_gpu_trace
)
4000 gpu_tracer_
->End(kTraceDecoder
);
4002 if (DebugImpl
&& debug()) {
4004 while ((error
= glGetError()) != GL_NO_ERROR
) {
4005 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4006 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4007 << " : " << GetCommandName(command
);
4008 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4012 result
= error::kInvalidArguments
;
4015 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4019 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4020 GetCommandName(command
));
4023 if (result
== error::kNoError
&&
4024 current_decoder_error_
!= error::kNoError
) {
4025 result
= current_decoder_error_
;
4026 current_decoder_error_
= error::kNoError
;
4029 if (result
!= error::kDeferCommandUntilLater
) {
4030 process_pos
+= size
;
4035 if (entries_processed
)
4036 *entries_processed
= process_pos
;
4038 if (error::IsError(result
)) {
4039 LOG(ERROR
) << "Error: " << result
<< " for Command "
4040 << GetCommandName(command
);
4046 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4049 int* entries_processed
) {
4050 if (gpu_debug_commands_
) {
4051 return DoCommandsImpl
<true>(
4052 num_commands
, buffer
, num_entries
, entries_processed
);
4054 return DoCommandsImpl
<false>(
4055 num_commands
, buffer
, num_entries
, entries_processed
);
4059 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4060 buffer_manager()->RemoveBuffer(client_id
);
4063 void GLES2DecoderImpl::DoFinish() {
4065 ProcessPendingReadPixels();
4066 ProcessPendingQueries(true);
4069 void GLES2DecoderImpl::DoFlush() {
4071 ProcessPendingQueries(false);
4074 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4075 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4076 if (texture_index
>= state_
.texture_units
.size()) {
4077 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4078 "glActiveTexture", texture_unit
, "texture_unit");
4081 state_
.active_texture_unit
= texture_index
;
4082 glActiveTexture(texture_unit
);
4085 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4086 Buffer
* buffer
= NULL
;
4087 GLuint service_id
= 0;
4088 if (client_id
!= 0) {
4089 buffer
= GetBuffer(client_id
);
4091 if (!group_
->bind_generates_resource()) {
4092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4094 "id not generated by glGenBuffers");
4098 // It's a new id so make a buffer buffer for it.
4099 glGenBuffersARB(1, &service_id
);
4100 CreateBuffer(client_id
, service_id
);
4101 buffer
= GetBuffer(client_id
);
4104 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4106 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4108 GL_INVALID_OPERATION
,
4109 "glBindBuffer", "buffer bound to more than 1 target");
4112 service_id
= buffer
->service_id();
4115 case GL_ARRAY_BUFFER
:
4116 state_
.bound_array_buffer
= buffer
;
4118 case GL_ELEMENT_ARRAY_BUFFER
:
4119 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
4122 NOTREACHED(); // Validation should prevent us getting here.
4125 glBindBuffer(target
, service_id
);
4128 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4129 bool all_draw_buffers
) {
4130 Framebuffer
* framebuffer
=
4131 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4132 if (!all_draw_buffers
|| !framebuffer
) {
4133 return (GLES2Util::GetChannelsForFormat(
4134 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4136 return framebuffer
->HasAlphaMRT();
4139 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4140 Framebuffer
* framebuffer
=
4141 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4143 return framebuffer
->HasDepthAttachment();
4145 if (offscreen_target_frame_buffer_
.get()) {
4146 return offscreen_target_depth_format_
!= 0;
4148 return back_buffer_has_depth_
;
4151 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4152 Framebuffer
* framebuffer
=
4153 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4155 return framebuffer
->HasStencilAttachment();
4157 if (offscreen_target_frame_buffer_
.get()) {
4158 return offscreen_target_stencil_format_
!= 0 ||
4159 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4161 return back_buffer_has_stencil_
;
4164 void GLES2DecoderImpl::ApplyDirtyState() {
4165 if (framebuffer_state_
.clear_state_dirty
) {
4166 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4167 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4168 state_
.color_mask_green
,
4169 state_
.color_mask_blue
,
4170 state_
.color_mask_alpha
&& have_alpha
);
4172 bool have_depth
= BoundFramebufferHasDepthAttachment();
4173 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4175 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4176 state_
.SetDeviceStencilMaskSeparate(
4177 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4178 state_
.SetDeviceStencilMaskSeparate(
4179 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4181 state_
.SetDeviceCapabilityState(
4182 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4183 state_
.SetDeviceCapabilityState(
4184 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4185 framebuffer_state_
.clear_state_dirty
= false;
4189 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4190 return (offscreen_target_frame_buffer_
.get())
4191 ? offscreen_target_frame_buffer_
->id()
4192 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4195 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4196 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4197 "context", logger_
.GetLogPrefix());
4198 // Restore the Framebuffer first because of bugs in Intel drivers.
4199 // Intel drivers incorrectly clip the viewport settings to
4200 // the size of the current framebuffer object.
4201 RestoreFramebufferBindings();
4202 state_
.RestoreState(prev_state
);
4205 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4207 framebuffer_state_
.bound_draw_framebuffer
.get()
4208 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4209 : GetBackbufferServiceId();
4210 if (!features().chromium_framebuffer_multisample
) {
4211 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4213 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4214 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4215 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4216 : GetBackbufferServiceId();
4217 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4222 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4223 state_
.RestoreRenderbufferBindings();
4226 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4227 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4229 GLenum target
= texture
->target();
4230 glBindTexture(target
, service_id
);
4232 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4234 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4236 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4238 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4239 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4243 void GLES2DecoderImpl::ClearAllAttributes() const {
4244 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4246 if (feature_info_
->feature_flags().native_vertex_array_object
)
4247 glBindVertexArrayOES(0);
4249 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4250 if (i
!= 0) // Never disable attribute 0
4251 glDisableVertexAttribArray(i
);
4252 if(features().angle_instanced_arrays
)
4253 glVertexAttribDivisorANGLE(i
, 0);
4257 void GLES2DecoderImpl::RestoreAllAttributes() const {
4258 state_
.RestoreVertexAttribs();
4261 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4262 state_
.SetIgnoreCachedStateForTest(ignore
);
4265 void GLES2DecoderImpl::OnFboChanged() const {
4266 if (workarounds().restore_scissor_on_fbo_change
)
4267 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
4269 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4270 GLint bound_fbo_unsigned
= -1;
4271 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4272 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4273 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4274 surface_
->NotifyWasBound();
4278 // Called after the FBO is checked for completeness.
4279 void GLES2DecoderImpl::OnUseFramebuffer() const {
4280 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
4281 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
4282 // The driver forgets the correct scissor when modifying the FBO binding.
4283 glScissor(state_
.scissor_x
,
4285 state_
.scissor_width
,
4286 state_
.scissor_height
);
4288 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4289 // it's unclear how this bug works.
4294 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4295 Framebuffer
* framebuffer
= NULL
;
4296 GLuint service_id
= 0;
4297 if (client_id
!= 0) {
4298 framebuffer
= GetFramebuffer(client_id
);
4300 if (!group_
->bind_generates_resource()) {
4301 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4302 "glBindFramebuffer",
4303 "id not generated by glGenFramebuffers");
4307 // It's a new id so make a framebuffer framebuffer for it.
4308 glGenFramebuffersEXT(1, &service_id
);
4309 CreateFramebuffer(client_id
, service_id
);
4310 framebuffer
= GetFramebuffer(client_id
);
4312 service_id
= framebuffer
->service_id();
4314 framebuffer
->MarkAsValid();
4316 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4318 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4319 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4322 // vmiura: This looks like dup code
4323 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4324 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4327 framebuffer_state_
.clear_state_dirty
= true;
4329 // If we are rendering to the backbuffer get the FBO id for any simulated
4331 if (framebuffer
== NULL
) {
4332 service_id
= GetBackbufferServiceId();
4335 glBindFramebufferEXT(target
, service_id
);
4339 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4340 Renderbuffer
* renderbuffer
= NULL
;
4341 GLuint service_id
= 0;
4342 if (client_id
!= 0) {
4343 renderbuffer
= GetRenderbuffer(client_id
);
4344 if (!renderbuffer
) {
4345 if (!group_
->bind_generates_resource()) {
4346 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4347 "glBindRenderbuffer",
4348 "id not generated by glGenRenderbuffers");
4352 // It's a new id so make a renderbuffer for it.
4353 glGenRenderbuffersEXT(1, &service_id
);
4354 CreateRenderbuffer(client_id
, service_id
);
4355 renderbuffer
= GetRenderbuffer(client_id
);
4357 service_id
= renderbuffer
->service_id();
4359 renderbuffer
->MarkAsValid();
4361 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4362 state_
.bound_renderbuffer
= renderbuffer
;
4363 state_
.bound_renderbuffer_valid
= true;
4364 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4367 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4368 TextureRef
* texture_ref
= NULL
;
4369 GLuint service_id
= 0;
4370 if (client_id
!= 0) {
4371 texture_ref
= GetTexture(client_id
);
4373 if (!group_
->bind_generates_resource()) {
4374 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4376 "id not generated by glGenTextures");
4380 // It's a new id so make a texture texture for it.
4381 glGenTextures(1, &service_id
);
4382 DCHECK_NE(0u, service_id
);
4383 CreateTexture(client_id
, service_id
);
4384 texture_ref
= GetTexture(client_id
);
4387 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4390 // Check the texture exists
4392 Texture
* texture
= texture_ref
->texture();
4393 // Check that we are not trying to bind it to a different target.
4394 if (texture
->target() != 0 && texture
->target() != target
) {
4395 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4397 "texture bound to more than 1 target.");
4400 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4401 if (texture
->target() == 0) {
4402 texture_manager()->SetTarget(texture_ref
, target
);
4404 glBindTexture(target
, texture
->service_id());
4406 glBindTexture(target
, 0);
4409 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4410 unit
.bind_target
= target
;
4413 unit
.bound_texture_2d
= texture_ref
;
4415 case GL_TEXTURE_CUBE_MAP
:
4416 unit
.bound_texture_cube_map
= texture_ref
;
4418 case GL_TEXTURE_EXTERNAL_OES
:
4419 unit
.bound_texture_external_oes
= texture_ref
;
4421 case GL_TEXTURE_RECTANGLE_ARB
:
4422 unit
.bound_texture_rectangle_arb
= texture_ref
;
4425 NOTREACHED(); // Validation should prevent us getting here.
4430 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4431 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4433 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4434 glDisableVertexAttribArray(index
);
4439 "glDisableVertexAttribArray", "index out of range");
4443 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4444 GLsizei numAttachments
,
4445 const GLenum
* attachments
) {
4446 Framebuffer
* framebuffer
=
4447 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4449 // Validates the attachments. If one of them fails
4450 // the whole command fails.
4451 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4453 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4455 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4456 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4457 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4462 // Marks each one of them as not cleared
4463 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4465 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4470 switch (attachments
[i
]) {
4472 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4475 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4476 case GL_STENCIL_EXT
:
4477 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4486 // If the default framebuffer is bound but we are still rendering to an
4487 // FBO, translate attachment names that refer to default framebuffer
4488 // channels to corresponding framebuffer attachments.
4489 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4490 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4491 GLenum attachment
= attachments
[i
];
4492 if (!framebuffer
&& GetBackbufferServiceId()) {
4493 switch (attachment
) {
4495 attachment
= GL_COLOR_ATTACHMENT0
;
4498 attachment
= GL_DEPTH_ATTACHMENT
;
4500 case GL_STENCIL_EXT
:
4501 attachment
= GL_STENCIL_ATTACHMENT
;
4508 translated_attachments
[i
] = attachment
;
4511 ScopedRenderTo
do_render(framebuffer
);
4512 if (feature_info_
->gl_version_info().is_es3
) {
4513 glInvalidateFramebuffer(
4514 target
, numAttachments
, translated_attachments
.get());
4516 glDiscardFramebufferEXT(
4517 target
, numAttachments
, translated_attachments
.get());
4521 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4522 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4523 glEnableVertexAttribArray(index
);
4526 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4530 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4531 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4534 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4536 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4540 if (target
== GL_TEXTURE_CUBE_MAP
) {
4541 for (int i
= 0; i
< 6; ++i
) {
4542 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4543 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4545 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4550 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4552 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4557 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4558 // Workaround for Mac driver bug. In the large scheme of things setting
4559 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4560 // hit so there's probably no need to make this conditional. The bug appears
4561 // to be that if the filtering mode is set to something that doesn't require
4562 // mipmaps for rendering, or is never set to something other than the default,
4563 // then glGenerateMipmap misbehaves.
4564 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4565 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4567 glGenerateMipmapEXT(target
);
4568 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4569 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4570 texture_ref
->texture()->min_filter());
4572 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4573 if (error
== GL_NO_ERROR
) {
4574 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4578 bool GLES2DecoderImpl::GetHelper(
4579 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4580 DCHECK(num_written
);
4581 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4583 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4585 // Return the GL implementation's preferred format and (see below type)
4586 // if we have the GL extension that exposes this. This allows the GPU
4587 // client to use the implementation's preferred format for glReadPixels
4588 // for optimisation.
4590 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4591 // case when requested on integer/floating point buffers but which is
4592 // acceptable on GLES2 and with the GL_OES_read_format extension.
4594 // Therefore if an error occurs we swallow the error and use the
4595 // internal implementation.
4597 if (context_
->HasExtension("GL_OES_read_format")) {
4598 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4600 glGetIntegerv(pname
, params
);
4601 if (glGetError() == GL_NO_ERROR
)
4604 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4605 GetBoundReadFrameBufferInternalFormat());
4608 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4611 if (context_
->HasExtension("GL_OES_read_format")) {
4612 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4614 glGetIntegerv(pname
, params
);
4615 if (glGetError() == GL_NO_ERROR
)
4618 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4619 GetBoundReadFrameBufferInternalFormat(),
4620 GetBoundReadFrameBufferTextureType());
4623 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4626 *params
= group_
->max_fragment_uniform_vectors();
4629 case GL_MAX_VARYING_VECTORS
:
4632 *params
= group_
->max_varying_vectors();
4635 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4638 *params
= group_
->max_vertex_uniform_vectors();
4644 case GL_MAX_VIEWPORT_DIMS
:
4645 if (offscreen_target_frame_buffer_
.get()) {
4648 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4649 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4654 case GL_MAX_SAMPLES
:
4657 params
[0] = renderbuffer_manager()->max_samples();
4660 case GL_MAX_RENDERBUFFER_SIZE
:
4663 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4666 case GL_MAX_TEXTURE_SIZE
:
4669 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4672 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4675 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4678 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4681 params
[0] = group_
->max_color_attachments();
4684 case GL_MAX_DRAW_BUFFERS_ARB
:
4687 params
[0] = group_
->max_draw_buffers();
4694 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4695 params
[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4702 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4703 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4706 case GL_STENCIL_BITS
:
4710 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4711 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4714 case GL_COMPRESSED_TEXTURE_FORMATS
:
4715 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4717 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4718 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4722 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4725 *params
= validators_
->compressed_texture_format
.GetValues().size();
4728 case GL_NUM_SHADER_BINARY_FORMATS
:
4731 *params
= validators_
->shader_binary_format
.GetValues().size();
4734 case GL_SHADER_BINARY_FORMATS
:
4735 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4737 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4738 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4742 case GL_SHADER_COMPILER
:
4748 case GL_ARRAY_BUFFER_BINDING
:
4751 if (state_
.bound_array_buffer
.get()) {
4752 GLuint client_id
= 0;
4753 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4755 *params
= client_id
;
4761 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4764 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4765 GLuint client_id
= 0;
4766 buffer_manager()->GetClientId(
4767 state_
.vertex_attrib_manager
->element_array_buffer()->
4768 service_id(), &client_id
);
4769 *params
= client_id
;
4775 case GL_FRAMEBUFFER_BINDING
:
4776 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4779 Framebuffer
* framebuffer
=
4780 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4782 GLuint client_id
= 0;
4783 framebuffer_manager()->GetClientId(
4784 framebuffer
->service_id(), &client_id
);
4785 *params
= client_id
;
4791 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4794 Framebuffer
* framebuffer
=
4795 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4797 GLuint client_id
= 0;
4798 framebuffer_manager()->GetClientId(
4799 framebuffer
->service_id(), &client_id
);
4800 *params
= client_id
;
4806 case GL_RENDERBUFFER_BINDING
:
4809 Renderbuffer
* renderbuffer
=
4810 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4812 *params
= renderbuffer
->client_id();
4818 case GL_CURRENT_PROGRAM
:
4821 if (state_
.current_program
.get()) {
4822 GLuint client_id
= 0;
4823 program_manager()->GetClientId(
4824 state_
.current_program
->service_id(), &client_id
);
4825 *params
= client_id
;
4831 case GL_VERTEX_ARRAY_BINDING_OES
:
4834 if (state_
.vertex_attrib_manager
.get() !=
4835 state_
.default_vertex_attrib_manager
.get()) {
4836 GLuint client_id
= 0;
4837 vertex_array_manager_
->GetClientId(
4838 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4839 *params
= client_id
;
4845 case GL_TEXTURE_BINDING_2D
:
4848 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4849 if (unit
.bound_texture_2d
.get()) {
4850 *params
= unit
.bound_texture_2d
->client_id();
4856 case GL_TEXTURE_BINDING_CUBE_MAP
:
4859 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4860 if (unit
.bound_texture_cube_map
.get()) {
4861 *params
= unit
.bound_texture_cube_map
->client_id();
4867 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
4870 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4871 if (unit
.bound_texture_external_oes
.get()) {
4872 *params
= unit
.bound_texture_external_oes
->client_id();
4878 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
4881 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4882 if (unit
.bound_texture_rectangle_arb
.get()) {
4883 *params
= unit
.bound_texture_rectangle_arb
->client_id();
4889 case GL_UNPACK_FLIP_Y_CHROMIUM
:
4892 params
[0] = unpack_flip_y_
;
4895 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
4898 params
[0] = unpack_premultiply_alpha_
;
4901 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
4904 params
[0] = unpack_unpremultiply_alpha_
;
4907 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
4910 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
4914 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
4915 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
4918 Framebuffer
* framebuffer
=
4919 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4921 params
[0] = framebuffer
->GetDrawBuffer(pname
);
4922 } else { // backbuffer
4923 if (pname
== GL_DRAW_BUFFER0_ARB
)
4924 params
[0] = group_
->draw_buffer();
4926 params
[0] = GL_NONE
;
4931 *num_written
= util_
.GLGetNumValuesReturned(pname
);
4936 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4937 GLenum pname
, GLsizei
* num_values
) {
4938 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
4941 return GetHelper(pname
, NULL
, num_values
);
4944 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
4945 if (GL_MAX_SAMPLES
== pname
&&
4946 features().use_img_for_multisampled_render_to_texture
) {
4947 return GL_MAX_SAMPLES_IMG
;
4952 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
4954 GLsizei num_written
= 0;
4955 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
4956 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4957 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
4958 GetHelper(pname
, values
.get(), &num_written
);
4960 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4961 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
4964 pname
= AdjustGetPname(pname
);
4965 glGetBooleanv(pname
, params
);
4969 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
4971 GLsizei num_written
= 0;
4972 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
4973 if (GetHelper(pname
, NULL
, &num_written
)) {
4974 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
4975 GetHelper(pname
, values
.get(), &num_written
);
4976 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
4977 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
4980 pname
= AdjustGetPname(pname
);
4981 glGetFloatv(pname
, params
);
4986 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
4988 GLsizei num_written
;
4989 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
4990 !GetHelper(pname
, params
, &num_written
)) {
4991 pname
= AdjustGetPname(pname
);
4992 glGetIntegerv(pname
, params
);
4996 void GLES2DecoderImpl::DoGetProgramiv(
4997 GLuint program_id
, GLenum pname
, GLint
* params
) {
4998 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5002 program
->GetProgramiv(pname
, params
);
5005 void GLES2DecoderImpl::DoGetBufferParameteriv(
5006 GLenum target
, GLenum pname
, GLint
* params
) {
5007 // Just delegate it. Some validation is actually done before this.
5008 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5009 &state_
, target
, pname
, params
);
5012 void GLES2DecoderImpl::DoBindAttribLocation(
5013 GLuint program_id
, GLuint index
, const char* name
) {
5014 if (!StringIsValidForGLES(name
)) {
5016 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5019 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5021 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5024 if (index
>= group_
->max_vertex_attribs()) {
5026 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5029 Program
* program
= GetProgramInfoNotShader(
5030 program_id
, "glBindAttribLocation");
5034 // At this point, the program's shaders may not be translated yet,
5035 // therefore, we may not find the hashed attribute name.
5036 // glBindAttribLocation call with original name is useless.
5037 // So instead, we should simply cache the binding, and then call
5038 // Program::ExecuteBindAttribLocationCalls() right before link.
5039 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5040 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5041 glBindAttribLocation(program
->service_id(), index
, name
);
5044 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5045 uint32 immediate_data_size
,
5046 const void* cmd_data
) {
5047 const gles2::cmds::BindAttribLocationBucket
& c
=
5048 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5049 GLuint program
= static_cast<GLuint
>(c
.program
);
5050 GLuint index
= static_cast<GLuint
>(c
.index
);
5051 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5052 if (!bucket
|| bucket
->size() == 0) {
5053 return error::kInvalidArguments
;
5055 std::string name_str
;
5056 if (!bucket
->GetAsString(&name_str
)) {
5057 return error::kInvalidArguments
;
5059 DoBindAttribLocation(program
, index
, name_str
.c_str());
5060 return error::kNoError
;
5063 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5064 GLuint program_id
, GLint location
, const char* name
) {
5065 if (!StringIsValidForGLES(name
)) {
5068 "glBindUniformLocationCHROMIUM", "Invalid character");
5071 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5073 GL_INVALID_OPERATION
,
5074 "glBindUniformLocationCHROMIUM", "reserved prefix");
5077 if (location
< 0 || static_cast<uint32
>(location
) >=
5078 (group_
->max_fragment_uniform_vectors() +
5079 group_
->max_vertex_uniform_vectors()) * 4) {
5082 "glBindUniformLocationCHROMIUM", "location out of range");
5085 Program
* program
= GetProgramInfoNotShader(
5086 program_id
, "glBindUniformLocationCHROMIUM");
5090 if (!program
->SetUniformLocationBinding(name
, location
)) {
5093 "glBindUniformLocationCHROMIUM", "location out of range");
5097 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5098 uint32 immediate_data_size
,
5099 const void* cmd_data
) {
5100 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5101 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5103 GLuint program
= static_cast<GLuint
>(c
.program
);
5104 GLint location
= static_cast<GLint
>(c
.location
);
5105 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5106 if (!bucket
|| bucket
->size() == 0) {
5107 return error::kInvalidArguments
;
5109 std::string name_str
;
5110 if (!bucket
->GetAsString(&name_str
)) {
5111 return error::kInvalidArguments
;
5113 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5114 return error::kNoError
;
5117 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5118 const void* cmd_data
) {
5119 const gles2::cmds::DeleteShader
& c
=
5120 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5121 GLuint client_id
= c
.shader
;
5123 Shader
* shader
= GetShader(client_id
);
5125 if (!shader
->IsDeleted()) {
5126 glDeleteShader(shader
->service_id());
5127 shader_manager()->MarkAsDeleted(shader
);
5130 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5133 return error::kNoError
;
5136 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5137 const void* cmd_data
) {
5138 const gles2::cmds::DeleteProgram
& c
=
5139 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5140 GLuint client_id
= c
.program
;
5142 Program
* program
= GetProgram(client_id
);
5144 if (!program
->IsDeleted()) {
5145 program_manager()->MarkAsDeleted(shader_manager(), program
);
5149 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5152 return error::kNoError
;
5155 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5156 DCHECK(!ShouldDeferDraws());
5157 if (CheckBoundFramebuffersValid("glClear")) {
5159 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5160 if (workarounds().gl_clear_broken
) {
5161 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5163 if (!BoundFramebufferHasDepthAttachment())
5164 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5165 if (!BoundFramebufferHasStencilAttachment())
5166 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5167 clear_framebuffer_blit_
->ClearFramebuffer(
5168 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5169 state_
.color_clear_green
, state_
.color_clear_blue
,
5170 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5171 return error::kNoError
;
5175 return error::kNoError
;
5178 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5179 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5180 GLuint client_renderbuffer_id
) {
5181 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5184 GL_INVALID_OPERATION
,
5185 "glFramebufferRenderbuffer", "no framebuffer bound");
5188 GLuint service_id
= 0;
5189 Renderbuffer
* renderbuffer
= NULL
;
5190 if (client_renderbuffer_id
) {
5191 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5192 if (!renderbuffer
) {
5194 GL_INVALID_OPERATION
,
5195 "glFramebufferRenderbuffer", "unknown renderbuffer");
5198 service_id
= renderbuffer
->service_id();
5200 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5201 glFramebufferRenderbufferEXT(
5202 target
, attachment
, renderbuffertarget
, service_id
);
5203 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5204 if (error
== GL_NO_ERROR
) {
5205 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5207 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5208 framebuffer_state_
.clear_state_dirty
= true;
5213 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5214 if (SetCapabilityState(cap
, false)) {
5219 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5220 if (SetCapabilityState(cap
, true)) {
5225 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5226 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5227 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5228 glDepthRange(znear
, zfar
);
5231 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5232 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5233 state_
.sample_coverage_invert
= (invert
!= 0);
5234 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5237 // Assumes framebuffer is complete.
5238 void GLES2DecoderImpl::ClearUnclearedAttachments(
5239 GLenum target
, Framebuffer
* framebuffer
) {
5240 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5241 // bind this to the DRAW point, clear then bind back to READ
5242 // TODO(gman): I don't think there is any guarantee that an FBO that
5243 // is complete on the READ attachment will be complete as a DRAW
5245 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5246 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5248 GLbitfield clear_bits
= 0;
5249 if (framebuffer
->HasUnclearedColorAttachments()) {
5252 (GLES2Util::GetChannelsForFormat(
5253 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5255 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5256 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5257 if (feature_info_
->feature_flags().ext_draw_buffers
)
5258 framebuffer
->PrepareDrawBuffersForClear();
5261 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5262 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5264 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5265 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5266 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5269 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5270 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5272 state_
.SetDeviceDepthMask(GL_TRUE
);
5273 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5276 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5277 glClear(clear_bits
);
5279 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5280 feature_info_
->feature_flags().ext_draw_buffers
)
5281 framebuffer
->RestoreDrawBuffersAfterClear();
5283 framebuffer_manager()->MarkAttachmentsAsCleared(
5284 framebuffer
, renderbuffer_manager(), texture_manager());
5286 RestoreClearState();
5288 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5289 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5290 Framebuffer
* draw_framebuffer
=
5291 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5292 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5293 GetBackbufferServiceId();
5294 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5298 void GLES2DecoderImpl::RestoreClearState() {
5299 framebuffer_state_
.clear_state_dirty
= true;
5301 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5302 state_
.color_clear_alpha
);
5303 glClearStencil(state_
.stencil_clear
);
5304 glClearDepth(state_
.depth_clear
);
5305 if (state_
.enable_flags
.scissor_test
) {
5306 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5310 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5311 Framebuffer
* framebuffer
=
5312 GetFramebufferInfoForTarget(target
);
5314 return GL_FRAMEBUFFER_COMPLETE
;
5316 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5317 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5318 return completeness
;
5320 return framebuffer
->GetStatus(texture_manager(), target
);
5323 void GLES2DecoderImpl::DoFramebufferTexture2D(
5324 GLenum target
, GLenum attachment
, GLenum textarget
,
5325 GLuint client_texture_id
, GLint level
) {
5326 DoFramebufferTexture2DCommon(
5327 "glFramebufferTexture2D", target
, attachment
,
5328 textarget
, client_texture_id
, level
, 0);
5331 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5332 GLenum target
, GLenum attachment
, GLenum textarget
,
5333 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5334 DoFramebufferTexture2DCommon(
5335 "glFramebufferTexture2DMultisample", target
, attachment
,
5336 textarget
, client_texture_id
, level
, samples
);
5339 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5340 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5341 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5342 if (samples
> renderbuffer_manager()->max_samples()) {
5345 "glFramebufferTexture2DMultisample", "samples too large");
5348 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5351 GL_INVALID_OPERATION
,
5352 name
, "no framebuffer bound.");
5355 GLuint service_id
= 0;
5356 TextureRef
* texture_ref
= NULL
;
5357 if (client_texture_id
) {
5358 texture_ref
= GetTexture(client_texture_id
);
5361 GL_INVALID_OPERATION
,
5362 name
, "unknown texture_ref");
5365 service_id
= texture_ref
->service_id();
5368 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5371 name
, "level out of range");
5376 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5378 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5380 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5382 if (features().use_img_for_multisampled_render_to_texture
) {
5383 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5384 service_id
, level
, samples
);
5386 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5387 service_id
, level
, samples
);
5390 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5391 if (error
== GL_NO_ERROR
) {
5392 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5395 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5396 framebuffer_state_
.clear_state_dirty
= true;
5400 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5405 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5406 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5407 GLint level
, GLint layer
) {
5408 // TODO(zmo): Unsafe ES3 API, missing states update.
5409 GLuint service_id
= 0;
5410 TextureRef
* texture_ref
= NULL
;
5411 if (client_texture_id
) {
5412 texture_ref
= GetTexture(client_texture_id
);
5415 GL_INVALID_OPERATION
,
5416 "glFramebufferTextureLayer", "unknown texture_ref");
5419 service_id
= texture_ref
->service_id();
5421 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5424 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5425 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5426 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5429 GL_INVALID_OPERATION
,
5430 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5433 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5434 const Framebuffer::Attachment
* attachment_object
=
5435 framebuffer
->GetAttachment(attachment
);
5436 *params
= attachment_object
? attachment_object
->object_name() : 0;
5438 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5439 features().use_img_for_multisampled_render_to_texture
) {
5440 pname
= GL_TEXTURE_SAMPLES_IMG
;
5442 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5446 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5447 GLenum target
, GLenum pname
, GLint
* params
) {
5448 Renderbuffer
* renderbuffer
=
5449 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5450 if (!renderbuffer
) {
5452 GL_INVALID_OPERATION
,
5453 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5457 EnsureRenderbufferBound();
5459 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5460 *params
= renderbuffer
->internal_format();
5462 case GL_RENDERBUFFER_WIDTH
:
5463 *params
= renderbuffer
->width();
5465 case GL_RENDERBUFFER_HEIGHT
:
5466 *params
= renderbuffer
->height();
5468 case GL_RENDERBUFFER_SAMPLES_EXT
:
5469 if (features().use_img_for_multisampled_render_to_texture
) {
5470 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5473 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5477 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5482 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5483 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5484 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5485 GLbitfield mask
, GLenum filter
) {
5486 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5488 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5492 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5493 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5494 BlitFramebufferHelper(
5495 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5496 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5497 state_
.enable_flags
.scissor_test
);
5500 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5501 if (!state_
.bound_renderbuffer_valid
) {
5502 state_
.bound_renderbuffer_valid
= true;
5503 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5504 state_
.bound_renderbuffer
.get()
5505 ? state_
.bound_renderbuffer
->service_id()
5510 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5511 const FeatureInfo
* feature_info
,
5514 GLenum internal_format
,
5517 // TODO(sievers): This could be resolved at the GL binding level, but the
5518 // binding process is currently a bit too 'brute force'.
5519 if (feature_info
->gl_version_info().is_angle
) {
5520 glRenderbufferStorageMultisampleANGLE(
5521 target
, samples
, internal_format
, width
, height
);
5522 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5523 glRenderbufferStorageMultisample(
5524 target
, samples
, internal_format
, width
, height
);
5526 glRenderbufferStorageMultisampleEXT(
5527 target
, samples
, internal_format
, width
, height
);
5531 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5541 // TODO(sievers): This could be resolved at the GL binding level, but the
5542 // binding process is currently a bit too 'brute force'.
5543 if (feature_info_
->gl_version_info().is_angle
) {
5544 glBlitFramebufferANGLE(
5545 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5546 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5548 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5550 glBlitFramebufferEXT(
5551 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5555 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5557 GLenum internalformat
,
5560 if (samples
> renderbuffer_manager()->max_samples()) {
5563 "glRenderbufferStorageMultisample", "samples too large");
5567 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5568 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5571 "glRenderbufferStorageMultisample", "dimensions too large");
5575 uint32 estimated_size
= 0;
5576 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5577 width
, height
, samples
, internalformat
, &estimated_size
)) {
5580 "glRenderbufferStorageMultisample", "dimensions too large");
5584 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5587 "glRenderbufferStorageMultisample", "out of memory");
5594 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5595 GLenum target
, GLsizei samples
, GLenum internalformat
,
5596 GLsizei width
, GLsizei height
) {
5597 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5598 if (!renderbuffer
) {
5599 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5600 "glRenderbufferStorageMultisampleCHROMIUM",
5601 "no renderbuffer bound");
5605 if (!ValidateRenderbufferStorageMultisample(
5606 samples
, internalformat
, width
, height
)) {
5610 EnsureRenderbufferBound();
5611 GLenum impl_format
=
5612 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5614 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5615 "glRenderbufferStorageMultisampleCHROMIUM");
5616 RenderbufferStorageMultisampleHelper(
5617 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5619 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5620 if (error
== GL_NO_ERROR
) {
5622 if (workarounds().validate_multisample_buffer_allocation
) {
5623 if (!VerifyMultisampleRenderbufferIntegrity(
5624 renderbuffer
->service_id(), impl_format
)) {
5627 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5632 // TODO(gman): If renderbuffers tracked which framebuffers they were
5633 // attached to we could just mark those framebuffers as not complete.
5634 framebuffer_manager()->IncFramebufferStateChangeCount();
5635 renderbuffer_manager()->SetInfo(
5636 renderbuffer
, samples
, internalformat
, width
, height
);
5640 // This is the handler for multisampled_render_to_texture extensions.
5641 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5642 GLenum target
, GLsizei samples
, GLenum internalformat
,
5643 GLsizei width
, GLsizei height
) {
5644 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5645 if (!renderbuffer
) {
5646 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5647 "glRenderbufferStorageMultisampleEXT",
5648 "no renderbuffer bound");
5652 if (!ValidateRenderbufferStorageMultisample(
5653 samples
, internalformat
, width
, height
)) {
5657 EnsureRenderbufferBound();
5658 GLenum impl_format
=
5659 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5661 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5662 if (features().use_img_for_multisampled_render_to_texture
) {
5663 glRenderbufferStorageMultisampleIMG(
5664 target
, samples
, impl_format
, width
, height
);
5666 glRenderbufferStorageMultisampleEXT(
5667 target
, samples
, impl_format
, width
, height
);
5669 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5670 if (error
== GL_NO_ERROR
) {
5671 // TODO(gman): If renderbuffers tracked which framebuffers they were
5672 // attached to we could just mark those framebuffers as not complete.
5673 framebuffer_manager()->IncFramebufferStateChangeCount();
5674 renderbuffer_manager()->SetInfo(
5675 renderbuffer
, samples
, internalformat
, width
, height
);
5679 // This function validates the allocation of a multisampled renderbuffer
5680 // by clearing it to a key color, blitting the contents to a texture, and
5681 // reading back the color to ensure it matches the key.
5682 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5683 GLuint renderbuffer
, GLenum format
) {
5685 // Only validate color buffers.
5686 // These formats have been selected because they are very common or are known
5687 // to be used by the WebGL backbuffer. If problems are observed with other
5688 // color formats they can be added here.
5699 GLint draw_framebuffer
, read_framebuffer
;
5701 // Cache framebuffer and texture bindings.
5702 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5703 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5705 if (!validation_texture_
) {
5706 GLint bound_texture
;
5707 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5709 // Create additional resources needed for the verification.
5710 glGenTextures(1, &validation_texture_
);
5711 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5712 glGenFramebuffersEXT(1, &validation_fbo_
);
5714 // Texture only needs to be 1x1.
5715 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5716 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5717 GL_UNSIGNED_BYTE
, NULL
);
5719 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5720 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5721 GL_TEXTURE_2D
, validation_texture_
, 0);
5723 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5726 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5727 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5728 GL_RENDERBUFFER
, renderbuffer
);
5730 // Cache current state and reset it to the values we require.
5731 GLboolean scissor_enabled
= false;
5732 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5733 if (scissor_enabled
)
5734 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5736 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5737 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5738 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5740 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5741 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5742 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5744 // Clear the buffer to the desired key color.
5745 glClear(GL_COLOR_BUFFER_BIT
);
5747 // Blit from the multisample buffer to a standard texture.
5748 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5749 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5751 BlitFramebufferHelper(
5752 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5754 // Read a pixel from the buffer.
5755 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5757 unsigned char pixel
[3] = {0, 0, 0};
5758 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5760 // Detach the renderbuffer.
5761 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5762 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5763 GL_RENDERBUFFER
, 0);
5765 // Restore cached state.
5766 if (scissor_enabled
)
5767 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5769 state_
.SetDeviceColorMask(
5770 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5771 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5772 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5773 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5775 // Return true if the pixel matched the desired key color.
5776 return (pixel
[0] == 0xFF &&
5781 void GLES2DecoderImpl::DoRenderbufferStorage(
5782 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5783 Renderbuffer
* renderbuffer
=
5784 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5785 if (!renderbuffer
) {
5787 GL_INVALID_OPERATION
,
5788 "glRenderbufferStorage", "no renderbuffer bound");
5792 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5793 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5795 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5799 uint32 estimated_size
= 0;
5800 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5801 width
, height
, 1, internalformat
, &estimated_size
)) {
5803 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5807 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5809 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5813 EnsureRenderbufferBound();
5814 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5815 glRenderbufferStorageEXT(
5817 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5821 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5822 if (error
== GL_NO_ERROR
) {
5823 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5824 // we could just mark those framebuffers as not complete.
5825 framebuffer_manager()->IncFramebufferStateChangeCount();
5826 renderbuffer_manager()->SetInfo(
5827 renderbuffer
, 1, internalformat
, width
, height
);
5831 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5832 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5833 Program
* program
= GetProgramInfoNotShader(
5834 program_id
, "glLinkProgram");
5839 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5840 ShaderTranslator
* vertex_translator
= NULL
;
5841 ShaderTranslator
* fragment_translator
= NULL
;
5842 if (use_shader_translator_
) {
5843 vertex_translator
= vertex_translator_
.get();
5844 fragment_translator
= fragment_translator_
.get();
5846 if (program
->Link(shader_manager(),
5848 fragment_translator
,
5849 workarounds().count_all_in_varyings_packing
?
5850 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5851 shader_cache_callback_
)) {
5852 if (program
== state_
.current_program
.get()) {
5853 if (workarounds().use_current_program_after_successful_link
)
5854 glUseProgram(program
->service_id());
5855 if (workarounds().clear_uniforms_before_first_program_use
)
5856 program_manager()->ClearUniforms(program
);
5860 // LinkProgram can be very slow. Exit command processing to allow for
5861 // context preemption and GPU watchdog checks.
5862 ExitCommandProcessingEarly();
5865 void GLES2DecoderImpl::DoSamplerParameterfv(
5866 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
5868 glSamplerParameterf(sampler
, pname
, params
[0]);
5871 void GLES2DecoderImpl::DoSamplerParameteriv(
5872 GLuint sampler
, GLenum pname
, const GLint
* params
) {
5874 glSamplerParameteri(sampler
, pname
, params
[0]);
5877 void GLES2DecoderImpl::DoTexParameterf(
5878 GLenum target
, GLenum pname
, GLfloat param
) {
5879 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5882 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
5886 texture_manager()->SetParameterf(
5887 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
5890 void GLES2DecoderImpl::DoTexParameteri(
5891 GLenum target
, GLenum pname
, GLint param
) {
5892 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5895 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
5899 texture_manager()->SetParameteri(
5900 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
5903 void GLES2DecoderImpl::DoTexParameterfv(
5904 GLenum target
, GLenum pname
, const GLfloat
* params
) {
5905 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5908 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
5912 texture_manager()->SetParameterf(
5913 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
5916 void GLES2DecoderImpl::DoTexParameteriv(
5917 GLenum target
, GLenum pname
, const GLint
* params
) {
5918 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
5922 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
5926 texture_manager()->SetParameteri(
5927 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
5930 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
5931 if (!state_
.bound_valuebuffer
.get()) {
5932 // There is no valuebuffer bound
5933 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5934 "no valuebuffer in use");
5940 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
5941 GLenum subscription
,
5942 const char* function_name
) {
5943 if (!CheckCurrentValuebuffer(function_name
)) {
5946 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
5947 // The valuebuffer is not subscribed to the target
5948 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5949 "valuebuffer is not subscribed");
5955 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
5956 GLenum subscription
,
5957 const char* function_name
) {
5958 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
5961 GLint real_location
= -1;
5962 GLint array_index
= -1;
5963 const Program::UniformInfo
* info
=
5964 state_
.current_program
->GetUniformInfoByFakeLocation(
5965 location
, &real_location
, &array_index
);
5967 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
5970 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
5971 info
->accepts_api_type
) == 0) {
5972 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
5973 "wrong type for subscription");
5979 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
5980 if (!state_
.current_program
.get()) {
5981 // The program does not exist.
5983 GL_INVALID_OPERATION
, function_name
, "no program in use");
5986 if (!state_
.current_program
->InUse()) {
5988 GL_INVALID_OPERATION
, function_name
, "program not linked");
5994 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5995 GLint location
, const char* function_name
) {
5996 if (!CheckCurrentProgram(function_name
)) {
5999 return location
!= -1;
6002 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6003 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6006 const Framebuffer::Attachment
* attachment
=
6007 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6011 DCHECK(state_
.current_program
.get());
6012 const Program::SamplerIndices
& sampler_indices
=
6013 state_
.current_program
->sampler_indices();
6014 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6015 const Program::UniformInfo
* uniform_info
=
6016 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6017 DCHECK(uniform_info
);
6018 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6020 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6021 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6022 if (texture_unit_index
>= state_
.texture_units
.size())
6024 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6025 TextureRef
* texture_ref
=
6026 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6027 if (attachment
->IsTexture(texture_ref
))
6034 bool GLES2DecoderImpl::CheckUniformForApiType(
6035 const Program::UniformInfo
* info
,
6036 const char* function_name
,
6037 Program::UniformApiType api_type
) {
6039 if ((api_type
& info
->accepts_api_type
) == 0) {
6040 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6041 "wrong uniform function for type");
6047 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6048 GLint fake_location
,
6049 const char* function_name
,
6050 Program::UniformApiType api_type
,
6051 GLint
* real_location
,
6056 DCHECK(real_location
);
6058 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6061 GLint array_index
= -1;
6062 const Program::UniformInfo
* info
=
6063 state_
.current_program
->GetUniformInfoByFakeLocation(
6064 fake_location
, real_location
, &array_index
);
6067 GL_INVALID_OPERATION
, function_name
, "unknown location");
6070 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6073 if (*count
> 1 && !info
->is_array
) {
6075 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6078 *count
= std::min(info
->size
- array_index
, *count
);
6086 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6089 GLint real_location
= -1;
6090 if (!PrepForSetUniformByLocation(fake_location
,
6092 Program::kUniform1i
,
6098 if (!state_
.current_program
->SetSamplers(
6099 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6101 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6104 glUniform1i(real_location
, v0
);
6107 void GLES2DecoderImpl::DoUniform1iv(
6108 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6110 GLint real_location
= -1;
6111 if (!PrepForSetUniformByLocation(fake_location
,
6113 Program::kUniform1i
,
6119 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6120 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6121 if (!state_
.current_program
->SetSamplers(
6122 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6124 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6128 glUniform1iv(real_location
, count
, value
);
6131 void GLES2DecoderImpl::DoUniform1fv(
6132 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6134 GLint real_location
= -1;
6135 if (!PrepForSetUniformByLocation(fake_location
,
6137 Program::kUniform1f
,
6143 if (type
== GL_BOOL
) {
6144 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6145 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6146 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6148 DoUniform1iv(real_location
, count
, temp
.get());
6150 glUniform1fv(real_location
, count
, value
);
6154 void GLES2DecoderImpl::DoUniform2fv(
6155 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6157 GLint real_location
= -1;
6158 if (!PrepForSetUniformByLocation(fake_location
,
6160 Program::kUniform2f
,
6166 if (type
== GL_BOOL_VEC2
) {
6167 GLsizei num_values
= count
* 2;
6168 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6169 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6170 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6172 glUniform2iv(real_location
, count
, temp
.get());
6174 glUniform2fv(real_location
, count
, value
);
6178 void GLES2DecoderImpl::DoUniform3fv(
6179 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6181 GLint real_location
= -1;
6182 if (!PrepForSetUniformByLocation(fake_location
,
6184 Program::kUniform3f
,
6190 if (type
== GL_BOOL_VEC3
) {
6191 GLsizei num_values
= count
* 3;
6192 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6193 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6194 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6196 glUniform3iv(real_location
, count
, temp
.get());
6198 glUniform3fv(real_location
, count
, value
);
6202 void GLES2DecoderImpl::DoUniform4fv(
6203 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6205 GLint real_location
= -1;
6206 if (!PrepForSetUniformByLocation(fake_location
,
6208 Program::kUniform4f
,
6214 if (type
== GL_BOOL_VEC4
) {
6215 GLsizei num_values
= count
* 4;
6216 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6217 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6218 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6220 glUniform4iv(real_location
, count
, temp
.get());
6222 glUniform4fv(real_location
, count
, value
);
6226 void GLES2DecoderImpl::DoUniform2iv(
6227 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6229 GLint real_location
= -1;
6230 if (!PrepForSetUniformByLocation(fake_location
,
6232 Program::kUniform2i
,
6238 glUniform2iv(real_location
, count
, value
);
6241 void GLES2DecoderImpl::DoUniform3iv(
6242 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6244 GLint real_location
= -1;
6245 if (!PrepForSetUniformByLocation(fake_location
,
6247 Program::kUniform3i
,
6253 glUniform3iv(real_location
, count
, value
);
6256 void GLES2DecoderImpl::DoUniform4iv(
6257 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6259 GLint real_location
= -1;
6260 if (!PrepForSetUniformByLocation(fake_location
,
6262 Program::kUniform4i
,
6268 glUniform4iv(real_location
, count
, value
);
6271 void GLES2DecoderImpl::DoUniformMatrix2fv(
6272 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6273 const GLfloat
* value
) {
6275 GLint real_location
= -1;
6276 if (!PrepForSetUniformByLocation(fake_location
,
6277 "glUniformMatrix2fv",
6278 Program::kUniformMatrix2f
,
6284 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6287 void GLES2DecoderImpl::DoUniformMatrix3fv(
6288 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6289 const GLfloat
* value
) {
6291 GLint real_location
= -1;
6292 if (!PrepForSetUniformByLocation(fake_location
,
6293 "glUniformMatrix3fv",
6294 Program::kUniformMatrix3f
,
6300 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6303 void GLES2DecoderImpl::DoUniformMatrix4fv(
6304 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6305 const GLfloat
* value
) {
6307 GLint real_location
= -1;
6308 if (!PrepForSetUniformByLocation(fake_location
,
6309 "glUniformMatrix4fv",
6310 Program::kUniformMatrix4f
,
6316 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6319 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6320 GLuint service_id
= 0;
6321 Program
* program
= NULL
;
6323 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6327 if (!program
->IsValid()) {
6328 // Program was not linked successfully. (ie, glLinkProgram)
6330 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6333 service_id
= program
->service_id();
6335 if (state_
.current_program
.get()) {
6336 program_manager()->UnuseProgram(shader_manager(),
6337 state_
.current_program
.get());
6339 state_
.current_program
= program
;
6340 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6341 glUseProgram(service_id
);
6342 if (state_
.current_program
.get()) {
6343 program_manager()->UseProgram(state_
.current_program
.get());
6344 if (workarounds().clear_uniforms_before_first_program_use
)
6345 program_manager()->ClearUniforms(program
);
6349 void GLES2DecoderImpl::RenderWarning(
6350 const char* filename
, int line
, const std::string
& msg
) {
6351 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6354 void GLES2DecoderImpl::PerformanceWarning(
6355 const char* filename
, int line
, const std::string
& msg
) {
6356 logger_
.LogMessage(filename
, line
,
6357 std::string("PERFORMANCE WARNING: ") + msg
);
6360 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6361 Texture
* texture
, GLenum textarget
) {
6362 // Image is already in use if texture is attached to a framebuffer.
6363 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6364 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6366 ScopedGLErrorSuppressor
suppressor(
6367 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6369 glBindTexture(textarget
, texture
->service_id());
6370 image
->WillUseTexImage();
6371 RestoreCurrentTextureBindings(&state_
, textarget
);
6376 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6377 Texture
* texture
, GLenum textarget
) {
6378 // Image is still in use if texture is attached to a framebuffer.
6379 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6380 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6382 ScopedGLErrorSuppressor
suppressor(
6383 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6385 glBindTexture(textarget
, texture
->service_id());
6386 image
->DidUseTexImage();
6387 RestoreCurrentTextureBindings(&state_
, textarget
);
6392 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6393 DCHECK(state_
.current_program
.get());
6394 if (!texture_manager()->HaveUnrenderableTextures() &&
6395 !texture_manager()->HaveImages()) {
6399 bool textures_set
= false;
6400 const Program::SamplerIndices
& sampler_indices
=
6401 state_
.current_program
->sampler_indices();
6402 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6403 const Program::UniformInfo
* uniform_info
=
6404 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6405 DCHECK(uniform_info
);
6406 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6407 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6408 if (texture_unit_index
< state_
.texture_units
.size()) {
6409 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6410 TextureRef
* texture_ref
=
6411 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6412 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6413 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6414 textures_set
= true;
6415 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6418 texture_manager()->black_texture_id(uniform_info
->type
));
6420 LOCAL_RENDER_WARNING(
6421 std::string("there is no texture bound to the unit ") +
6422 base::IntToString(texture_unit_index
));
6424 LOCAL_RENDER_WARNING(
6425 std::string("texture bound to texture unit ") +
6426 base::IntToString(texture_unit_index
) +
6427 " is not renderable. It maybe non-power-of-2 and have"
6428 " incompatible texture filtering.");
6433 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6434 Texture
* texture
= texture_ref
->texture();
6435 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6436 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6437 ScopedGLErrorSuppressor
suppressor(
6438 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6439 textures_set
= true;
6440 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6441 image
->WillUseTexImage();
6446 // else: should this be an error?
6449 return !textures_set
;
6452 void GLES2DecoderImpl::RestoreStateForTextures() {
6453 DCHECK(state_
.current_program
.get());
6454 const Program::SamplerIndices
& sampler_indices
=
6455 state_
.current_program
->sampler_indices();
6456 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6457 const Program::UniformInfo
* uniform_info
=
6458 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6459 DCHECK(uniform_info
);
6460 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6461 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6462 if (texture_unit_index
< state_
.texture_units
.size()) {
6463 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6464 TextureRef
* texture_ref
=
6465 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6466 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6467 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6468 // Get the texture_ref info that was previously bound here.
6469 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6470 ? texture_unit
.bound_texture_2d
.get()
6471 : texture_unit
.bound_texture_cube_map
.get();
6472 glBindTexture(texture_unit
.bind_target
,
6473 texture_ref
? texture_ref
->service_id() : 0);
6477 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6478 Texture
* texture
= texture_ref
->texture();
6479 gfx::GLImage
* image
=
6480 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6481 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6482 ScopedGLErrorSuppressor
suppressor(
6483 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6484 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6485 image
->DidUseTexImage();
6492 // Set the active texture back to whatever the user had it as.
6493 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6496 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6497 // Only check if there are some uncleared textures.
6498 if (!texture_manager()->HaveUnsafeTextures()) {
6502 // 1: Check all textures we are about to render with.
6503 if (state_
.current_program
.get()) {
6504 const Program::SamplerIndices
& sampler_indices
=
6505 state_
.current_program
->sampler_indices();
6506 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6507 const Program::UniformInfo
* uniform_info
=
6508 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6509 DCHECK(uniform_info
);
6510 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6511 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6512 if (texture_unit_index
< state_
.texture_units
.size()) {
6513 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6514 TextureRef
* texture_ref
=
6515 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6516 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6517 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6528 bool GLES2DecoderImpl::IsDrawValid(
6529 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6530 GLsizei primcount
) {
6531 DCHECK(instanced
|| primcount
== 1);
6533 // NOTE: We specifically do not check current_program->IsValid() because
6534 // it could never be invalid since glUseProgram would have failed. While
6535 // glLinkProgram could later mark the program as invalid the previous
6536 // valid program will still function if it is still the current program.
6537 if (!state_
.current_program
.get()) {
6538 // The program does not exist.
6539 // But GL says no ERROR.
6540 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6544 if (CheckDrawingFeedbackLoops()) {
6546 GL_INVALID_OPERATION
, function_name
,
6547 "Source and destination textures of the draw are the same.");
6551 return state_
.vertex_attrib_manager
6552 ->ValidateBindings(function_name
,
6554 feature_info_
.get(),
6555 state_
.current_program
.get(),
6556 max_vertex_accessed
,
6561 bool GLES2DecoderImpl::SimulateAttrib0(
6562 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6566 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6569 const VertexAttrib
* attrib
=
6570 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6571 // If it's enabled or it's not used then we don't need to do anything.
6572 bool attrib_0_used
=
6573 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6574 if (attrib
->enabled() && attrib_0_used
) {
6578 // Make a buffer with a single repeated vec4 value enough to
6579 // simulate the constant value that is supposed to be here.
6580 // This is required to emulate GLES2 on GL.
6581 GLuint num_vertices
= max_vertex_accessed
+ 1;
6582 uint32 size_needed
= 0;
6584 if (num_vertices
== 0 ||
6585 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6586 size_needed
> 0x7FFFFFFFU
) {
6587 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6591 LOCAL_PERFORMANCE_WARNING(
6592 "Attribute 0 is disabled. This has signficant performance penalty");
6594 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6595 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6597 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6599 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6600 GLenum error
= glGetError();
6601 if (error
!= GL_NO_ERROR
) {
6603 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6608 const Vec4
& value
= state_
.attrib_values
[0];
6611 (!attrib_0_buffer_matches_value_
||
6612 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6613 value
.v
[1] != attrib_0_value_
.v
[1] ||
6614 value
.v
[2] != attrib_0_value_
.v
[2] ||
6615 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6616 std::vector
<Vec4
> temp(num_vertices
, value
);
6617 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6618 attrib_0_buffer_matches_value_
= true;
6619 attrib_0_value_
= value
;
6620 attrib_0_size_
= size_needed
;
6623 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6625 if (attrib
->divisor())
6626 glVertexAttribDivisorANGLE(0, 0);
6632 void GLES2DecoderImpl::RestoreStateForAttrib(
6633 GLuint attrib_index
, bool restore_array_binding
) {
6634 const VertexAttrib
* attrib
=
6635 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6636 if (restore_array_binding
) {
6637 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6638 Buffer
* buffer
= attrib
->buffer();
6639 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6640 glVertexAttribPointer(
6641 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6642 attrib
->gl_stride(), ptr
);
6644 if (attrib
->divisor())
6645 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6647 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6648 state_
.bound_array_buffer
->service_id() : 0);
6650 // Never touch vertex attribute 0's state (in particular, never
6651 // disable it) when running on desktop GL because it will never be
6653 if (attrib_index
!= 0 ||
6654 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6655 if (attrib
->enabled()) {
6656 glEnableVertexAttribArray(attrib_index
);
6658 glDisableVertexAttribArray(attrib_index
);
6663 bool GLES2DecoderImpl::SimulateFixedAttribs(
6664 const char* function_name
,
6665 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6668 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6671 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6675 LOCAL_PERFORMANCE_WARNING(
6676 "GL_FIXED attributes have a signficant performance penalty");
6678 // NOTE: we could be smart and try to check if a buffer is used
6679 // twice in 2 different attribs, find the overlapping parts and therefore
6680 // duplicate the minimum amount of data but this whole code path is not meant
6681 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6682 // tests so we just add to the buffer attrib used.
6684 GLuint elements_needed
= 0;
6685 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6686 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6687 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6688 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6689 const VertexAttrib
* attrib
= *it
;
6690 const Program::VertexAttrib
* attrib_info
=
6691 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6692 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6693 max_vertex_accessed
);
6694 GLuint num_vertices
= max_accessed
+ 1;
6695 if (num_vertices
== 0) {
6697 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6701 attrib
->CanAccess(max_accessed
) &&
6702 attrib
->type() == GL_FIXED
) {
6703 uint32 elements_used
= 0;
6704 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6705 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6707 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6713 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6714 uint32 size_needed
= 0;
6715 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6716 size_needed
> 0x7FFFFFFFU
) {
6718 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6722 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6724 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6725 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6726 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6727 GLenum error
= glGetError();
6728 if (error
!= GL_NO_ERROR
) {
6730 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6735 // Copy the elements and convert to float
6736 GLintptr offset
= 0;
6737 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6738 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6739 const VertexAttrib
* attrib
= *it
;
6740 const Program::VertexAttrib
* attrib_info
=
6741 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6742 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6743 max_vertex_accessed
);
6744 GLuint num_vertices
= max_accessed
+ 1;
6745 if (num_vertices
== 0) {
6747 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6751 attrib
->CanAccess(max_accessed
) &&
6752 attrib
->type() == GL_FIXED
) {
6753 int num_elements
= attrib
->size() * num_vertices
;
6754 const int src_size
= num_elements
* sizeof(int32
);
6755 const int dst_size
= num_elements
* sizeof(float);
6756 scoped_ptr
<float[]> data(new float[num_elements
]);
6757 const int32
* src
= reinterpret_cast<const int32
*>(
6758 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
6759 const int32
* end
= src
+ num_elements
;
6760 float* dst
= data
.get();
6761 while (src
!= end
) {
6762 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6764 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
6765 glVertexAttribPointer(
6766 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6767 reinterpret_cast<GLvoid
*>(offset
));
6775 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6776 // There's no need to call glVertexAttribPointer because we shadow all the
6777 // settings and passing GL_FIXED to it will not work.
6780 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6784 error::Error
GLES2DecoderImpl::DoDrawArrays(
6785 const char* function_name
,
6790 GLsizei primcount
) {
6791 error::Error error
= WillAccessBoundFramebufferForDraw();
6792 if (error
!= error::kNoError
)
6794 if (!validators_
->draw_mode
.IsValid(mode
)) {
6795 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6796 return error::kNoError
;
6799 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6800 return error::kNoError
;
6802 if (primcount
< 0) {
6803 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6804 return error::kNoError
;
6806 if (!CheckBoundFramebuffersValid(function_name
)) {
6807 return error::kNoError
;
6809 // We have to check this here because the prototype for glDrawArrays
6810 // is GLint not GLsizei.
6812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6813 return error::kNoError
;
6816 if (count
== 0 || primcount
== 0) {
6817 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6818 return error::kNoError
;
6821 GLuint max_vertex_accessed
= first
+ count
- 1;
6822 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6823 if (!ClearUnclearedTextures()) {
6824 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6825 return error::kNoError
;
6827 bool simulated_attrib_0
= false;
6828 if (!SimulateAttrib0(
6829 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6830 return error::kNoError
;
6832 bool simulated_fixed_attribs
= false;
6833 if (SimulateFixedAttribs(
6834 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6836 bool textures_set
= !PrepareTexturesForRender();
6838 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6840 glDrawArrays(mode
, first
, count
);
6842 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6845 RestoreStateForTextures();
6847 if (simulated_fixed_attribs
) {
6848 RestoreStateForSimulatedFixedAttribs();
6851 if (simulated_attrib_0
) {
6852 // We don't have to restore attrib 0 generic data at the end of this
6853 // function even if it is simulated. This is because we will simulate
6854 // it in each draw call, and attrib 0 generic data queries use cached
6855 // values instead of passing down to the underlying driver.
6856 RestoreStateForAttrib(0, false);
6859 return error::kNoError
;
6862 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
6863 const void* cmd_data
) {
6864 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
6865 return DoDrawArrays("glDrawArrays",
6867 static_cast<GLenum
>(c
.mode
),
6868 static_cast<GLint
>(c
.first
),
6869 static_cast<GLsizei
>(c
.count
),
6873 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6874 uint32 immediate_data_size
,
6875 const void* cmd_data
) {
6876 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
6877 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
6878 if (!features().angle_instanced_arrays
) {
6880 GL_INVALID_OPERATION
,
6881 "glDrawArraysInstancedANGLE", "function not available");
6882 return error::kNoError
;
6884 return DoDrawArrays("glDrawArraysIntancedANGLE",
6886 static_cast<GLenum
>(c
.mode
),
6887 static_cast<GLint
>(c
.first
),
6888 static_cast<GLsizei
>(c
.count
),
6889 static_cast<GLsizei
>(c
.primcount
));
6892 error::Error
GLES2DecoderImpl::DoDrawElements(
6893 const char* function_name
,
6899 GLsizei primcount
) {
6900 error::Error error
= WillAccessBoundFramebufferForDraw();
6901 if (error
!= error::kNoError
)
6903 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
6905 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
6906 return error::kNoError
;
6910 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6911 return error::kNoError
;
6914 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
6915 return error::kNoError
;
6917 if (!validators_
->draw_mode
.IsValid(mode
)) {
6918 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6919 return error::kNoError
;
6921 if (!validators_
->index_type
.IsValid(type
)) {
6922 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
6923 return error::kNoError
;
6925 if (primcount
< 0) {
6926 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6927 return error::kNoError
;
6930 if (!CheckBoundFramebuffersValid(function_name
)) {
6931 return error::kNoError
;
6934 if (count
== 0 || primcount
== 0) {
6935 return error::kNoError
;
6938 GLuint max_vertex_accessed
;
6939 Buffer
* element_array_buffer
=
6940 state_
.vertex_attrib_manager
->element_array_buffer();
6942 if (!element_array_buffer
->GetMaxValueForRange(
6943 offset
, count
, type
, &max_vertex_accessed
)) {
6945 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
6946 return error::kNoError
;
6949 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6950 if (!ClearUnclearedTextures()) {
6951 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6952 return error::kNoError
;
6954 bool simulated_attrib_0
= false;
6955 if (!SimulateAttrib0(
6956 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6957 return error::kNoError
;
6959 bool simulated_fixed_attribs
= false;
6960 if (SimulateFixedAttribs(
6961 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6963 bool textures_set
= !PrepareTexturesForRender();
6965 // TODO(gman): Refactor to hide these details in BufferManager or
6966 // VertexAttribManager.
6967 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
6968 bool used_client_side_array
= false;
6969 if (element_array_buffer
->IsClientSideArray()) {
6970 used_client_side_array
= true;
6971 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
6972 indices
= element_array_buffer
->GetRange(offset
, 0);
6975 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6977 glDrawElements(mode
, count
, type
, indices
);
6979 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
6982 if (used_client_side_array
) {
6983 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
6984 element_array_buffer
->service_id());
6988 RestoreStateForTextures();
6990 if (simulated_fixed_attribs
) {
6991 RestoreStateForSimulatedFixedAttribs();
6994 if (simulated_attrib_0
) {
6995 // We don't have to restore attrib 0 generic data at the end of this
6996 // function even if it is simulated. This is because we will simulate
6997 // it in each draw call, and attrib 0 generic data queries use cached
6998 // values instead of passing down to the underlying driver.
6999 RestoreStateForAttrib(0, false);
7002 return error::kNoError
;
7005 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7006 const void* cmd_data
) {
7007 const gles2::cmds::DrawElements
& c
=
7008 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7009 return DoDrawElements("glDrawElements",
7011 static_cast<GLenum
>(c
.mode
),
7012 static_cast<GLsizei
>(c
.count
),
7013 static_cast<GLenum
>(c
.type
),
7014 static_cast<int32
>(c
.index_offset
),
7018 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7019 uint32 immediate_data_size
,
7020 const void* cmd_data
) {
7021 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7022 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7023 if (!features().angle_instanced_arrays
) {
7025 GL_INVALID_OPERATION
,
7026 "glDrawElementsInstancedANGLE", "function not available");
7027 return error::kNoError
;
7029 return DoDrawElements("glDrawElementsInstancedANGLE",
7031 static_cast<GLenum
>(c
.mode
),
7032 static_cast<GLsizei
>(c
.count
),
7033 static_cast<GLenum
>(c
.type
),
7034 static_cast<int32
>(c
.index_offset
),
7035 static_cast<GLsizei
>(c
.primcount
));
7038 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7039 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7040 GLuint max_vertex_accessed
= 0;
7041 Buffer
* buffer
= GetBuffer(buffer_id
);
7043 // TODO(gman): Should this be a GL error or a command buffer error?
7045 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7047 if (!buffer
->GetMaxValueForRange(
7048 offset
, count
, type
, &max_vertex_accessed
)) {
7049 // TODO(gman): Should this be a GL error or a command buffer error?
7051 GL_INVALID_OPERATION
,
7052 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7055 return max_vertex_accessed
;
7058 void GLES2DecoderImpl::DoShaderSource(
7059 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7061 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7062 if (length
&& length
[ii
] > 0)
7063 str
.append(data
[ii
], length
[ii
]);
7065 str
.append(data
[ii
]);
7067 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7071 // Note: We don't actually call glShaderSource here. We wait until
7072 // we actually compile the shader.
7073 shader
->set_source(str
);
7076 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7077 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7078 GLenum buffer_mode
) {
7079 Program
* program
= GetProgramInfoNotShader(
7080 client_program_id
, "glTransformFeedbackVaryings");
7084 glTransformFeedbackVaryings(
7085 program
->service_id(), count
, varyings
, buffer_mode
);
7088 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7089 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7090 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7094 ShaderTranslator
* translator
= NULL
;
7095 if (use_shader_translator_
) {
7096 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7097 vertex_translator_
.get() : fragment_translator_
.get();
7102 feature_info_
->feature_flags().angle_translated_shader_source
?
7103 Shader::kANGLE
: Shader::kGL
);
7105 // CompileShader can be very slow. Exit command processing to allow for
7106 // context preemption and GPU watchdog checks.
7107 ExitCommandProcessingEarly();
7110 void GLES2DecoderImpl::DoGetShaderiv(
7111 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7112 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7117 case GL_SHADER_SOURCE_LENGTH
:
7118 *params
= shader
->source().size();
7122 case GL_COMPILE_STATUS
:
7123 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7125 case GL_INFO_LOG_LENGTH
:
7126 *params
= shader
->log_info().size();
7130 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7131 *params
= shader
->translated_source().size();
7138 glGetShaderiv(shader
->service_id(), pname
, params
);
7141 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7142 const void* cmd_data
) {
7143 const gles2::cmds::GetShaderSource
& c
=
7144 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7145 GLuint shader_id
= c
.shader
;
7146 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7147 Bucket
* bucket
= CreateBucket(bucket_id
);
7148 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7149 if (!shader
|| shader
->source().empty()) {
7151 return error::kNoError
;
7153 bucket
->SetFromString(shader
->source().c_str());
7154 return error::kNoError
;
7157 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7158 uint32 immediate_data_size
,
7159 const void* cmd_data
) {
7160 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7161 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
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(
7167 shader_id
, "glGetTranslatedShaderSourceANGLE");
7170 return error::kNoError
;
7173 bucket
->SetFromString(shader
->translated_source().c_str());
7174 return error::kNoError
;
7177 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7178 uint32 immediate_data_size
,
7179 const void* cmd_data
) {
7180 const gles2::cmds::GetProgramInfoLog
& c
=
7181 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7182 GLuint program_id
= c
.program
;
7183 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7184 Bucket
* bucket
= CreateBucket(bucket_id
);
7185 Program
* program
= GetProgramInfoNotShader(
7186 program_id
, "glGetProgramInfoLog");
7187 if (!program
|| !program
->log_info()) {
7188 bucket
->SetFromString("");
7189 return error::kNoError
;
7191 bucket
->SetFromString(program
->log_info()->c_str());
7192 return error::kNoError
;
7195 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7196 uint32 immediate_data_size
,
7197 const void* cmd_data
) {
7198 const gles2::cmds::GetShaderInfoLog
& c
=
7199 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7200 GLuint shader_id
= c
.shader
;
7201 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7202 Bucket
* bucket
= CreateBucket(bucket_id
);
7203 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7205 bucket
->SetFromString("");
7206 return error::kNoError
;
7208 bucket
->SetFromString(shader
->log_info().c_str());
7209 return error::kNoError
;
7212 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7213 return state_
.GetEnabled(cap
);
7216 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7217 const Buffer
* buffer
= GetBuffer(client_id
);
7218 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7221 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7222 const Framebuffer
* framebuffer
=
7223 GetFramebuffer(client_id
);
7224 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7227 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7228 // IsProgram is true for programs as soon as they are created, until they are
7229 // deleted and no longer in use.
7230 const Program
* program
= GetProgram(client_id
);
7231 return program
!= NULL
&& !program
->IsDeleted();
7234 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7235 const Renderbuffer
* renderbuffer
=
7236 GetRenderbuffer(client_id
);
7237 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7240 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7241 // IsShader is true for shaders as soon as they are created, until they
7242 // are deleted and not attached to any programs.
7243 const Shader
* shader
= GetShader(client_id
);
7244 return shader
!= NULL
&& !shader
->IsDeleted();
7247 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7248 const TextureRef
* texture_ref
= GetTexture(client_id
);
7249 return texture_ref
&& texture_ref
->texture()->IsValid();
7252 void GLES2DecoderImpl::DoAttachShader(
7253 GLuint program_client_id
, GLint shader_client_id
) {
7254 Program
* program
= GetProgramInfoNotShader(
7255 program_client_id
, "glAttachShader");
7259 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7263 if (!program
->AttachShader(shader_manager(), shader
)) {
7265 GL_INVALID_OPERATION
,
7267 "can not attach more than one shader of the same type.");
7270 glAttachShader(program
->service_id(), shader
->service_id());
7273 void GLES2DecoderImpl::DoDetachShader(
7274 GLuint program_client_id
, GLint shader_client_id
) {
7275 Program
* program
= GetProgramInfoNotShader(
7276 program_client_id
, "glDetachShader");
7280 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7284 if (!program
->DetachShader(shader_manager(), shader
)) {
7286 GL_INVALID_OPERATION
,
7287 "glDetachShader", "shader not attached to program");
7290 glDetachShader(program
->service_id(), shader
->service_id());
7293 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7294 Program
* program
= GetProgramInfoNotShader(
7295 program_client_id
, "glValidateProgram");
7299 program
->Validate();
7302 void GLES2DecoderImpl::GetVertexAttribHelper(
7303 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7305 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7306 Buffer
* buffer
= attrib
->buffer();
7307 if (buffer
&& !buffer
->IsDeleted()) {
7309 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7310 *params
= client_id
;
7314 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7315 *params
= attrib
->enabled();
7317 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7318 *params
= attrib
->size();
7320 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7321 *params
= attrib
->gl_stride();
7323 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7324 *params
= attrib
->type();
7326 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7327 *params
= attrib
->normalized();
7329 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7330 *params
= attrib
->divisor();
7338 void GLES2DecoderImpl::DoGetTexParameterfv(
7339 GLenum target
, GLenum pname
, GLfloat
* params
) {
7340 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7341 glGetTexParameterfv(target
, pname
, params
);
7344 void GLES2DecoderImpl::DoGetTexParameteriv(
7345 GLenum target
, GLenum pname
, GLint
* params
) {
7346 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7347 glGetTexParameteriv(target
, pname
, params
);
7350 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7351 GLenum target
, GLenum pname
) {
7352 if (!workarounds().init_texture_max_anisotropy
)
7354 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7355 !validators_
->texture_parameter
.IsValid(pname
)) {
7359 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7363 GL_INVALID_OPERATION
,
7364 "glGetTexParamter{fi}v", "unknown texture for target");
7367 Texture
* texture
= texture_ref
->texture();
7368 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7371 void GLES2DecoderImpl::DoGetVertexAttribfv(
7372 GLuint index
, GLenum pname
, GLfloat
* params
) {
7373 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7376 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7380 case GL_CURRENT_VERTEX_ATTRIB
: {
7381 const Vec4
& value
= state_
.attrib_values
[index
];
7382 params
[0] = value
.v
[0];
7383 params
[1] = value
.v
[1];
7384 params
[2] = value
.v
[2];
7385 params
[3] = value
.v
[3];
7390 GetVertexAttribHelper(attrib
, pname
, &value
);
7391 *params
= static_cast<GLfloat
>(value
);
7397 void GLES2DecoderImpl::DoGetVertexAttribiv(
7398 GLuint index
, GLenum pname
, GLint
* params
) {
7399 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7402 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7406 case GL_CURRENT_VERTEX_ATTRIB
: {
7407 const Vec4
& value
= state_
.attrib_values
[index
];
7408 params
[0] = static_cast<GLint
>(value
.v
[0]);
7409 params
[1] = static_cast<GLint
>(value
.v
[1]);
7410 params
[2] = static_cast<GLint
>(value
.v
[2]);
7411 params
[3] = static_cast<GLint
>(value
.v
[3]);
7415 GetVertexAttribHelper(attrib
, pname
, params
);
7420 bool GLES2DecoderImpl::SetVertexAttribValue(
7421 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7422 if (index
>= state_
.attrib_values
.size()) {
7423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7426 Vec4
& v
= state_
.attrib_values
[index
];
7434 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7435 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7436 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7437 glVertexAttrib1f(index
, v0
);
7441 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7442 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7443 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7444 glVertexAttrib2f(index
, v0
, v1
);
7448 void GLES2DecoderImpl::DoVertexAttrib3f(
7449 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7450 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7451 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7452 glVertexAttrib3f(index
, v0
, v1
, v2
);
7456 void GLES2DecoderImpl::DoVertexAttrib4f(
7457 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7458 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7459 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7460 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7464 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7465 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7466 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7467 glVertexAttrib1fv(index
, v
);
7471 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7472 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7473 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7474 glVertexAttrib2fv(index
, v
);
7478 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7479 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7480 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7481 glVertexAttrib3fv(index
, v
);
7485 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7486 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7487 glVertexAttrib4fv(index
, v
);
7491 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7492 uint32 immediate_data_size
,
7493 const void* cmd_data
) {
7494 // TODO(zmo): Unsafe ES3 API, missing states update.
7495 if (!unsafe_es3_apis_enabled())
7496 return error::kUnknownCommand
;
7497 const gles2::cmds::VertexAttribIPointer
& c
=
7498 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7499 GLuint indx
= c
.indx
;
7500 GLint size
= c
.size
;
7501 GLenum type
= c
.type
;
7502 GLsizei stride
= c
.stride
;
7503 GLsizei offset
= c
.offset
;
7504 const void* ptr
= reinterpret_cast<const void*>(offset
);
7505 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7506 return error::kNoError
;
7509 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7510 uint32 immediate_data_size
,
7511 const void* cmd_data
) {
7512 const gles2::cmds::VertexAttribPointer
& c
=
7513 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7515 if (!state_
.bound_array_buffer
.get() ||
7516 state_
.bound_array_buffer
->IsDeleted()) {
7517 if (state_
.vertex_attrib_manager
.get() ==
7518 state_
.default_vertex_attrib_manager
.get()) {
7520 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7521 return error::kNoError
;
7522 } else if (c
.offset
!= 0) {
7525 "glVertexAttribPointer", "client side arrays are not allowed");
7526 return error::kNoError
;
7530 GLuint indx
= c
.indx
;
7531 GLint size
= c
.size
;
7532 GLenum type
= c
.type
;
7533 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
7534 GLsizei stride
= c
.stride
;
7535 GLsizei offset
= c
.offset
;
7536 const void* ptr
= reinterpret_cast<const void*>(offset
);
7537 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7538 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7539 return error::kNoError
;
7541 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7543 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7544 return error::kNoError
;
7546 if (indx
>= group_
->max_vertex_attribs()) {
7548 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7549 return error::kNoError
;
7553 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7554 return error::kNoError
;
7558 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7559 return error::kNoError
;
7563 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7564 return error::kNoError
;
7566 GLsizei component_size
=
7567 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7568 // component_size must be a power of two to use & as optimized modulo.
7569 DCHECK(GLES2Util::IsPOT(component_size
));
7570 if (offset
& (component_size
- 1)) {
7572 GL_INVALID_OPERATION
,
7573 "glVertexAttribPointer", "offset not valid for type");
7574 return error::kNoError
;
7576 if (stride
& (component_size
- 1)) {
7578 GL_INVALID_OPERATION
,
7579 "glVertexAttribPointer", "stride not valid for type");
7580 return error::kNoError
;
7582 state_
.vertex_attrib_manager
7583 ->SetAttribInfo(indx
,
7584 state_
.bound_array_buffer
.get(),
7589 stride
!= 0 ? stride
: component_size
* size
,
7591 if (type
!= GL_FIXED
) {
7592 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7594 return error::kNoError
;
7597 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7599 state_
.viewport_x
= x
;
7600 state_
.viewport_y
= y
;
7601 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7602 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7603 glViewport(x
, y
, width
, height
);
7606 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7607 uint32 immediate_data_size
,
7608 const void* cmd_data
) {
7609 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7610 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7611 if (!features().angle_instanced_arrays
) {
7613 GL_INVALID_OPERATION
,
7614 "glVertexAttribDivisorANGLE", "function not available");
7615 return error::kNoError
;
7617 GLuint index
= c
.index
;
7618 GLuint divisor
= c
.divisor
;
7619 if (index
>= group_
->max_vertex_attribs()) {
7622 "glVertexAttribDivisorANGLE", "index out of range");
7623 return error::kNoError
;
7626 state_
.vertex_attrib_manager
->SetDivisor(
7629 glVertexAttribDivisorANGLE(index
, divisor
);
7630 return error::kNoError
;
7633 template <typename pixel_data_type
>
7634 static void WriteAlphaData(
7635 void *pixels
, uint32 row_count
, uint32 channel_count
,
7636 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7637 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7638 DCHECK_GT(channel_count
, 0U);
7639 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7640 uint32 unpadded_row_size_in_elements
=
7641 unpadded_row_size
/ sizeof(pixel_data_type
);
7642 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7643 uint32 padded_row_size_in_elements
=
7644 padded_row_size
/ sizeof(pixel_data_type
);
7645 pixel_data_type
* dst
=
7646 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7647 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7648 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7649 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7652 dst
+= padded_row_size_in_elements
;
7656 void GLES2DecoderImpl::FinishReadPixels(
7657 const cmds::ReadPixels
& c
,
7659 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7660 GLsizei width
= c
.width
;
7661 GLsizei height
= c
.height
;
7662 GLenum format
= c
.format
;
7663 GLenum type
= c
.type
;
7664 typedef cmds::ReadPixels::Result Result
;
7666 Result
* result
= NULL
;
7667 if (c
.result_shm_id
!= 0) {
7668 result
= GetSharedMemoryAs
<Result
*>(
7669 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7672 glDeleteBuffersARB(1, &buffer
);
7677 GLES2Util::ComputeImageDataSizes(
7678 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7680 void* pixels
= GetSharedMemoryAs
<void*>(
7681 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7684 glDeleteBuffersARB(1, &buffer
);
7690 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7692 if (features().map_buffer_range
) {
7693 data
= glMapBufferRange(
7694 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7696 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7699 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
7700 "Unable to map memory for readback.");
7703 memcpy(pixels
, data
, pixels_size
);
7704 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7705 // have to restore the state.
7706 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7707 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7708 glDeleteBuffersARB(1, &buffer
);
7711 if (result
!= NULL
) {
7715 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7716 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7717 if ((channels_exist
& 0x0008) == 0 &&
7718 workarounds().clear_alpha_in_readpixels
) {
7719 // Set the alpha to 255 because some drivers are buggy in this regard.
7722 uint32 unpadded_row_size
;
7723 uint32 padded_row_size
;
7724 if (!GLES2Util::ComputeImageDataSizes(
7725 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
7726 &unpadded_row_size
, &padded_row_size
)) {
7730 uint32 channel_count
= 0;
7731 uint32 alpha_channel
= 0;
7744 if (channel_count
> 0) {
7746 case GL_UNSIGNED_BYTE
:
7747 WriteAlphaData
<uint8
>(
7748 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7749 padded_row_size
, 0xFF);
7752 WriteAlphaData
<float>(
7753 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7754 padded_row_size
, 1.0f
);
7757 WriteAlphaData
<uint16
>(
7758 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7759 padded_row_size
, 0x3C00);
7766 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
7767 const void* cmd_data
) {
7768 const gles2::cmds::ReadPixels
& c
=
7769 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
7770 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7771 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7772 if (fbo_error
!= error::kNoError
)
7776 GLsizei width
= c
.width
;
7777 GLsizei height
= c
.height
;
7778 GLenum format
= c
.format
;
7779 GLenum type
= c
.type
;
7780 GLboolean async
= static_cast<GLboolean
>(c
.async
);
7781 if (width
< 0 || height
< 0) {
7782 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7783 return error::kNoError
;
7785 typedef cmds::ReadPixels::Result Result
;
7787 if (!GLES2Util::ComputeImageDataSizes(
7788 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7790 return error::kOutOfBounds
;
7792 void* pixels
= GetSharedMemoryAs
<void*>(
7793 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7795 return error::kOutOfBounds
;
7797 Result
* result
= NULL
;
7798 if (c
.result_shm_id
!= 0) {
7799 result
= GetSharedMemoryAs
<Result
*>(
7800 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7802 return error::kOutOfBounds
;
7806 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7807 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7808 return error::kNoError
;
7810 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7811 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7812 return error::kNoError
;
7814 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7815 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7816 // format and type are acceptable enums but not guaranteed to be supported
7817 // for this framebuffer. Have to ask gl if they are valid.
7818 GLint preferred_format
= 0;
7819 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7820 GLint preferred_type
= 0;
7821 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7822 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7823 type
!= static_cast<GLenum
>(preferred_type
)) {
7825 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7826 "with the current read framebuffer");
7827 return error::kNoError
;
7830 if (width
== 0 || height
== 0) {
7831 return error::kNoError
;
7834 // Get the size of the current fbo or backbuffer.
7835 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7839 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
7841 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7842 return error::kNoError
;
7845 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7846 return error::kNoError
;
7849 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7850 return error::kNoError
;
7853 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7855 ScopedResolvedFrameBufferBinder
binder(this, false, true);
7857 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
7858 // The user requested an out of range area. Get the results 1 line
7861 uint32 unpadded_row_size
;
7862 uint32 padded_row_size
;
7863 if (!GLES2Util::ComputeImageDataSizes(
7864 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
7865 &unpadded_row_size
, &padded_row_size
)) {
7867 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7868 return error::kNoError
;
7871 GLint dest_x_offset
= std::max(-x
, 0);
7872 uint32 dest_row_offset
;
7873 if (!GLES2Util::ComputeImageDataSizes(
7874 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
7875 &dest_row_offset
, NULL
, NULL
)) {
7877 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
7878 return error::kNoError
;
7881 // Copy each row into the larger dest rect.
7882 int8
* dst
= static_cast<int8
*>(pixels
);
7883 GLint read_x
= std::max(0, x
);
7884 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
7885 GLint read_width
= read_end_x
- read_x
;
7886 for (GLint yy
= 0; yy
< height
; ++yy
) {
7890 memset(dst
, 0, unpadded_row_size
);
7892 // If the row is in range, copy it.
7893 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
7895 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
7897 dst
+= padded_row_size
;
7900 if (async
&& features().use_async_readpixels
) {
7902 glGenBuffersARB(1, &buffer
);
7903 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7904 // For ANGLE client version 2, GL_STREAM_READ is not available.
7905 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
7906 GL_STATIC_DRAW
: GL_STREAM_READ
;
7907 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
7908 GLenum error
= glGetError();
7909 if (error
== GL_NO_ERROR
) {
7910 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
7911 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
7912 new FenceCallback()));
7913 WaitForReadPixels(base::Bind(
7914 &GLES2DecoderImpl::FinishReadPixels
,
7915 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7916 <GLES2DecoderImpl
>(this),
7918 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7919 return error::kNoError
;
7921 // On error, unbind pack buffer and fall through to sync readpixels
7922 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7923 glDeleteBuffersARB(1, &buffer
);
7926 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
7928 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
7929 if (error
== GL_NO_ERROR
) {
7930 if (result
!= NULL
) {
7933 FinishReadPixels(c
, 0);
7936 return error::kNoError
;
7939 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
7940 const void* cmd_data
) {
7941 const gles2::cmds::PixelStorei
& c
=
7942 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
7943 GLenum pname
= c
.pname
;
7944 GLenum param
= c
.param
;
7945 if (!validators_
->pixel_store
.IsValid(pname
)) {
7946 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
7947 return error::kNoError
;
7950 case GL_PACK_ALIGNMENT
:
7951 case GL_UNPACK_ALIGNMENT
:
7952 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
7954 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
7955 return error::kNoError
;
7958 case GL_UNPACK_FLIP_Y_CHROMIUM
:
7959 unpack_flip_y_
= (param
!= 0);
7960 return error::kNoError
;
7961 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
7962 unpack_premultiply_alpha_
= (param
!= 0);
7963 return error::kNoError
;
7964 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
7965 unpack_unpremultiply_alpha_
= (param
!= 0);
7966 return error::kNoError
;
7970 glPixelStorei(pname
, param
);
7972 case GL_PACK_ALIGNMENT
:
7973 state_
.pack_alignment
= param
;
7975 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
7976 state_
.pack_reverse_row_order
= (param
!= 0);
7978 case GL_UNPACK_ALIGNMENT
:
7979 state_
.unpack_alignment
= param
;
7982 // Validation should have prevented us from getting here.
7986 return error::kNoError
;
7989 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7990 uint32 immediate_data_size
,
7991 const void* cmd_data
) {
7992 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
7993 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
7994 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7996 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7998 if (!supports_post_sub_buffer_
) {
8000 GL_INVALID_OPERATION
,
8001 "glPostSubBufferCHROMIUM", "command not supported by surface");
8002 return error::kNoError
;
8005 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8008 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8009 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8010 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8011 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8013 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8014 return error::kNoError
;
8016 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8017 return error::kLostContext
;
8021 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8022 uint32 immediate_data_size
,
8023 const void* cmd_data
) {
8024 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8025 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8026 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8029 "glScheduleOverlayPlaneCHROMIUM",
8031 return error::kNoError
;
8033 gfx::GLImage
* image
=
8034 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8036 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8037 "glScheduleOverlayPlaneCHROMIUM",
8038 "unsupported texture format");
8039 return error::kNoError
;
8041 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8042 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8043 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8044 "glScheduleOverlayPlaneCHROMIUM",
8045 "invalid transform enum");
8046 return error::kNoError
;
8048 if (!surface_
->ScheduleOverlayPlane(
8052 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8053 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8054 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8055 "glScheduleOverlayPlaneCHROMIUM",
8056 "failed to schedule overlay");
8058 return error::kNoError
;
8061 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8062 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8063 const std::string
& name_str
) {
8064 if (!StringIsValidForGLES(name_str
.c_str())) {
8066 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8067 return error::kNoError
;
8069 Program
* program
= GetProgramInfoNotShader(
8070 client_id
, "glGetAttribLocation");
8072 return error::kNoError
;
8074 if (!program
->IsValid()) {
8076 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8077 return error::kNoError
;
8079 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8080 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8082 return error::kOutOfBounds
;
8084 // Require the client to init this incase the context is lost and we are no
8085 // longer executing commands.
8086 if (*location
!= -1) {
8087 return error::kGenericError
;
8089 *location
= program
->GetAttribLocation(name_str
);
8090 return error::kNoError
;
8093 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8094 uint32 immediate_data_size
,
8095 const void* cmd_data
) {
8096 const gles2::cmds::GetAttribLocation
& c
=
8097 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8098 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8100 return error::kInvalidArguments
;
8102 std::string name_str
;
8103 if (!bucket
->GetAsString(&name_str
)) {
8104 return error::kInvalidArguments
;
8106 return GetAttribLocationHelper(
8107 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8110 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8111 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8112 const std::string
& name_str
) {
8113 if (!StringIsValidForGLES(name_str
.c_str())) {
8115 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8116 return error::kNoError
;
8118 Program
* program
= GetProgramInfoNotShader(
8119 client_id
, "glGetUniformLocation");
8121 return error::kNoError
;
8123 if (!program
->IsValid()) {
8125 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8126 return error::kNoError
;
8128 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8129 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8131 return error::kOutOfBounds
;
8133 // Require the client to init this incase the context is lost an we are no
8134 // longer executing commands.
8135 if (*location
!= -1) {
8136 return error::kGenericError
;
8138 *location
= program
->GetUniformFakeLocation(name_str
);
8139 return error::kNoError
;
8142 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8143 uint32 immediate_data_size
,
8144 const void* cmd_data
) {
8145 const gles2::cmds::GetUniformLocation
& c
=
8146 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8147 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8149 return error::kInvalidArguments
;
8151 std::string name_str
;
8152 if (!bucket
->GetAsString(&name_str
)) {
8153 return error::kInvalidArguments
;
8155 return GetUniformLocationHelper(
8156 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8159 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8160 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8161 const std::string
& name_str
) {
8162 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8163 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8165 return error::kOutOfBounds
;
8167 // Require the client to init this incase the context is lost and we are no
8168 // longer executing commands.
8169 if (*location
!= -1) {
8170 return error::kGenericError
;
8172 Program
* program
= GetProgramInfoNotShader(
8173 client_id
, "glGetFragDataLocation");
8175 return error::kNoError
;
8177 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8178 return error::kNoError
;
8181 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8182 uint32 immediate_data_size
,
8183 const void* cmd_data
) {
8184 if (!unsafe_es3_apis_enabled())
8185 return error::kUnknownCommand
;
8186 const gles2::cmds::GetFragDataLocation
& c
=
8187 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8188 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8190 return error::kInvalidArguments
;
8192 std::string name_str
;
8193 if (!bucket
->GetAsString(&name_str
)) {
8194 return error::kInvalidArguments
;
8196 return GetFragDataLocationHelper(
8197 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8200 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8201 const void* cmd_data
) {
8202 const gles2::cmds::GetString
& c
=
8203 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8204 GLenum name
= static_cast<GLenum
>(c
.name
);
8205 if (!validators_
->string_type
.IsValid(name
)) {
8206 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8207 return error::kNoError
;
8209 const char* str
= reinterpret_cast<const char*>(glGetString(name
));
8210 std::string extensions
;
8213 str
= "OpenGL ES 2.0 Chromium";
8215 case GL_SHADING_LANGUAGE_VERSION
:
8216 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8220 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8221 // They are used by WEBGL_debug_renderer_info.
8222 if (!force_webgl_glsl_validation_
)
8227 // For WebGL contexts, strip out the OES derivatives and
8228 // EXT frag depth extensions if they have not been enabled.
8229 if (force_webgl_glsl_validation_
) {
8230 extensions
= feature_info_
->extensions();
8231 if (!derivatives_explicitly_enabled_
) {
8232 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8233 if (std::string::npos
!= offset
) {
8234 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8238 if (!frag_depth_explicitly_enabled_
) {
8239 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8240 if (std::string::npos
!= offset
) {
8241 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8245 if (!draw_buffers_explicitly_enabled_
) {
8246 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8247 if (std::string::npos
!= offset
) {
8248 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8252 if (!shader_texture_lod_explicitly_enabled_
) {
8253 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8254 if (std::string::npos
!= offset
) {
8255 extensions
.replace(offset
,
8256 arraysize(kEXTShaderTextureLodExtension
),
8261 extensions
= feature_info_
->extensions().c_str();
8263 if (supports_post_sub_buffer_
)
8264 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8265 str
= extensions
.c_str();
8271 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8272 bucket
->SetFromString(str
);
8273 return error::kNoError
;
8276 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8277 const void* cmd_data
) {
8278 const gles2::cmds::BufferData
& c
=
8279 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8280 GLenum target
= static_cast<GLenum
>(c
.target
);
8281 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8282 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8283 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8284 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8285 const void* data
= NULL
;
8286 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8287 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8289 return error::kOutOfBounds
;
8292 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8293 return error::kNoError
;
8296 void GLES2DecoderImpl::DoBufferSubData(
8297 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8298 // Just delegate it. Some validation is actually done before this.
8299 buffer_manager()->ValidateAndDoBufferSubData(
8300 &state_
, target
, offset
, size
, data
);
8303 bool GLES2DecoderImpl::ClearLevel(
8304 unsigned service_id
,
8305 unsigned bind_target
,
8308 unsigned internal_format
,
8313 bool is_texture_immutable
) {
8314 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8315 if (feature_info_
->feature_flags().angle_depth_texture
&&
8316 (channels
& GLES2Util::kDepth
) != 0) {
8317 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8318 // on depth formats.
8320 glGenFramebuffersEXT(1, &fb
);
8321 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8323 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8324 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8325 GL_DEPTH_ATTACHMENT
;
8327 glFramebufferTexture2DEXT(
8328 GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
, service_id
, level
);
8329 // ANGLE promises a depth only attachment ok.
8330 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8331 GL_FRAMEBUFFER_COMPLETE
) {
8335 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8336 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8338 state_
.SetDeviceDepthMask(GL_TRUE
);
8339 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8340 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8342 RestoreClearState();
8344 glDeleteFramebuffersEXT(1, &fb
);
8345 Framebuffer
* framebuffer
=
8346 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8347 GLuint fb_service_id
=
8348 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8349 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8353 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8356 uint32 padded_row_size
;
8357 if (!GLES2Util::ComputeImageDataSizes(
8358 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8359 NULL
, &padded_row_size
)) {
8363 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8367 if (size
> kMaxZeroSize
) {
8368 if (kMaxZeroSize
< padded_row_size
) {
8369 // That'd be an awfully large texture.
8372 // We should never have a large total size with a zero row size.
8373 DCHECK_GT(padded_row_size
, 0U);
8374 tile_height
= kMaxZeroSize
/ padded_row_size
;
8375 if (!GLES2Util::ComputeImageDataSizes(
8376 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8381 tile_height
= height
;
8384 // Assumes the size has already been checked.
8385 scoped_ptr
<char[]> zero(new char[size
]);
8386 memset(zero
.get(), 0, size
);
8387 glBindTexture(bind_target
, service_id
);
8390 while (y
< height
) {
8391 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8392 if (is_texture_immutable
|| h
!= height
) {
8393 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8396 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8401 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
8402 &state_
, bind_target
);
8403 glBindTexture(bind_target
, texture
? texture
->service_id() : 0);
8409 const int kS3TCBlockWidth
= 4;
8410 const int kS3TCBlockHeight
= 4;
8411 const int kS3TCDXT1BlockSize
= 8;
8412 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8414 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8415 return (size
== 1) ||
8416 (size
== 2) || !(size
% kS3TCBlockWidth
);
8419 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8420 return GLES2Util::IsPOT(size
);
8423 } // anonymous namespace.
8425 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8426 const char* function_name
,
8427 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
8428 unsigned int bytes_required
= 0;
8431 case GL_ATC_RGB_AMD
:
8432 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8433 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8434 case GL_ETC1_RGB8_OES
: {
8435 int num_blocks_across
=
8436 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8437 int num_blocks_down
=
8438 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8439 int num_blocks
= num_blocks_across
* num_blocks_down
;
8440 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
8443 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8444 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8445 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8446 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8447 int num_blocks_across
=
8448 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8449 int num_blocks_down
=
8450 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8451 int num_blocks
= num_blocks_across
* num_blocks_down
;
8452 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
8455 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8456 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
8457 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
8460 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8461 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8462 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
8466 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8470 if (size
!= bytes_required
) {
8472 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8479 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8480 const char* function_name
,
8481 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
8483 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8484 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8485 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8486 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8487 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8489 GL_INVALID_OPERATION
, function_name
,
8490 "width or height invalid for level");
8495 case GL_ATC_RGB_AMD
:
8496 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8497 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8498 case GL_ETC1_RGB8_OES
: {
8499 if (width
<= 0 || height
<= 0) {
8501 GL_INVALID_OPERATION
, function_name
,
8502 "width or height invalid for level");
8507 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8508 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8509 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8510 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8511 if (!IsValidPVRTCSize(level
, width
) ||
8512 !IsValidPVRTCSize(level
, height
)) {
8514 GL_INVALID_OPERATION
, function_name
,
8515 "width or height invalid for level");
8525 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8526 const char* function_name
,
8527 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8528 GLsizei width
, GLsizei height
, GLenum format
,
8530 if (xoffset
< 0 || yoffset
< 0) {
8532 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8537 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8538 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8539 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8540 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8541 const int kBlockWidth
= 4;
8542 const int kBlockHeight
= 4;
8543 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8545 GL_INVALID_OPERATION
, function_name
,
8546 "xoffset or yoffset not multiple of 4");
8549 GLsizei tex_width
= 0;
8550 GLsizei tex_height
= 0;
8551 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8552 width
- xoffset
> tex_width
||
8553 height
- yoffset
> tex_height
) {
8555 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8558 return ValidateCompressedTexDimensions(
8559 function_name
, level
, width
, height
, format
);
8561 case GL_ATC_RGB_AMD
:
8562 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8563 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8565 GL_INVALID_OPERATION
, function_name
,
8566 "not supported for ATC textures");
8569 case GL_ETC1_RGB8_OES
: {
8571 GL_INVALID_OPERATION
, function_name
,
8572 "not supported for ECT1_RGB8_OES textures");
8575 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8576 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8577 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8578 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8579 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8581 GL_INVALID_OPERATION
, function_name
,
8582 "xoffset and yoffset must be zero");
8585 GLsizei tex_width
= 0;
8586 GLsizei tex_height
= 0;
8587 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8588 width
!= tex_width
||
8589 height
!= tex_height
) {
8591 GL_INVALID_OPERATION
, function_name
,
8592 "dimensions must match existing texture level dimensions");
8595 return ValidateCompressedTexDimensions(
8596 function_name
, level
, width
, height
, format
);
8603 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8606 GLenum internal_format
,
8612 // TODO(gman): Validate image_size is correct for width, height and format.
8613 if (!validators_
->texture_target
.IsValid(target
)) {
8614 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8615 "glCompressedTexImage2D", target
, "target");
8616 return error::kNoError
;
8618 if (!validators_
->compressed_texture_format
.IsValid(
8620 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8621 "glCompressedTexImage2D", internal_format
, "internal_format");
8622 return error::kNoError
;
8624 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8628 "glCompressedTexImage2D", "dimensions out of range");
8629 return error::kNoError
;
8631 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8636 "glCompressedTexImage2D", "unknown texture target");
8637 return error::kNoError
;
8639 Texture
* texture
= texture_ref
->texture();
8640 if (texture
->IsImmutable()) {
8642 GL_INVALID_OPERATION
,
8643 "glCompressedTexImage2D", "texture is immutable");
8644 return error::kNoError
;
8647 if (!ValidateCompressedTexDimensions(
8648 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8649 !ValidateCompressedTexFuncData(
8650 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8651 return error::kNoError
;
8654 if (!EnsureGPUMemoryAvailable(image_size
)) {
8656 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8657 return error::kNoError
;
8660 if (texture
->IsAttachedToFramebuffer()) {
8661 framebuffer_state_
.clear_state_dirty
= true;
8664 scoped_ptr
<int8
[]> zero
;
8666 zero
.reset(new int8
[image_size
]);
8667 memset(zero
.get(), 0, image_size
);
8670 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8671 glCompressedTexImage2D(
8672 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8673 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8674 if (error
== GL_NO_ERROR
) {
8675 texture_manager()->SetLevelInfo(
8676 texture_ref
, target
, level
, internal_format
,
8677 width
, height
, 1, border
, 0, 0, true);
8680 // This may be a slow command. Exit command processing to allow for
8681 // context preemption and GPU watchdog checks.
8682 ExitCommandProcessingEarly();
8683 return error::kNoError
;
8686 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8687 uint32 immediate_data_size
,
8688 const void* cmd_data
) {
8689 const gles2::cmds::CompressedTexImage2D
& c
=
8690 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
8691 GLenum target
= static_cast<GLenum
>(c
.target
);
8692 GLint level
= static_cast<GLint
>(c
.level
);
8693 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8694 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8695 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8696 GLint border
= static_cast<GLint
>(c
.border
);
8697 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8698 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8699 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8700 const void* data
= NULL
;
8701 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8702 data
= GetSharedMemoryAs
<const void*>(
8703 data_shm_id
, data_shm_offset
, image_size
);
8705 return error::kOutOfBounds
;
8708 return DoCompressedTexImage2D(
8709 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8712 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8713 uint32 immediate_data_size
,
8714 const void* cmd_data
) {
8715 const gles2::cmds::CompressedTexImage2DBucket
& c
=
8716 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
8717 GLenum target
= static_cast<GLenum
>(c
.target
);
8718 GLint level
= static_cast<GLint
>(c
.level
);
8719 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8720 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8721 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8722 GLint border
= static_cast<GLint
>(c
.border
);
8723 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8725 return error::kInvalidArguments
;
8727 uint32 data_size
= bucket
->size();
8728 GLsizei imageSize
= data_size
;
8729 const void* data
= bucket
->GetData(0, data_size
);
8731 return error::kInvalidArguments
;
8733 return DoCompressedTexImage2D(
8734 target
, level
, internal_format
, width
, height
, border
,
8738 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8739 uint32 immediate_data_size
,
8740 const void* cmd_data
) {
8741 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
8742 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
8743 GLenum target
= static_cast<GLenum
>(c
.target
);
8744 GLint level
= static_cast<GLint
>(c
.level
);
8745 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8746 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8747 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8748 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8749 GLenum format
= static_cast<GLenum
>(c
.format
);
8750 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8752 return error::kInvalidArguments
;
8754 uint32 data_size
= bucket
->size();
8755 GLsizei imageSize
= data_size
;
8756 const void* data
= bucket
->GetData(0, data_size
);
8758 return error::kInvalidArguments
;
8760 if (!validators_
->texture_target
.IsValid(target
)) {
8762 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
8763 return error::kNoError
;
8765 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
8766 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8767 "glCompressedTexSubImage2D", format
, "format");
8768 return error::kNoError
;
8772 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
8773 return error::kNoError
;
8777 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
8778 return error::kNoError
;
8780 if (imageSize
< 0) {
8782 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
8783 return error::kNoError
;
8785 DoCompressedTexSubImage2D(
8786 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
8787 return error::kNoError
;
8790 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
8791 const void* cmd_data
) {
8792 const gles2::cmds::TexImage2D
& c
=
8793 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
8794 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8795 "width", c
.width
, "height", c
.height
);
8796 // Set as failed for now, but if it successed, this will be set to not failed.
8797 texture_state_
.tex_image_2d_failed
= true;
8798 GLenum target
= static_cast<GLenum
>(c
.target
);
8799 GLint level
= static_cast<GLint
>(c
.level
);
8800 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8801 // for internalformat.
8802 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8803 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8804 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8805 GLint border
= static_cast<GLint
>(c
.border
);
8806 GLenum format
= static_cast<GLenum
>(c
.format
);
8807 GLenum type
= static_cast<GLenum
>(c
.type
);
8808 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8809 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8811 if (!GLES2Util::ComputeImageDataSizes(
8812 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8814 return error::kOutOfBounds
;
8816 const void* pixels
= NULL
;
8817 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8818 pixels
= GetSharedMemoryAs
<const void*>(
8819 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8821 return error::kOutOfBounds
;
8825 TextureManager::DoTextImage2DArguments args
= {
8826 target
, level
, internal_format
, width
, height
, border
, format
, type
,
8827 pixels
, pixels_size
};
8828 texture_manager()->ValidateAndDoTexImage2D(
8829 &texture_state_
, &state_
, &framebuffer_state_
, args
);
8831 // This may be a slow command. Exit command processing to allow for
8832 // context preemption and GPU watchdog checks.
8833 ExitCommandProcessingEarly();
8834 return error::kNoError
;
8837 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
8838 const void* cmd_data
) {
8839 // TODO(zmo): Unsafe ES3 API.
8840 if (!unsafe_es3_apis_enabled())
8841 return error::kUnknownCommand
;
8843 const gles2::cmds::TexImage3D
& c
=
8844 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
8845 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
8846 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
8847 GLenum target
= static_cast<GLenum
>(c
.target
);
8848 GLint level
= static_cast<GLint
>(c
.level
);
8849 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8850 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8851 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8852 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
8853 GLint border
= static_cast<GLint
>(c
.border
);
8854 GLenum format
= static_cast<GLenum
>(c
.format
);
8855 GLenum type
= static_cast<GLenum
>(c
.type
);
8856 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
8857 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
8859 if (!GLES2Util::ComputeImageDataSizes(
8860 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
8862 return error::kOutOfBounds
;
8864 const void* pixels
= NULL
;
8865 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
8866 pixels
= GetSharedMemoryAs
<const void*>(
8867 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
8869 return error::kOutOfBounds
;
8873 glTexImage3D(target
, level
, internal_format
, width
, height
, depth
, border
,
8874 format
, type
, pixels
);
8876 // This may be a slow command. Exit command processing to allow for
8877 // context preemption and GPU watchdog checks.
8878 ExitCommandProcessingEarly();
8879 return error::kNoError
;
8882 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8891 const void * data
) {
8892 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8896 GL_INVALID_OPERATION
,
8897 "glCompressedTexSubImage2D", "unknown texture for target");
8900 Texture
* texture
= texture_ref
->texture();
8902 GLenum internal_format
= 0;
8903 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
8905 GL_INVALID_OPERATION
,
8906 "glCompressedTexSubImage2D", "level does not exist.");
8909 if (internal_format
!= format
) {
8911 GL_INVALID_OPERATION
,
8912 "glCompressedTexSubImage2D", "format does not match internal format.");
8915 if (!texture
->ValidForTexture(
8916 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
8918 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
8922 if (!ValidateCompressedTexFuncData(
8923 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
8924 !ValidateCompressedTexSubDimensions(
8925 "glCompressedTexSubImage2D",
8926 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
8931 // Note: There is no need to deal with texture cleared tracking here
8932 // because the validation above means you can only get here if the level
8933 // is already a matching compressed format and in that case
8934 // CompressedTexImage2D already cleared the texture.
8935 glCompressedTexSubImage2D(
8936 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
8938 // This may be a slow command. Exit command processing to allow for
8939 // context preemption and GPU watchdog checks.
8940 ExitCommandProcessingEarly();
8944 GLint start
, GLint range
, GLint sourceRange
,
8945 GLint
* out_start
, GLint
* out_range
) {
8952 GLint end
= start
+ range
;
8953 if (end
> sourceRange
) {
8954 range
-= end
- sourceRange
;
8960 void GLES2DecoderImpl::DoCopyTexImage2D(
8963 GLenum internal_format
,
8969 DCHECK(!ShouldDeferReads());
8970 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8974 GL_INVALID_OPERATION
,
8975 "glCopyTexImage2D", "unknown texture for target");
8978 Texture
* texture
= texture_ref
->texture();
8979 if (texture
->IsImmutable()) {
8981 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
8984 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8987 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
8990 if (!texture_manager()->ValidateFormatAndTypeCombination(
8991 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
8992 GL_UNSIGNED_BYTE
)) {
8996 // Check we have compatible formats.
8997 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8998 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8999 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9001 if ((channels_needed
& channels_exist
) != channels_needed
) {
9003 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9007 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9009 GL_INVALID_OPERATION
,
9010 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9014 uint32 estimated_size
= 0;
9015 if (!GLES2Util::ComputeImageDataSizes(
9016 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9017 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9019 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9023 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9024 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9028 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9032 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9034 GL_INVALID_OPERATION
,
9035 "glCopyTexImage2D", "source and destination textures are the same");
9039 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9043 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9044 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9045 gfx::Size size
= GetBoundReadFrameBufferSize();
9047 if (texture
->IsAttachedToFramebuffer()) {
9048 framebuffer_state_
.clear_state_dirty
= true;
9051 // Clip to size to source dimensions
9054 GLint copyWidth
= 0;
9055 GLint copyHeight
= 0;
9056 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9057 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9061 copyWidth
!= width
||
9062 copyHeight
!= height
) {
9063 // some part was clipped so clear the texture.
9065 texture
->service_id(), texture
->target(),
9066 target
, level
, internal_format
, internal_format
, GL_UNSIGNED_BYTE
,
9067 width
, height
, texture
->IsImmutable())) {
9069 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9072 if (copyHeight
> 0 && copyWidth
> 0) {
9073 GLint dx
= copyX
- x
;
9074 GLint dy
= copyY
- y
;
9077 ScopedModifyPixels
modify(texture_ref
);
9078 glCopyTexSubImage2D(target
, level
,
9079 destX
, destY
, copyX
, copyY
,
9080 copyWidth
, copyHeight
);
9083 ScopedModifyPixels
modify(texture_ref
);
9084 glCopyTexImage2D(target
, level
, internal_format
,
9085 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9087 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9088 if (error
== GL_NO_ERROR
) {
9089 texture_manager()->SetLevelInfo(
9090 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
9091 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
9094 // This may be a slow command. Exit command processing to allow for
9095 // context preemption and GPU watchdog checks.
9096 ExitCommandProcessingEarly();
9099 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9108 DCHECK(!ShouldDeferReads());
9109 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9113 GL_INVALID_OPERATION
,
9114 "glCopyTexSubImage2D", "unknown texture for target");
9117 Texture
* texture
= texture_ref
->texture();
9120 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
9121 !texture
->ValidForTexture(
9122 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9124 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
9127 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9129 GL_INVALID_OPERATION
,
9130 "glCopyTexSubImage2D", "async upload pending for texture");
9134 // Check we have compatible formats.
9135 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9136 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9137 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
9139 if (!channels_needed
||
9140 (channels_needed
& channels_exist
) != channels_needed
) {
9142 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
9146 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9148 GL_INVALID_OPERATION
,
9149 "glCopySubImage2D", "can not be used with depth or stencil textures");
9153 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9157 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9159 GL_INVALID_OPERATION
,
9160 "glCopyTexSubImage2D", "source and destination textures are the same");
9164 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9168 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9169 gfx::Size size
= GetBoundReadFrameBufferSize();
9172 GLint copyWidth
= 0;
9173 GLint copyHeight
= 0;
9174 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9175 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9177 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
9178 height
!= size
.height()) {
9179 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
9181 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
9182 "dimensions too big");
9186 // Write all pixels in below.
9187 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9192 copyWidth
!= width
||
9193 copyHeight
!= height
) {
9194 // some part was clipped so clear the sub rect.
9195 uint32 pixels_size
= 0;
9196 if (!GLES2Util::ComputeImageDataSizes(
9197 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9200 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
9203 scoped_ptr
<char[]> zero(new char[pixels_size
]);
9204 memset(zero
.get(), 0, pixels_size
);
9205 ScopedModifyPixels
modify(texture_ref
);
9207 target
, level
, xoffset
, yoffset
, width
, height
,
9208 format
, type
, zero
.get());
9211 if (copyHeight
> 0 && copyWidth
> 0) {
9212 GLint dx
= copyX
- x
;
9213 GLint dy
= copyY
- y
;
9214 GLint destX
= xoffset
+ dx
;
9215 GLint destY
= yoffset
+ dy
;
9216 ScopedModifyPixels
modify(texture_ref
);
9217 glCopyTexSubImage2D(target
, level
,
9218 destX
, destY
, copyX
, copyY
,
9219 copyWidth
, copyHeight
);
9222 // This may be a slow command. Exit command processing to allow for
9223 // context preemption and GPU watchdog checks.
9224 ExitCommandProcessingEarly();
9227 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9228 error::Error
* error
,
9229 const char* function_name
,
9238 const void * data
) {
9239 (*error
) = error::kNoError
;
9240 if (!validators_
->texture_target
.IsValid(target
)) {
9241 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
9245 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
9249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
9252 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9256 GL_INVALID_OPERATION
,
9257 function_name
, "unknown texture for target");
9260 Texture
* texture
= texture_ref
->texture();
9261 GLenum current_type
= 0;
9262 GLenum internal_format
= 0;
9263 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
9265 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
9268 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
9269 function_name
, format
, type
, internal_format
, level
)) {
9272 if (type
!= current_type
) {
9274 GL_INVALID_OPERATION
,
9275 function_name
, "type does not match type of texture.");
9278 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9280 GL_INVALID_OPERATION
,
9281 function_name
, "async upload pending for texture");
9284 if (!texture
->ValidForTexture(
9285 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
9289 if ((GLES2Util::GetChannelsForFormat(format
) &
9290 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9292 GL_INVALID_OPERATION
,
9293 function_name
, "can not supply data for depth or stencil textures");
9297 (*error
) = error::kOutOfBounds
;
9303 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
9312 const void * data
) {
9313 error::Error error
= error::kNoError
;
9314 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
9315 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
9318 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9320 Texture
* texture
= texture_ref
->texture();
9321 GLsizei tex_width
= 0;
9322 GLsizei tex_height
= 0;
9323 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
9325 if (xoffset
!= 0 || yoffset
!= 0 ||
9326 width
!= tex_width
|| height
!= tex_height
) {
9327 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
9330 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
9331 return error::kNoError
;
9333 ScopedTextureUploadTimer
timer(&texture_state_
);
9335 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9336 return error::kNoError
;
9339 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
9340 !texture
->IsImmutable()) {
9341 ScopedTextureUploadTimer
timer(&texture_state_
);
9342 GLenum internal_format
;
9344 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
9345 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9348 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
9350 ScopedTextureUploadTimer
timer(&texture_state_
);
9352 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9354 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9356 // This may be a slow command. Exit command processing to allow for
9357 // context preemption and GPU watchdog checks.
9358 ExitCommandProcessingEarly();
9359 return error::kNoError
;
9362 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
9363 const void* cmd_data
) {
9364 const gles2::cmds::TexSubImage2D
& c
=
9365 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
9366 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9367 "width", c
.width
, "height", c
.height
);
9368 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
9369 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
9370 return error::kNoError
;
9372 GLenum target
= static_cast<GLenum
>(c
.target
);
9373 GLint level
= static_cast<GLint
>(c
.level
);
9374 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9375 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9376 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9377 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9378 GLenum format
= static_cast<GLenum
>(c
.format
);
9379 GLenum type
= static_cast<GLenum
>(c
.type
);
9381 if (!GLES2Util::ComputeImageDataSizes(
9382 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
9384 return error::kOutOfBounds
;
9386 const void* pixels
= GetSharedMemoryAs
<const void*>(
9387 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9388 return DoTexSubImage2D(
9389 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
9392 // TODO(zmo): Remove the below stub once we add the real function binding.
9393 // Currently it's missing due to a gmock limitation.
9394 static void glTexSubImage3D(
9395 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9396 GLsizei height
, GLsizei width
, GLsizei depth
, GLenum format
, GLenum type
,
9397 const void* pixels
) {
9401 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
9402 const void* cmd_data
) {
9403 // TODO(zmo): Unsafe ES3 API.
9404 if (!unsafe_es3_apis_enabled())
9405 return error::kUnknownCommand
;
9407 const gles2::cmds::TexSubImage3D
& c
=
9408 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
9409 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9410 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9411 GLenum target
= static_cast<GLenum
>(c
.target
);
9412 GLint level
= static_cast<GLint
>(c
.level
);
9413 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9414 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9415 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9416 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9417 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9418 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9419 GLenum format
= static_cast<GLenum
>(c
.format
);
9420 GLenum type
= static_cast<GLenum
>(c
.type
);
9422 if (!GLES2Util::ComputeImageDataSizes(
9423 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
9425 return error::kOutOfBounds
;
9427 const void* pixels
= GetSharedMemoryAs
<const void*>(
9428 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9429 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
9430 depth
, format
, type
, pixels
);
9431 return error::kNoError
;
9434 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9435 uint32 immediate_data_size
,
9436 const void* cmd_data
) {
9437 const gles2::cmds::GetVertexAttribPointerv
& c
=
9438 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
9439 GLuint index
= static_cast<GLuint
>(c
.index
);
9440 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9441 typedef cmds::GetVertexAttribPointerv::Result Result
;
9442 Result
* result
= GetSharedMemoryAs
<Result
*>(
9443 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
9445 return error::kOutOfBounds
;
9447 // Check that the client initialized the result.
9448 if (result
->size
!= 0) {
9449 return error::kInvalidArguments
;
9451 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
9452 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9453 "glGetVertexAttribPointerv", pname
, "pname");
9454 return error::kNoError
;
9456 if (index
>= group_
->max_vertex_attribs()) {
9458 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
9459 return error::kNoError
;
9461 result
->SetNumResults(1);
9462 *result
->GetData() =
9463 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
9464 return error::kNoError
;
9467 bool GLES2DecoderImpl::GetUniformSetup(
9468 GLuint program_id
, GLint fake_location
,
9469 uint32 shm_id
, uint32 shm_offset
,
9470 error::Error
* error
, GLint
* real_location
,
9471 GLuint
* service_id
, void** result_pointer
, GLenum
* result_type
) {
9474 DCHECK(result_pointer
);
9475 DCHECK(result_type
);
9476 DCHECK(real_location
);
9477 *error
= error::kNoError
;
9478 // Make sure we have enough room for the result on failure.
9479 SizedResult
<GLint
>* result
;
9480 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9481 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
9483 *error
= error::kOutOfBounds
;
9486 *result_pointer
= result
;
9487 // Set the result size to 0 so the client does not have to check for success.
9488 result
->SetNumResults(0);
9489 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
9493 if (!program
->IsValid()) {
9494 // Program was not linked successfully. (ie, glLinkProgram)
9496 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
9499 *service_id
= program
->service_id();
9500 GLint array_index
= -1;
9501 const Program::UniformInfo
* uniform_info
=
9502 program
->GetUniformInfoByFakeLocation(
9503 fake_location
, real_location
, &array_index
);
9504 if (!uniform_info
) {
9505 // No such location.
9507 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
9510 GLenum type
= uniform_info
->type
;
9511 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
9513 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
9516 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9517 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
9519 *error
= error::kOutOfBounds
;
9522 result
->size
= size
;
9523 *result_type
= type
;
9527 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
9528 const void* cmd_data
) {
9529 const gles2::cmds::GetUniformiv
& c
=
9530 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
9531 GLuint program
= c
.program
;
9532 GLint fake_location
= c
.location
;
9535 GLint real_location
= -1;
9538 if (GetUniformSetup(
9539 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9540 &error
, &real_location
, &service_id
, &result
, &result_type
)) {
9542 service_id
, real_location
,
9543 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
9548 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
9549 const void* cmd_data
) {
9550 const gles2::cmds::GetUniformfv
& c
=
9551 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
9552 GLuint program
= c
.program
;
9553 GLint fake_location
= c
.location
;
9555 GLint real_location
= -1;
9557 typedef cmds::GetUniformfv::Result Result
;
9560 if (GetUniformSetup(
9561 program
, fake_location
, c
.params_shm_id
, c
.params_shm_offset
,
9562 &error
, &real_location
, &service_id
,
9563 reinterpret_cast<void**>(&result
), &result_type
)) {
9564 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
9565 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
9566 GLsizei num_values
= result
->GetNumResults();
9567 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
9568 glGetUniformiv(service_id
, real_location
, temp
.get());
9569 GLfloat
* dst
= result
->GetData();
9570 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
9571 dst
[ii
] = (temp
[ii
] != 0);
9574 glGetUniformfv(service_id
, real_location
, result
->GetData());
9580 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9581 uint32 immediate_data_size
,
9582 const void* cmd_data
) {
9583 const gles2::cmds::GetShaderPrecisionFormat
& c
=
9584 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
9585 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
9586 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
9587 typedef cmds::GetShaderPrecisionFormat::Result Result
;
9588 Result
* result
= GetSharedMemoryAs
<Result
*>(
9589 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9591 return error::kOutOfBounds
;
9593 // Check that the client initialized the result.
9594 if (result
->success
!= 0) {
9595 return error::kInvalidArguments
;
9597 if (!validators_
->shader_type
.IsValid(shader_type
)) {
9598 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9599 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
9600 return error::kNoError
;
9602 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
9603 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9604 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
9605 return error::kNoError
;
9608 result
->success
= 1; // true
9610 GLint range
[2] = { 0, 0 };
9611 GLint precision
= 0;
9612 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
9614 result
->min_range
= range
[0];
9615 result
->max_range
= range
[1];
9616 result
->precision
= precision
;
9618 return error::kNoError
;
9621 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
9622 uint32 immediate_data_size
,
9623 const void* cmd_data
) {
9624 const gles2::cmds::GetAttachedShaders
& c
=
9625 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
9626 uint32 result_size
= c
.result_size
;
9627 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9628 Program
* program
= GetProgramInfoNotShader(
9629 program_id
, "glGetAttachedShaders");
9631 return error::kNoError
;
9633 typedef cmds::GetAttachedShaders::Result Result
;
9634 uint32 max_count
= Result::ComputeMaxResults(result_size
);
9635 Result
* result
= GetSharedMemoryAs
<Result
*>(
9636 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
9638 return error::kOutOfBounds
;
9640 // Check that the client initialized the result.
9641 if (result
->size
!= 0) {
9642 return error::kInvalidArguments
;
9645 glGetAttachedShaders(
9646 program
->service_id(), max_count
, &count
, result
->GetData());
9647 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
9648 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
9649 &result
->GetData()[ii
])) {
9651 return error::kGenericError
;
9654 result
->SetNumResults(count
);
9655 return error::kNoError
;
9658 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
9659 uint32 immediate_data_size
,
9660 const void* cmd_data
) {
9661 const gles2::cmds::GetActiveUniform
& c
=
9662 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
9663 GLuint program_id
= c
.program
;
9664 GLuint index
= c
.index
;
9665 uint32 name_bucket_id
= c
.name_bucket_id
;
9666 typedef cmds::GetActiveUniform::Result Result
;
9667 Result
* result
= GetSharedMemoryAs
<Result
*>(
9668 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9670 return error::kOutOfBounds
;
9672 // Check that the client initialized the result.
9673 if (result
->success
!= 0) {
9674 return error::kInvalidArguments
;
9676 Program
* program
= GetProgramInfoNotShader(
9677 program_id
, "glGetActiveUniform");
9679 return error::kNoError
;
9681 const Program::UniformInfo
* uniform_info
=
9682 program
->GetUniformInfo(index
);
9683 if (!uniform_info
) {
9685 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
9686 return error::kNoError
;
9688 result
->success
= 1; // true.
9689 result
->size
= uniform_info
->size
;
9690 result
->type
= uniform_info
->type
;
9691 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9692 bucket
->SetFromString(uniform_info
->name
.c_str());
9693 return error::kNoError
;
9696 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
9697 const void* cmd_data
) {
9698 const gles2::cmds::GetActiveAttrib
& c
=
9699 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
9700 GLuint program_id
= c
.program
;
9701 GLuint index
= c
.index
;
9702 uint32 name_bucket_id
= c
.name_bucket_id
;
9703 typedef cmds::GetActiveAttrib::Result Result
;
9704 Result
* result
= GetSharedMemoryAs
<Result
*>(
9705 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9707 return error::kOutOfBounds
;
9709 // Check that the client initialized the result.
9710 if (result
->success
!= 0) {
9711 return error::kInvalidArguments
;
9713 Program
* program
= GetProgramInfoNotShader(
9714 program_id
, "glGetActiveAttrib");
9716 return error::kNoError
;
9718 const Program::VertexAttrib
* attrib_info
=
9719 program
->GetAttribInfo(index
);
9722 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
9723 return error::kNoError
;
9725 result
->success
= 1; // true.
9726 result
->size
= attrib_info
->size
;
9727 result
->type
= attrib_info
->type
;
9728 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9729 bucket
->SetFromString(attrib_info
->name
.c_str());
9730 return error::kNoError
;
9733 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
9734 const void* cmd_data
) {
9735 #if 1 // No binary shader support.
9736 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
9737 return error::kNoError
;
9739 GLsizei n
= static_cast<GLsizei
>(c
.n
);
9741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
9742 return error::kNoError
;
9744 GLsizei length
= static_cast<GLsizei
>(c
.length
);
9746 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
9747 return error::kNoError
;
9750 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
9751 return error::kOutOfBounds
;
9753 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
9754 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
9755 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
9756 const void* binary
= GetSharedMemoryAs
<const void*>(
9757 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
9758 if (shaders
== NULL
|| binary
== NULL
) {
9759 return error::kOutOfBounds
;
9761 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
9762 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
9763 Shader
* shader
= GetShader(shaders
[ii
]);
9765 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
9766 return error::kNoError
;
9768 service_ids
[ii
] = shader
->service_id();
9770 // TODO(gman): call glShaderBinary
9771 return error::kNoError
;
9775 void GLES2DecoderImpl::DoSwapBuffers() {
9776 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9778 int this_frame_number
= frame_number_
++;
9779 // TRACE_EVENT for gpu tests:
9780 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9781 TRACE_EVENT_SCOPE_THREAD
,
9782 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9783 "width", (is_offscreen
? offscreen_size_
.width() :
9784 surface_
->GetSize().width()));
9785 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9786 "offscreen", is_offscreen
,
9787 "frame", this_frame_number
);
9789 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9792 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
9793 "gpu_toplevel", "SwapBuffer");
9796 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9799 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9800 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9801 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9804 // If offscreen then don't actually SwapBuffers to the display. Just copy
9805 // the rendered frame to another frame buffer.
9807 TRACE_EVENT2("gpu", "Offscreen",
9808 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
9809 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
9810 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9811 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9813 if (workarounds().needs_offscreen_buffer_workaround
) {
9814 offscreen_saved_frame_buffer_
->Create();
9818 // Allocate the offscreen saved color texture.
9819 DCHECK(offscreen_saved_color_format_
);
9820 offscreen_saved_color_texture_
->AllocateStorage(
9821 offscreen_size_
, offscreen_saved_color_format_
, false);
9823 offscreen_saved_frame_buffer_
->AttachRenderTexture(
9824 offscreen_saved_color_texture_
.get());
9825 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
9826 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
9827 GL_FRAMEBUFFER_COMPLETE
) {
9828 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9829 << "because offscreen saved FBO was incomplete.";
9830 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9834 // Clear the offscreen color texture.
9835 // TODO(piman): Is this still necessary?
9837 ScopedFrameBufferBinder
binder(this,
9838 offscreen_saved_frame_buffer_
->id());
9839 glClearColor(0, 0, 0, 0);
9840 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
9841 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
9842 glClear(GL_COLOR_BUFFER_BIT
);
9843 RestoreClearState();
9847 UpdateParentTextureInfo();
9850 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
9852 ScopedGLErrorSuppressor
suppressor(
9853 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9855 if (IsOffscreenBufferMultisampled()) {
9856 // For multisampled buffers, resolve the frame buffer.
9857 ScopedResolvedFrameBufferBinder
binder(this, true, false);
9859 ScopedFrameBufferBinder
binder(this,
9860 offscreen_target_frame_buffer_
->id());
9862 if (offscreen_target_buffer_preserved_
) {
9863 // Copy the target frame buffer to the saved offscreen texture.
9864 offscreen_saved_color_texture_
->Copy(
9865 offscreen_saved_color_texture_
->size(),
9866 offscreen_saved_color_format_
);
9868 // Flip the textures in the parent context via the texture manager.
9869 if (!!offscreen_saved_color_texture_info_
.get())
9870 offscreen_saved_color_texture_info_
->texture()->
9871 SetServiceId(offscreen_target_color_texture_
->id());
9873 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
9874 offscreen_target_frame_buffer_
->AttachRenderTexture(
9875 offscreen_target_color_texture_
.get());
9878 // Ensure the side effects of the copy are visible to the parent
9879 // context. There is no need to do this for ANGLE because it uses a
9880 // single D3D device for all contexts.
9881 if (!feature_info_
->gl_version_info().is_angle
)
9885 if (!surface_
->SwapBuffers()) {
9886 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
9887 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
9891 // This may be a slow command. Exit command processing to allow for
9892 // context preemption and GPU watchdog checks.
9893 ExitCommandProcessingEarly();
9896 void GLES2DecoderImpl::DoSwapInterval(int interval
)
9898 context_
->SetSwapInterval(interval
);
9901 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9902 uint32 immediate_data_size
,
9903 const void* cmd_data
) {
9904 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
9905 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
9906 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9907 if (!bucket
|| bucket
->size() == 0) {
9908 return error::kInvalidArguments
;
9910 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
9911 Result
* result
= GetSharedMemoryAs
<Result
*>(
9912 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9914 return error::kOutOfBounds
;
9916 // Check that the client initialized the result.
9918 return error::kInvalidArguments
;
9920 std::string feature_str
;
9921 if (!bucket
->GetAsString(&feature_str
)) {
9922 return error::kInvalidArguments
;
9925 // TODO(gman): make this some kind of table to function pointer thingy.
9926 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9927 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9928 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
9929 buffer_manager()->set_allow_fixed_attribs(true);
9930 // TODO(gman): decide how to remove the need for this const_cast.
9931 // I could make validators_ non const but that seems bad as this is the only
9932 // place it is needed. I could make some special friend class of validators
9933 // just to allow this to set them. That seems silly. I could refactor this
9934 // code to use the extension mechanism or the initialization attributes to
9935 // turn this feature on. Given that the only real point of this is to make
9936 // the conformance tests pass and given that there is lots of real work that
9937 // needs to be done it seems like refactoring for one to one of those
9938 // methods is a very low priority.
9939 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
9940 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
9941 force_webgl_glsl_validation_
= true;
9942 InitializeShaderTranslator();
9944 return error::kNoError
;
9947 *result
= 1; // true.
9948 return error::kNoError
;
9951 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9952 uint32 immediate_data_size
,
9953 const void* cmd_data
) {
9954 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
9955 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
9957 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9958 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
9959 info
->Initialize(disallowed_features_
);
9960 bucket
->SetFromString(info
->extensions().c_str());
9961 return error::kNoError
;
9964 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9965 uint32 immediate_data_size
,
9966 const void* cmd_data
) {
9967 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
9968 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
9969 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9970 if (!bucket
|| bucket
->size() == 0) {
9971 return error::kInvalidArguments
;
9973 std::string feature_str
;
9974 if (!bucket
->GetAsString(&feature_str
)) {
9975 return error::kInvalidArguments
;
9978 bool desire_webgl_glsl_validation
=
9979 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
9980 bool desire_standard_derivatives
= false;
9981 bool desire_frag_depth
= false;
9982 bool desire_draw_buffers
= false;
9983 bool desire_shader_texture_lod
= false;
9984 if (force_webgl_glsl_validation_
) {
9985 desire_standard_derivatives
=
9986 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
9988 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
9989 desire_draw_buffers
=
9990 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
9991 desire_shader_texture_lod
=
9992 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
9995 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
9996 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
9997 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
9998 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
9999 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
10000 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
10001 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
10002 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
10003 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
10004 InitializeShaderTranslator();
10007 UpdateCapabilities();
10009 return error::kNoError
;
10012 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10013 uint32 immediate_data_size
,
10014 const void* cmd_data
) {
10015 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
10016 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
10017 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10018 uint32 bucket_id
= c
.bucket_id
;
10019 Bucket
* bucket
= CreateBucket(bucket_id
);
10020 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
10021 Program
* program
= NULL
;
10022 program
= GetProgram(program_id
);
10023 if (!program
|| !program
->IsValid()) {
10024 return error::kNoError
;
10026 program
->GetProgramInfo(program_manager(), bucket
);
10027 return error::kNoError
;
10030 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
10031 switch (reset_status_
) {
10033 // TODO(kbr): improve the precision of the error code in this case.
10034 // Consider delegating to context for error code if MakeCurrent fails.
10035 return error::kUnknown
;
10036 case GL_GUILTY_CONTEXT_RESET_ARB
:
10037 return error::kGuilty
;
10038 case GL_INNOCENT_CONTEXT_RESET_ARB
:
10039 return error::kInnocent
;
10040 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
10041 return error::kUnknown
;
10045 return error::kUnknown
;
10048 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10049 // Some D3D drivers cannot recover from device lost in the GPU process
10050 // sandbox. Allow a new GPU process to launch.
10051 if (workarounds().exit_on_context_lost
) {
10052 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
10053 << " a D3D device in the Chrome GPU process sandbox.";
10054 #if defined(OS_WIN)
10055 base::win::SetShouldCrashOnProcessDetach(false);
10061 bool GLES2DecoderImpl::WasContextLost() {
10062 if (reset_status_
!= GL_NO_ERROR
) {
10063 MaybeExitOnContextLost();
10066 if (context_
->WasAllocatedUsingRobustnessExtension()) {
10067 GLenum status
= GL_NO_ERROR
;
10068 if (has_robustness_extension_
)
10069 status
= glGetGraphicsResetStatusARB();
10070 if (status
!= GL_NO_ERROR
) {
10071 // The graphics card was reset. Signal a lost context to the application.
10072 reset_status_
= status
;
10073 reset_by_robustness_extension_
= true;
10074 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
10075 << " context lost via ARB/EXT_robustness. Reset status = "
10076 << GLES2Util::GetStringEnum(status
);
10077 MaybeExitOnContextLost();
10084 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10085 return WasContextLost() && reset_by_robustness_extension_
;
10088 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
10089 // Only loses the context once.
10090 if (reset_status_
!= GL_NO_ERROR
) {
10094 if (workarounds().use_virtualized_gl_contexts
) {
10095 // If the context is virtual, the real context being guilty does not ensure
10096 // that the virtual context is guilty.
10097 if (reset_status
== GL_GUILTY_CONTEXT_RESET_ARB
) {
10098 reset_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
10100 } else if (reset_status
== GL_UNKNOWN_CONTEXT_RESET_ARB
&&
10101 has_robustness_extension_
) {
10102 // If the reason for the call was a GL error, we can try to determine the
10103 // reset status more accurately.
10104 GLenum driver_status
= glGetGraphicsResetStatusARB();
10105 if (driver_status
== GL_GUILTY_CONTEXT_RESET_ARB
||
10106 driver_status
== GL_INNOCENT_CONTEXT_RESET_ARB
) {
10107 reset_status
= driver_status
;
10111 // Marks this context as lost.
10112 reset_status_
= reset_status
;
10113 current_decoder_error_
= error::kLostContext
;
10116 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10117 uint32 immediate_data_size
,
10118 const void* cmd_data
) {
10119 return error::kUnknownCommand
;
10122 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10123 uint32 immediate_data_size
,
10124 const void* cmd_data
) {
10125 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
10126 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
10127 uint32 sync_point
= c
.sync_point
;
10128 if (wait_sync_point_callback_
.is_null())
10129 return error::kNoError
;
10131 return wait_sync_point_callback_
.Run(sync_point
) ?
10132 error::kNoError
: error::kDeferCommandUntilLater
;
10135 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10136 uint32 immediate_data_size
,
10137 const void* cmd_data
) {
10138 if (surface_
->DeferDraws())
10139 return error::kDeferCommandUntilLater
;
10140 if (!surface_
->SetBackbufferAllocation(false))
10141 return error::kLostContext
;
10142 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
10143 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
10144 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
10145 return error::kNoError
;
10148 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10149 GLsizei n
, const GLuint
* client_ids
) {
10150 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10151 if (query_manager_
->GetQuery(client_ids
[ii
])) {
10155 query_manager_
->GenQueries(n
, client_ids
);
10159 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10160 GLsizei n
, const GLuint
* client_ids
) {
10161 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10162 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
10163 if (query
&& !query
->IsDeleted()) {
10164 ContextState::QueryMap::iterator it
=
10165 state_
.current_queries
.find(query
->target());
10166 if (it
!= state_
.current_queries
.end())
10167 state_
.current_queries
.erase(it
);
10169 query
->Destroy(true);
10171 query_manager_
->RemoveQuery(client_ids
[ii
]);
10175 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
10176 if (query_manager_
.get() == NULL
) {
10179 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
10180 current_decoder_error_
= error::kOutOfBounds
;
10182 return query_manager_
->HavePendingQueries();
10185 // Note that if there are no pending readpixels right now,
10186 // this function will call the callback immediately.
10187 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
10188 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
10189 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
10195 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10196 while (!pending_readpixel_fences_
.empty() &&
10197 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
10198 std::vector
<base::Closure
> callbacks
=
10199 pending_readpixel_fences_
.front()->callbacks
;
10200 pending_readpixel_fences_
.pop();
10201 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
10202 callbacks
[i
].Run();
10207 bool GLES2DecoderImpl::HasMoreIdleWork() {
10208 return !pending_readpixel_fences_
.empty() ||
10209 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
10212 void GLES2DecoderImpl::PerformIdleWork() {
10213 ProcessPendingReadPixels();
10214 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
10216 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
10217 ProcessFinishedAsyncTransfers();
10220 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
10221 const void* cmd_data
) {
10222 const gles2::cmds::BeginQueryEXT
& c
=
10223 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
10224 GLenum target
= static_cast<GLenum
>(c
.target
);
10225 GLuint client_id
= static_cast<GLuint
>(c
.id
);
10226 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
10227 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10230 case GL_COMMANDS_ISSUED_CHROMIUM
:
10231 case GL_LATENCY_QUERY_CHROMIUM
:
10232 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
10233 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
10234 case GL_GET_ERROR_QUERY_CHROMIUM
:
10236 case GL_COMMANDS_COMPLETED_CHROMIUM
:
10237 if (!features().chromium_sync_query
) {
10238 LOCAL_SET_GL_ERROR(
10239 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10240 "not enabled for commands completed queries");
10241 return error::kNoError
;
10245 if (!features().occlusion_query_boolean
) {
10246 LOCAL_SET_GL_ERROR(
10247 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10248 "not enabled for occlusion queries");
10249 return error::kNoError
;
10254 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
10255 LOCAL_SET_GL_ERROR(
10256 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
10257 return error::kNoError
;
10260 if (client_id
== 0) {
10261 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
10262 return error::kNoError
;
10265 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
10267 if (!query_manager_
->IsValidQuery(client_id
)) {
10268 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10270 "id not made by glGenQueriesEXT");
10271 return error::kNoError
;
10273 query
= query_manager_
->CreateQuery(
10274 target
, client_id
, sync_shm_id
, sync_shm_offset
);
10277 if (query
->target() != target
) {
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
10280 return error::kNoError
;
10281 } else if (query
->shm_id() != sync_shm_id
||
10282 query
->shm_offset() != sync_shm_offset
) {
10283 DLOG(ERROR
) << "Shared memory used by query not the same as before";
10284 return error::kInvalidArguments
;
10287 if (!query_manager_
->BeginQuery(query
)) {
10288 return error::kOutOfBounds
;
10291 state_
.current_queries
[target
] = query
;
10292 return error::kNoError
;
10295 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
10296 const void* cmd_data
) {
10297 const gles2::cmds::EndQueryEXT
& c
=
10298 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
10299 GLenum target
= static_cast<GLenum
>(c
.target
);
10300 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
10301 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
10303 if (it
== state_
.current_queries
.end()) {
10304 LOCAL_SET_GL_ERROR(
10305 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
10306 return error::kNoError
;
10309 QueryManager::Query
* query
= it
->second
.get();
10310 if (!query_manager_
->EndQuery(query
, submit_count
)) {
10311 return error::kOutOfBounds
;
10314 query_manager_
->ProcessPendingTransferQueries();
10316 state_
.current_queries
.erase(it
);
10317 return error::kNoError
;
10320 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10321 GLsizei n
, const GLuint
* client_ids
) {
10322 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10323 if (GetVertexAttribManager(client_ids
[ii
])) {
10328 if (!features().native_vertex_array_object
) {
10330 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10331 CreateVertexAttribManager(client_ids
[ii
], 0, true);
10334 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10336 glGenVertexArraysOES(n
, service_ids
.get());
10337 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10338 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
10345 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10346 GLsizei n
, const GLuint
* client_ids
) {
10347 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10348 VertexAttribManager
* vao
=
10349 GetVertexAttribManager(client_ids
[ii
]);
10350 if (vao
&& !vao
->IsDeleted()) {
10351 if (state_
.vertex_attrib_manager
.get() == vao
) {
10352 DoBindVertexArrayOES(0);
10354 RemoveVertexAttribManager(client_ids
[ii
]);
10359 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
10360 VertexAttribManager
* vao
= NULL
;
10361 if (client_id
!= 0) {
10362 vao
= GetVertexAttribManager(client_id
);
10364 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10365 // only allows names that have been previously generated. As such, we do
10366 // not generate new names here.
10367 LOCAL_SET_GL_ERROR(
10368 GL_INVALID_OPERATION
,
10369 "glBindVertexArrayOES", "bad vertex array id.");
10370 current_decoder_error_
= error::kNoError
;
10374 vao
= state_
.default_vertex_attrib_manager
.get();
10377 // Only set the VAO state if it's changed
10378 if (state_
.vertex_attrib_manager
.get() != vao
) {
10379 state_
.vertex_attrib_manager
= vao
;
10380 if (!features().native_vertex_array_object
) {
10381 EmulateVertexArrayState();
10383 GLuint service_id
= vao
->service_id();
10384 glBindVertexArrayOES(service_id
);
10389 // Used when OES_vertex_array_object isn't natively supported
10390 void GLES2DecoderImpl::EmulateVertexArrayState() {
10391 // Setup the Vertex attribute state
10392 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
10393 RestoreStateForAttrib(vv
, true);
10396 // Setup the element buffer
10397 Buffer
* element_array_buffer
=
10398 state_
.vertex_attrib_manager
->element_array_buffer();
10399 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
10400 element_array_buffer
? element_array_buffer
->service_id() : 0);
10403 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
10404 const VertexAttribManager
* vao
=
10405 GetVertexAttribManager(client_id
);
10406 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
10409 #if defined(OS_MACOSX)
10410 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
10411 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
10413 if (it
!= texture_to_io_surface_map_
.end()) {
10414 // Found a previous IOSurface bound to this texture; release it.
10415 IOSurfaceRef surface
= it
->second
;
10416 CFRelease(surface
);
10417 texture_to_io_surface_map_
.erase(it
);
10422 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10423 GLenum target
, GLsizei width
, GLsizei height
,
10424 GLuint io_surface_id
, GLuint plane
) {
10425 #if defined(OS_MACOSX)
10426 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
10427 LOCAL_SET_GL_ERROR(
10428 GL_INVALID_OPERATION
,
10429 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10433 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
10434 // This might be supported in the future, and if we could require
10435 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10436 // could delete a lot of code. For now, perform strict validation so we
10437 // know what's going on.
10438 LOCAL_SET_GL_ERROR(
10439 GL_INVALID_OPERATION
,
10440 "glTexImageIOSurface2DCHROMIUM",
10441 "requires TEXTURE_RECTANGLE_ARB target");
10445 // Default target might be conceptually valid, but disallow it to avoid
10447 TextureRef
* texture_ref
=
10448 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10449 if (!texture_ref
) {
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION
,
10452 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10456 // Look up the new IOSurface. Note that because of asynchrony
10457 // between processes this might fail; during live resizing the
10458 // plugin process might allocate and release an IOSurface before
10459 // this process gets a chance to look it up. Hold on to any old
10460 // IOSurface in this case.
10461 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
10463 LOCAL_SET_GL_ERROR(
10464 GL_INVALID_OPERATION
,
10465 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10469 // Release any IOSurface previously bound to this texture.
10470 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
10472 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10473 texture_to_io_surface_map_
.insert(
10474 std::make_pair(texture_ref
->service_id(), surface
));
10476 CGLContextObj context
=
10477 static_cast<CGLContextObj
>(context_
->GetHandle());
10479 CGLError err
= CGLTexImageIOSurface2D(
10486 GL_UNSIGNED_INT_8_8_8_8_REV
,
10490 if (err
!= kCGLNoError
) {
10491 LOCAL_SET_GL_ERROR(
10492 GL_INVALID_OPERATION
,
10493 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10497 texture_manager()->SetLevelInfo(
10498 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
10499 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
10502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10503 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10507 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
10508 switch (internalformat
) {
10519 case GL_LUMINANCE8_ALPHA8_EXT
:
10520 return GL_LUMINANCE_ALPHA
;
10521 case GL_LUMINANCE8_EXT
:
10522 return GL_LUMINANCE
;
10523 case GL_ALPHA8_EXT
:
10525 case GL_RGBA32F_EXT
:
10527 case GL_RGB32F_EXT
:
10529 case GL_ALPHA32F_EXT
:
10531 case GL_LUMINANCE32F_EXT
:
10532 return GL_LUMINANCE
;
10533 case GL_LUMINANCE_ALPHA32F_EXT
:
10534 return GL_LUMINANCE_ALPHA
;
10535 case GL_RGBA16F_EXT
:
10537 case GL_RGB16F_EXT
:
10539 case GL_ALPHA16F_EXT
:
10541 case GL_LUMINANCE16F_EXT
:
10542 return GL_LUMINANCE
;
10543 case GL_LUMINANCE_ALPHA16F_EXT
:
10544 return GL_LUMINANCE_ALPHA
;
10546 return GL_BGRA_EXT
;
10547 case GL_SRGB8_ALPHA8_EXT
:
10548 return GL_SRGB_ALPHA_EXT
;
10554 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10555 GLenum target
, GLuint source_id
, GLuint dest_id
, GLint level
,
10556 GLenum internal_format
, GLenum dest_type
) {
10557 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10559 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
10560 TextureRef
* source_texture_ref
= GetTexture(source_id
);
10562 if (!source_texture_ref
|| !dest_texture_ref
) {
10563 LOCAL_SET_GL_ERROR(
10564 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "unknown texture id");
10568 if (GL_TEXTURE_2D
!= target
) {
10569 LOCAL_SET_GL_ERROR(
10570 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "invalid texture target");
10574 Texture
* source_texture
= source_texture_ref
->texture();
10575 Texture
* dest_texture
= dest_texture_ref
->texture();
10576 if (dest_texture
->target() != GL_TEXTURE_2D
||
10577 (source_texture
->target() != GL_TEXTURE_2D
&&
10578 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
10579 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
10580 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10581 "glCopyTextureCHROMIUM",
10582 "invalid texture target binding");
10586 int source_width
, source_height
, dest_width
, dest_height
;
10588 gfx::GLImage
* image
=
10589 source_texture
->GetLevelImage(source_texture
->target(), 0);
10591 gfx::Size size
= image
->GetSize();
10592 source_width
= size
.width();
10593 source_height
= size
.height();
10594 if (source_width
<= 0 || source_height
<= 0) {
10595 LOCAL_SET_GL_ERROR(
10597 "glCopyTextureChromium", "invalid image size");
10601 if (!source_texture
->GetLevelSize(
10602 source_texture
->target(), 0, &source_width
, &source_height
)) {
10603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
10604 "glCopyTextureChromium",
10605 "source texture has no level 0");
10609 // Check that this type of texture is allowed.
10610 if (!texture_manager()->ValidForTarget(
10611 source_texture
->target(), level
, source_width
, source_height
, 1)) {
10612 LOCAL_SET_GL_ERROR(
10613 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
10618 // Clear the source texture if necessary.
10619 if (!texture_manager()->ClearTextureLevel(
10620 this, source_texture_ref
, source_texture
->target(), 0)) {
10621 LOCAL_SET_GL_ERROR(
10622 GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM", "dimensions too big");
10626 GLenum source_type
= 0;
10627 GLenum source_internal_format
= 0;
10628 source_texture
->GetLevelType(
10629 source_texture
->target(), 0, &source_type
, &source_internal_format
);
10631 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10632 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10633 // renderable on some platforms.
10634 bool valid_dest_format
= internal_format
== GL_RGB
||
10635 internal_format
== GL_RGBA
||
10636 internal_format
== GL_BGRA_EXT
;
10637 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
10638 source_internal_format
== GL_RGB
||
10639 source_internal_format
== GL_RGBA
||
10640 source_internal_format
== GL_LUMINANCE
||
10641 source_internal_format
== GL_LUMINANCE_ALPHA
||
10642 source_internal_format
== GL_BGRA_EXT
;
10643 if (!valid_source_format
|| !valid_dest_format
) {
10644 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10645 "glCopyTextureCHROMIUM",
10646 "invalid internal format");
10650 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10651 // needed because it takes 10s of milliseconds to initialize.
10652 if (!copy_texture_CHROMIUM_
.get()) {
10653 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10654 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
10655 copy_texture_CHROMIUM_
->Initialize(this);
10656 RestoreCurrentFramebufferBindings();
10657 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
10661 GLenum dest_type_previous
= dest_type
;
10662 GLenum dest_internal_format
= internal_format
;
10663 bool dest_level_defined
= dest_texture
->GetLevelSize(
10664 GL_TEXTURE_2D
, level
, &dest_width
, &dest_height
);
10666 if (dest_level_defined
) {
10667 dest_texture
->GetLevelType(GL_TEXTURE_2D
, level
, &dest_type_previous
,
10668 &dest_internal_format
);
10671 // Resize the destination texture to the dimensions of the source texture.
10672 if (!dest_level_defined
|| dest_width
!= source_width
||
10673 dest_height
!= source_height
||
10674 dest_internal_format
!= internal_format
||
10675 dest_type_previous
!= dest_type
) {
10676 // Ensure that the glTexImage2D succeeds.
10677 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10678 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
10680 GL_TEXTURE_2D
, level
, internal_format
, source_width
, source_height
,
10681 0, internal_format
, dest_type
, NULL
);
10682 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10683 if (error
!= GL_NO_ERROR
) {
10684 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
10688 texture_manager()->SetLevelInfo(
10689 dest_texture_ref
, GL_TEXTURE_2D
, level
, internal_format
, source_width
,
10690 source_height
, 1, 0, internal_format
, dest_type
, true);
10692 texture_manager()->SetLevelCleared(
10693 dest_texture_ref
, GL_TEXTURE_2D
, level
, true);
10696 ScopedModifyPixels
modify(dest_texture_ref
);
10698 // Try using GLImage::CopyTexImage when possible.
10699 bool unpack_premultiply_alpha_change
=
10700 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
10701 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&& !level
) {
10702 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
10703 if (image
->CopyTexImage(GL_TEXTURE_2D
))
10707 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
10709 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10710 // before presenting.
10711 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
10712 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10713 // instead of using default matrix crbug.com/226218.
10714 const static GLfloat default_matrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
10715 0.0f
, 1.0f
, 0.0f
, 0.0f
,
10716 0.0f
, 0.0f
, 1.0f
, 0.0f
,
10717 0.0f
, 0.0f
, 0.0f
, 1.0f
};
10718 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
10720 source_texture
->target(),
10721 source_texture
->service_id(),
10722 dest_texture
->service_id(),
10727 unpack_premultiply_alpha_
,
10728 unpack_unpremultiply_alpha_
,
10731 copy_texture_CHROMIUM_
->DoCopyTexture(this,
10732 source_texture
->target(),
10733 source_texture
->service_id(),
10734 source_internal_format
,
10735 dest_texture
->service_id(),
10741 unpack_premultiply_alpha_
,
10742 unpack_unpremultiply_alpha_
);
10745 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
10748 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
10749 switch (internalformat
) {
10751 return GL_UNSIGNED_SHORT_5_6_5
;
10753 return GL_UNSIGNED_SHORT_4_4_4_4
;
10755 return GL_UNSIGNED_SHORT_5_5_5_1
;
10757 return GL_UNSIGNED_BYTE
;
10759 return GL_UNSIGNED_BYTE
;
10760 case GL_LUMINANCE8_ALPHA8_EXT
:
10761 return GL_UNSIGNED_BYTE
;
10762 case GL_LUMINANCE8_EXT
:
10763 return GL_UNSIGNED_BYTE
;
10764 case GL_ALPHA8_EXT
:
10765 return GL_UNSIGNED_BYTE
;
10766 case GL_RGBA32F_EXT
:
10768 case GL_RGB32F_EXT
:
10770 case GL_ALPHA32F_EXT
:
10772 case GL_LUMINANCE32F_EXT
:
10774 case GL_LUMINANCE_ALPHA32F_EXT
:
10776 case GL_RGBA16F_EXT
:
10777 return GL_HALF_FLOAT_OES
;
10778 case GL_RGB16F_EXT
:
10779 return GL_HALF_FLOAT_OES
;
10780 case GL_ALPHA16F_EXT
:
10781 return GL_HALF_FLOAT_OES
;
10782 case GL_LUMINANCE16F_EXT
:
10783 return GL_HALF_FLOAT_OES
;
10784 case GL_LUMINANCE_ALPHA16F_EXT
:
10785 return GL_HALF_FLOAT_OES
;
10787 return GL_UNSIGNED_BYTE
;
10793 void GLES2DecoderImpl::DoTexStorage2DEXT(
10796 GLenum internal_format
,
10799 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10800 "width", width
, "height", height
);
10801 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
10802 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
10803 LOCAL_SET_GL_ERROR(
10804 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
10807 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10809 if (!texture_ref
) {
10810 LOCAL_SET_GL_ERROR(
10811 GL_INVALID_OPERATION
,
10812 "glTexStorage2DEXT", "unknown texture for target");
10815 Texture
* texture
= texture_ref
->texture();
10816 if (texture
->IsAttachedToFramebuffer()) {
10817 framebuffer_state_
.clear_state_dirty
= true;
10819 if (texture
->IsImmutable()) {
10820 LOCAL_SET_GL_ERROR(
10821 GL_INVALID_OPERATION
,
10822 "glTexStorage2DEXT", "texture is immutable");
10826 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
10827 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
10830 GLsizei level_width
= width
;
10831 GLsizei level_height
= height
;
10832 uint32 estimated_size
= 0;
10833 for (int ii
= 0; ii
< levels
; ++ii
) {
10834 uint32 level_size
= 0;
10835 if (!GLES2Util::ComputeImageDataSizes(
10836 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
10837 &estimated_size
, NULL
, NULL
) ||
10838 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
10839 LOCAL_SET_GL_ERROR(
10840 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
10843 level_width
= std::max(1, level_width
>> 1);
10844 level_height
= std::max(1, level_height
>> 1);
10846 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10847 LOCAL_SET_GL_ERROR(
10848 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
10853 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10854 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
10855 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10856 if (error
== GL_NO_ERROR
) {
10857 GLsizei level_width
= width
;
10858 GLsizei level_height
= height
;
10859 for (int ii
= 0; ii
< levels
; ++ii
) {
10860 texture_manager()->SetLevelInfo(
10861 texture_ref
, target
, ii
, format
,
10862 level_width
, level_height
, 1, 0, format
, type
, false);
10863 level_width
= std::max(1, level_width
>> 1);
10864 level_height
= std::max(1, level_height
>> 1);
10866 texture
->SetImmutable(true);
10870 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10871 uint32 immediate_data_size
,
10872 const void* cmd_data
) {
10873 return error::kUnknownCommand
;
10876 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
10877 const GLbyte
* data
) {
10878 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10879 "context", logger_
.GetLogPrefix(),
10880 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10882 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10884 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
10887 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
10888 GLenum target
, const GLbyte
* data
) {
10889 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10890 "context", logger_
.GetLogPrefix(),
10891 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10893 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
10897 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
10898 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
10899 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10900 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
10901 "mailbox that was not generated by "
10902 "GenMailboxCHROMIUM.";
10904 if (!texture_ref
) {
10905 LOCAL_SET_GL_ERROR(
10906 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
10910 Texture
* produced
= texture_manager()->Produce(texture_ref
);
10912 LOCAL_SET_GL_ERROR(
10913 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
10917 if (produced
->target() != target
) {
10918 LOCAL_SET_GL_ERROR(
10919 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
10923 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
10926 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
10927 const GLbyte
* data
) {
10928 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10929 "context", logger_
.GetLogPrefix(),
10930 "mailbox[0]", static_cast<unsigned char>(data
[0]));
10931 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
10932 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10933 "mailbox that was not generated by "
10934 "GenMailboxCHROMIUM.";
10936 scoped_refptr
<TextureRef
> texture_ref
=
10937 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10938 if (!texture_ref
.get()) {
10939 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10940 "glConsumeTextureCHROMIUM",
10941 "unknown texture for target");
10944 GLuint client_id
= texture_ref
->client_id();
10946 LOCAL_SET_GL_ERROR(
10947 GL_INVALID_OPERATION
,
10948 "glConsumeTextureCHROMIUM", "unknown texture for target");
10951 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
10953 LOCAL_SET_GL_ERROR(
10954 GL_INVALID_OPERATION
,
10955 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10958 if (texture
->target() != target
) {
10959 LOCAL_SET_GL_ERROR(
10960 GL_INVALID_OPERATION
,
10961 "glConsumeTextureCHROMIUM", "invalid target");
10965 DeleteTexturesHelper(1, &client_id
);
10966 texture_ref
= texture_manager()->Consume(client_id
, texture
);
10967 glBindTexture(target
, texture_ref
->service_id());
10969 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
10970 unit
.bind_target
= target
;
10972 case GL_TEXTURE_2D
:
10973 unit
.bound_texture_2d
= texture_ref
;
10975 case GL_TEXTURE_CUBE_MAP
:
10976 unit
.bound_texture_cube_map
= texture_ref
;
10978 case GL_TEXTURE_EXTERNAL_OES
:
10979 unit
.bound_texture_external_oes
= texture_ref
;
10981 case GL_TEXTURE_RECTANGLE_ARB
:
10982 unit
.bound_texture_rectangle_arb
= texture_ref
;
10985 NOTREACHED(); // Validation should prevent us getting here.
10990 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10991 uint32_t immediate_data_size
,
10992 const void* cmd_data
) {
10993 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
10995 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
10997 GLenum target
= static_cast<GLenum
>(c
.target
);
10998 uint32_t data_size
;
10999 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
11000 return error::kOutOfBounds
;
11002 if (data_size
> immediate_data_size
) {
11003 return error::kOutOfBounds
;
11005 const GLbyte
* mailbox
=
11006 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
11007 if (!validators_
->texture_bind_target
.IsValid(target
)) {
11008 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11009 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
11010 return error::kNoError
;
11012 if (mailbox
== NULL
) {
11013 return error::kOutOfBounds
;
11015 uint32_t client_id
= c
.client_id
;
11016 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
11017 return error::kNoError
;
11020 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
11021 const GLbyte
* data
, GLuint client_id
) {
11022 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11023 "context", logger_
.GetLogPrefix(),
11024 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11025 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11026 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11027 "passed a mailbox that was not "
11028 "generated by GenMailboxCHROMIUM.";
11030 TextureRef
* texture_ref
= GetTexture(client_id
);
11032 LOCAL_SET_GL_ERROR(
11033 GL_INVALID_OPERATION
,
11034 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11037 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
11039 LOCAL_SET_GL_ERROR(
11040 GL_INVALID_OPERATION
,
11041 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11044 if (texture
->target() != target
) {
11045 LOCAL_SET_GL_ERROR(
11046 GL_INVALID_OPERATION
,
11047 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11051 texture_ref
= texture_manager()->Consume(client_id
, texture
);
11054 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
11055 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
11056 return valuebuffer
&& valuebuffer
->IsValid();
11059 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
11060 GLuint client_id
) {
11061 Valuebuffer
* valuebuffer
= NULL
;
11062 if (client_id
!= 0) {
11063 valuebuffer
= GetValuebuffer(client_id
);
11064 if (!valuebuffer
) {
11065 if (!group_
->bind_generates_resource()) {
11066 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
11067 "id not generated by glBindValuebufferCHROMIUM");
11071 // It's a new id so make a valuebuffer for it.
11072 CreateValuebuffer(client_id
);
11073 valuebuffer
= GetValuebuffer(client_id
);
11075 valuebuffer
->MarkAsValid();
11077 state_
.bound_valuebuffer
= valuebuffer
;
11080 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
11081 GLenum subscription
) {
11082 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11085 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
11088 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
11089 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11092 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
11095 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
11097 GLenum subscription
) {
11098 if (!CheckCurrentValuebufferForSubscription(
11099 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
11102 if (!CheckSubscriptionTarget(location
, subscription
,
11103 "glPopulateSubscribedValuesCHROMIUM")) {
11106 const ValueState
* state
=
11107 state_
.bound_valuebuffer
.get()->GetState(subscription
);
11109 switch (subscription
) {
11110 case GL_MOUSE_POSITION_CHROMIUM
:
11111 DoUniform2iv(location
, 1, state
->int_value
);
11114 NOTREACHED() << "Unhandled uniform subscription target "
11121 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11122 GLsizei length
, const GLchar
* marker
) {
11126 debug_marker_manager_
.SetMarker(
11127 length
? std::string(marker
, length
) : std::string(marker
));
11130 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11131 GLsizei length
, const GLchar
* marker
) {
11135 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
11136 debug_marker_manager_
.PushGroup(name
);
11137 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
11138 kTraceGroupMarker
);
11141 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11142 debug_marker_manager_
.PopGroup();
11143 gpu_tracer_
->End(kTraceGroupMarker
);
11146 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11147 GLenum target
, GLint image_id
) {
11148 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11150 if (target
== GL_TEXTURE_CUBE_MAP
) {
11151 LOCAL_SET_GL_ERROR(
11153 "glBindTexImage2DCHROMIUM", "invalid target");
11157 // Default target might be conceptually valid, but disallow it to avoid
11159 TextureRef
* texture_ref
=
11160 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11161 if (!texture_ref
) {
11162 LOCAL_SET_GL_ERROR(
11163 GL_INVALID_OPERATION
,
11164 "glBindTexImage2DCHROMIUM", "no texture bound");
11168 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11170 LOCAL_SET_GL_ERROR(
11171 GL_INVALID_OPERATION
,
11172 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11177 ScopedGLErrorSuppressor
suppressor(
11178 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11179 if (!gl_image
->BindTexImage(target
)) {
11180 LOCAL_SET_GL_ERROR(
11181 GL_INVALID_OPERATION
,
11182 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11187 gfx::Size size
= gl_image
->GetSize();
11188 texture_manager()->SetLevelInfo(
11189 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
11190 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
11191 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
11194 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11195 GLenum target
, GLint image_id
) {
11196 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11198 // Default target might be conceptually valid, but disallow it to avoid
11200 TextureRef
* texture_ref
=
11201 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11202 if (!texture_ref
) {
11203 LOCAL_SET_GL_ERROR(
11204 GL_INVALID_OPERATION
,
11205 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11209 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11211 LOCAL_SET_GL_ERROR(
11212 GL_INVALID_OPERATION
,
11213 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11217 // Do nothing when image is not currently bound.
11218 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
11222 ScopedGLErrorSuppressor
suppressor(
11223 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11224 gl_image
->ReleaseTexImage(target
);
11227 texture_manager()->SetLevelInfo(
11228 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
11229 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
11232 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11233 uint32 immediate_data_size
,
11234 const void* cmd_data
) {
11235 const gles2::cmds::TraceBeginCHROMIUM
& c
=
11236 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
11237 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
11238 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
11239 if (!category_bucket
|| category_bucket
->size() == 0 ||
11240 !name_bucket
|| name_bucket
->size() == 0) {
11241 return error::kInvalidArguments
;
11244 std::string category_name
;
11245 std::string trace_name
;
11246 if (!category_bucket
->GetAsString(&category_name
) ||
11247 !name_bucket
->GetAsString(&trace_name
)) {
11248 return error::kInvalidArguments
;
11251 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
11252 LOCAL_SET_GL_ERROR(
11253 GL_INVALID_OPERATION
,
11254 "glTraceBeginCHROMIUM", "unable to create begin trace");
11255 return error::kNoError
;
11257 return error::kNoError
;
11260 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11261 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
11262 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11263 "glTraceEndCHROMIUM", "no trace begin found");
11268 void GLES2DecoderImpl::DoDrawBuffersEXT(
11269 GLsizei count
, const GLenum
* bufs
) {
11270 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
11271 LOCAL_SET_GL_ERROR(
11273 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11277 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
11279 for (GLsizei i
= 0; i
< count
; ++i
) {
11280 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
11281 bufs
[i
] != GL_NONE
) {
11282 LOCAL_SET_GL_ERROR(
11283 GL_INVALID_OPERATION
,
11284 "glDrawBuffersEXT",
11285 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
11289 glDrawBuffersARB(count
, bufs
);
11290 framebuffer
->SetDrawBuffers(count
, bufs
);
11291 } else { // backbuffer
11293 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
11294 LOCAL_SET_GL_ERROR(
11295 GL_INVALID_OPERATION
,
11296 "glDrawBuffersEXT",
11297 "more than one buffer or bufs not GL_NONE or GL_BACK");
11300 GLenum mapped_buf
= bufs
[0];
11301 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
11302 bufs
[0] == GL_BACK
) {
11303 mapped_buf
= GL_COLOR_ATTACHMENT0
;
11305 glDrawBuffersARB(count
, &mapped_buf
);
11306 group_
->set_draw_buffer(bufs
[0]);
11310 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
11311 group_
->LoseContexts(other
);
11312 reset_status_
= current
;
11313 current_decoder_error_
= error::kLostContext
;
11316 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
11317 const GLfloat
* matrix
) {
11318 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
11319 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
11320 if (!features().chromium_path_rendering
) {
11321 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11322 "glMatrixLoadfCHROMIUM",
11323 "function not available");
11327 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
11328 ? state_
.projection_matrix
11329 : state_
.modelview_matrix
;
11330 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
11331 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11332 // since the values of the _NV and _CHROMIUM tokens match.
11333 glMatrixLoadfEXT(matrix_mode
, matrix
);
11336 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
11337 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
11338 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
11340 if (!features().chromium_path_rendering
) {
11341 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11342 "glMatrixLoadIdentityCHROMIUM",
11343 "function not available");
11347 static GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
,
11348 0.0f
, 0.0f
, 0.0f
, 0.0f
, 1.0f
, 0.0f
,
11349 0.0f
, 0.0f
, 0.0f
, 1.0f
};
11351 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
11352 ? state_
.projection_matrix
11353 : state_
.modelview_matrix
;
11354 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
11355 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11356 // since the values of the _NV and _CHROMIUM tokens match.
11357 glMatrixLoadIdentityEXT(matrix_mode
);
11360 bool GLES2DecoderImpl::ValidateAsyncTransfer(
11361 const char* function_name
,
11362 TextureRef
* texture_ref
,
11365 const void * data
) {
11366 // We only support async uploads to 2D textures for now.
11367 if (GL_TEXTURE_2D
!= target
) {
11368 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
11371 // We only support uploads to level zero for now.
11373 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
11376 // A transfer buffer must be bound, even for asyncTexImage2D.
11377 if (data
== NULL
) {
11378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
11381 // We only support one async transfer in progress.
11382 if (!texture_ref
||
11383 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
11384 LOCAL_SET_GL_ERROR(
11385 GL_INVALID_OPERATION
,
11386 function_name
, "transfer already in progress");
11392 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11393 uint32 async_upload_token
,
11394 uint32 sync_data_shm_id
,
11395 uint32 sync_data_shm_offset
) {
11396 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
11397 if (!buffer
.get() ||
11398 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
11399 return base::Closure();
11401 AsyncMemoryParams
mem_params(buffer
,
11402 sync_data_shm_offset
,
11403 sizeof(AsyncUploadSync
));
11405 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
11406 new AsyncUploadTokenCompletionObserver(async_upload_token
));
11409 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
11410 base::Unretained(GetAsyncPixelTransferManager()),
11415 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11416 uint32 immediate_data_size
,
11417 const void* cmd_data
) {
11418 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
11419 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
11420 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11421 GLenum target
= static_cast<GLenum
>(c
.target
);
11422 GLint level
= static_cast<GLint
>(c
.level
);
11423 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
11424 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11425 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11426 GLint border
= static_cast<GLint
>(c
.border
);
11427 GLenum format
= static_cast<GLenum
>(c
.format
);
11428 GLenum type
= static_cast<GLenum
>(c
.type
);
11429 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
11430 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
11431 uint32 pixels_size
;
11432 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11433 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11434 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11436 base::ScopedClosureRunner scoped_completion_callback
;
11437 if (async_upload_token
) {
11438 base::Closure completion_closure
=
11439 AsyncUploadTokenCompletionClosure(async_upload_token
,
11441 sync_data_shm_offset
);
11442 if (completion_closure
.is_null())
11443 return error::kInvalidArguments
;
11445 scoped_completion_callback
.Reset(completion_closure
);
11448 // TODO(epenner): Move this and copies of this memory validation
11449 // into ValidateTexImage2D step.
11450 if (!GLES2Util::ComputeImageDataSizes(
11451 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
11453 return error::kOutOfBounds
;
11455 const void* pixels
= NULL
;
11456 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
11457 pixels
= GetSharedMemoryAs
<const void*>(
11458 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
11460 return error::kOutOfBounds
;
11464 TextureManager::DoTextImage2DArguments args
= {
11465 target
, level
, internal_format
, width
, height
, border
, format
, type
,
11466 pixels
, pixels_size
};
11467 TextureRef
* texture_ref
;
11468 // All the normal glTexSubImage2D validation.
11469 if (!texture_manager()->ValidateTexImage2D(
11470 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
11471 return error::kNoError
;
11474 // Extra async validation.
11475 Texture
* texture
= texture_ref
->texture();
11476 if (!ValidateAsyncTransfer(
11477 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11478 return error::kNoError
;
11480 // Don't allow async redefinition of a textures.
11481 if (texture
->IsDefined()) {
11482 LOCAL_SET_GL_ERROR(
11483 GL_INVALID_OPERATION
,
11484 "glAsyncTexImage2DCHROMIUM", "already defined");
11485 return error::kNoError
;
11488 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
11489 LOCAL_SET_GL_ERROR(
11490 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
11491 return error::kNoError
;
11494 // Setup the parameters.
11495 AsyncTexImage2DParams tex_params
= {
11496 target
, level
, static_cast<GLenum
>(internal_format
),
11497 width
, height
, border
, format
, type
};
11498 AsyncMemoryParams
mem_params(
11499 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
11501 // Set up the async state if needed, and make the texture
11502 // immutable so the async state stays valid. The level info
11503 // is set up lazily when the transfer completes.
11504 AsyncPixelTransferDelegate
* delegate
=
11505 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
11507 texture
->SetImmutable(true);
11509 delegate
->AsyncTexImage2D(
11512 base::Bind(&TextureManager::SetLevelInfoFromParams
,
11513 // The callback is only invoked if the transfer delegate still
11514 // exists, which implies through manager->texture_ref->state
11515 // ownership that both of these pointers are valid.
11516 base::Unretained(texture_manager()),
11517 base::Unretained(texture_ref
),
11519 return error::kNoError
;
11522 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11523 uint32 immediate_data_size
,
11524 const void* cmd_data
) {
11525 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
11526 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
11527 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11528 GLenum target
= static_cast<GLenum
>(c
.target
);
11529 GLint level
= static_cast<GLint
>(c
.level
);
11530 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11531 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11532 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11533 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11534 GLenum format
= static_cast<GLenum
>(c
.format
);
11535 GLenum type
= static_cast<GLenum
>(c
.type
);
11536 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
11537 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
11538 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11540 base::ScopedClosureRunner scoped_completion_callback
;
11541 if (async_upload_token
) {
11542 base::Closure completion_closure
=
11543 AsyncUploadTokenCompletionClosure(async_upload_token
,
11545 sync_data_shm_offset
);
11546 if (completion_closure
.is_null())
11547 return error::kInvalidArguments
;
11549 scoped_completion_callback
.Reset(completion_closure
);
11552 // TODO(epenner): Move this and copies of this memory validation
11553 // into ValidateTexSubImage2D step.
11555 if (!GLES2Util::ComputeImageDataSizes(
11556 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
11558 return error::kOutOfBounds
;
11560 const void* pixels
= GetSharedMemoryAs
<const void*>(
11561 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
11563 // All the normal glTexSubImage2D validation.
11564 error::Error error
= error::kNoError
;
11565 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
11566 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
11570 // Extra async validation.
11571 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11573 Texture
* texture
= texture_ref
->texture();
11574 if (!ValidateAsyncTransfer(
11575 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
11576 return error::kNoError
;
11578 // Guarantee async textures are always 'cleared' as follows:
11579 // - AsyncTexImage2D can not redefine an existing texture
11580 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11581 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11582 // - Textures become immutable after an async call.
11583 // This way we know in all cases that an async texture is always clear.
11584 if (!texture
->SafeToRenderFrom()) {
11585 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
11587 LOCAL_SET_GL_ERROR(
11589 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11590 return error::kNoError
;
11594 // Setup the parameters.
11595 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
11596 width
, height
, format
, type
};
11597 AsyncMemoryParams
mem_params(
11598 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
11599 AsyncPixelTransferDelegate
* delegate
=
11600 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
11602 // TODO(epenner): We may want to enforce exclusive use
11603 // of async APIs in which case this should become an error,
11604 // (the texture should have been async defined).
11605 AsyncTexImage2DParams define_params
= {target
, level
,
11607 texture
->GetLevelSize(target
, level
, &define_params
.width
,
11608 &define_params
.height
);
11609 texture
->GetLevelType(target
, level
, &define_params
.type
,
11610 &define_params
.internal_format
);
11611 // Set up the async state if needed, and make the texture
11612 // immutable so the async state stays valid.
11613 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
11614 texture_ref
, define_params
);
11615 texture
->SetImmutable(true);
11618 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
11619 return error::kNoError
;
11622 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11623 uint32 immediate_data_size
,
11624 const void* cmd_data
) {
11625 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
11626 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
11627 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11628 GLenum target
= static_cast<GLenum
>(c
.target
);
11630 if (GL_TEXTURE_2D
!= target
) {
11631 LOCAL_SET_GL_ERROR(
11632 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
11633 return error::kNoError
;
11635 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11637 if (!texture_ref
) {
11638 LOCAL_SET_GL_ERROR(
11639 GL_INVALID_OPERATION
,
11640 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11641 return error::kNoError
;
11643 AsyncPixelTransferDelegate
* delegate
=
11644 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
11646 LOCAL_SET_GL_ERROR(
11647 GL_INVALID_OPERATION
,
11648 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11649 return error::kNoError
;
11651 delegate
->WaitForTransferCompletion();
11652 ProcessFinishedAsyncTransfers();
11653 return error::kNoError
;
11656 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11657 uint32 immediate_data_size
,
11658 const void* data
) {
11659 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11661 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11662 ProcessFinishedAsyncTransfers();
11663 return error::kNoError
;
11666 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11667 TextureRef
* texture_ref
) {
11668 Texture
* texture
= texture_ref
->texture();
11669 DoDidUseTexImageIfNeeded(texture
, texture
->target());
11672 void GLES2DecoderImpl::OnContextLostError() {
11673 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
11676 void GLES2DecoderImpl::OnOutOfMemoryError() {
11677 if (lose_context_when_out_of_memory_
) {
11678 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
11682 // Include the auto-generated part of this file. We split this because it means
11683 // we can easily edit the non-auto generated parts right here in this file
11684 // instead of having to edit some template or the code generator.
11685 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11687 } // namespace gles2