1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
77 #include "base/win/win_util.h"
85 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
91 0.0f
, 1.0f
, 0.0f
, 0.0f
,
92 0.0f
, 0.0f
, 1.0f
, 0.0f
,
93 0.0f
, 0.0f
, 0.0f
, 1.0f
};
95 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
98 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
101 void GetShaderPrecisionFormatImpl(GLenum shader_type
,
102 GLenum precision_type
,
103 GLint
* range
, GLint
* precision
) {
104 switch (precision_type
) {
108 // These values are for a 32-bit twos-complement integer format.
114 case GL_MEDIUM_FLOAT
:
116 // These values are for an IEEE single-precision floating-point format.
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
127 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 glGetShaderPrecisionFormat(shader_type
, precision_type
,
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range
[0] = abs(range
[0]);
143 range
[1] = abs(range
[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
148 if (precision_type
== GL_HIGH_FLOAT
&&
149 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
157 gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
158 switch (plane_transform
) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
160 return gfx::OVERLAY_TRANSFORM_NONE
;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
172 return gfx::OVERLAY_TRANSFORM_INVALID
;
176 template <typename MANAGER_TYPE
, typename OBJECT_TYPE
>
177 GLuint
GetClientId(const MANAGER_TYPE
* manager
, const OBJECT_TYPE
* object
) {
179 GLuint client_id
= 0;
181 manager
->GetClientId(object
->service_id(), &client_id
);
187 explicit Vec4f(const Vec4
& data
) {
196 class GLES2DecoderImpl
;
198 // Local versions of the SET_GL_ERROR macros
199 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
200 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
201 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
202 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
203 function_name, value, label)
204 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
205 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
206 function_name, pname)
207 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
208 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
210 #define LOCAL_PEEK_GL_ERROR(function_name) \
211 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
212 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
213 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
214 #define LOCAL_PERFORMANCE_WARNING(msg) \
215 PerformanceWarning(__FILE__, __LINE__, msg)
216 #define LOCAL_RENDER_WARNING(msg) \
217 RenderWarning(__FILE__, __LINE__, msg)
219 // Check that certain assumptions the code makes are true. There are places in
220 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
221 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
222 // a few others) are 32bits. If they are not 32bits the code will have to change
223 // to call those GL functions with service side memory and then copy the results
224 // to shared memory, converting the sizes.
225 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
226 "GLint should be the same size as uint32");
227 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
228 "GLsizei should be the same size as uint32");
229 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
230 "GLfloat should be the same size as float");
232 // TODO(kbr): the use of this anonymous namespace core dumps the
233 // linker on Mac OS X 10.6 when the symbol ordering file is used
236 // Returns the address of the first byte after a struct.
237 template <typename T
>
238 const void* AddressAfterStruct(const T
& pod
) {
239 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
242 // Returns the address of the frst byte after the struct or NULL if size >
243 // immediate_data_size.
244 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
245 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
247 uint32 immediate_data_size
) {
248 return (size
<= immediate_data_size
) ?
249 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
253 // Computes the data size for certain gl commands like glUniform.
254 bool ComputeDataSize(
257 unsigned int elements_per_unit
,
260 if (!SafeMultiplyUint32(count
, size
, &value
)) {
263 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
270 // Return true if a character belongs to the ASCII subset as defined in
271 // GLSL ES 1.0 spec section 3.1.
272 static bool CharacterIsValidForGLES(unsigned char c
) {
273 // Printing characters are valid except " $ ` @ \ ' DEL.
274 if (c
>= 32 && c
<= 126 &&
283 // Horizontal tab, line feed, vertical tab, form feed, carriage return
285 if (c
>= 9 && c
<= 13) {
292 static bool StringIsValidForGLES(const char* str
) {
293 for (; *str
; ++str
) {
294 if (!CharacterIsValidForGLES(*str
)) {
301 // This class prevents any GL errors that occur when it is in scope from
302 // being reported to the client.
303 class ScopedGLErrorSuppressor
{
305 explicit ScopedGLErrorSuppressor(
306 const char* function_name
, ErrorState
* error_state
);
307 ~ScopedGLErrorSuppressor();
309 const char* function_name_
;
310 ErrorState
* error_state_
;
311 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
314 // Temporarily changes a decoder's bound texture and restore it when this
315 // object goes out of scope. Also temporarily switches to using active texture
316 // unit zero in case the client has changed that to something invalid.
317 class ScopedTextureBinder
{
319 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
320 ~ScopedTextureBinder();
323 ContextState
* state_
;
325 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
328 // Temporarily changes a decoder's bound render buffer and restore it when this
329 // object goes out of scope.
330 class ScopedRenderBufferBinder
{
332 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
333 ~ScopedRenderBufferBinder();
336 ContextState
* state_
;
337 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
340 // Temporarily changes a decoder's bound frame buffer and restore it when this
341 // object goes out of scope.
342 class ScopedFrameBufferBinder
{
344 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
345 ~ScopedFrameBufferBinder();
348 GLES2DecoderImpl
* decoder_
;
349 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
352 // Temporarily changes a decoder's bound frame buffer to a resolved version of
353 // the multisampled offscreen render buffer if that buffer is multisampled, and,
354 // if it is bound or enforce_internal_framebuffer is true. If internal is
355 // true, the resolved framebuffer is not visible to the parent.
356 class ScopedResolvedFrameBufferBinder
{
358 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
359 bool enforce_internal_framebuffer
,
361 ~ScopedResolvedFrameBufferBinder();
364 GLES2DecoderImpl
* decoder_
;
365 bool resolve_and_bind_
;
366 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
369 class ScopedModifyPixels
{
371 explicit ScopedModifyPixels(TextureRef
* ref
);
372 ~ScopedModifyPixels();
378 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
380 ref_
->texture()->OnWillModifyPixels();
383 ScopedModifyPixels::~ScopedModifyPixels() {
385 ref_
->texture()->OnDidModifyPixels();
388 class ScopedRenderTo
{
390 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
394 const Framebuffer
* framebuffer_
;
397 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
398 : framebuffer_(framebuffer
) {
400 framebuffer_
->OnWillRenderTo();
403 ScopedRenderTo::~ScopedRenderTo() {
405 framebuffer_
->OnDidRenderTo();
408 // Encapsulates an OpenGL texture.
411 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
414 // Create a new render texture.
417 // Set the initial size and format of a render texture or resize it.
418 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
420 // Copy the contents of the currently bound frame buffer.
421 void Copy(const gfx::Size
& size
, GLenum format
);
423 // Destroy the render texture. This must be explicitly called before
424 // destroying this object.
427 // Invalidate the texture. This can be used when a context is lost and it is
428 // not possible to make it current in order to free the resource.
435 gfx::Size
size() const {
440 MemoryTypeTracker memory_tracker_
;
441 ContextState
* state_
;
442 size_t bytes_allocated_
;
445 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
448 // Encapsulates an OpenGL render buffer of any format.
449 class BackRenderbuffer
{
451 explicit BackRenderbuffer(
452 RenderbufferManager
* renderbuffer_manager
,
453 MemoryTracker
* memory_tracker
,
454 ContextState
* state
);
457 // Create a new render buffer.
460 // Set the initial size and format of a render buffer or resize it.
461 bool AllocateStorage(const FeatureInfo
* feature_info
,
462 const gfx::Size
& size
,
466 // Destroy the render buffer. This must be explicitly called before destroying
470 // Invalidate the render buffer. This can be used when a context is lost and
471 // it is not possible to make it current in order to free the resource.
479 RenderbufferManager
* renderbuffer_manager_
;
480 MemoryTypeTracker memory_tracker_
;
481 ContextState
* state_
;
482 size_t bytes_allocated_
;
484 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
487 // Encapsulates an OpenGL frame buffer.
488 class BackFramebuffer
{
490 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
493 // Create a new frame buffer.
496 // Attach a color render buffer to a frame buffer.
497 void AttachRenderTexture(BackTexture
* texture
);
499 // Attach a render buffer to a frame buffer. Note that this unbinds any
500 // currently bound frame buffer.
501 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
503 // Destroy the frame buffer. This must be explicitly called before destroying
507 // Invalidate the frame buffer. This can be used when a context is lost and it
508 // is not possible to make it current in order to free the resource.
511 // See glCheckFramebufferStatusEXT.
512 GLenum
CheckStatus();
519 GLES2DecoderImpl
* decoder_
;
521 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
524 struct FenceCallback
{
526 : fence(gfx::GLFence::Create()) {
529 std::vector
<base::Closure
> callbacks
;
530 scoped_ptr
<gfx::GLFence
> fence
;
533 class AsyncUploadTokenCompletionObserver
534 : public AsyncPixelTransferCompletionObserver
{
536 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
537 : async_upload_token_(async_upload_token
) {
540 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
541 DCHECK(mem_params
.buffer().get());
542 void* data
= mem_params
.GetDataAddress();
543 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
544 sync
->SetAsyncUploadToken(async_upload_token_
);
548 ~AsyncUploadTokenCompletionObserver() override
{}
550 uint32 async_upload_token_
;
552 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
555 // } // anonymous namespace.
558 const unsigned int GLES2Decoder::kDefaultStencilMask
=
559 static_cast<unsigned int>(-1);
561 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
562 uint32
* service_texture_id
) {
566 GLES2Decoder::GLES2Decoder()
567 : initialized_(false),
569 log_commands_(false),
570 unsafe_es3_apis_enabled_(false) {
573 GLES2Decoder::~GLES2Decoder() {
576 void GLES2Decoder::BeginDecoding() {}
578 void GLES2Decoder::EndDecoding() {}
580 // This class implements GLES2Decoder so we don't have to expose all the GLES2
581 // cmd stuff to outside this class.
582 class GLES2DecoderImpl
: public GLES2Decoder
,
583 public FramebufferManager::TextureDetachObserver
,
584 public ErrorStateClient
{
586 explicit GLES2DecoderImpl(ContextGroup
* group
);
587 ~GLES2DecoderImpl() override
;
589 // Overridden from AsyncAPIInterface.
590 Error
DoCommand(unsigned int command
,
591 unsigned int arg_count
,
592 const void* args
) override
;
594 error::Error
DoCommands(unsigned int num_commands
,
597 int* entries_processed
) override
;
599 template <bool DebugImpl
>
600 error::Error
DoCommandsImpl(unsigned int num_commands
,
603 int* entries_processed
);
605 // Overridden from AsyncAPIInterface.
606 const char* GetCommandName(unsigned int command_id
) const override
;
608 // Overridden from GLES2Decoder.
609 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
610 const scoped_refptr
<gfx::GLContext
>& context
,
612 const gfx::Size
& offscreen_size
,
613 const DisallowedFeatures
& disallowed_features
,
614 const std::vector
<int32
>& attribs
) override
;
615 void Destroy(bool have_context
) override
;
616 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
617 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
618 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
619 void UpdateParentTextureInfo();
620 bool MakeCurrent() override
;
621 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
622 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
623 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
624 Capabilities
GetCapabilities() override
;
625 void RestoreState(const ContextState
* prev_state
) override
;
627 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
628 void RestoreAllTextureUnitBindings(
629 const ContextState
* prev_state
) const override
{
630 state_
.RestoreAllTextureUnitBindings(prev_state
);
632 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
633 state_
.RestoreActiveTextureUnitBinding(target
);
635 void RestoreBufferBindings() const override
{
636 state_
.RestoreBufferBindings();
638 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
639 void RestoreProgramBindings() const override
{
640 state_
.RestoreProgramBindings();
642 void RestoreTextureUnitBindings(unsigned unit
) const override
{
643 state_
.RestoreTextureUnitBindings(unit
, NULL
);
645 void RestoreFramebufferBindings() const override
;
646 void RestoreRenderbufferBindings() override
;
647 void RestoreTextureState(unsigned service_id
) const override
;
649 void ClearAllAttributes() const override
;
650 void RestoreAllAttributes() const override
;
652 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
653 VertexArrayManager
* GetVertexArrayManager() override
{
654 return vertex_array_manager_
.get();
656 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
658 ValuebufferManager
* GetValuebufferManager() override
{
659 return valuebuffer_manager();
662 bool ProcessPendingQueries(bool did_finish
) override
;
664 bool HasMoreIdleWork() override
;
665 void PerformIdleWork() override
;
667 void WaitForReadPixels(base::Closure callback
) override
;
669 void SetResizeCallback(
670 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
672 Logger
* GetLogger() override
;
674 void BeginDecoding() override
;
675 void EndDecoding() override
;
677 ErrorState
* GetErrorState() override
;
678 const ContextState
* GetContextState() override
{ return &state_
; }
680 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
681 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
683 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
684 void ResetAsyncPixelTransferManagerForTest() override
;
685 void SetAsyncPixelTransferManagerForTest(
686 AsyncPixelTransferManager
* manager
) override
;
687 void SetIgnoreCachedStateForTest(bool ignore
) override
;
688 void ProcessFinishedAsyncTransfers();
690 bool GetServiceTextureId(uint32 client_texture_id
,
691 uint32
* service_texture_id
) override
;
693 uint32
GetTextureUploadCount() override
;
694 base::TimeDelta
GetTotalTextureUploadTime() override
;
695 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
696 void AddProcessingCommandsTime(base::TimeDelta
) override
;
698 // Restores the current state to the user's settings.
699 void RestoreCurrentFramebufferBindings();
701 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
702 void ApplyDirtyState();
704 // These check the state of the currently bound framebuffer or the
705 // backbuffer if no framebuffer is bound.
706 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
707 // check with all attached and enabled color attachments.
708 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
709 bool BoundFramebufferHasDepthAttachment();
710 bool BoundFramebufferHasStencilAttachment();
712 error::ContextLostReason
GetContextLostReason() override
;
714 // Overridden from FramebufferManager::TextureDetachObserver:
715 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
717 // Overriden from ErrorStateClient.
718 void OnContextLostError() override
;
719 void OnOutOfMemoryError() override
;
721 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
722 void EnsureRenderbufferBound();
724 // Helpers to facilitate calling into compatible extensions.
725 static void RenderbufferStorageMultisampleHelper(
726 const FeatureInfo
* feature_info
,
729 GLenum internal_format
,
733 void BlitFramebufferHelper(GLint srcX0
,
745 friend class ScopedFrameBufferBinder
;
746 friend class ScopedResolvedFrameBufferBinder
;
747 friend class BackFramebuffer
;
749 // Initialize or re-initialize the shader translator.
750 bool InitializeShaderTranslator();
752 void UpdateCapabilities();
754 // Helpers for the glGen and glDelete functions.
755 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
756 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
757 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
758 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
759 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
760 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
761 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
762 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
763 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
764 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
765 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
766 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
767 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
768 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
770 // Helper for async upload token completion notification callback.
771 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
772 uint32 sync_data_shm_id
,
773 uint32 sync_data_shm_offset
);
778 void OnFboChanged() const;
779 void OnUseFramebuffer() const;
781 error::ContextLostReason
GetContextLostReasonFromResetStatus(
782 GLenum reset_status
) const;
784 // TODO(gman): Cache these pointers?
785 BufferManager
* buffer_manager() {
786 return group_
->buffer_manager();
789 RenderbufferManager
* renderbuffer_manager() {
790 return group_
->renderbuffer_manager();
793 FramebufferManager
* framebuffer_manager() {
794 return group_
->framebuffer_manager();
797 ValuebufferManager
* valuebuffer_manager() {
798 return group_
->valuebuffer_manager();
801 ProgramManager
* program_manager() {
802 return group_
->program_manager();
805 ShaderManager
* shader_manager() {
806 return group_
->shader_manager();
809 ShaderTranslatorCache
* shader_translator_cache() {
810 return group_
->shader_translator_cache();
813 const TextureManager
* texture_manager() const {
814 return group_
->texture_manager();
817 TextureManager
* texture_manager() {
818 return group_
->texture_manager();
821 MailboxManager
* mailbox_manager() {
822 return group_
->mailbox_manager();
825 ImageManager
* image_manager() { return image_manager_
.get(); }
827 VertexArrayManager
* vertex_array_manager() {
828 return vertex_array_manager_
.get();
831 MemoryTracker
* memory_tracker() {
832 return group_
->memory_tracker();
835 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
836 MemoryTracker
* tracker
= memory_tracker();
838 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
843 bool IsOffscreenBufferMultisampled() const {
844 return offscreen_target_samples_
> 1;
847 // Creates a Texture for the given texture.
848 TextureRef
* CreateTexture(
849 GLuint client_id
, GLuint service_id
) {
850 return texture_manager()->CreateTexture(client_id
, service_id
);
853 // Gets the texture info for the given texture. Returns NULL if none exists.
854 TextureRef
* GetTexture(GLuint client_id
) const {
855 return texture_manager()->GetTexture(client_id
);
858 // Deletes the texture info for the given texture.
859 void RemoveTexture(GLuint client_id
) {
860 texture_manager()->RemoveTexture(client_id
);
863 // Get the size (in pixels) of the currently bound frame buffer (either FBO
864 // or regular back buffer).
865 gfx::Size
GetBoundReadFrameBufferSize();
867 // Get the format of the currently bound frame buffer (either FBO or regular
869 GLenum
GetBoundReadFrameBufferTextureType();
870 GLenum
GetBoundReadFrameBufferInternalFormat();
871 GLenum
GetBoundDrawFrameBufferInternalFormat();
873 // Wrapper for CompressedTexImage2D commands.
874 error::Error
DoCompressedTexImage2D(
877 GLenum internal_format
,
884 // Wrapper for CompressedTexImage3D commands.
885 error::Error
DoCompressedTexImage3D(
888 GLenum internal_format
,
896 // Wrapper for CompressedTexSubImage2D.
897 void DoCompressedTexSubImage2D(
908 // Wrapper for CompressedTexSubImage3D.
909 void DoCompressedTexSubImage3D(
922 // Wrapper for CopyTexImage2D.
923 void DoCopyTexImage2D(
926 GLenum internal_format
,
933 // Wrapper for SwapBuffers.
934 void DoSwapBuffers();
936 // Wrapper for SwapInterval.
937 void DoSwapInterval(int interval
);
939 // Wrapper for CopyTexSubImage2D.
940 void DoCopyTexSubImage2D(
950 // Validation for TexSubImage2D.
951 bool ValidateTexSubImage2D(
953 const char* function_name
,
964 // Wrapper for TexSubImage2D.
965 error::Error
DoTexSubImage2D(
976 // Wrapper for TexSubImage3D.
977 error::Error
DoTexSubImage3D(
990 // Extra validation for async tex(Sub)Image2D.
991 bool ValidateAsyncTransfer(
992 const char* function_name
,
993 TextureRef
* texture_ref
,
998 // Wrapper for TexImageIOSurface2DCHROMIUM.
999 void DoTexImageIOSurface2DCHROMIUM(
1003 GLuint io_surface_id
,
1006 void DoCopyTextureCHROMIUM(GLenum target
,
1009 GLenum internal_format
,
1012 void DoCopySubTextureCHROMIUM(GLenum target
,
1022 // Wrapper for TexStorage2DEXT.
1023 void DoTexStorage2DEXT(
1026 GLenum internal_format
,
1030 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1031 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1033 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1034 GLenum target
, const GLbyte
* data
);
1036 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1037 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1038 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1041 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1042 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1043 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1044 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1045 void DoUniformValueBufferCHROMIUM(GLint location
,
1047 GLenum subscription
);
1049 void DoBindTexImage2DCHROMIUM(
1052 void DoReleaseTexImage2DCHROMIUM(
1056 void DoTraceEndCHROMIUM(void);
1058 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1060 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1062 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1063 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1065 // Creates a Program for the given program.
1066 Program
* CreateProgram(
1067 GLuint client_id
, GLuint service_id
) {
1068 return program_manager()->CreateProgram(client_id
, service_id
);
1071 // Gets the program info for the given program. Returns NULL if none exists.
1072 Program
* GetProgram(GLuint client_id
) {
1073 return program_manager()->GetProgram(client_id
);
1077 void LogClientServiceMapping(
1078 const char* /* function_name */,
1079 GLuint
/* client_id */,
1080 GLuint
/* service_id */) {
1082 template<typename T
>
1083 void LogClientServiceForInfo(
1084 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1087 void LogClientServiceMapping(
1088 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1089 if (service_logging_
) {
1090 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1091 << ": client_id = " << client_id
1092 << ", service_id = " << service_id
;
1095 template<typename T
>
1096 void LogClientServiceForInfo(
1097 T
* info
, GLuint client_id
, const char* function_name
) {
1099 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1104 // Gets the program info for the given program. If it's not a program
1105 // generates a GL error. Returns NULL if not program.
1106 Program
* GetProgramInfoNotShader(
1107 GLuint client_id
, const char* function_name
) {
1108 Program
* program
= GetProgram(client_id
);
1110 if (GetShader(client_id
)) {
1112 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1114 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1117 LogClientServiceForInfo(program
, client_id
, function_name
);
1122 // Creates a Shader for the given shader.
1123 Shader
* CreateShader(
1126 GLenum shader_type
) {
1127 return shader_manager()->CreateShader(
1128 client_id
, service_id
, shader_type
);
1131 // Gets the shader info for the given shader. Returns NULL if none exists.
1132 Shader
* GetShader(GLuint client_id
) {
1133 return shader_manager()->GetShader(client_id
);
1136 // Gets the shader info for the given shader. If it's not a shader generates a
1137 // GL error. Returns NULL if not shader.
1138 Shader
* GetShaderInfoNotProgram(
1139 GLuint client_id
, const char* function_name
) {
1140 Shader
* shader
= GetShader(client_id
);
1142 if (GetProgram(client_id
)) {
1144 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1147 GL_INVALID_VALUE
, function_name
, "unknown shader");
1150 LogClientServiceForInfo(shader
, client_id
, function_name
);
1154 // Creates a buffer info for the given buffer.
1155 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1156 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1159 // Gets the buffer info for the given buffer.
1160 Buffer
* GetBuffer(GLuint client_id
) {
1161 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1165 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1166 // on glDeleteBuffers so we can make sure the user does not try to render
1167 // with deleted buffers.
1168 void RemoveBuffer(GLuint client_id
);
1170 // Creates a framebuffer info for the given framebuffer.
1171 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1172 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1175 // Gets the framebuffer info for the given framebuffer.
1176 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1177 return framebuffer_manager()->GetFramebuffer(client_id
);
1180 // Removes the framebuffer info for the given framebuffer.
1181 void RemoveFramebuffer(GLuint client_id
) {
1182 framebuffer_manager()->RemoveFramebuffer(client_id
);
1185 // Creates a renderbuffer info for the given renderbuffer.
1186 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1187 return renderbuffer_manager()->CreateRenderbuffer(
1188 client_id
, service_id
);
1191 // Gets the renderbuffer info for the given renderbuffer.
1192 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1193 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1196 // Removes the renderbuffer info for the given renderbuffer.
1197 void RemoveRenderbuffer(GLuint client_id
) {
1198 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1201 // Creates a valuebuffer info for the given valuebuffer.
1202 void CreateValuebuffer(GLuint client_id
) {
1203 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1206 // Gets the valuebuffer info for a given valuebuffer.
1207 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1208 return valuebuffer_manager()->GetValuebuffer(client_id
);
1211 // Removes the valuebuffer info for the given valuebuffer.
1212 void RemoveValuebuffer(GLuint client_id
) {
1213 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1216 // Gets the vertex attrib manager for the given vertex array.
1217 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1218 VertexAttribManager
* info
=
1219 vertex_array_manager()->GetVertexAttribManager(client_id
);
1223 // Removes the vertex attrib manager for the given vertex array.
1224 void RemoveVertexAttribManager(GLuint client_id
) {
1225 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1228 // Creates a vertex attrib manager for the given vertex array.
1229 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1232 bool client_visible
) {
1233 return vertex_array_manager()->CreateVertexAttribManager(
1234 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1237 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1238 void DoBindUniformLocationCHROMIUM(
1239 GLuint client_id
, GLint location
, const char* name
);
1241 error::Error
GetAttribLocationHelper(
1242 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1243 const std::string
& name_str
);
1245 error::Error
GetUniformLocationHelper(
1246 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1247 const std::string
& name_str
);
1249 error::Error
GetFragDataLocationHelper(
1250 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1251 const std::string
& name_str
);
1253 // Wrapper for glShaderSource.
1254 void DoShaderSource(
1255 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1257 // Wrapper for glTransformFeedbackVaryings.
1258 void DoTransformFeedbackVaryings(
1259 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1260 GLenum buffer_mode
);
1262 // Clear any textures used by the current program.
1263 bool ClearUnclearedTextures();
1265 // Clears any uncleared attachments attached to the given frame buffer.
1266 // Returns false if there was a generated GL error.
1267 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1269 // overridden from GLES2Decoder
1270 bool ClearLevel(Texture
* texture
,
1273 unsigned internal_format
,
1278 bool is_texture_immutable
) override
;
1280 // Restore all GL state that affects clearing.
1281 void RestoreClearState();
1283 // Remembers the state of some capabilities.
1284 // Returns: true if glEnable/glDisable should actually be called.
1285 bool SetCapabilityState(GLenum cap
, bool enabled
);
1287 // Check that the currently bound framebuffers are valid.
1288 // Generates GL error if not.
1289 bool CheckBoundFramebuffersValid(const char* func_name
);
1291 // Check that the currently bound read framebuffer has a color image
1292 // attached. Generates GL error if not.
1293 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1295 // Check that the currently bound read framebuffer's color image
1296 // isn't the target texture of the glCopyTex{Sub}Image2D.
1297 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1299 // Check if a framebuffer meets our requirements.
1300 bool CheckFramebufferValid(
1301 Framebuffer
* framebuffer
,
1303 const char* func_name
);
1305 // Check if the current valuebuffer exists and is valid. If not generates
1306 // the appropriate GL error. Returns true if the current valuebuffer is in
1308 bool CheckCurrentValuebuffer(const char* function_name
);
1310 // Check if the current valuebuffer exists and is valiud and that the
1311 // value buffer is actually subscribed to the given subscription
1312 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1313 const char* function_name
);
1315 // Check if the location can be used for the given subscription target. If not
1316 // generates the appropriate GL error. Returns true if the location is usable
1317 bool CheckSubscriptionTarget(GLint location
,
1318 GLenum subscription
,
1319 const char* function_name
);
1321 // Checks if the current program exists and is valid. If not generates the
1322 // appropriate GL error. Returns true if the current program is in a usable
1324 bool CheckCurrentProgram(const char* function_name
);
1326 // Checks if the current program exists and is valid and that location is not
1327 // -1. If the current program is not valid generates the appropriate GL
1328 // error. Returns true if the current program is in a usable state and
1329 // location is not -1.
1330 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1332 // Checks if the current program samples a texture that is also the color
1333 // image of the current bound framebuffer, i.e., the source and destination
1334 // of the draw operation are the same.
1335 bool CheckDrawingFeedbackLoops();
1337 // Checks if |api_type| is valid for the given uniform
1338 // If the api type is not valid generates the appropriate GL
1339 // error. Returns true if |api_type| is valid for the uniform
1340 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1341 const char* function_name
,
1342 Program::UniformApiType api_type
);
1344 // Gets the type of a uniform for a location in the current program. Sets GL
1345 // errors if the current program is not valid. Returns true if the current
1346 // program is valid and the location exists. Adjusts count so it
1347 // does not overflow the uniform.
1348 bool PrepForSetUniformByLocation(GLint fake_location
,
1349 const char* function_name
,
1350 Program::UniformApiType api_type
,
1351 GLint
* real_location
,
1355 // Gets the service id for any simulated backbuffer fbo.
1356 GLuint
GetBackbufferServiceId() const;
1358 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1359 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1361 // Helper for glGetVertexAttrib
1362 void GetVertexAttribHelper(
1363 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1365 // Wrapper for glActiveTexture
1366 void DoActiveTexture(GLenum texture_unit
);
1368 // Wrapper for glAttachShader
1369 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1371 // Wrapper for glBindBuffer since we need to track the current targets.
1372 void DoBindBuffer(GLenum target
, GLuint buffer
);
1374 // Wrapper for glBindFramebuffer since we need to track the current targets.
1375 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1377 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1378 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1380 // Wrapper for glBindTexture since we need to track the current targets.
1381 void DoBindTexture(GLenum target
, GLuint texture
);
1383 // Wrapper for glBindVertexArrayOES
1384 void DoBindVertexArrayOES(GLuint array
);
1385 void EmulateVertexArrayState();
1387 // Wrapper for glBlitFramebufferCHROMIUM.
1388 void DoBlitFramebufferCHROMIUM(
1389 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1390 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1391 GLbitfield mask
, GLenum filter
);
1393 // Wrapper for glBufferSubData.
1394 void DoBufferSubData(
1395 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1397 // Wrapper for glCheckFramebufferStatus
1398 GLenum
DoCheckFramebufferStatus(GLenum target
);
1400 // Wrapper for glClear
1401 error::Error
DoClear(GLbitfield mask
);
1403 // Wrappers for various state.
1404 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1405 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1407 // Wrapper for glCompileShader.
1408 void DoCompileShader(GLuint shader
);
1410 // Wrapper for glDetachShader
1411 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1413 // Wrapper for glDisable
1414 void DoDisable(GLenum cap
);
1416 // Wrapper for glDisableVertexAttribArray.
1417 void DoDisableVertexAttribArray(GLuint index
);
1419 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1421 void DoDiscardFramebufferEXT(GLenum target
,
1422 GLsizei numAttachments
,
1423 const GLenum
* attachments
);
1425 // Wrapper for glEnable
1426 void DoEnable(GLenum cap
);
1428 // Wrapper for glEnableVertexAttribArray.
1429 void DoEnableVertexAttribArray(GLuint index
);
1431 // Wrapper for glFinish.
1434 // Wrapper for glFlush.
1437 // Wrapper for glFramebufferRenderbufffer.
1438 void DoFramebufferRenderbuffer(
1439 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1440 GLuint renderbuffer
);
1442 // Wrapper for glFramebufferTexture2D.
1443 void DoFramebufferTexture2D(
1444 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1447 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1448 void DoFramebufferTexture2DMultisample(
1449 GLenum target
, GLenum attachment
, GLenum textarget
,
1450 GLuint texture
, GLint level
, GLsizei samples
);
1452 // Common implementation for both DoFramebufferTexture2D wrappers.
1453 void DoFramebufferTexture2DCommon(const char* name
,
1454 GLenum target
, GLenum attachment
, GLenum textarget
,
1455 GLuint texture
, GLint level
, GLsizei samples
);
1457 // Wrapper for glFramebufferTextureLayer.
1458 void DoFramebufferTextureLayer(
1459 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1462 // Wrapper for glGenerateMipmap
1463 void DoGenerateMipmap(GLenum target
);
1465 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1466 // to account for different pname values defined in different extension
1468 GLenum
AdjustGetPname(GLenum pname
);
1470 // Wrapper for DoGetBooleanv.
1471 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1473 // Wrapper for DoGetFloatv.
1474 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1476 // Wrapper for glGetFramebufferAttachmentParameteriv.
1477 void DoGetFramebufferAttachmentParameteriv(
1478 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1480 // Wrapper for glGetInteger64v.
1481 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1483 // Wrapper for glGetIntegerv.
1484 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1486 // Gets the max value in a range in a buffer.
1487 GLuint
DoGetMaxValueInBufferCHROMIUM(
1488 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1490 // Wrapper for glGetBufferParameteriv.
1491 void DoGetBufferParameteriv(
1492 GLenum target
, GLenum pname
, GLint
* params
);
1494 // Wrapper for glGetProgramiv.
1495 void DoGetProgramiv(
1496 GLuint program_id
, GLenum pname
, GLint
* params
);
1498 // Wrapper for glRenderbufferParameteriv.
1499 void DoGetRenderbufferParameteriv(
1500 GLenum target
, GLenum pname
, GLint
* params
);
1502 // Wrapper for glGetShaderiv
1503 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1505 // Wrappers for glGetTexParameter.
1506 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1507 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1508 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1510 // Wrappers for glGetVertexAttrib.
1511 template <typename T
>
1512 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1513 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1514 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1515 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1516 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1518 // Wrappers for glIsXXX functions.
1519 bool DoIsEnabled(GLenum cap
);
1520 bool DoIsBuffer(GLuint client_id
);
1521 bool DoIsFramebuffer(GLuint client_id
);
1522 bool DoIsProgram(GLuint client_id
);
1523 bool DoIsRenderbuffer(GLuint client_id
);
1524 bool DoIsShader(GLuint client_id
);
1525 bool DoIsTexture(GLuint client_id
);
1526 bool DoIsVertexArrayOES(GLuint client_id
);
1528 // Wrapper for glLinkProgram
1529 void DoLinkProgram(GLuint program
);
1531 // Wrapper for glRenderbufferStorage.
1532 void DoRenderbufferStorage(
1533 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1535 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1536 void DoRenderbufferStorageMultisampleCHROMIUM(
1537 GLenum target
, GLsizei samples
, GLenum internalformat
,
1538 GLsizei width
, GLsizei height
);
1540 // Handler for glRenderbufferStorageMultisampleEXT
1541 // (multisampled_render_to_texture).
1542 void DoRenderbufferStorageMultisampleEXT(
1543 GLenum target
, GLsizei samples
, GLenum internalformat
,
1544 GLsizei width
, GLsizei height
);
1546 // Common validation for multisample extensions.
1547 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1548 GLenum internalformat
,
1552 // Verifies that the currently bound multisample renderbuffer is valid
1553 // Very slow! Only done on platforms with driver bugs that return invalid
1554 // buffers under memory pressure
1555 bool VerifyMultisampleRenderbufferIntegrity(
1556 GLuint renderbuffer
, GLenum format
);
1558 // Wrapper for glReleaseShaderCompiler.
1559 void DoReleaseShaderCompiler() { }
1561 // Wrappers for glSamplerParameter*v functions.
1562 void DoSamplerParameterfv(
1563 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1564 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1566 // Wrappers for glTexParameter functions.
1567 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1568 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1569 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1570 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1572 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1573 // spec only these 2 functions can be used to set sampler uniforms.
1574 void DoUniform1i(GLint fake_location
, GLint v0
);
1575 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1576 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1577 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1578 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1580 // Wrappers for glUniformfv because some drivers don't correctly accept
1582 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1583 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1584 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1585 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1587 void DoUniformMatrix2fv(
1588 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1589 const GLfloat
* value
);
1590 void DoUniformMatrix3fv(
1591 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1592 const GLfloat
* value
);
1593 void DoUniformMatrix4fv(
1594 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1595 const GLfloat
* value
);
1597 template <typename T
>
1598 bool SetVertexAttribValue(
1599 const char* function_name
, GLuint index
, const T
* value
);
1601 // Wrappers for glVertexAttrib??
1602 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1603 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1604 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1605 void DoVertexAttrib4f(
1606 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1607 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1608 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1609 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1610 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1611 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1612 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1613 void DoVertexAttribI4ui(
1614 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1615 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1617 // Wrapper for glViewport
1618 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1620 // Wrapper for glUseProgram
1621 void DoUseProgram(GLuint program
);
1623 // Wrapper for glValidateProgram.
1624 void DoValidateProgram(GLuint program_client_id
);
1626 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1627 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1628 void DoPopGroupMarkerEXT(void);
1630 // Gets the number of values that will be returned by glGetXXX. Returns
1631 // false if pname is unknown.
1632 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1634 // Checks if the current program and vertex attributes are valid for drawing.
1636 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1639 // Returns true if successful, simulated will be true if attrib0 was
1641 bool SimulateAttrib0(
1642 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1643 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1645 // If an image is bound to texture, this will call Will/DidUseTexImage
1647 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1648 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1650 // Returns false if textures were replaced.
1651 bool PrepareTexturesForRender();
1652 void RestoreStateForTextures();
1654 // Returns true if GL_FIXED attribs were simulated.
1655 bool SimulateFixedAttribs(
1656 const char* function_name
,
1657 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1658 void RestoreStateForSimulatedFixedAttribs();
1660 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1661 // cases (primcount is always 1 for non-instanced).
1662 error::Error
DoDrawArrays(
1663 const char* function_name
,
1664 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1666 error::Error
DoDrawElements(
1667 const char* function_name
,
1668 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1669 int32 offset
, GLsizei primcount
);
1671 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1672 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1673 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1676 return GL_TEXTURE_2D
;
1677 case GL_SAMPLER_CUBE
:
1678 return GL_TEXTURE_CUBE_MAP
;
1679 case GL_SAMPLER_EXTERNAL_OES
:
1680 return GL_TEXTURE_EXTERNAL_OES
;
1681 case GL_SAMPLER_2D_RECT_ARB
:
1682 return GL_TEXTURE_RECTANGLE_ARB
;
1689 // Gets the framebuffer info for a particular target.
1690 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1691 Framebuffer
* framebuffer
= NULL
;
1693 case GL_FRAMEBUFFER
:
1694 case GL_DRAW_FRAMEBUFFER_EXT
:
1695 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1697 case GL_READ_FRAMEBUFFER_EXT
:
1698 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1707 Renderbuffer
* GetRenderbufferInfoForTarget(
1709 Renderbuffer
* renderbuffer
= NULL
;
1711 case GL_RENDERBUFFER
:
1712 renderbuffer
= state_
.bound_renderbuffer
.get();
1718 return renderbuffer
;
1721 // Validates the program and location for a glGetUniform call and returns
1722 // a SizeResult setup to receive the result. Returns true if glGetUniform
1723 // should be called.
1725 bool GetUniformSetup(GLuint program
,
1726 GLint fake_location
,
1729 error::Error
* error
,
1730 GLint
* real_location
,
1732 SizedResult
<T
>** result
,
1733 GLenum
* result_type
,
1734 GLsizei
* result_size
);
1736 bool WasContextLost() const override
;
1737 bool WasContextLostByRobustnessExtension() const override
;
1738 void MarkContextLost(error::ContextLostReason reason
) override
;
1739 bool CheckResetStatus();
1741 #if defined(OS_MACOSX)
1742 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1745 bool ValidateCompressedTexDimensions(
1746 const char* function_name
, GLenum target
, GLint level
,
1747 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1748 bool ValidateCompressedTexFuncData(
1749 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1750 GLenum format
, GLsizei size
);
1751 bool ValidateCompressedTexSubDimensions(
1752 const char* function_name
,
1753 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1754 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1756 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1758 TextureRef
* source_texture_ref
,
1759 TextureRef
* dest_texture_ref
,
1760 GLenum dest_internal_format
);
1762 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1763 void PerformanceWarning(
1764 const char* filename
, int line
, const std::string
& msg
);
1766 const FeatureInfo::FeatureFlags
& features() const {
1767 return feature_info_
->feature_flags();
1770 const FeatureInfo::Workarounds
& workarounds() const {
1771 return feature_info_
->workarounds();
1774 bool ShouldDeferDraws() {
1775 return !offscreen_target_frame_buffer_
.get() &&
1776 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1777 surface_
->DeferDraws();
1780 bool ShouldDeferReads() {
1781 return !offscreen_target_frame_buffer_
.get() &&
1782 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1783 surface_
->DeferDraws();
1786 bool IsRobustnessSupported() {
1787 return has_robustness_extension_
&&
1788 context_
->WasAllocatedUsingRobustnessExtension();
1791 error::Error
WillAccessBoundFramebufferForDraw() {
1792 if (ShouldDeferDraws())
1793 return error::kDeferCommandUntilLater
;
1794 if (!offscreen_target_frame_buffer_
.get() &&
1795 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1796 !surface_
->SetBackbufferAllocation(true))
1797 return error::kLostContext
;
1798 return error::kNoError
;
1801 error::Error
WillAccessBoundFramebufferForRead() {
1802 if (ShouldDeferReads())
1803 return error::kDeferCommandUntilLater
;
1804 if (!offscreen_target_frame_buffer_
.get() &&
1805 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1806 !surface_
->SetBackbufferAllocation(true))
1807 return error::kLostContext
;
1808 return error::kNoError
;
1811 // Set remaining commands to process to 0 to force DoCommands to return
1812 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1813 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1815 void ProcessPendingReadPixels();
1816 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1818 // Generate a member function prototype for each command in an automated and
1820 #define GLES2_CMD_OP(name) \
1821 Error Handle##name(uint32 immediate_data_size, const void* data);
1823 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1827 // The GL context this decoder renders to on behalf of the client.
1828 scoped_refptr
<gfx::GLSurface
> surface_
;
1829 scoped_refptr
<gfx::GLContext
> context_
;
1831 // The ContextGroup for this decoder uses to track resources.
1832 scoped_refptr
<ContextGroup
> group_
;
1834 DebugMarkerManager debug_marker_manager_
;
1837 // All the state for this context.
1838 ContextState state_
;
1840 // Current width and height of the offscreen frame buffer.
1841 gfx::Size offscreen_size_
;
1843 // Util to help with GL.
1846 // unpack flip y as last set by glPixelStorei
1847 bool unpack_flip_y_
;
1849 // unpack (un)premultiply alpha as last set by glPixelStorei
1850 bool unpack_premultiply_alpha_
;
1851 bool unpack_unpremultiply_alpha_
;
1853 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1854 GLuint attrib_0_buffer_id_
;
1856 // The value currently in attrib_0.
1857 Vec4 attrib_0_value_
;
1859 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1860 bool attrib_0_buffer_matches_value_
;
1862 // The size of attrib 0.
1863 GLsizei attrib_0_size_
;
1865 // The buffer used to simulate GL_FIXED attribs.
1866 GLuint fixed_attrib_buffer_id_
;
1868 // The size of fiixed attrib buffer.
1869 GLsizei fixed_attrib_buffer_size_
;
1871 // The offscreen frame buffer that the client renders to. With EGL, the
1872 // depth and stencil buffers are separate. With regular GL there is a single
1873 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1874 // offscreen_target_stencil_render_buffer_ is unused.
1875 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1876 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1877 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1878 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1879 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1880 GLenum offscreen_target_color_format_
;
1881 GLenum offscreen_target_depth_format_
;
1882 GLenum offscreen_target_stencil_format_
;
1883 GLsizei offscreen_target_samples_
;
1884 GLboolean offscreen_target_buffer_preserved_
;
1886 // The copy that is saved when SwapBuffers is called.
1887 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1888 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1889 scoped_refptr
<TextureRef
>
1890 offscreen_saved_color_texture_info_
;
1892 // The copy that is used as the destination for multi-sample resolves.
1893 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1894 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1895 GLenum offscreen_saved_color_format_
;
1897 scoped_ptr
<QueryManager
> query_manager_
;
1899 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1901 scoped_ptr
<ImageManager
> image_manager_
;
1903 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1905 WaitSyncPointCallback wait_sync_point_callback_
;
1907 ShaderCacheCallback shader_cache_callback_
;
1909 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1911 // The format of the back buffer_
1912 GLenum back_buffer_color_format_
;
1913 bool back_buffer_has_depth_
;
1914 bool back_buffer_has_stencil_
;
1918 // Backbuffer attachments that are currently undefined.
1919 uint32 backbuffer_needs_clear_bits_
;
1921 // The current decoder error communicates the decoder error through command
1922 // processing functions that do not return the error value. Should be set only
1923 // if not returning an error.
1924 error::Error current_decoder_error_
;
1926 bool use_shader_translator_
;
1927 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1928 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1930 DisallowedFeatures disallowed_features_
;
1932 // Cached from ContextGroup
1933 const Validators
* validators_
;
1934 scoped_refptr
<FeatureInfo
> feature_info_
;
1938 // Number of commands remaining to be processed in DoCommands().
1939 int commands_to_process_
;
1941 bool has_robustness_extension_
;
1942 error::ContextLostReason context_lost_reason_
;
1943 bool context_was_lost_
;
1944 bool reset_by_robustness_extension_
;
1945 bool supports_post_sub_buffer_
;
1947 // These flags are used to override the state of the shared feature_info_
1948 // member. Because the same FeatureInfo instance may be shared among many
1949 // contexts, the assumptions on the availablity of extensions in WebGL
1950 // contexts may be broken. These flags override the shared state to preserve
1952 bool force_webgl_glsl_validation_
;
1953 bool derivatives_explicitly_enabled_
;
1954 bool frag_depth_explicitly_enabled_
;
1955 bool draw_buffers_explicitly_enabled_
;
1956 bool shader_texture_lod_explicitly_enabled_
;
1958 bool compile_shader_always_succeeds_
;
1960 // An optional behaviour to lose the context and group when OOM.
1961 bool lose_context_when_out_of_memory_
;
1964 bool service_logging_
;
1966 #if defined(OS_MACOSX)
1967 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1968 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1971 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1972 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1974 // Cached values of the currently assigned viewport dimensions.
1975 GLsizei viewport_max_width_
;
1976 GLsizei viewport_max_height_
;
1978 // Command buffer stats.
1979 base::TimeDelta total_processing_commands_time_
;
1981 // States related to each manager.
1982 DecoderTextureState texture_state_
;
1983 DecoderFramebufferState framebuffer_state_
;
1985 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1986 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1987 const unsigned char* cb_command_trace_category_
;
1988 const unsigned char* gpu_decoder_category_
;
1989 int gpu_trace_level_
;
1990 bool gpu_trace_commands_
;
1991 bool gpu_debug_commands_
;
1993 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1995 // Used to validate multisample renderbuffers if needed
1996 GLuint validation_texture_
;
1997 GLuint validation_fbo_multisample_
;
1998 GLuint validation_fbo_
;
2000 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2001 uint32 immediate_data_size
,
2004 // A struct to hold info about each command.
2005 struct CommandInfo
{
2006 CmdHandler cmd_handler
;
2007 uint8 arg_flags
; // How to handle the arguments for this command
2008 uint8 cmd_flags
; // How to handle this command
2009 uint16 arg_count
; // How many arguments are expected for this command.
2012 // A table of CommandInfo for all the commands.
2013 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2015 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2018 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2019 #define GLES2_CMD_OP(name) \
2021 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2022 cmds::name::cmd_flags, \
2023 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2026 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2030 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2031 const char* function_name
, ErrorState
* error_state
)
2032 : function_name_(function_name
),
2033 error_state_(error_state
) {
2034 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2037 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2038 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2041 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2042 TextureUnit
& info
= state
->texture_units
[0];
2044 scoped_refptr
<TextureRef
> texture_ref
;
2047 texture_ref
= info
.bound_texture_2d
;
2049 case GL_TEXTURE_CUBE_MAP
:
2050 texture_ref
= info
.bound_texture_cube_map
;
2052 case GL_TEXTURE_EXTERNAL_OES
:
2053 texture_ref
= info
.bound_texture_external_oes
;
2055 case GL_TEXTURE_RECTANGLE_ARB
:
2056 texture_ref
= info
.bound_texture_rectangle_arb
;
2062 if (texture_ref
.get()) {
2063 last_id
= texture_ref
->service_id();
2068 glBindTexture(target
, last_id
);
2069 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2072 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2077 ScopedGLErrorSuppressor
suppressor(
2078 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2080 // TODO(apatrick): Check if there are any other states that need to be reset
2081 // before binding a new texture.
2082 glActiveTexture(GL_TEXTURE0
);
2083 glBindTexture(target
, id
);
2086 ScopedTextureBinder::~ScopedTextureBinder() {
2087 ScopedGLErrorSuppressor
suppressor(
2088 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2089 RestoreCurrentTextureBindings(state_
, target_
);
2092 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2095 ScopedGLErrorSuppressor
suppressor(
2096 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2097 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2100 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2101 ScopedGLErrorSuppressor
suppressor(
2102 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2103 state_
->RestoreRenderbufferBindings();
2106 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2108 : decoder_(decoder
) {
2109 ScopedGLErrorSuppressor
suppressor(
2110 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2111 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2112 decoder
->OnFboChanged();
2115 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2116 ScopedGLErrorSuppressor
suppressor(
2117 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2118 decoder_
->RestoreCurrentFramebufferBindings();
2121 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2122 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2123 : decoder_(decoder
) {
2124 resolve_and_bind_
= (
2125 decoder_
->offscreen_target_frame_buffer_
.get() &&
2126 decoder_
->IsOffscreenBufferMultisampled() &&
2127 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2128 enforce_internal_framebuffer
));
2129 if (!resolve_and_bind_
)
2132 ScopedGLErrorSuppressor
suppressor(
2133 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2134 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2135 decoder_
->offscreen_target_frame_buffer_
->id());
2138 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2139 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2140 new BackFramebuffer(decoder_
));
2141 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2142 decoder_
->offscreen_resolved_color_texture_
.reset(
2143 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2144 decoder_
->offscreen_resolved_color_texture_
->Create();
2146 DCHECK(decoder_
->offscreen_saved_color_format_
);
2147 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2148 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2150 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2151 decoder_
->offscreen_resolved_color_texture_
.get());
2152 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2153 GL_FRAMEBUFFER_COMPLETE
) {
2154 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2155 << "because offscreen resolved FBO was incomplete.";
2159 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2161 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2163 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2164 const int width
= decoder_
->offscreen_size_
.width();
2165 const int height
= decoder_
->offscreen_size_
.height();
2166 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2167 decoder
->BlitFramebufferHelper(0,
2175 GL_COLOR_BUFFER_BIT
,
2177 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2180 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2181 if (!resolve_and_bind_
)
2184 ScopedGLErrorSuppressor
suppressor(
2185 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2186 decoder_
->RestoreCurrentFramebufferBindings();
2187 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2188 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2192 BackTexture::BackTexture(
2193 MemoryTracker
* memory_tracker
,
2194 ContextState
* state
)
2195 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2197 bytes_allocated_(0),
2201 BackTexture::~BackTexture() {
2202 // This does not destroy the render texture because that would require that
2203 // the associated GL context was current. Just check that it was explicitly
2208 void BackTexture::Create() {
2209 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2210 state_
->GetErrorState());
2212 glGenTextures(1, &id_
);
2213 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2214 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2215 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2216 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2217 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2219 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2220 // never called on an offscreen context, no data will ever be uploaded to the
2221 // saved offscreen color texture (it is deferred until to when SwapBuffers
2222 // is called). My idea is that some nvidia drivers might have a bug where
2223 // deleting a texture that has never been populated might cause a
2226 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2228 bytes_allocated_
= 16u * 16u * 4u;
2229 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2232 bool BackTexture::AllocateStorage(
2233 const gfx::Size
& size
, GLenum format
, bool zero
) {
2235 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2236 state_
->GetErrorState());
2237 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2238 uint32 image_size
= 0;
2239 GLES2Util::ComputeImageDataSizes(
2240 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2243 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2247 scoped_ptr
<char[]> zero_data
;
2249 zero_data
.reset(new char[image_size
]);
2250 memset(zero_data
.get(), 0, image_size
);
2253 glTexImage2D(GL_TEXTURE_2D
,
2265 bool success
= glGetError() == GL_NO_ERROR
;
2267 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2268 bytes_allocated_
= image_size
;
2269 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2274 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2276 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2277 state_
->GetErrorState());
2278 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2279 glCopyTexImage2D(GL_TEXTURE_2D
,
2288 void BackTexture::Destroy() {
2290 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2291 state_
->GetErrorState());
2292 glDeleteTextures(1, &id_
);
2295 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2296 bytes_allocated_
= 0;
2299 void BackTexture::Invalidate() {
2303 BackRenderbuffer::BackRenderbuffer(
2304 RenderbufferManager
* renderbuffer_manager
,
2305 MemoryTracker
* memory_tracker
,
2306 ContextState
* state
)
2307 : renderbuffer_manager_(renderbuffer_manager
),
2308 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2310 bytes_allocated_(0),
2314 BackRenderbuffer::~BackRenderbuffer() {
2315 // This does not destroy the render buffer because that would require that
2316 // the associated GL context was current. Just check that it was explicitly
2321 void BackRenderbuffer::Create() {
2322 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2323 state_
->GetErrorState());
2325 glGenRenderbuffersEXT(1, &id_
);
2328 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2329 const gfx::Size
& size
,
2332 ScopedGLErrorSuppressor
suppressor(
2333 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2334 ScopedRenderBufferBinder
binder(state_
, id_
);
2336 uint32 estimated_size
= 0;
2337 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2338 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2342 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2347 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2352 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2359 bool success
= glGetError() == GL_NO_ERROR
;
2361 // Mark the previously allocated bytes as free.
2362 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2363 bytes_allocated_
= estimated_size
;
2364 // Track the newly allocated bytes.
2365 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2370 void BackRenderbuffer::Destroy() {
2372 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2373 state_
->GetErrorState());
2374 glDeleteRenderbuffersEXT(1, &id_
);
2377 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2378 bytes_allocated_
= 0;
2381 void BackRenderbuffer::Invalidate() {
2385 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2386 : decoder_(decoder
),
2390 BackFramebuffer::~BackFramebuffer() {
2391 // This does not destroy the frame buffer because that would require that
2392 // the associated GL context was current. Just check that it was explicitly
2397 void BackFramebuffer::Create() {
2398 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2399 decoder_
->GetErrorState());
2401 glGenFramebuffersEXT(1, &id_
);
2404 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2406 ScopedGLErrorSuppressor
suppressor(
2407 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2408 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2409 GLuint attach_id
= texture
? texture
->id() : 0;
2410 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2411 GL_COLOR_ATTACHMENT0
,
2417 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2418 BackRenderbuffer
* render_buffer
) {
2420 ScopedGLErrorSuppressor
suppressor(
2421 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2422 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2423 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2424 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2430 void BackFramebuffer::Destroy() {
2432 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2433 decoder_
->GetErrorState());
2434 glDeleteFramebuffersEXT(1, &id_
);
2439 void BackFramebuffer::Invalidate() {
2443 GLenum
BackFramebuffer::CheckStatus() {
2445 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2446 decoder_
->GetErrorState());
2447 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2448 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2451 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2452 return new GLES2DecoderImpl(group
);
2455 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2458 logger_(&debug_marker_manager_
),
2459 state_(group_
->feature_info(), this, &logger_
),
2460 unpack_flip_y_(false),
2461 unpack_premultiply_alpha_(false),
2462 unpack_unpremultiply_alpha_(false),
2463 attrib_0_buffer_id_(0),
2464 attrib_0_buffer_matches_value_(true),
2466 fixed_attrib_buffer_id_(0),
2467 fixed_attrib_buffer_size_(0),
2468 offscreen_target_color_format_(0),
2469 offscreen_target_depth_format_(0),
2470 offscreen_target_stencil_format_(0),
2471 offscreen_target_samples_(0),
2472 offscreen_target_buffer_preserved_(true),
2473 offscreen_saved_color_format_(0),
2474 back_buffer_color_format_(0),
2475 back_buffer_has_depth_(false),
2476 back_buffer_has_stencil_(false),
2477 surfaceless_(false),
2478 backbuffer_needs_clear_bits_(0),
2479 current_decoder_error_(error::kNoError
),
2480 use_shader_translator_(true),
2481 validators_(group_
->feature_info()->validators()),
2482 feature_info_(group_
->feature_info()),
2484 has_robustness_extension_(false),
2485 context_lost_reason_(error::kUnknown
),
2486 context_was_lost_(false),
2487 reset_by_robustness_extension_(false),
2488 supports_post_sub_buffer_(false),
2489 force_webgl_glsl_validation_(false),
2490 derivatives_explicitly_enabled_(false),
2491 frag_depth_explicitly_enabled_(false),
2492 draw_buffers_explicitly_enabled_(false),
2493 shader_texture_lod_explicitly_enabled_(false),
2494 compile_shader_always_succeeds_(false),
2495 lose_context_when_out_of_memory_(false),
2496 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2497 switches::kEnableGPUServiceLoggingGPU
)),
2498 viewport_max_width_(0),
2499 viewport_max_height_(0),
2500 texture_state_(group_
->feature_info()
2502 .texsubimage_faster_than_teximage
),
2503 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2504 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2505 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2506 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2507 gpu_trace_level_(2),
2508 gpu_trace_commands_(false),
2509 gpu_debug_commands_(false),
2510 validation_texture_(0),
2511 validation_fbo_multisample_(0),
2512 validation_fbo_(0) {
2515 // The shader translator is used for WebGL even when running on EGL
2516 // because additional restrictions are needed (like only enabling
2517 // GL_OES_standard_derivatives on demand). It is used for the unit
2518 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2519 // the empty string to CompileShader and this is not a valid shader.
2520 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2521 base::CommandLine::ForCurrentProcess()->HasSwitch(
2522 switches::kDisableGLSLTranslator
)) {
2523 use_shader_translator_
= false;
2527 GLES2DecoderImpl::~GLES2DecoderImpl() {
2530 bool GLES2DecoderImpl::Initialize(
2531 const scoped_refptr
<gfx::GLSurface
>& surface
,
2532 const scoped_refptr
<gfx::GLContext
>& context
,
2534 const gfx::Size
& offscreen_size
,
2535 const DisallowedFeatures
& disallowed_features
,
2536 const std::vector
<int32
>& attribs
) {
2537 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2538 DCHECK(context
->IsCurrent(surface
.get()));
2539 DCHECK(!context_
.get());
2540 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2542 ContextCreationAttribHelper attrib_parser
;
2543 if (!attrib_parser
.Parse(attribs
))
2546 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2549 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2551 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2552 switches::kEnableGPUDebugging
)) {
2556 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2557 switches::kEnableGPUCommandLogging
)) {
2558 set_log_commands(true);
2561 compile_shader_always_succeeds_
=
2562 base::CommandLine::ForCurrentProcess()->HasSwitch(
2563 switches::kCompileShaderAlwaysSucceeds
);
2565 // Take ownership of the context and surface. The surface can be replaced with
2570 // Create GPU Tracer for timing values.
2571 gpu_tracer_
.reset(new GPUTracer(this));
2573 // Save the loseContextWhenOutOfMemory context creation attribute.
2574 lose_context_when_out_of_memory_
=
2575 attrib_parser
.lose_context_when_out_of_memory
;
2577 // If the failIfMajorPerformanceCaveat context creation attribute was true
2578 // and we are using a software renderer, fail.
2579 if (attrib_parser
.fail_if_major_perf_caveat
&&
2580 feature_info_
->feature_flags().is_swiftshader
) {
2581 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2586 if (!group_
->Initialize(this, disallowed_features
)) {
2587 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2588 << "failed to initialize.";
2589 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2595 if (attrib_parser
.es3_context_required
&&
2596 feature_info_
->IsES3Capable()) {
2597 feature_info_
->EnableES3Validators();
2598 set_unsafe_es3_apis_enabled(true);
2601 disallowed_features_
= disallowed_features
;
2603 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2604 vertex_array_manager_
.reset(new VertexArrayManager());
2606 GLuint default_vertex_attrib_service_id
= 0;
2607 if (features().native_vertex_array_object
) {
2608 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2609 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2612 state_
.default_vertex_attrib_manager
=
2613 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2615 state_
.default_vertex_attrib_manager
->Initialize(
2616 group_
->max_vertex_attribs(),
2617 feature_info_
->workarounds().init_vertex_attributes
);
2619 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2620 DoBindVertexArrayOES(0);
2622 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2624 image_manager_
.reset(new ImageManager
);
2626 util_
.set_num_compressed_texture_formats(
2627 validators_
->compressed_texture_format
.GetValues().size());
2629 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2630 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2631 // OpenGL ES 2.0 does not have this issue.
2632 glEnableVertexAttribArray(0);
2634 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2635 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2636 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2637 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2638 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2640 state_
.texture_units
.resize(group_
->max_texture_units());
2641 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2642 glActiveTexture(GL_TEXTURE0
+ tt
);
2643 // We want the last bind to be 2D.
2645 if (features().oes_egl_image_external
) {
2646 ref
= texture_manager()->GetDefaultTextureInfo(
2647 GL_TEXTURE_EXTERNAL_OES
);
2648 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2649 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2651 if (features().arb_texture_rectangle
) {
2652 ref
= texture_manager()->GetDefaultTextureInfo(
2653 GL_TEXTURE_RECTANGLE_ARB
);
2654 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2655 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2657 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2658 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2659 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2660 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2661 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2662 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2664 glActiveTexture(GL_TEXTURE0
);
2667 // cache ALPHA_BITS result for re-use with clear behaviour
2668 GLint alpha_bits
= 0;
2671 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2672 features().chromium_framebuffer_multisample
) {
2673 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2674 // max_sample_count must be initialized to a sane value. If
2675 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2676 GLint max_sample_count
= 1;
2677 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2678 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2681 offscreen_target_samples_
= 1;
2683 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2685 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2686 const bool rgb8_supported
=
2687 context_
->HasExtension("GL_OES_rgb8_rgba8");
2688 // The only available default render buffer formats in GLES2 have very
2689 // little precision. Don't enable multisampling unless 8-bit render
2690 // buffer formats are available--instead fall back to 8-bit textures.
2691 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2692 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2695 offscreen_target_samples_
= 1;
2696 offscreen_target_color_format_
=
2697 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2702 // ANGLE only supports packed depth/stencil formats, so use it if it is
2704 const bool depth24_stencil8_supported
=
2705 feature_info_
->feature_flags().packed_depth24_stencil8
;
2706 VLOG(1) << "GL_OES_packed_depth_stencil "
2707 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2708 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2709 depth24_stencil8_supported
) {
2710 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2711 offscreen_target_stencil_format_
= 0;
2713 // It may be the case that this depth/stencil combination is not
2714 // supported, but this will be checked later by CheckFramebufferStatus.
2715 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2716 GL_DEPTH_COMPONENT16
: 0;
2717 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2718 GL_STENCIL_INDEX8
: 0;
2721 offscreen_target_color_format_
=
2722 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2726 // If depth is requested at all, use the packed depth stencil format if
2727 // it's available, as some desktop GL drivers don't support any non-packed
2728 // formats for depth attachments.
2729 const bool depth24_stencil8_supported
=
2730 feature_info_
->feature_flags().packed_depth24_stencil8
;
2731 VLOG(1) << "GL_EXT_packed_depth_stencil "
2732 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2734 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2735 depth24_stencil8_supported
) {
2736 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2737 offscreen_target_stencil_format_
= 0;
2739 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2740 GL_DEPTH_COMPONENT
: 0;
2741 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2742 GL_STENCIL_INDEX
: 0;
2746 offscreen_saved_color_format_
=
2747 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2751 // Create the target frame buffer. This is the one that the client renders
2753 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2754 offscreen_target_frame_buffer_
->Create();
2755 // Due to GLES2 format limitations, either the color texture (for
2756 // non-multisampling) or the color render buffer (for multisampling) will be
2757 // attached to the offscreen frame buffer. The render buffer has more
2758 // limited formats available to it, but the texture can't do multisampling.
2759 if (IsOffscreenBufferMultisampled()) {
2760 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2761 renderbuffer_manager(), memory_tracker(), &state_
));
2762 offscreen_target_color_render_buffer_
->Create();
2764 offscreen_target_color_texture_
.reset(new BackTexture(
2765 memory_tracker(), &state_
));
2766 offscreen_target_color_texture_
->Create();
2768 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2769 renderbuffer_manager(), memory_tracker(), &state_
));
2770 offscreen_target_depth_render_buffer_
->Create();
2771 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2772 renderbuffer_manager(), memory_tracker(), &state_
));
2773 offscreen_target_stencil_render_buffer_
->Create();
2775 // Create the saved offscreen texture. The target frame buffer is copied
2776 // here when SwapBuffers is called.
2777 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2778 offscreen_saved_frame_buffer_
->Create();
2780 offscreen_saved_color_texture_
.reset(new BackTexture(
2781 memory_tracker(), &state_
));
2782 offscreen_saved_color_texture_
->Create();
2784 // Allocate the render buffers at their initial size and check the status
2785 // of the frame buffers is okay.
2786 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2787 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2792 state_
.viewport_width
= offscreen_size
.width();
2793 state_
.viewport_height
= offscreen_size
.height();
2795 // Allocate the offscreen saved color texture.
2796 DCHECK(offscreen_saved_color_format_
);
2797 offscreen_saved_color_texture_
->AllocateStorage(
2798 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2800 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2801 offscreen_saved_color_texture_
.get());
2802 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2803 GL_FRAMEBUFFER_COMPLETE
) {
2804 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2809 // Bind to the new default frame buffer (the offscreen target frame buffer).
2810 // This should now be associated with ID zero.
2811 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2813 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2814 // These are NOT if the back buffer has these proprorties. They are
2815 // if we want the command buffer to enforce them regardless of what
2816 // the real backbuffer is assuming the real back buffer gives us more than
2817 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2818 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2819 // can't do anything about that.
2821 if (!surfaceless_
) {
2822 GLint depth_bits
= 0;
2823 GLint stencil_bits
= 0;
2825 bool default_fb
= (GetBackbufferServiceId() == 0);
2827 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2828 glGetFramebufferAttachmentParameterivEXT(
2830 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2831 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2832 glGetFramebufferAttachmentParameterivEXT(
2834 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2835 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2836 glGetFramebufferAttachmentParameterivEXT(
2838 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2839 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2841 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2842 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2843 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2846 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2847 // the user requested RGB then RGB. If the user did not specify a
2848 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2849 back_buffer_color_format_
=
2850 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2851 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2852 back_buffer_has_stencil_
=
2853 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2856 state_
.viewport_width
= surface
->GetSize().width();
2857 state_
.viewport_height
= surface
->GetSize().height();
2860 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2861 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2862 // isn't well documented; it was discovered in the Khronos OpenGL ES
2863 // mailing list archives. It also implicitly enables the desktop GL
2864 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2865 // variable in fragment shaders.
2866 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2867 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2868 glEnable(GL_POINT_SPRITE
);
2871 has_robustness_extension_
=
2872 context
->HasExtension("GL_ARB_robustness") ||
2873 context
->HasExtension("GL_KHR_robustness") ||
2874 context
->HasExtension("GL_EXT_robustness");
2876 if (!InitializeShaderTranslator()) {
2880 GLint viewport_params
[4] = { 0 };
2881 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2882 viewport_max_width_
= viewport_params
[0];
2883 viewport_max_height_
= viewport_params
[1];
2885 state_
.scissor_width
= state_
.viewport_width
;
2886 state_
.scissor_height
= state_
.viewport_height
;
2888 // Set all the default state because some GL drivers get it wrong.
2889 state_
.InitCapabilities(NULL
);
2890 state_
.InitState(NULL
);
2891 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2893 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2894 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2895 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2896 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2897 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2899 bool call_gl_clear
= !surfaceless_
;
2900 #if defined(OS_ANDROID)
2901 // Temporary workaround for Android WebView because this clear ignores the
2902 // clip and corrupts that external UI of the App. Not calling glClear is ok
2903 // because the system already clears the buffer before each draw. Proper
2904 // fix might be setting the scissor clip properly before initialize. See
2905 // crbug.com/259023 for details.
2906 call_gl_clear
= surface_
->GetHandle();
2908 if (call_gl_clear
) {
2909 // On configs where we report no alpha, if the underlying surface has
2910 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2911 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
2913 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2916 // Clear the backbuffer.
2917 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2919 // Restore alpha clear value if we changed it.
2921 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
2925 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2926 if (feature_info_
->workarounds()
2927 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2928 !surface
->IsOffscreen())
2929 supports_post_sub_buffer_
= false;
2931 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2932 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2935 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2936 context_
->SetUnbindFboOnMakeCurrent();
2939 // Only compositor contexts are known to use only the subset of GL
2940 // that can be safely migrated between the iGPU and the dGPU. Mark
2941 // those contexts as safe to forcibly transition between the GPUs.
2942 // http://crbug.com/180876, http://crbug.com/227228
2944 context_
->SetSafeToForceGpuSwitch();
2946 async_pixel_transfer_manager_
.reset(
2947 AsyncPixelTransferManager::Create(context
.get()));
2948 async_pixel_transfer_manager_
->Initialize(texture_manager());
2950 if (workarounds().gl_clear_broken
) {
2951 DCHECK(!clear_framebuffer_blit_
.get());
2952 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2953 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2954 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2958 framebuffer_manager()->AddObserver(this);
2963 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2964 DCHECK(initialized());
2966 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2967 Capabilities::ShaderPrecision
* shader_precision
) {
2968 GLint range
[2] = {0, 0};
2969 GLint precision
= 0;
2970 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2971 shader_precision
->min_range
= range
[0];
2972 shader_precision
->max_range
= range
[1];
2973 shader_precision
->precision
= precision
;
2975 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2976 &caps
.max_combined_texture_image_units
);
2977 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2978 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2979 &caps
.max_fragment_uniform_vectors
);
2980 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2981 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2982 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2983 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2984 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2985 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2986 &caps
.max_vertex_texture_image_units
);
2987 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2988 &caps
.max_vertex_uniform_vectors
);
2989 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2990 &caps
.num_compressed_texture_formats
);
2991 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2992 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2993 &caps
.bind_generates_resource_chromium
);
2994 if (unsafe_es3_apis_enabled()) {
2995 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2996 // but for now we clamp them to 32-bit max.
2997 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
2998 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
2999 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3000 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3001 &caps
.max_combined_fragment_uniform_components
);
3002 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3003 &caps
.max_combined_uniform_blocks
);
3004 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3005 &caps
.max_combined_vertex_uniform_components
);
3006 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3007 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3008 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3009 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3010 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3011 &caps
.max_fragment_input_components
);
3012 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3013 &caps
.max_fragment_uniform_blocks
);
3014 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3015 &caps
.max_fragment_uniform_components
);
3016 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3017 &caps
.max_program_texel_offset
);
3018 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3019 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3021 if (caps
.max_server_wait_timeout
< 0)
3022 caps
.max_server_wait_timeout
= 0;
3023 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3024 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3025 &caps
.max_transform_feedback_interleaved_components
);
3026 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3027 &caps
.max_transform_feedback_separate_attribs
);
3028 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3029 &caps
.max_transform_feedback_separate_components
);
3030 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3031 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3032 &caps
.max_uniform_buffer_bindings
);
3033 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3034 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3035 &caps
.max_vertex_output_components
);
3036 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3037 &caps
.max_vertex_uniform_blocks
);
3038 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3039 &caps
.max_vertex_uniform_components
);
3040 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3041 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3042 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3043 &caps
.num_program_binary_formats
);
3044 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3045 &caps
.uniform_buffer_offset_alignment
);
3046 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3047 caps
.major_version
= 3;
3048 caps
.minor_version
= 0;
3050 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3051 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3052 unsafe_es3_apis_enabled()) {
3053 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3056 caps
.egl_image_external
=
3057 feature_info_
->feature_flags().oes_egl_image_external
;
3058 caps
.texture_format_atc
=
3059 feature_info_
->feature_flags().ext_texture_format_atc
;
3060 caps
.texture_format_bgra8888
=
3061 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3062 caps
.texture_format_dxt1
=
3063 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3064 caps
.texture_format_dxt5
=
3065 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3066 caps
.texture_format_etc1
=
3067 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3068 caps
.texture_format_etc1_npot
=
3069 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3070 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3071 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3072 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3073 caps
.discard_framebuffer
=
3074 feature_info_
->feature_flags().ext_discard_framebuffer
;
3075 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3077 #if defined(OS_MACOSX)
3078 // This is unconditionally true on mac, no need to test for it at runtime.
3079 caps
.iosurface
= true;
3082 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3085 caps
.blend_equation_advanced
=
3086 feature_info_
->feature_flags().blend_equation_advanced
;
3087 caps
.blend_equation_advanced_coherent
=
3088 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3089 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3093 void GLES2DecoderImpl::UpdateCapabilities() {
3094 util_
.set_num_compressed_texture_formats(
3095 validators_
->compressed_texture_format
.GetValues().size());
3096 util_
.set_num_shader_binary_formats(
3097 validators_
->shader_binary_format
.GetValues().size());
3100 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3101 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3103 if (!use_shader_translator_
) {
3106 ShBuiltInResources resources
;
3107 ShInitBuiltInResources(&resources
);
3108 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3109 resources
.MaxVertexUniformVectors
=
3110 group_
->max_vertex_uniform_vectors();
3111 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3112 resources
.MaxVertexTextureImageUnits
=
3113 group_
->max_vertex_texture_image_units();
3114 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3115 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3116 resources
.MaxFragmentUniformVectors
=
3117 group_
->max_fragment_uniform_vectors();
3118 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3119 resources
.MaxExpressionComplexity
= 256;
3120 resources
.MaxCallStackDepth
= 256;
3122 GLint range
[2] = { 0, 0 };
3123 GLint precision
= 0;
3124 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3126 resources
.FragmentPrecisionHigh
=
3127 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3129 if (force_webgl_glsl_validation_
) {
3130 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3131 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3132 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3133 if (!draw_buffers_explicitly_enabled_
)
3134 resources
.MaxDrawBuffers
= 1;
3135 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3136 resources
.NV_draw_buffers
=
3137 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3139 resources
.OES_standard_derivatives
=
3140 features().oes_standard_derivatives
? 1 : 0;
3141 resources
.ARB_texture_rectangle
=
3142 features().arb_texture_rectangle
? 1 : 0;
3143 resources
.OES_EGL_image_external
=
3144 features().oes_egl_image_external
? 1 : 0;
3145 resources
.EXT_draw_buffers
=
3146 features().ext_draw_buffers
? 1 : 0;
3147 resources
.EXT_frag_depth
=
3148 features().ext_frag_depth
? 1 : 0;
3149 resources
.EXT_shader_texture_lod
=
3150 features().ext_shader_texture_lod
? 1 : 0;
3151 resources
.NV_draw_buffers
=
3152 features().nv_draw_buffers
? 1 : 0;
3155 ShShaderSpec shader_spec
;
3156 if (force_webgl_glsl_validation_
) {
3157 shader_spec
= unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3159 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3162 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3163 features().enable_shader_name_hashing
)
3164 resources
.HashFunction
= &CityHash64
;
3166 resources
.HashFunction
= NULL
;
3167 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3168 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3169 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3170 int driver_bug_workarounds
= 0;
3171 if (workarounds().needs_glsl_built_in_function_emulation
)
3172 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3173 if (workarounds().init_gl_position_in_vertex_shader
)
3174 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3175 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3176 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3177 if (workarounds().init_varyings_without_static_use
)
3178 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3179 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3180 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3181 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3182 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3183 if (workarounds().regenerate_struct_names
)
3184 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3186 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3187 switches::kEmulateShaderPrecision
))
3188 resources
.WEBGL_debug_shader_precision
= true;
3190 vertex_translator_
= shader_translator_cache()->GetTranslator(
3194 implementation_type
,
3195 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3196 if (!vertex_translator_
.get()) {
3197 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3202 fragment_translator_
= shader_translator_cache()->GetTranslator(
3206 implementation_type
,
3207 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3208 if (!fragment_translator_
.get()) {
3209 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3216 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3217 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3218 if (GetBuffer(client_ids
[ii
])) {
3222 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3223 glGenBuffersARB(n
, service_ids
.get());
3224 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3225 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3230 bool GLES2DecoderImpl::GenFramebuffersHelper(
3231 GLsizei n
, const GLuint
* client_ids
) {
3232 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3233 if (GetFramebuffer(client_ids
[ii
])) {
3237 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3238 glGenFramebuffersEXT(n
, service_ids
.get());
3239 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3240 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3245 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3246 GLsizei n
, const GLuint
* client_ids
) {
3247 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3248 if (GetRenderbuffer(client_ids
[ii
])) {
3252 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3253 glGenRenderbuffersEXT(n
, service_ids
.get());
3254 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3255 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3260 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3261 const GLuint
* client_ids
) {
3262 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3263 if (GetValuebuffer(client_ids
[ii
])) {
3267 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3268 CreateValuebuffer(client_ids
[ii
]);
3273 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3274 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3275 if (GetTexture(client_ids
[ii
])) {
3279 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3280 glGenTextures(n
, service_ids
.get());
3281 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3282 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3287 void GLES2DecoderImpl::DeleteBuffersHelper(
3288 GLsizei n
, const GLuint
* client_ids
) {
3289 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3290 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3291 if (buffer
&& !buffer
->IsDeleted()) {
3292 buffer
->RemoveMappedRange();
3293 state_
.RemoveBoundBuffer(buffer
);
3294 RemoveBuffer(client_ids
[ii
]);
3299 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3300 GLsizei n
, const GLuint
* client_ids
) {
3301 bool supports_separate_framebuffer_binds
=
3302 features().chromium_framebuffer_multisample
;
3304 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3305 Framebuffer
* framebuffer
=
3306 GetFramebuffer(client_ids
[ii
]);
3307 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3308 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3309 GLenum target
= supports_separate_framebuffer_binds
?
3310 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3312 // Unbind attachments on FBO before deletion.
3313 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3314 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3316 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3317 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3318 framebuffer_state_
.clear_state_dirty
= true;
3320 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3321 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3322 GLenum target
= supports_separate_framebuffer_binds
?
3323 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3324 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3327 RemoveFramebuffer(client_ids
[ii
]);
3332 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3333 GLsizei n
, const GLuint
* client_ids
) {
3334 bool supports_separate_framebuffer_binds
=
3335 features().chromium_framebuffer_multisample
;
3336 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3337 Renderbuffer
* renderbuffer
=
3338 GetRenderbuffer(client_ids
[ii
]);
3339 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3340 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3341 state_
.bound_renderbuffer
= NULL
;
3343 // Unbind from current framebuffers.
3344 if (supports_separate_framebuffer_binds
) {
3345 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3346 framebuffer_state_
.bound_read_framebuffer
3347 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3349 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3350 framebuffer_state_
.bound_draw_framebuffer
3351 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3354 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3355 framebuffer_state_
.bound_draw_framebuffer
3356 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3359 framebuffer_state_
.clear_state_dirty
= true;
3360 RemoveRenderbuffer(client_ids
[ii
]);
3365 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3367 const GLuint
* client_ids
) {
3368 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3369 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3371 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3372 state_
.bound_valuebuffer
= NULL
;
3374 RemoveValuebuffer(client_ids
[ii
]);
3379 void GLES2DecoderImpl::DeleteTexturesHelper(
3380 GLsizei n
, const GLuint
* client_ids
) {
3381 bool supports_separate_framebuffer_binds
=
3382 features().chromium_framebuffer_multisample
;
3383 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3384 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3386 Texture
* texture
= texture_ref
->texture();
3387 if (texture
->IsAttachedToFramebuffer()) {
3388 framebuffer_state_
.clear_state_dirty
= true;
3390 // Unbind texture_ref from texture_ref units.
3391 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3392 state_
.texture_units
[jj
].Unbind(texture_ref
);
3394 // Unbind from current framebuffers.
3395 if (supports_separate_framebuffer_binds
) {
3396 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3397 framebuffer_state_
.bound_read_framebuffer
3398 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3400 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3401 framebuffer_state_
.bound_draw_framebuffer
3402 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3405 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3406 framebuffer_state_
.bound_draw_framebuffer
3407 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3410 #if defined(OS_MACOSX)
3411 GLuint service_id
= texture
->service_id();
3412 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3413 ReleaseIOSurfaceForTexture(service_id
);
3416 RemoveTexture(client_ids
[ii
]);
3421 // } // anonymous namespace
3423 bool GLES2DecoderImpl::MakeCurrent() {
3424 if (!context_
.get())
3427 if (WasContextLost()) {
3428 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3432 if (!context_
->MakeCurrent(surface_
.get())) {
3433 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3434 MarkContextLost(error::kMakeCurrentFailed
);
3435 group_
->LoseContexts(error::kUnknown
);
3439 if (CheckResetStatus()) {
3441 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3442 group_
->LoseContexts(error::kUnknown
);
3446 ProcessFinishedAsyncTransfers();
3448 // Rebind the FBO if it was unbound by the context.
3449 if (workarounds().unbind_fbo_on_context_switch
)
3450 RestoreFramebufferBindings();
3452 framebuffer_state_
.clear_state_dirty
= true;
3457 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3458 ProcessPendingReadPixels();
3459 if (engine() && query_manager_
.get())
3460 query_manager_
->ProcessPendingTransferQueries();
3462 // TODO(epenner): Is there a better place to do this?
3463 // This needs to occur before we execute any batch of commands
3464 // from the client, as the client may have recieved an async
3465 // completion while issuing those commands.
3466 // "DidFlushStart" would be ideal if we had such a callback.
3467 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3470 static void RebindCurrentFramebuffer(
3472 Framebuffer
* framebuffer
,
3473 GLuint back_buffer_service_id
) {
3474 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3476 if (framebuffer_id
== 0) {
3477 framebuffer_id
= back_buffer_service_id
;
3480 glBindFramebufferEXT(target
, framebuffer_id
);
3483 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3484 framebuffer_state_
.clear_state_dirty
= true;
3486 if (!features().chromium_framebuffer_multisample
) {
3487 RebindCurrentFramebuffer(
3489 framebuffer_state_
.bound_draw_framebuffer
.get(),
3490 GetBackbufferServiceId());
3492 RebindCurrentFramebuffer(
3493 GL_READ_FRAMEBUFFER_EXT
,
3494 framebuffer_state_
.bound_read_framebuffer
.get(),
3495 GetBackbufferServiceId());
3496 RebindCurrentFramebuffer(
3497 GL_DRAW_FRAMEBUFFER_EXT
,
3498 framebuffer_state_
.bound_draw_framebuffer
.get(),
3499 GetBackbufferServiceId());
3504 bool GLES2DecoderImpl::CheckFramebufferValid(
3505 Framebuffer
* framebuffer
,
3506 GLenum target
, const char* func_name
) {
3510 if (backbuffer_needs_clear_bits_
) {
3511 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3512 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3513 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3515 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3516 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3518 state_
.SetDeviceDepthMask(GL_TRUE
);
3519 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3520 bool reset_draw_buffer
= false;
3521 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3522 group_
->draw_buffer() == GL_NONE
) {
3523 reset_draw_buffer
= true;
3524 GLenum buf
= GL_BACK
;
3525 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3526 buf
= GL_COLOR_ATTACHMENT0
;
3527 glDrawBuffersARB(1, &buf
);
3529 glClear(backbuffer_needs_clear_bits_
);
3530 if (reset_draw_buffer
) {
3531 GLenum buf
= GL_NONE
;
3532 glDrawBuffersARB(1, &buf
);
3534 backbuffer_needs_clear_bits_
= 0;
3535 RestoreClearState();
3540 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3544 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3545 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3547 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3551 // Are all the attachments cleared?
3552 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3553 texture_manager()->HaveUnclearedMips()) {
3554 if (!framebuffer
->IsCleared()) {
3555 // Can we clear them?
3556 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3557 GL_FRAMEBUFFER_COMPLETE
) {
3559 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3560 "framebuffer incomplete (clear)");
3563 ClearUnclearedAttachments(target
, framebuffer
);
3567 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3568 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3569 GL_FRAMEBUFFER_COMPLETE
) {
3571 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3572 "framebuffer incomplete (check)");
3575 framebuffer_manager()->MarkAsComplete(framebuffer
);
3578 // NOTE: At this point we don't know if the framebuffer is complete but
3579 // we DO know that everything that needs to be cleared has been cleared.
3583 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3584 if (!features().chromium_framebuffer_multisample
) {
3585 bool valid
= CheckFramebufferValid(
3586 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3594 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3595 GL_DRAW_FRAMEBUFFER_EXT
,
3597 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3598 GL_READ_FRAMEBUFFER_EXT
,
3602 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3603 const char* func_name
) {
3604 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3605 framebuffer_state_
.bound_read_framebuffer
.get() :
3606 framebuffer_state_
.bound_draw_framebuffer
.get();
3609 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3611 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3617 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3618 TextureRef
* texture
, GLint level
) {
3619 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3620 framebuffer_state_
.bound_read_framebuffer
.get() :
3621 framebuffer_state_
.bound_draw_framebuffer
.get();
3624 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3625 GL_COLOR_ATTACHMENT0
);
3628 return attachment
->FormsFeedbackLoop(texture
, level
);
3631 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3632 Framebuffer
* framebuffer
=
3633 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3634 if (framebuffer
!= NULL
) {
3635 const Framebuffer::Attachment
* attachment
=
3636 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3638 return gfx::Size(attachment
->width(), attachment
->height());
3640 return gfx::Size(0, 0);
3641 } else if (offscreen_target_frame_buffer_
.get()) {
3642 return offscreen_size_
;
3644 return surface_
->GetSize();
3648 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3649 Framebuffer
* framebuffer
=
3650 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3651 if (framebuffer
!= NULL
) {
3652 return framebuffer
->GetColorAttachmentTextureType();
3654 return GL_UNSIGNED_BYTE
;
3658 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3659 Framebuffer
* framebuffer
=
3660 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3661 if (framebuffer
!= NULL
) {
3662 return framebuffer
->GetColorAttachmentFormat();
3663 } else if (offscreen_target_frame_buffer_
.get()) {
3664 return offscreen_target_color_format_
;
3666 return back_buffer_color_format_
;
3670 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3671 Framebuffer
* framebuffer
=
3672 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3673 if (framebuffer
!= NULL
) {
3674 return framebuffer
->GetColorAttachmentFormat();
3675 } else if (offscreen_target_frame_buffer_
.get()) {
3676 return offscreen_target_color_format_
;
3678 return back_buffer_color_format_
;
3682 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3683 if (!offscreen_saved_color_texture_info_
.get())
3685 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3686 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3687 texture_manager()->SetLevelInfo(
3688 offscreen_saved_color_texture_info_
.get(),
3692 offscreen_size_
.width(),
3693 offscreen_size_
.height(),
3699 texture_manager()->SetParameteri(
3700 "UpdateParentTextureInfo",
3702 offscreen_saved_color_texture_info_
.get(),
3703 GL_TEXTURE_MAG_FILTER
,
3705 texture_manager()->SetParameteri(
3706 "UpdateParentTextureInfo",
3708 offscreen_saved_color_texture_info_
.get(),
3709 GL_TEXTURE_MIN_FILTER
,
3711 texture_manager()->SetParameteri(
3712 "UpdateParentTextureInfo",
3714 offscreen_saved_color_texture_info_
.get(),
3717 texture_manager()->SetParameteri(
3718 "UpdateParentTextureInfo",
3720 offscreen_saved_color_texture_info_
.get(),
3723 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3725 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3728 void GLES2DecoderImpl::SetResizeCallback(
3729 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3730 resize_callback_
= callback
;
3733 Logger
* GLES2DecoderImpl::GetLogger() {
3737 void GLES2DecoderImpl::BeginDecoding() {
3738 gpu_tracer_
->BeginDecoding();
3739 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3740 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3741 (*cb_command_trace_category_
!= 0);
3744 void GLES2DecoderImpl::EndDecoding() {
3745 gpu_tracer_
->EndDecoding();
3748 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3749 return state_
.GetErrorState();
3752 void GLES2DecoderImpl::SetShaderCacheCallback(
3753 const ShaderCacheCallback
& callback
) {
3754 shader_cache_callback_
= callback
;
3757 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3758 const WaitSyncPointCallback
& callback
) {
3759 wait_sync_point_callback_
= callback
;
3762 AsyncPixelTransferManager
*
3763 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3764 return async_pixel_transfer_manager_
.get();
3767 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3768 async_pixel_transfer_manager_
.reset();
3771 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3772 AsyncPixelTransferManager
* manager
) {
3773 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3776 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3777 uint32
* service_texture_id
) {
3778 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3780 *service_texture_id
= texture_ref
->service_id();
3786 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3787 return texture_state_
.texture_upload_count
+
3788 async_pixel_transfer_manager_
->GetTextureUploadCount();
3791 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3792 return texture_state_
.total_texture_upload_time
+
3793 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3796 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3797 return total_processing_commands_time_
;
3800 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3801 total_processing_commands_time_
+= time
;
3804 void GLES2DecoderImpl::Destroy(bool have_context
) {
3808 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3810 // Unbind everything.
3811 state_
.vertex_attrib_manager
= NULL
;
3812 state_
.default_vertex_attrib_manager
= NULL
;
3813 state_
.texture_units
.clear();
3814 state_
.bound_array_buffer
= NULL
;
3815 state_
.bound_copy_read_buffer
= NULL
;
3816 state_
.bound_copy_write_buffer
= NULL
;
3817 state_
.bound_pixel_pack_buffer
= NULL
;
3818 state_
.bound_pixel_unpack_buffer
= NULL
;
3819 state_
.bound_transform_feedback_buffer
= NULL
;
3820 state_
.bound_uniform_buffer
= NULL
;
3821 state_
.current_queries
.clear();
3822 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3823 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3824 state_
.bound_renderbuffer
= NULL
;
3825 state_
.bound_valuebuffer
= NULL
;
3827 if (offscreen_saved_color_texture_info_
.get()) {
3828 DCHECK(offscreen_target_color_texture_
);
3829 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3830 offscreen_saved_color_texture_
->id());
3831 offscreen_saved_color_texture_
->Invalidate();
3832 offscreen_saved_color_texture_info_
= NULL
;
3835 if (copy_texture_CHROMIUM_
.get()) {
3836 copy_texture_CHROMIUM_
->Destroy();
3837 copy_texture_CHROMIUM_
.reset();
3840 clear_framebuffer_blit_
.reset();
3842 if (state_
.current_program
.get()) {
3843 program_manager()->UnuseProgram(shader_manager(),
3844 state_
.current_program
.get());
3847 if (attrib_0_buffer_id_
) {
3848 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3850 if (fixed_attrib_buffer_id_
) {
3851 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3854 if (validation_texture_
) {
3855 glDeleteTextures(1, &validation_texture_
);
3856 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3857 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3860 if (offscreen_target_frame_buffer_
.get())
3861 offscreen_target_frame_buffer_
->Destroy();
3862 if (offscreen_target_color_texture_
.get())
3863 offscreen_target_color_texture_
->Destroy();
3864 if (offscreen_target_color_render_buffer_
.get())
3865 offscreen_target_color_render_buffer_
->Destroy();
3866 if (offscreen_target_depth_render_buffer_
.get())
3867 offscreen_target_depth_render_buffer_
->Destroy();
3868 if (offscreen_target_stencil_render_buffer_
.get())
3869 offscreen_target_stencil_render_buffer_
->Destroy();
3870 if (offscreen_saved_frame_buffer_
.get())
3871 offscreen_saved_frame_buffer_
->Destroy();
3872 if (offscreen_saved_color_texture_
.get())
3873 offscreen_saved_color_texture_
->Destroy();
3874 if (offscreen_resolved_frame_buffer_
.get())
3875 offscreen_resolved_frame_buffer_
->Destroy();
3876 if (offscreen_resolved_color_texture_
.get())
3877 offscreen_resolved_color_texture_
->Destroy();
3879 if (offscreen_target_frame_buffer_
.get())
3880 offscreen_target_frame_buffer_
->Invalidate();
3881 if (offscreen_target_color_texture_
.get())
3882 offscreen_target_color_texture_
->Invalidate();
3883 if (offscreen_target_color_render_buffer_
.get())
3884 offscreen_target_color_render_buffer_
->Invalidate();
3885 if (offscreen_target_depth_render_buffer_
.get())
3886 offscreen_target_depth_render_buffer_
->Invalidate();
3887 if (offscreen_target_stencil_render_buffer_
.get())
3888 offscreen_target_stencil_render_buffer_
->Invalidate();
3889 if (offscreen_saved_frame_buffer_
.get())
3890 offscreen_saved_frame_buffer_
->Invalidate();
3891 if (offscreen_saved_color_texture_
.get())
3892 offscreen_saved_color_texture_
->Invalidate();
3893 if (offscreen_resolved_frame_buffer_
.get())
3894 offscreen_resolved_frame_buffer_
->Invalidate();
3895 if (offscreen_resolved_color_texture_
.get())
3896 offscreen_resolved_color_texture_
->Invalidate();
3899 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3900 // Otherwise, we can leak objects. http://crbug.com/258772.
3901 // state_.current_program must be reset before group_ is reset because
3902 // the later deletes the ProgramManager object that referred by
3903 // state_.current_program object.
3904 state_
.current_program
= NULL
;
3906 copy_texture_CHROMIUM_
.reset();
3907 clear_framebuffer_blit_
.reset();
3909 if (query_manager_
.get()) {
3910 query_manager_
->Destroy(have_context
);
3911 query_manager_
.reset();
3914 if (vertex_array_manager_
.get()) {
3915 vertex_array_manager_
->Destroy(have_context
);
3916 vertex_array_manager_
.reset();
3919 if (image_manager_
.get()) {
3920 image_manager_
->Destroy(have_context
);
3921 image_manager_
.reset();
3924 offscreen_target_frame_buffer_
.reset();
3925 offscreen_target_color_texture_
.reset();
3926 offscreen_target_color_render_buffer_
.reset();
3927 offscreen_target_depth_render_buffer_
.reset();
3928 offscreen_target_stencil_render_buffer_
.reset();
3929 offscreen_saved_frame_buffer_
.reset();
3930 offscreen_saved_color_texture_
.reset();
3931 offscreen_resolved_frame_buffer_
.reset();
3932 offscreen_resolved_color_texture_
.reset();
3934 // Need to release these before releasing |group_| which may own the
3935 // ShaderTranslatorCache.
3936 fragment_translator_
= NULL
;
3937 vertex_translator_
= NULL
;
3939 // Should destroy the transfer manager before the texture manager held
3940 // by the context group.
3941 async_pixel_transfer_manager_
.reset();
3943 // Destroy the GPU Tracer which may own some in process GPU Timings.
3945 gpu_tracer_
->Destroy(have_context
);
3946 gpu_tracer_
.reset();
3950 framebuffer_manager()->RemoveObserver(this);
3951 group_
->Destroy(this, have_context
);
3955 if (context_
.get()) {
3956 context_
->ReleaseCurrent(NULL
);
3960 #if defined(OS_MACOSX)
3961 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3962 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3963 CFRelease(it
->second
);
3965 texture_to_io_surface_map_
.clear();
3969 void GLES2DecoderImpl::SetSurface(
3970 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3971 DCHECK(context_
->IsCurrent(NULL
));
3972 DCHECK(surface_
.get());
3974 RestoreCurrentFramebufferBindings();
3977 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3978 if (!offscreen_saved_color_texture_
.get()) {
3979 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3982 if (!offscreen_saved_color_texture_info_
.get()) {
3983 GLuint service_id
= offscreen_saved_color_texture_
->id();
3984 offscreen_saved_color_texture_info_
= TextureRef::Create(
3985 texture_manager(), 0, service_id
);
3986 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3988 UpdateParentTextureInfo();
3990 mailbox_manager()->ProduceTexture(
3991 mailbox
, offscreen_saved_color_texture_info_
->texture());
3994 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3995 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3996 if (!is_offscreen
) {
3997 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3998 << " with an onscreen framebuffer.";
4002 if (offscreen_size_
== size
)
4005 offscreen_size_
= size
;
4006 int w
= offscreen_size_
.width();
4007 int h
= offscreen_size_
.height();
4008 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4009 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4010 << "to allocate storage due to excessive dimensions.";
4014 // Reallocate the offscreen target buffers.
4015 DCHECK(offscreen_target_color_format_
);
4016 if (IsOffscreenBufferMultisampled()) {
4017 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4018 feature_info_
.get(),
4020 offscreen_target_color_format_
,
4021 offscreen_target_samples_
)) {
4022 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4023 << "to allocate storage for offscreen target color buffer.";
4027 if (!offscreen_target_color_texture_
->AllocateStorage(
4028 offscreen_size_
, offscreen_target_color_format_
, false)) {
4029 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4030 << "to allocate storage for offscreen target color texture.";
4034 if (offscreen_target_depth_format_
&&
4035 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4036 feature_info_
.get(),
4038 offscreen_target_depth_format_
,
4039 offscreen_target_samples_
)) {
4040 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4041 << "to allocate storage for offscreen target depth buffer.";
4044 if (offscreen_target_stencil_format_
&&
4045 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4046 feature_info_
.get(),
4048 offscreen_target_stencil_format_
,
4049 offscreen_target_samples_
)) {
4050 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4051 << "to allocate storage for offscreen target stencil buffer.";
4055 // Attach the offscreen target buffers to the target frame buffer.
4056 if (IsOffscreenBufferMultisampled()) {
4057 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4058 GL_COLOR_ATTACHMENT0
,
4059 offscreen_target_color_render_buffer_
.get());
4061 offscreen_target_frame_buffer_
->AttachRenderTexture(
4062 offscreen_target_color_texture_
.get());
4064 if (offscreen_target_depth_format_
) {
4065 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4066 GL_DEPTH_ATTACHMENT
,
4067 offscreen_target_depth_render_buffer_
.get());
4069 const bool packed_depth_stencil
=
4070 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4071 if (packed_depth_stencil
) {
4072 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4073 GL_STENCIL_ATTACHMENT
,
4074 offscreen_target_depth_render_buffer_
.get());
4075 } else if (offscreen_target_stencil_format_
) {
4076 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4077 GL_STENCIL_ATTACHMENT
,
4078 offscreen_target_stencil_render_buffer_
.get());
4081 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4082 GL_FRAMEBUFFER_COMPLETE
) {
4083 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4084 << "because offscreen FBO was incomplete.";
4088 // Clear the target frame buffer.
4090 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4091 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4092 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4093 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4095 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4096 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4098 state_
.SetDeviceDepthMask(GL_TRUE
);
4099 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4100 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4101 RestoreClearState();
4104 // Destroy the offscreen resolved framebuffers.
4105 if (offscreen_resolved_frame_buffer_
.get())
4106 offscreen_resolved_frame_buffer_
->Destroy();
4107 if (offscreen_resolved_color_texture_
.get())
4108 offscreen_resolved_color_texture_
->Destroy();
4109 offscreen_resolved_color_texture_
.reset();
4110 offscreen_resolved_frame_buffer_
.reset();
4115 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4116 const void* cmd_data
) {
4117 const gles2::cmds::ResizeCHROMIUM
& c
=
4118 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4119 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4120 return error::kDeferCommandUntilLater
;
4122 GLuint width
= static_cast<GLuint
>(c
.width
);
4123 GLuint height
= static_cast<GLuint
>(c
.height
);
4124 GLfloat scale_factor
= c
.scale_factor
;
4125 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4127 width
= std::max(1U, width
);
4128 height
= std::max(1U, height
);
4130 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4131 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4132 // Make sure that we are done drawing to the back buffer before resizing.
4135 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4137 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4138 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4139 << "ResizeOffscreenFrameBuffer failed.";
4140 return error::kLostContext
;
4144 if (!resize_callback_
.is_null()) {
4145 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4146 DCHECK(context_
->IsCurrent(surface_
.get()));
4147 if (!context_
->IsCurrent(surface_
.get())) {
4148 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4149 << "current after resize callback.";
4150 return error::kLostContext
;
4154 return error::kNoError
;
4157 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4158 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4159 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4161 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4164 // Decode a command, and call the corresponding GL functions.
4165 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4166 // of commands at once, and is now only used for tests that need to track
4167 // individual commands.
4168 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4169 unsigned int arg_count
,
4170 const void* cmd_data
) {
4171 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4174 // Decode multiple commands, and call the corresponding GL functions.
4175 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4176 // changed by a (malicious) client at any time, so if validation has to happen,
4177 // it should operate on a copy of them.
4178 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4179 // interest of performance in this critical execution loop.
4180 template <bool DebugImpl
>
4181 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4184 int* entries_processed
) {
4185 commands_to_process_
= num_commands
;
4186 error::Error result
= error::kNoError
;
4187 const CommandBufferEntry
* cmd_data
=
4188 static_cast<const CommandBufferEntry
*>(buffer
);
4189 int process_pos
= 0;
4190 unsigned int command
= 0;
4192 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4193 commands_to_process_
--) {
4194 const unsigned int size
= cmd_data
->value_header
.size
;
4195 command
= cmd_data
->value_header
.command
;
4198 result
= error::kInvalidSize
;
4202 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4203 result
= error::kOutOfBounds
;
4208 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4209 GetCommandName(command
));
4211 if (log_commands()) {
4212 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4213 << "cmd: " << GetCommandName(command
);
4217 const unsigned int arg_count
= size
- 1;
4218 unsigned int command_index
= command
- kStartPoint
- 1;
4219 if (command_index
< arraysize(command_info
)) {
4220 const CommandInfo
& info
= command_info
[command_index
];
4221 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4222 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4223 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4224 bool doing_gpu_trace
= false;
4225 if (DebugImpl
&& gpu_trace_commands_
) {
4226 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4227 doing_gpu_trace
= true;
4228 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4229 GetCommandName(command
),
4234 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4235 sizeof(CommandBufferEntry
); // NOLINT
4237 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4239 if (DebugImpl
&& doing_gpu_trace
)
4240 gpu_tracer_
->End(kTraceDecoder
);
4242 if (DebugImpl
&& debug()) {
4244 while ((error
= glGetError()) != GL_NO_ERROR
) {
4245 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4246 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4247 << " : " << GetCommandName(command
);
4248 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4252 result
= error::kInvalidArguments
;
4255 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4259 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4260 GetCommandName(command
));
4263 if (result
== error::kNoError
&&
4264 current_decoder_error_
!= error::kNoError
) {
4265 result
= current_decoder_error_
;
4266 current_decoder_error_
= error::kNoError
;
4269 if (result
!= error::kDeferCommandUntilLater
) {
4270 process_pos
+= size
;
4275 if (entries_processed
)
4276 *entries_processed
= process_pos
;
4278 if (error::IsError(result
)) {
4279 LOG(ERROR
) << "Error: " << result
<< " for Command "
4280 << GetCommandName(command
);
4286 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4289 int* entries_processed
) {
4290 if (gpu_debug_commands_
) {
4291 return DoCommandsImpl
<true>(
4292 num_commands
, buffer
, num_entries
, entries_processed
);
4294 return DoCommandsImpl
<false>(
4295 num_commands
, buffer
, num_entries
, entries_processed
);
4299 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4300 buffer_manager()->RemoveBuffer(client_id
);
4303 void GLES2DecoderImpl::DoFinish() {
4305 ProcessPendingReadPixels();
4306 ProcessPendingQueries(true);
4309 void GLES2DecoderImpl::DoFlush() {
4311 ProcessPendingQueries(false);
4314 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4315 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4316 if (texture_index
>= state_
.texture_units
.size()) {
4317 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4318 "glActiveTexture", texture_unit
, "texture_unit");
4321 state_
.active_texture_unit
= texture_index
;
4322 glActiveTexture(texture_unit
);
4325 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4326 Buffer
* buffer
= NULL
;
4327 GLuint service_id
= 0;
4328 if (client_id
!= 0) {
4329 buffer
= GetBuffer(client_id
);
4331 if (!group_
->bind_generates_resource()) {
4332 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4334 "id not generated by glGenBuffers");
4338 // It's a new id so make a buffer buffer for it.
4339 glGenBuffersARB(1, &service_id
);
4340 CreateBuffer(client_id
, service_id
);
4341 buffer
= GetBuffer(client_id
);
4344 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4346 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4348 GL_INVALID_OPERATION
,
4349 "glBindBuffer", "buffer bound to more than 1 target");
4352 service_id
= buffer
->service_id();
4354 state_
.SetBoundBuffer(target
, buffer
);
4355 glBindBuffer(target
, service_id
);
4358 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4359 bool all_draw_buffers
) {
4360 Framebuffer
* framebuffer
=
4361 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4362 if (!all_draw_buffers
|| !framebuffer
) {
4363 return (GLES2Util::GetChannelsForFormat(
4364 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4366 return framebuffer
->HasAlphaMRT();
4369 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4370 Framebuffer
* framebuffer
=
4371 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4373 return framebuffer
->HasDepthAttachment();
4375 if (offscreen_target_frame_buffer_
.get()) {
4376 return offscreen_target_depth_format_
!= 0;
4378 return back_buffer_has_depth_
;
4381 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4382 Framebuffer
* framebuffer
=
4383 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4385 return framebuffer
->HasStencilAttachment();
4387 if (offscreen_target_frame_buffer_
.get()) {
4388 return offscreen_target_stencil_format_
!= 0 ||
4389 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4391 return back_buffer_has_stencil_
;
4394 void GLES2DecoderImpl::ApplyDirtyState() {
4395 if (framebuffer_state_
.clear_state_dirty
) {
4396 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4397 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4398 state_
.color_mask_green
,
4399 state_
.color_mask_blue
,
4400 state_
.color_mask_alpha
&& have_alpha
);
4402 bool have_depth
= BoundFramebufferHasDepthAttachment();
4403 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4405 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4406 state_
.SetDeviceStencilMaskSeparate(
4407 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4408 state_
.SetDeviceStencilMaskSeparate(
4409 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4411 state_
.SetDeviceCapabilityState(
4412 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4413 state_
.SetDeviceCapabilityState(
4414 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4415 framebuffer_state_
.clear_state_dirty
= false;
4419 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4420 return (offscreen_target_frame_buffer_
.get())
4421 ? offscreen_target_frame_buffer_
->id()
4422 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4425 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4426 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4427 "context", logger_
.GetLogPrefix());
4428 // Restore the Framebuffer first because of bugs in Intel drivers.
4429 // Intel drivers incorrectly clip the viewport settings to
4430 // the size of the current framebuffer object.
4431 RestoreFramebufferBindings();
4432 state_
.RestoreState(prev_state
);
4435 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4437 framebuffer_state_
.bound_draw_framebuffer
.get()
4438 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4439 : GetBackbufferServiceId();
4440 if (!features().chromium_framebuffer_multisample
) {
4441 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4443 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4444 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4445 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4446 : GetBackbufferServiceId();
4447 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4452 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4453 state_
.RestoreRenderbufferBindings();
4456 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4457 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4459 GLenum target
= texture
->target();
4460 glBindTexture(target
, service_id
);
4462 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4464 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4466 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4468 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4469 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4473 void GLES2DecoderImpl::ClearAllAttributes() const {
4474 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4476 if (feature_info_
->feature_flags().native_vertex_array_object
)
4477 glBindVertexArrayOES(0);
4479 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4480 if (i
!= 0) // Never disable attribute 0
4481 glDisableVertexAttribArray(i
);
4482 if (features().angle_instanced_arrays
)
4483 glVertexAttribDivisorANGLE(i
, 0);
4487 void GLES2DecoderImpl::RestoreAllAttributes() const {
4488 state_
.RestoreVertexAttribs();
4491 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4492 state_
.SetIgnoreCachedStateForTest(ignore
);
4495 void GLES2DecoderImpl::OnFboChanged() const {
4496 if (workarounds().restore_scissor_on_fbo_change
)
4497 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4499 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4500 GLint bound_fbo_unsigned
= -1;
4501 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4502 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4503 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4504 surface_
->NotifyWasBound();
4508 // Called after the FBO is checked for completeness.
4509 void GLES2DecoderImpl::OnUseFramebuffer() const {
4510 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4511 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4512 // The driver forgets the correct scissor when modifying the FBO binding.
4513 glScissor(state_
.scissor_x
,
4515 state_
.scissor_width
,
4516 state_
.scissor_height
);
4518 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4519 // it's unclear how this bug works.
4524 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4525 Framebuffer
* framebuffer
= NULL
;
4526 GLuint service_id
= 0;
4527 if (client_id
!= 0) {
4528 framebuffer
= GetFramebuffer(client_id
);
4530 if (!group_
->bind_generates_resource()) {
4531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4532 "glBindFramebuffer",
4533 "id not generated by glGenFramebuffers");
4537 // It's a new id so make a framebuffer framebuffer for it.
4538 glGenFramebuffersEXT(1, &service_id
);
4539 CreateFramebuffer(client_id
, service_id
);
4540 framebuffer
= GetFramebuffer(client_id
);
4542 service_id
= framebuffer
->service_id();
4544 framebuffer
->MarkAsValid();
4546 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4548 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4549 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4552 // vmiura: This looks like dup code
4553 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4554 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4557 framebuffer_state_
.clear_state_dirty
= true;
4559 // If we are rendering to the backbuffer get the FBO id for any simulated
4561 if (framebuffer
== NULL
) {
4562 service_id
= GetBackbufferServiceId();
4565 glBindFramebufferEXT(target
, service_id
);
4569 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4570 Renderbuffer
* renderbuffer
= NULL
;
4571 GLuint service_id
= 0;
4572 if (client_id
!= 0) {
4573 renderbuffer
= GetRenderbuffer(client_id
);
4574 if (!renderbuffer
) {
4575 if (!group_
->bind_generates_resource()) {
4576 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4577 "glBindRenderbuffer",
4578 "id not generated by glGenRenderbuffers");
4582 // It's a new id so make a renderbuffer for it.
4583 glGenRenderbuffersEXT(1, &service_id
);
4584 CreateRenderbuffer(client_id
, service_id
);
4585 renderbuffer
= GetRenderbuffer(client_id
);
4587 service_id
= renderbuffer
->service_id();
4589 renderbuffer
->MarkAsValid();
4591 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4592 state_
.bound_renderbuffer
= renderbuffer
;
4593 state_
.bound_renderbuffer_valid
= true;
4594 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4597 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4598 TextureRef
* texture_ref
= NULL
;
4599 GLuint service_id
= 0;
4600 if (client_id
!= 0) {
4601 texture_ref
= GetTexture(client_id
);
4603 if (!group_
->bind_generates_resource()) {
4604 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4606 "id not generated by glGenTextures");
4610 // It's a new id so make a texture texture for it.
4611 glGenTextures(1, &service_id
);
4612 DCHECK_NE(0u, service_id
);
4613 CreateTexture(client_id
, service_id
);
4614 texture_ref
= GetTexture(client_id
);
4617 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4620 // Check the texture exists
4622 Texture
* texture
= texture_ref
->texture();
4623 // Check that we are not trying to bind it to a different target.
4624 if (texture
->target() != 0 && texture
->target() != target
) {
4625 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4627 "texture bound to more than 1 target.");
4630 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4631 if (texture
->target() == 0) {
4632 texture_manager()->SetTarget(texture_ref
, target
);
4634 glBindTexture(target
, texture
->service_id());
4636 glBindTexture(target
, 0);
4639 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4640 unit
.bind_target
= target
;
4643 unit
.bound_texture_2d
= texture_ref
;
4645 case GL_TEXTURE_CUBE_MAP
:
4646 unit
.bound_texture_cube_map
= texture_ref
;
4648 case GL_TEXTURE_EXTERNAL_OES
:
4649 unit
.bound_texture_external_oes
= texture_ref
;
4651 case GL_TEXTURE_RECTANGLE_ARB
:
4652 unit
.bound_texture_rectangle_arb
= texture_ref
;
4655 unit
.bound_texture_3d
= texture_ref
;
4657 case GL_TEXTURE_2D_ARRAY
:
4658 unit
.bound_texture_2d_array
= texture_ref
;
4661 NOTREACHED(); // Validation should prevent us getting here.
4666 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4667 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4669 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4670 glDisableVertexAttribArray(index
);
4675 "glDisableVertexAttribArray", "index out of range");
4679 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4680 GLsizei numAttachments
,
4681 const GLenum
* attachments
) {
4682 if (workarounds().disable_discard_framebuffer
)
4685 Framebuffer
* framebuffer
=
4686 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4688 // Validates the attachments. If one of them fails
4689 // the whole command fails.
4690 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4692 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4694 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4695 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4696 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4701 // Marks each one of them as not cleared
4702 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4704 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4709 switch (attachments
[i
]) {
4711 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4714 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4715 case GL_STENCIL_EXT
:
4716 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4725 // If the default framebuffer is bound but we are still rendering to an
4726 // FBO, translate attachment names that refer to default framebuffer
4727 // channels to corresponding framebuffer attachments.
4728 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4729 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4730 GLenum attachment
= attachments
[i
];
4731 if (!framebuffer
&& GetBackbufferServiceId()) {
4732 switch (attachment
) {
4734 attachment
= GL_COLOR_ATTACHMENT0
;
4737 attachment
= GL_DEPTH_ATTACHMENT
;
4739 case GL_STENCIL_EXT
:
4740 attachment
= GL_STENCIL_ATTACHMENT
;
4747 translated_attachments
[i
] = attachment
;
4750 ScopedRenderTo
do_render(framebuffer
);
4751 if (feature_info_
->gl_version_info().is_es3
) {
4752 glInvalidateFramebuffer(
4753 target
, numAttachments
, translated_attachments
.get());
4755 glDiscardFramebufferEXT(
4756 target
, numAttachments
, translated_attachments
.get());
4760 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4761 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4762 glEnableVertexAttribArray(index
);
4765 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4769 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4770 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4773 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4775 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4779 if (target
== GL_TEXTURE_CUBE_MAP
) {
4780 for (int i
= 0; i
< 6; ++i
) {
4781 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4782 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4784 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4789 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4791 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4796 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4797 // Workaround for Mac driver bug. In the large scheme of things setting
4798 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4799 // hit so there's probably no need to make this conditional. The bug appears
4800 // to be that if the filtering mode is set to something that doesn't require
4801 // mipmaps for rendering, or is never set to something other than the default,
4802 // then glGenerateMipmap misbehaves.
4803 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4804 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4806 glGenerateMipmapEXT(target
);
4807 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4808 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4809 texture_ref
->texture()->min_filter());
4811 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4812 if (error
== GL_NO_ERROR
) {
4813 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4817 bool GLES2DecoderImpl::GetHelper(
4818 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4819 DCHECK(num_written
);
4820 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4822 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4824 // Return the GL implementation's preferred format and (see below type)
4825 // if we have the GL extension that exposes this. This allows the GPU
4826 // client to use the implementation's preferred format for glReadPixels
4827 // for optimisation.
4829 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4830 // case when requested on integer/floating point buffers but which is
4831 // acceptable on GLES2 and with the GL_OES_read_format extension.
4833 // Therefore if an error occurs we swallow the error and use the
4834 // internal implementation.
4836 if (context_
->HasExtension("GL_OES_read_format")) {
4837 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4839 glGetIntegerv(pname
, params
);
4840 if (glGetError() == GL_NO_ERROR
)
4843 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4844 GetBoundReadFrameBufferInternalFormat());
4847 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4850 if (context_
->HasExtension("GL_OES_read_format")) {
4851 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4853 glGetIntegerv(pname
, params
);
4854 if (glGetError() == GL_NO_ERROR
)
4857 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4858 GetBoundReadFrameBufferInternalFormat(),
4859 GetBoundReadFrameBufferTextureType());
4862 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4865 *params
= group_
->max_fragment_uniform_vectors();
4868 case GL_MAX_VARYING_VECTORS
:
4871 *params
= group_
->max_varying_vectors();
4874 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4877 *params
= group_
->max_vertex_uniform_vectors();
4882 if (unsafe_es3_apis_enabled()) {
4884 case GL_MAX_VARYING_COMPONENTS
: {
4885 if (feature_info_
->gl_version_info().is_es
) {
4886 // We can just delegate this query to the driver.
4890 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4891 // OpenGL core profile, so for simplicity, just compute it
4892 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4894 GLint max_varying_vectors
= 0;
4895 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
4898 *params
= max_varying_vectors
* 4;
4905 case GL_MAX_VIEWPORT_DIMS
:
4906 if (offscreen_target_frame_buffer_
.get()) {
4909 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4910 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4915 case GL_MAX_SAMPLES
:
4918 params
[0] = renderbuffer_manager()->max_samples();
4921 case GL_MAX_RENDERBUFFER_SIZE
:
4924 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4927 case GL_MAX_TEXTURE_SIZE
:
4930 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4933 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4936 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4939 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4942 params
[0] = group_
->max_color_attachments();
4945 case GL_MAX_DRAW_BUFFERS_ARB
:
4948 params
[0] = group_
->max_draw_buffers();
4955 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4956 Framebuffer
* framebuffer
=
4957 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4959 glGetFramebufferAttachmentParameterivEXT(
4960 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
4961 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
4963 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
4966 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4969 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4976 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4977 Framebuffer
* framebuffer
=
4978 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4980 glGetFramebufferAttachmentParameterivEXT(
4981 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
4982 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
4984 v
= (back_buffer_has_depth_
? 24 : 0);
4987 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4989 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4998 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4999 Framebuffer
* framebuffer
=
5000 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5002 GLenum framebuffer_enum
= 0;
5005 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5008 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5011 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5014 glGetFramebufferAttachmentParameterivEXT(
5015 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5020 glGetIntegerv(pname
, &v
);
5025 case GL_STENCIL_BITS
:
5029 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5030 Framebuffer
* framebuffer
=
5031 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5033 glGetFramebufferAttachmentParameterivEXT(
5034 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5035 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5037 v
= (back_buffer_has_stencil_
? 8 : 0);
5040 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5042 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5045 case GL_COMPRESSED_TEXTURE_FORMATS
:
5046 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5048 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5049 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5053 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5056 *params
= validators_
->compressed_texture_format
.GetValues().size();
5059 case GL_NUM_SHADER_BINARY_FORMATS
:
5062 *params
= validators_
->shader_binary_format
.GetValues().size();
5065 case GL_SHADER_BINARY_FORMATS
:
5066 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5068 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5069 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5073 case GL_SHADER_COMPILER
:
5079 case GL_ARRAY_BUFFER_BINDING
:
5082 *params
= GetClientId(
5083 buffer_manager(), state_
.bound_array_buffer
.get());
5086 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5089 *params
= GetClientId(
5091 state_
.vertex_attrib_manager
->element_array_buffer());
5094 case GL_COPY_READ_BUFFER_BINDING
:
5097 *params
= GetClientId(
5098 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5101 case GL_COPY_WRITE_BUFFER_BINDING
:
5104 *params
= GetClientId(
5105 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5108 case GL_PIXEL_PACK_BUFFER_BINDING
:
5111 *params
= GetClientId(
5112 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5115 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5118 *params
= GetClientId(
5119 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5122 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5125 *params
= GetClientId(
5126 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5129 case GL_UNIFORM_BUFFER_BINDING
:
5132 *params
= GetClientId(
5133 buffer_manager(), state_
.bound_uniform_buffer
.get());
5136 case GL_FRAMEBUFFER_BINDING
:
5137 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5140 *params
= GetClientId(
5141 framebuffer_manager(),
5142 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5145 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5148 *params
= GetClientId(
5149 framebuffer_manager(),
5150 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5153 case GL_RENDERBUFFER_BINDING
:
5156 Renderbuffer
* renderbuffer
=
5157 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5159 *params
= renderbuffer
->client_id();
5165 case GL_CURRENT_PROGRAM
:
5168 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5171 case GL_VERTEX_ARRAY_BINDING_OES
:
5174 if (state_
.vertex_attrib_manager
.get() !=
5175 state_
.default_vertex_attrib_manager
.get()) {
5176 GLuint client_id
= 0;
5177 vertex_array_manager_
->GetClientId(
5178 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5179 *params
= client_id
;
5185 case GL_TEXTURE_BINDING_2D
:
5188 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5189 if (unit
.bound_texture_2d
.get()) {
5190 *params
= unit
.bound_texture_2d
->client_id();
5196 case GL_TEXTURE_BINDING_CUBE_MAP
:
5199 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5200 if (unit
.bound_texture_cube_map
.get()) {
5201 *params
= unit
.bound_texture_cube_map
->client_id();
5207 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5210 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5211 if (unit
.bound_texture_external_oes
.get()) {
5212 *params
= unit
.bound_texture_external_oes
->client_id();
5218 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5221 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5222 if (unit
.bound_texture_rectangle_arb
.get()) {
5223 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5229 case GL_UNPACK_FLIP_Y_CHROMIUM
:
5232 params
[0] = unpack_flip_y_
;
5235 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
5238 params
[0] = unpack_premultiply_alpha_
;
5241 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
5244 params
[0] = unpack_unpremultiply_alpha_
;
5247 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5250 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5254 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5255 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5258 Framebuffer
* framebuffer
=
5259 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5261 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5262 } else { // backbuffer
5263 if (pname
== GL_DRAW_BUFFER0_ARB
)
5264 params
[0] = group_
->draw_buffer();
5266 params
[0] = GL_NONE
;
5271 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5276 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5277 GLenum pname
, GLsizei
* num_values
) {
5278 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5281 return GetHelper(pname
, NULL
, num_values
);
5284 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5285 if (GL_MAX_SAMPLES
== pname
&&
5286 features().use_img_for_multisampled_render_to_texture
) {
5287 return GL_MAX_SAMPLES_IMG
;
5292 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5294 GLsizei num_written
= 0;
5295 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5296 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5297 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5298 GetHelper(pname
, values
.get(), &num_written
);
5300 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5301 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5304 pname
= AdjustGetPname(pname
);
5305 glGetBooleanv(pname
, params
);
5309 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5311 GLsizei num_written
= 0;
5312 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5313 if (GetHelper(pname
, NULL
, &num_written
)) {
5314 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5315 GetHelper(pname
, values
.get(), &num_written
);
5316 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5317 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5320 pname
= AdjustGetPname(pname
);
5321 glGetFloatv(pname
, params
);
5326 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5328 if (unsafe_es3_apis_enabled()) {
5330 case GL_MAX_ELEMENT_INDEX
: {
5331 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5332 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5333 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5335 // Assume that desktop GL implementations can generally support
5338 *params
= std::numeric_limits
<unsigned int>::max();
5345 pname
= AdjustGetPname(pname
);
5346 glGetInteger64v(pname
, params
);
5349 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5351 GLsizei num_written
;
5352 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5353 !GetHelper(pname
, params
, &num_written
)) {
5354 pname
= AdjustGetPname(pname
);
5355 glGetIntegerv(pname
, params
);
5359 void GLES2DecoderImpl::DoGetProgramiv(
5360 GLuint program_id
, GLenum pname
, GLint
* params
) {
5361 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5365 program
->GetProgramiv(pname
, params
);
5368 void GLES2DecoderImpl::DoGetBufferParameteriv(
5369 GLenum target
, GLenum pname
, GLint
* params
) {
5370 // Just delegate it. Some validation is actually done before this.
5371 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5372 &state_
, target
, pname
, params
);
5375 void GLES2DecoderImpl::DoBindAttribLocation(
5376 GLuint program_id
, GLuint index
, const char* name
) {
5377 if (!StringIsValidForGLES(name
)) {
5379 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5382 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5384 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5387 if (index
>= group_
->max_vertex_attribs()) {
5389 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5392 Program
* program
= GetProgramInfoNotShader(
5393 program_id
, "glBindAttribLocation");
5397 // At this point, the program's shaders may not be translated yet,
5398 // therefore, we may not find the hashed attribute name.
5399 // glBindAttribLocation call with original name is useless.
5400 // So instead, we should simply cache the binding, and then call
5401 // Program::ExecuteBindAttribLocationCalls() right before link.
5402 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5403 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5404 glBindAttribLocation(program
->service_id(), index
, name
);
5407 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5408 uint32 immediate_data_size
,
5409 const void* cmd_data
) {
5410 const gles2::cmds::BindAttribLocationBucket
& c
=
5411 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5412 GLuint program
= static_cast<GLuint
>(c
.program
);
5413 GLuint index
= static_cast<GLuint
>(c
.index
);
5414 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5415 if (!bucket
|| bucket
->size() == 0) {
5416 return error::kInvalidArguments
;
5418 std::string name_str
;
5419 if (!bucket
->GetAsString(&name_str
)) {
5420 return error::kInvalidArguments
;
5422 DoBindAttribLocation(program
, index
, name_str
.c_str());
5423 return error::kNoError
;
5426 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5427 GLuint program_id
, GLint location
, const char* name
) {
5428 if (!StringIsValidForGLES(name
)) {
5431 "glBindUniformLocationCHROMIUM", "Invalid character");
5434 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5436 GL_INVALID_OPERATION
,
5437 "glBindUniformLocationCHROMIUM", "reserved prefix");
5440 if (location
< 0 || static_cast<uint32
>(location
) >=
5441 (group_
->max_fragment_uniform_vectors() +
5442 group_
->max_vertex_uniform_vectors()) * 4) {
5445 "glBindUniformLocationCHROMIUM", "location out of range");
5448 Program
* program
= GetProgramInfoNotShader(
5449 program_id
, "glBindUniformLocationCHROMIUM");
5453 if (!program
->SetUniformLocationBinding(name
, location
)) {
5456 "glBindUniformLocationCHROMIUM", "location out of range");
5460 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5461 uint32 immediate_data_size
,
5462 const void* cmd_data
) {
5463 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5464 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5466 GLuint program
= static_cast<GLuint
>(c
.program
);
5467 GLint location
= static_cast<GLint
>(c
.location
);
5468 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5469 if (!bucket
|| bucket
->size() == 0) {
5470 return error::kInvalidArguments
;
5472 std::string name_str
;
5473 if (!bucket
->GetAsString(&name_str
)) {
5474 return error::kInvalidArguments
;
5476 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5477 return error::kNoError
;
5480 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5481 const void* cmd_data
) {
5482 const gles2::cmds::DeleteShader
& c
=
5483 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5484 GLuint client_id
= c
.shader
;
5486 Shader
* shader
= GetShader(client_id
);
5488 if (!shader
->IsDeleted()) {
5489 shader_manager()->Delete(shader
);
5492 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5495 return error::kNoError
;
5498 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5499 const void* cmd_data
) {
5500 const gles2::cmds::DeleteProgram
& c
=
5501 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5502 GLuint client_id
= c
.program
;
5504 Program
* program
= GetProgram(client_id
);
5506 if (!program
->IsDeleted()) {
5507 program_manager()->MarkAsDeleted(shader_manager(), program
);
5511 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5514 return error::kNoError
;
5517 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5518 DCHECK(!ShouldDeferDraws());
5519 if (CheckBoundFramebuffersValid("glClear")) {
5521 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5522 if (workarounds().gl_clear_broken
) {
5523 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5525 if (!BoundFramebufferHasDepthAttachment())
5526 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5527 if (!BoundFramebufferHasStencilAttachment())
5528 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5529 clear_framebuffer_blit_
->ClearFramebuffer(
5530 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5531 state_
.color_clear_green
, state_
.color_clear_blue
,
5532 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5533 return error::kNoError
;
5537 return error::kNoError
;
5540 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5541 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5542 GLuint client_renderbuffer_id
) {
5543 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5546 GL_INVALID_OPERATION
,
5547 "glFramebufferRenderbuffer", "no framebuffer bound");
5550 GLuint service_id
= 0;
5551 Renderbuffer
* renderbuffer
= NULL
;
5552 if (client_renderbuffer_id
) {
5553 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5554 if (!renderbuffer
) {
5556 GL_INVALID_OPERATION
,
5557 "glFramebufferRenderbuffer", "unknown renderbuffer");
5560 service_id
= renderbuffer
->service_id();
5562 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5563 glFramebufferRenderbufferEXT(
5564 target
, attachment
, renderbuffertarget
, service_id
);
5565 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5566 if (error
== GL_NO_ERROR
) {
5567 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5569 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5570 framebuffer_state_
.clear_state_dirty
= true;
5575 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5576 if (SetCapabilityState(cap
, false)) {
5581 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5582 if (SetCapabilityState(cap
, true)) {
5587 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5588 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5589 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5590 glDepthRange(znear
, zfar
);
5593 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5594 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5595 state_
.sample_coverage_invert
= (invert
!= 0);
5596 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5599 // Assumes framebuffer is complete.
5600 void GLES2DecoderImpl::ClearUnclearedAttachments(
5601 GLenum target
, Framebuffer
* framebuffer
) {
5602 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5603 // bind this to the DRAW point, clear then bind back to READ
5604 // TODO(gman): I don't think there is any guarantee that an FBO that
5605 // is complete on the READ attachment will be complete as a DRAW
5607 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5608 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5610 GLbitfield clear_bits
= 0;
5611 if (framebuffer
->HasUnclearedColorAttachments()) {
5614 (GLES2Util::GetChannelsForFormat(
5615 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5617 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5618 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5619 if (feature_info_
->feature_flags().ext_draw_buffers
)
5620 framebuffer
->PrepareDrawBuffersForClear();
5623 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5624 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5626 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5627 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5628 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5631 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5632 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5634 state_
.SetDeviceDepthMask(GL_TRUE
);
5635 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5638 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5639 glClear(clear_bits
);
5641 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5642 feature_info_
->feature_flags().ext_draw_buffers
)
5643 framebuffer
->RestoreDrawBuffersAfterClear();
5645 framebuffer_manager()->MarkAttachmentsAsCleared(
5646 framebuffer
, renderbuffer_manager(), texture_manager());
5648 RestoreClearState();
5650 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5651 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5652 Framebuffer
* draw_framebuffer
=
5653 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5654 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5655 GetBackbufferServiceId();
5656 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5660 void GLES2DecoderImpl::RestoreClearState() {
5661 framebuffer_state_
.clear_state_dirty
= true;
5663 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5664 state_
.color_clear_alpha
);
5665 glClearStencil(state_
.stencil_clear
);
5666 glClearDepth(state_
.depth_clear
);
5667 if (state_
.enable_flags
.scissor_test
) {
5668 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5672 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5673 Framebuffer
* framebuffer
=
5674 GetFramebufferInfoForTarget(target
);
5676 return GL_FRAMEBUFFER_COMPLETE
;
5678 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5679 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5680 return completeness
;
5682 return framebuffer
->GetStatus(texture_manager(), target
);
5685 void GLES2DecoderImpl::DoFramebufferTexture2D(
5686 GLenum target
, GLenum attachment
, GLenum textarget
,
5687 GLuint client_texture_id
, GLint level
) {
5688 DoFramebufferTexture2DCommon(
5689 "glFramebufferTexture2D", target
, attachment
,
5690 textarget
, client_texture_id
, level
, 0);
5693 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5694 GLenum target
, GLenum attachment
, GLenum textarget
,
5695 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5696 DoFramebufferTexture2DCommon(
5697 "glFramebufferTexture2DMultisample", target
, attachment
,
5698 textarget
, client_texture_id
, level
, samples
);
5701 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5702 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5703 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5704 if (samples
> renderbuffer_manager()->max_samples()) {
5707 "glFramebufferTexture2DMultisample", "samples too large");
5710 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5713 GL_INVALID_OPERATION
,
5714 name
, "no framebuffer bound.");
5717 GLuint service_id
= 0;
5718 TextureRef
* texture_ref
= NULL
;
5719 if (client_texture_id
) {
5720 texture_ref
= GetTexture(client_texture_id
);
5723 GL_INVALID_OPERATION
,
5724 name
, "unknown texture_ref");
5727 service_id
= texture_ref
->service_id();
5730 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5733 name
, "level out of range");
5738 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5740 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5742 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5744 if (features().use_img_for_multisampled_render_to_texture
) {
5745 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5746 service_id
, level
, samples
);
5748 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5749 service_id
, level
, samples
);
5752 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5753 if (error
== GL_NO_ERROR
) {
5754 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5757 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5758 framebuffer_state_
.clear_state_dirty
= true;
5762 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5767 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5768 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5769 GLint level
, GLint layer
) {
5770 // TODO(zmo): Unsafe ES3 API, missing states update.
5771 GLuint service_id
= 0;
5772 TextureRef
* texture_ref
= NULL
;
5773 if (client_texture_id
) {
5774 texture_ref
= GetTexture(client_texture_id
);
5777 GL_INVALID_OPERATION
,
5778 "glFramebufferTextureLayer", "unknown texture_ref");
5781 service_id
= texture_ref
->service_id();
5783 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5786 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5787 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5788 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5791 GL_INVALID_OPERATION
,
5792 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5795 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5796 const Framebuffer::Attachment
* attachment_object
=
5797 framebuffer
->GetAttachment(attachment
);
5798 *params
= attachment_object
? attachment_object
->object_name() : 0;
5800 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5801 features().use_img_for_multisampled_render_to_texture
) {
5802 pname
= GL_TEXTURE_SAMPLES_IMG
;
5804 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5808 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5809 GLenum target
, GLenum pname
, GLint
* params
) {
5810 Renderbuffer
* renderbuffer
=
5811 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5812 if (!renderbuffer
) {
5814 GL_INVALID_OPERATION
,
5815 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5819 EnsureRenderbufferBound();
5821 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5822 *params
= renderbuffer
->internal_format();
5824 case GL_RENDERBUFFER_WIDTH
:
5825 *params
= renderbuffer
->width();
5827 case GL_RENDERBUFFER_HEIGHT
:
5828 *params
= renderbuffer
->height();
5830 case GL_RENDERBUFFER_SAMPLES_EXT
:
5831 if (features().use_img_for_multisampled_render_to_texture
) {
5832 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5835 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5839 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5844 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5845 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5846 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5847 GLbitfield mask
, GLenum filter
) {
5848 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5850 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5854 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5855 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5856 BlitFramebufferHelper(
5857 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5858 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5859 state_
.enable_flags
.scissor_test
);
5862 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5863 if (!state_
.bound_renderbuffer_valid
) {
5864 state_
.bound_renderbuffer_valid
= true;
5865 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5866 state_
.bound_renderbuffer
.get()
5867 ? state_
.bound_renderbuffer
->service_id()
5872 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5873 const FeatureInfo
* feature_info
,
5876 GLenum internal_format
,
5879 // TODO(sievers): This could be resolved at the GL binding level, but the
5880 // binding process is currently a bit too 'brute force'.
5881 if (feature_info
->gl_version_info().is_angle
) {
5882 glRenderbufferStorageMultisampleANGLE(
5883 target
, samples
, internal_format
, width
, height
);
5884 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5885 glRenderbufferStorageMultisample(
5886 target
, samples
, internal_format
, width
, height
);
5888 glRenderbufferStorageMultisampleEXT(
5889 target
, samples
, internal_format
, width
, height
);
5893 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5903 // TODO(sievers): This could be resolved at the GL binding level, but the
5904 // binding process is currently a bit too 'brute force'.
5905 if (feature_info_
->gl_version_info().is_angle
) {
5906 glBlitFramebufferANGLE(
5907 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5908 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5910 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5912 glBlitFramebufferEXT(
5913 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5917 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5919 GLenum internalformat
,
5922 if (samples
> renderbuffer_manager()->max_samples()) {
5925 "glRenderbufferStorageMultisample", "samples too large");
5929 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5930 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5933 "glRenderbufferStorageMultisample", "dimensions too large");
5937 uint32 estimated_size
= 0;
5938 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5939 width
, height
, samples
, internalformat
, &estimated_size
)) {
5942 "glRenderbufferStorageMultisample", "dimensions too large");
5946 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5949 "glRenderbufferStorageMultisample", "out of memory");
5956 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5957 GLenum target
, GLsizei samples
, GLenum internalformat
,
5958 GLsizei width
, GLsizei height
) {
5959 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5960 if (!renderbuffer
) {
5961 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5962 "glRenderbufferStorageMultisampleCHROMIUM",
5963 "no renderbuffer bound");
5967 if (!ValidateRenderbufferStorageMultisample(
5968 samples
, internalformat
, width
, height
)) {
5972 EnsureRenderbufferBound();
5973 GLenum impl_format
=
5974 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5976 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5977 "glRenderbufferStorageMultisampleCHROMIUM");
5978 RenderbufferStorageMultisampleHelper(
5979 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5981 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5982 if (error
== GL_NO_ERROR
) {
5983 if (workarounds().validate_multisample_buffer_allocation
) {
5984 if (!VerifyMultisampleRenderbufferIntegrity(
5985 renderbuffer
->service_id(), impl_format
)) {
5988 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5993 // TODO(gman): If renderbuffers tracked which framebuffers they were
5994 // attached to we could just mark those framebuffers as not complete.
5995 framebuffer_manager()->IncFramebufferStateChangeCount();
5996 renderbuffer_manager()->SetInfo(
5997 renderbuffer
, samples
, internalformat
, width
, height
);
6001 // This is the handler for multisampled_render_to_texture extensions.
6002 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6003 GLenum target
, GLsizei samples
, GLenum internalformat
,
6004 GLsizei width
, GLsizei height
) {
6005 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6006 if (!renderbuffer
) {
6007 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6008 "glRenderbufferStorageMultisampleEXT",
6009 "no renderbuffer bound");
6013 if (!ValidateRenderbufferStorageMultisample(
6014 samples
, internalformat
, width
, height
)) {
6018 EnsureRenderbufferBound();
6019 GLenum impl_format
=
6020 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6022 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6023 if (features().use_img_for_multisampled_render_to_texture
) {
6024 glRenderbufferStorageMultisampleIMG(
6025 target
, samples
, impl_format
, width
, height
);
6027 glRenderbufferStorageMultisampleEXT(
6028 target
, samples
, impl_format
, width
, height
);
6030 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6031 if (error
== GL_NO_ERROR
) {
6032 // TODO(gman): If renderbuffers tracked which framebuffers they were
6033 // attached to we could just mark those framebuffers as not complete.
6034 framebuffer_manager()->IncFramebufferStateChangeCount();
6035 renderbuffer_manager()->SetInfo(
6036 renderbuffer
, samples
, internalformat
, width
, height
);
6040 // This function validates the allocation of a multisampled renderbuffer
6041 // by clearing it to a key color, blitting the contents to a texture, and
6042 // reading back the color to ensure it matches the key.
6043 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6044 GLuint renderbuffer
, GLenum format
) {
6046 // Only validate color buffers.
6047 // These formats have been selected because they are very common or are known
6048 // to be used by the WebGL backbuffer. If problems are observed with other
6049 // color formats they can be added here.
6060 GLint draw_framebuffer
, read_framebuffer
;
6062 // Cache framebuffer and texture bindings.
6063 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6064 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6066 if (!validation_texture_
) {
6067 GLint bound_texture
;
6068 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6070 // Create additional resources needed for the verification.
6071 glGenTextures(1, &validation_texture_
);
6072 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6073 glGenFramebuffersEXT(1, &validation_fbo_
);
6075 // Texture only needs to be 1x1.
6076 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6077 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6078 // multisample will fail if the color format of the source and destination
6079 // do not match. Here, we assume that the source is GL_RGBA, and make the
6080 // destination GL_RGBA. http://crbug.com/484203
6081 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6082 GL_UNSIGNED_BYTE
, NULL
);
6084 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6085 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6086 GL_TEXTURE_2D
, validation_texture_
, 0);
6088 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6091 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6092 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6093 GL_RENDERBUFFER
, renderbuffer
);
6095 // Cache current state and reset it to the values we require.
6096 GLboolean scissor_enabled
= false;
6097 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6098 if (scissor_enabled
)
6099 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6101 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6102 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6103 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6105 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6106 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6107 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6109 // Clear the buffer to the desired key color.
6110 glClear(GL_COLOR_BUFFER_BIT
);
6112 // Blit from the multisample buffer to a standard texture.
6113 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6114 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6116 BlitFramebufferHelper(
6117 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6119 // Read a pixel from the buffer.
6120 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6122 unsigned char pixel
[3] = {0, 0, 0};
6123 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6125 // Detach the renderbuffer.
6126 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6127 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6128 GL_RENDERBUFFER
, 0);
6130 // Restore cached state.
6131 if (scissor_enabled
)
6132 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6134 state_
.SetDeviceColorMask(
6135 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6136 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6137 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6138 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6140 // Return true if the pixel matched the desired key color.
6141 return (pixel
[0] == 0xFF &&
6146 void GLES2DecoderImpl::DoRenderbufferStorage(
6147 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6148 Renderbuffer
* renderbuffer
=
6149 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6150 if (!renderbuffer
) {
6152 GL_INVALID_OPERATION
,
6153 "glRenderbufferStorage", "no renderbuffer bound");
6157 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6158 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6160 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6164 uint32 estimated_size
= 0;
6165 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6166 width
, height
, 1, internalformat
, &estimated_size
)) {
6168 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6172 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6174 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6178 EnsureRenderbufferBound();
6179 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6180 glRenderbufferStorageEXT(
6182 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6186 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6187 if (error
== GL_NO_ERROR
) {
6188 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6189 // we could just mark those framebuffers as not complete.
6190 framebuffer_manager()->IncFramebufferStateChangeCount();
6191 renderbuffer_manager()->SetInfo(
6192 renderbuffer
, 1, internalformat
, width
, height
);
6196 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6197 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6198 Program
* program
= GetProgramInfoNotShader(
6199 program_id
, "glLinkProgram");
6204 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6205 if (program
->Link(shader_manager(),
6206 workarounds().count_all_in_varyings_packing
?
6207 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6208 shader_cache_callback_
)) {
6209 if (program
== state_
.current_program
.get()) {
6210 if (workarounds().use_current_program_after_successful_link
)
6211 glUseProgram(program
->service_id());
6212 if (workarounds().clear_uniforms_before_first_program_use
)
6213 program_manager()->ClearUniforms(program
);
6217 // LinkProgram can be very slow. Exit command processing to allow for
6218 // context preemption and GPU watchdog checks.
6219 ExitCommandProcessingEarly();
6222 void GLES2DecoderImpl::DoSamplerParameterfv(
6223 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6225 glSamplerParameterf(sampler
, pname
, params
[0]);
6228 void GLES2DecoderImpl::DoSamplerParameteriv(
6229 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6231 glSamplerParameteri(sampler
, pname
, params
[0]);
6234 void GLES2DecoderImpl::DoTexParameterf(
6235 GLenum target
, GLenum pname
, GLfloat param
) {
6236 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6239 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6243 texture_manager()->SetParameterf(
6244 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6247 void GLES2DecoderImpl::DoTexParameteri(
6248 GLenum target
, GLenum pname
, GLint param
) {
6249 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6252 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6256 texture_manager()->SetParameteri(
6257 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6260 void GLES2DecoderImpl::DoTexParameterfv(
6261 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6262 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6265 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6269 texture_manager()->SetParameterf(
6270 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6273 void GLES2DecoderImpl::DoTexParameteriv(
6274 GLenum target
, GLenum pname
, const GLint
* params
) {
6275 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6279 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6283 texture_manager()->SetParameteri(
6284 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6287 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6288 if (!state_
.bound_valuebuffer
.get()) {
6289 // There is no valuebuffer bound
6290 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6291 "no valuebuffer in use");
6297 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6298 GLenum subscription
,
6299 const char* function_name
) {
6300 if (!CheckCurrentValuebuffer(function_name
)) {
6303 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6304 // The valuebuffer is not subscribed to the target
6305 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6306 "valuebuffer is not subscribed");
6312 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6313 GLenum subscription
,
6314 const char* function_name
) {
6315 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6318 GLint real_location
= -1;
6319 GLint array_index
= -1;
6320 const Program::UniformInfo
* info
=
6321 state_
.current_program
->GetUniformInfoByFakeLocation(
6322 location
, &real_location
, &array_index
);
6324 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6327 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6328 info
->accepts_api_type
) == 0) {
6329 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6330 "wrong type for subscription");
6336 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6337 if (!state_
.current_program
.get()) {
6338 // The program does not exist.
6340 GL_INVALID_OPERATION
, function_name
, "no program in use");
6343 if (!state_
.current_program
->InUse()) {
6345 GL_INVALID_OPERATION
, function_name
, "program not linked");
6351 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6352 GLint location
, const char* function_name
) {
6353 if (!CheckCurrentProgram(function_name
)) {
6356 return location
!= -1;
6359 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6360 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6363 const Framebuffer::Attachment
* attachment
=
6364 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6368 DCHECK(state_
.current_program
.get());
6369 const Program::SamplerIndices
& sampler_indices
=
6370 state_
.current_program
->sampler_indices();
6371 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6372 const Program::UniformInfo
* uniform_info
=
6373 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6374 DCHECK(uniform_info
);
6375 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6377 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6378 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6379 if (texture_unit_index
>= state_
.texture_units
.size())
6381 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6382 TextureRef
* texture_ref
=
6383 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6384 if (attachment
->IsTexture(texture_ref
))
6391 bool GLES2DecoderImpl::CheckUniformForApiType(
6392 const Program::UniformInfo
* info
,
6393 const char* function_name
,
6394 Program::UniformApiType api_type
) {
6396 if ((api_type
& info
->accepts_api_type
) == 0) {
6397 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6398 "wrong uniform function for type");
6404 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6405 GLint fake_location
,
6406 const char* function_name
,
6407 Program::UniformApiType api_type
,
6408 GLint
* real_location
,
6413 DCHECK(real_location
);
6415 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6418 GLint array_index
= -1;
6419 const Program::UniformInfo
* info
=
6420 state_
.current_program
->GetUniformInfoByFakeLocation(
6421 fake_location
, real_location
, &array_index
);
6424 GL_INVALID_OPERATION
, function_name
, "unknown location");
6427 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6430 if (*count
> 1 && !info
->is_array
) {
6432 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6435 *count
= std::min(info
->size
- array_index
, *count
);
6443 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6446 GLint real_location
= -1;
6447 if (!PrepForSetUniformByLocation(fake_location
,
6449 Program::kUniform1i
,
6455 if (!state_
.current_program
->SetSamplers(
6456 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6458 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6461 glUniform1i(real_location
, v0
);
6464 void GLES2DecoderImpl::DoUniform1iv(
6465 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6467 GLint real_location
= -1;
6468 if (!PrepForSetUniformByLocation(fake_location
,
6470 Program::kUniform1i
,
6476 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6477 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6478 if (!state_
.current_program
->SetSamplers(
6479 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6481 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6485 glUniform1iv(real_location
, count
, value
);
6488 void GLES2DecoderImpl::DoUniform1fv(
6489 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6491 GLint real_location
= -1;
6492 if (!PrepForSetUniformByLocation(fake_location
,
6494 Program::kUniform1f
,
6500 if (type
== GL_BOOL
) {
6501 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6502 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6503 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6505 DoUniform1iv(real_location
, count
, temp
.get());
6507 glUniform1fv(real_location
, count
, value
);
6511 void GLES2DecoderImpl::DoUniform2fv(
6512 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6514 GLint real_location
= -1;
6515 if (!PrepForSetUniformByLocation(fake_location
,
6517 Program::kUniform2f
,
6523 if (type
== GL_BOOL_VEC2
) {
6524 GLsizei num_values
= count
* 2;
6525 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6526 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6527 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6529 glUniform2iv(real_location
, count
, temp
.get());
6531 glUniform2fv(real_location
, count
, value
);
6535 void GLES2DecoderImpl::DoUniform3fv(
6536 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6538 GLint real_location
= -1;
6539 if (!PrepForSetUniformByLocation(fake_location
,
6541 Program::kUniform3f
,
6547 if (type
== GL_BOOL_VEC3
) {
6548 GLsizei num_values
= count
* 3;
6549 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6550 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6551 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6553 glUniform3iv(real_location
, count
, temp
.get());
6555 glUniform3fv(real_location
, count
, value
);
6559 void GLES2DecoderImpl::DoUniform4fv(
6560 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6562 GLint real_location
= -1;
6563 if (!PrepForSetUniformByLocation(fake_location
,
6565 Program::kUniform4f
,
6571 if (type
== GL_BOOL_VEC4
) {
6572 GLsizei num_values
= count
* 4;
6573 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6574 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6575 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6577 glUniform4iv(real_location
, count
, temp
.get());
6579 glUniform4fv(real_location
, count
, value
);
6583 void GLES2DecoderImpl::DoUniform2iv(
6584 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6586 GLint real_location
= -1;
6587 if (!PrepForSetUniformByLocation(fake_location
,
6589 Program::kUniform2i
,
6595 glUniform2iv(real_location
, count
, value
);
6598 void GLES2DecoderImpl::DoUniform3iv(
6599 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6601 GLint real_location
= -1;
6602 if (!PrepForSetUniformByLocation(fake_location
,
6604 Program::kUniform3i
,
6610 glUniform3iv(real_location
, count
, value
);
6613 void GLES2DecoderImpl::DoUniform4iv(
6614 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6616 GLint real_location
= -1;
6617 if (!PrepForSetUniformByLocation(fake_location
,
6619 Program::kUniform4i
,
6625 glUniform4iv(real_location
, count
, value
);
6628 void GLES2DecoderImpl::DoUniformMatrix2fv(
6629 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6630 const GLfloat
* value
) {
6632 GLint real_location
= -1;
6633 if (!PrepForSetUniformByLocation(fake_location
,
6634 "glUniformMatrix2fv",
6635 Program::kUniformMatrix2f
,
6641 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6644 void GLES2DecoderImpl::DoUniformMatrix3fv(
6645 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6646 const GLfloat
* value
) {
6648 GLint real_location
= -1;
6649 if (!PrepForSetUniformByLocation(fake_location
,
6650 "glUniformMatrix3fv",
6651 Program::kUniformMatrix3f
,
6657 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6660 void GLES2DecoderImpl::DoUniformMatrix4fv(
6661 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6662 const GLfloat
* value
) {
6664 GLint real_location
= -1;
6665 if (!PrepForSetUniformByLocation(fake_location
,
6666 "glUniformMatrix4fv",
6667 Program::kUniformMatrix4f
,
6673 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6676 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6677 GLuint service_id
= 0;
6678 Program
* program
= NULL
;
6680 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6684 if (!program
->IsValid()) {
6685 // Program was not linked successfully. (ie, glLinkProgram)
6687 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6690 service_id
= program
->service_id();
6692 if (state_
.current_program
.get()) {
6693 program_manager()->UnuseProgram(shader_manager(),
6694 state_
.current_program
.get());
6696 state_
.current_program
= program
;
6697 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6698 glUseProgram(service_id
);
6699 if (state_
.current_program
.get()) {
6700 program_manager()->UseProgram(state_
.current_program
.get());
6701 if (workarounds().clear_uniforms_before_first_program_use
)
6702 program_manager()->ClearUniforms(program
);
6706 void GLES2DecoderImpl::RenderWarning(
6707 const char* filename
, int line
, const std::string
& msg
) {
6708 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6711 void GLES2DecoderImpl::PerformanceWarning(
6712 const char* filename
, int line
, const std::string
& msg
) {
6713 logger_
.LogMessage(filename
, line
,
6714 std::string("PERFORMANCE WARNING: ") + msg
);
6717 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6718 Texture
* texture
, GLenum textarget
) {
6719 // Image is already in use if texture is attached to a framebuffer.
6720 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6721 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6723 ScopedGLErrorSuppressor
suppressor(
6724 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6726 glBindTexture(textarget
, texture
->service_id());
6727 image
->WillUseTexImage();
6728 RestoreCurrentTextureBindings(&state_
, textarget
);
6733 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6734 Texture
* texture
, GLenum textarget
) {
6735 // Image is still in use if texture is attached to a framebuffer.
6736 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6737 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6739 ScopedGLErrorSuppressor
suppressor(
6740 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6742 glBindTexture(textarget
, texture
->service_id());
6743 image
->DidUseTexImage();
6744 RestoreCurrentTextureBindings(&state_
, textarget
);
6749 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6750 DCHECK(state_
.current_program
.get());
6751 if (!texture_manager()->HaveUnrenderableTextures() &&
6752 !texture_manager()->HaveImages()) {
6756 bool textures_set
= false;
6757 const Program::SamplerIndices
& sampler_indices
=
6758 state_
.current_program
->sampler_indices();
6759 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6760 const Program::UniformInfo
* uniform_info
=
6761 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6762 DCHECK(uniform_info
);
6763 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6764 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6765 if (texture_unit_index
< state_
.texture_units
.size()) {
6766 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6767 TextureRef
* texture_ref
=
6768 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6769 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6770 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6771 textures_set
= true;
6772 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6775 texture_manager()->black_texture_id(uniform_info
->type
));
6777 LOCAL_RENDER_WARNING(
6778 std::string("there is no texture bound to the unit ") +
6779 base::IntToString(texture_unit_index
));
6781 LOCAL_RENDER_WARNING(
6782 std::string("texture bound to texture unit ") +
6783 base::IntToString(texture_unit_index
) +
6784 " is not renderable. It maybe non-power-of-2 and have"
6785 " incompatible texture filtering.");
6790 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6791 Texture
* texture
= texture_ref
->texture();
6792 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6793 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6794 ScopedGLErrorSuppressor
suppressor(
6795 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6796 textures_set
= true;
6797 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6798 image
->WillUseTexImage();
6803 // else: should this be an error?
6806 return !textures_set
;
6809 void GLES2DecoderImpl::RestoreStateForTextures() {
6810 DCHECK(state_
.current_program
.get());
6811 const Program::SamplerIndices
& sampler_indices
=
6812 state_
.current_program
->sampler_indices();
6813 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6814 const Program::UniformInfo
* uniform_info
=
6815 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6816 DCHECK(uniform_info
);
6817 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6818 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6819 if (texture_unit_index
< state_
.texture_units
.size()) {
6820 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6821 TextureRef
* texture_ref
=
6822 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6823 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6824 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6825 // Get the texture_ref info that was previously bound here.
6826 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6827 ? texture_unit
.bound_texture_2d
.get()
6828 : texture_unit
.bound_texture_cube_map
.get();
6829 glBindTexture(texture_unit
.bind_target
,
6830 texture_ref
? texture_ref
->service_id() : 0);
6834 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6835 Texture
* texture
= texture_ref
->texture();
6836 gfx::GLImage
* image
=
6837 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6838 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6839 ScopedGLErrorSuppressor
suppressor(
6840 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6841 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6842 image
->DidUseTexImage();
6849 // Set the active texture back to whatever the user had it as.
6850 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6853 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6854 // Only check if there are some uncleared textures.
6855 if (!texture_manager()->HaveUnsafeTextures()) {
6859 // 1: Check all textures we are about to render with.
6860 if (state_
.current_program
.get()) {
6861 const Program::SamplerIndices
& sampler_indices
=
6862 state_
.current_program
->sampler_indices();
6863 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6864 const Program::UniformInfo
* uniform_info
=
6865 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6866 DCHECK(uniform_info
);
6867 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6868 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6869 if (texture_unit_index
< state_
.texture_units
.size()) {
6870 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6871 TextureRef
* texture_ref
=
6872 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6873 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6874 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6885 bool GLES2DecoderImpl::IsDrawValid(
6886 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6887 GLsizei primcount
) {
6888 DCHECK(instanced
|| primcount
== 1);
6890 // NOTE: We specifically do not check current_program->IsValid() because
6891 // it could never be invalid since glUseProgram would have failed. While
6892 // glLinkProgram could later mark the program as invalid the previous
6893 // valid program will still function if it is still the current program.
6894 if (!state_
.current_program
.get()) {
6895 // The program does not exist.
6896 // But GL says no ERROR.
6897 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6901 if (CheckDrawingFeedbackLoops()) {
6903 GL_INVALID_OPERATION
, function_name
,
6904 "Source and destination textures of the draw are the same.");
6908 return state_
.vertex_attrib_manager
6909 ->ValidateBindings(function_name
,
6911 feature_info_
.get(),
6912 state_
.current_program
.get(),
6913 max_vertex_accessed
,
6918 bool GLES2DecoderImpl::SimulateAttrib0(
6919 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6923 if (feature_info_
->gl_version_info().BehavesLikeGLES())
6926 const VertexAttrib
* attrib
=
6927 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6928 // If it's enabled or it's not used then we don't need to do anything.
6929 bool attrib_0_used
=
6930 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6931 if (attrib
->enabled() && attrib_0_used
) {
6935 // Make a buffer with a single repeated vec4 value enough to
6936 // simulate the constant value that is supposed to be here.
6937 // This is required to emulate GLES2 on GL.
6938 GLuint num_vertices
= max_vertex_accessed
+ 1;
6939 uint32 size_needed
= 0;
6941 if (num_vertices
== 0 ||
6942 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
6943 size_needed
> 0x7FFFFFFFU
) {
6944 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6948 LOCAL_PERFORMANCE_WARNING(
6949 "Attribute 0 is disabled. This has signficant performance penalty");
6951 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6952 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6954 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6956 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6957 GLenum error
= glGetError();
6958 if (error
!= GL_NO_ERROR
) {
6960 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6965 const Vec4
& value
= state_
.attrib_values
[0];
6968 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
6969 // TODO(zmo): This is not 100% correct because we might lose data when
6970 // casting to float type, but it is a corner case and once we migrate to
6971 // core profiles on desktop GL, it is no longer relevant.
6972 Vec4f
fvalue(value
);
6973 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
6974 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6975 attrib_0_buffer_matches_value_
= true;
6976 attrib_0_value_
= value
;
6977 attrib_0_size_
= size_needed
;
6980 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6982 if (attrib
->divisor())
6983 glVertexAttribDivisorANGLE(0, 0);
6989 void GLES2DecoderImpl::RestoreStateForAttrib(
6990 GLuint attrib_index
, bool restore_array_binding
) {
6991 const VertexAttrib
* attrib
=
6992 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6993 if (restore_array_binding
) {
6994 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6995 Buffer
* buffer
= attrib
->buffer();
6996 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6997 glVertexAttribPointer(
6998 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6999 attrib
->gl_stride(), ptr
);
7001 if (attrib
->divisor())
7002 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7004 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7005 state_
.bound_array_buffer
->service_id() : 0);
7007 // Never touch vertex attribute 0's state (in particular, never
7008 // disable it) when running on desktop GL because it will never be
7010 if (attrib_index
!= 0 ||
7011 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7012 if (attrib
->enabled()) {
7013 glEnableVertexAttribArray(attrib_index
);
7015 glDisableVertexAttribArray(attrib_index
);
7020 bool GLES2DecoderImpl::SimulateFixedAttribs(
7021 const char* function_name
,
7022 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7025 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7028 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7032 LOCAL_PERFORMANCE_WARNING(
7033 "GL_FIXED attributes have a signficant performance penalty");
7035 // NOTE: we could be smart and try to check if a buffer is used
7036 // twice in 2 different attribs, find the overlapping parts and therefore
7037 // duplicate the minimum amount of data but this whole code path is not meant
7038 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7039 // tests so we just add to the buffer attrib used.
7041 GLuint elements_needed
= 0;
7042 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7043 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7044 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7045 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7046 const VertexAttrib
* attrib
= *it
;
7047 const Program::VertexAttrib
* attrib_info
=
7048 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7049 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7050 max_vertex_accessed
);
7051 GLuint num_vertices
= max_accessed
+ 1;
7052 if (num_vertices
== 0) {
7054 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7058 attrib
->CanAccess(max_accessed
) &&
7059 attrib
->type() == GL_FIXED
) {
7060 uint32 elements_used
= 0;
7061 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7062 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7064 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7070 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7071 uint32 size_needed
= 0;
7072 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7073 size_needed
> 0x7FFFFFFFU
) {
7075 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7079 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7081 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7082 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7083 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7084 GLenum error
= glGetError();
7085 if (error
!= GL_NO_ERROR
) {
7087 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7092 // Copy the elements and convert to float
7093 GLintptr offset
= 0;
7094 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7095 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7096 const VertexAttrib
* attrib
= *it
;
7097 const Program::VertexAttrib
* attrib_info
=
7098 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7099 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7100 max_vertex_accessed
);
7101 GLuint num_vertices
= max_accessed
+ 1;
7102 if (num_vertices
== 0) {
7104 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7108 attrib
->CanAccess(max_accessed
) &&
7109 attrib
->type() == GL_FIXED
) {
7110 int num_elements
= attrib
->size() * num_vertices
;
7111 const int src_size
= num_elements
* sizeof(int32
);
7112 const int dst_size
= num_elements
* sizeof(float);
7113 scoped_ptr
<float[]> data(new float[num_elements
]);
7114 const int32
* src
= reinterpret_cast<const int32
*>(
7115 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7116 const int32
* end
= src
+ num_elements
;
7117 float* dst
= data
.get();
7118 while (src
!= end
) {
7119 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7121 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7122 glVertexAttribPointer(
7123 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7124 reinterpret_cast<GLvoid
*>(offset
));
7132 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7133 // There's no need to call glVertexAttribPointer because we shadow all the
7134 // settings and passing GL_FIXED to it will not work.
7137 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7141 error::Error
GLES2DecoderImpl::DoDrawArrays(
7142 const char* function_name
,
7147 GLsizei primcount
) {
7148 error::Error error
= WillAccessBoundFramebufferForDraw();
7149 if (error
!= error::kNoError
)
7151 if (!validators_
->draw_mode
.IsValid(mode
)) {
7152 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7153 return error::kNoError
;
7156 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7157 return error::kNoError
;
7159 if (primcount
< 0) {
7160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7161 return error::kNoError
;
7163 if (!CheckBoundFramebuffersValid(function_name
)) {
7164 return error::kNoError
;
7166 // We have to check this here because the prototype for glDrawArrays
7167 // is GLint not GLsizei.
7169 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7170 return error::kNoError
;
7173 if (count
== 0 || primcount
== 0) {
7174 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7175 return error::kNoError
;
7178 GLuint max_vertex_accessed
= first
+ count
- 1;
7179 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7180 if (!ClearUnclearedTextures()) {
7181 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7182 return error::kNoError
;
7184 bool simulated_attrib_0
= false;
7185 if (!SimulateAttrib0(
7186 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7187 return error::kNoError
;
7189 bool simulated_fixed_attribs
= false;
7190 if (SimulateFixedAttribs(
7191 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7193 bool textures_set
= !PrepareTexturesForRender();
7195 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7197 glDrawArrays(mode
, first
, count
);
7199 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7202 RestoreStateForTextures();
7204 if (simulated_fixed_attribs
) {
7205 RestoreStateForSimulatedFixedAttribs();
7208 if (simulated_attrib_0
) {
7209 // We don't have to restore attrib 0 generic data at the end of this
7210 // function even if it is simulated. This is because we will simulate
7211 // it in each draw call, and attrib 0 generic data queries use cached
7212 // values instead of passing down to the underlying driver.
7213 RestoreStateForAttrib(0, false);
7216 return error::kNoError
;
7219 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7220 const void* cmd_data
) {
7221 // TODO(zmo): crbug.com/481184
7222 // On Desktop GL with versions lower than 4.3, we need to emulate
7223 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7224 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7225 return DoDrawArrays("glDrawArrays",
7227 static_cast<GLenum
>(c
.mode
),
7228 static_cast<GLint
>(c
.first
),
7229 static_cast<GLsizei
>(c
.count
),
7233 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7234 uint32 immediate_data_size
,
7235 const void* cmd_data
) {
7236 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7237 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7238 if (!features().angle_instanced_arrays
) {
7240 GL_INVALID_OPERATION
,
7241 "glDrawArraysInstancedANGLE", "function not available");
7242 return error::kNoError
;
7244 return DoDrawArrays("glDrawArraysIntancedANGLE",
7246 static_cast<GLenum
>(c
.mode
),
7247 static_cast<GLint
>(c
.first
),
7248 static_cast<GLsizei
>(c
.count
),
7249 static_cast<GLsizei
>(c
.primcount
));
7252 error::Error
GLES2DecoderImpl::DoDrawElements(
7253 const char* function_name
,
7259 GLsizei primcount
) {
7260 error::Error error
= WillAccessBoundFramebufferForDraw();
7261 if (error
!= error::kNoError
)
7263 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7265 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7266 return error::kNoError
;
7270 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7271 return error::kNoError
;
7274 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7275 return error::kNoError
;
7277 if (!validators_
->draw_mode
.IsValid(mode
)) {
7278 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7279 return error::kNoError
;
7281 if (!validators_
->index_type
.IsValid(type
)) {
7282 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7283 return error::kNoError
;
7285 if (primcount
< 0) {
7286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7287 return error::kNoError
;
7290 if (!CheckBoundFramebuffersValid(function_name
)) {
7291 return error::kNoError
;
7294 if (count
== 0 || primcount
== 0) {
7295 return error::kNoError
;
7298 GLuint max_vertex_accessed
;
7299 Buffer
* element_array_buffer
=
7300 state_
.vertex_attrib_manager
->element_array_buffer();
7302 if (!element_array_buffer
->GetMaxValueForRange(
7303 offset
, count
, type
, &max_vertex_accessed
)) {
7305 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7306 return error::kNoError
;
7309 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7310 if (!ClearUnclearedTextures()) {
7311 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7312 return error::kNoError
;
7314 bool simulated_attrib_0
= false;
7315 if (!SimulateAttrib0(
7316 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7317 return error::kNoError
;
7319 bool simulated_fixed_attribs
= false;
7320 if (SimulateFixedAttribs(
7321 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7323 bool textures_set
= !PrepareTexturesForRender();
7325 // TODO(gman): Refactor to hide these details in BufferManager or
7326 // VertexAttribManager.
7327 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7328 bool used_client_side_array
= false;
7329 if (element_array_buffer
->IsClientSideArray()) {
7330 used_client_side_array
= true;
7331 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7332 indices
= element_array_buffer
->GetRange(offset
, 0);
7335 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7337 glDrawElements(mode
, count
, type
, indices
);
7339 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7342 if (used_client_side_array
) {
7343 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7344 element_array_buffer
->service_id());
7348 RestoreStateForTextures();
7350 if (simulated_fixed_attribs
) {
7351 RestoreStateForSimulatedFixedAttribs();
7354 if (simulated_attrib_0
) {
7355 // We don't have to restore attrib 0 generic data at the end of this
7356 // function even if it is simulated. This is because we will simulate
7357 // it in each draw call, and attrib 0 generic data queries use cached
7358 // values instead of passing down to the underlying driver.
7359 RestoreStateForAttrib(0, false);
7362 return error::kNoError
;
7365 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7366 const void* cmd_data
) {
7367 // TODO(zmo): crbug.com/481184
7368 // On Desktop GL with versions lower than 4.3, we need to emulate
7369 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7370 const gles2::cmds::DrawElements
& c
=
7371 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7372 return DoDrawElements("glDrawElements",
7374 static_cast<GLenum
>(c
.mode
),
7375 static_cast<GLsizei
>(c
.count
),
7376 static_cast<GLenum
>(c
.type
),
7377 static_cast<int32
>(c
.index_offset
),
7381 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7382 uint32 immediate_data_size
,
7383 const void* cmd_data
) {
7384 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7385 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7386 if (!features().angle_instanced_arrays
) {
7388 GL_INVALID_OPERATION
,
7389 "glDrawElementsInstancedANGLE", "function not available");
7390 return error::kNoError
;
7392 return DoDrawElements("glDrawElementsInstancedANGLE",
7394 static_cast<GLenum
>(c
.mode
),
7395 static_cast<GLsizei
>(c
.count
),
7396 static_cast<GLenum
>(c
.type
),
7397 static_cast<int32
>(c
.index_offset
),
7398 static_cast<GLsizei
>(c
.primcount
));
7401 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7402 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7403 GLuint max_vertex_accessed
= 0;
7404 Buffer
* buffer
= GetBuffer(buffer_id
);
7406 // TODO(gman): Should this be a GL error or a command buffer error?
7408 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7410 if (!buffer
->GetMaxValueForRange(
7411 offset
, count
, type
, &max_vertex_accessed
)) {
7412 // TODO(gman): Should this be a GL error or a command buffer error?
7414 GL_INVALID_OPERATION
,
7415 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7418 return max_vertex_accessed
;
7421 void GLES2DecoderImpl::DoShaderSource(
7422 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7424 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7425 if (length
&& length
[ii
] > 0)
7426 str
.append(data
[ii
], length
[ii
]);
7428 str
.append(data
[ii
]);
7430 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7434 // Note: We don't actually call glShaderSource here. We wait until
7435 // we actually compile the shader.
7436 shader
->set_source(str
);
7439 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7440 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7441 GLenum buffer_mode
) {
7442 Program
* program
= GetProgramInfoNotShader(
7443 client_program_id
, "glTransformFeedbackVaryings");
7447 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7448 glTransformFeedbackVaryings(
7449 program
->service_id(), count
, varyings
, buffer_mode
);
7452 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7453 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7454 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7459 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7460 if (use_shader_translator_
) {
7461 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7462 vertex_translator_
: fragment_translator_
;
7465 const Shader::TranslatedShaderSourceType source_type
=
7466 feature_info_
->feature_flags().angle_translated_shader_source
?
7467 Shader::kANGLE
: Shader::kGL
;
7468 shader
->RequestCompile(translator
, source_type
);
7471 void GLES2DecoderImpl::DoGetShaderiv(
7472 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7473 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7478 // Compile now for statuses that require it.
7480 case GL_COMPILE_STATUS
:
7481 case GL_INFO_LOG_LENGTH
:
7482 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7483 shader
->DoCompile();
7491 case GL_SHADER_SOURCE_LENGTH
:
7492 *params
= shader
->source().size();
7496 case GL_COMPILE_STATUS
:
7497 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7499 case GL_INFO_LOG_LENGTH
:
7500 *params
= shader
->log_info().size();
7504 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7505 *params
= shader
->translated_source().size();
7512 glGetShaderiv(shader
->service_id(), pname
, params
);
7515 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7516 const void* cmd_data
) {
7517 const gles2::cmds::GetShaderSource
& c
=
7518 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7519 GLuint shader_id
= c
.shader
;
7520 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7521 Bucket
* bucket
= CreateBucket(bucket_id
);
7522 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7523 if (!shader
|| shader
->source().empty()) {
7525 return error::kNoError
;
7527 bucket
->SetFromString(shader
->source().c_str());
7528 return error::kNoError
;
7531 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7532 uint32 immediate_data_size
,
7533 const void* cmd_data
) {
7534 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7535 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7537 GLuint shader_id
= c
.shader
;
7538 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7539 Bucket
* bucket
= CreateBucket(bucket_id
);
7540 Shader
* shader
= GetShaderInfoNotProgram(
7541 shader_id
, "glGetTranslatedShaderSourceANGLE");
7544 return error::kNoError
;
7547 // Make sure translator has been utilized in compile.
7548 shader
->DoCompile();
7550 bucket
->SetFromString(shader
->translated_source().c_str());
7551 return error::kNoError
;
7554 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7555 uint32 immediate_data_size
,
7556 const void* cmd_data
) {
7557 const gles2::cmds::GetProgramInfoLog
& c
=
7558 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7559 GLuint program_id
= c
.program
;
7560 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7561 Bucket
* bucket
= CreateBucket(bucket_id
);
7562 Program
* program
= GetProgramInfoNotShader(
7563 program_id
, "glGetProgramInfoLog");
7564 if (!program
|| !program
->log_info()) {
7565 bucket
->SetFromString("");
7566 return error::kNoError
;
7568 bucket
->SetFromString(program
->log_info()->c_str());
7569 return error::kNoError
;
7572 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7573 uint32 immediate_data_size
,
7574 const void* cmd_data
) {
7575 const gles2::cmds::GetShaderInfoLog
& c
=
7576 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7577 GLuint shader_id
= c
.shader
;
7578 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7579 Bucket
* bucket
= CreateBucket(bucket_id
);
7580 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7582 bucket
->SetFromString("");
7583 return error::kNoError
;
7586 // Shader must be compiled in order to get the info log.
7587 shader
->DoCompile();
7589 bucket
->SetFromString(shader
->log_info().c_str());
7590 return error::kNoError
;
7593 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7594 return state_
.GetEnabled(cap
);
7597 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7598 const Buffer
* buffer
= GetBuffer(client_id
);
7599 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7602 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7603 const Framebuffer
* framebuffer
=
7604 GetFramebuffer(client_id
);
7605 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7608 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7609 // IsProgram is true for programs as soon as they are created, until they are
7610 // deleted and no longer in use.
7611 const Program
* program
= GetProgram(client_id
);
7612 return program
!= NULL
&& !program
->IsDeleted();
7615 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7616 const Renderbuffer
* renderbuffer
=
7617 GetRenderbuffer(client_id
);
7618 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7621 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7622 // IsShader is true for shaders as soon as they are created, until they
7623 // are deleted and not attached to any programs.
7624 const Shader
* shader
= GetShader(client_id
);
7625 return shader
!= NULL
&& !shader
->IsDeleted();
7628 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7629 const TextureRef
* texture_ref
= GetTexture(client_id
);
7630 return texture_ref
&& texture_ref
->texture()->IsValid();
7633 void GLES2DecoderImpl::DoAttachShader(
7634 GLuint program_client_id
, GLint shader_client_id
) {
7635 Program
* program
= GetProgramInfoNotShader(
7636 program_client_id
, "glAttachShader");
7640 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7644 if (!program
->AttachShader(shader_manager(), shader
)) {
7646 GL_INVALID_OPERATION
,
7648 "can not attach more than one shader of the same type.");
7651 glAttachShader(program
->service_id(), shader
->service_id());
7654 void GLES2DecoderImpl::DoDetachShader(
7655 GLuint program_client_id
, GLint shader_client_id
) {
7656 Program
* program
= GetProgramInfoNotShader(
7657 program_client_id
, "glDetachShader");
7661 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7665 if (!program
->DetachShader(shader_manager(), shader
)) {
7667 GL_INVALID_OPERATION
,
7668 "glDetachShader", "shader not attached to program");
7671 glDetachShader(program
->service_id(), shader
->service_id());
7674 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7675 Program
* program
= GetProgramInfoNotShader(
7676 program_client_id
, "glValidateProgram");
7680 program
->Validate();
7683 void GLES2DecoderImpl::GetVertexAttribHelper(
7684 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7686 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7688 Buffer
* buffer
= attrib
->buffer();
7689 if (buffer
&& !buffer
->IsDeleted()) {
7691 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7692 *params
= client_id
;
7696 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7697 *params
= attrib
->enabled();
7699 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7700 *params
= attrib
->size();
7702 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7703 *params
= attrib
->gl_stride();
7705 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7706 *params
= attrib
->type();
7708 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7709 *params
= attrib
->normalized();
7711 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7712 *params
= attrib
->divisor();
7714 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7715 *params
= attrib
->integer();
7723 void GLES2DecoderImpl::DoGetTexParameterfv(
7724 GLenum target
, GLenum pname
, GLfloat
* params
) {
7725 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7726 glGetTexParameterfv(target
, pname
, params
);
7729 void GLES2DecoderImpl::DoGetTexParameteriv(
7730 GLenum target
, GLenum pname
, GLint
* params
) {
7731 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7732 glGetTexParameteriv(target
, pname
, params
);
7735 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7736 GLenum target
, GLenum pname
) {
7737 if (!workarounds().init_texture_max_anisotropy
)
7739 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7740 !validators_
->texture_parameter
.IsValid(pname
)) {
7744 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7748 GL_INVALID_OPERATION
,
7749 "glGetTexParamter{fi}v", "unknown texture for target");
7752 Texture
* texture
= texture_ref
->texture();
7753 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7756 template <typename T
>
7757 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7758 GLuint index
, GLenum pname
, T
* params
) {
7759 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7762 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7766 case GL_CURRENT_VERTEX_ATTRIB
:
7767 state_
.attrib_values
[index
].GetValues(params
);
7771 GetVertexAttribHelper(attrib
, pname
, &value
);
7772 *params
= static_cast<T
>(value
);
7778 void GLES2DecoderImpl::DoGetVertexAttribfv(
7779 GLuint index
, GLenum pname
, GLfloat
* params
) {
7780 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7783 void GLES2DecoderImpl::DoGetVertexAttribiv(
7784 GLuint index
, GLenum pname
, GLint
* params
) {
7785 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7788 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7789 GLuint index
, GLenum pname
, GLint
* params
) {
7790 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7793 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7794 GLuint index
, GLenum pname
, GLuint
* params
) {
7795 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7798 template <typename T
>
7799 bool GLES2DecoderImpl::SetVertexAttribValue(
7800 const char* function_name
, GLuint index
, const T
* value
) {
7801 if (index
>= state_
.attrib_values
.size()) {
7802 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7805 state_
.attrib_values
[index
].SetValues(value
);
7809 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7810 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7811 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7812 glVertexAttrib1f(index
, v0
);
7816 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7817 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7818 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7819 glVertexAttrib2f(index
, v0
, v1
);
7823 void GLES2DecoderImpl::DoVertexAttrib3f(
7824 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7825 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7826 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7827 glVertexAttrib3f(index
, v0
, v1
, v2
);
7831 void GLES2DecoderImpl::DoVertexAttrib4f(
7832 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7833 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7834 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7835 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7839 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7840 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7841 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7842 glVertexAttrib1fv(index
, v
);
7846 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7847 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7848 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7849 glVertexAttrib2fv(index
, v
);
7853 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7854 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7855 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7856 glVertexAttrib3fv(index
, v
);
7860 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7861 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7862 glVertexAttrib4fv(index
, v
);
7866 void GLES2DecoderImpl::DoVertexAttribI4i(
7867 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
7868 GLint v
[4] = { v0
, v1
, v2
, v3
};
7869 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
7870 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
7874 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
7875 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
7876 glVertexAttribI4iv(index
, v
);
7880 void GLES2DecoderImpl::DoVertexAttribI4ui(
7881 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
7882 GLuint v
[4] = { v0
, v1
, v2
, v3
};
7883 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
7884 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
7888 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
7889 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
7890 glVertexAttribI4uiv(index
, v
);
7894 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7895 uint32 immediate_data_size
,
7896 const void* cmd_data
) {
7897 if (!unsafe_es3_apis_enabled())
7898 return error::kUnknownCommand
;
7899 const gles2::cmds::VertexAttribIPointer
& c
=
7900 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7902 if (!state_
.bound_array_buffer
.get() ||
7903 state_
.bound_array_buffer
->IsDeleted()) {
7904 if (state_
.vertex_attrib_manager
.get() ==
7905 state_
.default_vertex_attrib_manager
.get()) {
7907 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
7908 return error::kNoError
;
7909 } else if (c
.offset
!= 0) {
7912 "glVertexAttribIPointer", "client side arrays are not allowed");
7913 return error::kNoError
;
7917 GLuint indx
= c
.indx
;
7918 GLint size
= c
.size
;
7919 GLenum type
= c
.type
;
7920 GLsizei stride
= c
.stride
;
7921 GLsizei offset
= c
.offset
;
7922 const void* ptr
= reinterpret_cast<const void*>(offset
);
7923 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
7924 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
7925 return error::kNoError
;
7927 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7929 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7930 return error::kNoError
;
7932 if (indx
>= group_
->max_vertex_attribs()) {
7934 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
7935 return error::kNoError
;
7939 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
7940 return error::kNoError
;
7944 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
7945 return error::kNoError
;
7949 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
7950 return error::kNoError
;
7952 GLsizei component_size
=
7953 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7954 // component_size must be a power of two to use & as optimized modulo.
7955 DCHECK(GLES2Util::IsPOT(component_size
));
7956 if (offset
& (component_size
- 1)) {
7958 GL_INVALID_OPERATION
,
7959 "glVertexAttribIPointer", "offset not valid for type");
7960 return error::kNoError
;
7962 if (stride
& (component_size
- 1)) {
7964 GL_INVALID_OPERATION
,
7965 "glVertexAttribIPointer", "stride not valid for type");
7966 return error::kNoError
;
7968 state_
.vertex_attrib_manager
7969 ->SetAttribInfo(indx
,
7970 state_
.bound_array_buffer
.get(),
7975 stride
!= 0 ? stride
: component_size
* size
,
7978 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7979 return error::kNoError
;
7982 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7983 uint32 immediate_data_size
,
7984 const void* cmd_data
) {
7985 const gles2::cmds::VertexAttribPointer
& c
=
7986 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7988 if (!state_
.bound_array_buffer
.get() ||
7989 state_
.bound_array_buffer
->IsDeleted()) {
7990 if (state_
.vertex_attrib_manager
.get() ==
7991 state_
.default_vertex_attrib_manager
.get()) {
7993 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7994 return error::kNoError
;
7995 } else if (c
.offset
!= 0) {
7998 "glVertexAttribPointer", "client side arrays are not allowed");
7999 return error::kNoError
;
8003 GLuint indx
= c
.indx
;
8004 GLint size
= c
.size
;
8005 GLenum type
= c
.type
;
8006 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8007 GLsizei stride
= c
.stride
;
8008 GLsizei offset
= c
.offset
;
8009 const void* ptr
= reinterpret_cast<const void*>(offset
);
8010 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8011 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8012 return error::kNoError
;
8014 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8016 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8017 return error::kNoError
;
8019 if (indx
>= group_
->max_vertex_attribs()) {
8021 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8022 return error::kNoError
;
8026 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8027 return error::kNoError
;
8031 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8032 return error::kNoError
;
8036 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8037 return error::kNoError
;
8039 GLsizei component_size
=
8040 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8041 // component_size must be a power of two to use & as optimized modulo.
8042 DCHECK(GLES2Util::IsPOT(component_size
));
8043 if (offset
& (component_size
- 1)) {
8045 GL_INVALID_OPERATION
,
8046 "glVertexAttribPointer", "offset not valid for type");
8047 return error::kNoError
;
8049 if (stride
& (component_size
- 1)) {
8051 GL_INVALID_OPERATION
,
8052 "glVertexAttribPointer", "stride not valid for type");
8053 return error::kNoError
;
8055 state_
.vertex_attrib_manager
8056 ->SetAttribInfo(indx
,
8057 state_
.bound_array_buffer
.get(),
8062 stride
!= 0 ? stride
: component_size
* size
,
8065 // We support GL_FIXED natively on EGL/GLES2 implementations
8066 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8067 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8069 return error::kNoError
;
8072 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8074 state_
.viewport_x
= x
;
8075 state_
.viewport_y
= y
;
8076 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8077 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8078 glViewport(x
, y
, width
, height
);
8081 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8082 uint32 immediate_data_size
,
8083 const void* cmd_data
) {
8084 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8085 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8086 if (!features().angle_instanced_arrays
) {
8088 GL_INVALID_OPERATION
,
8089 "glVertexAttribDivisorANGLE", "function not available");
8090 return error::kNoError
;
8092 GLuint index
= c
.index
;
8093 GLuint divisor
= c
.divisor
;
8094 if (index
>= group_
->max_vertex_attribs()) {
8097 "glVertexAttribDivisorANGLE", "index out of range");
8098 return error::kNoError
;
8101 state_
.vertex_attrib_manager
->SetDivisor(
8104 glVertexAttribDivisorANGLE(index
, divisor
);
8105 return error::kNoError
;
8108 template <typename pixel_data_type
>
8109 static void WriteAlphaData(
8110 void* pixels
, uint32 row_count
, uint32 channel_count
,
8111 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8112 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8113 DCHECK_GT(channel_count
, 0U);
8114 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8115 uint32 unpadded_row_size_in_elements
=
8116 unpadded_row_size
/ sizeof(pixel_data_type
);
8117 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8118 uint32 padded_row_size_in_elements
=
8119 padded_row_size
/ sizeof(pixel_data_type
);
8120 pixel_data_type
* dst
=
8121 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8122 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8123 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8124 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8127 dst
+= padded_row_size_in_elements
;
8131 void GLES2DecoderImpl::FinishReadPixels(
8132 const cmds::ReadPixels
& c
,
8134 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8135 GLsizei width
= c
.width
;
8136 GLsizei height
= c
.height
;
8137 GLenum format
= c
.format
;
8138 GLenum type
= c
.type
;
8139 typedef cmds::ReadPixels::Result Result
;
8141 Result
* result
= NULL
;
8142 if (c
.result_shm_id
!= 0) {
8143 result
= GetSharedMemoryAs
<Result
*>(
8144 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8147 glDeleteBuffersARB(1, &buffer
);
8152 GLES2Util::ComputeImageDataSizes(
8153 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8155 void* pixels
= GetSharedMemoryAs
<void*>(
8156 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8159 glDeleteBuffersARB(1, &buffer
);
8165 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8167 if (features().map_buffer_range
) {
8168 data
= glMapBufferRange(
8169 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8171 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8174 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8175 "Unable to map memory for readback.");
8178 memcpy(pixels
, data
, pixels_size
);
8179 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8180 // have to restore the state.
8181 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8182 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8183 glDeleteBuffersARB(1, &buffer
);
8186 if (result
!= NULL
) {
8190 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8191 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8192 if ((channels_exist
& 0x0008) == 0 &&
8193 workarounds().clear_alpha_in_readpixels
) {
8194 // Set the alpha to 255 because some drivers are buggy in this regard.
8197 uint32 unpadded_row_size
;
8198 uint32 padded_row_size
;
8199 if (!GLES2Util::ComputeImageDataSizes(
8200 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8201 &unpadded_row_size
, &padded_row_size
)) {
8205 uint32 channel_count
= 0;
8206 uint32 alpha_channel
= 0;
8219 if (channel_count
> 0) {
8221 case GL_UNSIGNED_BYTE
:
8222 WriteAlphaData
<uint8
>(
8223 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8224 padded_row_size
, 0xFF);
8227 WriteAlphaData
<float>(
8228 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8229 padded_row_size
, 1.0f
);
8232 WriteAlphaData
<uint16
>(
8233 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8234 padded_row_size
, 0x3C00);
8241 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8242 const void* cmd_data
) {
8243 const gles2::cmds::ReadPixels
& c
=
8244 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8245 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8246 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8247 if (fbo_error
!= error::kNoError
)
8251 GLsizei width
= c
.width
;
8252 GLsizei height
= c
.height
;
8253 GLenum format
= c
.format
;
8254 GLenum type
= c
.type
;
8255 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8256 if (width
< 0 || height
< 0) {
8257 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8258 return error::kNoError
;
8260 typedef cmds::ReadPixels::Result Result
;
8262 if (!GLES2Util::ComputeImageDataSizes(
8263 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8265 return error::kOutOfBounds
;
8267 void* pixels
= GetSharedMemoryAs
<void*>(
8268 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8270 return error::kOutOfBounds
;
8272 Result
* result
= NULL
;
8273 if (c
.result_shm_id
!= 0) {
8274 result
= GetSharedMemoryAs
<Result
*>(
8275 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8277 return error::kOutOfBounds
;
8281 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8282 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8283 return error::kNoError
;
8285 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8286 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8287 return error::kNoError
;
8289 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8290 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8291 // format and type are acceptable enums but not guaranteed to be supported
8292 // for this framebuffer. Have to ask gl if they are valid.
8293 GLint preferred_format
= 0;
8294 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8295 GLint preferred_type
= 0;
8296 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8297 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8298 type
!= static_cast<GLenum
>(preferred_type
)) {
8300 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8301 "with the current read framebuffer");
8302 return error::kNoError
;
8305 if (width
== 0 || height
== 0) {
8306 return error::kNoError
;
8309 // Get the size of the current fbo or backbuffer.
8310 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8314 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8316 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8317 return error::kNoError
;
8320 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8321 return error::kNoError
;
8324 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8325 return error::kNoError
;
8328 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8330 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8332 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8333 // The user requested an out of range area. Get the results 1 line
8336 uint32 unpadded_row_size
;
8337 uint32 padded_row_size
;
8338 if (!GLES2Util::ComputeImageDataSizes(
8339 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8340 &unpadded_row_size
, &padded_row_size
)) {
8342 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8343 return error::kNoError
;
8346 GLint dest_x_offset
= std::max(-x
, 0);
8347 uint32 dest_row_offset
;
8348 if (!GLES2Util::ComputeImageDataSizes(
8349 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8350 &dest_row_offset
, NULL
, NULL
)) {
8352 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8353 return error::kNoError
;
8356 // Copy each row into the larger dest rect.
8357 int8
* dst
= static_cast<int8
*>(pixels
);
8358 GLint read_x
= std::max(0, x
);
8359 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8360 GLint read_width
= read_end_x
- read_x
;
8361 for (GLint yy
= 0; yy
< height
; ++yy
) {
8365 memset(dst
, 0, unpadded_row_size
);
8367 // If the row is in range, copy it.
8368 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8370 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8372 dst
+= padded_row_size
;
8375 if (async
&& features().use_async_readpixels
) {
8377 glGenBuffersARB(1, &buffer
);
8378 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8379 // For ANGLE client version 2, GL_STREAM_READ is not available.
8380 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8381 GL_STATIC_DRAW
: GL_STREAM_READ
;
8382 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8383 GLenum error
= glGetError();
8384 if (error
== GL_NO_ERROR
) {
8385 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8386 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8387 new FenceCallback()));
8388 WaitForReadPixels(base::Bind(
8389 &GLES2DecoderImpl::FinishReadPixels
,
8390 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8391 <GLES2DecoderImpl
>(this),
8393 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8394 return error::kNoError
;
8396 // On error, unbind pack buffer and fall through to sync readpixels
8397 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8398 glDeleteBuffersARB(1, &buffer
);
8401 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8403 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8404 if (error
== GL_NO_ERROR
) {
8405 if (result
!= NULL
) {
8408 FinishReadPixels(c
, 0);
8411 return error::kNoError
;
8414 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8415 const void* cmd_data
) {
8416 const gles2::cmds::PixelStorei
& c
=
8417 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8418 GLenum pname
= c
.pname
;
8419 GLenum param
= c
.param
;
8420 if (!validators_
->pixel_store
.IsValid(pname
)) {
8421 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8422 return error::kNoError
;
8425 case GL_PACK_ALIGNMENT
:
8426 case GL_UNPACK_ALIGNMENT
:
8427 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8429 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8430 return error::kNoError
;
8433 case GL_UNPACK_FLIP_Y_CHROMIUM
:
8434 unpack_flip_y_
= (param
!= 0);
8435 return error::kNoError
;
8436 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
8437 unpack_premultiply_alpha_
= (param
!= 0);
8438 return error::kNoError
;
8439 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
8440 unpack_unpremultiply_alpha_
= (param
!= 0);
8441 return error::kNoError
;
8445 glPixelStorei(pname
, param
);
8447 case GL_PACK_ALIGNMENT
:
8448 state_
.pack_alignment
= param
;
8450 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8451 state_
.pack_reverse_row_order
= (param
!= 0);
8453 case GL_UNPACK_ALIGNMENT
:
8454 state_
.unpack_alignment
= param
;
8457 // Validation should have prevented us from getting here.
8461 return error::kNoError
;
8464 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8465 uint32 immediate_data_size
,
8466 const void* cmd_data
) {
8467 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8468 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8469 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8471 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8473 if (!supports_post_sub_buffer_
) {
8475 GL_INVALID_OPERATION
,
8476 "glPostSubBufferCHROMIUM", "command not supported by surface");
8477 return error::kNoError
;
8480 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8483 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8484 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8485 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8486 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8488 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8489 return error::kNoError
;
8491 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8492 return error::kLostContext
;
8496 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8497 uint32 immediate_data_size
,
8498 const void* cmd_data
) {
8499 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8500 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8501 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8503 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8504 "glScheduleOverlayPlaneCHROMIUM",
8506 return error::kNoError
;
8508 gfx::GLImage
* image
=
8509 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8511 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8512 "glScheduleOverlayPlaneCHROMIUM",
8513 "unsupported texture format");
8514 return error::kNoError
;
8516 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8517 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8518 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8519 "glScheduleOverlayPlaneCHROMIUM",
8520 "invalid transform enum");
8521 return error::kNoError
;
8523 if (!surface_
->ScheduleOverlayPlane(
8527 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8528 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8530 "glScheduleOverlayPlaneCHROMIUM",
8531 "failed to schedule overlay");
8533 return error::kNoError
;
8536 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8537 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8538 const std::string
& name_str
) {
8539 if (!StringIsValidForGLES(name_str
.c_str())) {
8541 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8542 return error::kNoError
;
8544 Program
* program
= GetProgramInfoNotShader(
8545 client_id
, "glGetAttribLocation");
8547 return error::kNoError
;
8549 if (!program
->IsValid()) {
8551 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8552 return error::kNoError
;
8554 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8555 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8557 return error::kOutOfBounds
;
8559 // Require the client to init this incase the context is lost and we are no
8560 // longer executing commands.
8561 if (*location
!= -1) {
8562 return error::kGenericError
;
8564 *location
= program
->GetAttribLocation(name_str
);
8565 return error::kNoError
;
8568 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8569 uint32 immediate_data_size
,
8570 const void* cmd_data
) {
8571 const gles2::cmds::GetAttribLocation
& c
=
8572 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8573 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8575 return error::kInvalidArguments
;
8577 std::string name_str
;
8578 if (!bucket
->GetAsString(&name_str
)) {
8579 return error::kInvalidArguments
;
8581 return GetAttribLocationHelper(
8582 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8585 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8586 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8587 const std::string
& name_str
) {
8588 if (!StringIsValidForGLES(name_str
.c_str())) {
8590 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8591 return error::kNoError
;
8593 Program
* program
= GetProgramInfoNotShader(
8594 client_id
, "glGetUniformLocation");
8596 return error::kNoError
;
8598 if (!program
->IsValid()) {
8600 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8601 return error::kNoError
;
8603 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8604 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8606 return error::kOutOfBounds
;
8608 // Require the client to init this incase the context is lost an we are no
8609 // longer executing commands.
8610 if (*location
!= -1) {
8611 return error::kGenericError
;
8613 *location
= program
->GetUniformFakeLocation(name_str
);
8614 return error::kNoError
;
8617 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8618 uint32 immediate_data_size
,
8619 const void* cmd_data
) {
8620 const gles2::cmds::GetUniformLocation
& c
=
8621 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8622 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8624 return error::kInvalidArguments
;
8626 std::string name_str
;
8627 if (!bucket
->GetAsString(&name_str
)) {
8628 return error::kInvalidArguments
;
8630 return GetUniformLocationHelper(
8631 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8634 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8635 uint32 immediate_data_size
,
8636 const void* cmd_data
) {
8637 if (!unsafe_es3_apis_enabled())
8638 return error::kUnknownCommand
;
8639 const gles2::cmds::GetUniformIndices
& c
=
8640 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8641 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8643 return error::kInvalidArguments
;
8646 std::vector
<char*> names
;
8647 std::vector
<GLint
> len
;
8648 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8649 return error::kInvalidArguments
;
8651 typedef cmds::GetUniformIndices::Result Result
;
8652 Result
* result
= GetSharedMemoryAs
<Result
*>(
8653 c
.indices_shm_id
, c
.indices_shm_offset
,
8654 Result::ComputeSize(static_cast<size_t>(count
)));
8655 GLuint
* indices
= result
? result
->GetData() : NULL
;
8656 if (indices
== NULL
) {
8657 return error::kOutOfBounds
;
8659 // Check that the client initialized the result.
8660 if (result
->size
!= 0) {
8661 return error::kInvalidArguments
;
8663 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8665 return error::kNoError
;
8667 GLuint service_id
= program
->service_id();
8668 GLint link_status
= GL_FALSE
;
8669 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8670 if (link_status
!= GL_TRUE
) {
8671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8672 "glGetUniformIndices", "program not linked");
8673 return error::kNoError
;
8675 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8676 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8677 GLenum error
= glGetError();
8678 if (error
== GL_NO_ERROR
) {
8679 result
->SetNumResults(count
);
8681 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8683 return error::kNoError
;
8686 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8687 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8688 const std::string
& name_str
) {
8689 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8690 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8692 return error::kOutOfBounds
;
8694 // Require the client to init this incase the context is lost and we are no
8695 // longer executing commands.
8696 if (*location
!= -1) {
8697 return error::kGenericError
;
8699 Program
* program
= GetProgramInfoNotShader(
8700 client_id
, "glGetFragDataLocation");
8702 return error::kNoError
;
8704 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8705 return error::kNoError
;
8708 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8709 uint32 immediate_data_size
,
8710 const void* cmd_data
) {
8711 if (!unsafe_es3_apis_enabled())
8712 return error::kUnknownCommand
;
8713 const gles2::cmds::GetFragDataLocation
& c
=
8714 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8715 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8717 return error::kInvalidArguments
;
8719 std::string name_str
;
8720 if (!bucket
->GetAsString(&name_str
)) {
8721 return error::kInvalidArguments
;
8723 return GetFragDataLocationHelper(
8724 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8727 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8728 uint32 immediate_data_size
, const void* cmd_data
) {
8729 if (!unsafe_es3_apis_enabled())
8730 return error::kUnknownCommand
;
8731 const gles2::cmds::GetUniformBlockIndex
& c
=
8732 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8733 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8735 return error::kInvalidArguments
;
8737 std::string name_str
;
8738 if (!bucket
->GetAsString(&name_str
)) {
8739 return error::kInvalidArguments
;
8741 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8742 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8744 return error::kOutOfBounds
;
8746 // Require the client to init this in case the context is lost and we are no
8747 // longer executing commands.
8748 if (*index
!= GL_INVALID_INDEX
) {
8749 return error::kGenericError
;
8751 Program
* program
= GetProgramInfoNotShader(
8752 c
.program
, "glGetUniformBlockIndex");
8754 return error::kNoError
;
8756 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8757 return error::kNoError
;
8760 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8761 const void* cmd_data
) {
8762 const gles2::cmds::GetString
& c
=
8763 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8764 GLenum name
= static_cast<GLenum
>(c
.name
);
8765 if (!validators_
->string_type
.IsValid(name
)) {
8766 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8767 return error::kNoError
;
8770 const char* str
= nullptr;
8771 std::string extensions
;
8774 str
= "OpenGL ES 2.0 Chromium";
8776 case GL_SHADING_LANGUAGE_VERSION
:
8777 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8781 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8782 // They are used by WEBGL_debug_renderer_info.
8783 if (!force_webgl_glsl_validation_
)
8786 str
= reinterpret_cast<const char*>(glGetString(name
));
8790 // For WebGL contexts, strip out the OES derivatives and
8791 // EXT frag depth extensions if they have not been enabled.
8792 if (force_webgl_glsl_validation_
) {
8793 extensions
= feature_info_
->extensions();
8794 if (!derivatives_explicitly_enabled_
) {
8795 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8796 if (std::string::npos
!= offset
) {
8797 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8801 if (!frag_depth_explicitly_enabled_
) {
8802 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8803 if (std::string::npos
!= offset
) {
8804 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8808 if (!draw_buffers_explicitly_enabled_
) {
8809 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8810 if (std::string::npos
!= offset
) {
8811 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8815 if (!shader_texture_lod_explicitly_enabled_
) {
8816 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8817 if (std::string::npos
!= offset
) {
8818 extensions
.replace(offset
,
8819 arraysize(kEXTShaderTextureLodExtension
),
8824 extensions
= feature_info_
->extensions().c_str();
8826 if (supports_post_sub_buffer_
)
8827 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8828 str
= extensions
.c_str();
8832 str
= reinterpret_cast<const char*>(glGetString(name
));
8835 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8836 bucket
->SetFromString(str
);
8837 return error::kNoError
;
8840 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8841 const void* cmd_data
) {
8842 const gles2::cmds::BufferData
& c
=
8843 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8844 GLenum target
= static_cast<GLenum
>(c
.target
);
8845 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8846 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8847 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8848 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8849 const void* data
= NULL
;
8850 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8851 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8853 return error::kOutOfBounds
;
8856 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8857 return error::kNoError
;
8860 void GLES2DecoderImpl::DoBufferSubData(
8861 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8862 // Just delegate it. Some validation is actually done before this.
8863 buffer_manager()->ValidateAndDoBufferSubData(
8864 &state_
, target
, offset
, size
, data
);
8867 bool GLES2DecoderImpl::ClearLevel(
8871 unsigned internal_format
,
8876 bool is_texture_immutable
) {
8877 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8878 if (feature_info_
->feature_flags().angle_depth_texture
&&
8879 (channels
& GLES2Util::kDepth
) != 0) {
8880 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8881 // on depth formats.
8883 glGenFramebuffersEXT(1, &fb
);
8884 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8886 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8887 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8888 GL_DEPTH_ATTACHMENT
;
8890 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8891 texture
->service_id(), level
);
8892 // ANGLE promises a depth only attachment ok.
8893 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8894 GL_FRAMEBUFFER_COMPLETE
) {
8898 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8899 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8901 state_
.SetDeviceDepthMask(GL_TRUE
);
8902 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8903 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8905 RestoreClearState();
8907 glDeleteFramebuffersEXT(1, &fb
);
8908 Framebuffer
* framebuffer
=
8909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8910 GLuint fb_service_id
=
8911 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8912 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8916 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8919 uint32 padded_row_size
;
8920 if (!GLES2Util::ComputeImageDataSizes(
8921 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8922 NULL
, &padded_row_size
)) {
8926 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8930 if (size
> kMaxZeroSize
) {
8931 if (kMaxZeroSize
< padded_row_size
) {
8932 // That'd be an awfully large texture.
8935 // We should never have a large total size with a zero row size.
8936 DCHECK_GT(padded_row_size
, 0U);
8937 tile_height
= kMaxZeroSize
/ padded_row_size
;
8938 if (!GLES2Util::ComputeImageDataSizes(
8939 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8944 tile_height
= height
;
8947 // Assumes the size has already been checked.
8948 scoped_ptr
<char[]> zero(new char[size
]);
8949 memset(zero
.get(), 0, size
);
8950 glBindTexture(texture
->target(), texture
->service_id());
8952 bool has_images
= texture
->HasImages();
8954 while (y
< height
) {
8955 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8956 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8957 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8960 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8965 TextureRef
* bound_texture
=
8966 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8967 glBindTexture(texture
->target(),
8968 bound_texture
? bound_texture
->service_id() : 0);
8974 const int kS3TCBlockWidth
= 4;
8975 const int kS3TCBlockHeight
= 4;
8976 const int kS3TCDXT1BlockSize
= 8;
8977 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8978 const int kEACAndETC2BlockSize
= 4;
8980 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8981 return (size
== 1) ||
8982 (size
== 2) || !(size
% kS3TCBlockWidth
);
8985 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8986 return GLES2Util::IsPOT(size
);
8989 } // anonymous namespace.
8991 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8992 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
8993 GLenum format
, GLsizei size
) {
8994 base::CheckedNumeric
<GLsizei
> bytes_required(0);
8997 case GL_ATC_RGB_AMD
:
8998 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8999 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9000 case GL_ETC1_RGB8_OES
:
9002 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9004 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9005 bytes_required
*= kS3TCDXT1BlockSize
;
9007 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9008 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9009 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9010 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9012 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9014 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9015 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9017 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9018 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9019 bytes_required
= std::max(width
, 8);
9020 bytes_required
*= std::max(height
, 8);
9021 bytes_required
*= 4;
9022 bytes_required
+= 7;
9023 bytes_required
/= 8;
9025 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9026 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9027 bytes_required
= std::max(width
, 16);
9028 bytes_required
*= std::max(height
, 8);
9029 bytes_required
*= 2;
9030 bytes_required
+= 7;
9031 bytes_required
/= 8;
9035 case GL_COMPRESSED_R11_EAC
:
9036 case GL_COMPRESSED_SIGNED_R11_EAC
:
9037 case GL_COMPRESSED_RGB8_ETC2
:
9038 case GL_COMPRESSED_SRGB8_ETC2
:
9039 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9040 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9042 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9044 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9045 bytes_required
*= 8;
9046 bytes_required
*= depth
;
9048 case GL_COMPRESSED_RG11_EAC
:
9049 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9050 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9051 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9053 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9055 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9056 bytes_required
*= 16;
9057 bytes_required
*= depth
;
9060 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9064 if (!bytes_required
.IsValid() || size
!= bytes_required
.ValueOrDefault(0)) {
9066 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9073 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9074 const char* function_name
, GLenum target
, GLint level
,
9075 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9077 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9078 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9079 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9080 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9081 DCHECK_EQ(1, depth
); // 2D formats.
9082 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9084 GL_INVALID_OPERATION
, function_name
,
9085 "width or height invalid for level");
9089 case GL_ATC_RGB_AMD
:
9090 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9091 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9092 case GL_ETC1_RGB8_OES
:
9093 DCHECK_EQ(1, depth
); // 2D formats.
9094 if (width
<= 0 || height
<= 0) {
9096 GL_INVALID_OPERATION
, function_name
,
9097 "width or height invalid for level");
9101 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9102 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9103 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9104 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9105 DCHECK_EQ(1, depth
); // 2D formats.
9106 if (!IsValidPVRTCSize(level
, width
) ||
9107 !IsValidPVRTCSize(level
, height
)) {
9109 GL_INVALID_OPERATION
, function_name
,
9110 "width or height invalid for level");
9116 case GL_COMPRESSED_R11_EAC
:
9117 case GL_COMPRESSED_SIGNED_R11_EAC
:
9118 case GL_COMPRESSED_RG11_EAC
:
9119 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9120 case GL_COMPRESSED_RGB8_ETC2
:
9121 case GL_COMPRESSED_SRGB8_ETC2
:
9122 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9123 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9124 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9125 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9126 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9128 GL_INVALID_OPERATION
, function_name
,
9129 "width, height, or depth invalid");
9132 if (target
== GL_TEXTURE_3D
) {
9134 GL_INVALID_OPERATION
, function_name
,
9135 "target invalid for format");
9144 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9145 const char* function_name
,
9146 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9147 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9149 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9151 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9156 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9157 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9158 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9159 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9160 const int kBlockWidth
= 4;
9161 const int kBlockHeight
= 4;
9162 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9164 GL_INVALID_OPERATION
, function_name
,
9165 "xoffset or yoffset not multiple of 4");
9168 GLsizei tex_width
= 0;
9169 GLsizei tex_height
= 0;
9170 if (!texture
->GetLevelSize(target
, level
,
9171 &tex_width
, &tex_height
, nullptr) ||
9172 width
- xoffset
> tex_width
||
9173 height
- yoffset
> tex_height
) {
9175 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9178 return ValidateCompressedTexDimensions(
9179 function_name
, target
, level
, width
, height
, 1, format
);
9181 case GL_ATC_RGB_AMD
:
9182 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9183 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9185 GL_INVALID_OPERATION
, function_name
,
9186 "not supported for ATC textures");
9189 case GL_ETC1_RGB8_OES
: {
9191 GL_INVALID_OPERATION
, function_name
,
9192 "not supported for ECT1_RGB8_OES textures");
9195 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9196 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9197 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9198 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9199 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9201 GL_INVALID_OPERATION
, function_name
,
9202 "xoffset and yoffset must be zero");
9205 GLsizei tex_width
= 0;
9206 GLsizei tex_height
= 0;
9207 if (!texture
->GetLevelSize(target
, level
,
9208 &tex_width
, &tex_height
, nullptr) ||
9209 width
!= tex_width
||
9210 height
!= tex_height
) {
9212 GL_INVALID_OPERATION
, function_name
,
9213 "dimensions must match existing texture level dimensions");
9216 return ValidateCompressedTexDimensions(
9217 function_name
, target
, level
, width
, height
, 1, format
);
9221 case GL_COMPRESSED_R11_EAC
:
9222 case GL_COMPRESSED_SIGNED_R11_EAC
:
9223 case GL_COMPRESSED_RG11_EAC
:
9224 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9225 case GL_COMPRESSED_RGB8_ETC2
:
9226 case GL_COMPRESSED_SRGB8_ETC2
:
9227 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9228 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9229 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9230 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9232 const int kBlockSize
= 4;
9233 GLsizei tex_width
, tex_height
;
9234 if (target
== GL_TEXTURE_3D
||
9235 !texture
->GetLevelSize(target
, level
,
9236 &tex_width
, &tex_height
, nullptr) ||
9237 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9238 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9239 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9241 GL_INVALID_OPERATION
, function_name
,
9242 "dimensions must match existing texture level dimensions");
9252 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9255 GLenum internal_format
,
9261 if (!validators_
->texture_target
.IsValid(target
)) {
9262 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9263 "glCompressedTexImage2D", target
, "target");
9264 return error::kNoError
;
9266 if (!validators_
->compressed_texture_format
.IsValid(
9268 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9269 "glCompressedTexImage2D", internal_format
, "internal_format");
9270 return error::kNoError
;
9272 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9276 "glCompressedTexImage2D", "dimensions out of range");
9277 return error::kNoError
;
9279 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9284 "glCompressedTexImage2D", "unknown texture target");
9285 return error::kNoError
;
9287 Texture
* texture
= texture_ref
->texture();
9288 if (texture
->IsImmutable()) {
9290 GL_INVALID_OPERATION
,
9291 "glCompressedTexImage2D", "texture is immutable");
9292 return error::kNoError
;
9295 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9296 width
, height
, 1, internal_format
) ||
9297 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9298 1, internal_format
, image_size
)) {
9299 return error::kNoError
;
9302 if (!EnsureGPUMemoryAvailable(image_size
)) {
9304 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9305 return error::kNoError
;
9308 if (texture
->IsAttachedToFramebuffer()) {
9309 framebuffer_state_
.clear_state_dirty
= true;
9312 scoped_ptr
<int8
[]> zero
;
9314 zero
.reset(new int8
[image_size
]);
9315 memset(zero
.get(), 0, image_size
);
9318 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9319 glCompressedTexImage2D(
9320 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9321 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9322 if (error
== GL_NO_ERROR
) {
9323 texture_manager()->SetLevelInfo(
9324 texture_ref
, target
, level
, internal_format
,
9325 width
, height
, 1, border
, 0, 0, true);
9328 // This may be a slow command. Exit command processing to allow for
9329 // context preemption and GPU watchdog checks.
9330 ExitCommandProcessingEarly();
9331 return error::kNoError
;
9334 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9335 uint32 immediate_data_size
,
9336 const void* cmd_data
) {
9337 const gles2::cmds::CompressedTexImage2D
& c
=
9338 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9339 GLenum target
= static_cast<GLenum
>(c
.target
);
9340 GLint level
= static_cast<GLint
>(c
.level
);
9341 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9342 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9343 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9344 GLint border
= static_cast<GLint
>(c
.border
);
9345 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9346 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9347 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9348 const void* data
= NULL
;
9349 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9350 data
= GetSharedMemoryAs
<const void*>(
9351 data_shm_id
, data_shm_offset
, image_size
);
9353 return error::kOutOfBounds
;
9356 return DoCompressedTexImage2D(
9357 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9360 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9361 uint32 immediate_data_size
,
9362 const void* cmd_data
) {
9363 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9364 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9365 GLenum target
= static_cast<GLenum
>(c
.target
);
9366 GLint level
= static_cast<GLint
>(c
.level
);
9367 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9368 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9369 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9370 GLint border
= static_cast<GLint
>(c
.border
);
9371 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9373 return error::kInvalidArguments
;
9375 uint32 data_size
= bucket
->size();
9376 GLsizei imageSize
= data_size
;
9377 const void* data
= bucket
->GetData(0, data_size
);
9379 return error::kInvalidArguments
;
9381 return DoCompressedTexImage2D(
9382 target
, level
, internal_format
, width
, height
, border
,
9386 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9387 uint32 immediate_data_size
,
9388 const void* cmd_data
) {
9389 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9390 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9391 GLenum target
= static_cast<GLenum
>(c
.target
);
9392 GLint level
= static_cast<GLint
>(c
.level
);
9393 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9394 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9395 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9396 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9397 GLenum format
= static_cast<GLenum
>(c
.format
);
9398 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9400 return error::kInvalidArguments
;
9402 uint32 data_size
= bucket
->size();
9403 GLsizei imageSize
= data_size
;
9404 const void* data
= bucket
->GetData(0, data_size
);
9406 return error::kInvalidArguments
;
9408 if (!validators_
->texture_target
.IsValid(target
)) {
9410 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9411 return error::kNoError
;
9413 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9414 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9415 "glCompressedTexSubImage2D", format
, "format");
9416 return error::kNoError
;
9420 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9421 return error::kNoError
;
9425 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9426 return error::kNoError
;
9428 if (imageSize
< 0) {
9430 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9431 return error::kNoError
;
9433 DoCompressedTexSubImage2D(
9434 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9435 return error::kNoError
;
9438 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9441 GLenum internal_format
,
9448 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9449 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9450 "glCompressedTexImage3D", target
, "target");
9451 return error::kNoError
;
9453 if (!validators_
->compressed_texture_format
.IsValid(
9455 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9456 "glCompressedTexImage3D", internal_format
, "internal_format");
9457 return error::kNoError
;
9459 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9463 "glCompressedTexImage3D", "dimensions out of range");
9464 return error::kNoError
;
9466 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9471 "glCompressedTexImage3D", "unknown texture target");
9472 return error::kNoError
;
9474 Texture
* texture
= texture_ref
->texture();
9475 if (texture
->IsImmutable()) {
9477 GL_INVALID_OPERATION
,
9478 "glCompressedTexImage3D", "texture is immutable");
9479 return error::kNoError
;
9482 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9483 width
, height
, depth
, internal_format
) ||
9484 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9485 depth
, internal_format
, image_size
)) {
9486 return error::kNoError
;
9489 if (!EnsureGPUMemoryAvailable(image_size
)) {
9491 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9492 return error::kNoError
;
9495 if (texture
->IsAttachedToFramebuffer()) {
9496 framebuffer_state_
.clear_state_dirty
= true;
9499 scoped_ptr
<int8
[]> zero
;
9501 zero
.reset(new int8
[image_size
]);
9502 memset(zero
.get(), 0, image_size
);
9505 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9506 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9507 border
, image_size
, data
);
9508 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9509 if (error
== GL_NO_ERROR
) {
9510 texture_manager()->SetLevelInfo(
9511 texture_ref
, target
, level
, internal_format
,
9512 width
, height
, depth
, border
, 0, 0, true);
9515 // This may be a slow command. Exit command processing to allow for
9516 // context preemption and GPU watchdog checks.
9517 ExitCommandProcessingEarly();
9518 return error::kNoError
;
9521 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9522 uint32 immediate_data_size
, const void* cmd_data
) {
9523 if (!unsafe_es3_apis_enabled())
9524 return error::kUnknownCommand
;
9526 const gles2::cmds::CompressedTexImage3D
& c
=
9527 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9528 GLenum target
= static_cast<GLenum
>(c
.target
);
9529 GLint level
= static_cast<GLint
>(c
.level
);
9530 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9531 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9532 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9533 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9534 GLint border
= static_cast<GLint
>(c
.border
);
9535 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9536 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9537 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9538 const void* data
= NULL
;
9539 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9540 data
= GetSharedMemoryAs
<const void*>(
9541 data_shm_id
, data_shm_offset
, image_size
);
9543 return error::kOutOfBounds
;
9546 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9547 depth
, border
, image_size
, data
);
9550 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9551 uint32 immediate_data_size
, const void* cmd_data
) {
9552 if (!unsafe_es3_apis_enabled())
9553 return error::kUnknownCommand
;
9555 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9556 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9557 GLenum target
= static_cast<GLenum
>(c
.target
);
9558 GLint level
= static_cast<GLint
>(c
.level
);
9559 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9560 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9561 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9562 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9563 GLint border
= static_cast<GLint
>(c
.border
);
9564 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9566 return error::kInvalidArguments
;
9568 uint32 data_size
= bucket
->size();
9569 GLsizei imageSize
= data_size
;
9570 const void* data
= bucket
->GetData(0, data_size
);
9572 return error::kInvalidArguments
;
9574 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9575 depth
, border
, imageSize
, data
);
9578 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9579 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9580 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9581 GLsizei image_size
, const void* data
) {
9582 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9584 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9587 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9588 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9589 "glCompressedTexSubImage3D", format
, "format");
9592 if (width
< 0 || height
< 0 || depth
< 0) {
9594 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9597 if (image_size
< 0) {
9599 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9602 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9605 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9606 "unknown texture for target");
9609 Texture
* texture
= texture_ref
->texture();
9610 GLenum type
= 0, internal_format
= 0;
9611 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9612 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9613 "level does not exist");
9616 if (internal_format
!= format
) {
9617 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9618 "format does not match internal format");
9621 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9622 width
, height
, depth
, type
)) {
9623 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9627 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9628 width
, height
, depth
, format
,
9630 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9631 target
, level
, xoffset
, yoffset
,
9632 zoffset
, width
, height
, depth
,
9637 // Note: There is no need to deal with texture cleared tracking here
9638 // because the validation above means you can only get here if the level
9639 // is already a matching compressed format and in that case
9640 // CompressedTexImage3D already cleared the texture.
9641 glCompressedTexSubImage3D(
9642 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9645 // This may be a slow command. Exit command processing to allow for
9646 // context preemption and GPU watchdog checks.
9647 ExitCommandProcessingEarly();
9650 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9651 uint32 immediate_data_size
, const void* cmd_data
) {
9652 if (!unsafe_es3_apis_enabled())
9653 return error::kUnknownCommand
;
9654 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9655 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9656 GLenum target
= static_cast<GLenum
>(c
.target
);
9657 GLint level
= static_cast<GLint
>(c
.level
);
9658 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9659 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9660 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9661 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9662 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9663 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9664 GLenum format
= static_cast<GLenum
>(c
.format
);
9665 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9667 return error::kInvalidArguments
;
9669 uint32 data_size
= bucket
->size();
9670 GLsizei image_size
= data_size
;
9671 const void* data
= bucket
->GetData(0, data_size
);
9673 return error::kInvalidArguments
;
9675 DoCompressedTexSubImage3D(
9676 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9678 return error::kNoError
;
9681 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9682 const void* cmd_data
) {
9683 const gles2::cmds::TexImage2D
& c
=
9684 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9685 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9686 "width", c
.width
, "height", c
.height
);
9687 // Set as failed for now, but if it successed, this will be set to not failed.
9688 texture_state_
.tex_image_failed
= true;
9689 GLenum target
= static_cast<GLenum
>(c
.target
);
9690 GLint level
= static_cast<GLint
>(c
.level
);
9691 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9692 // for internalformat.
9693 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9694 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9695 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9696 GLint border
= static_cast<GLint
>(c
.border
);
9697 GLenum format
= static_cast<GLenum
>(c
.format
);
9698 GLenum type
= static_cast<GLenum
>(c
.type
);
9699 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9700 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9702 if (!GLES2Util::ComputeImageDataSizes(
9703 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9705 return error::kOutOfBounds
;
9707 const void* pixels
= NULL
;
9708 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9709 pixels
= GetSharedMemoryAs
<const void*>(
9710 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9712 return error::kOutOfBounds
;
9716 // For testing only. Allows us to stress the ability to respond to OOM errors.
9717 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9718 (width
* height
>= 4096 * 4096)) {
9721 "glTexImage2D", "synthetic out of memory");
9722 return error::kNoError
;
9725 TextureManager::DoTexImageArguments args
= {
9726 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9727 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9728 texture_manager()->ValidateAndDoTexImage(
9729 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9731 // This may be a slow command. Exit command processing to allow for
9732 // context preemption and GPU watchdog checks.
9733 ExitCommandProcessingEarly();
9734 return error::kNoError
;
9737 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9738 const void* cmd_data
) {
9739 if (!unsafe_es3_apis_enabled())
9740 return error::kUnknownCommand
;
9742 const gles2::cmds::TexImage3D
& c
=
9743 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9744 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9745 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9746 // Set as failed for now, but if it successed, this will be set to not failed.
9747 texture_state_
.tex_image_failed
= true;
9748 GLenum target
= static_cast<GLenum
>(c
.target
);
9749 GLint level
= static_cast<GLint
>(c
.level
);
9750 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9751 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9752 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9753 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9754 GLint border
= static_cast<GLint
>(c
.border
);
9755 GLenum format
= static_cast<GLenum
>(c
.format
);
9756 GLenum type
= static_cast<GLenum
>(c
.type
);
9757 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9758 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9760 if (!GLES2Util::ComputeImageDataSizes(
9761 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9763 return error::kOutOfBounds
;
9765 const void* pixels
= NULL
;
9766 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9767 pixels
= GetSharedMemoryAs
<const void*>(
9768 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9770 return error::kOutOfBounds
;
9774 // For testing only. Allows us to stress the ability to respond to OOM errors.
9775 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9776 (width
* height
* depth
>= 4096 * 4096)) {
9779 "glTexImage3D", "synthetic out of memory");
9780 return error::kNoError
;
9783 TextureManager::DoTexImageArguments args
= {
9784 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
9785 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
9786 texture_manager()->ValidateAndDoTexImage(
9787 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
9789 // This may be a slow command. Exit command processing to allow for
9790 // context preemption and GPU watchdog checks.
9791 ExitCommandProcessingEarly();
9792 return error::kNoError
;
9795 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9804 const void * data
) {
9805 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9809 GL_INVALID_OPERATION
,
9810 "glCompressedTexSubImage2D", "unknown texture for target");
9813 Texture
* texture
= texture_ref
->texture();
9815 GLenum internal_format
= 0;
9816 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9818 GL_INVALID_OPERATION
,
9819 "glCompressedTexSubImage2D", "level does not exist.");
9822 if (internal_format
!= format
) {
9824 GL_INVALID_OPERATION
,
9825 "glCompressedTexSubImage2D", "format does not match internal format.");
9828 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
9831 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9835 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9836 width
, height
, 1, format
, image_size
) ||
9837 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9838 target
, level
, xoffset
, yoffset
, 0,
9839 width
, height
, 1, format
, texture
)) {
9844 // Note: There is no need to deal with texture cleared tracking here
9845 // because the validation above means you can only get here if the level
9846 // is already a matching compressed format and in that case
9847 // CompressedTexImage2D already cleared the texture.
9848 glCompressedTexSubImage2D(
9849 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9851 // This may be a slow command. Exit command processing to allow for
9852 // context preemption and GPU watchdog checks.
9853 ExitCommandProcessingEarly();
9857 GLint start
, GLint range
, GLint sourceRange
,
9858 GLint
* out_start
, GLint
* out_range
) {
9865 GLint end
= start
+ range
;
9866 if (end
> sourceRange
) {
9867 range
-= end
- sourceRange
;
9873 void GLES2DecoderImpl::DoCopyTexImage2D(
9876 GLenum internal_format
,
9882 DCHECK(!ShouldDeferReads());
9883 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9887 GL_INVALID_OPERATION
,
9888 "glCopyTexImage2D", "unknown texture for target");
9891 Texture
* texture
= texture_ref
->texture();
9892 if (texture
->IsImmutable()) {
9894 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9897 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9900 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9903 if (!texture_manager()->ValidateFormatAndTypeCombination(
9904 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9905 GL_UNSIGNED_BYTE
)) {
9909 // Check we have compatible formats.
9910 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9911 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9912 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9914 if ((channels_needed
& channels_exist
) != channels_needed
) {
9916 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9920 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9922 GL_INVALID_OPERATION
,
9923 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9927 uint32 estimated_size
= 0;
9928 if (!GLES2Util::ComputeImageDataSizes(
9929 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9930 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9932 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9936 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9937 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9941 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9945 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9947 GL_INVALID_OPERATION
,
9948 "glCopyTexImage2D", "source and destination textures are the same");
9952 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9957 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9958 gfx::Size size
= GetBoundReadFrameBufferSize();
9960 if (texture
->IsAttachedToFramebuffer()) {
9961 framebuffer_state_
.clear_state_dirty
= true;
9964 // Clip to size to source dimensions
9967 GLint copyWidth
= 0;
9968 GLint copyHeight
= 0;
9969 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9970 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9974 copyWidth
!= width
||
9975 copyHeight
!= height
) {
9976 // some part was clipped so clear the texture.
9977 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9978 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9980 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9983 if (copyHeight
> 0 && copyWidth
> 0) {
9984 GLint dx
= copyX
- x
;
9985 GLint dy
= copyY
- y
;
9988 ScopedModifyPixels
modify(texture_ref
);
9989 glCopyTexSubImage2D(target
, level
,
9990 destX
, destY
, copyX
, copyY
,
9991 copyWidth
, copyHeight
);
9994 ScopedModifyPixels
modify(texture_ref
);
9995 glCopyTexImage2D(target
, level
, internal_format
,
9996 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9998 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9999 if (error
== GL_NO_ERROR
) {
10000 texture_manager()->SetLevelInfo(
10001 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
10002 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
10005 // This may be a slow command. Exit command processing to allow for
10006 // context preemption and GPU watchdog checks.
10007 ExitCommandProcessingEarly();
10010 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10019 DCHECK(!ShouldDeferReads());
10020 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10022 if (!texture_ref
) {
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION
,
10025 "glCopyTexSubImage2D", "unknown texture for target");
10028 Texture
* texture
= texture_ref
->texture();
10031 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10032 !texture
->ValidForTexture(
10033 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10038 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10039 LOCAL_SET_GL_ERROR(
10040 GL_INVALID_OPERATION
,
10041 "glCopyTexSubImage2D", "async upload pending for texture");
10045 // Check we have compatible formats.
10046 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10047 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10048 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10050 if (!channels_needed
||
10051 (channels_needed
& channels_exist
) != channels_needed
) {
10052 LOCAL_SET_GL_ERROR(
10053 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10057 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10058 LOCAL_SET_GL_ERROR(
10059 GL_INVALID_OPERATION
,
10060 "glCopySubImage2D", "can not be used with depth or stencil textures");
10064 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10068 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION
,
10071 "glCopyTexSubImage2D", "source and destination textures are the same");
10075 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10079 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10080 gfx::Size size
= GetBoundReadFrameBufferSize();
10083 GLint copyWidth
= 0;
10084 GLint copyHeight
= 0;
10085 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10086 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10088 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10089 height
!= size
.height()) {
10090 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10092 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10093 "dimensions too big");
10097 // Write all pixels in below.
10098 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10103 copyWidth
!= width
||
10104 copyHeight
!= height
) {
10105 // some part was clipped so clear the sub rect.
10106 uint32 pixels_size
= 0;
10107 if (!GLES2Util::ComputeImageDataSizes(
10108 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10110 LOCAL_SET_GL_ERROR(
10111 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10114 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10115 memset(zero
.get(), 0, pixels_size
);
10116 ScopedModifyPixels
modify(texture_ref
);
10118 target
, level
, xoffset
, yoffset
, width
, height
,
10119 format
, type
, zero
.get());
10122 if (copyHeight
> 0 && copyWidth
> 0) {
10123 GLint dx
= copyX
- x
;
10124 GLint dy
= copyY
- y
;
10125 GLint destX
= xoffset
+ dx
;
10126 GLint destY
= yoffset
+ dy
;
10127 ScopedModifyPixels
modify(texture_ref
);
10128 glCopyTexSubImage2D(target
, level
,
10129 destX
, destY
, copyX
, copyY
,
10130 copyWidth
, copyHeight
);
10133 // This may be a slow command. Exit command processing to allow for
10134 // context preemption and GPU watchdog checks.
10135 ExitCommandProcessingEarly();
10138 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10139 error::Error
* error
,
10140 const char* function_name
,
10149 const void * data
) {
10150 (*error
) = error::kNoError
;
10151 if (!validators_
->texture_target
.IsValid(target
)) {
10152 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10156 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10160 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10163 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10165 if (!texture_ref
) {
10166 LOCAL_SET_GL_ERROR(
10167 GL_INVALID_OPERATION
,
10168 function_name
, "unknown texture for target");
10171 Texture
* texture
= texture_ref
->texture();
10172 GLenum current_type
= 0;
10173 GLenum internal_format
= 0;
10174 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10175 LOCAL_SET_GL_ERROR(
10176 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10179 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10180 function_name
, format
, type
, internal_format
, level
)) {
10183 if (type
!= current_type
) {
10184 LOCAL_SET_GL_ERROR(
10185 GL_INVALID_OPERATION
,
10186 function_name
, "type does not match type of texture.");
10189 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10190 LOCAL_SET_GL_ERROR(
10191 GL_INVALID_OPERATION
,
10192 function_name
, "async upload pending for texture");
10195 if (!texture
->ValidForTexture(
10196 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10197 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10200 if ((GLES2Util::GetChannelsForFormat(format
) &
10201 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10202 LOCAL_SET_GL_ERROR(
10203 GL_INVALID_OPERATION
,
10204 function_name
, "can not supply data for depth or stencil textures");
10207 if (data
== NULL
) {
10208 (*error
) = error::kOutOfBounds
;
10214 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10223 const void * data
) {
10224 error::Error error
= error::kNoError
;
10225 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10226 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10229 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10231 Texture
* texture
= texture_ref
->texture();
10232 GLsizei tex_width
= 0;
10233 GLsizei tex_height
= 0;
10234 bool ok
= texture
->GetLevelSize(
10235 target
, level
, &tex_width
, &tex_height
, nullptr);
10237 if (xoffset
!= 0 || yoffset
!= 0 ||
10238 width
!= tex_width
|| height
!= tex_height
) {
10239 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10241 LOCAL_SET_GL_ERROR(
10242 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
10243 return error::kNoError
;
10245 ScopedTextureUploadTimer
timer(&texture_state_
);
10247 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10248 return error::kNoError
;
10251 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10252 !texture
->IsImmutable() &&
10253 !texture
->HasImages()) {
10254 ScopedTextureUploadTimer
timer(&texture_state_
);
10255 GLenum internal_format
;
10257 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10258 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10261 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10263 ScopedTextureUploadTimer
timer(&texture_state_
);
10265 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10267 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10269 // This may be a slow command. Exit command processing to allow for
10270 // context preemption and GPU watchdog checks.
10271 ExitCommandProcessingEarly();
10272 return error::kNoError
;
10275 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10276 const void* cmd_data
) {
10277 const gles2::cmds::TexSubImage2D
& c
=
10278 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10279 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10280 "width", c
.width
, "height", c
.height
);
10281 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10282 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10283 return error::kNoError
;
10285 GLenum target
= static_cast<GLenum
>(c
.target
);
10286 GLint level
= static_cast<GLint
>(c
.level
);
10287 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10288 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10289 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10290 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10291 GLenum format
= static_cast<GLenum
>(c
.format
);
10292 GLenum type
= static_cast<GLenum
>(c
.type
);
10294 if (!GLES2Util::ComputeImageDataSizes(
10295 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10297 return error::kOutOfBounds
;
10299 const void* pixels
= GetSharedMemoryAs
<const void*>(
10300 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10301 return DoTexSubImage2D(
10302 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10305 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10316 const void * data
) {
10317 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10319 if (!texture_ref
) {
10320 LOCAL_SET_GL_ERROR(
10321 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10324 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10325 ScopedTextureUploadTimer
timer(&texture_state_
);
10326 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10327 depth
, format
, type
, data
);
10328 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10329 if (error
== GL_NO_ERROR
) {
10330 // TODO(zmo): This is not 100% correct because only part of the level
10331 // image is cleared.
10332 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10335 // This may be a slow command. Exit command processing to allow for
10336 // context preemption and GPU watchdog checks.
10337 ExitCommandProcessingEarly();
10338 return error::kNoError
;
10341 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10342 const void* cmd_data
) {
10343 if (!unsafe_es3_apis_enabled())
10344 return error::kUnknownCommand
;
10346 const gles2::cmds::TexSubImage3D
& c
=
10347 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10348 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10349 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10350 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10351 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10352 return error::kNoError
;
10354 GLenum target
= static_cast<GLenum
>(c
.target
);
10355 GLint level
= static_cast<GLint
>(c
.level
);
10356 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10357 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10358 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10359 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10360 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10361 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10362 GLenum format
= static_cast<GLenum
>(c
.format
);
10363 GLenum type
= static_cast<GLenum
>(c
.type
);
10365 if (!GLES2Util::ComputeImageDataSizes(
10366 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10368 return error::kOutOfBounds
;
10370 const void* pixels
= GetSharedMemoryAs
<const void*>(
10371 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10372 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10373 height
, depth
, format
, type
, pixels
);
10376 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10377 uint32 immediate_data_size
,
10378 const void* cmd_data
) {
10379 const gles2::cmds::GetVertexAttribPointerv
& c
=
10380 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10381 GLuint index
= static_cast<GLuint
>(c
.index
);
10382 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10383 typedef cmds::GetVertexAttribPointerv::Result Result
;
10384 Result
* result
= GetSharedMemoryAs
<Result
*>(
10385 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10387 return error::kOutOfBounds
;
10389 // Check that the client initialized the result.
10390 if (result
->size
!= 0) {
10391 return error::kInvalidArguments
;
10393 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10394 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10395 "glGetVertexAttribPointerv", pname
, "pname");
10396 return error::kNoError
;
10398 if (index
>= group_
->max_vertex_attribs()) {
10399 LOCAL_SET_GL_ERROR(
10400 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10401 return error::kNoError
;
10403 result
->SetNumResults(1);
10404 *result
->GetData() =
10405 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10406 return error::kNoError
;
10410 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10411 GLint fake_location
,
10414 error::Error
* error
,
10415 GLint
* real_location
,
10416 GLuint
* service_id
,
10417 SizedResult
<T
>** result_pointer
,
10418 GLenum
* result_type
,
10419 GLsizei
* result_size
) {
10421 DCHECK(service_id
);
10422 DCHECK(result_pointer
);
10423 DCHECK(result_type
);
10424 DCHECK(result_size
);
10425 DCHECK(real_location
);
10426 *error
= error::kNoError
;
10427 // Make sure we have enough room for the result on failure.
10428 SizedResult
<T
>* result
;
10429 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10430 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10432 *error
= error::kOutOfBounds
;
10435 *result_pointer
= result
;
10436 // Set the result size to 0 so the client does not have to check for success.
10437 result
->SetNumResults(0);
10438 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10442 if (!program
->IsValid()) {
10443 // Program was not linked successfully. (ie, glLinkProgram)
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10448 *service_id
= program
->service_id();
10449 GLint array_index
= -1;
10450 const Program::UniformInfo
* uniform_info
=
10451 program
->GetUniformInfoByFakeLocation(
10452 fake_location
, real_location
, &array_index
);
10453 if (!uniform_info
) {
10454 // No such location.
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10459 GLenum type
= uniform_info
->type
;
10460 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10461 if (num_elements
== 0) {
10462 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10465 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10466 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10468 *error
= error::kOutOfBounds
;
10471 result
->SetNumResults(num_elements
);
10472 *result_size
= num_elements
* sizeof(T
);
10473 *result_type
= type
;
10477 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10478 const void* cmd_data
) {
10479 const gles2::cmds::GetUniformiv
& c
=
10480 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10481 GLuint program
= c
.program
;
10482 GLint fake_location
= c
.location
;
10484 GLenum result_type
;
10485 GLsizei result_size
;
10486 GLint real_location
= -1;
10488 cmds::GetUniformiv::Result
* result
;
10489 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10490 c
.params_shm_offset
, &error
, &real_location
,
10491 &service_id
, &result
, &result_type
,
10494 service_id
, real_location
, result
->GetData());
10499 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10500 const void* cmd_data
) {
10501 if (!unsafe_es3_apis_enabled())
10502 return error::kUnknownCommand
;
10504 const gles2::cmds::GetUniformuiv
& c
=
10505 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10506 GLuint program
= c
.program
;
10507 GLint fake_location
= c
.location
;
10509 GLenum result_type
;
10510 GLsizei result_size
;
10511 GLint real_location
= -1;
10513 cmds::GetUniformuiv::Result
* result
;
10514 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10515 c
.params_shm_offset
, &error
, &real_location
,
10516 &service_id
, &result
, &result_type
,
10519 service_id
, real_location
, result
->GetData());
10524 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10525 const void* cmd_data
) {
10526 const gles2::cmds::GetUniformfv
& c
=
10527 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10528 GLuint program
= c
.program
;
10529 GLint fake_location
= c
.location
;
10531 GLint real_location
= -1;
10533 cmds::GetUniformfv::Result
* result
;
10534 GLenum result_type
;
10535 GLsizei result_size
;
10536 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10537 c
.params_shm_offset
, &error
, &real_location
,
10538 &service_id
, &result
, &result_type
,
10540 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10541 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10542 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10543 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10544 glGetUniformiv(service_id
, real_location
, temp
.get());
10545 GLfloat
* dst
= result
->GetData();
10546 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10547 dst
[ii
] = (temp
[ii
] != 0);
10550 glGetUniformfv(service_id
, real_location
, result
->GetData());
10556 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10557 uint32 immediate_data_size
,
10558 const void* cmd_data
) {
10559 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10560 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10561 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10562 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10563 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10564 Result
* result
= GetSharedMemoryAs
<Result
*>(
10565 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10567 return error::kOutOfBounds
;
10569 // Check that the client initialized the result.
10570 if (result
->success
!= 0) {
10571 return error::kInvalidArguments
;
10573 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10574 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10575 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10576 return error::kNoError
;
10578 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10579 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10580 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10581 return error::kNoError
;
10584 result
->success
= 1; // true
10586 GLint range
[2] = { 0, 0 };
10587 GLint precision
= 0;
10588 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10590 result
->min_range
= range
[0];
10591 result
->max_range
= range
[1];
10592 result
->precision
= precision
;
10594 return error::kNoError
;
10597 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10598 uint32 immediate_data_size
,
10599 const void* cmd_data
) {
10600 const gles2::cmds::GetAttachedShaders
& c
=
10601 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10602 uint32 result_size
= c
.result_size
;
10603 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10604 Program
* program
= GetProgramInfoNotShader(
10605 program_id
, "glGetAttachedShaders");
10607 return error::kNoError
;
10609 typedef cmds::GetAttachedShaders::Result Result
;
10610 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10611 Result
* result
= GetSharedMemoryAs
<Result
*>(
10612 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10614 return error::kOutOfBounds
;
10616 // Check that the client initialized the result.
10617 if (result
->size
!= 0) {
10618 return error::kInvalidArguments
;
10621 glGetAttachedShaders(
10622 program
->service_id(), max_count
, &count
, result
->GetData());
10623 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10624 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10625 &result
->GetData()[ii
])) {
10627 return error::kGenericError
;
10630 result
->SetNumResults(count
);
10631 return error::kNoError
;
10634 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10635 uint32 immediate_data_size
,
10636 const void* cmd_data
) {
10637 const gles2::cmds::GetActiveUniform
& c
=
10638 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10639 GLuint program_id
= c
.program
;
10640 GLuint index
= c
.index
;
10641 uint32 name_bucket_id
= c
.name_bucket_id
;
10642 typedef cmds::GetActiveUniform::Result Result
;
10643 Result
* result
= GetSharedMemoryAs
<Result
*>(
10644 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10646 return error::kOutOfBounds
;
10648 // Check that the client initialized the result.
10649 if (result
->success
!= 0) {
10650 return error::kInvalidArguments
;
10652 Program
* program
= GetProgramInfoNotShader(
10653 program_id
, "glGetActiveUniform");
10655 return error::kNoError
;
10657 const Program::UniformInfo
* uniform_info
=
10658 program
->GetUniformInfo(index
);
10659 if (!uniform_info
) {
10660 LOCAL_SET_GL_ERROR(
10661 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10662 return error::kNoError
;
10664 result
->success
= 1; // true.
10665 result
->size
= uniform_info
->size
;
10666 result
->type
= uniform_info
->type
;
10667 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10668 bucket
->SetFromString(uniform_info
->name
.c_str());
10669 return error::kNoError
;
10672 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10673 uint32 immediate_data_size
, const void* cmd_data
) {
10674 if (!unsafe_es3_apis_enabled())
10675 return error::kUnknownCommand
;
10676 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10677 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10678 GLuint program_id
= c
.program
;
10679 GLuint index
= static_cast<GLuint
>(c
.index
);
10680 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10681 Program
* program
= GetProgramInfoNotShader(
10682 program_id
, "glGetActiveUniformBlockiv");
10684 return error::kNoError
;
10686 GLuint service_id
= program
->service_id();
10687 GLint link_status
= GL_FALSE
;
10688 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10689 if (link_status
!= GL_TRUE
) {
10690 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10691 "glGetActiveActiveUniformBlockiv", "program not linked");
10692 return error::kNoError
;
10694 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10695 GLsizei num_values
= 1;
10696 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10698 glGetActiveUniformBlockiv(
10699 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10700 GLenum error
= glGetError();
10701 if (error
!= GL_NO_ERROR
) {
10702 // Assume this will the same error if calling with pname.
10703 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10704 return error::kNoError
;
10706 num_values
= static_cast<GLsizei
>(num
);
10708 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10709 Result
* result
= GetSharedMemoryAs
<Result
*>(
10710 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10711 GLint
* params
= result
? result
->GetData() : NULL
;
10712 if (params
== NULL
) {
10713 return error::kOutOfBounds
;
10715 // Check that the client initialized the result.
10716 if (result
->size
!= 0) {
10717 return error::kInvalidArguments
;
10719 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10720 GLenum error
= glGetError();
10721 if (error
== GL_NO_ERROR
) {
10722 result
->SetNumResults(num_values
);
10724 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10726 return error::kNoError
;
10729 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10730 uint32 immediate_data_size
, const void* cmd_data
) {
10731 if (!unsafe_es3_apis_enabled())
10732 return error::kUnknownCommand
;
10733 const gles2::cmds::GetActiveUniformBlockName
& c
=
10734 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10735 GLuint program_id
= c
.program
;
10736 GLuint index
= c
.index
;
10737 uint32 name_bucket_id
= c
.name_bucket_id
;
10738 typedef cmds::GetActiveUniformBlockName::Result Result
;
10739 Result
* result
= GetSharedMemoryAs
<Result
*>(
10740 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10742 return error::kOutOfBounds
;
10744 // Check that the client initialized the result.
10745 if (*result
!= 0) {
10746 return error::kInvalidArguments
;
10748 Program
* program
= GetProgramInfoNotShader(
10749 program_id
, "glGetActiveUniformBlockName");
10751 return error::kNoError
;
10753 GLuint service_id
= program
->service_id();
10754 GLint link_status
= GL_FALSE
;
10755 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10756 if (link_status
!= GL_TRUE
) {
10757 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10758 "glGetActiveActiveUniformBlockName", "program not linked");
10759 return error::kNoError
;
10761 GLint max_length
= 0;
10763 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10764 // Increase one so &buffer[0] is always valid.
10765 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10766 std::vector
<char> buffer(buf_size
);
10767 GLsizei length
= 0;
10768 glGetActiveUniformBlockName(
10769 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10772 return error::kNoError
;
10775 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10776 DCHECK_GT(buf_size
, length
);
10777 DCHECK_EQ(0, buffer
[length
]);
10778 bucket
->SetFromString(&buffer
[0]);
10779 return error::kNoError
;
10782 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10783 uint32 immediate_data_size
, const void* cmd_data
) {
10784 if (!unsafe_es3_apis_enabled())
10785 return error::kUnknownCommand
;
10786 const gles2::cmds::GetActiveUniformsiv
& c
=
10787 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10788 GLuint program_id
= c
.program
;
10789 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10790 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10792 return error::kInvalidArguments
;
10794 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10795 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10796 typedef cmds::GetActiveUniformsiv::Result Result
;
10797 Result
* result
= GetSharedMemoryAs
<Result
*>(
10798 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10799 GLint
* params
= result
? result
->GetData() : NULL
;
10800 if (params
== NULL
) {
10801 return error::kOutOfBounds
;
10803 // Check that the client initialized the result.
10804 if (result
->size
!= 0) {
10805 return error::kInvalidArguments
;
10807 Program
* program
= GetProgramInfoNotShader(
10808 program_id
, "glGetActiveUniformsiv");
10810 return error::kNoError
;
10812 GLuint service_id
= program
->service_id();
10813 GLint link_status
= GL_FALSE
;
10814 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10815 if (link_status
!= GL_TRUE
) {
10816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10817 "glGetActiveUniformsiv", "program not linked");
10818 return error::kNoError
;
10820 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10821 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10822 GLenum error
= glGetError();
10823 if (error
== GL_NO_ERROR
) {
10824 result
->SetNumResults(count
);
10826 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10828 return error::kNoError
;
10831 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10832 const void* cmd_data
) {
10833 const gles2::cmds::GetActiveAttrib
& c
=
10834 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10835 GLuint program_id
= c
.program
;
10836 GLuint index
= c
.index
;
10837 uint32 name_bucket_id
= c
.name_bucket_id
;
10838 typedef cmds::GetActiveAttrib::Result Result
;
10839 Result
* result
= GetSharedMemoryAs
<Result
*>(
10840 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10842 return error::kOutOfBounds
;
10844 // Check that the client initialized the result.
10845 if (result
->success
!= 0) {
10846 return error::kInvalidArguments
;
10848 Program
* program
= GetProgramInfoNotShader(
10849 program_id
, "glGetActiveAttrib");
10851 return error::kNoError
;
10853 const Program::VertexAttrib
* attrib_info
=
10854 program
->GetAttribInfo(index
);
10855 if (!attrib_info
) {
10856 LOCAL_SET_GL_ERROR(
10857 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10858 return error::kNoError
;
10860 result
->success
= 1; // true.
10861 result
->size
= attrib_info
->size
;
10862 result
->type
= attrib_info
->type
;
10863 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10864 bucket
->SetFromString(attrib_info
->name
.c_str());
10865 return error::kNoError
;
10868 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10869 const void* cmd_data
) {
10870 #if 1 // No binary shader support.
10871 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10872 return error::kNoError
;
10874 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10876 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10877 return error::kNoError
;
10879 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10881 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10882 return error::kNoError
;
10885 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10886 return error::kOutOfBounds
;
10888 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10889 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10890 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10891 const void* binary
= GetSharedMemoryAs
<const void*>(
10892 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10893 if (shaders
== NULL
|| binary
== NULL
) {
10894 return error::kOutOfBounds
;
10896 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10897 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10898 Shader
* shader
= GetShader(shaders
[ii
]);
10900 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10901 return error::kNoError
;
10903 service_ids
[ii
] = shader
->service_id();
10905 // TODO(gman): call glShaderBinary
10906 return error::kNoError
;
10910 void GLES2DecoderImpl::DoSwapBuffers() {
10911 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10913 int this_frame_number
= frame_number_
++;
10914 // TRACE_EVENT for gpu tests:
10915 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10916 TRACE_EVENT_SCOPE_THREAD
,
10917 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10918 "width", (is_offscreen
? offscreen_size_
.width() :
10919 surface_
->GetSize().width()));
10920 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10921 "offscreen", is_offscreen
,
10922 "frame", this_frame_number
);
10924 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10927 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10928 "gpu_toplevel", "SwapBuffer");
10931 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10934 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10935 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10936 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10939 // If offscreen then don't actually SwapBuffers to the display. Just copy
10940 // the rendered frame to another frame buffer.
10941 if (is_offscreen
) {
10942 TRACE_EVENT2("gpu", "Offscreen",
10943 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10944 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10945 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10946 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10948 if (workarounds().needs_offscreen_buffer_workaround
) {
10949 offscreen_saved_frame_buffer_
->Create();
10953 // Allocate the offscreen saved color texture.
10954 DCHECK(offscreen_saved_color_format_
);
10955 offscreen_saved_color_texture_
->AllocateStorage(
10956 offscreen_size_
, offscreen_saved_color_format_
, false);
10958 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10959 offscreen_saved_color_texture_
.get());
10960 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10961 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10962 GL_FRAMEBUFFER_COMPLETE
) {
10963 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10964 << "because offscreen saved FBO was incomplete.";
10965 MarkContextLost(error::kUnknown
);
10966 group_
->LoseContexts(error::kUnknown
);
10970 // Clear the offscreen color texture.
10971 // TODO(piman): Is this still necessary?
10973 ScopedFrameBufferBinder
binder(this,
10974 offscreen_saved_frame_buffer_
->id());
10975 glClearColor(0, 0, 0, 0);
10976 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10977 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10978 glClear(GL_COLOR_BUFFER_BIT
);
10979 RestoreClearState();
10983 UpdateParentTextureInfo();
10986 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10988 ScopedGLErrorSuppressor
suppressor(
10989 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10991 if (IsOffscreenBufferMultisampled()) {
10992 // For multisampled buffers, resolve the frame buffer.
10993 ScopedResolvedFrameBufferBinder
binder(this, true, false);
10995 ScopedFrameBufferBinder
binder(this,
10996 offscreen_target_frame_buffer_
->id());
10998 if (offscreen_target_buffer_preserved_
) {
10999 // Copy the target frame buffer to the saved offscreen texture.
11000 offscreen_saved_color_texture_
->Copy(
11001 offscreen_saved_color_texture_
->size(),
11002 offscreen_saved_color_format_
);
11004 // Flip the textures in the parent context via the texture manager.
11005 if (!!offscreen_saved_color_texture_info_
.get())
11006 offscreen_saved_color_texture_info_
->texture()->
11007 SetServiceId(offscreen_target_color_texture_
->id());
11009 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11010 offscreen_target_frame_buffer_
->AttachRenderTexture(
11011 offscreen_target_color_texture_
.get());
11014 // Ensure the side effects of the copy are visible to the parent
11015 // context. There is no need to do this for ANGLE because it uses a
11016 // single D3D device for all contexts.
11017 if (!feature_info_
->gl_version_info().is_angle
)
11021 if (!surface_
->SwapBuffers()) {
11022 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11023 if (!CheckResetStatus()) {
11024 MarkContextLost(error::kUnknown
);
11025 group_
->LoseContexts(error::kUnknown
);
11030 // This may be a slow command. Exit command processing to allow for
11031 // context preemption and GPU watchdog checks.
11032 ExitCommandProcessingEarly();
11035 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11036 context_
->SetSwapInterval(interval
);
11039 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11040 uint32 immediate_data_size
,
11041 const void* cmd_data
) {
11042 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11043 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11044 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11045 if (!bucket
|| bucket
->size() == 0) {
11046 return error::kInvalidArguments
;
11048 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11049 Result
* result
= GetSharedMemoryAs
<Result
*>(
11050 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11052 return error::kOutOfBounds
;
11054 // Check that the client initialized the result.
11055 if (*result
!= 0) {
11056 return error::kInvalidArguments
;
11058 std::string feature_str
;
11059 if (!bucket
->GetAsString(&feature_str
)) {
11060 return error::kInvalidArguments
;
11063 // TODO(gman): make this some kind of table to function pointer thingy.
11064 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11065 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11066 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11067 buffer_manager()->set_allow_fixed_attribs(true);
11068 // TODO(gman): decide how to remove the need for this const_cast.
11069 // I could make validators_ non const but that seems bad as this is the only
11070 // place it is needed. I could make some special friend class of validators
11071 // just to allow this to set them. That seems silly. I could refactor this
11072 // code to use the extension mechanism or the initialization attributes to
11073 // turn this feature on. Given that the only real point of this is to make
11074 // the conformance tests pass and given that there is lots of real work that
11075 // needs to be done it seems like refactoring for one to one of those
11076 // methods is a very low priority.
11077 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11078 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
11079 force_webgl_glsl_validation_
= true;
11080 InitializeShaderTranslator();
11082 return error::kNoError
;
11085 *result
= 1; // true.
11086 return error::kNoError
;
11089 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11090 uint32 immediate_data_size
,
11091 const void* cmd_data
) {
11092 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11093 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11095 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11096 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11097 info
->Initialize(disallowed_features_
);
11098 bucket
->SetFromString(info
->extensions().c_str());
11099 return error::kNoError
;
11102 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11103 uint32 immediate_data_size
,
11104 const void* cmd_data
) {
11105 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11106 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11107 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11108 if (!bucket
|| bucket
->size() == 0) {
11109 return error::kInvalidArguments
;
11111 std::string feature_str
;
11112 if (!bucket
->GetAsString(&feature_str
)) {
11113 return error::kInvalidArguments
;
11116 bool desire_webgl_glsl_validation
=
11117 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
11118 bool desire_standard_derivatives
= false;
11119 bool desire_frag_depth
= false;
11120 bool desire_draw_buffers
= false;
11121 bool desire_shader_texture_lod
= false;
11122 if (force_webgl_glsl_validation_
) {
11123 desire_standard_derivatives
=
11124 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11125 desire_frag_depth
=
11126 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11127 desire_draw_buffers
=
11128 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11129 desire_shader_texture_lod
=
11130 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11133 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
11134 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11135 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11136 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
11137 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
11138 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11139 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11140 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11141 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11142 InitializeShaderTranslator();
11145 UpdateCapabilities();
11147 return error::kNoError
;
11150 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11151 uint32 immediate_data_size
,
11152 const void* cmd_data
) {
11153 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11154 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11155 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11156 uint32 bucket_id
= c
.bucket_id
;
11157 Bucket
* bucket
= CreateBucket(bucket_id
);
11158 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11159 Program
* program
= NULL
;
11160 program
= GetProgram(program_id
);
11161 if (!program
|| !program
->IsValid()) {
11162 return error::kNoError
;
11164 program
->GetProgramInfo(program_manager(), bucket
);
11165 return error::kNoError
;
11168 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11169 uint32 immediate_data_size
, const void* cmd_data
) {
11170 if (!unsafe_es3_apis_enabled())
11171 return error::kUnknownCommand
;
11172 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11173 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11174 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11175 uint32 bucket_id
= c
.bucket_id
;
11176 Bucket
* bucket
= CreateBucket(bucket_id
);
11177 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11178 Program
* program
= NULL
;
11179 program
= GetProgram(program_id
);
11180 if (!program
|| !program
->IsValid()) {
11181 return error::kNoError
;
11183 program
->GetUniformBlocks(bucket
);
11184 return error::kNoError
;
11187 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11188 uint32 immediate_data_size
, const void* cmd_data
) {
11189 if (!unsafe_es3_apis_enabled())
11190 return error::kUnknownCommand
;
11191 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11192 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11193 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11194 uint32 bucket_id
= c
.bucket_id
;
11195 Bucket
* bucket
= CreateBucket(bucket_id
);
11196 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11197 Program
* program
= NULL
;
11198 program
= GetProgram(program_id
);
11199 if (!program
|| !program
->IsValid()) {
11200 return error::kNoError
;
11202 program
->GetUniformsES3(bucket
);
11203 return error::kNoError
;
11206 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11207 uint32 immediate_data_size
,
11208 const void* cmd_data
) {
11209 if (!unsafe_es3_apis_enabled())
11210 return error::kUnknownCommand
;
11211 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11212 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11213 GLuint program_id
= c
.program
;
11214 GLuint index
= c
.index
;
11215 uint32 name_bucket_id
= c
.name_bucket_id
;
11216 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11217 Result
* result
= GetSharedMemoryAs
<Result
*>(
11218 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11220 return error::kOutOfBounds
;
11222 // Check that the client initialized the result.
11223 if (result
->success
!= 0) {
11224 return error::kInvalidArguments
;
11226 Program
* program
= GetProgramInfoNotShader(
11227 program_id
, "glGetTransformFeedbackVarying");
11229 return error::kNoError
;
11231 GLuint service_id
= program
->service_id();
11232 GLint link_status
= GL_FALSE
;
11233 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11234 if (link_status
!= GL_TRUE
) {
11235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11236 "glGetTransformFeedbackVarying", "program not linked");
11237 return error::kNoError
;
11239 GLint max_length
= 0;
11241 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11242 max_length
= std::max(1, max_length
);
11243 std::vector
<char> buffer(max_length
);
11244 GLsizei length
= 0;
11247 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11248 glGetTransformFeedbackVarying(
11249 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11250 GLenum error
= glGetError();
11251 if (error
!= GL_NO_ERROR
) {
11252 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11253 return error::kNoError
;
11255 result
->success
= 1; // true.
11256 result
->size
= static_cast<int32_t>(size
);
11257 result
->type
= static_cast<uint32_t>(type
);
11258 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11259 DCHECK(length
>= 0 && length
< max_length
);
11260 buffer
[length
] = '\0'; // Just to be safe.
11261 bucket
->SetFromString(&buffer
[0]);
11262 return error::kNoError
;
11265 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11266 uint32 immediate_data_size
, const void* cmd_data
) {
11267 if (!unsafe_es3_apis_enabled())
11268 return error::kUnknownCommand
;
11269 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11270 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11272 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11273 uint32 bucket_id
= c
.bucket_id
;
11274 Bucket
* bucket
= CreateBucket(bucket_id
);
11275 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11276 Program
* program
= NULL
;
11277 program
= GetProgram(program_id
);
11278 if (!program
|| !program
->IsValid()) {
11279 return error::kNoError
;
11281 program
->GetTransformFeedbackVaryings(bucket
);
11282 return error::kNoError
;
11285 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11286 return context_lost_reason_
;
11289 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11290 GLenum reset_status
) const {
11291 switch (reset_status
) {
11293 // TODO(kbr): improve the precision of the error code in this case.
11294 // Consider delegating to context for error code if MakeCurrent fails.
11295 return error::kUnknown
;
11296 case GL_GUILTY_CONTEXT_RESET_ARB
:
11297 return error::kGuilty
;
11298 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11299 return error::kInnocent
;
11300 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11301 return error::kUnknown
;
11305 return error::kUnknown
;
11308 bool GLES2DecoderImpl::WasContextLost() const {
11309 return context_was_lost_
;
11312 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11313 return WasContextLost() && reset_by_robustness_extension_
;
11316 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11317 // Only lose the context once.
11318 if (WasContextLost())
11321 // Don't make GL calls in here, the context might not be current.
11322 context_lost_reason_
= reason
;
11323 current_decoder_error_
= error::kLostContext
;
11324 context_was_lost_
= true;
11326 // Some D3D drivers cannot recover from device lost in the GPU process
11327 // sandbox. Allow a new GPU process to launch.
11328 if (workarounds().exit_on_context_lost
) {
11329 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
11330 << " a D3D device in the Chrome GPU process sandbox.";
11331 #if defined(OS_WIN)
11332 base::win::SetShouldCrashOnProcessDetach(false);
11338 bool GLES2DecoderImpl::CheckResetStatus() {
11339 DCHECK(!WasContextLost());
11340 DCHECK(context_
->IsCurrent(NULL
));
11342 if (IsRobustnessSupported()) {
11343 // If the reason for the call was a GL error, we can try to determine the
11344 // reset status more accurately.
11345 GLenum driver_status
= glGetGraphicsResetStatusARB();
11346 if (driver_status
== GL_NO_ERROR
)
11349 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11350 << " context lost via ARB/EXT_robustness. Reset status = "
11351 << GLES2Util::GetStringEnum(driver_status
);
11353 // Don't pretend we know which client was responsible.
11354 if (workarounds().use_virtualized_gl_contexts
)
11355 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11357 switch (driver_status
) {
11358 case GL_GUILTY_CONTEXT_RESET_ARB
:
11359 MarkContextLost(error::kGuilty
);
11361 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11362 MarkContextLost(error::kInnocent
);
11364 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11365 MarkContextLost(error::kUnknown
);
11371 reset_by_robustness_extension_
= true;
11377 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11378 uint32 immediate_data_size
,
11379 const void* cmd_data
) {
11380 return error::kUnknownCommand
;
11383 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11384 uint32 immediate_data_size
,
11385 const void* cmd_data
) {
11386 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11387 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11388 uint32 sync_point
= c
.sync_point
;
11389 if (wait_sync_point_callback_
.is_null())
11390 return error::kNoError
;
11392 return wait_sync_point_callback_
.Run(sync_point
) ?
11393 error::kNoError
: error::kDeferCommandUntilLater
;
11396 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11397 uint32 immediate_data_size
,
11398 const void* cmd_data
) {
11399 if (surface_
->DeferDraws())
11400 return error::kDeferCommandUntilLater
;
11401 if (!surface_
->SetBackbufferAllocation(false))
11402 return error::kLostContext
;
11403 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11404 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11405 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11406 return error::kNoError
;
11409 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11410 GLsizei n
, const GLuint
* client_ids
) {
11411 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11412 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11416 query_manager_
->GenQueries(n
, client_ids
);
11420 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11421 GLsizei n
, const GLuint
* client_ids
) {
11422 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11423 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
11424 if (query
&& !query
->IsDeleted()) {
11425 ContextState::QueryMap::iterator it
=
11426 state_
.current_queries
.find(query
->target());
11427 if (it
!= state_
.current_queries
.end())
11428 state_
.current_queries
.erase(it
);
11430 query
->Destroy(true);
11432 query_manager_
->RemoveQuery(client_ids
[ii
]);
11436 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11437 if (query_manager_
.get() == NULL
) {
11440 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11441 current_decoder_error_
= error::kOutOfBounds
;
11443 return query_manager_
->HavePendingQueries();
11446 // Note that if there are no pending readpixels right now,
11447 // this function will call the callback immediately.
11448 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11449 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11450 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11456 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11457 while (!pending_readpixel_fences_
.empty() &&
11458 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
11459 std::vector
<base::Closure
> callbacks
=
11460 pending_readpixel_fences_
.front()->callbacks
;
11461 pending_readpixel_fences_
.pop();
11462 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11463 callbacks
[i
].Run();
11468 bool GLES2DecoderImpl::HasMoreIdleWork() {
11469 return !pending_readpixel_fences_
.empty() ||
11470 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11473 void GLES2DecoderImpl::PerformIdleWork() {
11474 ProcessPendingReadPixels();
11475 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11477 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11478 ProcessFinishedAsyncTransfers();
11481 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11482 const void* cmd_data
) {
11483 const gles2::cmds::BeginQueryEXT
& c
=
11484 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11485 GLenum target
= static_cast<GLenum
>(c
.target
);
11486 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11487 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11488 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11491 case GL_COMMANDS_ISSUED_CHROMIUM
:
11492 case GL_LATENCY_QUERY_CHROMIUM
:
11493 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11494 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11495 case GL_GET_ERROR_QUERY_CHROMIUM
:
11497 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11498 if (!features().chromium_sync_query
) {
11499 LOCAL_SET_GL_ERROR(
11500 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11501 "not enabled for commands completed queries");
11502 return error::kNoError
;
11506 if (!features().occlusion_query_boolean
) {
11507 LOCAL_SET_GL_ERROR(
11508 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11509 "not enabled for occlusion queries");
11510 return error::kNoError
;
11515 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
11516 LOCAL_SET_GL_ERROR(
11517 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11518 return error::kNoError
;
11521 if (client_id
== 0) {
11522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11523 return error::kNoError
;
11526 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11528 if (!query_manager_
->IsValidQuery(client_id
)) {
11529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11531 "id not made by glGenQueriesEXT");
11532 return error::kNoError
;
11534 query
= query_manager_
->CreateQuery(
11535 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11538 if (query
->target() != target
) {
11539 LOCAL_SET_GL_ERROR(
11540 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11541 return error::kNoError
;
11542 } else if (query
->shm_id() != sync_shm_id
||
11543 query
->shm_offset() != sync_shm_offset
) {
11544 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11545 return error::kInvalidArguments
;
11548 if (!query_manager_
->BeginQuery(query
)) {
11549 return error::kOutOfBounds
;
11552 state_
.current_queries
[target
] = query
;
11553 return error::kNoError
;
11556 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11557 const void* cmd_data
) {
11558 const gles2::cmds::EndQueryEXT
& c
=
11559 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11560 GLenum target
= static_cast<GLenum
>(c
.target
);
11561 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11562 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
11564 if (it
== state_
.current_queries
.end()) {
11565 LOCAL_SET_GL_ERROR(
11566 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11567 return error::kNoError
;
11570 QueryManager::Query
* query
= it
->second
.get();
11571 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11572 return error::kOutOfBounds
;
11575 query_manager_
->ProcessPendingTransferQueries();
11577 state_
.current_queries
.erase(it
);
11578 return error::kNoError
;
11581 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11582 GLsizei n
, const GLuint
* client_ids
) {
11583 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11584 if (GetVertexAttribManager(client_ids
[ii
])) {
11589 if (!features().native_vertex_array_object
) {
11591 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11592 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11595 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11597 glGenVertexArraysOES(n
, service_ids
.get());
11598 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11599 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11606 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11607 GLsizei n
, const GLuint
* client_ids
) {
11608 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11609 VertexAttribManager
* vao
=
11610 GetVertexAttribManager(client_ids
[ii
]);
11611 if (vao
&& !vao
->IsDeleted()) {
11612 if (state_
.vertex_attrib_manager
.get() == vao
) {
11613 DoBindVertexArrayOES(0);
11615 RemoveVertexAttribManager(client_ids
[ii
]);
11620 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11621 VertexAttribManager
* vao
= NULL
;
11622 if (client_id
!= 0) {
11623 vao
= GetVertexAttribManager(client_id
);
11625 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11626 // only allows names that have been previously generated. As such, we do
11627 // not generate new names here.
11628 LOCAL_SET_GL_ERROR(
11629 GL_INVALID_OPERATION
,
11630 "glBindVertexArrayOES", "bad vertex array id.");
11631 current_decoder_error_
= error::kNoError
;
11635 vao
= state_
.default_vertex_attrib_manager
.get();
11638 // Only set the VAO state if it's changed
11639 if (state_
.vertex_attrib_manager
.get() != vao
) {
11640 state_
.vertex_attrib_manager
= vao
;
11641 if (!features().native_vertex_array_object
) {
11642 EmulateVertexArrayState();
11644 GLuint service_id
= vao
->service_id();
11645 glBindVertexArrayOES(service_id
);
11650 // Used when OES_vertex_array_object isn't natively supported
11651 void GLES2DecoderImpl::EmulateVertexArrayState() {
11652 // Setup the Vertex attribute state
11653 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11654 RestoreStateForAttrib(vv
, true);
11657 // Setup the element buffer
11658 Buffer
* element_array_buffer
=
11659 state_
.vertex_attrib_manager
->element_array_buffer();
11660 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11661 element_array_buffer
? element_array_buffer
->service_id() : 0);
11664 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11665 const VertexAttribManager
* vao
=
11666 GetVertexAttribManager(client_id
);
11667 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11670 #if defined(OS_MACOSX)
11671 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11672 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11674 if (it
!= texture_to_io_surface_map_
.end()) {
11675 // Found a previous IOSurface bound to this texture; release it.
11676 IOSurfaceRef surface
= it
->second
;
11677 CFRelease(surface
);
11678 texture_to_io_surface_map_
.erase(it
);
11683 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11684 GLenum target
, GLsizei width
, GLsizei height
,
11685 GLuint io_surface_id
, GLuint plane
) {
11686 #if defined(OS_MACOSX)
11687 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11688 LOCAL_SET_GL_ERROR(
11689 GL_INVALID_OPERATION
,
11690 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11694 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11695 // This might be supported in the future, and if we could require
11696 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11697 // could delete a lot of code. For now, perform strict validation so we
11698 // know what's going on.
11699 LOCAL_SET_GL_ERROR(
11700 GL_INVALID_OPERATION
,
11701 "glTexImageIOSurface2DCHROMIUM",
11702 "requires TEXTURE_RECTANGLE_ARB target");
11706 // Default target might be conceptually valid, but disallow it to avoid
11708 TextureRef
* texture_ref
=
11709 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11710 if (!texture_ref
) {
11711 LOCAL_SET_GL_ERROR(
11712 GL_INVALID_OPERATION
,
11713 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11717 // Look up the new IOSurface. Note that because of asynchrony
11718 // between processes this might fail; during live resizing the
11719 // plugin process might allocate and release an IOSurface before
11720 // this process gets a chance to look it up. Hold on to any old
11721 // IOSurface in this case.
11722 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11724 LOCAL_SET_GL_ERROR(
11725 GL_INVALID_OPERATION
,
11726 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11730 // Release any IOSurface previously bound to this texture.
11731 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11733 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11734 texture_to_io_surface_map_
.insert(
11735 std::make_pair(texture_ref
->service_id(), surface
));
11737 CGLContextObj context
=
11738 static_cast<CGLContextObj
>(context_
->GetHandle());
11740 CGLError err
= CGLTexImageIOSurface2D(
11747 GL_UNSIGNED_INT_8_8_8_8_REV
,
11751 if (err
!= kCGLNoError
) {
11752 LOCAL_SET_GL_ERROR(
11753 GL_INVALID_OPERATION
,
11754 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11758 texture_manager()->SetLevelInfo(
11759 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
11760 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
11763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11764 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11768 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11769 switch (internalformat
) {
11780 case GL_LUMINANCE8_ALPHA8_EXT
:
11781 return GL_LUMINANCE_ALPHA
;
11782 case GL_LUMINANCE8_EXT
:
11783 return GL_LUMINANCE
;
11784 case GL_ALPHA8_EXT
:
11786 case GL_RGBA32F_EXT
:
11788 case GL_RGB32F_EXT
:
11790 case GL_ALPHA32F_EXT
:
11792 case GL_LUMINANCE32F_EXT
:
11793 return GL_LUMINANCE
;
11794 case GL_LUMINANCE_ALPHA32F_EXT
:
11795 return GL_LUMINANCE_ALPHA
;
11796 case GL_RGBA16F_EXT
:
11798 case GL_RGB16F_EXT
:
11800 case GL_ALPHA16F_EXT
:
11802 case GL_LUMINANCE16F_EXT
:
11803 return GL_LUMINANCE
;
11804 case GL_LUMINANCE_ALPHA16F_EXT
:
11805 return GL_LUMINANCE_ALPHA
;
11807 return GL_BGRA_EXT
;
11808 case GL_SRGB8_ALPHA8_EXT
:
11809 return GL_SRGB_ALPHA_EXT
;
11815 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11816 const char* function_name
,
11818 TextureRef
* source_texture_ref
,
11819 TextureRef
* dest_texture_ref
,
11820 GLenum dest_internal_format
) {
11821 if (!source_texture_ref
|| !dest_texture_ref
) {
11822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
11826 if (GL_TEXTURE_2D
!= target
) {
11827 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11828 "invalid texture target");
11832 Texture
* source_texture
= source_texture_ref
->texture();
11833 Texture
* dest_texture
= dest_texture_ref
->texture();
11834 if (source_texture
== dest_texture
) {
11835 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11836 "source and destination textures are the same");
11840 if (dest_texture
->target() != GL_TEXTURE_2D
||
11841 (source_texture
->target() != GL_TEXTURE_2D
&&
11842 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
11843 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
11844 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11845 "invalid texture target binding");
11849 GLenum source_type
= 0;
11850 GLenum source_internal_format
= 0;
11851 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11852 &source_internal_format
);
11854 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11855 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11856 // renderable on some platforms.
11857 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
11858 dest_internal_format
== GL_RGBA
||
11859 dest_internal_format
== GL_BGRA_EXT
;
11860 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11861 source_internal_format
== GL_RGB
||
11862 source_internal_format
== GL_RGBA
||
11863 source_internal_format
== GL_LUMINANCE
||
11864 source_internal_format
== GL_LUMINANCE_ALPHA
||
11865 source_internal_format
== GL_BGRA_EXT
;
11866 if (!valid_source_format
|| !valid_dest_format
) {
11867 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11868 "invalid internal format");
11874 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target
,
11877 GLenum internal_format
,
11878 GLenum dest_type
) {
11879 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11881 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11882 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11883 Texture
* source_texture
= source_texture_ref
->texture();
11884 Texture
* dest_texture
= dest_texture_ref
->texture();
11885 int source_width
= 0;
11886 int source_height
= 0;
11887 gfx::GLImage
* image
=
11888 source_texture
->GetLevelImage(source_texture
->target(), 0);
11890 gfx::Size size
= image
->GetSize();
11891 source_width
= size
.width();
11892 source_height
= size
.height();
11893 if (source_width
<= 0 || source_height
<= 0) {
11894 LOCAL_SET_GL_ERROR(
11896 "glCopyTextureChromium", "invalid image size");
11900 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11901 &source_width
, &source_height
, nullptr)) {
11902 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
11903 "glCopyTextureChromium",
11904 "source texture has no level 0");
11908 // Check that this type of texture is allowed.
11909 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11910 source_width
, source_height
, 1)) {
11911 LOCAL_SET_GL_ERROR(
11912 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11917 GLenum source_type
= 0;
11918 GLenum source_internal_format
= 0;
11919 source_texture
->GetLevelType(
11920 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11922 if (dest_texture
->IsImmutable()) {
11923 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
11924 "texture is immutable");
11928 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
11929 source_texture_ref
, dest_texture_ref
,
11930 internal_format
)) {
11934 // Clear the source texture if necessary.
11935 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11936 source_texture
->target(), 0)) {
11937 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
11938 "dimensions too big");
11942 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11943 // needed because it takes 10s of milliseconds to initialize.
11944 if (!copy_texture_CHROMIUM_
.get()) {
11945 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11946 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11947 copy_texture_CHROMIUM_
->Initialize(this);
11948 RestoreCurrentFramebufferBindings();
11949 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11953 GLenum dest_type_previous
= dest_type
;
11954 GLenum dest_internal_format
= internal_format
;
11955 int dest_width
= 0;
11956 int dest_height
= 0;
11957 bool dest_level_defined
= dest_texture
->GetLevelSize(
11958 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
11960 if (dest_level_defined
) {
11961 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
11962 &dest_internal_format
);
11965 // Resize the destination texture to the dimensions of the source texture.
11966 if (!dest_level_defined
|| dest_width
!= source_width
||
11967 dest_height
!= source_height
||
11968 dest_internal_format
!= internal_format
||
11969 dest_type_previous
!= dest_type
) {
11970 // Ensure that the glTexImage2D succeeds.
11971 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11972 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11973 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
11974 0, internal_format
, dest_type
, NULL
);
11975 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11976 if (error
!= GL_NO_ERROR
) {
11977 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11981 texture_manager()->SetLevelInfo(
11982 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
11983 source_height
, 1, 0, internal_format
, dest_type
, true);
11985 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11989 ScopedModifyPixels
modify(dest_texture_ref
);
11991 // Try using GLImage::CopyTexSubImage when possible.
11992 bool unpack_premultiply_alpha_change
=
11993 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11994 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
11995 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11996 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
11997 gfx::Rect(0, 0, source_width
, source_height
))) {
12002 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12004 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12005 // before presenting.
12006 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12007 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12008 // instead of using kIdentityMatrix crbug.com/226218.
12009 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12010 this, source_texture
->target(), source_texture
->service_id(),
12011 dest_texture
->service_id(), source_width
, source_height
, unpack_flip_y_
,
12012 unpack_premultiply_alpha_
, unpack_unpremultiply_alpha_
,
12015 copy_texture_CHROMIUM_
->DoCopyTexture(
12016 this, source_texture
->target(), source_texture
->service_id(),
12017 source_internal_format
, dest_texture
->service_id(), internal_format
,
12018 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
12019 unpack_unpremultiply_alpha_
);
12022 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12025 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target
,
12034 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12036 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12037 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12038 Texture
* source_texture
= source_texture_ref
->texture();
12039 Texture
* dest_texture
= dest_texture_ref
->texture();
12040 int source_width
= 0;
12041 int source_height
= 0;
12042 gfx::GLImage
* image
=
12043 source_texture
->GetLevelImage(source_texture
->target(), 0);
12045 gfx::Size size
= image
->GetSize();
12046 source_width
= size
.width();
12047 source_height
= size
.height();
12048 if (source_width
<= 0 || source_height
<= 0) {
12049 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12050 "invalid image size");
12054 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12055 &source_width
, &source_height
, nullptr)) {
12056 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12057 "source texture has no level 0");
12061 // Check that this type of texture is allowed.
12062 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12063 source_width
, source_height
, 1)) {
12064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12065 "source texture bad dimensions");
12070 GLenum source_type
= 0;
12071 GLenum source_internal_format
= 0;
12072 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12073 &source_internal_format
);
12074 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12075 width
, height
, 1, source_type
)) {
12076 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12077 "source texture bad dimensions.");
12081 GLenum dest_type
= 0;
12082 GLenum dest_internal_format
= 0;
12083 bool dest_level_defined
= dest_texture
->GetLevelType(
12084 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12085 if (!dest_level_defined
) {
12086 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12087 "destination texture is not defined");
12090 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12091 yoffset
, 0, width
, height
, 1, dest_type
)) {
12092 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12093 "destination texture bad dimensions.");
12097 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12098 source_texture_ref
, dest_texture_ref
,
12099 dest_internal_format
)) {
12103 // Clear the source texture if necessary.
12104 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12105 source_texture
->target(), 0)) {
12106 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12107 "source texture dimensions too big");
12111 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12112 // needed because it takes 10s of milliseconds to initialize.
12113 if (!copy_texture_CHROMIUM_
.get()) {
12114 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12115 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12116 copy_texture_CHROMIUM_
->Initialize(this);
12117 RestoreCurrentFramebufferBindings();
12118 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12122 int dest_width
= 0;
12123 int dest_height
= 0;
12124 bool ok
= dest_texture
->GetLevelSize(
12125 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12127 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12128 height
!= dest_height
) {
12129 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12131 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12132 "destination texture dimensions too big");
12136 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12140 ScopedModifyPixels
modify(dest_texture_ref
);
12142 // Try using GLImage::CopyTexSubImage when possible.
12143 bool unpack_premultiply_alpha_change
=
12144 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
12145 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
12146 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12147 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12148 gfx::Rect(x
, y
, width
, height
))) {
12153 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12155 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12156 // crbug.com/226218.
12157 copy_texture_CHROMIUM_
->DoCopySubTexture(
12158 this, source_texture
->target(), source_texture
->service_id(),
12159 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12160 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12161 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
12162 unpack_unpremultiply_alpha_
);
12164 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12167 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
12168 switch (internalformat
) {
12170 return GL_UNSIGNED_SHORT_5_6_5
;
12172 return GL_UNSIGNED_SHORT_4_4_4_4
;
12174 return GL_UNSIGNED_SHORT_5_5_5_1
;
12176 return GL_UNSIGNED_BYTE
;
12178 return GL_UNSIGNED_BYTE
;
12179 case GL_LUMINANCE8_ALPHA8_EXT
:
12180 return GL_UNSIGNED_BYTE
;
12181 case GL_LUMINANCE8_EXT
:
12182 return GL_UNSIGNED_BYTE
;
12183 case GL_ALPHA8_EXT
:
12184 return GL_UNSIGNED_BYTE
;
12185 case GL_RGBA32F_EXT
:
12187 case GL_RGB32F_EXT
:
12189 case GL_ALPHA32F_EXT
:
12191 case GL_LUMINANCE32F_EXT
:
12193 case GL_LUMINANCE_ALPHA32F_EXT
:
12195 case GL_RGBA16F_EXT
:
12196 return GL_HALF_FLOAT_OES
;
12197 case GL_RGB16F_EXT
:
12198 return GL_HALF_FLOAT_OES
;
12199 case GL_ALPHA16F_EXT
:
12200 return GL_HALF_FLOAT_OES
;
12201 case GL_LUMINANCE16F_EXT
:
12202 return GL_HALF_FLOAT_OES
;
12203 case GL_LUMINANCE_ALPHA16F_EXT
:
12204 return GL_HALF_FLOAT_OES
;
12206 return GL_UNSIGNED_BYTE
;
12212 void GLES2DecoderImpl::DoTexStorage2DEXT(
12215 GLenum internal_format
,
12218 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12219 "width", width
, "height", height
);
12220 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12221 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12222 LOCAL_SET_GL_ERROR(
12223 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12226 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12228 if (!texture_ref
) {
12229 LOCAL_SET_GL_ERROR(
12230 GL_INVALID_OPERATION
,
12231 "glTexStorage2DEXT", "unknown texture for target");
12234 Texture
* texture
= texture_ref
->texture();
12235 if (texture
->IsAttachedToFramebuffer()) {
12236 framebuffer_state_
.clear_state_dirty
= true;
12238 if (texture
->IsImmutable()) {
12239 LOCAL_SET_GL_ERROR(
12240 GL_INVALID_OPERATION
,
12241 "glTexStorage2DEXT", "texture is immutable");
12245 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12246 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12249 GLsizei level_width
= width
;
12250 GLsizei level_height
= height
;
12251 uint32 estimated_size
= 0;
12252 for (int ii
= 0; ii
< levels
; ++ii
) {
12253 uint32 level_size
= 0;
12254 if (!GLES2Util::ComputeImageDataSizes(
12255 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12256 &estimated_size
, NULL
, NULL
) ||
12257 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12258 LOCAL_SET_GL_ERROR(
12259 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12262 level_width
= std::max(1, level_width
>> 1);
12263 level_height
= std::max(1, level_height
>> 1);
12265 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12266 LOCAL_SET_GL_ERROR(
12267 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
12272 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12273 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
12274 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12275 if (error
== GL_NO_ERROR
) {
12276 GLsizei level_width
= width
;
12277 GLsizei level_height
= height
;
12278 for (int ii
= 0; ii
< levels
; ++ii
) {
12279 texture_manager()->SetLevelInfo(
12280 texture_ref
, target
, ii
, format
,
12281 level_width
, level_height
, 1, 0, format
, type
, false);
12282 level_width
= std::max(1, level_width
>> 1);
12283 level_height
= std::max(1, level_height
>> 1);
12285 texture
->SetImmutable(true);
12289 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12290 uint32 immediate_data_size
,
12291 const void* cmd_data
) {
12292 return error::kUnknownCommand
;
12295 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
12296 const GLbyte
* data
) {
12297 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12298 "context", logger_
.GetLogPrefix(),
12299 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12301 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12303 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
12306 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
12307 GLenum target
, const GLbyte
* data
) {
12308 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12309 "context", logger_
.GetLogPrefix(),
12310 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12312 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
12316 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
12317 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
12318 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12319 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
12320 "mailbox that was not generated by "
12321 "GenMailboxCHROMIUM.";
12323 if (!texture_ref
) {
12324 LOCAL_SET_GL_ERROR(
12325 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
12329 Texture
* produced
= texture_manager()->Produce(texture_ref
);
12331 LOCAL_SET_GL_ERROR(
12332 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
12336 if (produced
->target() != target
) {
12337 LOCAL_SET_GL_ERROR(
12338 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
12342 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
12345 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
12346 const GLbyte
* data
) {
12347 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12348 "context", logger_
.GetLogPrefix(),
12349 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12350 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12351 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12352 "mailbox that was not generated by "
12353 "GenMailboxCHROMIUM.";
12355 scoped_refptr
<TextureRef
> texture_ref
=
12356 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12357 if (!texture_ref
.get()) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12359 "glConsumeTextureCHROMIUM",
12360 "unknown texture for target");
12363 GLuint client_id
= texture_ref
->client_id();
12365 LOCAL_SET_GL_ERROR(
12366 GL_INVALID_OPERATION
,
12367 "glConsumeTextureCHROMIUM", "unknown texture for target");
12370 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12372 LOCAL_SET_GL_ERROR(
12373 GL_INVALID_OPERATION
,
12374 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12377 if (texture
->target() != target
) {
12378 LOCAL_SET_GL_ERROR(
12379 GL_INVALID_OPERATION
,
12380 "glConsumeTextureCHROMIUM", "invalid target");
12384 DeleteTexturesHelper(1, &client_id
);
12385 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12386 glBindTexture(target
, texture_ref
->service_id());
12388 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
12389 unit
.bind_target
= target
;
12391 case GL_TEXTURE_2D
:
12392 unit
.bound_texture_2d
= texture_ref
;
12394 case GL_TEXTURE_CUBE_MAP
:
12395 unit
.bound_texture_cube_map
= texture_ref
;
12397 case GL_TEXTURE_EXTERNAL_OES
:
12398 unit
.bound_texture_external_oes
= texture_ref
;
12400 case GL_TEXTURE_RECTANGLE_ARB
:
12401 unit
.bound_texture_rectangle_arb
= texture_ref
;
12404 NOTREACHED(); // Validation should prevent us getting here.
12409 void GLES2DecoderImpl::EnsureTextureForClientId(
12411 GLuint client_id
) {
12412 TextureRef
* texture_ref
= GetTexture(client_id
);
12413 if (!texture_ref
) {
12415 glGenTextures(1, &service_id
);
12416 DCHECK_NE(0u, service_id
);
12417 texture_ref
= CreateTexture(client_id
, service_id
);
12418 texture_manager()->SetTarget(texture_ref
, target
);
12419 glBindTexture(target
, service_id
);
12420 RestoreCurrentTextureBindings(&state_
, target
);
12424 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12425 // provided is associated with a service_id/TextureRef for consistency, even if
12426 // the resulting texture is incomplete.
12427 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12428 uint32_t immediate_data_size
,
12429 const void* cmd_data
) {
12430 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
12432 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
12434 GLenum target
= static_cast<GLenum
>(c
.target
);
12435 uint32_t data_size
;
12436 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
12437 return error::kOutOfBounds
;
12439 if (data_size
> immediate_data_size
) {
12440 return error::kOutOfBounds
;
12442 const GLbyte
* mailbox
=
12443 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
12444 if (!validators_
->texture_bind_target
.IsValid(target
)) {
12445 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12446 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
12447 return error::kNoError
;
12449 if (mailbox
== NULL
) {
12450 return error::kOutOfBounds
;
12452 uint32_t client_id
= c
.client_id
;
12453 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
12454 return error::kNoError
;
12457 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
12458 const GLbyte
* data
, GLuint client_id
) {
12459 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12460 "context", logger_
.GetLogPrefix(),
12461 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12462 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12463 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12464 "passed a mailbox that was not "
12465 "generated by GenMailboxCHROMIUM.";
12467 TextureRef
* texture_ref
= GetTexture(client_id
);
12469 // No need to call EnsureTextureForClientId here, the client_id already has
12470 // an associated texture.
12471 LOCAL_SET_GL_ERROR(
12472 GL_INVALID_OPERATION
,
12473 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12476 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12478 EnsureTextureForClientId(target
, client_id
);
12479 LOCAL_SET_GL_ERROR(
12480 GL_INVALID_OPERATION
,
12481 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12485 if (texture
->target() != target
) {
12486 EnsureTextureForClientId(target
, client_id
);
12487 LOCAL_SET_GL_ERROR(
12488 GL_INVALID_OPERATION
,
12489 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12493 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12496 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
12497 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
12498 return valuebuffer
&& valuebuffer
->IsValid();
12501 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
12502 GLuint client_id
) {
12503 Valuebuffer
* valuebuffer
= NULL
;
12504 if (client_id
!= 0) {
12505 valuebuffer
= GetValuebuffer(client_id
);
12506 if (!valuebuffer
) {
12507 if (!group_
->bind_generates_resource()) {
12508 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
12509 "id not generated by glBindValuebufferCHROMIUM");
12513 // It's a new id so make a valuebuffer for it.
12514 CreateValuebuffer(client_id
);
12515 valuebuffer
= GetValuebuffer(client_id
);
12517 valuebuffer
->MarkAsValid();
12519 state_
.bound_valuebuffer
= valuebuffer
;
12522 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
12523 GLenum subscription
) {
12524 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12527 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
12530 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
12531 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12534 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
12537 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
12539 GLenum subscription
) {
12540 if (!CheckCurrentValuebufferForSubscription(
12541 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
12544 if (!CheckSubscriptionTarget(location
, subscription
,
12545 "glPopulateSubscribedValuesCHROMIUM")) {
12548 const ValueState
* state
=
12549 state_
.bound_valuebuffer
.get()->GetState(subscription
);
12551 switch (subscription
) {
12552 case GL_MOUSE_POSITION_CHROMIUM
:
12553 DoUniform2iv(location
, 1, state
->int_value
);
12556 NOTREACHED() << "Unhandled uniform subscription target "
12563 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12564 GLsizei length
, const GLchar
* marker
) {
12568 debug_marker_manager_
.SetMarker(
12569 length
? std::string(marker
, length
) : std::string(marker
));
12572 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12573 GLsizei length
, const GLchar
* marker
) {
12577 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
12578 debug_marker_manager_
.PushGroup(name
);
12579 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
12580 kTraceGroupMarker
);
12583 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12584 debug_marker_manager_
.PopGroup();
12585 gpu_tracer_
->End(kTraceGroupMarker
);
12588 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12589 GLenum target
, GLint image_id
) {
12590 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12592 if (target
== GL_TEXTURE_CUBE_MAP
) {
12593 LOCAL_SET_GL_ERROR(
12595 "glBindTexImage2DCHROMIUM", "invalid target");
12599 // Default target might be conceptually valid, but disallow it to avoid
12601 TextureRef
* texture_ref
=
12602 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12603 if (!texture_ref
) {
12604 LOCAL_SET_GL_ERROR(
12605 GL_INVALID_OPERATION
,
12606 "glBindTexImage2DCHROMIUM", "no texture bound");
12610 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12612 LOCAL_SET_GL_ERROR(
12613 GL_INVALID_OPERATION
,
12614 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12619 ScopedGLErrorSuppressor
suppressor(
12620 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12621 if (!gl_image
->BindTexImage(target
)) {
12622 LOCAL_SET_GL_ERROR(
12623 GL_INVALID_OPERATION
,
12624 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12629 gfx::Size size
= gl_image
->GetSize();
12630 texture_manager()->SetLevelInfo(
12631 texture_ref
, target
, 0, gl_image
->GetInternalFormat(),
12632 size
.width(), size
.height(), 1, 0,
12633 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, true);
12634 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
12637 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12638 GLenum target
, GLint image_id
) {
12639 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12641 // Default target might be conceptually valid, but disallow it to avoid
12643 TextureRef
* texture_ref
=
12644 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12645 if (!texture_ref
) {
12646 LOCAL_SET_GL_ERROR(
12647 GL_INVALID_OPERATION
,
12648 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12652 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12654 LOCAL_SET_GL_ERROR(
12655 GL_INVALID_OPERATION
,
12656 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12660 // Do nothing when image is not currently bound.
12661 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
12665 ScopedGLErrorSuppressor
suppressor(
12666 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12667 gl_image
->ReleaseTexImage(target
);
12670 texture_manager()->SetLevelInfo(
12671 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
12672 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, false);
12675 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12676 uint32 immediate_data_size
,
12677 const void* cmd_data
) {
12678 const gles2::cmds::TraceBeginCHROMIUM
& c
=
12679 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
12680 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
12681 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
12682 if (!category_bucket
|| category_bucket
->size() == 0 ||
12683 !name_bucket
|| name_bucket
->size() == 0) {
12684 return error::kInvalidArguments
;
12687 std::string category_name
;
12688 std::string trace_name
;
12689 if (!category_bucket
->GetAsString(&category_name
) ||
12690 !name_bucket
->GetAsString(&trace_name
)) {
12691 return error::kInvalidArguments
;
12694 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
12695 LOCAL_SET_GL_ERROR(
12696 GL_INVALID_OPERATION
,
12697 "glTraceBeginCHROMIUM", "unable to create begin trace");
12698 return error::kNoError
;
12700 return error::kNoError
;
12703 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12704 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
12705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12706 "glTraceEndCHROMIUM", "no trace begin found");
12711 void GLES2DecoderImpl::DoDrawBuffersEXT(
12712 GLsizei count
, const GLenum
* bufs
) {
12713 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
12714 LOCAL_SET_GL_ERROR(
12716 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12720 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
12722 for (GLsizei i
= 0; i
< count
; ++i
) {
12723 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
12724 bufs
[i
] != GL_NONE
) {
12725 LOCAL_SET_GL_ERROR(
12726 GL_INVALID_OPERATION
,
12727 "glDrawBuffersEXT",
12728 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12732 glDrawBuffersARB(count
, bufs
);
12733 framebuffer
->SetDrawBuffers(count
, bufs
);
12734 } else { // backbuffer
12736 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
12737 LOCAL_SET_GL_ERROR(
12738 GL_INVALID_OPERATION
,
12739 "glDrawBuffersEXT",
12740 "more than one buffer or bufs not GL_NONE or GL_BACK");
12743 GLenum mapped_buf
= bufs
[0];
12744 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12745 bufs
[0] == GL_BACK
) {
12746 mapped_buf
= GL_COLOR_ATTACHMENT0
;
12748 glDrawBuffersARB(count
, &mapped_buf
);
12749 group_
->set_draw_buffer(bufs
[0]);
12753 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
12754 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
12755 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
12756 reset_by_robustness_extension_
= true;
12759 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
12760 const GLfloat
* matrix
) {
12761 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12762 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12763 if (!features().chromium_path_rendering
) {
12764 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12765 "glMatrixLoadfCHROMIUM",
12766 "function not available");
12770 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12771 ? state_
.projection_matrix
12772 : state_
.modelview_matrix
;
12773 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
12774 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12775 // since the values of the _NV and _CHROMIUM tokens match.
12776 glMatrixLoadfEXT(matrix_mode
, matrix
);
12779 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
12780 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12781 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12783 if (!features().chromium_path_rendering
) {
12784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12785 "glMatrixLoadIdentityCHROMIUM",
12786 "function not available");
12790 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12791 ? state_
.projection_matrix
12792 : state_
.modelview_matrix
;
12793 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
12794 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12795 // since the values of the _NV and _CHROMIUM tokens match.
12796 glMatrixLoadIdentityEXT(matrix_mode
);
12799 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12800 const char* function_name
,
12801 TextureRef
* texture_ref
,
12804 const void * data
) {
12805 // We only support async uploads to 2D textures for now.
12806 if (GL_TEXTURE_2D
!= target
) {
12807 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
12810 // We only support uploads to level zero for now.
12812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
12815 // A transfer buffer must be bound, even for asyncTexImage2D.
12816 if (data
== NULL
) {
12817 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
12820 // We only support one async transfer in progress.
12821 if (!texture_ref
||
12822 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
12823 LOCAL_SET_GL_ERROR(
12824 GL_INVALID_OPERATION
,
12825 function_name
, "transfer already in progress");
12831 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12832 uint32 async_upload_token
,
12833 uint32 sync_data_shm_id
,
12834 uint32 sync_data_shm_offset
) {
12835 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
12836 if (!buffer
.get() ||
12837 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
12838 return base::Closure();
12840 AsyncMemoryParams
mem_params(buffer
,
12841 sync_data_shm_offset
,
12842 sizeof(AsyncUploadSync
));
12844 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
12845 new AsyncUploadTokenCompletionObserver(async_upload_token
));
12848 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
12849 base::Unretained(GetAsyncPixelTransferManager()),
12854 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12855 uint32 immediate_data_size
,
12856 const void* cmd_data
) {
12857 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
12858 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
12859 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12860 GLenum target
= static_cast<GLenum
>(c
.target
);
12861 GLint level
= static_cast<GLint
>(c
.level
);
12862 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
12863 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12864 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12865 GLint border
= static_cast<GLint
>(c
.border
);
12866 GLenum format
= static_cast<GLenum
>(c
.format
);
12867 GLenum type
= static_cast<GLenum
>(c
.type
);
12868 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
12869 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
12870 uint32 pixels_size
;
12871 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12872 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12873 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12875 base::ScopedClosureRunner scoped_completion_callback
;
12876 if (async_upload_token
) {
12877 base::Closure completion_closure
=
12878 AsyncUploadTokenCompletionClosure(async_upload_token
,
12880 sync_data_shm_offset
);
12881 if (completion_closure
.is_null())
12882 return error::kInvalidArguments
;
12884 scoped_completion_callback
.Reset(completion_closure
);
12887 // TODO(epenner): Move this and copies of this memory validation
12888 // into ValidateTexImage2D step.
12889 if (!GLES2Util::ComputeImageDataSizes(
12890 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
12892 return error::kOutOfBounds
;
12894 const void* pixels
= NULL
;
12895 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
12896 pixels
= GetSharedMemoryAs
<const void*>(
12897 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
12899 return error::kOutOfBounds
;
12903 TextureManager::DoTexImageArguments args
= {
12904 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
12905 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
12906 TextureRef
* texture_ref
;
12907 // All the normal glTexSubImage2D validation.
12908 if (!texture_manager()->ValidateTexImage(
12909 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
12910 return error::kNoError
;
12913 // Extra async validation.
12914 Texture
* texture
= texture_ref
->texture();
12915 if (!ValidateAsyncTransfer(
12916 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12917 return error::kNoError
;
12919 // Don't allow async redefinition of a textures.
12920 if (texture
->IsDefined()) {
12921 LOCAL_SET_GL_ERROR(
12922 GL_INVALID_OPERATION
,
12923 "glAsyncTexImage2DCHROMIUM", "already defined");
12924 return error::kNoError
;
12927 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
12928 LOCAL_SET_GL_ERROR(
12929 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
12930 return error::kNoError
;
12933 // Setup the parameters.
12934 AsyncTexImage2DParams tex_params
= {
12935 target
, level
, static_cast<GLenum
>(internal_format
),
12936 width
, height
, border
, format
, type
};
12937 AsyncMemoryParams
mem_params(
12938 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
12940 // Set up the async state if needed, and make the texture
12941 // immutable so the async state stays valid. The level info
12942 // is set up lazily when the transfer completes.
12943 AsyncPixelTransferDelegate
* delegate
=
12944 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
12946 texture
->SetImmutable(true);
12948 delegate
->AsyncTexImage2D(
12951 base::Bind(&TextureManager::SetLevelInfoFromParams
,
12952 // The callback is only invoked if the transfer delegate still
12953 // exists, which implies through manager->texture_ref->state
12954 // ownership that both of these pointers are valid.
12955 base::Unretained(texture_manager()),
12956 base::Unretained(texture_ref
),
12958 return error::kNoError
;
12961 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12962 uint32 immediate_data_size
,
12963 const void* cmd_data
) {
12964 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
12965 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
12966 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12967 GLenum target
= static_cast<GLenum
>(c
.target
);
12968 GLint level
= static_cast<GLint
>(c
.level
);
12969 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
12970 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
12971 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12972 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12973 GLenum format
= static_cast<GLenum
>(c
.format
);
12974 GLenum type
= static_cast<GLenum
>(c
.type
);
12975 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12976 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12977 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12979 base::ScopedClosureRunner scoped_completion_callback
;
12980 if (async_upload_token
) {
12981 base::Closure completion_closure
=
12982 AsyncUploadTokenCompletionClosure(async_upload_token
,
12984 sync_data_shm_offset
);
12985 if (completion_closure
.is_null())
12986 return error::kInvalidArguments
;
12988 scoped_completion_callback
.Reset(completion_closure
);
12991 // TODO(epenner): Move this and copies of this memory validation
12992 // into ValidateTexSubImage2D step.
12994 if (!GLES2Util::ComputeImageDataSizes(
12995 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
12997 return error::kOutOfBounds
;
12999 const void* pixels
= GetSharedMemoryAs
<const void*>(
13000 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13002 // All the normal glTexSubImage2D validation.
13003 error::Error error
= error::kNoError
;
13004 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13005 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13009 // Extra async validation.
13010 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13012 Texture
* texture
= texture_ref
->texture();
13013 if (!ValidateAsyncTransfer(
13014 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13015 return error::kNoError
;
13017 // Guarantee async textures are always 'cleared' as follows:
13018 // - AsyncTexImage2D can not redefine an existing texture
13019 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13020 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13021 // - Textures become immutable after an async call.
13022 // This way we know in all cases that an async texture is always clear.
13023 if (!texture
->SafeToRenderFrom()) {
13024 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
13026 LOCAL_SET_GL_ERROR(
13028 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13029 return error::kNoError
;
13033 // Setup the parameters.
13034 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
13035 width
, height
, format
, type
};
13036 AsyncMemoryParams
mem_params(
13037 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
13038 AsyncPixelTransferDelegate
* delegate
=
13039 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13041 // TODO(epenner): We may want to enforce exclusive use
13042 // of async APIs in which case this should become an error,
13043 // (the texture should have been async defined).
13044 AsyncTexImage2DParams define_params
= {target
, level
,
13046 texture
->GetLevelSize(
13047 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
13048 texture
->GetLevelType(
13049 target
, level
, &define_params
.type
, &define_params
.internal_format
);
13050 // Set up the async state if needed, and make the texture
13051 // immutable so the async state stays valid.
13052 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
13053 texture_ref
, define_params
);
13054 texture
->SetImmutable(true);
13057 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
13058 return error::kNoError
;
13061 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13062 uint32 immediate_data_size
,
13063 const void* cmd_data
) {
13064 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
13065 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
13066 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13067 GLenum target
= static_cast<GLenum
>(c
.target
);
13069 if (GL_TEXTURE_2D
!= target
) {
13070 LOCAL_SET_GL_ERROR(
13071 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
13072 return error::kNoError
;
13074 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13076 if (!texture_ref
) {
13077 LOCAL_SET_GL_ERROR(
13078 GL_INVALID_OPERATION
,
13079 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13080 return error::kNoError
;
13082 AsyncPixelTransferDelegate
* delegate
=
13083 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13085 LOCAL_SET_GL_ERROR(
13086 GL_INVALID_OPERATION
,
13087 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13088 return error::kNoError
;
13090 delegate
->WaitForTransferCompletion();
13091 ProcessFinishedAsyncTransfers();
13092 return error::kNoError
;
13095 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13096 uint32 immediate_data_size
,
13097 const void* data
) {
13098 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13100 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13101 ProcessFinishedAsyncTransfers();
13102 return error::kNoError
;
13105 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
13106 uint32_t immediate_data_size
, const void* cmd_data
) {
13107 if (!unsafe_es3_apis_enabled())
13108 return error::kUnknownCommand
;
13109 const gles2::cmds::UniformBlockBinding
& c
=
13110 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
13111 GLuint client_id
= c
.program
;
13112 GLuint index
= static_cast<GLuint
>(c
.index
);
13113 GLuint binding
= static_cast<GLuint
>(c
.binding
);
13114 Program
* program
= GetProgramInfoNotShader(
13115 client_id
, "glUniformBlockBinding");
13117 return error::kNoError
;
13119 GLuint service_id
= program
->service_id();
13120 glUniformBlockBinding(service_id
, index
, binding
);
13121 return error::kNoError
;
13124 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
13125 uint32_t immediate_data_size
, const void* cmd_data
) {
13126 if (!unsafe_es3_apis_enabled())
13127 return error::kUnknownCommand
;
13128 const gles2::cmds::ClientWaitSync
& c
=
13129 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
13130 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13131 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13132 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13133 typedef cmds::ClientWaitSync::Result Result
;
13134 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
13135 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
13137 return error::kOutOfBounds
;
13139 if (*result_dst
!= GL_WAIT_FAILED
) {
13140 return error::kInvalidArguments
;
13142 GLsync service_sync
= 0;
13143 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13144 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
13145 return error::kNoError
;
13147 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
13148 return error::kNoError
;
13151 error::Error
GLES2DecoderImpl::HandleWaitSync(
13152 uint32_t immediate_data_size
, const void* cmd_data
) {
13153 if (!unsafe_es3_apis_enabled())
13154 return error::kUnknownCommand
;
13155 const gles2::cmds::WaitSync
& c
=
13156 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
13157 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13158 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13159 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13160 GLsync service_sync
= 0;
13161 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13162 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
13163 return error::kNoError
;
13165 glWaitSync(service_sync
, flags
, timeout
);
13166 return error::kNoError
;
13169 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13170 uint32_t immediate_data_size
, const void* cmd_data
) {
13171 if (!unsafe_es3_apis_enabled()) {
13172 return error::kUnknownCommand
;
13174 const gles2::cmds::MapBufferRange
& c
=
13175 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13176 GLenum target
= static_cast<GLenum
>(c
.target
);
13177 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13178 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13179 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13181 typedef cmds::MapBufferRange::Result Result
;
13182 Result
* result
= GetSharedMemoryAs
<Result
*>(
13183 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13185 return error::kOutOfBounds
;
13187 if (*result
!= 0) {
13189 return error::kInvalidArguments
;
13192 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13194 return error::kOutOfBounds
;
13197 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13198 if ((access
& mask
) == mask
) {
13199 // TODO(zmo): To be on the safe side, always map
13200 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13201 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13202 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
13204 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13205 // undefined behaviors.
13206 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
13207 if ((access
& mask
) == mask
) {
13208 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
13209 "incompatible access bits");
13210 return error::kNoError
;
13212 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
13213 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
13214 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13215 access
= (access
| GL_MAP_READ_BIT
);
13217 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
13218 if (ptr
== nullptr) {
13219 return error::kNoError
;
13221 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13223 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
13224 GetSharedMemoryBuffer(c
.data_shm_id
));
13225 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13226 memcpy(mem
, ptr
, size
);
13229 return error::kNoError
;
13232 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
13233 uint32_t immediate_data_size
, const void* cmd_data
) {
13234 if (!unsafe_es3_apis_enabled()) {
13235 return error::kUnknownCommand
;
13237 const gles2::cmds::UnmapBuffer
& c
=
13238 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
13239 GLenum target
= static_cast<GLenum
>(c
.target
);
13241 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13243 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
13244 return error::kNoError
;
13246 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
13247 if (!mapped_range
) {
13248 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
13249 "buffer is unmapped");
13250 return error::kNoError
;
13252 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
13253 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
13254 GL_MAP_FLUSH_EXPLICIT_BIT
) {
13255 // If we don't need to write back, or explict flush is required, no copying
13258 void* mem
= mapped_range
->GetShmPointer();
13260 return error::kOutOfBounds
;
13262 DCHECK(mapped_range
->pointer
);
13263 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
13265 buffer
->RemoveMappedRange();
13266 GLboolean rt
= glUnmapBuffer(target
);
13267 if (rt
== GL_FALSE
) {
13268 // At this point, we have already done the necessary validation, so
13269 // GL_FALSE indicates data corruption.
13270 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13271 // the second unmap could still return GL_FALSE. For now, we simply lose
13272 // the contexts in the share group.
13273 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13274 // Need to lose current context before broadcasting!
13275 MarkContextLost(error::kGuilty
);
13276 group_
->LoseContexts(error::kInnocent
);
13277 return error::kLostContext
;
13279 return error::kNoError
;
13282 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13283 TextureRef
* texture_ref
) {
13284 Texture
* texture
= texture_ref
->texture();
13285 DoDidUseTexImageIfNeeded(texture
, texture
->target());
13288 // Note that GL_LOST_CONTEXT is specific to GLES.
13289 // For desktop GL we have to query the reset status proactively.
13290 void GLES2DecoderImpl::OnContextLostError() {
13291 if (!WasContextLost()) {
13292 // Need to lose current context before broadcasting!
13293 CheckResetStatus();
13294 group_
->LoseContexts(error::kUnknown
);
13295 reset_by_robustness_extension_
= true;
13299 void GLES2DecoderImpl::OnOutOfMemoryError() {
13300 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
13301 error::ContextLostReason other
= error::kOutOfMemory
;
13302 if (CheckResetStatus()) {
13303 other
= error::kUnknown
;
13305 // Need to lose current context before broadcasting!
13306 MarkContextLost(error::kOutOfMemory
);
13308 group_
->LoseContexts(other
);
13312 // Include the auto-generated part of this file. We split this because it means
13313 // we can easily edit the non-auto generated parts right here in this file
13314 // instead of having to edit some template or the code generator.
13315 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13317 } // namespace gles2