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 SetAllowExit(bool allow_exit
) override
;
689 void ProcessFinishedAsyncTransfers();
691 bool GetServiceTextureId(uint32 client_texture_id
,
692 uint32
* service_texture_id
) override
;
694 uint32
GetTextureUploadCount() override
;
695 base::TimeDelta
GetTotalTextureUploadTime() override
;
696 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
697 void AddProcessingCommandsTime(base::TimeDelta
) override
;
699 // Restores the current state to the user's settings.
700 void RestoreCurrentFramebufferBindings();
702 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
703 void ApplyDirtyState();
705 // These check the state of the currently bound framebuffer or the
706 // backbuffer if no framebuffer is bound.
707 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
708 // check with all attached and enabled color attachments.
709 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
710 bool BoundFramebufferHasDepthAttachment();
711 bool BoundFramebufferHasStencilAttachment();
713 error::ContextLostReason
GetContextLostReason() override
;
715 // Overridden from FramebufferManager::TextureDetachObserver:
716 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
718 // Overriden from ErrorStateClient.
719 void OnContextLostError() override
;
720 void OnOutOfMemoryError() override
;
722 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
723 void EnsureRenderbufferBound();
725 // Helpers to facilitate calling into compatible extensions.
726 static void RenderbufferStorageMultisampleHelper(
727 const FeatureInfo
* feature_info
,
730 GLenum internal_format
,
734 void BlitFramebufferHelper(GLint srcX0
,
746 friend class ScopedFrameBufferBinder
;
747 friend class ScopedResolvedFrameBufferBinder
;
748 friend class BackFramebuffer
;
750 // Initialize or re-initialize the shader translator.
751 bool InitializeShaderTranslator();
753 void UpdateCapabilities();
755 // Helpers for the glGen and glDelete functions.
756 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
757 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
758 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
759 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
760 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
761 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
762 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
763 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
764 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
765 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
766 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
767 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
768 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
769 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
771 // Helper for async upload token completion notification callback.
772 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
773 uint32 sync_data_shm_id
,
774 uint32 sync_data_shm_offset
);
779 void OnFboChanged() const;
780 void OnUseFramebuffer() const;
782 error::ContextLostReason
GetContextLostReasonFromResetStatus(
783 GLenum reset_status
) const;
785 // TODO(gman): Cache these pointers?
786 BufferManager
* buffer_manager() {
787 return group_
->buffer_manager();
790 RenderbufferManager
* renderbuffer_manager() {
791 return group_
->renderbuffer_manager();
794 FramebufferManager
* framebuffer_manager() {
795 return group_
->framebuffer_manager();
798 ValuebufferManager
* valuebuffer_manager() {
799 return group_
->valuebuffer_manager();
802 ProgramManager
* program_manager() {
803 return group_
->program_manager();
806 ShaderManager
* shader_manager() {
807 return group_
->shader_manager();
810 ShaderTranslatorCache
* shader_translator_cache() {
811 return group_
->shader_translator_cache();
814 const TextureManager
* texture_manager() const {
815 return group_
->texture_manager();
818 TextureManager
* texture_manager() {
819 return group_
->texture_manager();
822 MailboxManager
* mailbox_manager() {
823 return group_
->mailbox_manager();
826 ImageManager
* image_manager() { return image_manager_
.get(); }
828 VertexArrayManager
* vertex_array_manager() {
829 return vertex_array_manager_
.get();
832 MemoryTracker
* memory_tracker() {
833 return group_
->memory_tracker();
836 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
837 MemoryTracker
* tracker
= memory_tracker();
839 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
844 bool IsOffscreenBufferMultisampled() const {
845 return offscreen_target_samples_
> 1;
848 // Creates a Texture for the given texture.
849 TextureRef
* CreateTexture(
850 GLuint client_id
, GLuint service_id
) {
851 return texture_manager()->CreateTexture(client_id
, service_id
);
854 // Gets the texture info for the given texture. Returns NULL if none exists.
855 TextureRef
* GetTexture(GLuint client_id
) const {
856 return texture_manager()->GetTexture(client_id
);
859 // Deletes the texture info for the given texture.
860 void RemoveTexture(GLuint client_id
) {
861 texture_manager()->RemoveTexture(client_id
);
864 // Get the size (in pixels) of the currently bound frame buffer (either FBO
865 // or regular back buffer).
866 gfx::Size
GetBoundReadFrameBufferSize();
868 // Get the format of the currently bound frame buffer (either FBO or regular
870 GLenum
GetBoundReadFrameBufferTextureType();
871 GLenum
GetBoundReadFrameBufferInternalFormat();
872 GLenum
GetBoundDrawFrameBufferInternalFormat();
874 // Wrapper for CompressedTexImage2D commands.
875 error::Error
DoCompressedTexImage2D(
878 GLenum internal_format
,
885 // Wrapper for CompressedTexImage3D commands.
886 error::Error
DoCompressedTexImage3D(
889 GLenum internal_format
,
897 // Wrapper for CompressedTexSubImage2D.
898 void DoCompressedTexSubImage2D(
909 // Wrapper for CompressedTexSubImage3D.
910 void DoCompressedTexSubImage3D(
923 // Wrapper for CopyTexImage2D.
924 void DoCopyTexImage2D(
927 GLenum internal_format
,
934 // Wrapper for SwapBuffers.
935 void DoSwapBuffers();
937 // Wrapper for SwapInterval.
938 void DoSwapInterval(int interval
);
940 // Wrapper for CopyTexSubImage2D.
941 void DoCopyTexSubImage2D(
951 // Validation for TexSubImage2D.
952 bool ValidateTexSubImage2D(
954 const char* function_name
,
965 // Wrapper for TexSubImage2D.
966 error::Error
DoTexSubImage2D(
977 // Wrapper for TexSubImage3D.
978 error::Error
DoTexSubImage3D(
991 // Extra validation for async tex(Sub)Image2D.
992 bool ValidateAsyncTransfer(
993 const char* function_name
,
994 TextureRef
* texture_ref
,
999 // Wrapper for TexImageIOSurface2DCHROMIUM.
1000 void DoTexImageIOSurface2DCHROMIUM(
1004 GLuint io_surface_id
,
1007 void DoCopyTextureCHROMIUM(GLenum target
,
1010 GLenum internal_format
,
1013 void DoCopySubTextureCHROMIUM(GLenum target
,
1023 // Wrapper for TexStorage2DEXT.
1024 void DoTexStorage2DEXT(
1027 GLenum internal_format
,
1031 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1032 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1034 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1035 GLenum target
, const GLbyte
* data
);
1037 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1038 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1039 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1042 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1043 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1044 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1045 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1046 void DoUniformValueBufferCHROMIUM(GLint location
,
1048 GLenum subscription
);
1050 void DoBindTexImage2DCHROMIUM(
1053 void DoReleaseTexImage2DCHROMIUM(
1057 void DoTraceEndCHROMIUM(void);
1059 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1061 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1063 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1064 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1066 // Creates a Program for the given program.
1067 Program
* CreateProgram(
1068 GLuint client_id
, GLuint service_id
) {
1069 return program_manager()->CreateProgram(client_id
, service_id
);
1072 // Gets the program info for the given program. Returns NULL if none exists.
1073 Program
* GetProgram(GLuint client_id
) {
1074 return program_manager()->GetProgram(client_id
);
1078 void LogClientServiceMapping(
1079 const char* /* function_name */,
1080 GLuint
/* client_id */,
1081 GLuint
/* service_id */) {
1083 template<typename T
>
1084 void LogClientServiceForInfo(
1085 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1088 void LogClientServiceMapping(
1089 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1090 if (service_logging_
) {
1091 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1092 << ": client_id = " << client_id
1093 << ", service_id = " << service_id
;
1096 template<typename T
>
1097 void LogClientServiceForInfo(
1098 T
* info
, GLuint client_id
, const char* function_name
) {
1100 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1105 // Gets the program info for the given program. If it's not a program
1106 // generates a GL error. Returns NULL if not program.
1107 Program
* GetProgramInfoNotShader(
1108 GLuint client_id
, const char* function_name
) {
1109 Program
* program
= GetProgram(client_id
);
1111 if (GetShader(client_id
)) {
1113 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1115 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1118 LogClientServiceForInfo(program
, client_id
, function_name
);
1123 // Creates a Shader for the given shader.
1124 Shader
* CreateShader(
1127 GLenum shader_type
) {
1128 return shader_manager()->CreateShader(
1129 client_id
, service_id
, shader_type
);
1132 // Gets the shader info for the given shader. Returns NULL if none exists.
1133 Shader
* GetShader(GLuint client_id
) {
1134 return shader_manager()->GetShader(client_id
);
1137 // Gets the shader info for the given shader. If it's not a shader generates a
1138 // GL error. Returns NULL if not shader.
1139 Shader
* GetShaderInfoNotProgram(
1140 GLuint client_id
, const char* function_name
) {
1141 Shader
* shader
= GetShader(client_id
);
1143 if (GetProgram(client_id
)) {
1145 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1148 GL_INVALID_VALUE
, function_name
, "unknown shader");
1151 LogClientServiceForInfo(shader
, client_id
, function_name
);
1155 // Creates a buffer info for the given buffer.
1156 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1157 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1160 // Gets the buffer info for the given buffer.
1161 Buffer
* GetBuffer(GLuint client_id
) {
1162 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1166 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1167 // on glDeleteBuffers so we can make sure the user does not try to render
1168 // with deleted buffers.
1169 void RemoveBuffer(GLuint client_id
);
1171 // Creates a framebuffer info for the given framebuffer.
1172 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1173 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1176 // Gets the framebuffer info for the given framebuffer.
1177 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1178 return framebuffer_manager()->GetFramebuffer(client_id
);
1181 // Removes the framebuffer info for the given framebuffer.
1182 void RemoveFramebuffer(GLuint client_id
) {
1183 framebuffer_manager()->RemoveFramebuffer(client_id
);
1186 // Creates a renderbuffer info for the given renderbuffer.
1187 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1188 return renderbuffer_manager()->CreateRenderbuffer(
1189 client_id
, service_id
);
1192 // Gets the renderbuffer info for the given renderbuffer.
1193 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1194 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1197 // Removes the renderbuffer info for the given renderbuffer.
1198 void RemoveRenderbuffer(GLuint client_id
) {
1199 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1202 // Creates a valuebuffer info for the given valuebuffer.
1203 void CreateValuebuffer(GLuint client_id
) {
1204 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1207 // Gets the valuebuffer info for a given valuebuffer.
1208 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1209 return valuebuffer_manager()->GetValuebuffer(client_id
);
1212 // Removes the valuebuffer info for the given valuebuffer.
1213 void RemoveValuebuffer(GLuint client_id
) {
1214 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1217 // Gets the vertex attrib manager for the given vertex array.
1218 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1219 VertexAttribManager
* info
=
1220 vertex_array_manager()->GetVertexAttribManager(client_id
);
1224 // Removes the vertex attrib manager for the given vertex array.
1225 void RemoveVertexAttribManager(GLuint client_id
) {
1226 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1229 // Creates a vertex attrib manager for the given vertex array.
1230 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1233 bool client_visible
) {
1234 return vertex_array_manager()->CreateVertexAttribManager(
1235 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1238 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1239 void DoBindUniformLocationCHROMIUM(
1240 GLuint client_id
, GLint location
, const char* name
);
1242 error::Error
GetAttribLocationHelper(
1243 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1244 const std::string
& name_str
);
1246 error::Error
GetUniformLocationHelper(
1247 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1248 const std::string
& name_str
);
1250 error::Error
GetFragDataLocationHelper(
1251 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1252 const std::string
& name_str
);
1254 // Wrapper for glShaderSource.
1255 void DoShaderSource(
1256 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1258 // Wrapper for glTransformFeedbackVaryings.
1259 void DoTransformFeedbackVaryings(
1260 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1261 GLenum buffer_mode
);
1263 // Clear any textures used by the current program.
1264 bool ClearUnclearedTextures();
1266 // Clears any uncleared attachments attached to the given frame buffer.
1267 // Returns false if there was a generated GL error.
1268 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1270 // overridden from GLES2Decoder
1271 bool ClearLevel(Texture
* texture
,
1274 unsigned internal_format
,
1279 bool is_texture_immutable
) override
;
1281 // Restore all GL state that affects clearing.
1282 void RestoreClearState();
1284 // Remembers the state of some capabilities.
1285 // Returns: true if glEnable/glDisable should actually be called.
1286 bool SetCapabilityState(GLenum cap
, bool enabled
);
1288 // Check that the currently bound framebuffers are valid.
1289 // Generates GL error if not.
1290 bool CheckBoundFramebuffersValid(const char* func_name
);
1292 // Check that the currently bound read framebuffer has a color image
1293 // attached. Generates GL error if not.
1294 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1296 // Check that the currently bound read framebuffer's color image
1297 // isn't the target texture of the glCopyTex{Sub}Image2D.
1298 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1300 // Check if a framebuffer meets our requirements.
1301 bool CheckFramebufferValid(
1302 Framebuffer
* framebuffer
,
1304 const char* func_name
);
1306 // Check if the current valuebuffer exists and is valid. If not generates
1307 // the appropriate GL error. Returns true if the current valuebuffer is in
1309 bool CheckCurrentValuebuffer(const char* function_name
);
1311 // Check if the current valuebuffer exists and is valiud and that the
1312 // value buffer is actually subscribed to the given subscription
1313 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1314 const char* function_name
);
1316 // Check if the location can be used for the given subscription target. If not
1317 // generates the appropriate GL error. Returns true if the location is usable
1318 bool CheckSubscriptionTarget(GLint location
,
1319 GLenum subscription
,
1320 const char* function_name
);
1322 // Checks if the current program exists and is valid. If not generates the
1323 // appropriate GL error. Returns true if the current program is in a usable
1325 bool CheckCurrentProgram(const char* function_name
);
1327 // Checks if the current program exists and is valid and that location is not
1328 // -1. If the current program is not valid generates the appropriate GL
1329 // error. Returns true if the current program is in a usable state and
1330 // location is not -1.
1331 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1333 // Checks if the current program samples a texture that is also the color
1334 // image of the current bound framebuffer, i.e., the source and destination
1335 // of the draw operation are the same.
1336 bool CheckDrawingFeedbackLoops();
1338 // Checks if |api_type| is valid for the given uniform
1339 // If the api type is not valid generates the appropriate GL
1340 // error. Returns true if |api_type| is valid for the uniform
1341 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1342 const char* function_name
,
1343 Program::UniformApiType api_type
);
1345 // Gets the type of a uniform for a location in the current program. Sets GL
1346 // errors if the current program is not valid. Returns true if the current
1347 // program is valid and the location exists. Adjusts count so it
1348 // does not overflow the uniform.
1349 bool PrepForSetUniformByLocation(GLint fake_location
,
1350 const char* function_name
,
1351 Program::UniformApiType api_type
,
1352 GLint
* real_location
,
1356 // Gets the service id for any simulated backbuffer fbo.
1357 GLuint
GetBackbufferServiceId() const;
1359 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1360 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1362 // Helper for glGetVertexAttrib
1363 void GetVertexAttribHelper(
1364 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1366 // Wrapper for glActiveTexture
1367 void DoActiveTexture(GLenum texture_unit
);
1369 // Wrapper for glAttachShader
1370 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1372 // Wrapper for glBindBuffer since we need to track the current targets.
1373 void DoBindBuffer(GLenum target
, GLuint buffer
);
1375 // Wrapper for glBindFramebuffer since we need to track the current targets.
1376 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1378 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1379 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1381 // Wrapper for glBindTexture since we need to track the current targets.
1382 void DoBindTexture(GLenum target
, GLuint texture
);
1384 // Wrapper for glBindVertexArrayOES
1385 void DoBindVertexArrayOES(GLuint array
);
1386 void EmulateVertexArrayState();
1388 // Wrapper for glBlitFramebufferCHROMIUM.
1389 void DoBlitFramebufferCHROMIUM(
1390 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1391 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1392 GLbitfield mask
, GLenum filter
);
1394 // Wrapper for glBufferSubData.
1395 void DoBufferSubData(
1396 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1398 // Wrapper for glCheckFramebufferStatus
1399 GLenum
DoCheckFramebufferStatus(GLenum target
);
1401 // Wrapper for glClear
1402 error::Error
DoClear(GLbitfield mask
);
1404 // Wrappers for various state.
1405 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1406 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1408 // Wrapper for glCompileShader.
1409 void DoCompileShader(GLuint shader
);
1411 // Wrapper for glDetachShader
1412 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1414 // Wrapper for glDisable
1415 void DoDisable(GLenum cap
);
1417 // Wrapper for glDisableVertexAttribArray.
1418 void DoDisableVertexAttribArray(GLuint index
);
1420 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1422 void DoDiscardFramebufferEXT(GLenum target
,
1423 GLsizei numAttachments
,
1424 const GLenum
* attachments
);
1426 // Wrapper for glEnable
1427 void DoEnable(GLenum cap
);
1429 // Wrapper for glEnableVertexAttribArray.
1430 void DoEnableVertexAttribArray(GLuint index
);
1432 // Wrapper for glFinish.
1435 // Wrapper for glFlush.
1438 // Wrapper for glFramebufferRenderbufffer.
1439 void DoFramebufferRenderbuffer(
1440 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1441 GLuint renderbuffer
);
1443 // Wrapper for glFramebufferTexture2D.
1444 void DoFramebufferTexture2D(
1445 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1448 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1449 void DoFramebufferTexture2DMultisample(
1450 GLenum target
, GLenum attachment
, GLenum textarget
,
1451 GLuint texture
, GLint level
, GLsizei samples
);
1453 // Common implementation for both DoFramebufferTexture2D wrappers.
1454 void DoFramebufferTexture2DCommon(const char* name
,
1455 GLenum target
, GLenum attachment
, GLenum textarget
,
1456 GLuint texture
, GLint level
, GLsizei samples
);
1458 // Wrapper for glFramebufferTextureLayer.
1459 void DoFramebufferTextureLayer(
1460 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1463 // Wrapper for glGenerateMipmap
1464 void DoGenerateMipmap(GLenum target
);
1466 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1467 // to account for different pname values defined in different extension
1469 GLenum
AdjustGetPname(GLenum pname
);
1471 // Wrapper for DoGetBooleanv.
1472 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1474 // Wrapper for DoGetFloatv.
1475 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1477 // Wrapper for glGetFramebufferAttachmentParameteriv.
1478 void DoGetFramebufferAttachmentParameteriv(
1479 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1481 // Wrapper for glGetInteger64v.
1482 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1484 // Wrapper for glGetIntegerv.
1485 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1487 // Gets the max value in a range in a buffer.
1488 GLuint
DoGetMaxValueInBufferCHROMIUM(
1489 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1491 // Wrapper for glGetBufferParameteriv.
1492 void DoGetBufferParameteriv(
1493 GLenum target
, GLenum pname
, GLint
* params
);
1495 // Wrapper for glGetProgramiv.
1496 void DoGetProgramiv(
1497 GLuint program_id
, GLenum pname
, GLint
* params
);
1499 // Wrapper for glRenderbufferParameteriv.
1500 void DoGetRenderbufferParameteriv(
1501 GLenum target
, GLenum pname
, GLint
* params
);
1503 // Wrapper for glGetShaderiv
1504 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1506 // Wrappers for glGetTexParameter.
1507 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1508 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1509 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1511 // Wrappers for glGetVertexAttrib.
1512 template <typename T
>
1513 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1514 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1515 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1516 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1517 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1519 // Wrappers for glIsXXX functions.
1520 bool DoIsEnabled(GLenum cap
);
1521 bool DoIsBuffer(GLuint client_id
);
1522 bool DoIsFramebuffer(GLuint client_id
);
1523 bool DoIsProgram(GLuint client_id
);
1524 bool DoIsRenderbuffer(GLuint client_id
);
1525 bool DoIsShader(GLuint client_id
);
1526 bool DoIsTexture(GLuint client_id
);
1527 bool DoIsVertexArrayOES(GLuint client_id
);
1529 // Wrapper for glLinkProgram
1530 void DoLinkProgram(GLuint program
);
1532 // Wrapper for glRenderbufferStorage.
1533 void DoRenderbufferStorage(
1534 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1536 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1537 void DoRenderbufferStorageMultisampleCHROMIUM(
1538 GLenum target
, GLsizei samples
, GLenum internalformat
,
1539 GLsizei width
, GLsizei height
);
1541 // Handler for glRenderbufferStorageMultisampleEXT
1542 // (multisampled_render_to_texture).
1543 void DoRenderbufferStorageMultisampleEXT(
1544 GLenum target
, GLsizei samples
, GLenum internalformat
,
1545 GLsizei width
, GLsizei height
);
1547 // Common validation for multisample extensions.
1548 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1549 GLenum internalformat
,
1553 // Verifies that the currently bound multisample renderbuffer is valid
1554 // Very slow! Only done on platforms with driver bugs that return invalid
1555 // buffers under memory pressure
1556 bool VerifyMultisampleRenderbufferIntegrity(
1557 GLuint renderbuffer
, GLenum format
);
1559 // Wrapper for glReleaseShaderCompiler.
1560 void DoReleaseShaderCompiler() { }
1562 // Wrappers for glSamplerParameter*v functions.
1563 void DoSamplerParameterfv(
1564 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1565 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1567 // Wrappers for glTexParameter functions.
1568 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1569 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1570 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1571 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1573 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1574 // spec only these 2 functions can be used to set sampler uniforms.
1575 void DoUniform1i(GLint fake_location
, GLint v0
);
1576 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1577 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1578 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1579 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1581 // Wrappers for glUniformfv because some drivers don't correctly accept
1583 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1584 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1585 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1586 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1588 void DoUniformMatrix2fv(
1589 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1590 const GLfloat
* value
);
1591 void DoUniformMatrix3fv(
1592 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1593 const GLfloat
* value
);
1594 void DoUniformMatrix4fv(
1595 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1596 const GLfloat
* value
);
1598 template <typename T
>
1599 bool SetVertexAttribValue(
1600 const char* function_name
, GLuint index
, const T
* value
);
1602 // Wrappers for glVertexAttrib??
1603 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1604 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1605 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1606 void DoVertexAttrib4f(
1607 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1608 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1609 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1610 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1611 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1612 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1613 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1614 void DoVertexAttribI4ui(
1615 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1616 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1618 // Wrapper for glViewport
1619 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1621 // Wrapper for glUseProgram
1622 void DoUseProgram(GLuint program
);
1624 // Wrapper for glValidateProgram.
1625 void DoValidateProgram(GLuint program_client_id
);
1627 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1628 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1629 void DoPopGroupMarkerEXT(void);
1631 // Gets the number of values that will be returned by glGetXXX. Returns
1632 // false if pname is unknown.
1633 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1635 // Checks if the current program and vertex attributes are valid for drawing.
1637 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1640 // Returns true if successful, simulated will be true if attrib0 was
1642 bool SimulateAttrib0(
1643 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1644 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1646 // If an image is bound to texture, this will call Will/DidUseTexImage
1648 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1649 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1651 // Returns false if textures were replaced.
1652 bool PrepareTexturesForRender();
1653 void RestoreStateForTextures();
1655 // Returns true if GL_FIXED attribs were simulated.
1656 bool SimulateFixedAttribs(
1657 const char* function_name
,
1658 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1659 void RestoreStateForSimulatedFixedAttribs();
1661 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1662 // cases (primcount is always 1 for non-instanced).
1663 error::Error
DoDrawArrays(
1664 const char* function_name
,
1665 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1667 error::Error
DoDrawElements(
1668 const char* function_name
,
1669 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1670 int32 offset
, GLsizei primcount
);
1672 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1673 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1674 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1677 return GL_TEXTURE_2D
;
1678 case GL_SAMPLER_CUBE
:
1679 return GL_TEXTURE_CUBE_MAP
;
1680 case GL_SAMPLER_EXTERNAL_OES
:
1681 return GL_TEXTURE_EXTERNAL_OES
;
1682 case GL_SAMPLER_2D_RECT_ARB
:
1683 return GL_TEXTURE_RECTANGLE_ARB
;
1690 // Gets the framebuffer info for a particular target.
1691 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1692 Framebuffer
* framebuffer
= NULL
;
1694 case GL_FRAMEBUFFER
:
1695 case GL_DRAW_FRAMEBUFFER_EXT
:
1696 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1698 case GL_READ_FRAMEBUFFER_EXT
:
1699 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1708 Renderbuffer
* GetRenderbufferInfoForTarget(
1710 Renderbuffer
* renderbuffer
= NULL
;
1712 case GL_RENDERBUFFER
:
1713 renderbuffer
= state_
.bound_renderbuffer
.get();
1719 return renderbuffer
;
1722 // Validates the program and location for a glGetUniform call and returns
1723 // a SizeResult setup to receive the result. Returns true if glGetUniform
1724 // should be called.
1726 bool GetUniformSetup(GLuint program
,
1727 GLint fake_location
,
1730 error::Error
* error
,
1731 GLint
* real_location
,
1733 SizedResult
<T
>** result
,
1734 GLenum
* result_type
,
1735 GLsizei
* result_size
);
1737 bool WasContextLost() const override
;
1738 bool WasContextLostByRobustnessExtension() const override
;
1739 void MarkContextLost(error::ContextLostReason reason
) override
;
1740 bool CheckResetStatus();
1742 #if defined(OS_MACOSX)
1743 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1746 bool ValidateCompressedTexDimensions(
1747 const char* function_name
, GLenum target
, GLint level
,
1748 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1749 bool ValidateCompressedTexFuncData(
1750 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1751 GLenum format
, GLsizei size
);
1752 bool ValidateCompressedTexSubDimensions(
1753 const char* function_name
,
1754 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1755 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1757 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1759 TextureRef
* source_texture_ref
,
1760 TextureRef
* dest_texture_ref
,
1761 GLenum dest_internal_format
);
1763 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1764 void PerformanceWarning(
1765 const char* filename
, int line
, const std::string
& msg
);
1767 const FeatureInfo::FeatureFlags
& features() const {
1768 return feature_info_
->feature_flags();
1771 const FeatureInfo::Workarounds
& workarounds() const {
1772 return feature_info_
->workarounds();
1775 bool ShouldDeferDraws() {
1776 return !offscreen_target_frame_buffer_
.get() &&
1777 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1778 surface_
->DeferDraws();
1781 bool ShouldDeferReads() {
1782 return !offscreen_target_frame_buffer_
.get() &&
1783 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1784 surface_
->DeferDraws();
1787 bool IsRobustnessSupported() {
1788 return has_robustness_extension_
&&
1789 context_
->WasAllocatedUsingRobustnessExtension();
1792 error::Error
WillAccessBoundFramebufferForDraw() {
1793 if (ShouldDeferDraws())
1794 return error::kDeferCommandUntilLater
;
1795 if (!offscreen_target_frame_buffer_
.get() &&
1796 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1797 !surface_
->SetBackbufferAllocation(true))
1798 return error::kLostContext
;
1799 return error::kNoError
;
1802 error::Error
WillAccessBoundFramebufferForRead() {
1803 if (ShouldDeferReads())
1804 return error::kDeferCommandUntilLater
;
1805 if (!offscreen_target_frame_buffer_
.get() &&
1806 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1807 !surface_
->SetBackbufferAllocation(true))
1808 return error::kLostContext
;
1809 return error::kNoError
;
1812 // Set remaining commands to process to 0 to force DoCommands to return
1813 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1814 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1816 void ProcessPendingReadPixels();
1817 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1819 // Generate a member function prototype for each command in an automated and
1821 #define GLES2_CMD_OP(name) \
1822 Error Handle##name(uint32 immediate_data_size, const void* data);
1824 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1828 // The GL context this decoder renders to on behalf of the client.
1829 scoped_refptr
<gfx::GLSurface
> surface_
;
1830 scoped_refptr
<gfx::GLContext
> context_
;
1832 // The ContextGroup for this decoder uses to track resources.
1833 scoped_refptr
<ContextGroup
> group_
;
1835 DebugMarkerManager debug_marker_manager_
;
1838 // All the state for this context.
1839 ContextState state_
;
1841 // Current width and height of the offscreen frame buffer.
1842 gfx::Size offscreen_size_
;
1844 // Util to help with GL.
1847 // unpack flip y as last set by glPixelStorei
1848 bool unpack_flip_y_
;
1850 // unpack (un)premultiply alpha as last set by glPixelStorei
1851 bool unpack_premultiply_alpha_
;
1852 bool unpack_unpremultiply_alpha_
;
1854 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1855 GLuint attrib_0_buffer_id_
;
1857 // The value currently in attrib_0.
1858 Vec4 attrib_0_value_
;
1860 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1861 bool attrib_0_buffer_matches_value_
;
1863 // The size of attrib 0.
1864 GLsizei attrib_0_size_
;
1866 // The buffer used to simulate GL_FIXED attribs.
1867 GLuint fixed_attrib_buffer_id_
;
1869 // The size of fiixed attrib buffer.
1870 GLsizei fixed_attrib_buffer_size_
;
1872 // The offscreen frame buffer that the client renders to. With EGL, the
1873 // depth and stencil buffers are separate. With regular GL there is a single
1874 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1875 // offscreen_target_stencil_render_buffer_ is unused.
1876 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1877 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1878 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1879 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1880 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1881 GLenum offscreen_target_color_format_
;
1882 GLenum offscreen_target_depth_format_
;
1883 GLenum offscreen_target_stencil_format_
;
1884 GLsizei offscreen_target_samples_
;
1885 GLboolean offscreen_target_buffer_preserved_
;
1887 // The copy that is saved when SwapBuffers is called.
1888 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1889 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1890 scoped_refptr
<TextureRef
>
1891 offscreen_saved_color_texture_info_
;
1893 // The copy that is used as the destination for multi-sample resolves.
1894 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1895 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1896 GLenum offscreen_saved_color_format_
;
1898 scoped_ptr
<QueryManager
> query_manager_
;
1900 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1902 scoped_ptr
<ImageManager
> image_manager_
;
1904 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1906 WaitSyncPointCallback wait_sync_point_callback_
;
1908 ShaderCacheCallback shader_cache_callback_
;
1910 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1912 // The format of the back buffer_
1913 GLenum back_buffer_color_format_
;
1914 bool back_buffer_has_depth_
;
1915 bool back_buffer_has_stencil_
;
1919 // Backbuffer attachments that are currently undefined.
1920 uint32 backbuffer_needs_clear_bits_
;
1922 // The current decoder error communicates the decoder error through command
1923 // processing functions that do not return the error value. Should be set only
1924 // if not returning an error.
1925 error::Error current_decoder_error_
;
1927 bool use_shader_translator_
;
1928 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1929 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1931 DisallowedFeatures disallowed_features_
;
1933 // Cached from ContextGroup
1934 const Validators
* validators_
;
1935 scoped_refptr
<FeatureInfo
> feature_info_
;
1939 // Number of commands remaining to be processed in DoCommands().
1940 int commands_to_process_
;
1942 bool has_robustness_extension_
;
1943 error::ContextLostReason context_lost_reason_
;
1944 bool context_was_lost_
;
1945 bool reset_by_robustness_extension_
;
1946 bool supports_post_sub_buffer_
;
1948 // These flags are used to override the state of the shared feature_info_
1949 // member. Because the same FeatureInfo instance may be shared among many
1950 // contexts, the assumptions on the availablity of extensions in WebGL
1951 // contexts may be broken. These flags override the shared state to preserve
1953 bool force_webgl_glsl_validation_
;
1954 bool derivatives_explicitly_enabled_
;
1955 bool frag_depth_explicitly_enabled_
;
1956 bool draw_buffers_explicitly_enabled_
;
1957 bool shader_texture_lod_explicitly_enabled_
;
1959 bool compile_shader_always_succeeds_
;
1961 // An optional behaviour to lose the context and group when OOM.
1962 bool lose_context_when_out_of_memory_
;
1965 bool service_logging_
;
1967 #if defined(OS_MACOSX)
1968 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1969 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1972 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1973 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1975 // Cached values of the currently assigned viewport dimensions.
1976 GLsizei viewport_max_width_
;
1977 GLsizei viewport_max_height_
;
1979 // Command buffer stats.
1980 base::TimeDelta total_processing_commands_time_
;
1982 // States related to each manager.
1983 DecoderTextureState texture_state_
;
1984 DecoderFramebufferState framebuffer_state_
;
1986 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1987 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1988 const unsigned char* cb_command_trace_category_
;
1989 const unsigned char* gpu_decoder_category_
;
1990 int gpu_trace_level_
;
1991 bool gpu_trace_commands_
;
1992 bool gpu_debug_commands_
;
1994 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1996 // Used to validate multisample renderbuffers if needed
1997 GLuint validation_texture_
;
1998 GLuint validation_fbo_multisample_
;
1999 GLuint validation_fbo_
;
2003 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2004 uint32 immediate_data_size
,
2007 // A struct to hold info about each command.
2008 struct CommandInfo
{
2009 CmdHandler cmd_handler
;
2010 uint8 arg_flags
; // How to handle the arguments for this command
2011 uint8 cmd_flags
; // How to handle this command
2012 uint16 arg_count
; // How many arguments are expected for this command.
2015 // A table of CommandInfo for all the commands.
2016 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2018 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2021 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2022 #define GLES2_CMD_OP(name) \
2024 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2025 cmds::name::cmd_flags, \
2026 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2029 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2033 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2034 const char* function_name
, ErrorState
* error_state
)
2035 : function_name_(function_name
),
2036 error_state_(error_state
) {
2037 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2040 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2041 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2044 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2045 TextureUnit
& info
= state
->texture_units
[0];
2047 scoped_refptr
<TextureRef
> texture_ref
;
2050 texture_ref
= info
.bound_texture_2d
;
2052 case GL_TEXTURE_CUBE_MAP
:
2053 texture_ref
= info
.bound_texture_cube_map
;
2055 case GL_TEXTURE_EXTERNAL_OES
:
2056 texture_ref
= info
.bound_texture_external_oes
;
2058 case GL_TEXTURE_RECTANGLE_ARB
:
2059 texture_ref
= info
.bound_texture_rectangle_arb
;
2065 if (texture_ref
.get()) {
2066 last_id
= texture_ref
->service_id();
2071 glBindTexture(target
, last_id
);
2072 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2075 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2080 ScopedGLErrorSuppressor
suppressor(
2081 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2083 // TODO(apatrick): Check if there are any other states that need to be reset
2084 // before binding a new texture.
2085 glActiveTexture(GL_TEXTURE0
);
2086 glBindTexture(target
, id
);
2089 ScopedTextureBinder::~ScopedTextureBinder() {
2090 ScopedGLErrorSuppressor
suppressor(
2091 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2092 RestoreCurrentTextureBindings(state_
, target_
);
2095 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2098 ScopedGLErrorSuppressor
suppressor(
2099 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2100 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2103 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2104 ScopedGLErrorSuppressor
suppressor(
2105 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2106 state_
->RestoreRenderbufferBindings();
2109 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2111 : decoder_(decoder
) {
2112 ScopedGLErrorSuppressor
suppressor(
2113 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2114 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2115 decoder
->OnFboChanged();
2118 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2119 ScopedGLErrorSuppressor
suppressor(
2120 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2121 decoder_
->RestoreCurrentFramebufferBindings();
2124 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2125 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2126 : decoder_(decoder
) {
2127 resolve_and_bind_
= (
2128 decoder_
->offscreen_target_frame_buffer_
.get() &&
2129 decoder_
->IsOffscreenBufferMultisampled() &&
2130 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2131 enforce_internal_framebuffer
));
2132 if (!resolve_and_bind_
)
2135 ScopedGLErrorSuppressor
suppressor(
2136 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2137 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2138 decoder_
->offscreen_target_frame_buffer_
->id());
2141 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2142 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2143 new BackFramebuffer(decoder_
));
2144 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2145 decoder_
->offscreen_resolved_color_texture_
.reset(
2146 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2147 decoder_
->offscreen_resolved_color_texture_
->Create();
2149 DCHECK(decoder_
->offscreen_saved_color_format_
);
2150 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2151 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2153 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2154 decoder_
->offscreen_resolved_color_texture_
.get());
2155 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2156 GL_FRAMEBUFFER_COMPLETE
) {
2157 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2158 << "because offscreen resolved FBO was incomplete.";
2162 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2164 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2166 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2167 const int width
= decoder_
->offscreen_size_
.width();
2168 const int height
= decoder_
->offscreen_size_
.height();
2169 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2170 decoder
->BlitFramebufferHelper(0,
2178 GL_COLOR_BUFFER_BIT
,
2180 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2183 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2184 if (!resolve_and_bind_
)
2187 ScopedGLErrorSuppressor
suppressor(
2188 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2189 decoder_
->RestoreCurrentFramebufferBindings();
2190 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2191 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2195 BackTexture::BackTexture(
2196 MemoryTracker
* memory_tracker
,
2197 ContextState
* state
)
2198 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2200 bytes_allocated_(0),
2204 BackTexture::~BackTexture() {
2205 // This does not destroy the render texture because that would require that
2206 // the associated GL context was current. Just check that it was explicitly
2211 void BackTexture::Create() {
2212 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2213 state_
->GetErrorState());
2215 glGenTextures(1, &id_
);
2216 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2217 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2218 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2219 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2220 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2222 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2223 // never called on an offscreen context, no data will ever be uploaded to the
2224 // saved offscreen color texture (it is deferred until to when SwapBuffers
2225 // is called). My idea is that some nvidia drivers might have a bug where
2226 // deleting a texture that has never been populated might cause a
2229 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2231 bytes_allocated_
= 16u * 16u * 4u;
2232 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2235 bool BackTexture::AllocateStorage(
2236 const gfx::Size
& size
, GLenum format
, bool zero
) {
2238 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2239 state_
->GetErrorState());
2240 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2241 uint32 image_size
= 0;
2242 GLES2Util::ComputeImageDataSizes(
2243 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2246 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2250 scoped_ptr
<char[]> zero_data
;
2252 zero_data
.reset(new char[image_size
]);
2253 memset(zero_data
.get(), 0, image_size
);
2256 glTexImage2D(GL_TEXTURE_2D
,
2268 bool success
= glGetError() == GL_NO_ERROR
;
2270 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2271 bytes_allocated_
= image_size
;
2272 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2277 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2279 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2280 state_
->GetErrorState());
2281 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2282 glCopyTexImage2D(GL_TEXTURE_2D
,
2291 void BackTexture::Destroy() {
2293 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2294 state_
->GetErrorState());
2295 glDeleteTextures(1, &id_
);
2298 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2299 bytes_allocated_
= 0;
2302 void BackTexture::Invalidate() {
2306 BackRenderbuffer::BackRenderbuffer(
2307 RenderbufferManager
* renderbuffer_manager
,
2308 MemoryTracker
* memory_tracker
,
2309 ContextState
* state
)
2310 : renderbuffer_manager_(renderbuffer_manager
),
2311 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2313 bytes_allocated_(0),
2317 BackRenderbuffer::~BackRenderbuffer() {
2318 // This does not destroy the render buffer because that would require that
2319 // the associated GL context was current. Just check that it was explicitly
2324 void BackRenderbuffer::Create() {
2325 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2326 state_
->GetErrorState());
2328 glGenRenderbuffersEXT(1, &id_
);
2331 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2332 const gfx::Size
& size
,
2335 ScopedGLErrorSuppressor
suppressor(
2336 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2337 ScopedRenderBufferBinder
binder(state_
, id_
);
2339 uint32 estimated_size
= 0;
2340 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2341 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2345 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2350 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2355 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2362 bool success
= glGetError() == GL_NO_ERROR
;
2364 // Mark the previously allocated bytes as free.
2365 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2366 bytes_allocated_
= estimated_size
;
2367 // Track the newly allocated bytes.
2368 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2373 void BackRenderbuffer::Destroy() {
2375 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2376 state_
->GetErrorState());
2377 glDeleteRenderbuffersEXT(1, &id_
);
2380 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2381 bytes_allocated_
= 0;
2384 void BackRenderbuffer::Invalidate() {
2388 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2389 : decoder_(decoder
),
2393 BackFramebuffer::~BackFramebuffer() {
2394 // This does not destroy the frame buffer because that would require that
2395 // the associated GL context was current. Just check that it was explicitly
2400 void BackFramebuffer::Create() {
2401 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2402 decoder_
->GetErrorState());
2404 glGenFramebuffersEXT(1, &id_
);
2407 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2409 ScopedGLErrorSuppressor
suppressor(
2410 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2411 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2412 GLuint attach_id
= texture
? texture
->id() : 0;
2413 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2414 GL_COLOR_ATTACHMENT0
,
2420 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2421 BackRenderbuffer
* render_buffer
) {
2423 ScopedGLErrorSuppressor
suppressor(
2424 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2425 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2426 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2427 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2433 void BackFramebuffer::Destroy() {
2435 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2436 decoder_
->GetErrorState());
2437 glDeleteFramebuffersEXT(1, &id_
);
2442 void BackFramebuffer::Invalidate() {
2446 GLenum
BackFramebuffer::CheckStatus() {
2448 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2449 decoder_
->GetErrorState());
2450 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2451 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2454 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2455 return new GLES2DecoderImpl(group
);
2458 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2461 logger_(&debug_marker_manager_
),
2462 state_(group_
->feature_info(), this, &logger_
),
2463 unpack_flip_y_(false),
2464 unpack_premultiply_alpha_(false),
2465 unpack_unpremultiply_alpha_(false),
2466 attrib_0_buffer_id_(0),
2467 attrib_0_buffer_matches_value_(true),
2469 fixed_attrib_buffer_id_(0),
2470 fixed_attrib_buffer_size_(0),
2471 offscreen_target_color_format_(0),
2472 offscreen_target_depth_format_(0),
2473 offscreen_target_stencil_format_(0),
2474 offscreen_target_samples_(0),
2475 offscreen_target_buffer_preserved_(true),
2476 offscreen_saved_color_format_(0),
2477 back_buffer_color_format_(0),
2478 back_buffer_has_depth_(false),
2479 back_buffer_has_stencil_(false),
2480 surfaceless_(false),
2481 backbuffer_needs_clear_bits_(0),
2482 current_decoder_error_(error::kNoError
),
2483 use_shader_translator_(true),
2484 validators_(group_
->feature_info()->validators()),
2485 feature_info_(group_
->feature_info()),
2487 has_robustness_extension_(false),
2488 context_lost_reason_(error::kUnknown
),
2489 context_was_lost_(false),
2490 reset_by_robustness_extension_(false),
2491 supports_post_sub_buffer_(false),
2492 force_webgl_glsl_validation_(false),
2493 derivatives_explicitly_enabled_(false),
2494 frag_depth_explicitly_enabled_(false),
2495 draw_buffers_explicitly_enabled_(false),
2496 shader_texture_lod_explicitly_enabled_(false),
2497 compile_shader_always_succeeds_(false),
2498 lose_context_when_out_of_memory_(false),
2499 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2500 switches::kEnableGPUServiceLoggingGPU
)),
2501 viewport_max_width_(0),
2502 viewport_max_height_(0),
2503 texture_state_(group_
->feature_info()
2505 .texsubimage_faster_than_teximage
),
2506 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2507 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2508 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2509 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2510 gpu_trace_level_(2),
2511 gpu_trace_commands_(false),
2512 gpu_debug_commands_(false),
2513 validation_texture_(0),
2514 validation_fbo_multisample_(0),
2516 allow_exit_(false) {
2519 // The shader translator is used for WebGL even when running on EGL
2520 // because additional restrictions are needed (like only enabling
2521 // GL_OES_standard_derivatives on demand). It is used for the unit
2522 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2523 // the empty string to CompileShader and this is not a valid shader.
2524 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2525 base::CommandLine::ForCurrentProcess()->HasSwitch(
2526 switches::kDisableGLSLTranslator
)) {
2527 use_shader_translator_
= false;
2531 GLES2DecoderImpl::~GLES2DecoderImpl() {
2534 bool GLES2DecoderImpl::Initialize(
2535 const scoped_refptr
<gfx::GLSurface
>& surface
,
2536 const scoped_refptr
<gfx::GLContext
>& context
,
2538 const gfx::Size
& offscreen_size
,
2539 const DisallowedFeatures
& disallowed_features
,
2540 const std::vector
<int32
>& attribs
) {
2541 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2542 DCHECK(context
->IsCurrent(surface
.get()));
2543 DCHECK(!context_
.get());
2544 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2546 ContextCreationAttribHelper attrib_parser
;
2547 if (!attrib_parser
.Parse(attribs
))
2550 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2553 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2555 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2556 switches::kEnableGPUDebugging
)) {
2560 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2561 switches::kEnableGPUCommandLogging
)) {
2562 set_log_commands(true);
2565 compile_shader_always_succeeds_
=
2566 base::CommandLine::ForCurrentProcess()->HasSwitch(
2567 switches::kCompileShaderAlwaysSucceeds
);
2569 // Take ownership of the context and surface. The surface can be replaced with
2574 // Create GPU Tracer for timing values.
2575 gpu_tracer_
.reset(new GPUTracer(this));
2577 // Save the loseContextWhenOutOfMemory context creation attribute.
2578 lose_context_when_out_of_memory_
=
2579 attrib_parser
.lose_context_when_out_of_memory
;
2581 // If the failIfMajorPerformanceCaveat context creation attribute was true
2582 // and we are using a software renderer, fail.
2583 if (attrib_parser
.fail_if_major_perf_caveat
&&
2584 feature_info_
->feature_flags().is_swiftshader
) {
2585 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2590 if (!group_
->Initialize(this, disallowed_features
)) {
2591 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2592 << "failed to initialize.";
2593 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2599 if (attrib_parser
.es3_context_required
&&
2600 feature_info_
->IsES3Capable()) {
2601 feature_info_
->EnableES3Validators();
2602 set_unsafe_es3_apis_enabled(true);
2605 disallowed_features_
= disallowed_features
;
2607 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2608 vertex_array_manager_
.reset(new VertexArrayManager());
2610 GLuint default_vertex_attrib_service_id
= 0;
2611 if (features().native_vertex_array_object
) {
2612 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2613 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2616 state_
.default_vertex_attrib_manager
=
2617 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2619 state_
.default_vertex_attrib_manager
->Initialize(
2620 group_
->max_vertex_attribs(),
2621 feature_info_
->workarounds().init_vertex_attributes
);
2623 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2624 DoBindVertexArrayOES(0);
2626 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2628 image_manager_
.reset(new ImageManager
);
2630 util_
.set_num_compressed_texture_formats(
2631 validators_
->compressed_texture_format
.GetValues().size());
2633 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2634 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2635 // OpenGL ES 2.0 does not have this issue.
2636 glEnableVertexAttribArray(0);
2638 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2639 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2640 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2641 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2642 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2644 state_
.texture_units
.resize(group_
->max_texture_units());
2645 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2646 glActiveTexture(GL_TEXTURE0
+ tt
);
2647 // We want the last bind to be 2D.
2649 if (features().oes_egl_image_external
) {
2650 ref
= texture_manager()->GetDefaultTextureInfo(
2651 GL_TEXTURE_EXTERNAL_OES
);
2652 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2653 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2655 if (features().arb_texture_rectangle
) {
2656 ref
= texture_manager()->GetDefaultTextureInfo(
2657 GL_TEXTURE_RECTANGLE_ARB
);
2658 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2659 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2661 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2662 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2663 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2664 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2665 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2666 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2668 glActiveTexture(GL_TEXTURE0
);
2671 // cache ALPHA_BITS result for re-use with clear behaviour
2672 GLint alpha_bits
= 0;
2675 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2676 features().chromium_framebuffer_multisample
) {
2677 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2678 // max_sample_count must be initialized to a sane value. If
2679 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2680 GLint max_sample_count
= 1;
2681 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2682 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2685 offscreen_target_samples_
= 1;
2687 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2689 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2690 const bool rgb8_supported
=
2691 context_
->HasExtension("GL_OES_rgb8_rgba8");
2692 // The only available default render buffer formats in GLES2 have very
2693 // little precision. Don't enable multisampling unless 8-bit render
2694 // buffer formats are available--instead fall back to 8-bit textures.
2695 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2696 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2699 offscreen_target_samples_
= 1;
2700 offscreen_target_color_format_
=
2701 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2706 // ANGLE only supports packed depth/stencil formats, so use it if it is
2708 const bool depth24_stencil8_supported
=
2709 feature_info_
->feature_flags().packed_depth24_stencil8
;
2710 VLOG(1) << "GL_OES_packed_depth_stencil "
2711 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2712 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2713 depth24_stencil8_supported
) {
2714 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2715 offscreen_target_stencil_format_
= 0;
2717 // It may be the case that this depth/stencil combination is not
2718 // supported, but this will be checked later by CheckFramebufferStatus.
2719 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2720 GL_DEPTH_COMPONENT16
: 0;
2721 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2722 GL_STENCIL_INDEX8
: 0;
2725 offscreen_target_color_format_
=
2726 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2730 // If depth is requested at all, use the packed depth stencil format if
2731 // it's available, as some desktop GL drivers don't support any non-packed
2732 // formats for depth attachments.
2733 const bool depth24_stencil8_supported
=
2734 feature_info_
->feature_flags().packed_depth24_stencil8
;
2735 VLOG(1) << "GL_EXT_packed_depth_stencil "
2736 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2738 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2739 depth24_stencil8_supported
) {
2740 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2741 offscreen_target_stencil_format_
= 0;
2743 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2744 GL_DEPTH_COMPONENT
: 0;
2745 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2746 GL_STENCIL_INDEX
: 0;
2750 offscreen_saved_color_format_
=
2751 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2755 // Create the target frame buffer. This is the one that the client renders
2757 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2758 offscreen_target_frame_buffer_
->Create();
2759 // Due to GLES2 format limitations, either the color texture (for
2760 // non-multisampling) or the color render buffer (for multisampling) will be
2761 // attached to the offscreen frame buffer. The render buffer has more
2762 // limited formats available to it, but the texture can't do multisampling.
2763 if (IsOffscreenBufferMultisampled()) {
2764 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2765 renderbuffer_manager(), memory_tracker(), &state_
));
2766 offscreen_target_color_render_buffer_
->Create();
2768 offscreen_target_color_texture_
.reset(new BackTexture(
2769 memory_tracker(), &state_
));
2770 offscreen_target_color_texture_
->Create();
2772 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2773 renderbuffer_manager(), memory_tracker(), &state_
));
2774 offscreen_target_depth_render_buffer_
->Create();
2775 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2776 renderbuffer_manager(), memory_tracker(), &state_
));
2777 offscreen_target_stencil_render_buffer_
->Create();
2779 // Create the saved offscreen texture. The target frame buffer is copied
2780 // here when SwapBuffers is called.
2781 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2782 offscreen_saved_frame_buffer_
->Create();
2784 offscreen_saved_color_texture_
.reset(new BackTexture(
2785 memory_tracker(), &state_
));
2786 offscreen_saved_color_texture_
->Create();
2788 // Allocate the render buffers at their initial size and check the status
2789 // of the frame buffers is okay.
2790 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2791 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2796 state_
.viewport_width
= offscreen_size
.width();
2797 state_
.viewport_height
= offscreen_size
.height();
2799 // Allocate the offscreen saved color texture.
2800 DCHECK(offscreen_saved_color_format_
);
2801 offscreen_saved_color_texture_
->AllocateStorage(
2802 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2804 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2805 offscreen_saved_color_texture_
.get());
2806 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2807 GL_FRAMEBUFFER_COMPLETE
) {
2808 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2813 // Bind to the new default frame buffer (the offscreen target frame buffer).
2814 // This should now be associated with ID zero.
2815 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2817 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2818 // These are NOT if the back buffer has these proprorties. They are
2819 // if we want the command buffer to enforce them regardless of what
2820 // the real backbuffer is assuming the real back buffer gives us more than
2821 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2822 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2823 // can't do anything about that.
2825 if (!surfaceless_
) {
2826 GLint depth_bits
= 0;
2827 GLint stencil_bits
= 0;
2829 bool default_fb
= (GetBackbufferServiceId() == 0);
2831 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2832 glGetFramebufferAttachmentParameterivEXT(
2834 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2835 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2836 glGetFramebufferAttachmentParameterivEXT(
2838 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2839 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2840 glGetFramebufferAttachmentParameterivEXT(
2842 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2843 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2845 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2846 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2847 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2850 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2851 // the user requested RGB then RGB. If the user did not specify a
2852 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2853 back_buffer_color_format_
=
2854 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2855 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2856 back_buffer_has_stencil_
=
2857 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2860 state_
.viewport_width
= surface
->GetSize().width();
2861 state_
.viewport_height
= surface
->GetSize().height();
2864 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2865 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2866 // isn't well documented; it was discovered in the Khronos OpenGL ES
2867 // mailing list archives. It also implicitly enables the desktop GL
2868 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2869 // variable in fragment shaders.
2870 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2871 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2872 glEnable(GL_POINT_SPRITE
);
2875 has_robustness_extension_
=
2876 context
->HasExtension("GL_ARB_robustness") ||
2877 context
->HasExtension("GL_KHR_robustness") ||
2878 context
->HasExtension("GL_EXT_robustness");
2880 if (!InitializeShaderTranslator()) {
2884 GLint viewport_params
[4] = { 0 };
2885 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2886 viewport_max_width_
= viewport_params
[0];
2887 viewport_max_height_
= viewport_params
[1];
2889 state_
.scissor_width
= state_
.viewport_width
;
2890 state_
.scissor_height
= state_
.viewport_height
;
2892 // Set all the default state because some GL drivers get it wrong.
2893 state_
.InitCapabilities(NULL
);
2894 state_
.InitState(NULL
);
2895 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2897 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2898 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2899 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2900 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2901 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2903 bool call_gl_clear
= !surfaceless_
;
2904 #if defined(OS_ANDROID)
2905 // Temporary workaround for Android WebView because this clear ignores the
2906 // clip and corrupts that external UI of the App. Not calling glClear is ok
2907 // because the system already clears the buffer before each draw. Proper
2908 // fix might be setting the scissor clip properly before initialize. See
2909 // crbug.com/259023 for details.
2910 call_gl_clear
= surface_
->GetHandle();
2912 if (call_gl_clear
) {
2913 // On configs where we report no alpha, if the underlying surface has
2914 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2915 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
2917 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2920 // Clear the backbuffer.
2921 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2923 // Restore alpha clear value if we changed it.
2925 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
2929 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2930 if (feature_info_
->workarounds()
2931 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2932 !surface
->IsOffscreen())
2933 supports_post_sub_buffer_
= false;
2935 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2936 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2939 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2940 context_
->SetUnbindFboOnMakeCurrent();
2943 // Only compositor contexts are known to use only the subset of GL
2944 // that can be safely migrated between the iGPU and the dGPU. Mark
2945 // those contexts as safe to forcibly transition between the GPUs.
2946 // http://crbug.com/180876, http://crbug.com/227228
2948 context_
->SetSafeToForceGpuSwitch();
2950 async_pixel_transfer_manager_
.reset(
2951 AsyncPixelTransferManager::Create(context
.get()));
2952 async_pixel_transfer_manager_
->Initialize(texture_manager());
2954 if (workarounds().gl_clear_broken
) {
2955 DCHECK(!clear_framebuffer_blit_
.get());
2956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2957 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2958 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2962 framebuffer_manager()->AddObserver(this);
2967 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2968 DCHECK(initialized());
2970 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2971 Capabilities::ShaderPrecision
* shader_precision
) {
2972 GLint range
[2] = {0, 0};
2973 GLint precision
= 0;
2974 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2975 shader_precision
->min_range
= range
[0];
2976 shader_precision
->max_range
= range
[1];
2977 shader_precision
->precision
= precision
;
2979 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2980 &caps
.max_combined_texture_image_units
);
2981 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2982 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2983 &caps
.max_fragment_uniform_vectors
);
2984 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2985 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2986 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2987 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2988 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2989 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2990 &caps
.max_vertex_texture_image_units
);
2991 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2992 &caps
.max_vertex_uniform_vectors
);
2993 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2994 &caps
.num_compressed_texture_formats
);
2995 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2996 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2997 &caps
.bind_generates_resource_chromium
);
2998 if (unsafe_es3_apis_enabled()) {
2999 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3000 // but for now we clamp them to 32-bit max.
3001 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3002 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3003 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3004 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3005 &caps
.max_combined_fragment_uniform_components
);
3006 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3007 &caps
.max_combined_uniform_blocks
);
3008 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3009 &caps
.max_combined_vertex_uniform_components
);
3010 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3011 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3012 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3013 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3014 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3015 &caps
.max_fragment_input_components
);
3016 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3017 &caps
.max_fragment_uniform_blocks
);
3018 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3019 &caps
.max_fragment_uniform_components
);
3020 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3021 &caps
.max_program_texel_offset
);
3022 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3023 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3025 if (caps
.max_server_wait_timeout
< 0)
3026 caps
.max_server_wait_timeout
= 0;
3027 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3028 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3029 &caps
.max_transform_feedback_interleaved_components
);
3030 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3031 &caps
.max_transform_feedback_separate_attribs
);
3032 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3033 &caps
.max_transform_feedback_separate_components
);
3034 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3035 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3036 &caps
.max_uniform_buffer_bindings
);
3037 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3038 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3039 &caps
.max_vertex_output_components
);
3040 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3041 &caps
.max_vertex_uniform_blocks
);
3042 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3043 &caps
.max_vertex_uniform_components
);
3044 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3045 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3046 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3047 &caps
.num_program_binary_formats
);
3048 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3049 &caps
.uniform_buffer_offset_alignment
);
3050 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3051 caps
.major_version
= 3;
3052 caps
.minor_version
= 0;
3054 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3055 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3056 unsafe_es3_apis_enabled()) {
3057 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3060 caps
.egl_image_external
=
3061 feature_info_
->feature_flags().oes_egl_image_external
;
3062 caps
.texture_format_atc
=
3063 feature_info_
->feature_flags().ext_texture_format_atc
;
3064 caps
.texture_format_bgra8888
=
3065 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3066 caps
.texture_format_dxt1
=
3067 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3068 caps
.texture_format_dxt5
=
3069 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3070 caps
.texture_format_etc1
=
3071 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3072 caps
.texture_format_etc1_npot
=
3073 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3074 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3075 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3076 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3077 caps
.discard_framebuffer
=
3078 feature_info_
->feature_flags().ext_discard_framebuffer
;
3079 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3081 #if defined(OS_MACOSX)
3082 // This is unconditionally true on mac, no need to test for it at runtime.
3083 caps
.iosurface
= true;
3086 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3089 caps
.blend_equation_advanced
=
3090 feature_info_
->feature_flags().blend_equation_advanced
;
3091 caps
.blend_equation_advanced_coherent
=
3092 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3093 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3097 void GLES2DecoderImpl::UpdateCapabilities() {
3098 util_
.set_num_compressed_texture_formats(
3099 validators_
->compressed_texture_format
.GetValues().size());
3100 util_
.set_num_shader_binary_formats(
3101 validators_
->shader_binary_format
.GetValues().size());
3104 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3105 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3107 if (!use_shader_translator_
) {
3110 ShBuiltInResources resources
;
3111 ShInitBuiltInResources(&resources
);
3112 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3113 resources
.MaxVertexUniformVectors
=
3114 group_
->max_vertex_uniform_vectors();
3115 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3116 resources
.MaxVertexTextureImageUnits
=
3117 group_
->max_vertex_texture_image_units();
3118 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3119 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3120 resources
.MaxFragmentUniformVectors
=
3121 group_
->max_fragment_uniform_vectors();
3122 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3123 resources
.MaxExpressionComplexity
= 256;
3124 resources
.MaxCallStackDepth
= 256;
3126 GLint range
[2] = { 0, 0 };
3127 GLint precision
= 0;
3128 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3130 resources
.FragmentPrecisionHigh
=
3131 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3133 if (force_webgl_glsl_validation_
) {
3134 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3135 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3136 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3137 if (!draw_buffers_explicitly_enabled_
)
3138 resources
.MaxDrawBuffers
= 1;
3139 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3140 resources
.NV_draw_buffers
=
3141 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3143 resources
.OES_standard_derivatives
=
3144 features().oes_standard_derivatives
? 1 : 0;
3145 resources
.ARB_texture_rectangle
=
3146 features().arb_texture_rectangle
? 1 : 0;
3147 resources
.OES_EGL_image_external
=
3148 features().oes_egl_image_external
? 1 : 0;
3149 resources
.EXT_draw_buffers
=
3150 features().ext_draw_buffers
? 1 : 0;
3151 resources
.EXT_frag_depth
=
3152 features().ext_frag_depth
? 1 : 0;
3153 resources
.EXT_shader_texture_lod
=
3154 features().ext_shader_texture_lod
? 1 : 0;
3155 resources
.NV_draw_buffers
=
3156 features().nv_draw_buffers
? 1 : 0;
3159 ShShaderSpec shader_spec
;
3160 if (force_webgl_glsl_validation_
) {
3161 shader_spec
= unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3163 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3166 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3167 features().enable_shader_name_hashing
)
3168 resources
.HashFunction
= &CityHash64
;
3170 resources
.HashFunction
= NULL
;
3171 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3172 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3173 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3174 int driver_bug_workarounds
= 0;
3175 if (workarounds().needs_glsl_built_in_function_emulation
)
3176 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3177 if (workarounds().init_gl_position_in_vertex_shader
)
3178 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3179 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3180 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3181 if (workarounds().init_varyings_without_static_use
)
3182 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3183 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3184 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3185 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3186 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3187 if (workarounds().regenerate_struct_names
)
3188 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3189 if (workarounds().remove_pow_with_constant_exponent
)
3190 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3192 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3193 switches::kEmulateShaderPrecision
))
3194 resources
.WEBGL_debug_shader_precision
= true;
3196 vertex_translator_
= shader_translator_cache()->GetTranslator(
3200 implementation_type
,
3201 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3202 if (!vertex_translator_
.get()) {
3203 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3208 fragment_translator_
= shader_translator_cache()->GetTranslator(
3212 implementation_type
,
3213 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3214 if (!fragment_translator_
.get()) {
3215 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3222 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3223 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3224 if (GetBuffer(client_ids
[ii
])) {
3228 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3229 glGenBuffersARB(n
, service_ids
.get());
3230 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3231 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3236 bool GLES2DecoderImpl::GenFramebuffersHelper(
3237 GLsizei n
, const GLuint
* client_ids
) {
3238 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3239 if (GetFramebuffer(client_ids
[ii
])) {
3243 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3244 glGenFramebuffersEXT(n
, service_ids
.get());
3245 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3246 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3251 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3252 GLsizei n
, const GLuint
* client_ids
) {
3253 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3254 if (GetRenderbuffer(client_ids
[ii
])) {
3258 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3259 glGenRenderbuffersEXT(n
, service_ids
.get());
3260 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3261 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3266 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3267 const GLuint
* client_ids
) {
3268 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3269 if (GetValuebuffer(client_ids
[ii
])) {
3273 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3274 CreateValuebuffer(client_ids
[ii
]);
3279 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3280 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3281 if (GetTexture(client_ids
[ii
])) {
3285 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3286 glGenTextures(n
, service_ids
.get());
3287 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3288 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3293 void GLES2DecoderImpl::DeleteBuffersHelper(
3294 GLsizei n
, const GLuint
* client_ids
) {
3295 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3296 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3297 if (buffer
&& !buffer
->IsDeleted()) {
3298 buffer
->RemoveMappedRange();
3299 state_
.RemoveBoundBuffer(buffer
);
3300 RemoveBuffer(client_ids
[ii
]);
3305 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3306 GLsizei n
, const GLuint
* client_ids
) {
3307 bool supports_separate_framebuffer_binds
=
3308 features().chromium_framebuffer_multisample
;
3310 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3311 Framebuffer
* framebuffer
=
3312 GetFramebuffer(client_ids
[ii
]);
3313 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3314 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3315 GLenum target
= supports_separate_framebuffer_binds
?
3316 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3318 // Unbind attachments on FBO before deletion.
3319 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3320 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3322 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3323 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3324 framebuffer_state_
.clear_state_dirty
= true;
3326 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3327 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3328 GLenum target
= supports_separate_framebuffer_binds
?
3329 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3330 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3333 RemoveFramebuffer(client_ids
[ii
]);
3338 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3339 GLsizei n
, const GLuint
* client_ids
) {
3340 bool supports_separate_framebuffer_binds
=
3341 features().chromium_framebuffer_multisample
;
3342 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3343 Renderbuffer
* renderbuffer
=
3344 GetRenderbuffer(client_ids
[ii
]);
3345 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3346 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3347 state_
.bound_renderbuffer
= NULL
;
3349 // Unbind from current framebuffers.
3350 if (supports_separate_framebuffer_binds
) {
3351 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3352 framebuffer_state_
.bound_read_framebuffer
3353 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3355 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3356 framebuffer_state_
.bound_draw_framebuffer
3357 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3360 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3361 framebuffer_state_
.bound_draw_framebuffer
3362 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3365 framebuffer_state_
.clear_state_dirty
= true;
3366 RemoveRenderbuffer(client_ids
[ii
]);
3371 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3373 const GLuint
* client_ids
) {
3374 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3375 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3377 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3378 state_
.bound_valuebuffer
= NULL
;
3380 RemoveValuebuffer(client_ids
[ii
]);
3385 void GLES2DecoderImpl::DeleteTexturesHelper(
3386 GLsizei n
, const GLuint
* client_ids
) {
3387 bool supports_separate_framebuffer_binds
=
3388 features().chromium_framebuffer_multisample
;
3389 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3390 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3392 Texture
* texture
= texture_ref
->texture();
3393 if (texture
->IsAttachedToFramebuffer()) {
3394 framebuffer_state_
.clear_state_dirty
= true;
3396 // Unbind texture_ref from texture_ref units.
3397 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3398 state_
.texture_units
[jj
].Unbind(texture_ref
);
3400 // Unbind from current framebuffers.
3401 if (supports_separate_framebuffer_binds
) {
3402 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3403 framebuffer_state_
.bound_read_framebuffer
3404 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3406 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3407 framebuffer_state_
.bound_draw_framebuffer
3408 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3411 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3412 framebuffer_state_
.bound_draw_framebuffer
3413 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3416 #if defined(OS_MACOSX)
3417 GLuint service_id
= texture
->service_id();
3418 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3419 ReleaseIOSurfaceForTexture(service_id
);
3422 RemoveTexture(client_ids
[ii
]);
3427 // } // anonymous namespace
3429 bool GLES2DecoderImpl::MakeCurrent() {
3430 if (!context_
.get())
3433 if (WasContextLost()) {
3434 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3438 if (!context_
->MakeCurrent(surface_
.get())) {
3439 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3440 MarkContextLost(error::kMakeCurrentFailed
);
3441 group_
->LoseContexts(error::kUnknown
);
3445 if (CheckResetStatus()) {
3447 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3448 group_
->LoseContexts(error::kUnknown
);
3452 ProcessFinishedAsyncTransfers();
3454 // Rebind the FBO if it was unbound by the context.
3455 if (workarounds().unbind_fbo_on_context_switch
)
3456 RestoreFramebufferBindings();
3458 framebuffer_state_
.clear_state_dirty
= true;
3463 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3464 ProcessPendingReadPixels();
3465 if (engine() && query_manager_
.get())
3466 query_manager_
->ProcessPendingTransferQueries();
3468 // TODO(epenner): Is there a better place to do this?
3469 // This needs to occur before we execute any batch of commands
3470 // from the client, as the client may have recieved an async
3471 // completion while issuing those commands.
3472 // "DidFlushStart" would be ideal if we had such a callback.
3473 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3476 static void RebindCurrentFramebuffer(
3478 Framebuffer
* framebuffer
,
3479 GLuint back_buffer_service_id
) {
3480 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3482 if (framebuffer_id
== 0) {
3483 framebuffer_id
= back_buffer_service_id
;
3486 glBindFramebufferEXT(target
, framebuffer_id
);
3489 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3490 framebuffer_state_
.clear_state_dirty
= true;
3492 if (!features().chromium_framebuffer_multisample
) {
3493 RebindCurrentFramebuffer(
3495 framebuffer_state_
.bound_draw_framebuffer
.get(),
3496 GetBackbufferServiceId());
3498 RebindCurrentFramebuffer(
3499 GL_READ_FRAMEBUFFER_EXT
,
3500 framebuffer_state_
.bound_read_framebuffer
.get(),
3501 GetBackbufferServiceId());
3502 RebindCurrentFramebuffer(
3503 GL_DRAW_FRAMEBUFFER_EXT
,
3504 framebuffer_state_
.bound_draw_framebuffer
.get(),
3505 GetBackbufferServiceId());
3510 bool GLES2DecoderImpl::CheckFramebufferValid(
3511 Framebuffer
* framebuffer
,
3512 GLenum target
, const char* func_name
) {
3516 if (backbuffer_needs_clear_bits_
) {
3517 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3518 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3519 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3521 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3522 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3524 state_
.SetDeviceDepthMask(GL_TRUE
);
3525 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3526 bool reset_draw_buffer
= false;
3527 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3528 group_
->draw_buffer() == GL_NONE
) {
3529 reset_draw_buffer
= true;
3530 GLenum buf
= GL_BACK
;
3531 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3532 buf
= GL_COLOR_ATTACHMENT0
;
3533 glDrawBuffersARB(1, &buf
);
3535 glClear(backbuffer_needs_clear_bits_
);
3536 if (reset_draw_buffer
) {
3537 GLenum buf
= GL_NONE
;
3538 glDrawBuffersARB(1, &buf
);
3540 backbuffer_needs_clear_bits_
= 0;
3541 RestoreClearState();
3546 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3550 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3551 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3553 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3557 // Are all the attachments cleared?
3558 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3559 texture_manager()->HaveUnclearedMips()) {
3560 if (!framebuffer
->IsCleared()) {
3561 // Can we clear them?
3562 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3563 GL_FRAMEBUFFER_COMPLETE
) {
3565 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3566 "framebuffer incomplete (clear)");
3569 ClearUnclearedAttachments(target
, framebuffer
);
3573 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3574 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3575 GL_FRAMEBUFFER_COMPLETE
) {
3577 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3578 "framebuffer incomplete (check)");
3581 framebuffer_manager()->MarkAsComplete(framebuffer
);
3584 // NOTE: At this point we don't know if the framebuffer is complete but
3585 // we DO know that everything that needs to be cleared has been cleared.
3589 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3590 if (!features().chromium_framebuffer_multisample
) {
3591 bool valid
= CheckFramebufferValid(
3592 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3600 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3601 GL_DRAW_FRAMEBUFFER_EXT
,
3603 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3604 GL_READ_FRAMEBUFFER_EXT
,
3608 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3609 const char* func_name
) {
3610 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3611 framebuffer_state_
.bound_read_framebuffer
.get() :
3612 framebuffer_state_
.bound_draw_framebuffer
.get();
3615 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3617 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3623 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3624 TextureRef
* texture
, GLint level
) {
3625 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3626 framebuffer_state_
.bound_read_framebuffer
.get() :
3627 framebuffer_state_
.bound_draw_framebuffer
.get();
3630 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3631 GL_COLOR_ATTACHMENT0
);
3634 return attachment
->FormsFeedbackLoop(texture
, level
);
3637 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3638 Framebuffer
* framebuffer
=
3639 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3640 if (framebuffer
!= NULL
) {
3641 const Framebuffer::Attachment
* attachment
=
3642 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3644 return gfx::Size(attachment
->width(), attachment
->height());
3646 return gfx::Size(0, 0);
3647 } else if (offscreen_target_frame_buffer_
.get()) {
3648 return offscreen_size_
;
3650 return surface_
->GetSize();
3654 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3655 Framebuffer
* framebuffer
=
3656 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3657 if (framebuffer
!= NULL
) {
3658 return framebuffer
->GetColorAttachmentTextureType();
3660 return GL_UNSIGNED_BYTE
;
3664 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3665 Framebuffer
* framebuffer
=
3666 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3667 if (framebuffer
!= NULL
) {
3668 return framebuffer
->GetColorAttachmentFormat();
3669 } else if (offscreen_target_frame_buffer_
.get()) {
3670 return offscreen_target_color_format_
;
3672 return back_buffer_color_format_
;
3676 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3677 Framebuffer
* framebuffer
=
3678 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3679 if (framebuffer
!= NULL
) {
3680 return framebuffer
->GetColorAttachmentFormat();
3681 } else if (offscreen_target_frame_buffer_
.get()) {
3682 return offscreen_target_color_format_
;
3684 return back_buffer_color_format_
;
3688 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3689 if (!offscreen_saved_color_texture_info_
.get())
3691 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3692 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3693 texture_manager()->SetLevelInfo(
3694 offscreen_saved_color_texture_info_
.get(),
3698 offscreen_size_
.width(),
3699 offscreen_size_
.height(),
3705 texture_manager()->SetParameteri(
3706 "UpdateParentTextureInfo",
3708 offscreen_saved_color_texture_info_
.get(),
3709 GL_TEXTURE_MAG_FILTER
,
3711 texture_manager()->SetParameteri(
3712 "UpdateParentTextureInfo",
3714 offscreen_saved_color_texture_info_
.get(),
3715 GL_TEXTURE_MIN_FILTER
,
3717 texture_manager()->SetParameteri(
3718 "UpdateParentTextureInfo",
3720 offscreen_saved_color_texture_info_
.get(),
3723 texture_manager()->SetParameteri(
3724 "UpdateParentTextureInfo",
3726 offscreen_saved_color_texture_info_
.get(),
3729 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3731 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3734 void GLES2DecoderImpl::SetResizeCallback(
3735 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3736 resize_callback_
= callback
;
3739 Logger
* GLES2DecoderImpl::GetLogger() {
3743 void GLES2DecoderImpl::BeginDecoding() {
3744 gpu_tracer_
->BeginDecoding();
3745 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3746 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3747 (*cb_command_trace_category_
!= 0);
3750 void GLES2DecoderImpl::EndDecoding() {
3751 gpu_tracer_
->EndDecoding();
3754 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3755 return state_
.GetErrorState();
3758 void GLES2DecoderImpl::SetShaderCacheCallback(
3759 const ShaderCacheCallback
& callback
) {
3760 shader_cache_callback_
= callback
;
3763 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3764 const WaitSyncPointCallback
& callback
) {
3765 wait_sync_point_callback_
= callback
;
3768 AsyncPixelTransferManager
*
3769 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3770 return async_pixel_transfer_manager_
.get();
3773 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3774 async_pixel_transfer_manager_
.reset();
3777 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3778 AsyncPixelTransferManager
* manager
) {
3779 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3782 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3783 uint32
* service_texture_id
) {
3784 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3786 *service_texture_id
= texture_ref
->service_id();
3792 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3793 return texture_state_
.texture_upload_count
+
3794 async_pixel_transfer_manager_
->GetTextureUploadCount();
3797 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3798 return texture_state_
.total_texture_upload_time
+
3799 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3802 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3803 return total_processing_commands_time_
;
3806 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3807 total_processing_commands_time_
+= time
;
3810 void GLES2DecoderImpl::Destroy(bool have_context
) {
3814 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3816 // Unbind everything.
3817 state_
.vertex_attrib_manager
= NULL
;
3818 state_
.default_vertex_attrib_manager
= NULL
;
3819 state_
.texture_units
.clear();
3820 state_
.bound_array_buffer
= NULL
;
3821 state_
.bound_copy_read_buffer
= NULL
;
3822 state_
.bound_copy_write_buffer
= NULL
;
3823 state_
.bound_pixel_pack_buffer
= NULL
;
3824 state_
.bound_pixel_unpack_buffer
= NULL
;
3825 state_
.bound_transform_feedback_buffer
= NULL
;
3826 state_
.bound_uniform_buffer
= NULL
;
3827 state_
.current_queries
.clear();
3828 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3829 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3830 state_
.bound_renderbuffer
= NULL
;
3831 state_
.bound_valuebuffer
= NULL
;
3833 if (offscreen_saved_color_texture_info_
.get()) {
3834 DCHECK(offscreen_target_color_texture_
);
3835 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3836 offscreen_saved_color_texture_
->id());
3837 offscreen_saved_color_texture_
->Invalidate();
3838 offscreen_saved_color_texture_info_
= NULL
;
3841 if (copy_texture_CHROMIUM_
.get()) {
3842 copy_texture_CHROMIUM_
->Destroy();
3843 copy_texture_CHROMIUM_
.reset();
3846 clear_framebuffer_blit_
.reset();
3848 if (state_
.current_program
.get()) {
3849 program_manager()->UnuseProgram(shader_manager(),
3850 state_
.current_program
.get());
3853 if (attrib_0_buffer_id_
) {
3854 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3856 if (fixed_attrib_buffer_id_
) {
3857 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3860 if (validation_texture_
) {
3861 glDeleteTextures(1, &validation_texture_
);
3862 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3863 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3866 if (offscreen_target_frame_buffer_
.get())
3867 offscreen_target_frame_buffer_
->Destroy();
3868 if (offscreen_target_color_texture_
.get())
3869 offscreen_target_color_texture_
->Destroy();
3870 if (offscreen_target_color_render_buffer_
.get())
3871 offscreen_target_color_render_buffer_
->Destroy();
3872 if (offscreen_target_depth_render_buffer_
.get())
3873 offscreen_target_depth_render_buffer_
->Destroy();
3874 if (offscreen_target_stencil_render_buffer_
.get())
3875 offscreen_target_stencil_render_buffer_
->Destroy();
3876 if (offscreen_saved_frame_buffer_
.get())
3877 offscreen_saved_frame_buffer_
->Destroy();
3878 if (offscreen_saved_color_texture_
.get())
3879 offscreen_saved_color_texture_
->Destroy();
3880 if (offscreen_resolved_frame_buffer_
.get())
3881 offscreen_resolved_frame_buffer_
->Destroy();
3882 if (offscreen_resolved_color_texture_
.get())
3883 offscreen_resolved_color_texture_
->Destroy();
3885 if (offscreen_target_frame_buffer_
.get())
3886 offscreen_target_frame_buffer_
->Invalidate();
3887 if (offscreen_target_color_texture_
.get())
3888 offscreen_target_color_texture_
->Invalidate();
3889 if (offscreen_target_color_render_buffer_
.get())
3890 offscreen_target_color_render_buffer_
->Invalidate();
3891 if (offscreen_target_depth_render_buffer_
.get())
3892 offscreen_target_depth_render_buffer_
->Invalidate();
3893 if (offscreen_target_stencil_render_buffer_
.get())
3894 offscreen_target_stencil_render_buffer_
->Invalidate();
3895 if (offscreen_saved_frame_buffer_
.get())
3896 offscreen_saved_frame_buffer_
->Invalidate();
3897 if (offscreen_saved_color_texture_
.get())
3898 offscreen_saved_color_texture_
->Invalidate();
3899 if (offscreen_resolved_frame_buffer_
.get())
3900 offscreen_resolved_frame_buffer_
->Invalidate();
3901 if (offscreen_resolved_color_texture_
.get())
3902 offscreen_resolved_color_texture_
->Invalidate();
3905 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3906 // Otherwise, we can leak objects. http://crbug.com/258772.
3907 // state_.current_program must be reset before group_ is reset because
3908 // the later deletes the ProgramManager object that referred by
3909 // state_.current_program object.
3910 state_
.current_program
= NULL
;
3912 copy_texture_CHROMIUM_
.reset();
3913 clear_framebuffer_blit_
.reset();
3915 if (query_manager_
.get()) {
3916 query_manager_
->Destroy(have_context
);
3917 query_manager_
.reset();
3920 if (vertex_array_manager_
.get()) {
3921 vertex_array_manager_
->Destroy(have_context
);
3922 vertex_array_manager_
.reset();
3925 if (image_manager_
.get()) {
3926 image_manager_
->Destroy(have_context
);
3927 image_manager_
.reset();
3930 offscreen_target_frame_buffer_
.reset();
3931 offscreen_target_color_texture_
.reset();
3932 offscreen_target_color_render_buffer_
.reset();
3933 offscreen_target_depth_render_buffer_
.reset();
3934 offscreen_target_stencil_render_buffer_
.reset();
3935 offscreen_saved_frame_buffer_
.reset();
3936 offscreen_saved_color_texture_
.reset();
3937 offscreen_resolved_frame_buffer_
.reset();
3938 offscreen_resolved_color_texture_
.reset();
3940 // Need to release these before releasing |group_| which may own the
3941 // ShaderTranslatorCache.
3942 fragment_translator_
= NULL
;
3943 vertex_translator_
= NULL
;
3945 // Should destroy the transfer manager before the texture manager held
3946 // by the context group.
3947 async_pixel_transfer_manager_
.reset();
3949 // Destroy the GPU Tracer which may own some in process GPU Timings.
3951 gpu_tracer_
->Destroy(have_context
);
3952 gpu_tracer_
.reset();
3956 framebuffer_manager()->RemoveObserver(this);
3957 group_
->Destroy(this, have_context
);
3961 if (context_
.get()) {
3962 context_
->ReleaseCurrent(NULL
);
3966 #if defined(OS_MACOSX)
3967 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3968 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3969 CFRelease(it
->second
);
3971 texture_to_io_surface_map_
.clear();
3975 void GLES2DecoderImpl::SetSurface(
3976 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3977 DCHECK(context_
->IsCurrent(NULL
));
3978 DCHECK(surface_
.get());
3980 RestoreCurrentFramebufferBindings();
3983 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3984 if (!offscreen_saved_color_texture_
.get()) {
3985 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3988 if (!offscreen_saved_color_texture_info_
.get()) {
3989 GLuint service_id
= offscreen_saved_color_texture_
->id();
3990 offscreen_saved_color_texture_info_
= TextureRef::Create(
3991 texture_manager(), 0, service_id
);
3992 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3994 UpdateParentTextureInfo();
3996 mailbox_manager()->ProduceTexture(
3997 mailbox
, offscreen_saved_color_texture_info_
->texture());
4000 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4001 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4002 if (!is_offscreen
) {
4003 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4004 << " with an onscreen framebuffer.";
4008 if (offscreen_size_
== size
)
4011 offscreen_size_
= size
;
4012 int w
= offscreen_size_
.width();
4013 int h
= offscreen_size_
.height();
4014 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4015 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4016 << "to allocate storage due to excessive dimensions.";
4020 // Reallocate the offscreen target buffers.
4021 DCHECK(offscreen_target_color_format_
);
4022 if (IsOffscreenBufferMultisampled()) {
4023 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4024 feature_info_
.get(),
4026 offscreen_target_color_format_
,
4027 offscreen_target_samples_
)) {
4028 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4029 << "to allocate storage for offscreen target color buffer.";
4033 if (!offscreen_target_color_texture_
->AllocateStorage(
4034 offscreen_size_
, offscreen_target_color_format_
, false)) {
4035 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4036 << "to allocate storage for offscreen target color texture.";
4040 if (offscreen_target_depth_format_
&&
4041 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4042 feature_info_
.get(),
4044 offscreen_target_depth_format_
,
4045 offscreen_target_samples_
)) {
4046 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4047 << "to allocate storage for offscreen target depth buffer.";
4050 if (offscreen_target_stencil_format_
&&
4051 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4052 feature_info_
.get(),
4054 offscreen_target_stencil_format_
,
4055 offscreen_target_samples_
)) {
4056 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4057 << "to allocate storage for offscreen target stencil buffer.";
4061 // Attach the offscreen target buffers to the target frame buffer.
4062 if (IsOffscreenBufferMultisampled()) {
4063 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4064 GL_COLOR_ATTACHMENT0
,
4065 offscreen_target_color_render_buffer_
.get());
4067 offscreen_target_frame_buffer_
->AttachRenderTexture(
4068 offscreen_target_color_texture_
.get());
4070 if (offscreen_target_depth_format_
) {
4071 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4072 GL_DEPTH_ATTACHMENT
,
4073 offscreen_target_depth_render_buffer_
.get());
4075 const bool packed_depth_stencil
=
4076 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4077 if (packed_depth_stencil
) {
4078 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4079 GL_STENCIL_ATTACHMENT
,
4080 offscreen_target_depth_render_buffer_
.get());
4081 } else if (offscreen_target_stencil_format_
) {
4082 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4083 GL_STENCIL_ATTACHMENT
,
4084 offscreen_target_stencil_render_buffer_
.get());
4087 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4088 GL_FRAMEBUFFER_COMPLETE
) {
4089 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4090 << "because offscreen FBO was incomplete.";
4094 // Clear the target frame buffer.
4096 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4097 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4098 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4099 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4101 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4102 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4104 state_
.SetDeviceDepthMask(GL_TRUE
);
4105 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4106 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4107 RestoreClearState();
4110 // Destroy the offscreen resolved framebuffers.
4111 if (offscreen_resolved_frame_buffer_
.get())
4112 offscreen_resolved_frame_buffer_
->Destroy();
4113 if (offscreen_resolved_color_texture_
.get())
4114 offscreen_resolved_color_texture_
->Destroy();
4115 offscreen_resolved_color_texture_
.reset();
4116 offscreen_resolved_frame_buffer_
.reset();
4121 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4122 const void* cmd_data
) {
4123 const gles2::cmds::ResizeCHROMIUM
& c
=
4124 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4125 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4126 return error::kDeferCommandUntilLater
;
4128 GLuint width
= static_cast<GLuint
>(c
.width
);
4129 GLuint height
= static_cast<GLuint
>(c
.height
);
4130 GLfloat scale_factor
= c
.scale_factor
;
4131 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4133 width
= std::max(1U, width
);
4134 height
= std::max(1U, height
);
4136 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4137 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4138 // Make sure that we are done drawing to the back buffer before resizing.
4141 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4143 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4144 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4145 << "ResizeOffscreenFrameBuffer failed.";
4146 return error::kLostContext
;
4150 if (!resize_callback_
.is_null()) {
4151 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4152 DCHECK(context_
->IsCurrent(surface_
.get()));
4153 if (!context_
->IsCurrent(surface_
.get())) {
4154 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4155 << "current after resize callback.";
4156 return error::kLostContext
;
4160 return error::kNoError
;
4163 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4164 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4165 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4167 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4170 // Decode a command, and call the corresponding GL functions.
4171 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4172 // of commands at once, and is now only used for tests that need to track
4173 // individual commands.
4174 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4175 unsigned int arg_count
,
4176 const void* cmd_data
) {
4177 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4180 // Decode multiple commands, and call the corresponding GL functions.
4181 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4182 // changed by a (malicious) client at any time, so if validation has to happen,
4183 // it should operate on a copy of them.
4184 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4185 // interest of performance in this critical execution loop.
4186 template <bool DebugImpl
>
4187 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4190 int* entries_processed
) {
4191 commands_to_process_
= num_commands
;
4192 error::Error result
= error::kNoError
;
4193 const CommandBufferEntry
* cmd_data
=
4194 static_cast<const CommandBufferEntry
*>(buffer
);
4195 int process_pos
= 0;
4196 unsigned int command
= 0;
4198 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4199 commands_to_process_
--) {
4200 const unsigned int size
= cmd_data
->value_header
.size
;
4201 command
= cmd_data
->value_header
.command
;
4204 result
= error::kInvalidSize
;
4208 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4209 result
= error::kOutOfBounds
;
4214 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4215 GetCommandName(command
));
4217 if (log_commands()) {
4218 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4219 << "cmd: " << GetCommandName(command
);
4223 const unsigned int arg_count
= size
- 1;
4224 unsigned int command_index
= command
- kStartPoint
- 1;
4225 if (command_index
< arraysize(command_info
)) {
4226 const CommandInfo
& info
= command_info
[command_index
];
4227 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4228 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4229 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4230 bool doing_gpu_trace
= false;
4231 if (DebugImpl
&& gpu_trace_commands_
) {
4232 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4233 doing_gpu_trace
= true;
4234 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4235 GetCommandName(command
),
4240 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4241 sizeof(CommandBufferEntry
); // NOLINT
4243 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4245 if (DebugImpl
&& doing_gpu_trace
)
4246 gpu_tracer_
->End(kTraceDecoder
);
4248 if (DebugImpl
&& debug()) {
4250 while ((error
= glGetError()) != GL_NO_ERROR
) {
4251 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4252 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4253 << " : " << GetCommandName(command
);
4254 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4258 result
= error::kInvalidArguments
;
4261 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4265 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4266 GetCommandName(command
));
4269 if (result
== error::kNoError
&&
4270 current_decoder_error_
!= error::kNoError
) {
4271 result
= current_decoder_error_
;
4272 current_decoder_error_
= error::kNoError
;
4275 if (result
!= error::kDeferCommandUntilLater
) {
4276 process_pos
+= size
;
4281 if (entries_processed
)
4282 *entries_processed
= process_pos
;
4284 if (error::IsError(result
)) {
4285 LOG(ERROR
) << "Error: " << result
<< " for Command "
4286 << GetCommandName(command
);
4292 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4295 int* entries_processed
) {
4296 if (gpu_debug_commands_
) {
4297 return DoCommandsImpl
<true>(
4298 num_commands
, buffer
, num_entries
, entries_processed
);
4300 return DoCommandsImpl
<false>(
4301 num_commands
, buffer
, num_entries
, entries_processed
);
4305 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4306 buffer_manager()->RemoveBuffer(client_id
);
4309 void GLES2DecoderImpl::DoFinish() {
4311 ProcessPendingReadPixels();
4312 ProcessPendingQueries(true);
4315 void GLES2DecoderImpl::DoFlush() {
4317 ProcessPendingQueries(false);
4320 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4321 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4322 if (texture_index
>= state_
.texture_units
.size()) {
4323 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4324 "glActiveTexture", texture_unit
, "texture_unit");
4327 state_
.active_texture_unit
= texture_index
;
4328 glActiveTexture(texture_unit
);
4331 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4332 Buffer
* buffer
= NULL
;
4333 GLuint service_id
= 0;
4334 if (client_id
!= 0) {
4335 buffer
= GetBuffer(client_id
);
4337 if (!group_
->bind_generates_resource()) {
4338 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4340 "id not generated by glGenBuffers");
4344 // It's a new id so make a buffer buffer for it.
4345 glGenBuffersARB(1, &service_id
);
4346 CreateBuffer(client_id
, service_id
);
4347 buffer
= GetBuffer(client_id
);
4350 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4352 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4354 GL_INVALID_OPERATION
,
4355 "glBindBuffer", "buffer bound to more than 1 target");
4358 service_id
= buffer
->service_id();
4360 state_
.SetBoundBuffer(target
, buffer
);
4361 glBindBuffer(target
, service_id
);
4364 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4365 bool all_draw_buffers
) {
4366 Framebuffer
* framebuffer
=
4367 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4368 if (!all_draw_buffers
|| !framebuffer
) {
4369 return (GLES2Util::GetChannelsForFormat(
4370 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4372 return framebuffer
->HasAlphaMRT();
4375 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4376 Framebuffer
* framebuffer
=
4377 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4379 return framebuffer
->HasDepthAttachment();
4381 if (offscreen_target_frame_buffer_
.get()) {
4382 return offscreen_target_depth_format_
!= 0;
4384 return back_buffer_has_depth_
;
4387 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4388 Framebuffer
* framebuffer
=
4389 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4391 return framebuffer
->HasStencilAttachment();
4393 if (offscreen_target_frame_buffer_
.get()) {
4394 return offscreen_target_stencil_format_
!= 0 ||
4395 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4397 return back_buffer_has_stencil_
;
4400 void GLES2DecoderImpl::ApplyDirtyState() {
4401 if (framebuffer_state_
.clear_state_dirty
) {
4402 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4403 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4404 state_
.color_mask_green
,
4405 state_
.color_mask_blue
,
4406 state_
.color_mask_alpha
&& have_alpha
);
4408 bool have_depth
= BoundFramebufferHasDepthAttachment();
4409 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4411 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4412 state_
.SetDeviceStencilMaskSeparate(
4413 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4414 state_
.SetDeviceStencilMaskSeparate(
4415 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4417 state_
.SetDeviceCapabilityState(
4418 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4419 state_
.SetDeviceCapabilityState(
4420 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4421 framebuffer_state_
.clear_state_dirty
= false;
4425 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4426 return (offscreen_target_frame_buffer_
.get())
4427 ? offscreen_target_frame_buffer_
->id()
4428 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4431 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4432 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4433 "context", logger_
.GetLogPrefix());
4434 // Restore the Framebuffer first because of bugs in Intel drivers.
4435 // Intel drivers incorrectly clip the viewport settings to
4436 // the size of the current framebuffer object.
4437 RestoreFramebufferBindings();
4438 state_
.RestoreState(prev_state
);
4441 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4443 framebuffer_state_
.bound_draw_framebuffer
.get()
4444 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4445 : GetBackbufferServiceId();
4446 if (!features().chromium_framebuffer_multisample
) {
4447 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4449 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4450 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4451 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4452 : GetBackbufferServiceId();
4453 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4458 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4459 state_
.RestoreRenderbufferBindings();
4462 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4463 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4465 GLenum target
= texture
->target();
4466 glBindTexture(target
, service_id
);
4468 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4470 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4472 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4474 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4475 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4479 void GLES2DecoderImpl::ClearAllAttributes() const {
4480 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4482 if (feature_info_
->feature_flags().native_vertex_array_object
)
4483 glBindVertexArrayOES(0);
4485 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4486 if (i
!= 0) // Never disable attribute 0
4487 glDisableVertexAttribArray(i
);
4488 if (features().angle_instanced_arrays
)
4489 glVertexAttribDivisorANGLE(i
, 0);
4493 void GLES2DecoderImpl::RestoreAllAttributes() const {
4494 state_
.RestoreVertexAttribs();
4497 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4498 state_
.SetIgnoreCachedStateForTest(ignore
);
4501 void GLES2DecoderImpl::SetAllowExit(bool allow_exit
) {
4502 allow_exit_
= allow_exit
;
4505 void GLES2DecoderImpl::OnFboChanged() const {
4506 if (workarounds().restore_scissor_on_fbo_change
)
4507 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4509 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4510 GLint bound_fbo_unsigned
= -1;
4511 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4512 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4513 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4514 surface_
->NotifyWasBound();
4518 // Called after the FBO is checked for completeness.
4519 void GLES2DecoderImpl::OnUseFramebuffer() const {
4520 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4521 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4522 // The driver forgets the correct scissor when modifying the FBO binding.
4523 glScissor(state_
.scissor_x
,
4525 state_
.scissor_width
,
4526 state_
.scissor_height
);
4528 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4529 // it's unclear how this bug works.
4534 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4535 Framebuffer
* framebuffer
= NULL
;
4536 GLuint service_id
= 0;
4537 if (client_id
!= 0) {
4538 framebuffer
= GetFramebuffer(client_id
);
4540 if (!group_
->bind_generates_resource()) {
4541 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4542 "glBindFramebuffer",
4543 "id not generated by glGenFramebuffers");
4547 // It's a new id so make a framebuffer framebuffer for it.
4548 glGenFramebuffersEXT(1, &service_id
);
4549 CreateFramebuffer(client_id
, service_id
);
4550 framebuffer
= GetFramebuffer(client_id
);
4552 service_id
= framebuffer
->service_id();
4554 framebuffer
->MarkAsValid();
4556 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4558 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4559 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4562 // vmiura: This looks like dup code
4563 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4564 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4567 framebuffer_state_
.clear_state_dirty
= true;
4569 // If we are rendering to the backbuffer get the FBO id for any simulated
4571 if (framebuffer
== NULL
) {
4572 service_id
= GetBackbufferServiceId();
4575 glBindFramebufferEXT(target
, service_id
);
4579 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4580 Renderbuffer
* renderbuffer
= NULL
;
4581 GLuint service_id
= 0;
4582 if (client_id
!= 0) {
4583 renderbuffer
= GetRenderbuffer(client_id
);
4584 if (!renderbuffer
) {
4585 if (!group_
->bind_generates_resource()) {
4586 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4587 "glBindRenderbuffer",
4588 "id not generated by glGenRenderbuffers");
4592 // It's a new id so make a renderbuffer for it.
4593 glGenRenderbuffersEXT(1, &service_id
);
4594 CreateRenderbuffer(client_id
, service_id
);
4595 renderbuffer
= GetRenderbuffer(client_id
);
4597 service_id
= renderbuffer
->service_id();
4599 renderbuffer
->MarkAsValid();
4601 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4602 state_
.bound_renderbuffer
= renderbuffer
;
4603 state_
.bound_renderbuffer_valid
= true;
4604 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4607 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4608 TextureRef
* texture_ref
= NULL
;
4609 GLuint service_id
= 0;
4610 if (client_id
!= 0) {
4611 texture_ref
= GetTexture(client_id
);
4613 if (!group_
->bind_generates_resource()) {
4614 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4616 "id not generated by glGenTextures");
4620 // It's a new id so make a texture texture for it.
4621 glGenTextures(1, &service_id
);
4622 DCHECK_NE(0u, service_id
);
4623 CreateTexture(client_id
, service_id
);
4624 texture_ref
= GetTexture(client_id
);
4627 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4630 // Check the texture exists
4632 Texture
* texture
= texture_ref
->texture();
4633 // Check that we are not trying to bind it to a different target.
4634 if (texture
->target() != 0 && texture
->target() != target
) {
4635 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4637 "texture bound to more than 1 target.");
4640 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4641 if (texture
->target() == 0) {
4642 texture_manager()->SetTarget(texture_ref
, target
);
4644 glBindTexture(target
, texture
->service_id());
4646 glBindTexture(target
, 0);
4649 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4650 unit
.bind_target
= target
;
4653 unit
.bound_texture_2d
= texture_ref
;
4655 case GL_TEXTURE_CUBE_MAP
:
4656 unit
.bound_texture_cube_map
= texture_ref
;
4658 case GL_TEXTURE_EXTERNAL_OES
:
4659 unit
.bound_texture_external_oes
= texture_ref
;
4661 case GL_TEXTURE_RECTANGLE_ARB
:
4662 unit
.bound_texture_rectangle_arb
= texture_ref
;
4665 unit
.bound_texture_3d
= texture_ref
;
4667 case GL_TEXTURE_2D_ARRAY
:
4668 unit
.bound_texture_2d_array
= texture_ref
;
4671 NOTREACHED(); // Validation should prevent us getting here.
4676 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4677 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4679 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4680 glDisableVertexAttribArray(index
);
4685 "glDisableVertexAttribArray", "index out of range");
4689 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4690 GLsizei numAttachments
,
4691 const GLenum
* attachments
) {
4692 if (workarounds().disable_discard_framebuffer
)
4695 Framebuffer
* framebuffer
=
4696 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4698 // Validates the attachments. If one of them fails
4699 // the whole command fails.
4700 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4702 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4704 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4705 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4706 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4711 // Marks each one of them as not cleared
4712 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4714 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4719 switch (attachments
[i
]) {
4721 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4724 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4725 case GL_STENCIL_EXT
:
4726 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4735 // If the default framebuffer is bound but we are still rendering to an
4736 // FBO, translate attachment names that refer to default framebuffer
4737 // channels to corresponding framebuffer attachments.
4738 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4739 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4740 GLenum attachment
= attachments
[i
];
4741 if (!framebuffer
&& GetBackbufferServiceId()) {
4742 switch (attachment
) {
4744 attachment
= GL_COLOR_ATTACHMENT0
;
4747 attachment
= GL_DEPTH_ATTACHMENT
;
4749 case GL_STENCIL_EXT
:
4750 attachment
= GL_STENCIL_ATTACHMENT
;
4757 translated_attachments
[i
] = attachment
;
4760 ScopedRenderTo
do_render(framebuffer
);
4761 if (feature_info_
->gl_version_info().is_es3
) {
4762 glInvalidateFramebuffer(
4763 target
, numAttachments
, translated_attachments
.get());
4765 glDiscardFramebufferEXT(
4766 target
, numAttachments
, translated_attachments
.get());
4770 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4771 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4772 glEnableVertexAttribArray(index
);
4775 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4779 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4780 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4783 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4785 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4789 if (target
== GL_TEXTURE_CUBE_MAP
) {
4790 for (int i
= 0; i
< 6; ++i
) {
4791 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4792 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4794 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4799 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4801 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4806 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4807 // Workaround for Mac driver bug. In the large scheme of things setting
4808 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4809 // hit so there's probably no need to make this conditional. The bug appears
4810 // to be that if the filtering mode is set to something that doesn't require
4811 // mipmaps for rendering, or is never set to something other than the default,
4812 // then glGenerateMipmap misbehaves.
4813 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4814 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4816 glGenerateMipmapEXT(target
);
4817 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4818 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4819 texture_ref
->texture()->min_filter());
4821 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4822 if (error
== GL_NO_ERROR
) {
4823 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4827 bool GLES2DecoderImpl::GetHelper(
4828 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4829 DCHECK(num_written
);
4830 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4832 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4834 // Return the GL implementation's preferred format and (see below type)
4835 // if we have the GL extension that exposes this. This allows the GPU
4836 // client to use the implementation's preferred format for glReadPixels
4837 // for optimisation.
4839 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4840 // case when requested on integer/floating point buffers but which is
4841 // acceptable on GLES2 and with the GL_OES_read_format extension.
4843 // Therefore if an error occurs we swallow the error and use the
4844 // internal implementation.
4846 if (context_
->HasExtension("GL_OES_read_format")) {
4847 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4849 glGetIntegerv(pname
, params
);
4850 if (glGetError() == GL_NO_ERROR
)
4853 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4854 GetBoundReadFrameBufferInternalFormat());
4857 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4860 if (context_
->HasExtension("GL_OES_read_format")) {
4861 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4863 glGetIntegerv(pname
, params
);
4864 if (glGetError() == GL_NO_ERROR
)
4867 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4868 GetBoundReadFrameBufferInternalFormat(),
4869 GetBoundReadFrameBufferTextureType());
4872 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4875 *params
= group_
->max_fragment_uniform_vectors();
4878 case GL_MAX_VARYING_VECTORS
:
4881 *params
= group_
->max_varying_vectors();
4884 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4887 *params
= group_
->max_vertex_uniform_vectors();
4892 if (unsafe_es3_apis_enabled()) {
4894 case GL_MAX_VARYING_COMPONENTS
: {
4895 if (feature_info_
->gl_version_info().is_es
) {
4896 // We can just delegate this query to the driver.
4900 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
4901 // OpenGL core profile, so for simplicity, just compute it
4902 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
4904 GLint max_varying_vectors
= 0;
4905 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
4908 *params
= max_varying_vectors
* 4;
4915 case GL_MAX_VIEWPORT_DIMS
:
4916 if (offscreen_target_frame_buffer_
.get()) {
4919 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4920 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4925 case GL_MAX_SAMPLES
:
4928 params
[0] = renderbuffer_manager()->max_samples();
4931 case GL_MAX_RENDERBUFFER_SIZE
:
4934 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4937 case GL_MAX_TEXTURE_SIZE
:
4940 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4943 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4946 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4949 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4952 params
[0] = group_
->max_color_attachments();
4955 case GL_MAX_DRAW_BUFFERS_ARB
:
4958 params
[0] = group_
->max_draw_buffers();
4965 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4966 Framebuffer
* framebuffer
=
4967 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4969 glGetFramebufferAttachmentParameterivEXT(
4970 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
4971 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
4973 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
4976 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4979 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4986 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4987 Framebuffer
* framebuffer
=
4988 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4990 glGetFramebufferAttachmentParameterivEXT(
4991 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
4992 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
4994 v
= (back_buffer_has_depth_
? 24 : 0);
4997 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4999 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5008 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5009 Framebuffer
* framebuffer
=
5010 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5012 GLenum framebuffer_enum
= 0;
5015 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5018 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5021 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5024 glGetFramebufferAttachmentParameterivEXT(
5025 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5030 glGetIntegerv(pname
, &v
);
5035 case GL_STENCIL_BITS
:
5039 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5040 Framebuffer
* framebuffer
=
5041 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5043 glGetFramebufferAttachmentParameterivEXT(
5044 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5045 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5047 v
= (back_buffer_has_stencil_
? 8 : 0);
5050 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5052 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5055 case GL_COMPRESSED_TEXTURE_FORMATS
:
5056 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5058 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5059 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5063 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5066 *params
= validators_
->compressed_texture_format
.GetValues().size();
5069 case GL_NUM_SHADER_BINARY_FORMATS
:
5072 *params
= validators_
->shader_binary_format
.GetValues().size();
5075 case GL_SHADER_BINARY_FORMATS
:
5076 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5078 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5079 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5083 case GL_SHADER_COMPILER
:
5089 case GL_ARRAY_BUFFER_BINDING
:
5092 *params
= GetClientId(
5093 buffer_manager(), state_
.bound_array_buffer
.get());
5096 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5099 *params
= GetClientId(
5101 state_
.vertex_attrib_manager
->element_array_buffer());
5104 case GL_COPY_READ_BUFFER_BINDING
:
5107 *params
= GetClientId(
5108 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5111 case GL_COPY_WRITE_BUFFER_BINDING
:
5114 *params
= GetClientId(
5115 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5118 case GL_PIXEL_PACK_BUFFER_BINDING
:
5121 *params
= GetClientId(
5122 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5125 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5128 *params
= GetClientId(
5129 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5132 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5135 *params
= GetClientId(
5136 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5139 case GL_UNIFORM_BUFFER_BINDING
:
5142 *params
= GetClientId(
5143 buffer_manager(), state_
.bound_uniform_buffer
.get());
5146 case GL_FRAMEBUFFER_BINDING
:
5147 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5150 *params
= GetClientId(
5151 framebuffer_manager(),
5152 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5155 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5158 *params
= GetClientId(
5159 framebuffer_manager(),
5160 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5163 case GL_RENDERBUFFER_BINDING
:
5166 Renderbuffer
* renderbuffer
=
5167 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5169 *params
= renderbuffer
->client_id();
5175 case GL_CURRENT_PROGRAM
:
5178 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5181 case GL_VERTEX_ARRAY_BINDING_OES
:
5184 if (state_
.vertex_attrib_manager
.get() !=
5185 state_
.default_vertex_attrib_manager
.get()) {
5186 GLuint client_id
= 0;
5187 vertex_array_manager_
->GetClientId(
5188 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5189 *params
= client_id
;
5195 case GL_TEXTURE_BINDING_2D
:
5198 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5199 if (unit
.bound_texture_2d
.get()) {
5200 *params
= unit
.bound_texture_2d
->client_id();
5206 case GL_TEXTURE_BINDING_CUBE_MAP
:
5209 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5210 if (unit
.bound_texture_cube_map
.get()) {
5211 *params
= unit
.bound_texture_cube_map
->client_id();
5217 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5220 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5221 if (unit
.bound_texture_external_oes
.get()) {
5222 *params
= unit
.bound_texture_external_oes
->client_id();
5228 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5231 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5232 if (unit
.bound_texture_rectangle_arb
.get()) {
5233 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5239 case GL_UNPACK_FLIP_Y_CHROMIUM
:
5242 params
[0] = unpack_flip_y_
;
5245 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
5248 params
[0] = unpack_premultiply_alpha_
;
5251 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
5254 params
[0] = unpack_unpremultiply_alpha_
;
5257 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5260 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5264 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5265 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5268 Framebuffer
* framebuffer
=
5269 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5271 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5272 } else { // backbuffer
5273 if (pname
== GL_DRAW_BUFFER0_ARB
)
5274 params
[0] = group_
->draw_buffer();
5276 params
[0] = GL_NONE
;
5281 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5286 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5287 GLenum pname
, GLsizei
* num_values
) {
5288 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5291 return GetHelper(pname
, NULL
, num_values
);
5294 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5295 if (GL_MAX_SAMPLES
== pname
&&
5296 features().use_img_for_multisampled_render_to_texture
) {
5297 return GL_MAX_SAMPLES_IMG
;
5302 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5304 GLsizei num_written
= 0;
5305 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5306 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5307 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5308 GetHelper(pname
, values
.get(), &num_written
);
5310 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5311 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5314 pname
= AdjustGetPname(pname
);
5315 glGetBooleanv(pname
, params
);
5319 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5321 GLsizei num_written
= 0;
5322 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5323 if (GetHelper(pname
, NULL
, &num_written
)) {
5324 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5325 GetHelper(pname
, values
.get(), &num_written
);
5326 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5327 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5330 pname
= AdjustGetPname(pname
);
5331 glGetFloatv(pname
, params
);
5336 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5338 if (unsafe_es3_apis_enabled()) {
5340 case GL_MAX_ELEMENT_INDEX
: {
5341 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5342 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5343 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5345 // Assume that desktop GL implementations can generally support
5348 *params
= std::numeric_limits
<unsigned int>::max();
5355 pname
= AdjustGetPname(pname
);
5356 glGetInteger64v(pname
, params
);
5359 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5361 GLsizei num_written
;
5362 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5363 !GetHelper(pname
, params
, &num_written
)) {
5364 pname
= AdjustGetPname(pname
);
5365 glGetIntegerv(pname
, params
);
5369 void GLES2DecoderImpl::DoGetProgramiv(
5370 GLuint program_id
, GLenum pname
, GLint
* params
) {
5371 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5375 program
->GetProgramiv(pname
, params
);
5378 void GLES2DecoderImpl::DoGetBufferParameteriv(
5379 GLenum target
, GLenum pname
, GLint
* params
) {
5380 // Just delegate it. Some validation is actually done before this.
5381 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5382 &state_
, target
, pname
, params
);
5385 void GLES2DecoderImpl::DoBindAttribLocation(
5386 GLuint program_id
, GLuint index
, const char* name
) {
5387 if (!StringIsValidForGLES(name
)) {
5389 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5392 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5394 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5397 if (index
>= group_
->max_vertex_attribs()) {
5399 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5402 Program
* program
= GetProgramInfoNotShader(
5403 program_id
, "glBindAttribLocation");
5407 // At this point, the program's shaders may not be translated yet,
5408 // therefore, we may not find the hashed attribute name.
5409 // glBindAttribLocation call with original name is useless.
5410 // So instead, we should simply cache the binding, and then call
5411 // Program::ExecuteBindAttribLocationCalls() right before link.
5412 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5413 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5414 glBindAttribLocation(program
->service_id(), index
, name
);
5417 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5418 uint32 immediate_data_size
,
5419 const void* cmd_data
) {
5420 const gles2::cmds::BindAttribLocationBucket
& c
=
5421 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5422 GLuint program
= static_cast<GLuint
>(c
.program
);
5423 GLuint index
= static_cast<GLuint
>(c
.index
);
5424 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5425 if (!bucket
|| bucket
->size() == 0) {
5426 return error::kInvalidArguments
;
5428 std::string name_str
;
5429 if (!bucket
->GetAsString(&name_str
)) {
5430 return error::kInvalidArguments
;
5432 DoBindAttribLocation(program
, index
, name_str
.c_str());
5433 return error::kNoError
;
5436 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5437 GLuint program_id
, GLint location
, const char* name
) {
5438 if (!StringIsValidForGLES(name
)) {
5441 "glBindUniformLocationCHROMIUM", "Invalid character");
5444 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5446 GL_INVALID_OPERATION
,
5447 "glBindUniformLocationCHROMIUM", "reserved prefix");
5450 if (location
< 0 || static_cast<uint32
>(location
) >=
5451 (group_
->max_fragment_uniform_vectors() +
5452 group_
->max_vertex_uniform_vectors()) * 4) {
5455 "glBindUniformLocationCHROMIUM", "location out of range");
5458 Program
* program
= GetProgramInfoNotShader(
5459 program_id
, "glBindUniformLocationCHROMIUM");
5463 if (!program
->SetUniformLocationBinding(name
, location
)) {
5466 "glBindUniformLocationCHROMIUM", "location out of range");
5470 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5471 uint32 immediate_data_size
,
5472 const void* cmd_data
) {
5473 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5474 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5476 GLuint program
= static_cast<GLuint
>(c
.program
);
5477 GLint location
= static_cast<GLint
>(c
.location
);
5478 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5479 if (!bucket
|| bucket
->size() == 0) {
5480 return error::kInvalidArguments
;
5482 std::string name_str
;
5483 if (!bucket
->GetAsString(&name_str
)) {
5484 return error::kInvalidArguments
;
5486 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5487 return error::kNoError
;
5490 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5491 const void* cmd_data
) {
5492 const gles2::cmds::DeleteShader
& c
=
5493 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5494 GLuint client_id
= c
.shader
;
5496 Shader
* shader
= GetShader(client_id
);
5498 if (!shader
->IsDeleted()) {
5499 shader_manager()->Delete(shader
);
5502 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5505 return error::kNoError
;
5508 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5509 const void* cmd_data
) {
5510 const gles2::cmds::DeleteProgram
& c
=
5511 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5512 GLuint client_id
= c
.program
;
5514 Program
* program
= GetProgram(client_id
);
5516 if (!program
->IsDeleted()) {
5517 program_manager()->MarkAsDeleted(shader_manager(), program
);
5521 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5524 return error::kNoError
;
5527 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5528 DCHECK(!ShouldDeferDraws());
5529 if (CheckBoundFramebuffersValid("glClear")) {
5531 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5532 if (workarounds().gl_clear_broken
) {
5533 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5535 if (!BoundFramebufferHasDepthAttachment())
5536 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5537 if (!BoundFramebufferHasStencilAttachment())
5538 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5539 clear_framebuffer_blit_
->ClearFramebuffer(
5540 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5541 state_
.color_clear_green
, state_
.color_clear_blue
,
5542 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5543 return error::kNoError
;
5547 return error::kNoError
;
5550 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5551 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5552 GLuint client_renderbuffer_id
) {
5553 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5556 GL_INVALID_OPERATION
,
5557 "glFramebufferRenderbuffer", "no framebuffer bound");
5560 GLuint service_id
= 0;
5561 Renderbuffer
* renderbuffer
= NULL
;
5562 if (client_renderbuffer_id
) {
5563 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5564 if (!renderbuffer
) {
5566 GL_INVALID_OPERATION
,
5567 "glFramebufferRenderbuffer", "unknown renderbuffer");
5570 service_id
= renderbuffer
->service_id();
5572 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5573 glFramebufferRenderbufferEXT(
5574 target
, attachment
, renderbuffertarget
, service_id
);
5575 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5576 if (error
== GL_NO_ERROR
) {
5577 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5579 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5580 framebuffer_state_
.clear_state_dirty
= true;
5585 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5586 if (SetCapabilityState(cap
, false)) {
5591 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5592 if (SetCapabilityState(cap
, true)) {
5597 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5598 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5599 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5600 glDepthRange(znear
, zfar
);
5603 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5604 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5605 state_
.sample_coverage_invert
= (invert
!= 0);
5606 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5609 // Assumes framebuffer is complete.
5610 void GLES2DecoderImpl::ClearUnclearedAttachments(
5611 GLenum target
, Framebuffer
* framebuffer
) {
5612 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5613 // bind this to the DRAW point, clear then bind back to READ
5614 // TODO(gman): I don't think there is any guarantee that an FBO that
5615 // is complete on the READ attachment will be complete as a DRAW
5617 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5618 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5620 GLbitfield clear_bits
= 0;
5621 if (framebuffer
->HasUnclearedColorAttachments()) {
5624 (GLES2Util::GetChannelsForFormat(
5625 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5627 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5628 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5629 if (feature_info_
->feature_flags().ext_draw_buffers
)
5630 framebuffer
->PrepareDrawBuffersForClear();
5633 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5634 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5636 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5637 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5638 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5641 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5642 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5644 state_
.SetDeviceDepthMask(GL_TRUE
);
5645 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5648 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5649 glClear(clear_bits
);
5651 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5652 feature_info_
->feature_flags().ext_draw_buffers
)
5653 framebuffer
->RestoreDrawBuffersAfterClear();
5655 framebuffer_manager()->MarkAttachmentsAsCleared(
5656 framebuffer
, renderbuffer_manager(), texture_manager());
5658 RestoreClearState();
5660 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5661 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5662 Framebuffer
* draw_framebuffer
=
5663 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5664 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5665 GetBackbufferServiceId();
5666 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5670 void GLES2DecoderImpl::RestoreClearState() {
5671 framebuffer_state_
.clear_state_dirty
= true;
5673 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5674 state_
.color_clear_alpha
);
5675 glClearStencil(state_
.stencil_clear
);
5676 glClearDepth(state_
.depth_clear
);
5677 if (state_
.enable_flags
.scissor_test
) {
5678 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5682 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5683 Framebuffer
* framebuffer
=
5684 GetFramebufferInfoForTarget(target
);
5686 return GL_FRAMEBUFFER_COMPLETE
;
5688 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5689 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5690 return completeness
;
5692 return framebuffer
->GetStatus(texture_manager(), target
);
5695 void GLES2DecoderImpl::DoFramebufferTexture2D(
5696 GLenum target
, GLenum attachment
, GLenum textarget
,
5697 GLuint client_texture_id
, GLint level
) {
5698 DoFramebufferTexture2DCommon(
5699 "glFramebufferTexture2D", target
, attachment
,
5700 textarget
, client_texture_id
, level
, 0);
5703 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5704 GLenum target
, GLenum attachment
, GLenum textarget
,
5705 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5706 DoFramebufferTexture2DCommon(
5707 "glFramebufferTexture2DMultisample", target
, attachment
,
5708 textarget
, client_texture_id
, level
, samples
);
5711 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5712 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5713 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5714 if (samples
> renderbuffer_manager()->max_samples()) {
5717 "glFramebufferTexture2DMultisample", "samples too large");
5720 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5723 GL_INVALID_OPERATION
,
5724 name
, "no framebuffer bound.");
5727 GLuint service_id
= 0;
5728 TextureRef
* texture_ref
= NULL
;
5729 if (client_texture_id
) {
5730 texture_ref
= GetTexture(client_texture_id
);
5733 GL_INVALID_OPERATION
,
5734 name
, "unknown texture_ref");
5737 service_id
= texture_ref
->service_id();
5740 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5743 name
, "level out of range");
5748 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5750 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5752 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5754 if (features().use_img_for_multisampled_render_to_texture
) {
5755 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5756 service_id
, level
, samples
);
5758 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5759 service_id
, level
, samples
);
5762 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5763 if (error
== GL_NO_ERROR
) {
5764 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5767 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5768 framebuffer_state_
.clear_state_dirty
= true;
5772 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5777 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5778 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5779 GLint level
, GLint layer
) {
5780 // TODO(zmo): Unsafe ES3 API, missing states update.
5781 GLuint service_id
= 0;
5782 TextureRef
* texture_ref
= NULL
;
5783 if (client_texture_id
) {
5784 texture_ref
= GetTexture(client_texture_id
);
5787 GL_INVALID_OPERATION
,
5788 "glFramebufferTextureLayer", "unknown texture_ref");
5791 service_id
= texture_ref
->service_id();
5793 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5796 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5797 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5798 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5801 GL_INVALID_OPERATION
,
5802 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5805 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5806 const Framebuffer::Attachment
* attachment_object
=
5807 framebuffer
->GetAttachment(attachment
);
5808 *params
= attachment_object
? attachment_object
->object_name() : 0;
5810 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5811 features().use_img_for_multisampled_render_to_texture
) {
5812 pname
= GL_TEXTURE_SAMPLES_IMG
;
5814 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5818 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5819 GLenum target
, GLenum pname
, GLint
* params
) {
5820 Renderbuffer
* renderbuffer
=
5821 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5822 if (!renderbuffer
) {
5824 GL_INVALID_OPERATION
,
5825 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5829 EnsureRenderbufferBound();
5831 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5832 *params
= renderbuffer
->internal_format();
5834 case GL_RENDERBUFFER_WIDTH
:
5835 *params
= renderbuffer
->width();
5837 case GL_RENDERBUFFER_HEIGHT
:
5838 *params
= renderbuffer
->height();
5840 case GL_RENDERBUFFER_SAMPLES_EXT
:
5841 if (features().use_img_for_multisampled_render_to_texture
) {
5842 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5845 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5849 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5854 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5855 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5856 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5857 GLbitfield mask
, GLenum filter
) {
5858 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5860 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5864 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5865 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5866 BlitFramebufferHelper(
5867 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5868 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5869 state_
.enable_flags
.scissor_test
);
5872 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5873 if (!state_
.bound_renderbuffer_valid
) {
5874 state_
.bound_renderbuffer_valid
= true;
5875 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5876 state_
.bound_renderbuffer
.get()
5877 ? state_
.bound_renderbuffer
->service_id()
5882 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5883 const FeatureInfo
* feature_info
,
5886 GLenum internal_format
,
5889 // TODO(sievers): This could be resolved at the GL binding level, but the
5890 // binding process is currently a bit too 'brute force'.
5891 if (feature_info
->gl_version_info().is_angle
) {
5892 glRenderbufferStorageMultisampleANGLE(
5893 target
, samples
, internal_format
, width
, height
);
5894 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5895 glRenderbufferStorageMultisample(
5896 target
, samples
, internal_format
, width
, height
);
5898 glRenderbufferStorageMultisampleEXT(
5899 target
, samples
, internal_format
, width
, height
);
5903 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5913 // TODO(sievers): This could be resolved at the GL binding level, but the
5914 // binding process is currently a bit too 'brute force'.
5915 if (feature_info_
->gl_version_info().is_angle
) {
5916 glBlitFramebufferANGLE(
5917 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5918 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5920 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5922 glBlitFramebufferEXT(
5923 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5927 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5929 GLenum internalformat
,
5932 if (samples
> renderbuffer_manager()->max_samples()) {
5935 "glRenderbufferStorageMultisample", "samples too large");
5939 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5940 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5943 "glRenderbufferStorageMultisample", "dimensions too large");
5947 uint32 estimated_size
= 0;
5948 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5949 width
, height
, samples
, internalformat
, &estimated_size
)) {
5952 "glRenderbufferStorageMultisample", "dimensions too large");
5956 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5959 "glRenderbufferStorageMultisample", "out of memory");
5966 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5967 GLenum target
, GLsizei samples
, GLenum internalformat
,
5968 GLsizei width
, GLsizei height
) {
5969 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5970 if (!renderbuffer
) {
5971 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5972 "glRenderbufferStorageMultisampleCHROMIUM",
5973 "no renderbuffer bound");
5977 if (!ValidateRenderbufferStorageMultisample(
5978 samples
, internalformat
, width
, height
)) {
5982 EnsureRenderbufferBound();
5983 GLenum impl_format
=
5984 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5986 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5987 "glRenderbufferStorageMultisampleCHROMIUM");
5988 RenderbufferStorageMultisampleHelper(
5989 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5991 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5992 if (error
== GL_NO_ERROR
) {
5993 if (workarounds().validate_multisample_buffer_allocation
) {
5994 if (!VerifyMultisampleRenderbufferIntegrity(
5995 renderbuffer
->service_id(), impl_format
)) {
5998 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6003 // TODO(gman): If renderbuffers tracked which framebuffers they were
6004 // attached to we could just mark those framebuffers as not complete.
6005 framebuffer_manager()->IncFramebufferStateChangeCount();
6006 renderbuffer_manager()->SetInfo(
6007 renderbuffer
, samples
, internalformat
, width
, height
);
6011 // This is the handler for multisampled_render_to_texture extensions.
6012 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6013 GLenum target
, GLsizei samples
, GLenum internalformat
,
6014 GLsizei width
, GLsizei height
) {
6015 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6016 if (!renderbuffer
) {
6017 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6018 "glRenderbufferStorageMultisampleEXT",
6019 "no renderbuffer bound");
6023 if (!ValidateRenderbufferStorageMultisample(
6024 samples
, internalformat
, width
, height
)) {
6028 EnsureRenderbufferBound();
6029 GLenum impl_format
=
6030 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6032 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6033 if (features().use_img_for_multisampled_render_to_texture
) {
6034 glRenderbufferStorageMultisampleIMG(
6035 target
, samples
, impl_format
, width
, height
);
6037 glRenderbufferStorageMultisampleEXT(
6038 target
, samples
, impl_format
, width
, height
);
6040 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6041 if (error
== GL_NO_ERROR
) {
6042 // TODO(gman): If renderbuffers tracked which framebuffers they were
6043 // attached to we could just mark those framebuffers as not complete.
6044 framebuffer_manager()->IncFramebufferStateChangeCount();
6045 renderbuffer_manager()->SetInfo(
6046 renderbuffer
, samples
, internalformat
, width
, height
);
6050 // This function validates the allocation of a multisampled renderbuffer
6051 // by clearing it to a key color, blitting the contents to a texture, and
6052 // reading back the color to ensure it matches the key.
6053 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6054 GLuint renderbuffer
, GLenum format
) {
6056 // Only validate color buffers.
6057 // These formats have been selected because they are very common or are known
6058 // to be used by the WebGL backbuffer. If problems are observed with other
6059 // color formats they can be added here.
6070 GLint draw_framebuffer
, read_framebuffer
;
6072 // Cache framebuffer and texture bindings.
6073 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6074 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6076 if (!validation_texture_
) {
6077 GLint bound_texture
;
6078 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6080 // Create additional resources needed for the verification.
6081 glGenTextures(1, &validation_texture_
);
6082 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6083 glGenFramebuffersEXT(1, &validation_fbo_
);
6085 // Texture only needs to be 1x1.
6086 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6087 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6088 // multisample will fail if the color format of the source and destination
6089 // do not match. Here, we assume that the source is GL_RGBA, and make the
6090 // destination GL_RGBA. http://crbug.com/484203
6091 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6092 GL_UNSIGNED_BYTE
, NULL
);
6094 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6095 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6096 GL_TEXTURE_2D
, validation_texture_
, 0);
6098 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6101 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6102 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6103 GL_RENDERBUFFER
, renderbuffer
);
6105 // Cache current state and reset it to the values we require.
6106 GLboolean scissor_enabled
= false;
6107 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6108 if (scissor_enabled
)
6109 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6111 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6112 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6113 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6115 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6116 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6117 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6119 // Clear the buffer to the desired key color.
6120 glClear(GL_COLOR_BUFFER_BIT
);
6122 // Blit from the multisample buffer to a standard texture.
6123 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6124 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6126 BlitFramebufferHelper(
6127 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6129 // Read a pixel from the buffer.
6130 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6132 unsigned char pixel
[3] = {0, 0, 0};
6133 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6135 // Detach the renderbuffer.
6136 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6137 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6138 GL_RENDERBUFFER
, 0);
6140 // Restore cached state.
6141 if (scissor_enabled
)
6142 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6144 state_
.SetDeviceColorMask(
6145 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6146 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6147 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6148 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6150 // Return true if the pixel matched the desired key color.
6151 return (pixel
[0] == 0xFF &&
6156 void GLES2DecoderImpl::DoRenderbufferStorage(
6157 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6158 Renderbuffer
* renderbuffer
=
6159 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6160 if (!renderbuffer
) {
6162 GL_INVALID_OPERATION
,
6163 "glRenderbufferStorage", "no renderbuffer bound");
6167 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6168 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6170 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6174 uint32 estimated_size
= 0;
6175 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6176 width
, height
, 1, internalformat
, &estimated_size
)) {
6178 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6182 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6184 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6188 EnsureRenderbufferBound();
6189 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6190 glRenderbufferStorageEXT(
6192 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6196 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6197 if (error
== GL_NO_ERROR
) {
6198 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6199 // we could just mark those framebuffers as not complete.
6200 framebuffer_manager()->IncFramebufferStateChangeCount();
6201 renderbuffer_manager()->SetInfo(
6202 renderbuffer
, 1, internalformat
, width
, height
);
6206 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6207 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6208 Program
* program
= GetProgramInfoNotShader(
6209 program_id
, "glLinkProgram");
6214 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6215 if (program
->Link(shader_manager(),
6216 workarounds().count_all_in_varyings_packing
?
6217 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6218 shader_cache_callback_
)) {
6219 if (program
== state_
.current_program
.get()) {
6220 if (workarounds().use_current_program_after_successful_link
)
6221 glUseProgram(program
->service_id());
6222 if (workarounds().clear_uniforms_before_first_program_use
)
6223 program_manager()->ClearUniforms(program
);
6227 // LinkProgram can be very slow. Exit command processing to allow for
6228 // context preemption and GPU watchdog checks.
6229 ExitCommandProcessingEarly();
6232 void GLES2DecoderImpl::DoSamplerParameterfv(
6233 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6235 glSamplerParameterf(sampler
, pname
, params
[0]);
6238 void GLES2DecoderImpl::DoSamplerParameteriv(
6239 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6241 glSamplerParameteri(sampler
, pname
, params
[0]);
6244 void GLES2DecoderImpl::DoTexParameterf(
6245 GLenum target
, GLenum pname
, GLfloat param
) {
6246 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6253 texture_manager()->SetParameterf(
6254 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6257 void GLES2DecoderImpl::DoTexParameteri(
6258 GLenum target
, GLenum pname
, GLint param
) {
6259 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6262 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6266 texture_manager()->SetParameteri(
6267 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6270 void GLES2DecoderImpl::DoTexParameterfv(
6271 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6272 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6275 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6279 texture_manager()->SetParameterf(
6280 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6283 void GLES2DecoderImpl::DoTexParameteriv(
6284 GLenum target
, GLenum pname
, const GLint
* params
) {
6285 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6289 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6293 texture_manager()->SetParameteri(
6294 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6297 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6298 if (!state_
.bound_valuebuffer
.get()) {
6299 // There is no valuebuffer bound
6300 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6301 "no valuebuffer in use");
6307 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6308 GLenum subscription
,
6309 const char* function_name
) {
6310 if (!CheckCurrentValuebuffer(function_name
)) {
6313 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6314 // The valuebuffer is not subscribed to the target
6315 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6316 "valuebuffer is not subscribed");
6322 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6323 GLenum subscription
,
6324 const char* function_name
) {
6325 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6328 GLint real_location
= -1;
6329 GLint array_index
= -1;
6330 const Program::UniformInfo
* info
=
6331 state_
.current_program
->GetUniformInfoByFakeLocation(
6332 location
, &real_location
, &array_index
);
6334 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6337 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6338 info
->accepts_api_type
) == 0) {
6339 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6340 "wrong type for subscription");
6346 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6347 if (!state_
.current_program
.get()) {
6348 // The program does not exist.
6350 GL_INVALID_OPERATION
, function_name
, "no program in use");
6353 if (!state_
.current_program
->InUse()) {
6355 GL_INVALID_OPERATION
, function_name
, "program not linked");
6361 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6362 GLint location
, const char* function_name
) {
6363 if (!CheckCurrentProgram(function_name
)) {
6366 return location
!= -1;
6369 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6370 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6373 const Framebuffer::Attachment
* attachment
=
6374 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6378 DCHECK(state_
.current_program
.get());
6379 const Program::SamplerIndices
& sampler_indices
=
6380 state_
.current_program
->sampler_indices();
6381 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6382 const Program::UniformInfo
* uniform_info
=
6383 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6384 DCHECK(uniform_info
);
6385 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6387 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6388 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6389 if (texture_unit_index
>= state_
.texture_units
.size())
6391 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6392 TextureRef
* texture_ref
=
6393 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6394 if (attachment
->IsTexture(texture_ref
))
6401 bool GLES2DecoderImpl::CheckUniformForApiType(
6402 const Program::UniformInfo
* info
,
6403 const char* function_name
,
6404 Program::UniformApiType api_type
) {
6406 if ((api_type
& info
->accepts_api_type
) == 0) {
6407 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6408 "wrong uniform function for type");
6414 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6415 GLint fake_location
,
6416 const char* function_name
,
6417 Program::UniformApiType api_type
,
6418 GLint
* real_location
,
6423 DCHECK(real_location
);
6425 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6428 GLint array_index
= -1;
6429 const Program::UniformInfo
* info
=
6430 state_
.current_program
->GetUniformInfoByFakeLocation(
6431 fake_location
, real_location
, &array_index
);
6434 GL_INVALID_OPERATION
, function_name
, "unknown location");
6437 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6440 if (*count
> 1 && !info
->is_array
) {
6442 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6445 *count
= std::min(info
->size
- array_index
, *count
);
6453 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6456 GLint real_location
= -1;
6457 if (!PrepForSetUniformByLocation(fake_location
,
6459 Program::kUniform1i
,
6465 if (!state_
.current_program
->SetSamplers(
6466 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6468 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6471 glUniform1i(real_location
, v0
);
6474 void GLES2DecoderImpl::DoUniform1iv(
6475 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6477 GLint real_location
= -1;
6478 if (!PrepForSetUniformByLocation(fake_location
,
6480 Program::kUniform1i
,
6486 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6487 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6488 if (!state_
.current_program
->SetSamplers(
6489 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6491 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6495 glUniform1iv(real_location
, count
, value
);
6498 void GLES2DecoderImpl::DoUniform1fv(
6499 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6501 GLint real_location
= -1;
6502 if (!PrepForSetUniformByLocation(fake_location
,
6504 Program::kUniform1f
,
6510 if (type
== GL_BOOL
) {
6511 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6512 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6513 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6515 DoUniform1iv(real_location
, count
, temp
.get());
6517 glUniform1fv(real_location
, count
, value
);
6521 void GLES2DecoderImpl::DoUniform2fv(
6522 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6524 GLint real_location
= -1;
6525 if (!PrepForSetUniformByLocation(fake_location
,
6527 Program::kUniform2f
,
6533 if (type
== GL_BOOL_VEC2
) {
6534 GLsizei num_values
= count
* 2;
6535 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6536 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6537 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6539 glUniform2iv(real_location
, count
, temp
.get());
6541 glUniform2fv(real_location
, count
, value
);
6545 void GLES2DecoderImpl::DoUniform3fv(
6546 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6548 GLint real_location
= -1;
6549 if (!PrepForSetUniformByLocation(fake_location
,
6551 Program::kUniform3f
,
6557 if (type
== GL_BOOL_VEC3
) {
6558 GLsizei num_values
= count
* 3;
6559 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6560 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6561 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6563 glUniform3iv(real_location
, count
, temp
.get());
6565 glUniform3fv(real_location
, count
, value
);
6569 void GLES2DecoderImpl::DoUniform4fv(
6570 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6572 GLint real_location
= -1;
6573 if (!PrepForSetUniformByLocation(fake_location
,
6575 Program::kUniform4f
,
6581 if (type
== GL_BOOL_VEC4
) {
6582 GLsizei num_values
= count
* 4;
6583 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6584 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6585 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6587 glUniform4iv(real_location
, count
, temp
.get());
6589 glUniform4fv(real_location
, count
, value
);
6593 void GLES2DecoderImpl::DoUniform2iv(
6594 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6596 GLint real_location
= -1;
6597 if (!PrepForSetUniformByLocation(fake_location
,
6599 Program::kUniform2i
,
6605 glUniform2iv(real_location
, count
, value
);
6608 void GLES2DecoderImpl::DoUniform3iv(
6609 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6611 GLint real_location
= -1;
6612 if (!PrepForSetUniformByLocation(fake_location
,
6614 Program::kUniform3i
,
6620 glUniform3iv(real_location
, count
, value
);
6623 void GLES2DecoderImpl::DoUniform4iv(
6624 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6626 GLint real_location
= -1;
6627 if (!PrepForSetUniformByLocation(fake_location
,
6629 Program::kUniform4i
,
6635 glUniform4iv(real_location
, count
, value
);
6638 void GLES2DecoderImpl::DoUniformMatrix2fv(
6639 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6640 const GLfloat
* value
) {
6642 GLint real_location
= -1;
6643 if (!PrepForSetUniformByLocation(fake_location
,
6644 "glUniformMatrix2fv",
6645 Program::kUniformMatrix2f
,
6651 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6654 void GLES2DecoderImpl::DoUniformMatrix3fv(
6655 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6656 const GLfloat
* value
) {
6658 GLint real_location
= -1;
6659 if (!PrepForSetUniformByLocation(fake_location
,
6660 "glUniformMatrix3fv",
6661 Program::kUniformMatrix3f
,
6667 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6670 void GLES2DecoderImpl::DoUniformMatrix4fv(
6671 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6672 const GLfloat
* value
) {
6674 GLint real_location
= -1;
6675 if (!PrepForSetUniformByLocation(fake_location
,
6676 "glUniformMatrix4fv",
6677 Program::kUniformMatrix4f
,
6683 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6686 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6687 GLuint service_id
= 0;
6688 Program
* program
= NULL
;
6690 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6694 if (!program
->IsValid()) {
6695 // Program was not linked successfully. (ie, glLinkProgram)
6697 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6700 service_id
= program
->service_id();
6702 if (state_
.current_program
.get()) {
6703 program_manager()->UnuseProgram(shader_manager(),
6704 state_
.current_program
.get());
6706 state_
.current_program
= program
;
6707 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6708 glUseProgram(service_id
);
6709 if (state_
.current_program
.get()) {
6710 program_manager()->UseProgram(state_
.current_program
.get());
6711 if (workarounds().clear_uniforms_before_first_program_use
)
6712 program_manager()->ClearUniforms(program
);
6716 void GLES2DecoderImpl::RenderWarning(
6717 const char* filename
, int line
, const std::string
& msg
) {
6718 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6721 void GLES2DecoderImpl::PerformanceWarning(
6722 const char* filename
, int line
, const std::string
& msg
) {
6723 logger_
.LogMessage(filename
, line
,
6724 std::string("PERFORMANCE WARNING: ") + msg
);
6727 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6728 Texture
* texture
, GLenum textarget
) {
6729 // Image is already in use if texture is attached to a framebuffer.
6730 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6731 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6733 ScopedGLErrorSuppressor
suppressor(
6734 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6736 glBindTexture(textarget
, texture
->service_id());
6737 image
->WillUseTexImage();
6738 RestoreCurrentTextureBindings(&state_
, textarget
);
6743 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6744 Texture
* texture
, GLenum textarget
) {
6745 // Image is still in use if texture is attached to a framebuffer.
6746 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6747 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6749 ScopedGLErrorSuppressor
suppressor(
6750 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6752 glBindTexture(textarget
, texture
->service_id());
6753 image
->DidUseTexImage();
6754 RestoreCurrentTextureBindings(&state_
, textarget
);
6759 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6760 DCHECK(state_
.current_program
.get());
6761 if (!texture_manager()->HaveUnrenderableTextures() &&
6762 !texture_manager()->HaveImages()) {
6766 bool textures_set
= false;
6767 const Program::SamplerIndices
& sampler_indices
=
6768 state_
.current_program
->sampler_indices();
6769 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6770 const Program::UniformInfo
* uniform_info
=
6771 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6772 DCHECK(uniform_info
);
6773 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6774 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6775 if (texture_unit_index
< state_
.texture_units
.size()) {
6776 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6777 TextureRef
* texture_ref
=
6778 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6779 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6780 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6781 textures_set
= true;
6782 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6785 texture_manager()->black_texture_id(uniform_info
->type
));
6787 LOCAL_RENDER_WARNING(
6788 std::string("there is no texture bound to the unit ") +
6789 base::IntToString(texture_unit_index
));
6791 LOCAL_RENDER_WARNING(
6792 std::string("texture bound to texture unit ") +
6793 base::IntToString(texture_unit_index
) +
6794 " is not renderable. It maybe non-power-of-2 and have"
6795 " incompatible texture filtering.");
6800 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6801 Texture
* texture
= texture_ref
->texture();
6802 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6803 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6804 ScopedGLErrorSuppressor
suppressor(
6805 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6806 textures_set
= true;
6807 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6808 image
->WillUseTexImage();
6813 // else: should this be an error?
6816 return !textures_set
;
6819 void GLES2DecoderImpl::RestoreStateForTextures() {
6820 DCHECK(state_
.current_program
.get());
6821 const Program::SamplerIndices
& sampler_indices
=
6822 state_
.current_program
->sampler_indices();
6823 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6824 const Program::UniformInfo
* uniform_info
=
6825 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6826 DCHECK(uniform_info
);
6827 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6828 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6829 if (texture_unit_index
< state_
.texture_units
.size()) {
6830 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6831 TextureRef
* texture_ref
=
6832 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6833 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6834 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6835 // Get the texture_ref info that was previously bound here.
6836 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6837 ? texture_unit
.bound_texture_2d
.get()
6838 : texture_unit
.bound_texture_cube_map
.get();
6839 glBindTexture(texture_unit
.bind_target
,
6840 texture_ref
? texture_ref
->service_id() : 0);
6844 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6845 Texture
* texture
= texture_ref
->texture();
6846 gfx::GLImage
* image
=
6847 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6848 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6849 ScopedGLErrorSuppressor
suppressor(
6850 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6851 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6852 image
->DidUseTexImage();
6859 // Set the active texture back to whatever the user had it as.
6860 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6863 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6864 // Only check if there are some uncleared textures.
6865 if (!texture_manager()->HaveUnsafeTextures()) {
6869 // 1: Check all textures we are about to render with.
6870 if (state_
.current_program
.get()) {
6871 const Program::SamplerIndices
& sampler_indices
=
6872 state_
.current_program
->sampler_indices();
6873 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6874 const Program::UniformInfo
* uniform_info
=
6875 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6876 DCHECK(uniform_info
);
6877 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6878 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6879 if (texture_unit_index
< state_
.texture_units
.size()) {
6880 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6881 TextureRef
* texture_ref
=
6882 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6883 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6884 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6895 bool GLES2DecoderImpl::IsDrawValid(
6896 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6897 GLsizei primcount
) {
6898 DCHECK(instanced
|| primcount
== 1);
6900 // NOTE: We specifically do not check current_program->IsValid() because
6901 // it could never be invalid since glUseProgram would have failed. While
6902 // glLinkProgram could later mark the program as invalid the previous
6903 // valid program will still function if it is still the current program.
6904 if (!state_
.current_program
.get()) {
6905 // The program does not exist.
6906 // But GL says no ERROR.
6907 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6911 if (CheckDrawingFeedbackLoops()) {
6913 GL_INVALID_OPERATION
, function_name
,
6914 "Source and destination textures of the draw are the same.");
6918 return state_
.vertex_attrib_manager
6919 ->ValidateBindings(function_name
,
6921 feature_info_
.get(),
6922 state_
.current_program
.get(),
6923 max_vertex_accessed
,
6928 bool GLES2DecoderImpl::SimulateAttrib0(
6929 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6933 if (feature_info_
->gl_version_info().BehavesLikeGLES())
6936 const VertexAttrib
* attrib
=
6937 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6938 // If it's enabled or it's not used then we don't need to do anything.
6939 bool attrib_0_used
=
6940 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6941 if (attrib
->enabled() && attrib_0_used
) {
6945 // Make a buffer with a single repeated vec4 value enough to
6946 // simulate the constant value that is supposed to be here.
6947 // This is required to emulate GLES2 on GL.
6948 GLuint num_vertices
= max_vertex_accessed
+ 1;
6949 uint32 size_needed
= 0;
6951 if (num_vertices
== 0 ||
6952 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
6953 size_needed
> 0x7FFFFFFFU
) {
6954 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6958 LOCAL_PERFORMANCE_WARNING(
6959 "Attribute 0 is disabled. This has signficant performance penalty");
6961 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6962 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6964 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6966 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6967 GLenum error
= glGetError();
6968 if (error
!= GL_NO_ERROR
) {
6970 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6975 const Vec4
& value
= state_
.attrib_values
[0];
6978 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
6979 // TODO(zmo): This is not 100% correct because we might lose data when
6980 // casting to float type, but it is a corner case and once we migrate to
6981 // core profiles on desktop GL, it is no longer relevant.
6982 Vec4f
fvalue(value
);
6983 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
6984 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6985 attrib_0_buffer_matches_value_
= true;
6986 attrib_0_value_
= value
;
6987 attrib_0_size_
= size_needed
;
6990 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6992 if (attrib
->divisor())
6993 glVertexAttribDivisorANGLE(0, 0);
6999 void GLES2DecoderImpl::RestoreStateForAttrib(
7000 GLuint attrib_index
, bool restore_array_binding
) {
7001 const VertexAttrib
* attrib
=
7002 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7003 if (restore_array_binding
) {
7004 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7005 Buffer
* buffer
= attrib
->buffer();
7006 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7007 glVertexAttribPointer(
7008 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7009 attrib
->gl_stride(), ptr
);
7011 if (attrib
->divisor())
7012 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7014 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7015 state_
.bound_array_buffer
->service_id() : 0);
7017 // Never touch vertex attribute 0's state (in particular, never
7018 // disable it) when running on desktop GL because it will never be
7020 if (attrib_index
!= 0 ||
7021 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7022 if (attrib
->enabled()) {
7023 glEnableVertexAttribArray(attrib_index
);
7025 glDisableVertexAttribArray(attrib_index
);
7030 bool GLES2DecoderImpl::SimulateFixedAttribs(
7031 const char* function_name
,
7032 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7035 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7038 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7042 LOCAL_PERFORMANCE_WARNING(
7043 "GL_FIXED attributes have a signficant performance penalty");
7045 // NOTE: we could be smart and try to check if a buffer is used
7046 // twice in 2 different attribs, find the overlapping parts and therefore
7047 // duplicate the minimum amount of data but this whole code path is not meant
7048 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7049 // tests so we just add to the buffer attrib used.
7051 GLuint elements_needed
= 0;
7052 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7053 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7054 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7055 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7056 const VertexAttrib
* attrib
= *it
;
7057 const Program::VertexAttrib
* attrib_info
=
7058 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7059 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7060 max_vertex_accessed
);
7061 GLuint num_vertices
= max_accessed
+ 1;
7062 if (num_vertices
== 0) {
7064 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7068 attrib
->CanAccess(max_accessed
) &&
7069 attrib
->type() == GL_FIXED
) {
7070 uint32 elements_used
= 0;
7071 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7072 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7074 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7080 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7081 uint32 size_needed
= 0;
7082 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7083 size_needed
> 0x7FFFFFFFU
) {
7085 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7089 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7091 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7092 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7093 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7094 GLenum error
= glGetError();
7095 if (error
!= GL_NO_ERROR
) {
7097 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7102 // Copy the elements and convert to float
7103 GLintptr offset
= 0;
7104 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7105 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7106 const VertexAttrib
* attrib
= *it
;
7107 const Program::VertexAttrib
* attrib_info
=
7108 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7109 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7110 max_vertex_accessed
);
7111 GLuint num_vertices
= max_accessed
+ 1;
7112 if (num_vertices
== 0) {
7114 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7118 attrib
->CanAccess(max_accessed
) &&
7119 attrib
->type() == GL_FIXED
) {
7120 int num_elements
= attrib
->size() * num_vertices
;
7121 const int src_size
= num_elements
* sizeof(int32
);
7122 const int dst_size
= num_elements
* sizeof(float);
7123 scoped_ptr
<float[]> data(new float[num_elements
]);
7124 const int32
* src
= reinterpret_cast<const int32
*>(
7125 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7126 const int32
* end
= src
+ num_elements
;
7127 float* dst
= data
.get();
7128 while (src
!= end
) {
7129 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7131 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7132 glVertexAttribPointer(
7133 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7134 reinterpret_cast<GLvoid
*>(offset
));
7142 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7143 // There's no need to call glVertexAttribPointer because we shadow all the
7144 // settings and passing GL_FIXED to it will not work.
7147 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7151 error::Error
GLES2DecoderImpl::DoDrawArrays(
7152 const char* function_name
,
7157 GLsizei primcount
) {
7158 error::Error error
= WillAccessBoundFramebufferForDraw();
7159 if (error
!= error::kNoError
)
7161 if (!validators_
->draw_mode
.IsValid(mode
)) {
7162 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7163 return error::kNoError
;
7166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7167 return error::kNoError
;
7169 if (primcount
< 0) {
7170 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7171 return error::kNoError
;
7173 if (!CheckBoundFramebuffersValid(function_name
)) {
7174 return error::kNoError
;
7176 // We have to check this here because the prototype for glDrawArrays
7177 // is GLint not GLsizei.
7179 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7180 return error::kNoError
;
7183 if (count
== 0 || primcount
== 0) {
7184 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7185 return error::kNoError
;
7188 GLuint max_vertex_accessed
= first
+ count
- 1;
7189 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7190 if (!ClearUnclearedTextures()) {
7191 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7192 return error::kNoError
;
7194 bool simulated_attrib_0
= false;
7195 if (!SimulateAttrib0(
7196 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7197 return error::kNoError
;
7199 bool simulated_fixed_attribs
= false;
7200 if (SimulateFixedAttribs(
7201 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7203 bool textures_set
= !PrepareTexturesForRender();
7205 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7207 glDrawArrays(mode
, first
, count
);
7209 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7212 RestoreStateForTextures();
7214 if (simulated_fixed_attribs
) {
7215 RestoreStateForSimulatedFixedAttribs();
7218 if (simulated_attrib_0
) {
7219 // We don't have to restore attrib 0 generic data at the end of this
7220 // function even if it is simulated. This is because we will simulate
7221 // it in each draw call, and attrib 0 generic data queries use cached
7222 // values instead of passing down to the underlying driver.
7223 RestoreStateForAttrib(0, false);
7226 return error::kNoError
;
7229 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7230 const void* cmd_data
) {
7231 // TODO(zmo): crbug.com/481184
7232 // On Desktop GL with versions lower than 4.3, we need to emulate
7233 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7234 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7235 return DoDrawArrays("glDrawArrays",
7237 static_cast<GLenum
>(c
.mode
),
7238 static_cast<GLint
>(c
.first
),
7239 static_cast<GLsizei
>(c
.count
),
7243 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7244 uint32 immediate_data_size
,
7245 const void* cmd_data
) {
7246 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7247 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7248 if (!features().angle_instanced_arrays
) {
7250 GL_INVALID_OPERATION
,
7251 "glDrawArraysInstancedANGLE", "function not available");
7252 return error::kNoError
;
7254 return DoDrawArrays("glDrawArraysIntancedANGLE",
7256 static_cast<GLenum
>(c
.mode
),
7257 static_cast<GLint
>(c
.first
),
7258 static_cast<GLsizei
>(c
.count
),
7259 static_cast<GLsizei
>(c
.primcount
));
7262 error::Error
GLES2DecoderImpl::DoDrawElements(
7263 const char* function_name
,
7269 GLsizei primcount
) {
7270 error::Error error
= WillAccessBoundFramebufferForDraw();
7271 if (error
!= error::kNoError
)
7273 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7275 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7276 return error::kNoError
;
7280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7281 return error::kNoError
;
7284 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7285 return error::kNoError
;
7287 if (!validators_
->draw_mode
.IsValid(mode
)) {
7288 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7289 return error::kNoError
;
7291 if (!validators_
->index_type
.IsValid(type
)) {
7292 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7293 return error::kNoError
;
7295 if (primcount
< 0) {
7296 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7297 return error::kNoError
;
7300 if (!CheckBoundFramebuffersValid(function_name
)) {
7301 return error::kNoError
;
7304 if (count
== 0 || primcount
== 0) {
7305 return error::kNoError
;
7308 GLuint max_vertex_accessed
;
7309 Buffer
* element_array_buffer
=
7310 state_
.vertex_attrib_manager
->element_array_buffer();
7312 if (!element_array_buffer
->GetMaxValueForRange(
7313 offset
, count
, type
, &max_vertex_accessed
)) {
7315 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7316 return error::kNoError
;
7319 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7320 if (!ClearUnclearedTextures()) {
7321 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7322 return error::kNoError
;
7324 bool simulated_attrib_0
= false;
7325 if (!SimulateAttrib0(
7326 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7327 return error::kNoError
;
7329 bool simulated_fixed_attribs
= false;
7330 if (SimulateFixedAttribs(
7331 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7333 bool textures_set
= !PrepareTexturesForRender();
7335 // TODO(gman): Refactor to hide these details in BufferManager or
7336 // VertexAttribManager.
7337 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7338 bool used_client_side_array
= false;
7339 if (element_array_buffer
->IsClientSideArray()) {
7340 used_client_side_array
= true;
7341 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7342 indices
= element_array_buffer
->GetRange(offset
, 0);
7345 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7347 glDrawElements(mode
, count
, type
, indices
);
7349 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7352 if (used_client_side_array
) {
7353 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7354 element_array_buffer
->service_id());
7358 RestoreStateForTextures();
7360 if (simulated_fixed_attribs
) {
7361 RestoreStateForSimulatedFixedAttribs();
7364 if (simulated_attrib_0
) {
7365 // We don't have to restore attrib 0 generic data at the end of this
7366 // function even if it is simulated. This is because we will simulate
7367 // it in each draw call, and attrib 0 generic data queries use cached
7368 // values instead of passing down to the underlying driver.
7369 RestoreStateForAttrib(0, false);
7372 return error::kNoError
;
7375 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7376 const void* cmd_data
) {
7377 // TODO(zmo): crbug.com/481184
7378 // On Desktop GL with versions lower than 4.3, we need to emulate
7379 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7380 const gles2::cmds::DrawElements
& c
=
7381 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7382 return DoDrawElements("glDrawElements",
7384 static_cast<GLenum
>(c
.mode
),
7385 static_cast<GLsizei
>(c
.count
),
7386 static_cast<GLenum
>(c
.type
),
7387 static_cast<int32
>(c
.index_offset
),
7391 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7392 uint32 immediate_data_size
,
7393 const void* cmd_data
) {
7394 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7395 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7396 if (!features().angle_instanced_arrays
) {
7398 GL_INVALID_OPERATION
,
7399 "glDrawElementsInstancedANGLE", "function not available");
7400 return error::kNoError
;
7402 return DoDrawElements("glDrawElementsInstancedANGLE",
7404 static_cast<GLenum
>(c
.mode
),
7405 static_cast<GLsizei
>(c
.count
),
7406 static_cast<GLenum
>(c
.type
),
7407 static_cast<int32
>(c
.index_offset
),
7408 static_cast<GLsizei
>(c
.primcount
));
7411 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7412 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7413 GLuint max_vertex_accessed
= 0;
7414 Buffer
* buffer
= GetBuffer(buffer_id
);
7416 // TODO(gman): Should this be a GL error or a command buffer error?
7418 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7420 if (!buffer
->GetMaxValueForRange(
7421 offset
, count
, type
, &max_vertex_accessed
)) {
7422 // TODO(gman): Should this be a GL error or a command buffer error?
7424 GL_INVALID_OPERATION
,
7425 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7428 return max_vertex_accessed
;
7431 void GLES2DecoderImpl::DoShaderSource(
7432 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7434 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7435 if (length
&& length
[ii
] > 0)
7436 str
.append(data
[ii
], length
[ii
]);
7438 str
.append(data
[ii
]);
7440 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7444 // Note: We don't actually call glShaderSource here. We wait until
7445 // we actually compile the shader.
7446 shader
->set_source(str
);
7449 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7450 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7451 GLenum buffer_mode
) {
7452 Program
* program
= GetProgramInfoNotShader(
7453 client_program_id
, "glTransformFeedbackVaryings");
7457 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7458 glTransformFeedbackVaryings(
7459 program
->service_id(), count
, varyings
, buffer_mode
);
7462 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7463 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7464 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7469 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7470 if (use_shader_translator_
) {
7471 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7472 vertex_translator_
: fragment_translator_
;
7475 const Shader::TranslatedShaderSourceType source_type
=
7476 feature_info_
->feature_flags().angle_translated_shader_source
?
7477 Shader::kANGLE
: Shader::kGL
;
7478 shader
->RequestCompile(translator
, source_type
);
7481 void GLES2DecoderImpl::DoGetShaderiv(
7482 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7483 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7488 // Compile now for statuses that require it.
7490 case GL_COMPILE_STATUS
:
7491 case GL_INFO_LOG_LENGTH
:
7492 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7493 shader
->DoCompile();
7501 case GL_SHADER_SOURCE_LENGTH
:
7502 *params
= shader
->source().size();
7506 case GL_COMPILE_STATUS
:
7507 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7509 case GL_INFO_LOG_LENGTH
:
7510 *params
= shader
->log_info().size();
7514 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7515 *params
= shader
->translated_source().size();
7522 glGetShaderiv(shader
->service_id(), pname
, params
);
7525 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7526 const void* cmd_data
) {
7527 const gles2::cmds::GetShaderSource
& c
=
7528 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7529 GLuint shader_id
= c
.shader
;
7530 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7531 Bucket
* bucket
= CreateBucket(bucket_id
);
7532 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7533 if (!shader
|| shader
->source().empty()) {
7535 return error::kNoError
;
7537 bucket
->SetFromString(shader
->source().c_str());
7538 return error::kNoError
;
7541 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7542 uint32 immediate_data_size
,
7543 const void* cmd_data
) {
7544 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7545 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7547 GLuint shader_id
= c
.shader
;
7548 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7549 Bucket
* bucket
= CreateBucket(bucket_id
);
7550 Shader
* shader
= GetShaderInfoNotProgram(
7551 shader_id
, "glGetTranslatedShaderSourceANGLE");
7554 return error::kNoError
;
7557 // Make sure translator has been utilized in compile.
7558 shader
->DoCompile();
7560 bucket
->SetFromString(shader
->translated_source().c_str());
7561 return error::kNoError
;
7564 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7565 uint32 immediate_data_size
,
7566 const void* cmd_data
) {
7567 const gles2::cmds::GetProgramInfoLog
& c
=
7568 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7569 GLuint program_id
= c
.program
;
7570 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7571 Bucket
* bucket
= CreateBucket(bucket_id
);
7572 Program
* program
= GetProgramInfoNotShader(
7573 program_id
, "glGetProgramInfoLog");
7574 if (!program
|| !program
->log_info()) {
7575 bucket
->SetFromString("");
7576 return error::kNoError
;
7578 bucket
->SetFromString(program
->log_info()->c_str());
7579 return error::kNoError
;
7582 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7583 uint32 immediate_data_size
,
7584 const void* cmd_data
) {
7585 const gles2::cmds::GetShaderInfoLog
& c
=
7586 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7587 GLuint shader_id
= c
.shader
;
7588 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7589 Bucket
* bucket
= CreateBucket(bucket_id
);
7590 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7592 bucket
->SetFromString("");
7593 return error::kNoError
;
7596 // Shader must be compiled in order to get the info log.
7597 shader
->DoCompile();
7599 bucket
->SetFromString(shader
->log_info().c_str());
7600 return error::kNoError
;
7603 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7604 return state_
.GetEnabled(cap
);
7607 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7608 const Buffer
* buffer
= GetBuffer(client_id
);
7609 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7612 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7613 const Framebuffer
* framebuffer
=
7614 GetFramebuffer(client_id
);
7615 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7618 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7619 // IsProgram is true for programs as soon as they are created, until they are
7620 // deleted and no longer in use.
7621 const Program
* program
= GetProgram(client_id
);
7622 return program
!= NULL
&& !program
->IsDeleted();
7625 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7626 const Renderbuffer
* renderbuffer
=
7627 GetRenderbuffer(client_id
);
7628 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7631 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7632 // IsShader is true for shaders as soon as they are created, until they
7633 // are deleted and not attached to any programs.
7634 const Shader
* shader
= GetShader(client_id
);
7635 return shader
!= NULL
&& !shader
->IsDeleted();
7638 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7639 const TextureRef
* texture_ref
= GetTexture(client_id
);
7640 return texture_ref
&& texture_ref
->texture()->IsValid();
7643 void GLES2DecoderImpl::DoAttachShader(
7644 GLuint program_client_id
, GLint shader_client_id
) {
7645 Program
* program
= GetProgramInfoNotShader(
7646 program_client_id
, "glAttachShader");
7650 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7654 if (!program
->AttachShader(shader_manager(), shader
)) {
7656 GL_INVALID_OPERATION
,
7658 "can not attach more than one shader of the same type.");
7661 glAttachShader(program
->service_id(), shader
->service_id());
7664 void GLES2DecoderImpl::DoDetachShader(
7665 GLuint program_client_id
, GLint shader_client_id
) {
7666 Program
* program
= GetProgramInfoNotShader(
7667 program_client_id
, "glDetachShader");
7671 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7675 if (!program
->DetachShader(shader_manager(), shader
)) {
7677 GL_INVALID_OPERATION
,
7678 "glDetachShader", "shader not attached to program");
7681 glDetachShader(program
->service_id(), shader
->service_id());
7684 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7685 Program
* program
= GetProgramInfoNotShader(
7686 program_client_id
, "glValidateProgram");
7690 program
->Validate();
7693 void GLES2DecoderImpl::GetVertexAttribHelper(
7694 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7696 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
7698 Buffer
* buffer
= attrib
->buffer();
7699 if (buffer
&& !buffer
->IsDeleted()) {
7701 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7702 *params
= client_id
;
7706 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7707 *params
= attrib
->enabled();
7709 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7710 *params
= attrib
->size();
7712 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7713 *params
= attrib
->gl_stride();
7715 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7716 *params
= attrib
->type();
7718 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7719 *params
= attrib
->normalized();
7721 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
7722 *params
= attrib
->divisor();
7724 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
7725 *params
= attrib
->integer();
7733 void GLES2DecoderImpl::DoGetTexParameterfv(
7734 GLenum target
, GLenum pname
, GLfloat
* params
) {
7735 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7736 glGetTexParameterfv(target
, pname
, params
);
7739 void GLES2DecoderImpl::DoGetTexParameteriv(
7740 GLenum target
, GLenum pname
, GLint
* params
) {
7741 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7742 glGetTexParameteriv(target
, pname
, params
);
7745 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7746 GLenum target
, GLenum pname
) {
7747 if (!workarounds().init_texture_max_anisotropy
)
7749 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7750 !validators_
->texture_parameter
.IsValid(pname
)) {
7754 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7758 GL_INVALID_OPERATION
,
7759 "glGetTexParamter{fi}v", "unknown texture for target");
7762 Texture
* texture
= texture_ref
->texture();
7763 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7766 template <typename T
>
7767 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7768 GLuint index
, GLenum pname
, T
* params
) {
7769 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7772 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
7776 case GL_CURRENT_VERTEX_ATTRIB
:
7777 state_
.attrib_values
[index
].GetValues(params
);
7781 GetVertexAttribHelper(attrib
, pname
, &value
);
7782 *params
= static_cast<T
>(value
);
7788 void GLES2DecoderImpl::DoGetVertexAttribfv(
7789 GLuint index
, GLenum pname
, GLfloat
* params
) {
7790 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
7793 void GLES2DecoderImpl::DoGetVertexAttribiv(
7794 GLuint index
, GLenum pname
, GLint
* params
) {
7795 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7798 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7799 GLuint index
, GLenum pname
, GLint
* params
) {
7800 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
7803 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7804 GLuint index
, GLenum pname
, GLuint
* params
) {
7805 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
7808 template <typename T
>
7809 bool GLES2DecoderImpl::SetVertexAttribValue(
7810 const char* function_name
, GLuint index
, const T
* value
) {
7811 if (index
>= state_
.attrib_values
.size()) {
7812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7815 state_
.attrib_values
[index
].SetValues(value
);
7819 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7820 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7821 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7822 glVertexAttrib1f(index
, v0
);
7826 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7827 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7828 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7829 glVertexAttrib2f(index
, v0
, v1
);
7833 void GLES2DecoderImpl::DoVertexAttrib3f(
7834 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7835 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7836 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7837 glVertexAttrib3f(index
, v0
, v1
, v2
);
7841 void GLES2DecoderImpl::DoVertexAttrib4f(
7842 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7843 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7844 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7845 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7849 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7850 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7851 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7852 glVertexAttrib1fv(index
, v
);
7856 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7857 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7858 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7859 glVertexAttrib2fv(index
, v
);
7863 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7864 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7865 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7866 glVertexAttrib3fv(index
, v
);
7870 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7871 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7872 glVertexAttrib4fv(index
, v
);
7876 void GLES2DecoderImpl::DoVertexAttribI4i(
7877 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
7878 GLint v
[4] = { v0
, v1
, v2
, v3
};
7879 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
7880 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
7884 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
7885 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
7886 glVertexAttribI4iv(index
, v
);
7890 void GLES2DecoderImpl::DoVertexAttribI4ui(
7891 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
7892 GLuint v
[4] = { v0
, v1
, v2
, v3
};
7893 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
7894 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
7898 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
7899 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
7900 glVertexAttribI4uiv(index
, v
);
7904 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7905 uint32 immediate_data_size
,
7906 const void* cmd_data
) {
7907 if (!unsafe_es3_apis_enabled())
7908 return error::kUnknownCommand
;
7909 const gles2::cmds::VertexAttribIPointer
& c
=
7910 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7912 if (!state_
.bound_array_buffer
.get() ||
7913 state_
.bound_array_buffer
->IsDeleted()) {
7914 if (state_
.vertex_attrib_manager
.get() ==
7915 state_
.default_vertex_attrib_manager
.get()) {
7917 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
7918 return error::kNoError
;
7919 } else if (c
.offset
!= 0) {
7922 "glVertexAttribIPointer", "client side arrays are not allowed");
7923 return error::kNoError
;
7927 GLuint indx
= c
.indx
;
7928 GLint size
= c
.size
;
7929 GLenum type
= c
.type
;
7930 GLsizei stride
= c
.stride
;
7931 GLsizei offset
= c
.offset
;
7932 const void* ptr
= reinterpret_cast<const void*>(offset
);
7933 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
7934 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
7935 return error::kNoError
;
7937 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7939 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7940 return error::kNoError
;
7942 if (indx
>= group_
->max_vertex_attribs()) {
7944 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
7945 return error::kNoError
;
7949 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
7950 return error::kNoError
;
7954 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
7955 return error::kNoError
;
7959 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
7960 return error::kNoError
;
7962 GLsizei component_size
=
7963 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7964 // component_size must be a power of two to use & as optimized modulo.
7965 DCHECK(GLES2Util::IsPOT(component_size
));
7966 if (offset
& (component_size
- 1)) {
7968 GL_INVALID_OPERATION
,
7969 "glVertexAttribIPointer", "offset not valid for type");
7970 return error::kNoError
;
7972 if (stride
& (component_size
- 1)) {
7974 GL_INVALID_OPERATION
,
7975 "glVertexAttribIPointer", "stride not valid for type");
7976 return error::kNoError
;
7978 state_
.vertex_attrib_manager
7979 ->SetAttribInfo(indx
,
7980 state_
.bound_array_buffer
.get(),
7985 stride
!= 0 ? stride
: component_size
* size
,
7988 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7989 return error::kNoError
;
7992 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7993 uint32 immediate_data_size
,
7994 const void* cmd_data
) {
7995 const gles2::cmds::VertexAttribPointer
& c
=
7996 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7998 if (!state_
.bound_array_buffer
.get() ||
7999 state_
.bound_array_buffer
->IsDeleted()) {
8000 if (state_
.vertex_attrib_manager
.get() ==
8001 state_
.default_vertex_attrib_manager
.get()) {
8003 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8004 return error::kNoError
;
8005 } else if (c
.offset
!= 0) {
8008 "glVertexAttribPointer", "client side arrays are not allowed");
8009 return error::kNoError
;
8013 GLuint indx
= c
.indx
;
8014 GLint size
= c
.size
;
8015 GLenum type
= c
.type
;
8016 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8017 GLsizei stride
= c
.stride
;
8018 GLsizei offset
= c
.offset
;
8019 const void* ptr
= reinterpret_cast<const void*>(offset
);
8020 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8021 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8022 return error::kNoError
;
8024 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8026 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8027 return error::kNoError
;
8029 if (indx
>= group_
->max_vertex_attribs()) {
8031 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8032 return error::kNoError
;
8036 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8037 return error::kNoError
;
8041 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8042 return error::kNoError
;
8046 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8047 return error::kNoError
;
8049 GLsizei component_size
=
8050 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8051 // component_size must be a power of two to use & as optimized modulo.
8052 DCHECK(GLES2Util::IsPOT(component_size
));
8053 if (offset
& (component_size
- 1)) {
8055 GL_INVALID_OPERATION
,
8056 "glVertexAttribPointer", "offset not valid for type");
8057 return error::kNoError
;
8059 if (stride
& (component_size
- 1)) {
8061 GL_INVALID_OPERATION
,
8062 "glVertexAttribPointer", "stride not valid for type");
8063 return error::kNoError
;
8065 state_
.vertex_attrib_manager
8066 ->SetAttribInfo(indx
,
8067 state_
.bound_array_buffer
.get(),
8072 stride
!= 0 ? stride
: component_size
* size
,
8075 // We support GL_FIXED natively on EGL/GLES2 implementations
8076 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8077 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8079 return error::kNoError
;
8082 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8084 state_
.viewport_x
= x
;
8085 state_
.viewport_y
= y
;
8086 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8087 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8088 glViewport(x
, y
, width
, height
);
8091 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8092 uint32 immediate_data_size
,
8093 const void* cmd_data
) {
8094 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8095 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8096 if (!features().angle_instanced_arrays
) {
8098 GL_INVALID_OPERATION
,
8099 "glVertexAttribDivisorANGLE", "function not available");
8100 return error::kNoError
;
8102 GLuint index
= c
.index
;
8103 GLuint divisor
= c
.divisor
;
8104 if (index
>= group_
->max_vertex_attribs()) {
8107 "glVertexAttribDivisorANGLE", "index out of range");
8108 return error::kNoError
;
8111 state_
.vertex_attrib_manager
->SetDivisor(
8114 glVertexAttribDivisorANGLE(index
, divisor
);
8115 return error::kNoError
;
8118 template <typename pixel_data_type
>
8119 static void WriteAlphaData(
8120 void* pixels
, uint32 row_count
, uint32 channel_count
,
8121 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8122 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8123 DCHECK_GT(channel_count
, 0U);
8124 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8125 uint32 unpadded_row_size_in_elements
=
8126 unpadded_row_size
/ sizeof(pixel_data_type
);
8127 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8128 uint32 padded_row_size_in_elements
=
8129 padded_row_size
/ sizeof(pixel_data_type
);
8130 pixel_data_type
* dst
=
8131 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8132 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8133 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8134 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8137 dst
+= padded_row_size_in_elements
;
8141 void GLES2DecoderImpl::FinishReadPixels(
8142 const cmds::ReadPixels
& c
,
8144 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8145 GLsizei width
= c
.width
;
8146 GLsizei height
= c
.height
;
8147 GLenum format
= c
.format
;
8148 GLenum type
= c
.type
;
8149 typedef cmds::ReadPixels::Result Result
;
8151 Result
* result
= NULL
;
8152 if (c
.result_shm_id
!= 0) {
8153 result
= GetSharedMemoryAs
<Result
*>(
8154 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8157 glDeleteBuffersARB(1, &buffer
);
8162 GLES2Util::ComputeImageDataSizes(
8163 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8165 void* pixels
= GetSharedMemoryAs
<void*>(
8166 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8169 glDeleteBuffersARB(1, &buffer
);
8175 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8177 if (features().map_buffer_range
) {
8178 data
= glMapBufferRange(
8179 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8181 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8184 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8185 "Unable to map memory for readback.");
8188 memcpy(pixels
, data
, pixels_size
);
8189 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8190 // have to restore the state.
8191 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8192 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8193 glDeleteBuffersARB(1, &buffer
);
8196 if (result
!= NULL
) {
8200 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8201 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8202 if ((channels_exist
& 0x0008) == 0 &&
8203 workarounds().clear_alpha_in_readpixels
) {
8204 // Set the alpha to 255 because some drivers are buggy in this regard.
8207 uint32 unpadded_row_size
;
8208 uint32 padded_row_size
;
8209 if (!GLES2Util::ComputeImageDataSizes(
8210 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8211 &unpadded_row_size
, &padded_row_size
)) {
8215 uint32 channel_count
= 0;
8216 uint32 alpha_channel
= 0;
8229 if (channel_count
> 0) {
8231 case GL_UNSIGNED_BYTE
:
8232 WriteAlphaData
<uint8
>(
8233 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8234 padded_row_size
, 0xFF);
8237 WriteAlphaData
<float>(
8238 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8239 padded_row_size
, 1.0f
);
8242 WriteAlphaData
<uint16
>(
8243 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8244 padded_row_size
, 0x3C00);
8251 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8252 const void* cmd_data
) {
8253 const gles2::cmds::ReadPixels
& c
=
8254 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8255 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8256 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8257 if (fbo_error
!= error::kNoError
)
8261 GLsizei width
= c
.width
;
8262 GLsizei height
= c
.height
;
8263 GLenum format
= c
.format
;
8264 GLenum type
= c
.type
;
8265 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8266 if (width
< 0 || height
< 0) {
8267 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8268 return error::kNoError
;
8270 typedef cmds::ReadPixels::Result Result
;
8272 if (!GLES2Util::ComputeImageDataSizes(
8273 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8275 return error::kOutOfBounds
;
8277 void* pixels
= GetSharedMemoryAs
<void*>(
8278 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8280 return error::kOutOfBounds
;
8282 Result
* result
= NULL
;
8283 if (c
.result_shm_id
!= 0) {
8284 result
= GetSharedMemoryAs
<Result
*>(
8285 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8287 return error::kOutOfBounds
;
8291 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8292 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8293 return error::kNoError
;
8295 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8296 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8297 return error::kNoError
;
8299 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8300 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8301 // format and type are acceptable enums but not guaranteed to be supported
8302 // for this framebuffer. Have to ask gl if they are valid.
8303 GLint preferred_format
= 0;
8304 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8305 GLint preferred_type
= 0;
8306 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8307 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8308 type
!= static_cast<GLenum
>(preferred_type
)) {
8310 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8311 "with the current read framebuffer");
8312 return error::kNoError
;
8315 if (width
== 0 || height
== 0) {
8316 return error::kNoError
;
8319 // Get the size of the current fbo or backbuffer.
8320 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8324 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8326 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8327 return error::kNoError
;
8330 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8331 return error::kNoError
;
8334 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8335 return error::kNoError
;
8338 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8340 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8342 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8343 // The user requested an out of range area. Get the results 1 line
8346 uint32 unpadded_row_size
;
8347 uint32 padded_row_size
;
8348 if (!GLES2Util::ComputeImageDataSizes(
8349 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8350 &unpadded_row_size
, &padded_row_size
)) {
8352 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8353 return error::kNoError
;
8356 GLint dest_x_offset
= std::max(-x
, 0);
8357 uint32 dest_row_offset
;
8358 if (!GLES2Util::ComputeImageDataSizes(
8359 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8360 &dest_row_offset
, NULL
, NULL
)) {
8362 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8363 return error::kNoError
;
8366 // Copy each row into the larger dest rect.
8367 int8
* dst
= static_cast<int8
*>(pixels
);
8368 GLint read_x
= std::max(0, x
);
8369 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8370 GLint read_width
= read_end_x
- read_x
;
8371 for (GLint yy
= 0; yy
< height
; ++yy
) {
8375 memset(dst
, 0, unpadded_row_size
);
8377 // If the row is in range, copy it.
8378 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8380 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8382 dst
+= padded_row_size
;
8385 if (async
&& features().use_async_readpixels
) {
8387 glGenBuffersARB(1, &buffer
);
8388 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8389 // For ANGLE client version 2, GL_STREAM_READ is not available.
8390 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8391 GL_STATIC_DRAW
: GL_STREAM_READ
;
8392 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8393 GLenum error
= glGetError();
8394 if (error
== GL_NO_ERROR
) {
8395 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8396 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8397 new FenceCallback()));
8398 WaitForReadPixels(base::Bind(
8399 &GLES2DecoderImpl::FinishReadPixels
,
8400 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8401 <GLES2DecoderImpl
>(this),
8403 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8404 return error::kNoError
;
8406 // On error, unbind pack buffer and fall through to sync readpixels
8407 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8408 glDeleteBuffersARB(1, &buffer
);
8411 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8413 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8414 if (error
== GL_NO_ERROR
) {
8415 if (result
!= NULL
) {
8418 FinishReadPixels(c
, 0);
8421 return error::kNoError
;
8424 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8425 const void* cmd_data
) {
8426 const gles2::cmds::PixelStorei
& c
=
8427 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8428 GLenum pname
= c
.pname
;
8429 GLenum param
= c
.param
;
8430 if (!validators_
->pixel_store
.IsValid(pname
)) {
8431 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8432 return error::kNoError
;
8435 case GL_PACK_ALIGNMENT
:
8436 case GL_UNPACK_ALIGNMENT
:
8437 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8439 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8440 return error::kNoError
;
8443 case GL_UNPACK_FLIP_Y_CHROMIUM
:
8444 unpack_flip_y_
= (param
!= 0);
8445 return error::kNoError
;
8446 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
8447 unpack_premultiply_alpha_
= (param
!= 0);
8448 return error::kNoError
;
8449 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
8450 unpack_unpremultiply_alpha_
= (param
!= 0);
8451 return error::kNoError
;
8455 glPixelStorei(pname
, param
);
8457 case GL_PACK_ALIGNMENT
:
8458 state_
.pack_alignment
= param
;
8460 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8461 state_
.pack_reverse_row_order
= (param
!= 0);
8463 case GL_UNPACK_ALIGNMENT
:
8464 state_
.unpack_alignment
= param
;
8467 // Validation should have prevented us from getting here.
8471 return error::kNoError
;
8474 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8475 uint32 immediate_data_size
,
8476 const void* cmd_data
) {
8477 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8478 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8479 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8481 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8483 if (!supports_post_sub_buffer_
) {
8485 GL_INVALID_OPERATION
,
8486 "glPostSubBufferCHROMIUM", "command not supported by surface");
8487 return error::kNoError
;
8490 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8493 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8494 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8495 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8496 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8498 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
8499 gfx::SwapResult::SWAP_FAILED
) {
8500 return error::kNoError
;
8502 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8503 return error::kLostContext
;
8507 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8508 uint32 immediate_data_size
,
8509 const void* cmd_data
) {
8510 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8511 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8512 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8515 "glScheduleOverlayPlaneCHROMIUM",
8517 return error::kNoError
;
8519 gfx::GLImage
* image
=
8520 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8522 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8523 "glScheduleOverlayPlaneCHROMIUM",
8524 "unsupported texture format");
8525 return error::kNoError
;
8527 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8528 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8529 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8530 "glScheduleOverlayPlaneCHROMIUM",
8531 "invalid transform enum");
8532 return error::kNoError
;
8534 if (!surface_
->ScheduleOverlayPlane(
8538 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8539 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8540 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8541 "glScheduleOverlayPlaneCHROMIUM",
8542 "failed to schedule overlay");
8544 return error::kNoError
;
8547 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8548 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8549 const std::string
& name_str
) {
8550 if (!StringIsValidForGLES(name_str
.c_str())) {
8552 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8553 return error::kNoError
;
8555 Program
* program
= GetProgramInfoNotShader(
8556 client_id
, "glGetAttribLocation");
8558 return error::kNoError
;
8560 if (!program
->IsValid()) {
8562 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8563 return error::kNoError
;
8565 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8566 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8568 return error::kOutOfBounds
;
8570 // Require the client to init this incase the context is lost and we are no
8571 // longer executing commands.
8572 if (*location
!= -1) {
8573 return error::kGenericError
;
8575 *location
= program
->GetAttribLocation(name_str
);
8576 return error::kNoError
;
8579 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8580 uint32 immediate_data_size
,
8581 const void* cmd_data
) {
8582 const gles2::cmds::GetAttribLocation
& c
=
8583 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8584 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8586 return error::kInvalidArguments
;
8588 std::string name_str
;
8589 if (!bucket
->GetAsString(&name_str
)) {
8590 return error::kInvalidArguments
;
8592 return GetAttribLocationHelper(
8593 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8596 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8597 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8598 const std::string
& name_str
) {
8599 if (!StringIsValidForGLES(name_str
.c_str())) {
8601 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8602 return error::kNoError
;
8604 Program
* program
= GetProgramInfoNotShader(
8605 client_id
, "glGetUniformLocation");
8607 return error::kNoError
;
8609 if (!program
->IsValid()) {
8611 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8612 return error::kNoError
;
8614 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8615 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8617 return error::kOutOfBounds
;
8619 // Require the client to init this incase the context is lost an we are no
8620 // longer executing commands.
8621 if (*location
!= -1) {
8622 return error::kGenericError
;
8624 *location
= program
->GetUniformFakeLocation(name_str
);
8625 return error::kNoError
;
8628 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8629 uint32 immediate_data_size
,
8630 const void* cmd_data
) {
8631 const gles2::cmds::GetUniformLocation
& c
=
8632 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8633 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8635 return error::kInvalidArguments
;
8637 std::string name_str
;
8638 if (!bucket
->GetAsString(&name_str
)) {
8639 return error::kInvalidArguments
;
8641 return GetUniformLocationHelper(
8642 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8645 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8646 uint32 immediate_data_size
,
8647 const void* cmd_data
) {
8648 if (!unsafe_es3_apis_enabled())
8649 return error::kUnknownCommand
;
8650 const gles2::cmds::GetUniformIndices
& c
=
8651 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8652 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8654 return error::kInvalidArguments
;
8657 std::vector
<char*> names
;
8658 std::vector
<GLint
> len
;
8659 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8660 return error::kInvalidArguments
;
8662 typedef cmds::GetUniformIndices::Result Result
;
8663 Result
* result
= GetSharedMemoryAs
<Result
*>(
8664 c
.indices_shm_id
, c
.indices_shm_offset
,
8665 Result::ComputeSize(static_cast<size_t>(count
)));
8666 GLuint
* indices
= result
? result
->GetData() : NULL
;
8667 if (indices
== NULL
) {
8668 return error::kOutOfBounds
;
8670 // Check that the client initialized the result.
8671 if (result
->size
!= 0) {
8672 return error::kInvalidArguments
;
8674 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8676 return error::kNoError
;
8678 GLuint service_id
= program
->service_id();
8679 GLint link_status
= GL_FALSE
;
8680 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8681 if (link_status
!= GL_TRUE
) {
8682 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8683 "glGetUniformIndices", "program not linked");
8684 return error::kNoError
;
8686 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8687 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8688 GLenum error
= glGetError();
8689 if (error
== GL_NO_ERROR
) {
8690 result
->SetNumResults(count
);
8692 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8694 return error::kNoError
;
8697 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8698 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8699 const std::string
& name_str
) {
8700 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8701 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8703 return error::kOutOfBounds
;
8705 // Require the client to init this incase the context is lost and we are no
8706 // longer executing commands.
8707 if (*location
!= -1) {
8708 return error::kGenericError
;
8710 Program
* program
= GetProgramInfoNotShader(
8711 client_id
, "glGetFragDataLocation");
8713 return error::kNoError
;
8715 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8716 return error::kNoError
;
8719 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8720 uint32 immediate_data_size
,
8721 const void* cmd_data
) {
8722 if (!unsafe_es3_apis_enabled())
8723 return error::kUnknownCommand
;
8724 const gles2::cmds::GetFragDataLocation
& c
=
8725 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8726 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8728 return error::kInvalidArguments
;
8730 std::string name_str
;
8731 if (!bucket
->GetAsString(&name_str
)) {
8732 return error::kInvalidArguments
;
8734 return GetFragDataLocationHelper(
8735 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8738 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8739 uint32 immediate_data_size
, const void* cmd_data
) {
8740 if (!unsafe_es3_apis_enabled())
8741 return error::kUnknownCommand
;
8742 const gles2::cmds::GetUniformBlockIndex
& c
=
8743 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8744 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8746 return error::kInvalidArguments
;
8748 std::string name_str
;
8749 if (!bucket
->GetAsString(&name_str
)) {
8750 return error::kInvalidArguments
;
8752 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8753 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8755 return error::kOutOfBounds
;
8757 // Require the client to init this in case the context is lost and we are no
8758 // longer executing commands.
8759 if (*index
!= GL_INVALID_INDEX
) {
8760 return error::kGenericError
;
8762 Program
* program
= GetProgramInfoNotShader(
8763 c
.program
, "glGetUniformBlockIndex");
8765 return error::kNoError
;
8767 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8768 return error::kNoError
;
8771 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8772 const void* cmd_data
) {
8773 const gles2::cmds::GetString
& c
=
8774 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8775 GLenum name
= static_cast<GLenum
>(c
.name
);
8776 if (!validators_
->string_type
.IsValid(name
)) {
8777 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8778 return error::kNoError
;
8781 const char* str
= nullptr;
8782 std::string extensions
;
8785 str
= "OpenGL ES 2.0 Chromium";
8787 case GL_SHADING_LANGUAGE_VERSION
:
8788 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8792 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8793 // They are used by WEBGL_debug_renderer_info.
8794 if (!force_webgl_glsl_validation_
)
8797 str
= reinterpret_cast<const char*>(glGetString(name
));
8801 // For WebGL contexts, strip out the OES derivatives and
8802 // EXT frag depth extensions if they have not been enabled.
8803 if (force_webgl_glsl_validation_
) {
8804 extensions
= feature_info_
->extensions();
8805 if (!derivatives_explicitly_enabled_
) {
8806 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8807 if (std::string::npos
!= offset
) {
8808 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8812 if (!frag_depth_explicitly_enabled_
) {
8813 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8814 if (std::string::npos
!= offset
) {
8815 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8819 if (!draw_buffers_explicitly_enabled_
) {
8820 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8821 if (std::string::npos
!= offset
) {
8822 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8826 if (!shader_texture_lod_explicitly_enabled_
) {
8827 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8828 if (std::string::npos
!= offset
) {
8829 extensions
.replace(offset
,
8830 arraysize(kEXTShaderTextureLodExtension
),
8835 extensions
= feature_info_
->extensions().c_str();
8837 if (supports_post_sub_buffer_
)
8838 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8839 str
= extensions
.c_str();
8843 str
= reinterpret_cast<const char*>(glGetString(name
));
8846 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8847 bucket
->SetFromString(str
);
8848 return error::kNoError
;
8851 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8852 const void* cmd_data
) {
8853 const gles2::cmds::BufferData
& c
=
8854 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8855 GLenum target
= static_cast<GLenum
>(c
.target
);
8856 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8857 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8858 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8859 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8860 const void* data
= NULL
;
8861 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8862 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8864 return error::kOutOfBounds
;
8867 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8868 return error::kNoError
;
8871 void GLES2DecoderImpl::DoBufferSubData(
8872 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8873 // Just delegate it. Some validation is actually done before this.
8874 buffer_manager()->ValidateAndDoBufferSubData(
8875 &state_
, target
, offset
, size
, data
);
8878 bool GLES2DecoderImpl::ClearLevel(
8882 unsigned internal_format
,
8887 bool is_texture_immutable
) {
8888 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8889 if (feature_info_
->feature_flags().angle_depth_texture
&&
8890 (channels
& GLES2Util::kDepth
) != 0) {
8891 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8892 // on depth formats.
8894 glGenFramebuffersEXT(1, &fb
);
8895 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8897 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8898 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8899 GL_DEPTH_ATTACHMENT
;
8901 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8902 texture
->service_id(), level
);
8903 // ANGLE promises a depth only attachment ok.
8904 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8905 GL_FRAMEBUFFER_COMPLETE
) {
8909 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8910 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8912 state_
.SetDeviceDepthMask(GL_TRUE
);
8913 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8914 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8916 RestoreClearState();
8918 glDeleteFramebuffersEXT(1, &fb
);
8919 Framebuffer
* framebuffer
=
8920 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8921 GLuint fb_service_id
=
8922 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8923 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8927 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8930 uint32 padded_row_size
;
8931 if (!GLES2Util::ComputeImageDataSizes(
8932 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8933 NULL
, &padded_row_size
)) {
8937 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8941 if (size
> kMaxZeroSize
) {
8942 if (kMaxZeroSize
< padded_row_size
) {
8943 // That'd be an awfully large texture.
8946 // We should never have a large total size with a zero row size.
8947 DCHECK_GT(padded_row_size
, 0U);
8948 tile_height
= kMaxZeroSize
/ padded_row_size
;
8949 if (!GLES2Util::ComputeImageDataSizes(
8950 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8955 tile_height
= height
;
8958 // Assumes the size has already been checked.
8959 scoped_ptr
<char[]> zero(new char[size
]);
8960 memset(zero
.get(), 0, size
);
8961 glBindTexture(texture
->target(), texture
->service_id());
8963 bool has_images
= texture
->HasImages();
8965 while (y
< height
) {
8966 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8967 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8968 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8971 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8976 TextureRef
* bound_texture
=
8977 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8978 glBindTexture(texture
->target(),
8979 bound_texture
? bound_texture
->service_id() : 0);
8985 const int kS3TCBlockWidth
= 4;
8986 const int kS3TCBlockHeight
= 4;
8987 const int kS3TCDXT1BlockSize
= 8;
8988 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8989 const int kEACAndETC2BlockSize
= 4;
8991 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8992 return (size
== 1) ||
8993 (size
== 2) || !(size
% kS3TCBlockWidth
);
8996 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8997 return GLES2Util::IsPOT(size
);
9000 } // anonymous namespace.
9002 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9003 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9004 GLenum format
, GLsizei size
) {
9005 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9008 case GL_ATC_RGB_AMD
:
9009 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9010 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9011 case GL_ETC1_RGB8_OES
:
9013 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9015 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9016 bytes_required
*= kS3TCDXT1BlockSize
;
9018 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9019 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9020 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9021 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9023 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9025 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9026 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9028 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9029 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9030 bytes_required
= std::max(width
, 8);
9031 bytes_required
*= std::max(height
, 8);
9032 bytes_required
*= 4;
9033 bytes_required
+= 7;
9034 bytes_required
/= 8;
9036 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9037 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9038 bytes_required
= std::max(width
, 16);
9039 bytes_required
*= std::max(height
, 8);
9040 bytes_required
*= 2;
9041 bytes_required
+= 7;
9042 bytes_required
/= 8;
9046 case GL_COMPRESSED_R11_EAC
:
9047 case GL_COMPRESSED_SIGNED_R11_EAC
:
9048 case GL_COMPRESSED_RGB8_ETC2
:
9049 case GL_COMPRESSED_SRGB8_ETC2
:
9050 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9051 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9053 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9055 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9056 bytes_required
*= 8;
9057 bytes_required
*= depth
;
9059 case GL_COMPRESSED_RG11_EAC
:
9060 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9061 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9062 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9064 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9066 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9067 bytes_required
*= 16;
9068 bytes_required
*= depth
;
9071 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9075 if (!bytes_required
.IsValid() || size
!= bytes_required
.ValueOrDefault(0)) {
9077 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9084 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9085 const char* function_name
, GLenum target
, GLint level
,
9086 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9088 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9089 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9090 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9091 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9092 DCHECK_EQ(1, depth
); // 2D formats.
9093 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9095 GL_INVALID_OPERATION
, function_name
,
9096 "width or height invalid for level");
9100 case GL_ATC_RGB_AMD
:
9101 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9102 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9103 case GL_ETC1_RGB8_OES
:
9104 DCHECK_EQ(1, depth
); // 2D formats.
9105 if (width
<= 0 || height
<= 0) {
9107 GL_INVALID_OPERATION
, function_name
,
9108 "width or height invalid for level");
9112 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9113 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9114 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9115 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9116 DCHECK_EQ(1, depth
); // 2D formats.
9117 if (!IsValidPVRTCSize(level
, width
) ||
9118 !IsValidPVRTCSize(level
, height
)) {
9120 GL_INVALID_OPERATION
, function_name
,
9121 "width or height invalid for level");
9127 case GL_COMPRESSED_R11_EAC
:
9128 case GL_COMPRESSED_SIGNED_R11_EAC
:
9129 case GL_COMPRESSED_RG11_EAC
:
9130 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9131 case GL_COMPRESSED_RGB8_ETC2
:
9132 case GL_COMPRESSED_SRGB8_ETC2
:
9133 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9134 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9135 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9136 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9137 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9139 GL_INVALID_OPERATION
, function_name
,
9140 "width, height, or depth invalid");
9143 if (target
== GL_TEXTURE_3D
) {
9145 GL_INVALID_OPERATION
, function_name
,
9146 "target invalid for format");
9155 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9156 const char* function_name
,
9157 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9158 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9160 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9162 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9167 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9168 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9169 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9170 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9171 const int kBlockWidth
= 4;
9172 const int kBlockHeight
= 4;
9173 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9175 GL_INVALID_OPERATION
, function_name
,
9176 "xoffset or yoffset not multiple of 4");
9179 GLsizei tex_width
= 0;
9180 GLsizei tex_height
= 0;
9181 if (!texture
->GetLevelSize(target
, level
,
9182 &tex_width
, &tex_height
, nullptr) ||
9183 width
- xoffset
> tex_width
||
9184 height
- yoffset
> tex_height
) {
9186 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9189 return ValidateCompressedTexDimensions(
9190 function_name
, target
, level
, width
, height
, 1, format
);
9192 case GL_ATC_RGB_AMD
:
9193 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9194 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9196 GL_INVALID_OPERATION
, function_name
,
9197 "not supported for ATC textures");
9200 case GL_ETC1_RGB8_OES
: {
9202 GL_INVALID_OPERATION
, function_name
,
9203 "not supported for ECT1_RGB8_OES textures");
9206 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9207 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9208 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9209 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9210 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9212 GL_INVALID_OPERATION
, function_name
,
9213 "xoffset and yoffset must be zero");
9216 GLsizei tex_width
= 0;
9217 GLsizei tex_height
= 0;
9218 if (!texture
->GetLevelSize(target
, level
,
9219 &tex_width
, &tex_height
, nullptr) ||
9220 width
!= tex_width
||
9221 height
!= tex_height
) {
9223 GL_INVALID_OPERATION
, function_name
,
9224 "dimensions must match existing texture level dimensions");
9227 return ValidateCompressedTexDimensions(
9228 function_name
, target
, level
, width
, height
, 1, format
);
9232 case GL_COMPRESSED_R11_EAC
:
9233 case GL_COMPRESSED_SIGNED_R11_EAC
:
9234 case GL_COMPRESSED_RG11_EAC
:
9235 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9236 case GL_COMPRESSED_RGB8_ETC2
:
9237 case GL_COMPRESSED_SRGB8_ETC2
:
9238 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9239 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9240 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9241 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9243 const int kBlockSize
= 4;
9244 GLsizei tex_width
, tex_height
;
9245 if (target
== GL_TEXTURE_3D
||
9246 !texture
->GetLevelSize(target
, level
,
9247 &tex_width
, &tex_height
, nullptr) ||
9248 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9249 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9250 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9252 GL_INVALID_OPERATION
, function_name
,
9253 "dimensions must match existing texture level dimensions");
9263 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9266 GLenum internal_format
,
9272 if (!validators_
->texture_target
.IsValid(target
)) {
9273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9274 "glCompressedTexImage2D", target
, "target");
9275 return error::kNoError
;
9277 if (!validators_
->compressed_texture_format
.IsValid(
9279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9280 "glCompressedTexImage2D", internal_format
, "internal_format");
9281 return error::kNoError
;
9283 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9287 "glCompressedTexImage2D", "dimensions out of range");
9288 return error::kNoError
;
9290 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9295 "glCompressedTexImage2D", "unknown texture target");
9296 return error::kNoError
;
9298 Texture
* texture
= texture_ref
->texture();
9299 if (texture
->IsImmutable()) {
9301 GL_INVALID_OPERATION
,
9302 "glCompressedTexImage2D", "texture is immutable");
9303 return error::kNoError
;
9306 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9307 width
, height
, 1, internal_format
) ||
9308 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9309 1, internal_format
, image_size
)) {
9310 return error::kNoError
;
9313 if (!EnsureGPUMemoryAvailable(image_size
)) {
9315 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9316 return error::kNoError
;
9319 if (texture
->IsAttachedToFramebuffer()) {
9320 framebuffer_state_
.clear_state_dirty
= true;
9323 scoped_ptr
<int8
[]> zero
;
9325 zero
.reset(new int8
[image_size
]);
9326 memset(zero
.get(), 0, image_size
);
9329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9330 glCompressedTexImage2D(
9331 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9332 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9333 if (error
== GL_NO_ERROR
) {
9334 texture_manager()->SetLevelInfo(
9335 texture_ref
, target
, level
, internal_format
,
9336 width
, height
, 1, border
, 0, 0, true);
9339 // This may be a slow command. Exit command processing to allow for
9340 // context preemption and GPU watchdog checks.
9341 ExitCommandProcessingEarly();
9342 return error::kNoError
;
9345 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9346 uint32 immediate_data_size
,
9347 const void* cmd_data
) {
9348 const gles2::cmds::CompressedTexImage2D
& c
=
9349 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9350 GLenum target
= static_cast<GLenum
>(c
.target
);
9351 GLint level
= static_cast<GLint
>(c
.level
);
9352 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9353 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9354 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9355 GLint border
= static_cast<GLint
>(c
.border
);
9356 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9357 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9358 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9359 const void* data
= NULL
;
9360 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9361 data
= GetSharedMemoryAs
<const void*>(
9362 data_shm_id
, data_shm_offset
, image_size
);
9364 return error::kOutOfBounds
;
9367 return DoCompressedTexImage2D(
9368 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9371 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9372 uint32 immediate_data_size
,
9373 const void* cmd_data
) {
9374 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9375 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9376 GLenum target
= static_cast<GLenum
>(c
.target
);
9377 GLint level
= static_cast<GLint
>(c
.level
);
9378 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9379 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9380 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9381 GLint border
= static_cast<GLint
>(c
.border
);
9382 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9384 return error::kInvalidArguments
;
9386 uint32 data_size
= bucket
->size();
9387 GLsizei imageSize
= data_size
;
9388 const void* data
= bucket
->GetData(0, data_size
);
9390 return error::kInvalidArguments
;
9392 return DoCompressedTexImage2D(
9393 target
, level
, internal_format
, width
, height
, border
,
9397 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9398 uint32 immediate_data_size
,
9399 const void* cmd_data
) {
9400 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9401 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9402 GLenum target
= static_cast<GLenum
>(c
.target
);
9403 GLint level
= static_cast<GLint
>(c
.level
);
9404 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9405 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9406 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9407 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9408 GLenum format
= static_cast<GLenum
>(c
.format
);
9409 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9411 return error::kInvalidArguments
;
9413 uint32 data_size
= bucket
->size();
9414 GLsizei imageSize
= data_size
;
9415 const void* data
= bucket
->GetData(0, data_size
);
9417 return error::kInvalidArguments
;
9419 if (!validators_
->texture_target
.IsValid(target
)) {
9421 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9422 return error::kNoError
;
9424 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9425 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9426 "glCompressedTexSubImage2D", format
, "format");
9427 return error::kNoError
;
9431 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9432 return error::kNoError
;
9436 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9437 return error::kNoError
;
9439 if (imageSize
< 0) {
9441 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9442 return error::kNoError
;
9444 DoCompressedTexSubImage2D(
9445 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9446 return error::kNoError
;
9449 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9452 GLenum internal_format
,
9459 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9460 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9461 "glCompressedTexImage3D", target
, "target");
9462 return error::kNoError
;
9464 if (!validators_
->compressed_texture_format
.IsValid(
9466 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9467 "glCompressedTexImage3D", internal_format
, "internal_format");
9468 return error::kNoError
;
9470 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9474 "glCompressedTexImage3D", "dimensions out of range");
9475 return error::kNoError
;
9477 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9482 "glCompressedTexImage3D", "unknown texture target");
9483 return error::kNoError
;
9485 Texture
* texture
= texture_ref
->texture();
9486 if (texture
->IsImmutable()) {
9488 GL_INVALID_OPERATION
,
9489 "glCompressedTexImage3D", "texture is immutable");
9490 return error::kNoError
;
9493 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9494 width
, height
, depth
, internal_format
) ||
9495 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9496 depth
, internal_format
, image_size
)) {
9497 return error::kNoError
;
9500 if (!EnsureGPUMemoryAvailable(image_size
)) {
9502 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9503 return error::kNoError
;
9506 if (texture
->IsAttachedToFramebuffer()) {
9507 framebuffer_state_
.clear_state_dirty
= true;
9510 scoped_ptr
<int8
[]> zero
;
9512 zero
.reset(new int8
[image_size
]);
9513 memset(zero
.get(), 0, image_size
);
9516 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9517 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9518 border
, image_size
, data
);
9519 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9520 if (error
== GL_NO_ERROR
) {
9521 texture_manager()->SetLevelInfo(
9522 texture_ref
, target
, level
, internal_format
,
9523 width
, height
, depth
, border
, 0, 0, true);
9526 // This may be a slow command. Exit command processing to allow for
9527 // context preemption and GPU watchdog checks.
9528 ExitCommandProcessingEarly();
9529 return error::kNoError
;
9532 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9533 uint32 immediate_data_size
, const void* cmd_data
) {
9534 if (!unsafe_es3_apis_enabled())
9535 return error::kUnknownCommand
;
9537 const gles2::cmds::CompressedTexImage3D
& c
=
9538 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9539 GLenum target
= static_cast<GLenum
>(c
.target
);
9540 GLint level
= static_cast<GLint
>(c
.level
);
9541 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9542 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9543 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9544 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9545 GLint border
= static_cast<GLint
>(c
.border
);
9546 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9547 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9548 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9549 const void* data
= NULL
;
9550 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9551 data
= GetSharedMemoryAs
<const void*>(
9552 data_shm_id
, data_shm_offset
, image_size
);
9554 return error::kOutOfBounds
;
9557 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9558 depth
, border
, image_size
, data
);
9561 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9562 uint32 immediate_data_size
, const void* cmd_data
) {
9563 if (!unsafe_es3_apis_enabled())
9564 return error::kUnknownCommand
;
9566 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9567 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9568 GLenum target
= static_cast<GLenum
>(c
.target
);
9569 GLint level
= static_cast<GLint
>(c
.level
);
9570 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9571 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9572 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9573 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9574 GLint border
= static_cast<GLint
>(c
.border
);
9575 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9577 return error::kInvalidArguments
;
9579 uint32 data_size
= bucket
->size();
9580 GLsizei imageSize
= data_size
;
9581 const void* data
= bucket
->GetData(0, data_size
);
9583 return error::kInvalidArguments
;
9585 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9586 depth
, border
, imageSize
, data
);
9589 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9590 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9591 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9592 GLsizei image_size
, const void* data
) {
9593 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9595 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9598 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9599 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9600 "glCompressedTexSubImage3D", format
, "format");
9603 if (width
< 0 || height
< 0 || depth
< 0) {
9605 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9608 if (image_size
< 0) {
9610 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9613 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9616 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9617 "unknown texture for target");
9620 Texture
* texture
= texture_ref
->texture();
9621 GLenum type
= 0, internal_format
= 0;
9622 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9623 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9624 "level does not exist");
9627 if (internal_format
!= format
) {
9628 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9629 "format does not match internal format");
9632 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9633 width
, height
, depth
, type
)) {
9634 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9638 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9639 width
, height
, depth
, format
,
9641 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9642 target
, level
, xoffset
, yoffset
,
9643 zoffset
, width
, height
, depth
,
9648 // Note: There is no need to deal with texture cleared tracking here
9649 // because the validation above means you can only get here if the level
9650 // is already a matching compressed format and in that case
9651 // CompressedTexImage3D already cleared the texture.
9652 glCompressedTexSubImage3D(
9653 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9656 // This may be a slow command. Exit command processing to allow for
9657 // context preemption and GPU watchdog checks.
9658 ExitCommandProcessingEarly();
9661 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9662 uint32 immediate_data_size
, const void* cmd_data
) {
9663 if (!unsafe_es3_apis_enabled())
9664 return error::kUnknownCommand
;
9665 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9666 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9667 GLenum target
= static_cast<GLenum
>(c
.target
);
9668 GLint level
= static_cast<GLint
>(c
.level
);
9669 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9670 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9671 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9672 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9673 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9674 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9675 GLenum format
= static_cast<GLenum
>(c
.format
);
9676 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9678 return error::kInvalidArguments
;
9680 uint32 data_size
= bucket
->size();
9681 GLsizei image_size
= data_size
;
9682 const void* data
= bucket
->GetData(0, data_size
);
9684 return error::kInvalidArguments
;
9686 DoCompressedTexSubImage3D(
9687 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9689 return error::kNoError
;
9692 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9693 const void* cmd_data
) {
9694 const gles2::cmds::TexImage2D
& c
=
9695 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9696 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9697 "width", c
.width
, "height", c
.height
);
9698 // Set as failed for now, but if it successed, this will be set to not failed.
9699 texture_state_
.tex_image_failed
= true;
9700 GLenum target
= static_cast<GLenum
>(c
.target
);
9701 GLint level
= static_cast<GLint
>(c
.level
);
9702 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9703 // for internalformat.
9704 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9705 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9706 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9707 GLint border
= static_cast<GLint
>(c
.border
);
9708 GLenum format
= static_cast<GLenum
>(c
.format
);
9709 GLenum type
= static_cast<GLenum
>(c
.type
);
9710 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9711 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9713 if (!GLES2Util::ComputeImageDataSizes(
9714 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9716 return error::kOutOfBounds
;
9718 const void* pixels
= NULL
;
9719 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9720 pixels
= GetSharedMemoryAs
<const void*>(
9721 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9723 return error::kOutOfBounds
;
9727 // For testing only. Allows us to stress the ability to respond to OOM errors.
9728 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9729 (width
* height
>= 4096 * 4096)) {
9732 "glTexImage2D", "synthetic out of memory");
9733 return error::kNoError
;
9736 TextureManager::DoTexImageArguments args
= {
9737 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
9738 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
9739 texture_manager()->ValidateAndDoTexImage(
9740 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
9742 // This may be a slow command. Exit command processing to allow for
9743 // context preemption and GPU watchdog checks.
9744 ExitCommandProcessingEarly();
9745 return error::kNoError
;
9748 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9749 const void* cmd_data
) {
9750 if (!unsafe_es3_apis_enabled())
9751 return error::kUnknownCommand
;
9753 const gles2::cmds::TexImage3D
& c
=
9754 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9755 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9756 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9757 // Set as failed for now, but if it successed, this will be set to not failed.
9758 texture_state_
.tex_image_failed
= true;
9759 GLenum target
= static_cast<GLenum
>(c
.target
);
9760 GLint level
= static_cast<GLint
>(c
.level
);
9761 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9762 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9763 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9764 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9765 GLint border
= static_cast<GLint
>(c
.border
);
9766 GLenum format
= static_cast<GLenum
>(c
.format
);
9767 GLenum type
= static_cast<GLenum
>(c
.type
);
9768 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9769 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9771 if (!GLES2Util::ComputeImageDataSizes(
9772 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9774 return error::kOutOfBounds
;
9776 const void* pixels
= NULL
;
9777 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9778 pixels
= GetSharedMemoryAs
<const void*>(
9779 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9781 return error::kOutOfBounds
;
9785 // For testing only. Allows us to stress the ability to respond to OOM errors.
9786 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9787 (width
* height
* depth
>= 4096 * 4096)) {
9790 "glTexImage3D", "synthetic out of memory");
9791 return error::kNoError
;
9794 TextureManager::DoTexImageArguments args
= {
9795 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
9796 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
9797 texture_manager()->ValidateAndDoTexImage(
9798 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
9800 // This may be a slow command. Exit command processing to allow for
9801 // context preemption and GPU watchdog checks.
9802 ExitCommandProcessingEarly();
9803 return error::kNoError
;
9806 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9815 const void * data
) {
9816 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9820 GL_INVALID_OPERATION
,
9821 "glCompressedTexSubImage2D", "unknown texture for target");
9824 Texture
* texture
= texture_ref
->texture();
9826 GLenum internal_format
= 0;
9827 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9829 GL_INVALID_OPERATION
,
9830 "glCompressedTexSubImage2D", "level does not exist.");
9833 if (internal_format
!= format
) {
9835 GL_INVALID_OPERATION
,
9836 "glCompressedTexSubImage2D", "format does not match internal format.");
9839 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
9842 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9846 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9847 width
, height
, 1, format
, image_size
) ||
9848 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9849 target
, level
, xoffset
, yoffset
, 0,
9850 width
, height
, 1, format
, texture
)) {
9855 // Note: There is no need to deal with texture cleared tracking here
9856 // because the validation above means you can only get here if the level
9857 // is already a matching compressed format and in that case
9858 // CompressedTexImage2D already cleared the texture.
9859 glCompressedTexSubImage2D(
9860 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9862 // This may be a slow command. Exit command processing to allow for
9863 // context preemption and GPU watchdog checks.
9864 ExitCommandProcessingEarly();
9868 GLint start
, GLint range
, GLint sourceRange
,
9869 GLint
* out_start
, GLint
* out_range
) {
9876 GLint end
= start
+ range
;
9877 if (end
> sourceRange
) {
9878 range
-= end
- sourceRange
;
9884 void GLES2DecoderImpl::DoCopyTexImage2D(
9887 GLenum internal_format
,
9893 DCHECK(!ShouldDeferReads());
9894 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9898 GL_INVALID_OPERATION
,
9899 "glCopyTexImage2D", "unknown texture for target");
9902 Texture
* texture
= texture_ref
->texture();
9903 if (texture
->IsImmutable()) {
9905 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9908 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9911 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9914 if (!texture_manager()->ValidateFormatAndTypeCombination(
9915 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9916 GL_UNSIGNED_BYTE
)) {
9920 // Check we have compatible formats.
9921 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9922 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9923 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9925 if ((channels_needed
& channels_exist
) != channels_needed
) {
9927 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9931 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9933 GL_INVALID_OPERATION
,
9934 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9938 uint32 estimated_size
= 0;
9939 if (!GLES2Util::ComputeImageDataSizes(
9940 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9941 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9943 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9947 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9948 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9952 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9956 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9958 GL_INVALID_OPERATION
,
9959 "glCopyTexImage2D", "source and destination textures are the same");
9963 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9967 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9968 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9969 gfx::Size size
= GetBoundReadFrameBufferSize();
9971 if (texture
->IsAttachedToFramebuffer()) {
9972 framebuffer_state_
.clear_state_dirty
= true;
9975 // Clip to size to source dimensions
9978 GLint copyWidth
= 0;
9979 GLint copyHeight
= 0;
9980 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9981 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9985 copyWidth
!= width
||
9986 copyHeight
!= height
) {
9987 // some part was clipped so clear the texture.
9988 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9989 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9991 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9994 if (copyHeight
> 0 && copyWidth
> 0) {
9995 GLint dx
= copyX
- x
;
9996 GLint dy
= copyY
- y
;
9999 ScopedModifyPixels
modify(texture_ref
);
10000 glCopyTexSubImage2D(target
, level
,
10001 destX
, destY
, copyX
, copyY
,
10002 copyWidth
, copyHeight
);
10005 ScopedModifyPixels
modify(texture_ref
);
10006 glCopyTexImage2D(target
, level
, internal_format
,
10007 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10009 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10010 if (error
== GL_NO_ERROR
) {
10011 texture_manager()->SetLevelInfo(
10012 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
10013 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
10016 // This may be a slow command. Exit command processing to allow for
10017 // context preemption and GPU watchdog checks.
10018 ExitCommandProcessingEarly();
10021 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10030 DCHECK(!ShouldDeferReads());
10031 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10033 if (!texture_ref
) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION
,
10036 "glCopyTexSubImage2D", "unknown texture for target");
10039 Texture
* texture
= texture_ref
->texture();
10042 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10043 !texture
->ValidForTexture(
10044 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10045 LOCAL_SET_GL_ERROR(
10046 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10049 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10050 LOCAL_SET_GL_ERROR(
10051 GL_INVALID_OPERATION
,
10052 "glCopyTexSubImage2D", "async upload pending for texture");
10056 // Check we have compatible formats.
10057 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10058 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10059 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10061 if (!channels_needed
||
10062 (channels_needed
& channels_exist
) != channels_needed
) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10068 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION
,
10071 "glCopySubImage2D", "can not be used with depth or stencil textures");
10075 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10079 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10080 LOCAL_SET_GL_ERROR(
10081 GL_INVALID_OPERATION
,
10082 "glCopyTexSubImage2D", "source and destination textures are the same");
10086 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10090 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10091 gfx::Size size
= GetBoundReadFrameBufferSize();
10094 GLint copyWidth
= 0;
10095 GLint copyHeight
= 0;
10096 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10097 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10099 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10100 height
!= size
.height()) {
10101 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10103 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10104 "dimensions too big");
10108 // Write all pixels in below.
10109 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10114 copyWidth
!= width
||
10115 copyHeight
!= height
) {
10116 // some part was clipped so clear the sub rect.
10117 uint32 pixels_size
= 0;
10118 if (!GLES2Util::ComputeImageDataSizes(
10119 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10121 LOCAL_SET_GL_ERROR(
10122 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10125 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10126 memset(zero
.get(), 0, pixels_size
);
10127 ScopedModifyPixels
modify(texture_ref
);
10129 target
, level
, xoffset
, yoffset
, width
, height
,
10130 format
, type
, zero
.get());
10133 if (copyHeight
> 0 && copyWidth
> 0) {
10134 GLint dx
= copyX
- x
;
10135 GLint dy
= copyY
- y
;
10136 GLint destX
= xoffset
+ dx
;
10137 GLint destY
= yoffset
+ dy
;
10138 ScopedModifyPixels
modify(texture_ref
);
10139 glCopyTexSubImage2D(target
, level
,
10140 destX
, destY
, copyX
, copyY
,
10141 copyWidth
, copyHeight
);
10144 // This may be a slow command. Exit command processing to allow for
10145 // context preemption and GPU watchdog checks.
10146 ExitCommandProcessingEarly();
10149 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10150 error::Error
* error
,
10151 const char* function_name
,
10160 const void * data
) {
10161 (*error
) = error::kNoError
;
10162 if (!validators_
->texture_target
.IsValid(target
)) {
10163 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10167 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10174 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10176 if (!texture_ref
) {
10177 LOCAL_SET_GL_ERROR(
10178 GL_INVALID_OPERATION
,
10179 function_name
, "unknown texture for target");
10182 Texture
* texture
= texture_ref
->texture();
10183 GLenum current_type
= 0;
10184 GLenum internal_format
= 0;
10185 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10186 LOCAL_SET_GL_ERROR(
10187 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10190 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10191 function_name
, format
, type
, internal_format
, level
)) {
10194 if (type
!= current_type
) {
10195 LOCAL_SET_GL_ERROR(
10196 GL_INVALID_OPERATION
,
10197 function_name
, "type does not match type of texture.");
10200 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10201 LOCAL_SET_GL_ERROR(
10202 GL_INVALID_OPERATION
,
10203 function_name
, "async upload pending for texture");
10206 if (!texture
->ValidForTexture(
10207 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10208 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10211 if ((GLES2Util::GetChannelsForFormat(format
) &
10212 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10213 LOCAL_SET_GL_ERROR(
10214 GL_INVALID_OPERATION
,
10215 function_name
, "can not supply data for depth or stencil textures");
10218 if (data
== NULL
) {
10219 (*error
) = error::kOutOfBounds
;
10225 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10234 const void * data
) {
10235 error::Error error
= error::kNoError
;
10236 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10237 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10240 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10242 Texture
* texture
= texture_ref
->texture();
10243 GLsizei tex_width
= 0;
10244 GLsizei tex_height
= 0;
10245 bool ok
= texture
->GetLevelSize(
10246 target
, level
, &tex_width
, &tex_height
, nullptr);
10248 if (xoffset
!= 0 || yoffset
!= 0 ||
10249 width
!= tex_width
|| height
!= tex_height
) {
10250 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10252 LOCAL_SET_GL_ERROR(
10253 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
10254 return error::kNoError
;
10256 ScopedTextureUploadTimer
timer(&texture_state_
);
10258 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10259 return error::kNoError
;
10262 if (!texture_state_
.texsubimage_faster_than_teximage
&&
10263 !texture
->IsImmutable() &&
10264 !texture
->HasImages()) {
10265 ScopedTextureUploadTimer
timer(&texture_state_
);
10266 GLenum internal_format
;
10268 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10269 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10272 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10274 ScopedTextureUploadTimer
timer(&texture_state_
);
10276 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10278 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10280 // This may be a slow command. Exit command processing to allow for
10281 // context preemption and GPU watchdog checks.
10282 ExitCommandProcessingEarly();
10283 return error::kNoError
;
10286 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10287 const void* cmd_data
) {
10288 const gles2::cmds::TexSubImage2D
& c
=
10289 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10290 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10291 "width", c
.width
, "height", c
.height
);
10292 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10293 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10294 return error::kNoError
;
10296 GLenum target
= static_cast<GLenum
>(c
.target
);
10297 GLint level
= static_cast<GLint
>(c
.level
);
10298 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10299 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10300 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10301 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10302 GLenum format
= static_cast<GLenum
>(c
.format
);
10303 GLenum type
= static_cast<GLenum
>(c
.type
);
10305 if (!GLES2Util::ComputeImageDataSizes(
10306 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10308 return error::kOutOfBounds
;
10310 const void* pixels
= GetSharedMemoryAs
<const void*>(
10311 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10312 return DoTexSubImage2D(
10313 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10316 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
10327 const void * data
) {
10328 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10330 if (!texture_ref
) {
10331 LOCAL_SET_GL_ERROR(
10332 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
10335 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10336 ScopedTextureUploadTimer
timer(&texture_state_
);
10337 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10338 depth
, format
, type
, data
);
10339 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10340 if (error
== GL_NO_ERROR
) {
10341 // TODO(zmo): This is not 100% correct because only part of the level
10342 // image is cleared.
10343 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10346 // This may be a slow command. Exit command processing to allow for
10347 // context preemption and GPU watchdog checks.
10348 ExitCommandProcessingEarly();
10349 return error::kNoError
;
10352 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10353 const void* cmd_data
) {
10354 if (!unsafe_es3_apis_enabled())
10355 return error::kUnknownCommand
;
10357 const gles2::cmds::TexSubImage3D
& c
=
10358 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10359 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10360 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10361 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10362 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
10363 return error::kNoError
;
10365 GLenum target
= static_cast<GLenum
>(c
.target
);
10366 GLint level
= static_cast<GLint
>(c
.level
);
10367 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10368 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10369 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10370 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10371 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10372 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10373 GLenum format
= static_cast<GLenum
>(c
.format
);
10374 GLenum type
= static_cast<GLenum
>(c
.type
);
10376 if (!GLES2Util::ComputeImageDataSizes(
10377 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10379 return error::kOutOfBounds
;
10381 const void* pixels
= GetSharedMemoryAs
<const void*>(
10382 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10383 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
10384 height
, depth
, format
, type
, pixels
);
10387 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10388 uint32 immediate_data_size
,
10389 const void* cmd_data
) {
10390 const gles2::cmds::GetVertexAttribPointerv
& c
=
10391 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10392 GLuint index
= static_cast<GLuint
>(c
.index
);
10393 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10394 typedef cmds::GetVertexAttribPointerv::Result Result
;
10395 Result
* result
= GetSharedMemoryAs
<Result
*>(
10396 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10398 return error::kOutOfBounds
;
10400 // Check that the client initialized the result.
10401 if (result
->size
!= 0) {
10402 return error::kInvalidArguments
;
10404 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10405 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10406 "glGetVertexAttribPointerv", pname
, "pname");
10407 return error::kNoError
;
10409 if (index
>= group_
->max_vertex_attribs()) {
10410 LOCAL_SET_GL_ERROR(
10411 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10412 return error::kNoError
;
10414 result
->SetNumResults(1);
10415 *result
->GetData() =
10416 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10417 return error::kNoError
;
10421 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10422 GLint fake_location
,
10425 error::Error
* error
,
10426 GLint
* real_location
,
10427 GLuint
* service_id
,
10428 SizedResult
<T
>** result_pointer
,
10429 GLenum
* result_type
,
10430 GLsizei
* result_size
) {
10432 DCHECK(service_id
);
10433 DCHECK(result_pointer
);
10434 DCHECK(result_type
);
10435 DCHECK(result_size
);
10436 DCHECK(real_location
);
10437 *error
= error::kNoError
;
10438 // Make sure we have enough room for the result on failure.
10439 SizedResult
<T
>* result
;
10440 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10441 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10443 *error
= error::kOutOfBounds
;
10446 *result_pointer
= result
;
10447 // Set the result size to 0 so the client does not have to check for success.
10448 result
->SetNumResults(0);
10449 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10453 if (!program
->IsValid()) {
10454 // Program was not linked successfully. (ie, glLinkProgram)
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10459 *service_id
= program
->service_id();
10460 GLint array_index
= -1;
10461 const Program::UniformInfo
* uniform_info
=
10462 program
->GetUniformInfoByFakeLocation(
10463 fake_location
, real_location
, &array_index
);
10464 if (!uniform_info
) {
10465 // No such location.
10466 LOCAL_SET_GL_ERROR(
10467 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10470 GLenum type
= uniform_info
->type
;
10471 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10472 if (num_elements
== 0) {
10473 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10476 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10477 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10479 *error
= error::kOutOfBounds
;
10482 result
->SetNumResults(num_elements
);
10483 *result_size
= num_elements
* sizeof(T
);
10484 *result_type
= type
;
10488 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10489 const void* cmd_data
) {
10490 const gles2::cmds::GetUniformiv
& c
=
10491 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10492 GLuint program
= c
.program
;
10493 GLint fake_location
= c
.location
;
10495 GLenum result_type
;
10496 GLsizei result_size
;
10497 GLint real_location
= -1;
10499 cmds::GetUniformiv::Result
* result
;
10500 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10501 c
.params_shm_offset
, &error
, &real_location
,
10502 &service_id
, &result
, &result_type
,
10505 service_id
, real_location
, result
->GetData());
10510 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10511 const void* cmd_data
) {
10512 if (!unsafe_es3_apis_enabled())
10513 return error::kUnknownCommand
;
10515 const gles2::cmds::GetUniformuiv
& c
=
10516 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10517 GLuint program
= c
.program
;
10518 GLint fake_location
= c
.location
;
10520 GLenum result_type
;
10521 GLsizei result_size
;
10522 GLint real_location
= -1;
10524 cmds::GetUniformuiv::Result
* result
;
10525 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10526 c
.params_shm_offset
, &error
, &real_location
,
10527 &service_id
, &result
, &result_type
,
10530 service_id
, real_location
, result
->GetData());
10535 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10536 const void* cmd_data
) {
10537 const gles2::cmds::GetUniformfv
& c
=
10538 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10539 GLuint program
= c
.program
;
10540 GLint fake_location
= c
.location
;
10542 GLint real_location
= -1;
10544 cmds::GetUniformfv::Result
* result
;
10545 GLenum result_type
;
10546 GLsizei result_size
;
10547 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10548 c
.params_shm_offset
, &error
, &real_location
,
10549 &service_id
, &result
, &result_type
,
10551 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10552 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10553 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10554 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10555 glGetUniformiv(service_id
, real_location
, temp
.get());
10556 GLfloat
* dst
= result
->GetData();
10557 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10558 dst
[ii
] = (temp
[ii
] != 0);
10561 glGetUniformfv(service_id
, real_location
, result
->GetData());
10567 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10568 uint32 immediate_data_size
,
10569 const void* cmd_data
) {
10570 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10571 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10572 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10573 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10574 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10575 Result
* result
= GetSharedMemoryAs
<Result
*>(
10576 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10578 return error::kOutOfBounds
;
10580 // Check that the client initialized the result.
10581 if (result
->success
!= 0) {
10582 return error::kInvalidArguments
;
10584 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10585 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10586 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10587 return error::kNoError
;
10589 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10590 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10591 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10592 return error::kNoError
;
10595 result
->success
= 1; // true
10597 GLint range
[2] = { 0, 0 };
10598 GLint precision
= 0;
10599 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10601 result
->min_range
= range
[0];
10602 result
->max_range
= range
[1];
10603 result
->precision
= precision
;
10605 return error::kNoError
;
10608 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10609 uint32 immediate_data_size
,
10610 const void* cmd_data
) {
10611 const gles2::cmds::GetAttachedShaders
& c
=
10612 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10613 uint32 result_size
= c
.result_size
;
10614 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10615 Program
* program
= GetProgramInfoNotShader(
10616 program_id
, "glGetAttachedShaders");
10618 return error::kNoError
;
10620 typedef cmds::GetAttachedShaders::Result Result
;
10621 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10622 Result
* result
= GetSharedMemoryAs
<Result
*>(
10623 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10625 return error::kOutOfBounds
;
10627 // Check that the client initialized the result.
10628 if (result
->size
!= 0) {
10629 return error::kInvalidArguments
;
10632 glGetAttachedShaders(
10633 program
->service_id(), max_count
, &count
, result
->GetData());
10634 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10635 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10636 &result
->GetData()[ii
])) {
10638 return error::kGenericError
;
10641 result
->SetNumResults(count
);
10642 return error::kNoError
;
10645 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10646 uint32 immediate_data_size
,
10647 const void* cmd_data
) {
10648 const gles2::cmds::GetActiveUniform
& c
=
10649 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10650 GLuint program_id
= c
.program
;
10651 GLuint index
= c
.index
;
10652 uint32 name_bucket_id
= c
.name_bucket_id
;
10653 typedef cmds::GetActiveUniform::Result Result
;
10654 Result
* result
= GetSharedMemoryAs
<Result
*>(
10655 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10657 return error::kOutOfBounds
;
10659 // Check that the client initialized the result.
10660 if (result
->success
!= 0) {
10661 return error::kInvalidArguments
;
10663 Program
* program
= GetProgramInfoNotShader(
10664 program_id
, "glGetActiveUniform");
10666 return error::kNoError
;
10668 const Program::UniformInfo
* uniform_info
=
10669 program
->GetUniformInfo(index
);
10670 if (!uniform_info
) {
10671 LOCAL_SET_GL_ERROR(
10672 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10673 return error::kNoError
;
10675 result
->success
= 1; // true.
10676 result
->size
= uniform_info
->size
;
10677 result
->type
= uniform_info
->type
;
10678 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10679 bucket
->SetFromString(uniform_info
->name
.c_str());
10680 return error::kNoError
;
10683 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10684 uint32 immediate_data_size
, const void* cmd_data
) {
10685 if (!unsafe_es3_apis_enabled())
10686 return error::kUnknownCommand
;
10687 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10688 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10689 GLuint program_id
= c
.program
;
10690 GLuint index
= static_cast<GLuint
>(c
.index
);
10691 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10692 Program
* program
= GetProgramInfoNotShader(
10693 program_id
, "glGetActiveUniformBlockiv");
10695 return error::kNoError
;
10697 GLuint service_id
= program
->service_id();
10698 GLint link_status
= GL_FALSE
;
10699 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10700 if (link_status
!= GL_TRUE
) {
10701 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10702 "glGetActiveActiveUniformBlockiv", "program not linked");
10703 return error::kNoError
;
10705 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10706 GLsizei num_values
= 1;
10707 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10709 glGetActiveUniformBlockiv(
10710 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10711 GLenum error
= glGetError();
10712 if (error
!= GL_NO_ERROR
) {
10713 // Assume this will the same error if calling with pname.
10714 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10715 return error::kNoError
;
10717 num_values
= static_cast<GLsizei
>(num
);
10719 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10720 Result
* result
= GetSharedMemoryAs
<Result
*>(
10721 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10722 GLint
* params
= result
? result
->GetData() : NULL
;
10723 if (params
== NULL
) {
10724 return error::kOutOfBounds
;
10726 // Check that the client initialized the result.
10727 if (result
->size
!= 0) {
10728 return error::kInvalidArguments
;
10730 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10731 GLenum error
= glGetError();
10732 if (error
== GL_NO_ERROR
) {
10733 result
->SetNumResults(num_values
);
10735 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10737 return error::kNoError
;
10740 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10741 uint32 immediate_data_size
, const void* cmd_data
) {
10742 if (!unsafe_es3_apis_enabled())
10743 return error::kUnknownCommand
;
10744 const gles2::cmds::GetActiveUniformBlockName
& c
=
10745 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10746 GLuint program_id
= c
.program
;
10747 GLuint index
= c
.index
;
10748 uint32 name_bucket_id
= c
.name_bucket_id
;
10749 typedef cmds::GetActiveUniformBlockName::Result Result
;
10750 Result
* result
= GetSharedMemoryAs
<Result
*>(
10751 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10753 return error::kOutOfBounds
;
10755 // Check that the client initialized the result.
10756 if (*result
!= 0) {
10757 return error::kInvalidArguments
;
10759 Program
* program
= GetProgramInfoNotShader(
10760 program_id
, "glGetActiveUniformBlockName");
10762 return error::kNoError
;
10764 GLuint service_id
= program
->service_id();
10765 GLint link_status
= GL_FALSE
;
10766 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10767 if (link_status
!= GL_TRUE
) {
10768 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10769 "glGetActiveActiveUniformBlockName", "program not linked");
10770 return error::kNoError
;
10772 GLint max_length
= 0;
10774 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10775 // Increase one so &buffer[0] is always valid.
10776 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10777 std::vector
<char> buffer(buf_size
);
10778 GLsizei length
= 0;
10779 glGetActiveUniformBlockName(
10780 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10783 return error::kNoError
;
10786 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10787 DCHECK_GT(buf_size
, length
);
10788 DCHECK_EQ(0, buffer
[length
]);
10789 bucket
->SetFromString(&buffer
[0]);
10790 return error::kNoError
;
10793 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10794 uint32 immediate_data_size
, const void* cmd_data
) {
10795 if (!unsafe_es3_apis_enabled())
10796 return error::kUnknownCommand
;
10797 const gles2::cmds::GetActiveUniformsiv
& c
=
10798 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10799 GLuint program_id
= c
.program
;
10800 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10801 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10803 return error::kInvalidArguments
;
10805 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10806 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10807 typedef cmds::GetActiveUniformsiv::Result Result
;
10808 Result
* result
= GetSharedMemoryAs
<Result
*>(
10809 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10810 GLint
* params
= result
? result
->GetData() : NULL
;
10811 if (params
== NULL
) {
10812 return error::kOutOfBounds
;
10814 // Check that the client initialized the result.
10815 if (result
->size
!= 0) {
10816 return error::kInvalidArguments
;
10818 Program
* program
= GetProgramInfoNotShader(
10819 program_id
, "glGetActiveUniformsiv");
10821 return error::kNoError
;
10823 GLuint service_id
= program
->service_id();
10824 GLint link_status
= GL_FALSE
;
10825 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10826 if (link_status
!= GL_TRUE
) {
10827 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10828 "glGetActiveUniformsiv", "program not linked");
10829 return error::kNoError
;
10831 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10832 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10833 GLenum error
= glGetError();
10834 if (error
== GL_NO_ERROR
) {
10835 result
->SetNumResults(count
);
10837 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10839 return error::kNoError
;
10842 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10843 const void* cmd_data
) {
10844 const gles2::cmds::GetActiveAttrib
& c
=
10845 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10846 GLuint program_id
= c
.program
;
10847 GLuint index
= c
.index
;
10848 uint32 name_bucket_id
= c
.name_bucket_id
;
10849 typedef cmds::GetActiveAttrib::Result Result
;
10850 Result
* result
= GetSharedMemoryAs
<Result
*>(
10851 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10853 return error::kOutOfBounds
;
10855 // Check that the client initialized the result.
10856 if (result
->success
!= 0) {
10857 return error::kInvalidArguments
;
10859 Program
* program
= GetProgramInfoNotShader(
10860 program_id
, "glGetActiveAttrib");
10862 return error::kNoError
;
10864 const Program::VertexAttrib
* attrib_info
=
10865 program
->GetAttribInfo(index
);
10866 if (!attrib_info
) {
10867 LOCAL_SET_GL_ERROR(
10868 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10869 return error::kNoError
;
10871 result
->success
= 1; // true.
10872 result
->size
= attrib_info
->size
;
10873 result
->type
= attrib_info
->type
;
10874 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10875 bucket
->SetFromString(attrib_info
->name
.c_str());
10876 return error::kNoError
;
10879 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10880 const void* cmd_data
) {
10881 #if 1 // No binary shader support.
10882 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10883 return error::kNoError
;
10885 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10887 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10888 return error::kNoError
;
10890 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10892 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10893 return error::kNoError
;
10896 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10897 return error::kOutOfBounds
;
10899 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10900 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10901 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10902 const void* binary
= GetSharedMemoryAs
<const void*>(
10903 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10904 if (shaders
== NULL
|| binary
== NULL
) {
10905 return error::kOutOfBounds
;
10907 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10908 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10909 Shader
* shader
= GetShader(shaders
[ii
]);
10911 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10912 return error::kNoError
;
10914 service_ids
[ii
] = shader
->service_id();
10916 // TODO(gman): call glShaderBinary
10917 return error::kNoError
;
10921 void GLES2DecoderImpl::DoSwapBuffers() {
10922 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10924 int this_frame_number
= frame_number_
++;
10925 // TRACE_EVENT for gpu tests:
10926 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10927 TRACE_EVENT_SCOPE_THREAD
,
10928 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10929 "width", (is_offscreen
? offscreen_size_
.width() :
10930 surface_
->GetSize().width()));
10931 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10932 "offscreen", is_offscreen
,
10933 "frame", this_frame_number
);
10935 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10938 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10939 "gpu_toplevel", "SwapBuffer");
10942 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10945 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10946 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10947 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10950 // If offscreen then don't actually SwapBuffers to the display. Just copy
10951 // the rendered frame to another frame buffer.
10952 if (is_offscreen
) {
10953 TRACE_EVENT2("gpu", "Offscreen",
10954 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10955 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10956 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10957 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10959 if (workarounds().needs_offscreen_buffer_workaround
) {
10960 offscreen_saved_frame_buffer_
->Create();
10964 // Allocate the offscreen saved color texture.
10965 DCHECK(offscreen_saved_color_format_
);
10966 offscreen_saved_color_texture_
->AllocateStorage(
10967 offscreen_size_
, offscreen_saved_color_format_
, false);
10969 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10970 offscreen_saved_color_texture_
.get());
10971 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10972 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10973 GL_FRAMEBUFFER_COMPLETE
) {
10974 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10975 << "because offscreen saved FBO was incomplete.";
10976 MarkContextLost(error::kUnknown
);
10977 group_
->LoseContexts(error::kUnknown
);
10981 // Clear the offscreen color texture.
10982 // TODO(piman): Is this still necessary?
10984 ScopedFrameBufferBinder
binder(this,
10985 offscreen_saved_frame_buffer_
->id());
10986 glClearColor(0, 0, 0, 0);
10987 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10988 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10989 glClear(GL_COLOR_BUFFER_BIT
);
10990 RestoreClearState();
10994 UpdateParentTextureInfo();
10997 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10999 ScopedGLErrorSuppressor
suppressor(
11000 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11002 if (IsOffscreenBufferMultisampled()) {
11003 // For multisampled buffers, resolve the frame buffer.
11004 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11006 ScopedFrameBufferBinder
binder(this,
11007 offscreen_target_frame_buffer_
->id());
11009 if (offscreen_target_buffer_preserved_
) {
11010 // Copy the target frame buffer to the saved offscreen texture.
11011 offscreen_saved_color_texture_
->Copy(
11012 offscreen_saved_color_texture_
->size(),
11013 offscreen_saved_color_format_
);
11015 // Flip the textures in the parent context via the texture manager.
11016 if (!!offscreen_saved_color_texture_info_
.get())
11017 offscreen_saved_color_texture_info_
->texture()->
11018 SetServiceId(offscreen_target_color_texture_
->id());
11020 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11021 offscreen_target_frame_buffer_
->AttachRenderTexture(
11022 offscreen_target_color_texture_
.get());
11025 // Ensure the side effects of the copy are visible to the parent
11026 // context. There is no need to do this for ANGLE because it uses a
11027 // single D3D device for all contexts.
11028 if (!feature_info_
->gl_version_info().is_angle
)
11032 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11033 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11034 if (!CheckResetStatus()) {
11035 MarkContextLost(error::kUnknown
);
11036 group_
->LoseContexts(error::kUnknown
);
11041 // This may be a slow command. Exit command processing to allow for
11042 // context preemption and GPU watchdog checks.
11043 ExitCommandProcessingEarly();
11046 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11047 context_
->SetSwapInterval(interval
);
11050 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11051 uint32 immediate_data_size
,
11052 const void* cmd_data
) {
11053 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11054 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11055 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11056 if (!bucket
|| bucket
->size() == 0) {
11057 return error::kInvalidArguments
;
11059 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11060 Result
* result
= GetSharedMemoryAs
<Result
*>(
11061 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11063 return error::kOutOfBounds
;
11065 // Check that the client initialized the result.
11066 if (*result
!= 0) {
11067 return error::kInvalidArguments
;
11069 std::string feature_str
;
11070 if (!bucket
->GetAsString(&feature_str
)) {
11071 return error::kInvalidArguments
;
11074 // TODO(gman): make this some kind of table to function pointer thingy.
11075 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11076 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11077 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11078 buffer_manager()->set_allow_fixed_attribs(true);
11079 // TODO(gman): decide how to remove the need for this const_cast.
11080 // I could make validators_ non const but that seems bad as this is the only
11081 // place it is needed. I could make some special friend class of validators
11082 // just to allow this to set them. That seems silly. I could refactor this
11083 // code to use the extension mechanism or the initialization attributes to
11084 // turn this feature on. Given that the only real point of this is to make
11085 // the conformance tests pass and given that there is lots of real work that
11086 // needs to be done it seems like refactoring for one to one of those
11087 // methods is a very low priority.
11088 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11089 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
11090 force_webgl_glsl_validation_
= true;
11091 InitializeShaderTranslator();
11093 return error::kNoError
;
11096 *result
= 1; // true.
11097 return error::kNoError
;
11100 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11101 uint32 immediate_data_size
,
11102 const void* cmd_data
) {
11103 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11104 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11106 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11107 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11108 info
->Initialize(disallowed_features_
);
11109 bucket
->SetFromString(info
->extensions().c_str());
11110 return error::kNoError
;
11113 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11114 uint32 immediate_data_size
,
11115 const void* cmd_data
) {
11116 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11117 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11118 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11119 if (!bucket
|| bucket
->size() == 0) {
11120 return error::kInvalidArguments
;
11122 std::string feature_str
;
11123 if (!bucket
->GetAsString(&feature_str
)) {
11124 return error::kInvalidArguments
;
11127 bool desire_webgl_glsl_validation
=
11128 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
11129 bool desire_standard_derivatives
= false;
11130 bool desire_frag_depth
= false;
11131 bool desire_draw_buffers
= false;
11132 bool desire_shader_texture_lod
= false;
11133 if (force_webgl_glsl_validation_
) {
11134 desire_standard_derivatives
=
11135 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11136 desire_frag_depth
=
11137 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11138 desire_draw_buffers
=
11139 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11140 desire_shader_texture_lod
=
11141 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11144 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
11145 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11146 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11147 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
11148 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
11149 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11150 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11151 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11152 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11153 InitializeShaderTranslator();
11156 UpdateCapabilities();
11158 return error::kNoError
;
11161 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11162 uint32 immediate_data_size
,
11163 const void* cmd_data
) {
11164 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11165 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11166 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11167 uint32 bucket_id
= c
.bucket_id
;
11168 Bucket
* bucket
= CreateBucket(bucket_id
);
11169 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11170 Program
* program
= NULL
;
11171 program
= GetProgram(program_id
);
11172 if (!program
|| !program
->IsValid()) {
11173 return error::kNoError
;
11175 program
->GetProgramInfo(program_manager(), bucket
);
11176 return error::kNoError
;
11179 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11180 uint32 immediate_data_size
, const void* cmd_data
) {
11181 if (!unsafe_es3_apis_enabled())
11182 return error::kUnknownCommand
;
11183 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11184 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11185 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11186 uint32 bucket_id
= c
.bucket_id
;
11187 Bucket
* bucket
= CreateBucket(bucket_id
);
11188 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11189 Program
* program
= NULL
;
11190 program
= GetProgram(program_id
);
11191 if (!program
|| !program
->IsValid()) {
11192 return error::kNoError
;
11194 program
->GetUniformBlocks(bucket
);
11195 return error::kNoError
;
11198 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11199 uint32 immediate_data_size
, const void* cmd_data
) {
11200 if (!unsafe_es3_apis_enabled())
11201 return error::kUnknownCommand
;
11202 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11203 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11204 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11205 uint32 bucket_id
= c
.bucket_id
;
11206 Bucket
* bucket
= CreateBucket(bucket_id
);
11207 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11208 Program
* program
= NULL
;
11209 program
= GetProgram(program_id
);
11210 if (!program
|| !program
->IsValid()) {
11211 return error::kNoError
;
11213 program
->GetUniformsES3(bucket
);
11214 return error::kNoError
;
11217 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11218 uint32 immediate_data_size
,
11219 const void* cmd_data
) {
11220 if (!unsafe_es3_apis_enabled())
11221 return error::kUnknownCommand
;
11222 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11223 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11224 GLuint program_id
= c
.program
;
11225 GLuint index
= c
.index
;
11226 uint32 name_bucket_id
= c
.name_bucket_id
;
11227 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11228 Result
* result
= GetSharedMemoryAs
<Result
*>(
11229 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11231 return error::kOutOfBounds
;
11233 // Check that the client initialized the result.
11234 if (result
->success
!= 0) {
11235 return error::kInvalidArguments
;
11237 Program
* program
= GetProgramInfoNotShader(
11238 program_id
, "glGetTransformFeedbackVarying");
11240 return error::kNoError
;
11242 GLuint service_id
= program
->service_id();
11243 GLint link_status
= GL_FALSE
;
11244 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11245 if (link_status
!= GL_TRUE
) {
11246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11247 "glGetTransformFeedbackVarying", "program not linked");
11248 return error::kNoError
;
11250 GLint max_length
= 0;
11252 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11253 max_length
= std::max(1, max_length
);
11254 std::vector
<char> buffer(max_length
);
11255 GLsizei length
= 0;
11258 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11259 glGetTransformFeedbackVarying(
11260 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11261 GLenum error
= glGetError();
11262 if (error
!= GL_NO_ERROR
) {
11263 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11264 return error::kNoError
;
11266 result
->success
= 1; // true.
11267 result
->size
= static_cast<int32_t>(size
);
11268 result
->type
= static_cast<uint32_t>(type
);
11269 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11270 DCHECK(length
>= 0 && length
< max_length
);
11271 buffer
[length
] = '\0'; // Just to be safe.
11272 bucket
->SetFromString(&buffer
[0]);
11273 return error::kNoError
;
11276 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11277 uint32 immediate_data_size
, const void* cmd_data
) {
11278 if (!unsafe_es3_apis_enabled())
11279 return error::kUnknownCommand
;
11280 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11281 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11283 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11284 uint32 bucket_id
= c
.bucket_id
;
11285 Bucket
* bucket
= CreateBucket(bucket_id
);
11286 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11287 Program
* program
= NULL
;
11288 program
= GetProgram(program_id
);
11289 if (!program
|| !program
->IsValid()) {
11290 return error::kNoError
;
11292 program
->GetTransformFeedbackVaryings(bucket
);
11293 return error::kNoError
;
11296 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11297 return context_lost_reason_
;
11300 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11301 GLenum reset_status
) const {
11302 switch (reset_status
) {
11304 // TODO(kbr): improve the precision of the error code in this case.
11305 // Consider delegating to context for error code if MakeCurrent fails.
11306 return error::kUnknown
;
11307 case GL_GUILTY_CONTEXT_RESET_ARB
:
11308 return error::kGuilty
;
11309 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11310 return error::kInnocent
;
11311 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11312 return error::kUnknown
;
11316 return error::kUnknown
;
11319 bool GLES2DecoderImpl::WasContextLost() const {
11320 return context_was_lost_
;
11323 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11324 return WasContextLost() && reset_by_robustness_extension_
;
11327 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11328 // Only lose the context once.
11329 if (WasContextLost())
11332 // Don't make GL calls in here, the context might not be current.
11333 context_lost_reason_
= reason
;
11334 current_decoder_error_
= error::kLostContext
;
11335 context_was_lost_
= true;
11337 // Work around issues with recovery by allowing a new GPU process to launch.
11338 if (workarounds().exit_on_context_lost
&& allow_exit_
) {
11339 LOG(ERROR
) << "Exiting GPU process because some drivers cannot recover"
11340 << " from problems.";
11341 #if defined(OS_WIN)
11342 base::win::SetShouldCrashOnProcessDetach(false);
11348 bool GLES2DecoderImpl::CheckResetStatus() {
11349 DCHECK(!WasContextLost());
11350 DCHECK(context_
->IsCurrent(NULL
));
11352 if (IsRobustnessSupported()) {
11353 // If the reason for the call was a GL error, we can try to determine the
11354 // reset status more accurately.
11355 GLenum driver_status
= glGetGraphicsResetStatusARB();
11356 if (driver_status
== GL_NO_ERROR
)
11359 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11360 << " context lost via ARB/EXT_robustness. Reset status = "
11361 << GLES2Util::GetStringEnum(driver_status
);
11363 // Don't pretend we know which client was responsible.
11364 if (workarounds().use_virtualized_gl_contexts
)
11365 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11367 switch (driver_status
) {
11368 case GL_GUILTY_CONTEXT_RESET_ARB
:
11369 MarkContextLost(error::kGuilty
);
11371 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11372 MarkContextLost(error::kInnocent
);
11374 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11375 MarkContextLost(error::kUnknown
);
11381 reset_by_robustness_extension_
= true;
11387 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11388 uint32 immediate_data_size
,
11389 const void* cmd_data
) {
11390 return error::kUnknownCommand
;
11393 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11394 uint32 immediate_data_size
,
11395 const void* cmd_data
) {
11396 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11397 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11398 uint32 sync_point
= c
.sync_point
;
11399 if (wait_sync_point_callback_
.is_null())
11400 return error::kNoError
;
11402 return wait_sync_point_callback_
.Run(sync_point
) ?
11403 error::kNoError
: error::kDeferCommandUntilLater
;
11406 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11407 uint32 immediate_data_size
,
11408 const void* cmd_data
) {
11409 if (surface_
->DeferDraws())
11410 return error::kDeferCommandUntilLater
;
11411 if (!surface_
->SetBackbufferAllocation(false))
11412 return error::kLostContext
;
11413 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11414 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11415 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11416 return error::kNoError
;
11419 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11420 GLsizei n
, const GLuint
* client_ids
) {
11421 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11422 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11426 query_manager_
->GenQueries(n
, client_ids
);
11430 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11431 GLsizei n
, const GLuint
* client_ids
) {
11432 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11433 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
11434 if (query
&& !query
->IsDeleted()) {
11435 ContextState::QueryMap::iterator it
=
11436 state_
.current_queries
.find(query
->target());
11437 if (it
!= state_
.current_queries
.end())
11438 state_
.current_queries
.erase(it
);
11440 query
->Destroy(true);
11442 query_manager_
->RemoveQuery(client_ids
[ii
]);
11446 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11447 if (query_manager_
.get() == NULL
) {
11450 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11451 current_decoder_error_
= error::kOutOfBounds
;
11453 return query_manager_
->HavePendingQueries();
11456 // Note that if there are no pending readpixels right now,
11457 // this function will call the callback immediately.
11458 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11459 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11460 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11466 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11467 while (!pending_readpixel_fences_
.empty() &&
11468 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
11469 std::vector
<base::Closure
> callbacks
=
11470 pending_readpixel_fences_
.front()->callbacks
;
11471 pending_readpixel_fences_
.pop();
11472 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11473 callbacks
[i
].Run();
11478 bool GLES2DecoderImpl::HasMoreIdleWork() {
11479 return !pending_readpixel_fences_
.empty() ||
11480 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11483 void GLES2DecoderImpl::PerformIdleWork() {
11484 ProcessPendingReadPixels();
11485 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11487 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11488 ProcessFinishedAsyncTransfers();
11491 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11492 const void* cmd_data
) {
11493 const gles2::cmds::BeginQueryEXT
& c
=
11494 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11495 GLenum target
= static_cast<GLenum
>(c
.target
);
11496 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11497 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11498 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11501 case GL_COMMANDS_ISSUED_CHROMIUM
:
11502 case GL_LATENCY_QUERY_CHROMIUM
:
11503 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11504 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11505 case GL_GET_ERROR_QUERY_CHROMIUM
:
11507 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11508 if (!features().chromium_sync_query
) {
11509 LOCAL_SET_GL_ERROR(
11510 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11511 "not enabled for commands completed queries");
11512 return error::kNoError
;
11516 if (!features().occlusion_query_boolean
) {
11517 LOCAL_SET_GL_ERROR(
11518 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11519 "not enabled for occlusion queries");
11520 return error::kNoError
;
11525 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
11526 LOCAL_SET_GL_ERROR(
11527 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11528 return error::kNoError
;
11531 if (client_id
== 0) {
11532 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11533 return error::kNoError
;
11536 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11538 if (!query_manager_
->IsValidQuery(client_id
)) {
11539 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11541 "id not made by glGenQueriesEXT");
11542 return error::kNoError
;
11544 query
= query_manager_
->CreateQuery(
11545 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11548 if (query
->target() != target
) {
11549 LOCAL_SET_GL_ERROR(
11550 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11551 return error::kNoError
;
11552 } else if (query
->shm_id() != sync_shm_id
||
11553 query
->shm_offset() != sync_shm_offset
) {
11554 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11555 return error::kInvalidArguments
;
11558 if (!query_manager_
->BeginQuery(query
)) {
11559 return error::kOutOfBounds
;
11562 state_
.current_queries
[target
] = query
;
11563 return error::kNoError
;
11566 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11567 const void* cmd_data
) {
11568 const gles2::cmds::EndQueryEXT
& c
=
11569 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11570 GLenum target
= static_cast<GLenum
>(c
.target
);
11571 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11572 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
11574 if (it
== state_
.current_queries
.end()) {
11575 LOCAL_SET_GL_ERROR(
11576 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11577 return error::kNoError
;
11580 QueryManager::Query
* query
= it
->second
.get();
11581 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11582 return error::kOutOfBounds
;
11585 query_manager_
->ProcessPendingTransferQueries();
11587 state_
.current_queries
.erase(it
);
11588 return error::kNoError
;
11591 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11592 GLsizei n
, const GLuint
* client_ids
) {
11593 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11594 if (GetVertexAttribManager(client_ids
[ii
])) {
11599 if (!features().native_vertex_array_object
) {
11601 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11602 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11605 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11607 glGenVertexArraysOES(n
, service_ids
.get());
11608 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11609 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11616 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11617 GLsizei n
, const GLuint
* client_ids
) {
11618 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11619 VertexAttribManager
* vao
=
11620 GetVertexAttribManager(client_ids
[ii
]);
11621 if (vao
&& !vao
->IsDeleted()) {
11622 if (state_
.vertex_attrib_manager
.get() == vao
) {
11623 DoBindVertexArrayOES(0);
11625 RemoveVertexAttribManager(client_ids
[ii
]);
11630 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11631 VertexAttribManager
* vao
= NULL
;
11632 if (client_id
!= 0) {
11633 vao
= GetVertexAttribManager(client_id
);
11635 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11636 // only allows names that have been previously generated. As such, we do
11637 // not generate new names here.
11638 LOCAL_SET_GL_ERROR(
11639 GL_INVALID_OPERATION
,
11640 "glBindVertexArrayOES", "bad vertex array id.");
11641 current_decoder_error_
= error::kNoError
;
11645 vao
= state_
.default_vertex_attrib_manager
.get();
11648 // Only set the VAO state if it's changed
11649 if (state_
.vertex_attrib_manager
.get() != vao
) {
11650 state_
.vertex_attrib_manager
= vao
;
11651 if (!features().native_vertex_array_object
) {
11652 EmulateVertexArrayState();
11654 GLuint service_id
= vao
->service_id();
11655 glBindVertexArrayOES(service_id
);
11660 // Used when OES_vertex_array_object isn't natively supported
11661 void GLES2DecoderImpl::EmulateVertexArrayState() {
11662 // Setup the Vertex attribute state
11663 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11664 RestoreStateForAttrib(vv
, true);
11667 // Setup the element buffer
11668 Buffer
* element_array_buffer
=
11669 state_
.vertex_attrib_manager
->element_array_buffer();
11670 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11671 element_array_buffer
? element_array_buffer
->service_id() : 0);
11674 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11675 const VertexAttribManager
* vao
=
11676 GetVertexAttribManager(client_id
);
11677 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11680 #if defined(OS_MACOSX)
11681 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11682 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11684 if (it
!= texture_to_io_surface_map_
.end()) {
11685 // Found a previous IOSurface bound to this texture; release it.
11686 IOSurfaceRef surface
= it
->second
;
11687 CFRelease(surface
);
11688 texture_to_io_surface_map_
.erase(it
);
11693 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11694 GLenum target
, GLsizei width
, GLsizei height
,
11695 GLuint io_surface_id
, GLuint plane
) {
11696 #if defined(OS_MACOSX)
11697 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11698 LOCAL_SET_GL_ERROR(
11699 GL_INVALID_OPERATION
,
11700 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11704 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11705 // This might be supported in the future, and if we could require
11706 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11707 // could delete a lot of code. For now, perform strict validation so we
11708 // know what's going on.
11709 LOCAL_SET_GL_ERROR(
11710 GL_INVALID_OPERATION
,
11711 "glTexImageIOSurface2DCHROMIUM",
11712 "requires TEXTURE_RECTANGLE_ARB target");
11716 // Default target might be conceptually valid, but disallow it to avoid
11718 TextureRef
* texture_ref
=
11719 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11720 if (!texture_ref
) {
11721 LOCAL_SET_GL_ERROR(
11722 GL_INVALID_OPERATION
,
11723 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11727 // Look up the new IOSurface. Note that because of asynchrony
11728 // between processes this might fail; during live resizing the
11729 // plugin process might allocate and release an IOSurface before
11730 // this process gets a chance to look it up. Hold on to any old
11731 // IOSurface in this case.
11732 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11734 LOCAL_SET_GL_ERROR(
11735 GL_INVALID_OPERATION
,
11736 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11740 // Release any IOSurface previously bound to this texture.
11741 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11743 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11744 texture_to_io_surface_map_
.insert(
11745 std::make_pair(texture_ref
->service_id(), surface
));
11747 CGLContextObj context
=
11748 static_cast<CGLContextObj
>(context_
->GetHandle());
11750 CGLError err
= CGLTexImageIOSurface2D(
11757 GL_UNSIGNED_INT_8_8_8_8_REV
,
11761 if (err
!= kCGLNoError
) {
11762 LOCAL_SET_GL_ERROR(
11763 GL_INVALID_OPERATION
,
11764 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11768 texture_manager()->SetLevelInfo(
11769 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
11770 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
11773 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11774 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11778 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11779 switch (internalformat
) {
11790 case GL_LUMINANCE8_ALPHA8_EXT
:
11791 return GL_LUMINANCE_ALPHA
;
11792 case GL_LUMINANCE8_EXT
:
11793 return GL_LUMINANCE
;
11794 case GL_ALPHA8_EXT
:
11796 case GL_RGBA32F_EXT
:
11798 case GL_RGB32F_EXT
:
11800 case GL_ALPHA32F_EXT
:
11802 case GL_LUMINANCE32F_EXT
:
11803 return GL_LUMINANCE
;
11804 case GL_LUMINANCE_ALPHA32F_EXT
:
11805 return GL_LUMINANCE_ALPHA
;
11806 case GL_RGBA16F_EXT
:
11808 case GL_RGB16F_EXT
:
11810 case GL_ALPHA16F_EXT
:
11812 case GL_LUMINANCE16F_EXT
:
11813 return GL_LUMINANCE
;
11814 case GL_LUMINANCE_ALPHA16F_EXT
:
11815 return GL_LUMINANCE_ALPHA
;
11817 return GL_BGRA_EXT
;
11818 case GL_SRGB8_ALPHA8_EXT
:
11819 return GL_SRGB_ALPHA_EXT
;
11825 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11826 const char* function_name
,
11828 TextureRef
* source_texture_ref
,
11829 TextureRef
* dest_texture_ref
,
11830 GLenum dest_internal_format
) {
11831 if (!source_texture_ref
|| !dest_texture_ref
) {
11832 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
11836 if (GL_TEXTURE_2D
!= target
) {
11837 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11838 "invalid texture target");
11842 Texture
* source_texture
= source_texture_ref
->texture();
11843 Texture
* dest_texture
= dest_texture_ref
->texture();
11844 if (source_texture
== dest_texture
) {
11845 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11846 "source and destination textures are the same");
11850 if (dest_texture
->target() != GL_TEXTURE_2D
||
11851 (source_texture
->target() != GL_TEXTURE_2D
&&
11852 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
11853 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
11854 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11855 "invalid texture target binding");
11859 GLenum source_type
= 0;
11860 GLenum source_internal_format
= 0;
11861 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11862 &source_internal_format
);
11864 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11865 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11866 // renderable on some platforms.
11867 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
11868 dest_internal_format
== GL_RGBA
||
11869 dest_internal_format
== GL_BGRA_EXT
;
11870 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11871 source_internal_format
== GL_RGB
||
11872 source_internal_format
== GL_RGBA
||
11873 source_internal_format
== GL_LUMINANCE
||
11874 source_internal_format
== GL_LUMINANCE_ALPHA
||
11875 source_internal_format
== GL_BGRA_EXT
;
11876 if (!valid_source_format
|| !valid_dest_format
) {
11877 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11878 "invalid internal format");
11884 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target
,
11887 GLenum internal_format
,
11888 GLenum dest_type
) {
11889 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11891 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11892 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11893 Texture
* source_texture
= source_texture_ref
->texture();
11894 Texture
* dest_texture
= dest_texture_ref
->texture();
11895 int source_width
= 0;
11896 int source_height
= 0;
11897 gfx::GLImage
* image
=
11898 source_texture
->GetLevelImage(source_texture
->target(), 0);
11900 gfx::Size size
= image
->GetSize();
11901 source_width
= size
.width();
11902 source_height
= size
.height();
11903 if (source_width
<= 0 || source_height
<= 0) {
11904 LOCAL_SET_GL_ERROR(
11906 "glCopyTextureChromium", "invalid image size");
11910 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11911 &source_width
, &source_height
, nullptr)) {
11912 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
11913 "glCopyTextureChromium",
11914 "source texture has no level 0");
11918 // Check that this type of texture is allowed.
11919 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11920 source_width
, source_height
, 1)) {
11921 LOCAL_SET_GL_ERROR(
11922 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11927 GLenum source_type
= 0;
11928 GLenum source_internal_format
= 0;
11929 source_texture
->GetLevelType(
11930 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11932 if (dest_texture
->IsImmutable()) {
11933 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
11934 "texture is immutable");
11938 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
11939 source_texture_ref
, dest_texture_ref
,
11940 internal_format
)) {
11944 // Clear the source texture if necessary.
11945 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11946 source_texture
->target(), 0)) {
11947 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
11948 "dimensions too big");
11952 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11953 // needed because it takes 10s of milliseconds to initialize.
11954 if (!copy_texture_CHROMIUM_
.get()) {
11955 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11956 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11957 copy_texture_CHROMIUM_
->Initialize(this);
11958 RestoreCurrentFramebufferBindings();
11959 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11963 GLenum dest_type_previous
= dest_type
;
11964 GLenum dest_internal_format
= internal_format
;
11965 int dest_width
= 0;
11966 int dest_height
= 0;
11967 bool dest_level_defined
= dest_texture
->GetLevelSize(
11968 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
11970 if (dest_level_defined
) {
11971 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
11972 &dest_internal_format
);
11975 // Resize the destination texture to the dimensions of the source texture.
11976 if (!dest_level_defined
|| dest_width
!= source_width
||
11977 dest_height
!= source_height
||
11978 dest_internal_format
!= internal_format
||
11979 dest_type_previous
!= dest_type
) {
11980 // Ensure that the glTexImage2D succeeds.
11981 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11982 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11983 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
11984 0, internal_format
, dest_type
, NULL
);
11985 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11986 if (error
!= GL_NO_ERROR
) {
11987 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11991 texture_manager()->SetLevelInfo(
11992 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
11993 source_height
, 1, 0, internal_format
, dest_type
, true);
11995 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11999 ScopedModifyPixels
modify(dest_texture_ref
);
12001 // Try using GLImage::CopyTexSubImage when possible.
12002 bool unpack_premultiply_alpha_change
=
12003 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
12004 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
12005 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12006 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
12007 gfx::Rect(0, 0, source_width
, source_height
))) {
12012 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12014 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12015 // before presenting.
12016 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
12017 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12018 // instead of using kIdentityMatrix crbug.com/226218.
12019 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
12020 this, source_texture
->target(), source_texture
->service_id(),
12021 dest_texture
->service_id(), source_width
, source_height
, unpack_flip_y_
,
12022 unpack_premultiply_alpha_
, unpack_unpremultiply_alpha_
,
12025 copy_texture_CHROMIUM_
->DoCopyTexture(
12026 this, source_texture
->target(), source_texture
->service_id(),
12027 source_internal_format
, dest_texture
->service_id(), internal_format
,
12028 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
12029 unpack_unpremultiply_alpha_
);
12032 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12035 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target
,
12044 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12046 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12047 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12048 Texture
* source_texture
= source_texture_ref
->texture();
12049 Texture
* dest_texture
= dest_texture_ref
->texture();
12050 int source_width
= 0;
12051 int source_height
= 0;
12052 gfx::GLImage
* image
=
12053 source_texture
->GetLevelImage(source_texture
->target(), 0);
12055 gfx::Size size
= image
->GetSize();
12056 source_width
= size
.width();
12057 source_height
= size
.height();
12058 if (source_width
<= 0 || source_height
<= 0) {
12059 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12060 "invalid image size");
12064 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12065 &source_width
, &source_height
, nullptr)) {
12066 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12067 "source texture has no level 0");
12071 // Check that this type of texture is allowed.
12072 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12073 source_width
, source_height
, 1)) {
12074 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12075 "source texture bad dimensions");
12080 GLenum source_type
= 0;
12081 GLenum source_internal_format
= 0;
12082 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12083 &source_internal_format
);
12084 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
12085 width
, height
, 1, source_type
)) {
12086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12087 "source texture bad dimensions.");
12091 GLenum dest_type
= 0;
12092 GLenum dest_internal_format
= 0;
12093 bool dest_level_defined
= dest_texture
->GetLevelType(
12094 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
12095 if (!dest_level_defined
) {
12096 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
12097 "destination texture is not defined");
12100 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
12101 yoffset
, 0, width
, height
, 1, dest_type
)) {
12102 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
12103 "destination texture bad dimensions.");
12107 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
12108 source_texture_ref
, dest_texture_ref
,
12109 dest_internal_format
)) {
12113 // Clear the source texture if necessary.
12114 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12115 source_texture
->target(), 0)) {
12116 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12117 "source texture dimensions too big");
12121 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12122 // needed because it takes 10s of milliseconds to initialize.
12123 if (!copy_texture_CHROMIUM_
.get()) {
12124 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12125 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12126 copy_texture_CHROMIUM_
->Initialize(this);
12127 RestoreCurrentFramebufferBindings();
12128 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
12132 int dest_width
= 0;
12133 int dest_height
= 0;
12134 bool ok
= dest_texture
->GetLevelSize(
12135 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12137 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
12138 height
!= dest_height
) {
12139 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
12141 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
12142 "destination texture dimensions too big");
12146 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12150 ScopedModifyPixels
modify(dest_texture_ref
);
12152 // Try using GLImage::CopyTexSubImage when possible.
12153 bool unpack_premultiply_alpha_change
=
12154 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
12155 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
12156 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12157 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
12158 gfx::Rect(x
, y
, width
, height
))) {
12163 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
12165 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12166 // crbug.com/226218.
12167 copy_texture_CHROMIUM_
->DoCopySubTexture(
12168 this, source_texture
->target(), source_texture
->service_id(),
12169 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
12170 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
12171 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
12172 unpack_unpremultiply_alpha_
);
12174 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
12177 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
12178 switch (internalformat
) {
12180 return GL_UNSIGNED_SHORT_5_6_5
;
12182 return GL_UNSIGNED_SHORT_4_4_4_4
;
12184 return GL_UNSIGNED_SHORT_5_5_5_1
;
12186 return GL_UNSIGNED_BYTE
;
12188 return GL_UNSIGNED_BYTE
;
12189 case GL_LUMINANCE8_ALPHA8_EXT
:
12190 return GL_UNSIGNED_BYTE
;
12191 case GL_LUMINANCE8_EXT
:
12192 return GL_UNSIGNED_BYTE
;
12193 case GL_ALPHA8_EXT
:
12194 return GL_UNSIGNED_BYTE
;
12195 case GL_RGBA32F_EXT
:
12197 case GL_RGB32F_EXT
:
12199 case GL_ALPHA32F_EXT
:
12201 case GL_LUMINANCE32F_EXT
:
12203 case GL_LUMINANCE_ALPHA32F_EXT
:
12205 case GL_RGBA16F_EXT
:
12206 return GL_HALF_FLOAT_OES
;
12207 case GL_RGB16F_EXT
:
12208 return GL_HALF_FLOAT_OES
;
12209 case GL_ALPHA16F_EXT
:
12210 return GL_HALF_FLOAT_OES
;
12211 case GL_LUMINANCE16F_EXT
:
12212 return GL_HALF_FLOAT_OES
;
12213 case GL_LUMINANCE_ALPHA16F_EXT
:
12214 return GL_HALF_FLOAT_OES
;
12216 return GL_UNSIGNED_BYTE
;
12222 void GLES2DecoderImpl::DoTexStorage2DEXT(
12225 GLenum internal_format
,
12228 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12229 "width", width
, "height", height
);
12230 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12231 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12232 LOCAL_SET_GL_ERROR(
12233 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12236 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12238 if (!texture_ref
) {
12239 LOCAL_SET_GL_ERROR(
12240 GL_INVALID_OPERATION
,
12241 "glTexStorage2DEXT", "unknown texture for target");
12244 Texture
* texture
= texture_ref
->texture();
12245 if (texture
->IsAttachedToFramebuffer()) {
12246 framebuffer_state_
.clear_state_dirty
= true;
12248 if (texture
->IsImmutable()) {
12249 LOCAL_SET_GL_ERROR(
12250 GL_INVALID_OPERATION
,
12251 "glTexStorage2DEXT", "texture is immutable");
12255 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12256 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12259 GLsizei level_width
= width
;
12260 GLsizei level_height
= height
;
12261 uint32 estimated_size
= 0;
12262 for (int ii
= 0; ii
< levels
; ++ii
) {
12263 uint32 level_size
= 0;
12264 if (!GLES2Util::ComputeImageDataSizes(
12265 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12266 &estimated_size
, NULL
, NULL
) ||
12267 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12268 LOCAL_SET_GL_ERROR(
12269 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12272 level_width
= std::max(1, level_width
>> 1);
12273 level_height
= std::max(1, level_height
>> 1);
12275 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12276 LOCAL_SET_GL_ERROR(
12277 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
12282 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12283 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
12284 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12285 if (error
== GL_NO_ERROR
) {
12286 GLsizei level_width
= width
;
12287 GLsizei level_height
= height
;
12288 for (int ii
= 0; ii
< levels
; ++ii
) {
12289 texture_manager()->SetLevelInfo(
12290 texture_ref
, target
, ii
, format
,
12291 level_width
, level_height
, 1, 0, format
, type
, false);
12292 level_width
= std::max(1, level_width
>> 1);
12293 level_height
= std::max(1, level_height
>> 1);
12295 texture
->SetImmutable(true);
12299 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12300 uint32 immediate_data_size
,
12301 const void* cmd_data
) {
12302 return error::kUnknownCommand
;
12305 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
12306 const GLbyte
* data
) {
12307 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12308 "context", logger_
.GetLogPrefix(),
12309 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12311 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12313 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
12316 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
12317 GLenum target
, const GLbyte
* data
) {
12318 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12319 "context", logger_
.GetLogPrefix(),
12320 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12322 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
12326 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
12327 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
12328 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12329 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
12330 "mailbox that was not generated by "
12331 "GenMailboxCHROMIUM.";
12333 if (!texture_ref
) {
12334 LOCAL_SET_GL_ERROR(
12335 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
12339 Texture
* produced
= texture_manager()->Produce(texture_ref
);
12341 LOCAL_SET_GL_ERROR(
12342 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
12346 if (produced
->target() != target
) {
12347 LOCAL_SET_GL_ERROR(
12348 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
12352 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
12355 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
12356 const GLbyte
* data
) {
12357 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12358 "context", logger_
.GetLogPrefix(),
12359 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12360 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12361 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12362 "mailbox that was not generated by "
12363 "GenMailboxCHROMIUM.";
12365 scoped_refptr
<TextureRef
> texture_ref
=
12366 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12367 if (!texture_ref
.get()) {
12368 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12369 "glConsumeTextureCHROMIUM",
12370 "unknown texture for target");
12373 GLuint client_id
= texture_ref
->client_id();
12375 LOCAL_SET_GL_ERROR(
12376 GL_INVALID_OPERATION
,
12377 "glConsumeTextureCHROMIUM", "unknown texture for target");
12380 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12382 LOCAL_SET_GL_ERROR(
12383 GL_INVALID_OPERATION
,
12384 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12387 if (texture
->target() != target
) {
12388 LOCAL_SET_GL_ERROR(
12389 GL_INVALID_OPERATION
,
12390 "glConsumeTextureCHROMIUM", "invalid target");
12394 DeleteTexturesHelper(1, &client_id
);
12395 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12396 glBindTexture(target
, texture_ref
->service_id());
12398 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
12399 unit
.bind_target
= target
;
12401 case GL_TEXTURE_2D
:
12402 unit
.bound_texture_2d
= texture_ref
;
12404 case GL_TEXTURE_CUBE_MAP
:
12405 unit
.bound_texture_cube_map
= texture_ref
;
12407 case GL_TEXTURE_EXTERNAL_OES
:
12408 unit
.bound_texture_external_oes
= texture_ref
;
12410 case GL_TEXTURE_RECTANGLE_ARB
:
12411 unit
.bound_texture_rectangle_arb
= texture_ref
;
12414 NOTREACHED(); // Validation should prevent us getting here.
12419 void GLES2DecoderImpl::EnsureTextureForClientId(
12421 GLuint client_id
) {
12422 TextureRef
* texture_ref
= GetTexture(client_id
);
12423 if (!texture_ref
) {
12425 glGenTextures(1, &service_id
);
12426 DCHECK_NE(0u, service_id
);
12427 texture_ref
= CreateTexture(client_id
, service_id
);
12428 texture_manager()->SetTarget(texture_ref
, target
);
12429 glBindTexture(target
, service_id
);
12430 RestoreCurrentTextureBindings(&state_
, target
);
12434 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12435 // provided is associated with a service_id/TextureRef for consistency, even if
12436 // the resulting texture is incomplete.
12437 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12438 uint32_t immediate_data_size
,
12439 const void* cmd_data
) {
12440 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
12442 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
12444 GLenum target
= static_cast<GLenum
>(c
.target
);
12445 uint32_t data_size
;
12446 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
12447 return error::kOutOfBounds
;
12449 if (data_size
> immediate_data_size
) {
12450 return error::kOutOfBounds
;
12452 const GLbyte
* mailbox
=
12453 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
12454 if (!validators_
->texture_bind_target
.IsValid(target
)) {
12455 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12456 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
12457 return error::kNoError
;
12459 if (mailbox
== NULL
) {
12460 return error::kOutOfBounds
;
12462 uint32_t client_id
= c
.client_id
;
12463 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
12464 return error::kNoError
;
12467 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
12468 const GLbyte
* data
, GLuint client_id
) {
12469 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12470 "context", logger_
.GetLogPrefix(),
12471 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12472 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12473 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12474 "passed a mailbox that was not "
12475 "generated by GenMailboxCHROMIUM.";
12477 TextureRef
* texture_ref
= GetTexture(client_id
);
12479 // No need to call EnsureTextureForClientId here, the client_id already has
12480 // an associated texture.
12481 LOCAL_SET_GL_ERROR(
12482 GL_INVALID_OPERATION
,
12483 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12486 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12488 EnsureTextureForClientId(target
, client_id
);
12489 LOCAL_SET_GL_ERROR(
12490 GL_INVALID_OPERATION
,
12491 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12495 if (texture
->target() != target
) {
12496 EnsureTextureForClientId(target
, client_id
);
12497 LOCAL_SET_GL_ERROR(
12498 GL_INVALID_OPERATION
,
12499 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12503 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12506 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
12507 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
12508 return valuebuffer
&& valuebuffer
->IsValid();
12511 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
12512 GLuint client_id
) {
12513 Valuebuffer
* valuebuffer
= NULL
;
12514 if (client_id
!= 0) {
12515 valuebuffer
= GetValuebuffer(client_id
);
12516 if (!valuebuffer
) {
12517 if (!group_
->bind_generates_resource()) {
12518 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
12519 "id not generated by glBindValuebufferCHROMIUM");
12523 // It's a new id so make a valuebuffer for it.
12524 CreateValuebuffer(client_id
);
12525 valuebuffer
= GetValuebuffer(client_id
);
12527 valuebuffer
->MarkAsValid();
12529 state_
.bound_valuebuffer
= valuebuffer
;
12532 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
12533 GLenum subscription
) {
12534 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12537 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
12540 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
12541 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12544 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
12547 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
12549 GLenum subscription
) {
12550 if (!CheckCurrentValuebufferForSubscription(
12551 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
12554 if (!CheckSubscriptionTarget(location
, subscription
,
12555 "glPopulateSubscribedValuesCHROMIUM")) {
12558 const ValueState
* state
=
12559 state_
.bound_valuebuffer
.get()->GetState(subscription
);
12561 switch (subscription
) {
12562 case GL_MOUSE_POSITION_CHROMIUM
:
12563 DoUniform2iv(location
, 1, state
->int_value
);
12566 NOTREACHED() << "Unhandled uniform subscription target "
12573 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12574 GLsizei length
, const GLchar
* marker
) {
12578 debug_marker_manager_
.SetMarker(
12579 length
? std::string(marker
, length
) : std::string(marker
));
12582 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12583 GLsizei length
, const GLchar
* marker
) {
12587 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
12588 debug_marker_manager_
.PushGroup(name
);
12589 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
12590 kTraceGroupMarker
);
12593 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12594 debug_marker_manager_
.PopGroup();
12595 gpu_tracer_
->End(kTraceGroupMarker
);
12598 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12599 GLenum target
, GLint image_id
) {
12600 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12602 if (target
== GL_TEXTURE_CUBE_MAP
) {
12603 LOCAL_SET_GL_ERROR(
12605 "glBindTexImage2DCHROMIUM", "invalid target");
12609 // Default target might be conceptually valid, but disallow it to avoid
12611 TextureRef
* texture_ref
=
12612 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12613 if (!texture_ref
) {
12614 LOCAL_SET_GL_ERROR(
12615 GL_INVALID_OPERATION
,
12616 "glBindTexImage2DCHROMIUM", "no texture bound");
12620 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12622 LOCAL_SET_GL_ERROR(
12623 GL_INVALID_OPERATION
,
12624 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12629 ScopedGLErrorSuppressor
suppressor(
12630 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12631 if (!gl_image
->BindTexImage(target
)) {
12632 LOCAL_SET_GL_ERROR(
12633 GL_INVALID_OPERATION
,
12634 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12639 gfx::Size size
= gl_image
->GetSize();
12640 texture_manager()->SetLevelInfo(
12641 texture_ref
, target
, 0, gl_image
->GetInternalFormat(),
12642 size
.width(), size
.height(), 1, 0,
12643 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, true);
12644 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
12647 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12648 GLenum target
, GLint image_id
) {
12649 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12651 // Default target might be conceptually valid, but disallow it to avoid
12653 TextureRef
* texture_ref
=
12654 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12655 if (!texture_ref
) {
12656 LOCAL_SET_GL_ERROR(
12657 GL_INVALID_OPERATION
,
12658 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12662 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12664 LOCAL_SET_GL_ERROR(
12665 GL_INVALID_OPERATION
,
12666 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12670 // Do nothing when image is not currently bound.
12671 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
12675 ScopedGLErrorSuppressor
suppressor(
12676 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12677 gl_image
->ReleaseTexImage(target
);
12680 texture_manager()->SetLevelInfo(
12681 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
12682 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, false);
12685 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12686 uint32 immediate_data_size
,
12687 const void* cmd_data
) {
12688 const gles2::cmds::TraceBeginCHROMIUM
& c
=
12689 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
12690 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
12691 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
12692 if (!category_bucket
|| category_bucket
->size() == 0 ||
12693 !name_bucket
|| name_bucket
->size() == 0) {
12694 return error::kInvalidArguments
;
12697 std::string category_name
;
12698 std::string trace_name
;
12699 if (!category_bucket
->GetAsString(&category_name
) ||
12700 !name_bucket
->GetAsString(&trace_name
)) {
12701 return error::kInvalidArguments
;
12704 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
12705 LOCAL_SET_GL_ERROR(
12706 GL_INVALID_OPERATION
,
12707 "glTraceBeginCHROMIUM", "unable to create begin trace");
12708 return error::kNoError
;
12710 return error::kNoError
;
12713 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12714 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
12715 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12716 "glTraceEndCHROMIUM", "no trace begin found");
12721 void GLES2DecoderImpl::DoDrawBuffersEXT(
12722 GLsizei count
, const GLenum
* bufs
) {
12723 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
12724 LOCAL_SET_GL_ERROR(
12726 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12730 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
12732 for (GLsizei i
= 0; i
< count
; ++i
) {
12733 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
12734 bufs
[i
] != GL_NONE
) {
12735 LOCAL_SET_GL_ERROR(
12736 GL_INVALID_OPERATION
,
12737 "glDrawBuffersEXT",
12738 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12742 glDrawBuffersARB(count
, bufs
);
12743 framebuffer
->SetDrawBuffers(count
, bufs
);
12744 } else { // backbuffer
12746 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
12747 LOCAL_SET_GL_ERROR(
12748 GL_INVALID_OPERATION
,
12749 "glDrawBuffersEXT",
12750 "more than one buffer or bufs not GL_NONE or GL_BACK");
12753 GLenum mapped_buf
= bufs
[0];
12754 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12755 bufs
[0] == GL_BACK
) {
12756 mapped_buf
= GL_COLOR_ATTACHMENT0
;
12758 glDrawBuffersARB(count
, &mapped_buf
);
12759 group_
->set_draw_buffer(bufs
[0]);
12763 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
12764 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
12765 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
12766 reset_by_robustness_extension_
= true;
12769 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
12770 const GLfloat
* matrix
) {
12771 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12772 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12773 if (!features().chromium_path_rendering
) {
12774 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12775 "glMatrixLoadfCHROMIUM",
12776 "function not available");
12780 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12781 ? state_
.projection_matrix
12782 : state_
.modelview_matrix
;
12783 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
12784 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12785 // since the values of the _NV and _CHROMIUM tokens match.
12786 glMatrixLoadfEXT(matrix_mode
, matrix
);
12789 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
12790 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12791 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12793 if (!features().chromium_path_rendering
) {
12794 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12795 "glMatrixLoadIdentityCHROMIUM",
12796 "function not available");
12800 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12801 ? state_
.projection_matrix
12802 : state_
.modelview_matrix
;
12803 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
12804 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12805 // since the values of the _NV and _CHROMIUM tokens match.
12806 glMatrixLoadIdentityEXT(matrix_mode
);
12809 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12810 const char* function_name
,
12811 TextureRef
* texture_ref
,
12814 const void * data
) {
12815 // We only support async uploads to 2D textures for now.
12816 if (GL_TEXTURE_2D
!= target
) {
12817 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
12820 // We only support uploads to level zero for now.
12822 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
12825 // A transfer buffer must be bound, even for asyncTexImage2D.
12826 if (data
== NULL
) {
12827 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
12830 // We only support one async transfer in progress.
12831 if (!texture_ref
||
12832 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
12833 LOCAL_SET_GL_ERROR(
12834 GL_INVALID_OPERATION
,
12835 function_name
, "transfer already in progress");
12841 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12842 uint32 async_upload_token
,
12843 uint32 sync_data_shm_id
,
12844 uint32 sync_data_shm_offset
) {
12845 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
12846 if (!buffer
.get() ||
12847 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
12848 return base::Closure();
12850 AsyncMemoryParams
mem_params(buffer
,
12851 sync_data_shm_offset
,
12852 sizeof(AsyncUploadSync
));
12854 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
12855 new AsyncUploadTokenCompletionObserver(async_upload_token
));
12858 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
12859 base::Unretained(GetAsyncPixelTransferManager()),
12864 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12865 uint32 immediate_data_size
,
12866 const void* cmd_data
) {
12867 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
12868 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
12869 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12870 GLenum target
= static_cast<GLenum
>(c
.target
);
12871 GLint level
= static_cast<GLint
>(c
.level
);
12872 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
12873 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12874 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12875 GLint border
= static_cast<GLint
>(c
.border
);
12876 GLenum format
= static_cast<GLenum
>(c
.format
);
12877 GLenum type
= static_cast<GLenum
>(c
.type
);
12878 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
12879 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
12880 uint32 pixels_size
;
12881 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12882 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12883 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12885 base::ScopedClosureRunner scoped_completion_callback
;
12886 if (async_upload_token
) {
12887 base::Closure completion_closure
=
12888 AsyncUploadTokenCompletionClosure(async_upload_token
,
12890 sync_data_shm_offset
);
12891 if (completion_closure
.is_null())
12892 return error::kInvalidArguments
;
12894 scoped_completion_callback
.Reset(completion_closure
);
12897 // TODO(epenner): Move this and copies of this memory validation
12898 // into ValidateTexImage2D step.
12899 if (!GLES2Util::ComputeImageDataSizes(
12900 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
12902 return error::kOutOfBounds
;
12904 const void* pixels
= NULL
;
12905 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
12906 pixels
= GetSharedMemoryAs
<const void*>(
12907 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
12909 return error::kOutOfBounds
;
12913 TextureManager::DoTexImageArguments args
= {
12914 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
12915 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
12916 TextureRef
* texture_ref
;
12917 // All the normal glTexSubImage2D validation.
12918 if (!texture_manager()->ValidateTexImage(
12919 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
12920 return error::kNoError
;
12923 // Extra async validation.
12924 Texture
* texture
= texture_ref
->texture();
12925 if (!ValidateAsyncTransfer(
12926 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12927 return error::kNoError
;
12929 // Don't allow async redefinition of a textures.
12930 if (texture
->IsDefined()) {
12931 LOCAL_SET_GL_ERROR(
12932 GL_INVALID_OPERATION
,
12933 "glAsyncTexImage2DCHROMIUM", "already defined");
12934 return error::kNoError
;
12937 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
12938 LOCAL_SET_GL_ERROR(
12939 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
12940 return error::kNoError
;
12943 // Setup the parameters.
12944 AsyncTexImage2DParams tex_params
= {
12945 target
, level
, static_cast<GLenum
>(internal_format
),
12946 width
, height
, border
, format
, type
};
12947 AsyncMemoryParams
mem_params(
12948 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
12950 // Set up the async state if needed, and make the texture
12951 // immutable so the async state stays valid. The level info
12952 // is set up lazily when the transfer completes.
12953 AsyncPixelTransferDelegate
* delegate
=
12954 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
12956 texture
->SetImmutable(true);
12958 delegate
->AsyncTexImage2D(
12961 base::Bind(&TextureManager::SetLevelInfoFromParams
,
12962 // The callback is only invoked if the transfer delegate still
12963 // exists, which implies through manager->texture_ref->state
12964 // ownership that both of these pointers are valid.
12965 base::Unretained(texture_manager()),
12966 base::Unretained(texture_ref
),
12968 return error::kNoError
;
12971 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12972 uint32 immediate_data_size
,
12973 const void* cmd_data
) {
12974 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
12975 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
12976 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12977 GLenum target
= static_cast<GLenum
>(c
.target
);
12978 GLint level
= static_cast<GLint
>(c
.level
);
12979 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
12980 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
12981 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12982 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12983 GLenum format
= static_cast<GLenum
>(c
.format
);
12984 GLenum type
= static_cast<GLenum
>(c
.type
);
12985 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12986 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12987 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12989 base::ScopedClosureRunner scoped_completion_callback
;
12990 if (async_upload_token
) {
12991 base::Closure completion_closure
=
12992 AsyncUploadTokenCompletionClosure(async_upload_token
,
12994 sync_data_shm_offset
);
12995 if (completion_closure
.is_null())
12996 return error::kInvalidArguments
;
12998 scoped_completion_callback
.Reset(completion_closure
);
13001 // TODO(epenner): Move this and copies of this memory validation
13002 // into ValidateTexSubImage2D step.
13004 if (!GLES2Util::ComputeImageDataSizes(
13005 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
13007 return error::kOutOfBounds
;
13009 const void* pixels
= GetSharedMemoryAs
<const void*>(
13010 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
13012 // All the normal glTexSubImage2D validation.
13013 error::Error error
= error::kNoError
;
13014 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
13015 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
13019 // Extra async validation.
13020 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13022 Texture
* texture
= texture_ref
->texture();
13023 if (!ValidateAsyncTransfer(
13024 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
13025 return error::kNoError
;
13027 // Guarantee async textures are always 'cleared' as follows:
13028 // - AsyncTexImage2D can not redefine an existing texture
13029 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13030 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13031 // - Textures become immutable after an async call.
13032 // This way we know in all cases that an async texture is always clear.
13033 if (!texture
->SafeToRenderFrom()) {
13034 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
13036 LOCAL_SET_GL_ERROR(
13038 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
13039 return error::kNoError
;
13043 // Setup the parameters.
13044 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
13045 width
, height
, format
, type
};
13046 AsyncMemoryParams
mem_params(
13047 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
13048 AsyncPixelTransferDelegate
* delegate
=
13049 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13051 // TODO(epenner): We may want to enforce exclusive use
13052 // of async APIs in which case this should become an error,
13053 // (the texture should have been async defined).
13054 AsyncTexImage2DParams define_params
= {target
, level
,
13056 texture
->GetLevelSize(
13057 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
13058 texture
->GetLevelType(
13059 target
, level
, &define_params
.type
, &define_params
.internal_format
);
13060 // Set up the async state if needed, and make the texture
13061 // immutable so the async state stays valid.
13062 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
13063 texture_ref
, define_params
);
13064 texture
->SetImmutable(true);
13067 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
13068 return error::kNoError
;
13071 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
13072 uint32 immediate_data_size
,
13073 const void* cmd_data
) {
13074 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
13075 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
13076 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13077 GLenum target
= static_cast<GLenum
>(c
.target
);
13079 if (GL_TEXTURE_2D
!= target
) {
13080 LOCAL_SET_GL_ERROR(
13081 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
13082 return error::kNoError
;
13084 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13086 if (!texture_ref
) {
13087 LOCAL_SET_GL_ERROR(
13088 GL_INVALID_OPERATION
,
13089 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
13090 return error::kNoError
;
13092 AsyncPixelTransferDelegate
* delegate
=
13093 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
13095 LOCAL_SET_GL_ERROR(
13096 GL_INVALID_OPERATION
,
13097 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
13098 return error::kNoError
;
13100 delegate
->WaitForTransferCompletion();
13101 ProcessFinishedAsyncTransfers();
13102 return error::kNoError
;
13105 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
13106 uint32 immediate_data_size
,
13107 const void* data
) {
13108 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
13110 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
13111 ProcessFinishedAsyncTransfers();
13112 return error::kNoError
;
13115 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
13116 uint32_t immediate_data_size
, const void* cmd_data
) {
13117 if (!unsafe_es3_apis_enabled())
13118 return error::kUnknownCommand
;
13119 const gles2::cmds::UniformBlockBinding
& c
=
13120 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
13121 GLuint client_id
= c
.program
;
13122 GLuint index
= static_cast<GLuint
>(c
.index
);
13123 GLuint binding
= static_cast<GLuint
>(c
.binding
);
13124 Program
* program
= GetProgramInfoNotShader(
13125 client_id
, "glUniformBlockBinding");
13127 return error::kNoError
;
13129 GLuint service_id
= program
->service_id();
13130 glUniformBlockBinding(service_id
, index
, binding
);
13131 return error::kNoError
;
13134 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
13135 uint32_t immediate_data_size
, const void* cmd_data
) {
13136 if (!unsafe_es3_apis_enabled())
13137 return error::kUnknownCommand
;
13138 const gles2::cmds::ClientWaitSync
& c
=
13139 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
13140 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13141 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13142 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13143 typedef cmds::ClientWaitSync::Result Result
;
13144 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
13145 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
13147 return error::kOutOfBounds
;
13149 if (*result_dst
!= GL_WAIT_FAILED
) {
13150 return error::kInvalidArguments
;
13152 GLsync service_sync
= 0;
13153 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13154 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
13155 return error::kNoError
;
13157 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
13158 return error::kNoError
;
13161 error::Error
GLES2DecoderImpl::HandleWaitSync(
13162 uint32_t immediate_data_size
, const void* cmd_data
) {
13163 if (!unsafe_es3_apis_enabled())
13164 return error::kUnknownCommand
;
13165 const gles2::cmds::WaitSync
& c
=
13166 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
13167 GLuint sync
= static_cast<GLuint
>(c
.sync
);
13168 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
13169 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
13170 GLsync service_sync
= 0;
13171 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
13172 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
13173 return error::kNoError
;
13175 glWaitSync(service_sync
, flags
, timeout
);
13176 return error::kNoError
;
13179 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13180 uint32_t immediate_data_size
, const void* cmd_data
) {
13181 if (!unsafe_es3_apis_enabled()) {
13182 return error::kUnknownCommand
;
13184 const gles2::cmds::MapBufferRange
& c
=
13185 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13186 GLenum target
= static_cast<GLenum
>(c
.target
);
13187 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13188 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13189 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13191 typedef cmds::MapBufferRange::Result Result
;
13192 Result
* result
= GetSharedMemoryAs
<Result
*>(
13193 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13195 return error::kOutOfBounds
;
13197 if (*result
!= 0) {
13199 return error::kInvalidArguments
;
13202 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13204 return error::kOutOfBounds
;
13207 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13208 if ((access
& mask
) == mask
) {
13209 // TODO(zmo): To be on the safe side, always map
13210 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13211 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13212 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
13214 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13215 // undefined behaviors.
13216 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
13217 if ((access
& mask
) == mask
) {
13218 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
13219 "incompatible access bits");
13220 return error::kNoError
;
13222 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
13223 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
13224 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13225 access
= (access
| GL_MAP_READ_BIT
);
13227 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
13228 if (ptr
== nullptr) {
13229 return error::kNoError
;
13231 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13233 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
13234 GetSharedMemoryBuffer(c
.data_shm_id
));
13235 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13236 memcpy(mem
, ptr
, size
);
13239 return error::kNoError
;
13242 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
13243 uint32_t immediate_data_size
, const void* cmd_data
) {
13244 if (!unsafe_es3_apis_enabled()) {
13245 return error::kUnknownCommand
;
13247 const gles2::cmds::UnmapBuffer
& c
=
13248 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
13249 GLenum target
= static_cast<GLenum
>(c
.target
);
13251 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13253 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
13254 return error::kNoError
;
13256 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
13257 if (!mapped_range
) {
13258 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
13259 "buffer is unmapped");
13260 return error::kNoError
;
13262 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
13263 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
13264 GL_MAP_FLUSH_EXPLICIT_BIT
) {
13265 // If we don't need to write back, or explict flush is required, no copying
13268 void* mem
= mapped_range
->GetShmPointer();
13270 return error::kOutOfBounds
;
13272 DCHECK(mapped_range
->pointer
);
13273 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
13275 buffer
->RemoveMappedRange();
13276 GLboolean rt
= glUnmapBuffer(target
);
13277 if (rt
== GL_FALSE
) {
13278 // At this point, we have already done the necessary validation, so
13279 // GL_FALSE indicates data corruption.
13280 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13281 // the second unmap could still return GL_FALSE. For now, we simply lose
13282 // the contexts in the share group.
13283 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13284 // Need to lose current context before broadcasting!
13285 MarkContextLost(error::kGuilty
);
13286 group_
->LoseContexts(error::kInnocent
);
13287 return error::kLostContext
;
13289 return error::kNoError
;
13292 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13293 TextureRef
* texture_ref
) {
13294 Texture
* texture
= texture_ref
->texture();
13295 DoDidUseTexImageIfNeeded(texture
, texture
->target());
13298 // Note that GL_LOST_CONTEXT is specific to GLES.
13299 // For desktop GL we have to query the reset status proactively.
13300 void GLES2DecoderImpl::OnContextLostError() {
13301 if (!WasContextLost()) {
13302 // Need to lose current context before broadcasting!
13303 CheckResetStatus();
13304 group_
->LoseContexts(error::kUnknown
);
13305 reset_by_robustness_extension_
= true;
13309 void GLES2DecoderImpl::OnOutOfMemoryError() {
13310 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
13311 error::ContextLostReason other
= error::kOutOfMemory
;
13312 if (CheckResetStatus()) {
13313 other
= error::kUnknown
;
13315 // Need to lose current context before broadcasting!
13316 MarkContextLost(error::kOutOfMemory
);
13318 group_
->LoseContexts(other
);
13322 // Include the auto-generated part of this file. We split this because it means
13323 // we can easily edit the non-auto generated parts right here in this file
13324 // instead of having to edit some template or the code generator.
13325 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13327 } // namespace gles2