1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 #include "base/at_exit.h"
19 #include "base/bind.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "base/trace_event/trace_event.h"
27 #include "base/trace_event/trace_event_synthetic_delay.h"
28 #include "build/build_config.h"
29 #define GLES2_GPU_SERVICE 1
30 #include "gpu/command_buffer/common/debug_marker_manager.h"
31 #include "gpu/command_buffer/common/gles2_cmd_format.h"
32 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
33 #include "gpu/command_buffer/common/id_allocator.h"
34 #include "gpu/command_buffer/common/mailbox.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
36 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
37 #include "gpu/command_buffer/service/buffer_manager.h"
38 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
39 #include "gpu/command_buffer/service/context_group.h"
40 #include "gpu/command_buffer/service/context_state.h"
41 #include "gpu/command_buffer/service/error_state.h"
42 #include "gpu/command_buffer/service/feature_info.h"
43 #include "gpu/command_buffer/service/framebuffer_manager.h"
44 #include "gpu/command_buffer/service/gl_utils.h"
45 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
46 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
47 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
48 #include "gpu/command_buffer/service/gpu_state_tracer.h"
49 #include "gpu/command_buffer/service/gpu_switches.h"
50 #include "gpu/command_buffer/service/gpu_tracer.h"
51 #include "gpu/command_buffer/service/image_manager.h"
52 #include "gpu/command_buffer/service/mailbox_manager.h"
53 #include "gpu/command_buffer/service/memory_tracking.h"
54 #include "gpu/command_buffer/service/program_manager.h"
55 #include "gpu/command_buffer/service/query_manager.h"
56 #include "gpu/command_buffer/service/renderbuffer_manager.h"
57 #include "gpu/command_buffer/service/shader_manager.h"
58 #include "gpu/command_buffer/service/shader_translator.h"
59 #include "gpu/command_buffer/service/shader_translator_cache.h"
60 #include "gpu/command_buffer/service/texture_manager.h"
61 #include "gpu/command_buffer/service/valuebuffer_manager.h"
62 #include "gpu/command_buffer/service/vertex_array_manager.h"
63 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
64 #include "third_party/smhasher/src/City.h"
65 #include "ui/gl/gl_fence.h"
66 #include "ui/gl/gl_image.h"
67 #include "ui/gl/gl_implementation.h"
68 #include "ui/gl/gl_surface.h"
70 #if defined(OS_MACOSX)
71 #include <IOSurface/IOSurfaceAPI.h>
72 // Note that this must be included after gl_bindings.h to avoid conflicts.
73 #include <OpenGL/CGLIOSurface.h>
77 #include "base/win/win_util.h"
85 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
86 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
87 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
88 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
90 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
91 0.0f
, 1.0f
, 0.0f
, 0.0f
,
92 0.0f
, 0.0f
, 1.0f
, 0.0f
,
93 0.0f
, 0.0f
, 0.0f
, 1.0f
};
95 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
98 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
101 static void GetShaderPrecisionFormatImpl(GLenum shader_type
,
102 GLenum precision_type
,
103 GLint
* range
, GLint
* precision
) {
104 switch (precision_type
) {
108 // These values are for a 32-bit twos-complement integer format.
114 case GL_MEDIUM_FLOAT
:
116 // These values are for an IEEE single-precision floating-point format.
126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
127 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 glGetShaderPrecisionFormat(shader_type
, precision_type
,
137 // TODO(brianderson): Make the following official workarounds.
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range
[0] = abs(range
[0]);
143 range
[1] = abs(range
[1]);
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
148 if (precision_type
== GL_HIGH_FLOAT
&&
149 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
157 static gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
158 switch (plane_transform
) {
159 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
160 return gfx::OVERLAY_TRANSFORM_NONE
;
161 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
162 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
163 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
164 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
165 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
166 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
167 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
168 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
169 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
170 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
172 return gfx::OVERLAY_TRANSFORM_INVALID
;
178 class GLES2DecoderImpl
;
180 // Local versions of the SET_GL_ERROR macros
181 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
182 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
183 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
184 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
185 function_name, value, label)
186 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
187 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
188 function_name, pname)
189 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
190 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
192 #define LOCAL_PEEK_GL_ERROR(function_name) \
193 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
194 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
195 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
196 #define LOCAL_PERFORMANCE_WARNING(msg) \
197 PerformanceWarning(__FILE__, __LINE__, msg)
198 #define LOCAL_RENDER_WARNING(msg) \
199 RenderWarning(__FILE__, __LINE__, msg)
201 // Check that certain assumptions the code makes are true. There are places in
202 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
203 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
204 // a few others) are 32bits. If they are not 32bits the code will have to change
205 // to call those GL functions with service side memory and then copy the results
206 // to shared memory, converting the sizes.
207 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
208 "GLint should be the same size as uint32");
209 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
210 "GLsizei should be the same size as uint32");
211 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
212 "GLfloat should be the same size as float");
214 // TODO(kbr): the use of this anonymous namespace core dumps the
215 // linker on Mac OS X 10.6 when the symbol ordering file is used
218 // Returns the address of the first byte after a struct.
219 template <typename T
>
220 const void* AddressAfterStruct(const T
& pod
) {
221 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
224 // Returns the address of the frst byte after the struct or NULL if size >
225 // immediate_data_size.
226 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
227 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
229 uint32 immediate_data_size
) {
230 return (size
<= immediate_data_size
) ?
231 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
235 // Computes the data size for certain gl commands like glUniform.
236 bool ComputeDataSize(
239 unsigned int elements_per_unit
,
242 if (!SafeMultiplyUint32(count
, size
, &value
)) {
245 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 static bool CharacterIsValidForGLES(unsigned char c
) {
255 // Printing characters are valid except " $ ` @ \ ' DEL.
256 if (c
>= 32 && c
<= 126 &&
265 // Horizontal tab, line feed, vertical tab, form feed, carriage return
267 if (c
>= 9 && c
<= 13) {
274 static bool StringIsValidForGLES(const char* str
) {
275 for (; *str
; ++str
) {
276 if (!CharacterIsValidForGLES(*str
)) {
283 // This class prevents any GL errors that occur when it is in scope from
284 // being reported to the client.
285 class ScopedGLErrorSuppressor
{
287 explicit ScopedGLErrorSuppressor(
288 const char* function_name
, ErrorState
* error_state
);
289 ~ScopedGLErrorSuppressor();
291 const char* function_name_
;
292 ErrorState
* error_state_
;
293 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
296 // Temporarily changes a decoder's bound texture and restore it when this
297 // object goes out of scope. Also temporarily switches to using active texture
298 // unit zero in case the client has changed that to something invalid.
299 class ScopedTextureBinder
{
301 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
302 ~ScopedTextureBinder();
305 ContextState
* state_
;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
310 // Temporarily changes a decoder's bound render buffer and restore it when this
311 // object goes out of scope.
312 class ScopedRenderBufferBinder
{
314 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
315 ~ScopedRenderBufferBinder();
318 ContextState
* state_
;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
322 // Temporarily changes a decoder's bound frame buffer and restore it when this
323 // object goes out of scope.
324 class ScopedFrameBufferBinder
{
326 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
327 ~ScopedFrameBufferBinder();
330 GLES2DecoderImpl
* decoder_
;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
334 // Temporarily changes a decoder's bound frame buffer to a resolved version of
335 // the multisampled offscreen render buffer if that buffer is multisampled, and,
336 // if it is bound or enforce_internal_framebuffer is true. If internal is
337 // true, the resolved framebuffer is not visible to the parent.
338 class ScopedResolvedFrameBufferBinder
{
340 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
341 bool enforce_internal_framebuffer
,
343 ~ScopedResolvedFrameBufferBinder();
346 GLES2DecoderImpl
* decoder_
;
347 bool resolve_and_bind_
;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
351 class ScopedModifyPixels
{
353 explicit ScopedModifyPixels(TextureRef
* ref
);
354 ~ScopedModifyPixels();
360 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
362 ref_
->texture()->OnWillModifyPixels();
365 ScopedModifyPixels::~ScopedModifyPixels() {
367 ref_
->texture()->OnDidModifyPixels();
370 class ScopedRenderTo
{
372 explicit ScopedRenderTo(Framebuffer
* framebuffer
);
376 const Framebuffer
* framebuffer_
;
379 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
)
380 : framebuffer_(framebuffer
) {
382 framebuffer_
->OnWillRenderTo();
385 ScopedRenderTo::~ScopedRenderTo() {
387 framebuffer_
->OnDidRenderTo();
390 // Encapsulates an OpenGL texture.
393 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
396 // Create a new render texture.
399 // Set the initial size and format of a render texture or resize it.
400 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
402 // Copy the contents of the currently bound frame buffer.
403 void Copy(const gfx::Size
& size
, GLenum format
);
405 // Destroy the render texture. This must be explicitly called before
406 // destroying this object.
409 // Invalidate the texture. This can be used when a context is lost and it is
410 // not possible to make it current in order to free the resource.
417 gfx::Size
size() const {
422 MemoryTypeTracker memory_tracker_
;
423 ContextState
* state_
;
424 size_t bytes_allocated_
;
427 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
430 // Encapsulates an OpenGL render buffer of any format.
431 class BackRenderbuffer
{
433 explicit BackRenderbuffer(
434 RenderbufferManager
* renderbuffer_manager
,
435 MemoryTracker
* memory_tracker
,
436 ContextState
* state
);
439 // Create a new render buffer.
442 // Set the initial size and format of a render buffer or resize it.
443 bool AllocateStorage(const FeatureInfo
* feature_info
,
444 const gfx::Size
& size
,
448 // Destroy the render buffer. This must be explicitly called before destroying
452 // Invalidate the render buffer. This can be used when a context is lost and
453 // it is not possible to make it current in order to free the resource.
461 RenderbufferManager
* renderbuffer_manager_
;
462 MemoryTypeTracker memory_tracker_
;
463 ContextState
* state_
;
464 size_t bytes_allocated_
;
466 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
469 // Encapsulates an OpenGL frame buffer.
470 class BackFramebuffer
{
472 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
475 // Create a new frame buffer.
478 // Attach a color render buffer to a frame buffer.
479 void AttachRenderTexture(BackTexture
* texture
);
481 // Attach a render buffer to a frame buffer. Note that this unbinds any
482 // currently bound frame buffer.
483 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
485 // Destroy the frame buffer. This must be explicitly called before destroying
489 // Invalidate the frame buffer. This can be used when a context is lost and it
490 // is not possible to make it current in order to free the resource.
493 // See glCheckFramebufferStatusEXT.
494 GLenum
CheckStatus();
501 GLES2DecoderImpl
* decoder_
;
503 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
506 struct FenceCallback
{
508 : fence(gfx::GLFence::Create()) {
511 std::vector
<base::Closure
> callbacks
;
512 scoped_ptr
<gfx::GLFence
> fence
;
515 class AsyncUploadTokenCompletionObserver
516 : public AsyncPixelTransferCompletionObserver
{
518 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token
)
519 : async_upload_token_(async_upload_token
) {
522 void DidComplete(const AsyncMemoryParams
& mem_params
) override
{
523 DCHECK(mem_params
.buffer().get());
524 void* data
= mem_params
.GetDataAddress();
525 AsyncUploadSync
* sync
= static_cast<AsyncUploadSync
*>(data
);
526 sync
->SetAsyncUploadToken(async_upload_token_
);
530 ~AsyncUploadTokenCompletionObserver() override
{}
532 uint32 async_upload_token_
;
534 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver
);
537 // } // anonymous namespace.
540 const unsigned int GLES2Decoder::kDefaultStencilMask
=
541 static_cast<unsigned int>(-1);
543 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
544 uint32
* service_texture_id
) {
548 GLES2Decoder::GLES2Decoder()
549 : initialized_(false),
551 log_commands_(false),
552 unsafe_es3_apis_enabled_(false) {
555 GLES2Decoder::~GLES2Decoder() {
558 void GLES2Decoder::BeginDecoding() {}
560 void GLES2Decoder::EndDecoding() {}
562 // This class implements GLES2Decoder so we don't have to expose all the GLES2
563 // cmd stuff to outside this class.
564 class GLES2DecoderImpl
: public GLES2Decoder
,
565 public FramebufferManager::TextureDetachObserver
,
566 public ErrorStateClient
{
568 explicit GLES2DecoderImpl(ContextGroup
* group
);
569 ~GLES2DecoderImpl() override
;
571 // Overridden from AsyncAPIInterface.
572 Error
DoCommand(unsigned int command
,
573 unsigned int arg_count
,
574 const void* args
) override
;
576 error::Error
DoCommands(unsigned int num_commands
,
579 int* entries_processed
) override
;
581 template <bool DebugImpl
>
582 error::Error
DoCommandsImpl(unsigned int num_commands
,
585 int* entries_processed
);
587 // Overridden from AsyncAPIInterface.
588 const char* GetCommandName(unsigned int command_id
) const override
;
590 // Overridden from GLES2Decoder.
591 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
592 const scoped_refptr
<gfx::GLContext
>& context
,
594 const gfx::Size
& offscreen_size
,
595 const DisallowedFeatures
& disallowed_features
,
596 const std::vector
<int32
>& attribs
) override
;
597 void Destroy(bool have_context
) override
;
598 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
599 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
600 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
601 void UpdateParentTextureInfo();
602 bool MakeCurrent() override
;
603 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
604 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
605 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
606 Capabilities
GetCapabilities() override
;
607 void RestoreState(const ContextState
* prev_state
) override
;
609 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
610 void RestoreAllTextureUnitBindings(
611 const ContextState
* prev_state
) const override
{
612 state_
.RestoreAllTextureUnitBindings(prev_state
);
614 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
615 state_
.RestoreActiveTextureUnitBinding(target
);
617 void RestoreBufferBindings() const override
{
618 state_
.RestoreBufferBindings();
620 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
621 void RestoreProgramBindings() const override
{
622 state_
.RestoreProgramBindings();
624 void RestoreTextureUnitBindings(unsigned unit
) const override
{
625 state_
.RestoreTextureUnitBindings(unit
, NULL
);
627 void RestoreFramebufferBindings() const override
;
628 void RestoreRenderbufferBindings() override
;
629 void RestoreTextureState(unsigned service_id
) const override
;
631 void ClearAllAttributes() const override
;
632 void RestoreAllAttributes() const override
;
634 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
635 VertexArrayManager
* GetVertexArrayManager() override
{
636 return vertex_array_manager_
.get();
638 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
640 ValuebufferManager
* GetValuebufferManager() override
{
641 return valuebuffer_manager();
644 bool ProcessPendingQueries(bool did_finish
) override
;
646 bool HasMoreIdleWork() override
;
647 void PerformIdleWork() override
;
649 void WaitForReadPixels(base::Closure callback
) override
;
651 void SetResizeCallback(
652 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
654 Logger
* GetLogger() override
;
656 void BeginDecoding() override
;
657 void EndDecoding() override
;
659 ErrorState
* GetErrorState() override
;
660 const ContextState
* GetContextState() override
{ return &state_
; }
662 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
663 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
665 AsyncPixelTransferManager
* GetAsyncPixelTransferManager() override
;
666 void ResetAsyncPixelTransferManagerForTest() override
;
667 void SetAsyncPixelTransferManagerForTest(
668 AsyncPixelTransferManager
* manager
) override
;
669 void SetIgnoreCachedStateForTest(bool ignore
) override
;
670 void ProcessFinishedAsyncTransfers();
672 bool GetServiceTextureId(uint32 client_texture_id
,
673 uint32
* service_texture_id
) override
;
675 uint32
GetTextureUploadCount() override
;
676 base::TimeDelta
GetTotalTextureUploadTime() override
;
677 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
678 void AddProcessingCommandsTime(base::TimeDelta
) override
;
680 // Restores the current state to the user's settings.
681 void RestoreCurrentFramebufferBindings();
683 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
684 void ApplyDirtyState();
686 // These check the state of the currently bound framebuffer or the
687 // backbuffer if no framebuffer is bound.
688 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
689 // check with all attached and enabled color attachments.
690 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers
);
691 bool BoundFramebufferHasDepthAttachment();
692 bool BoundFramebufferHasStencilAttachment();
694 error::ContextLostReason
GetContextLostReason() override
;
696 // Overridden from FramebufferManager::TextureDetachObserver:
697 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
699 // Overriden from ErrorStateClient.
700 void OnContextLostError() override
;
701 void OnOutOfMemoryError() override
;
703 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
704 void EnsureRenderbufferBound();
706 // Helpers to facilitate calling into compatible extensions.
707 static void RenderbufferStorageMultisampleHelper(
708 const FeatureInfo
* feature_info
,
711 GLenum internal_format
,
715 void BlitFramebufferHelper(GLint srcX0
,
727 friend class ScopedFrameBufferBinder
;
728 friend class ScopedResolvedFrameBufferBinder
;
729 friend class BackFramebuffer
;
731 // Initialize or re-initialize the shader translator.
732 bool InitializeShaderTranslator();
734 void UpdateCapabilities();
736 // Helpers for the glGen and glDelete functions.
737 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
738 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
739 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
740 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
741 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
742 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
743 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
744 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
745 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
746 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
747 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
748 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
749 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
750 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
752 // Helper for async upload token completion notification callback.
753 base::Closure
AsyncUploadTokenCompletionClosure(uint32 async_upload_token
,
754 uint32 sync_data_shm_id
,
755 uint32 sync_data_shm_offset
);
760 void OnFboChanged() const;
761 void OnUseFramebuffer() const;
763 error::ContextLostReason
GetContextLostReasonFromResetStatus(
764 GLenum reset_status
) const;
766 // TODO(gman): Cache these pointers?
767 BufferManager
* buffer_manager() {
768 return group_
->buffer_manager();
771 RenderbufferManager
* renderbuffer_manager() {
772 return group_
->renderbuffer_manager();
775 FramebufferManager
* framebuffer_manager() {
776 return group_
->framebuffer_manager();
779 ValuebufferManager
* valuebuffer_manager() {
780 return group_
->valuebuffer_manager();
783 ProgramManager
* program_manager() {
784 return group_
->program_manager();
787 ShaderManager
* shader_manager() {
788 return group_
->shader_manager();
791 ShaderTranslatorCache
* shader_translator_cache() {
792 return group_
->shader_translator_cache();
795 const TextureManager
* texture_manager() const {
796 return group_
->texture_manager();
799 TextureManager
* texture_manager() {
800 return group_
->texture_manager();
803 MailboxManager
* mailbox_manager() {
804 return group_
->mailbox_manager();
807 ImageManager
* image_manager() { return image_manager_
.get(); }
809 VertexArrayManager
* vertex_array_manager() {
810 return vertex_array_manager_
.get();
813 MemoryTracker
* memory_tracker() {
814 return group_
->memory_tracker();
817 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
818 MemoryTracker
* tracker
= memory_tracker();
820 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
825 bool IsOffscreenBufferMultisampled() const {
826 return offscreen_target_samples_
> 1;
829 // Creates a Texture for the given texture.
830 TextureRef
* CreateTexture(
831 GLuint client_id
, GLuint service_id
) {
832 return texture_manager()->CreateTexture(client_id
, service_id
);
835 // Gets the texture info for the given texture. Returns NULL if none exists.
836 TextureRef
* GetTexture(GLuint client_id
) const {
837 return texture_manager()->GetTexture(client_id
);
840 // Deletes the texture info for the given texture.
841 void RemoveTexture(GLuint client_id
) {
842 texture_manager()->RemoveTexture(client_id
);
845 // Get the size (in pixels) of the currently bound frame buffer (either FBO
846 // or regular back buffer).
847 gfx::Size
GetBoundReadFrameBufferSize();
849 // Get the format of the currently bound frame buffer (either FBO or regular
851 GLenum
GetBoundReadFrameBufferTextureType();
852 GLenum
GetBoundReadFrameBufferInternalFormat();
853 GLenum
GetBoundDrawFrameBufferInternalFormat();
855 // Wrapper for CompressedTexImage2D commands.
856 error::Error
DoCompressedTexImage2D(
859 GLenum internal_format
,
866 // Wrapper for CompressedTexImage3D commands.
867 error::Error
DoCompressedTexImage3D(
870 GLenum internal_format
,
878 // Wrapper for CompressedTexSubImage2D.
879 void DoCompressedTexSubImage2D(
890 // Wrapper for CompressedTexSubImage3D.
891 void DoCompressedTexSubImage3D(
904 // Wrapper for CopyTexImage2D.
905 void DoCopyTexImage2D(
908 GLenum internal_format
,
915 // Wrapper for SwapBuffers.
916 void DoSwapBuffers();
918 // Wrapper for SwapInterval.
919 void DoSwapInterval(int interval
);
921 // Wrapper for CopyTexSubImage2D.
922 void DoCopyTexSubImage2D(
932 // Validation for TexSubImage2D.
933 bool ValidateTexSubImage2D(
935 const char* function_name
,
946 // Wrapper for TexSubImage2D.
947 error::Error
DoTexSubImage2D(
958 // Extra validation for async tex(Sub)Image2D.
959 bool ValidateAsyncTransfer(
960 const char* function_name
,
961 TextureRef
* texture_ref
,
966 // Wrapper for TexImageIOSurface2DCHROMIUM.
967 void DoTexImageIOSurface2DCHROMIUM(
971 GLuint io_surface_id
,
974 void DoCopyTextureCHROMIUM(GLenum target
,
977 GLenum internal_format
,
980 void DoCopySubTextureCHROMIUM(GLenum target
,
986 // Wrapper for TexStorage2DEXT.
987 void DoTexStorage2DEXT(
990 GLenum internal_format
,
994 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
995 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
997 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
998 GLenum target
, const GLbyte
* data
);
1000 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1001 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1002 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1005 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1006 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1007 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1008 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1009 void DoUniformValueBufferCHROMIUM(GLint location
,
1011 GLenum subscription
);
1013 void DoBindTexImage2DCHROMIUM(
1016 void DoReleaseTexImage2DCHROMIUM(
1020 void DoTraceEndCHROMIUM(void);
1022 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1024 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1026 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1027 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1029 // Creates a Program for the given program.
1030 Program
* CreateProgram(
1031 GLuint client_id
, GLuint service_id
) {
1032 return program_manager()->CreateProgram(client_id
, service_id
);
1035 // Gets the program info for the given program. Returns NULL if none exists.
1036 Program
* GetProgram(GLuint client_id
) {
1037 return program_manager()->GetProgram(client_id
);
1041 void LogClientServiceMapping(
1042 const char* /* function_name */,
1043 GLuint
/* client_id */,
1044 GLuint
/* service_id */) {
1046 template<typename T
>
1047 void LogClientServiceForInfo(
1048 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1051 void LogClientServiceMapping(
1052 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1053 if (service_logging_
) {
1054 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1055 << ": client_id = " << client_id
1056 << ", service_id = " << service_id
;
1059 template<typename T
>
1060 void LogClientServiceForInfo(
1061 T
* info
, GLuint client_id
, const char* function_name
) {
1063 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1068 // Gets the program info for the given program. If it's not a program
1069 // generates a GL error. Returns NULL if not program.
1070 Program
* GetProgramInfoNotShader(
1071 GLuint client_id
, const char* function_name
) {
1072 Program
* program
= GetProgram(client_id
);
1074 if (GetShader(client_id
)) {
1076 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1078 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1081 LogClientServiceForInfo(program
, client_id
, function_name
);
1086 // Creates a Shader for the given shader.
1087 Shader
* CreateShader(
1090 GLenum shader_type
) {
1091 return shader_manager()->CreateShader(
1092 client_id
, service_id
, shader_type
);
1095 // Gets the shader info for the given shader. Returns NULL if none exists.
1096 Shader
* GetShader(GLuint client_id
) {
1097 return shader_manager()->GetShader(client_id
);
1100 // Gets the shader info for the given shader. If it's not a shader generates a
1101 // GL error. Returns NULL if not shader.
1102 Shader
* GetShaderInfoNotProgram(
1103 GLuint client_id
, const char* function_name
) {
1104 Shader
* shader
= GetShader(client_id
);
1106 if (GetProgram(client_id
)) {
1108 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1111 GL_INVALID_VALUE
, function_name
, "unknown shader");
1114 LogClientServiceForInfo(shader
, client_id
, function_name
);
1118 // Creates a buffer info for the given buffer.
1119 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1120 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1123 // Gets the buffer info for the given buffer.
1124 Buffer
* GetBuffer(GLuint client_id
) {
1125 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1129 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1130 // on glDeleteBuffers so we can make sure the user does not try to render
1131 // with deleted buffers.
1132 void RemoveBuffer(GLuint client_id
);
1134 // Creates a framebuffer info for the given framebuffer.
1135 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1136 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1139 // Gets the framebuffer info for the given framebuffer.
1140 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1141 return framebuffer_manager()->GetFramebuffer(client_id
);
1144 // Removes the framebuffer info for the given framebuffer.
1145 void RemoveFramebuffer(GLuint client_id
) {
1146 framebuffer_manager()->RemoveFramebuffer(client_id
);
1149 // Creates a renderbuffer info for the given renderbuffer.
1150 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1151 return renderbuffer_manager()->CreateRenderbuffer(
1152 client_id
, service_id
);
1155 // Gets the renderbuffer info for the given renderbuffer.
1156 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1157 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1160 // Removes the renderbuffer info for the given renderbuffer.
1161 void RemoveRenderbuffer(GLuint client_id
) {
1162 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1165 // Creates a valuebuffer info for the given valuebuffer.
1166 void CreateValuebuffer(GLuint client_id
) {
1167 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1170 // Gets the valuebuffer info for a given valuebuffer.
1171 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1172 return valuebuffer_manager()->GetValuebuffer(client_id
);
1175 // Removes the valuebuffer info for the given valuebuffer.
1176 void RemoveValuebuffer(GLuint client_id
) {
1177 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1180 // Gets the vertex attrib manager for the given vertex array.
1181 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1182 VertexAttribManager
* info
=
1183 vertex_array_manager()->GetVertexAttribManager(client_id
);
1187 // Removes the vertex attrib manager for the given vertex array.
1188 void RemoveVertexAttribManager(GLuint client_id
) {
1189 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1192 // Creates a vertex attrib manager for the given vertex array.
1193 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1196 bool client_visible
) {
1197 return vertex_array_manager()->CreateVertexAttribManager(
1198 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1201 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1202 void DoBindUniformLocationCHROMIUM(
1203 GLuint client_id
, GLint location
, const char* name
);
1205 error::Error
GetAttribLocationHelper(
1206 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1207 const std::string
& name_str
);
1209 error::Error
GetUniformLocationHelper(
1210 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1211 const std::string
& name_str
);
1213 error::Error
GetFragDataLocationHelper(
1214 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1215 const std::string
& name_str
);
1217 // Wrapper for glShaderSource.
1218 void DoShaderSource(
1219 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1221 // Wrapper for glTransformFeedbackVaryings.
1222 void DoTransformFeedbackVaryings(
1223 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1224 GLenum buffer_mode
);
1226 // Clear any textures used by the current program.
1227 bool ClearUnclearedTextures();
1229 // Clears any uncleared attachments attached to the given frame buffer.
1230 // Returns false if there was a generated GL error.
1231 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1233 // overridden from GLES2Decoder
1234 bool ClearLevel(Texture
* texture
,
1237 unsigned internal_format
,
1242 bool is_texture_immutable
) override
;
1244 // Restore all GL state that affects clearing.
1245 void RestoreClearState();
1247 // Remembers the state of some capabilities.
1248 // Returns: true if glEnable/glDisable should actually be called.
1249 bool SetCapabilityState(GLenum cap
, bool enabled
);
1251 // Check that the currently bound framebuffers are valid.
1252 // Generates GL error if not.
1253 bool CheckBoundFramebuffersValid(const char* func_name
);
1255 // Check that the currently bound read framebuffer has a color image
1256 // attached. Generates GL error if not.
1257 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1259 // Check that the currently bound read framebuffer's color image
1260 // isn't the target texture of the glCopyTex{Sub}Image2D.
1261 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1263 // Check if a framebuffer meets our requirements.
1264 bool CheckFramebufferValid(
1265 Framebuffer
* framebuffer
,
1267 const char* func_name
);
1269 // Check if the current valuebuffer exists and is valid. If not generates
1270 // the appropriate GL error. Returns true if the current valuebuffer is in
1272 bool CheckCurrentValuebuffer(const char* function_name
);
1274 // Check if the current valuebuffer exists and is valiud and that the
1275 // value buffer is actually subscribed to the given subscription
1276 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1277 const char* function_name
);
1279 // Check if the location can be used for the given subscription target. If not
1280 // generates the appropriate GL error. Returns true if the location is usable
1281 bool CheckSubscriptionTarget(GLint location
,
1282 GLenum subscription
,
1283 const char* function_name
);
1285 // Checks if the current program exists and is valid. If not generates the
1286 // appropriate GL error. Returns true if the current program is in a usable
1288 bool CheckCurrentProgram(const char* function_name
);
1290 // Checks if the current program exists and is valid and that location is not
1291 // -1. If the current program is not valid generates the appropriate GL
1292 // error. Returns true if the current program is in a usable state and
1293 // location is not -1.
1294 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1296 // Checks if the current program samples a texture that is also the color
1297 // image of the current bound framebuffer, i.e., the source and destination
1298 // of the draw operation are the same.
1299 bool CheckDrawingFeedbackLoops();
1301 // Checks if |api_type| is valid for the given uniform
1302 // If the api type is not valid generates the appropriate GL
1303 // error. Returns true if |api_type| is valid for the uniform
1304 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1305 const char* function_name
,
1306 Program::UniformApiType api_type
);
1308 // Gets the type of a uniform for a location in the current program. Sets GL
1309 // errors if the current program is not valid. Returns true if the current
1310 // program is valid and the location exists. Adjusts count so it
1311 // does not overflow the uniform.
1312 bool PrepForSetUniformByLocation(GLint fake_location
,
1313 const char* function_name
,
1314 Program::UniformApiType api_type
,
1315 GLint
* real_location
,
1319 // Gets the service id for any simulated backbuffer fbo.
1320 GLuint
GetBackbufferServiceId() const;
1322 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1323 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1325 // Helper for glGetVertexAttrib
1326 void GetVertexAttribHelper(
1327 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1329 // Wrapper for glActiveTexture
1330 void DoActiveTexture(GLenum texture_unit
);
1332 // Wrapper for glAttachShader
1333 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1335 // Wrapper for glBindBuffer since we need to track the current targets.
1336 void DoBindBuffer(GLenum target
, GLuint buffer
);
1338 // Wrapper for glBindFramebuffer since we need to track the current targets.
1339 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1341 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1342 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1344 // Wrapper for glBindTexture since we need to track the current targets.
1345 void DoBindTexture(GLenum target
, GLuint texture
);
1347 // Wrapper for glBindVertexArrayOES
1348 void DoBindVertexArrayOES(GLuint array
);
1349 void EmulateVertexArrayState();
1351 // Wrapper for glBlitFramebufferCHROMIUM.
1352 void DoBlitFramebufferCHROMIUM(
1353 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1354 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1355 GLbitfield mask
, GLenum filter
);
1357 // Wrapper for glBufferSubData.
1358 void DoBufferSubData(
1359 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1361 // Wrapper for glCheckFramebufferStatus
1362 GLenum
DoCheckFramebufferStatus(GLenum target
);
1364 // Wrapper for glClear
1365 error::Error
DoClear(GLbitfield mask
);
1367 // Wrappers for various state.
1368 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1369 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1371 // Wrapper for glCompileShader.
1372 void DoCompileShader(GLuint shader
);
1374 // Wrapper for glDetachShader
1375 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1377 // Wrapper for glDisable
1378 void DoDisable(GLenum cap
);
1380 // Wrapper for glDisableVertexAttribArray.
1381 void DoDisableVertexAttribArray(GLuint index
);
1383 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1385 void DoDiscardFramebufferEXT(GLenum target
,
1386 GLsizei numAttachments
,
1387 const GLenum
* attachments
);
1389 // Wrapper for glEnable
1390 void DoEnable(GLenum cap
);
1392 // Wrapper for glEnableVertexAttribArray.
1393 void DoEnableVertexAttribArray(GLuint index
);
1395 // Wrapper for glFinish.
1398 // Wrapper for glFlush.
1401 // Wrapper for glFramebufferRenderbufffer.
1402 void DoFramebufferRenderbuffer(
1403 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1404 GLuint renderbuffer
);
1406 // Wrapper for glFramebufferTexture2D.
1407 void DoFramebufferTexture2D(
1408 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1411 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1412 void DoFramebufferTexture2DMultisample(
1413 GLenum target
, GLenum attachment
, GLenum textarget
,
1414 GLuint texture
, GLint level
, GLsizei samples
);
1416 // Common implementation for both DoFramebufferTexture2D wrappers.
1417 void DoFramebufferTexture2DCommon(const char* name
,
1418 GLenum target
, GLenum attachment
, GLenum textarget
,
1419 GLuint texture
, GLint level
, GLsizei samples
);
1421 // Wrapper for glFramebufferTextureLayer.
1422 void DoFramebufferTextureLayer(
1423 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1426 // Wrapper for glGenerateMipmap
1427 void DoGenerateMipmap(GLenum target
);
1429 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1430 // to account for different pname values defined in different extension
1432 GLenum
AdjustGetPname(GLenum pname
);
1434 // Wrapper for DoGetBooleanv.
1435 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1437 // Wrapper for DoGetFloatv.
1438 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1440 // Wrapper for glGetFramebufferAttachmentParameteriv.
1441 void DoGetFramebufferAttachmentParameteriv(
1442 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1444 // Wrapper for glGetInteger64v.
1445 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1447 // Wrapper for glGetIntegerv.
1448 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1450 // Gets the max value in a range in a buffer.
1451 GLuint
DoGetMaxValueInBufferCHROMIUM(
1452 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1454 // Wrapper for glGetBufferParameteriv.
1455 void DoGetBufferParameteriv(
1456 GLenum target
, GLenum pname
, GLint
* params
);
1458 // Wrapper for glGetProgramiv.
1459 void DoGetProgramiv(
1460 GLuint program_id
, GLenum pname
, GLint
* params
);
1462 // Wrapper for glRenderbufferParameteriv.
1463 void DoGetRenderbufferParameteriv(
1464 GLenum target
, GLenum pname
, GLint
* params
);
1466 // Wrapper for glGetShaderiv
1467 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1469 // Wrappers for glGetTexParameter.
1470 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1471 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1472 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1474 // Wrappers for glGetVertexAttrib.
1475 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1476 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1478 // Wrappers for glIsXXX functions.
1479 bool DoIsEnabled(GLenum cap
);
1480 bool DoIsBuffer(GLuint client_id
);
1481 bool DoIsFramebuffer(GLuint client_id
);
1482 bool DoIsProgram(GLuint client_id
);
1483 bool DoIsRenderbuffer(GLuint client_id
);
1484 bool DoIsShader(GLuint client_id
);
1485 bool DoIsTexture(GLuint client_id
);
1486 bool DoIsVertexArrayOES(GLuint client_id
);
1488 // Wrapper for glLinkProgram
1489 void DoLinkProgram(GLuint program
);
1491 // Wrapper for glRenderbufferStorage.
1492 void DoRenderbufferStorage(
1493 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1495 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1496 void DoRenderbufferStorageMultisampleCHROMIUM(
1497 GLenum target
, GLsizei samples
, GLenum internalformat
,
1498 GLsizei width
, GLsizei height
);
1500 // Handler for glRenderbufferStorageMultisampleEXT
1501 // (multisampled_render_to_texture).
1502 void DoRenderbufferStorageMultisampleEXT(
1503 GLenum target
, GLsizei samples
, GLenum internalformat
,
1504 GLsizei width
, GLsizei height
);
1506 // Common validation for multisample extensions.
1507 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1508 GLenum internalformat
,
1512 // Verifies that the currently bound multisample renderbuffer is valid
1513 // Very slow! Only done on platforms with driver bugs that return invalid
1514 // buffers under memory pressure
1515 bool VerifyMultisampleRenderbufferIntegrity(
1516 GLuint renderbuffer
, GLenum format
);
1518 // Wrapper for glReleaseShaderCompiler.
1519 void DoReleaseShaderCompiler() { }
1521 // Wrappers for glSamplerParameter*v functions.
1522 void DoSamplerParameterfv(
1523 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1524 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1526 // Wrappers for glTexParameter functions.
1527 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1528 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1529 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1530 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1532 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1533 // spec only these 2 functions can be used to set sampler uniforms.
1534 void DoUniform1i(GLint fake_location
, GLint v0
);
1535 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1536 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1537 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1538 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1540 // Wrappers for glUniformfv because some drivers don't correctly accept
1542 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1543 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1544 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1545 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1547 void DoUniformMatrix2fv(
1548 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1549 const GLfloat
* value
);
1550 void DoUniformMatrix3fv(
1551 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1552 const GLfloat
* value
);
1553 void DoUniformMatrix4fv(
1554 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1555 const GLfloat
* value
);
1557 bool SetVertexAttribValue(
1558 const char* function_name
, GLuint index
, const GLfloat
* value
);
1560 // Wrappers for glVertexAttrib??
1561 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1562 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1563 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1564 void DoVertexAttrib4f(
1565 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1566 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1567 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1568 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1569 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1571 // Wrapper for glViewport
1572 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1574 // Wrapper for glUseProgram
1575 void DoUseProgram(GLuint program
);
1577 // Wrapper for glValidateProgram.
1578 void DoValidateProgram(GLuint program_client_id
);
1580 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1581 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1582 void DoPopGroupMarkerEXT(void);
1584 // Gets the number of values that will be returned by glGetXXX. Returns
1585 // false if pname is unknown.
1586 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1588 // Checks if the current program and vertex attributes are valid for drawing.
1590 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1593 // Returns true if successful, simulated will be true if attrib0 was
1595 bool SimulateAttrib0(
1596 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1597 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1599 // If an image is bound to texture, this will call Will/DidUseTexImage
1601 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1602 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1604 // Returns false if textures were replaced.
1605 bool PrepareTexturesForRender();
1606 void RestoreStateForTextures();
1608 // Returns true if GL_FIXED attribs were simulated.
1609 bool SimulateFixedAttribs(
1610 const char* function_name
,
1611 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1612 void RestoreStateForSimulatedFixedAttribs();
1614 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1615 // cases (primcount is always 1 for non-instanced).
1616 error::Error
DoDrawArrays(
1617 const char* function_name
,
1618 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1620 error::Error
DoDrawElements(
1621 const char* function_name
,
1622 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1623 int32 offset
, GLsizei primcount
);
1625 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1626 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1627 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1630 return GL_TEXTURE_2D
;
1631 case GL_SAMPLER_CUBE
:
1632 return GL_TEXTURE_CUBE_MAP
;
1633 case GL_SAMPLER_EXTERNAL_OES
:
1634 return GL_TEXTURE_EXTERNAL_OES
;
1635 case GL_SAMPLER_2D_RECT_ARB
:
1636 return GL_TEXTURE_RECTANGLE_ARB
;
1643 // Gets the framebuffer info for a particular target.
1644 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1645 Framebuffer
* framebuffer
= NULL
;
1647 case GL_FRAMEBUFFER
:
1648 case GL_DRAW_FRAMEBUFFER_EXT
:
1649 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1651 case GL_READ_FRAMEBUFFER_EXT
:
1652 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1661 Renderbuffer
* GetRenderbufferInfoForTarget(
1663 Renderbuffer
* renderbuffer
= NULL
;
1665 case GL_RENDERBUFFER
:
1666 renderbuffer
= state_
.bound_renderbuffer
.get();
1672 return renderbuffer
;
1675 // Validates the program and location for a glGetUniform call and returns
1676 // a SizeResult setup to receive the result. Returns true if glGetUniform
1677 // should be called.
1679 bool GetUniformSetup(GLuint program
,
1680 GLint fake_location
,
1683 error::Error
* error
,
1684 GLint
* real_location
,
1686 SizedResult
<T
>** result
,
1687 GLenum
* result_type
,
1688 GLsizei
* result_size
);
1690 bool WasContextLost() const override
;
1691 bool WasContextLostByRobustnessExtension() const override
;
1692 void MarkContextLost(error::ContextLostReason reason
) override
;
1693 bool CheckResetStatus();
1695 #if defined(OS_MACOSX)
1696 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1699 bool ValidateCompressedTexDimensions(
1700 const char* function_name
, GLenum target
, GLint level
,
1701 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1702 bool ValidateCompressedTexFuncData(
1703 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1704 GLenum format
, GLsizei size
);
1705 bool ValidateCompressedTexSubDimensions(
1706 const char* function_name
,
1707 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1708 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1710 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1712 TextureRef
* source_texture_ref
,
1713 TextureRef
* dest_texture_ref
,
1714 GLenum dest_internal_format
);
1716 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1717 void PerformanceWarning(
1718 const char* filename
, int line
, const std::string
& msg
);
1720 const FeatureInfo::FeatureFlags
& features() const {
1721 return feature_info_
->feature_flags();
1724 const FeatureInfo::Workarounds
& workarounds() const {
1725 return feature_info_
->workarounds();
1728 bool ShouldDeferDraws() {
1729 return !offscreen_target_frame_buffer_
.get() &&
1730 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1731 surface_
->DeferDraws();
1734 bool ShouldDeferReads() {
1735 return !offscreen_target_frame_buffer_
.get() &&
1736 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1737 surface_
->DeferDraws();
1740 bool IsRobustnessSupported() {
1741 return has_robustness_extension_
&&
1742 context_
->WasAllocatedUsingRobustnessExtension();
1745 error::Error
WillAccessBoundFramebufferForDraw() {
1746 if (ShouldDeferDraws())
1747 return error::kDeferCommandUntilLater
;
1748 if (!offscreen_target_frame_buffer_
.get() &&
1749 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1750 !surface_
->SetBackbufferAllocation(true))
1751 return error::kLostContext
;
1752 return error::kNoError
;
1755 error::Error
WillAccessBoundFramebufferForRead() {
1756 if (ShouldDeferReads())
1757 return error::kDeferCommandUntilLater
;
1758 if (!offscreen_target_frame_buffer_
.get() &&
1759 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1760 !surface_
->SetBackbufferAllocation(true))
1761 return error::kLostContext
;
1762 return error::kNoError
;
1765 // Set remaining commands to process to 0 to force DoCommands to return
1766 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1767 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1769 void ProcessPendingReadPixels();
1770 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1772 // Generate a member function prototype for each command in an automated and
1774 #define GLES2_CMD_OP(name) \
1775 Error Handle##name(uint32 immediate_data_size, const void* data);
1777 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1781 // The GL context this decoder renders to on behalf of the client.
1782 scoped_refptr
<gfx::GLSurface
> surface_
;
1783 scoped_refptr
<gfx::GLContext
> context_
;
1785 // The ContextGroup for this decoder uses to track resources.
1786 scoped_refptr
<ContextGroup
> group_
;
1788 DebugMarkerManager debug_marker_manager_
;
1791 // All the state for this context.
1792 ContextState state_
;
1794 // Current width and height of the offscreen frame buffer.
1795 gfx::Size offscreen_size_
;
1797 // Util to help with GL.
1800 // unpack flip y as last set by glPixelStorei
1801 bool unpack_flip_y_
;
1803 // unpack (un)premultiply alpha as last set by glPixelStorei
1804 bool unpack_premultiply_alpha_
;
1805 bool unpack_unpremultiply_alpha_
;
1807 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1808 GLuint attrib_0_buffer_id_
;
1810 // The value currently in attrib_0.
1811 Vec4 attrib_0_value_
;
1813 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1814 bool attrib_0_buffer_matches_value_
;
1816 // The size of attrib 0.
1817 GLsizei attrib_0_size_
;
1819 // The buffer used to simulate GL_FIXED attribs.
1820 GLuint fixed_attrib_buffer_id_
;
1822 // The size of fiixed attrib buffer.
1823 GLsizei fixed_attrib_buffer_size_
;
1825 // The offscreen frame buffer that the client renders to. With EGL, the
1826 // depth and stencil buffers are separate. With regular GL there is a single
1827 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1828 // offscreen_target_stencil_render_buffer_ is unused.
1829 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1830 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1831 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1832 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1833 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1834 GLenum offscreen_target_color_format_
;
1835 GLenum offscreen_target_depth_format_
;
1836 GLenum offscreen_target_stencil_format_
;
1837 GLsizei offscreen_target_samples_
;
1838 GLboolean offscreen_target_buffer_preserved_
;
1840 // The copy that is saved when SwapBuffers is called.
1841 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1842 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1843 scoped_refptr
<TextureRef
>
1844 offscreen_saved_color_texture_info_
;
1846 // The copy that is used as the destination for multi-sample resolves.
1847 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1848 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1849 GLenum offscreen_saved_color_format_
;
1851 scoped_ptr
<QueryManager
> query_manager_
;
1853 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1855 scoped_ptr
<ImageManager
> image_manager_
;
1857 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1859 WaitSyncPointCallback wait_sync_point_callback_
;
1861 ShaderCacheCallback shader_cache_callback_
;
1863 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1865 // The format of the back buffer_
1866 GLenum back_buffer_color_format_
;
1867 bool back_buffer_has_depth_
;
1868 bool back_buffer_has_stencil_
;
1872 // Backbuffer attachments that are currently undefined.
1873 uint32 backbuffer_needs_clear_bits_
;
1875 // The current decoder error communicates the decoder error through command
1876 // processing functions that do not return the error value. Should be set only
1877 // if not returning an error.
1878 error::Error current_decoder_error_
;
1880 bool use_shader_translator_
;
1881 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1882 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1884 DisallowedFeatures disallowed_features_
;
1886 // Cached from ContextGroup
1887 const Validators
* validators_
;
1888 scoped_refptr
<FeatureInfo
> feature_info_
;
1892 // Number of commands remaining to be processed in DoCommands().
1893 int commands_to_process_
;
1895 bool has_robustness_extension_
;
1896 error::ContextLostReason context_lost_reason_
;
1897 bool context_was_lost_
;
1898 bool reset_by_robustness_extension_
;
1899 bool supports_post_sub_buffer_
;
1901 // These flags are used to override the state of the shared feature_info_
1902 // member. Because the same FeatureInfo instance may be shared among many
1903 // contexts, the assumptions on the availablity of extensions in WebGL
1904 // contexts may be broken. These flags override the shared state to preserve
1906 bool force_webgl_glsl_validation_
;
1907 bool derivatives_explicitly_enabled_
;
1908 bool frag_depth_explicitly_enabled_
;
1909 bool draw_buffers_explicitly_enabled_
;
1910 bool shader_texture_lod_explicitly_enabled_
;
1912 bool compile_shader_always_succeeds_
;
1914 // An optional behaviour to lose the context and group when OOM.
1915 bool lose_context_when_out_of_memory_
;
1918 bool service_logging_
;
1920 #if defined(OS_MACOSX)
1921 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1922 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1925 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1926 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1928 // Cached values of the currently assigned viewport dimensions.
1929 GLsizei viewport_max_width_
;
1930 GLsizei viewport_max_height_
;
1932 // Command buffer stats.
1933 base::TimeDelta total_processing_commands_time_
;
1935 // States related to each manager.
1936 DecoderTextureState texture_state_
;
1937 DecoderFramebufferState framebuffer_state_
;
1939 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1940 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1941 const unsigned char* cb_command_trace_category_
;
1942 const unsigned char* gpu_decoder_category_
;
1943 int gpu_trace_level_
;
1944 bool gpu_trace_commands_
;
1945 bool gpu_debug_commands_
;
1947 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1949 // Used to validate multisample renderbuffers if needed
1950 GLuint validation_texture_
;
1951 GLuint validation_fbo_multisample_
;
1952 GLuint validation_fbo_
;
1954 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1955 uint32 immediate_data_size
,
1958 // A struct to hold info about each command.
1959 struct CommandInfo
{
1960 CmdHandler cmd_handler
;
1961 uint8 arg_flags
; // How to handle the arguments for this command
1962 uint8 cmd_flags
; // How to handle this command
1963 uint16 arg_count
; // How many arguments are expected for this command.
1966 // A table of CommandInfo for all the commands.
1967 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1969 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1972 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1973 #define GLES2_CMD_OP(name) \
1975 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1976 cmds::name::cmd_flags, \
1977 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1980 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1984 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1985 const char* function_name
, ErrorState
* error_state
)
1986 : function_name_(function_name
),
1987 error_state_(error_state
) {
1988 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1991 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1992 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1995 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1996 TextureUnit
& info
= state
->texture_units
[0];
1998 scoped_refptr
<TextureRef
> texture_ref
;
2001 texture_ref
= info
.bound_texture_2d
;
2003 case GL_TEXTURE_CUBE_MAP
:
2004 texture_ref
= info
.bound_texture_cube_map
;
2006 case GL_TEXTURE_EXTERNAL_OES
:
2007 texture_ref
= info
.bound_texture_external_oes
;
2009 case GL_TEXTURE_RECTANGLE_ARB
:
2010 texture_ref
= info
.bound_texture_rectangle_arb
;
2016 if (texture_ref
.get()) {
2017 last_id
= texture_ref
->service_id();
2022 glBindTexture(target
, last_id
);
2023 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2026 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2031 ScopedGLErrorSuppressor
suppressor(
2032 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2034 // TODO(apatrick): Check if there are any other states that need to be reset
2035 // before binding a new texture.
2036 glActiveTexture(GL_TEXTURE0
);
2037 glBindTexture(target
, id
);
2040 ScopedTextureBinder::~ScopedTextureBinder() {
2041 ScopedGLErrorSuppressor
suppressor(
2042 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2043 RestoreCurrentTextureBindings(state_
, target_
);
2046 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2049 ScopedGLErrorSuppressor
suppressor(
2050 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2051 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2054 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2055 ScopedGLErrorSuppressor
suppressor(
2056 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2057 state_
->RestoreRenderbufferBindings();
2060 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2062 : decoder_(decoder
) {
2063 ScopedGLErrorSuppressor
suppressor(
2064 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2065 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2066 decoder
->OnFboChanged();
2069 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2070 ScopedGLErrorSuppressor
suppressor(
2071 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2072 decoder_
->RestoreCurrentFramebufferBindings();
2075 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2076 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2077 : decoder_(decoder
) {
2078 resolve_and_bind_
= (
2079 decoder_
->offscreen_target_frame_buffer_
.get() &&
2080 decoder_
->IsOffscreenBufferMultisampled() &&
2081 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2082 enforce_internal_framebuffer
));
2083 if (!resolve_and_bind_
)
2086 ScopedGLErrorSuppressor
suppressor(
2087 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2088 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2089 decoder_
->offscreen_target_frame_buffer_
->id());
2092 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2093 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2094 new BackFramebuffer(decoder_
));
2095 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2096 decoder_
->offscreen_resolved_color_texture_
.reset(
2097 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2098 decoder_
->offscreen_resolved_color_texture_
->Create();
2100 DCHECK(decoder_
->offscreen_saved_color_format_
);
2101 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2102 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2104 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2105 decoder_
->offscreen_resolved_color_texture_
.get());
2106 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2107 GL_FRAMEBUFFER_COMPLETE
) {
2108 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2109 << "because offscreen resolved FBO was incomplete.";
2113 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2115 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2117 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2118 const int width
= decoder_
->offscreen_size_
.width();
2119 const int height
= decoder_
->offscreen_size_
.height();
2120 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2121 decoder
->BlitFramebufferHelper(0,
2129 GL_COLOR_BUFFER_BIT
,
2131 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2134 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2135 if (!resolve_and_bind_
)
2138 ScopedGLErrorSuppressor
suppressor(
2139 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2140 decoder_
->RestoreCurrentFramebufferBindings();
2141 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2142 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2146 BackTexture::BackTexture(
2147 MemoryTracker
* memory_tracker
,
2148 ContextState
* state
)
2149 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2151 bytes_allocated_(0),
2155 BackTexture::~BackTexture() {
2156 // This does not destroy the render texture because that would require that
2157 // the associated GL context was current. Just check that it was explicitly
2162 void BackTexture::Create() {
2163 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2164 state_
->GetErrorState());
2166 glGenTextures(1, &id_
);
2167 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2168 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2169 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2170 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2171 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2173 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2174 // never called on an offscreen context, no data will ever be uploaded to the
2175 // saved offscreen color texture (it is deferred until to when SwapBuffers
2176 // is called). My idea is that some nvidia drivers might have a bug where
2177 // deleting a texture that has never been populated might cause a
2180 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2182 bytes_allocated_
= 16u * 16u * 4u;
2183 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2186 bool BackTexture::AllocateStorage(
2187 const gfx::Size
& size
, GLenum format
, bool zero
) {
2189 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2190 state_
->GetErrorState());
2191 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2192 uint32 image_size
= 0;
2193 GLES2Util::ComputeImageDataSizes(
2194 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2197 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2201 scoped_ptr
<char[]> zero_data
;
2203 zero_data
.reset(new char[image_size
]);
2204 memset(zero_data
.get(), 0, image_size
);
2207 glTexImage2D(GL_TEXTURE_2D
,
2219 bool success
= glGetError() == GL_NO_ERROR
;
2221 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2222 bytes_allocated_
= image_size
;
2223 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2228 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2230 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2231 state_
->GetErrorState());
2232 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2233 glCopyTexImage2D(GL_TEXTURE_2D
,
2242 void BackTexture::Destroy() {
2244 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2245 state_
->GetErrorState());
2246 glDeleteTextures(1, &id_
);
2249 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2250 bytes_allocated_
= 0;
2253 void BackTexture::Invalidate() {
2257 BackRenderbuffer::BackRenderbuffer(
2258 RenderbufferManager
* renderbuffer_manager
,
2259 MemoryTracker
* memory_tracker
,
2260 ContextState
* state
)
2261 : renderbuffer_manager_(renderbuffer_manager
),
2262 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2264 bytes_allocated_(0),
2268 BackRenderbuffer::~BackRenderbuffer() {
2269 // This does not destroy the render buffer because that would require that
2270 // the associated GL context was current. Just check that it was explicitly
2275 void BackRenderbuffer::Create() {
2276 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2277 state_
->GetErrorState());
2279 glGenRenderbuffersEXT(1, &id_
);
2282 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2283 const gfx::Size
& size
,
2286 ScopedGLErrorSuppressor
suppressor(
2287 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2288 ScopedRenderBufferBinder
binder(state_
, id_
);
2290 uint32 estimated_size
= 0;
2291 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2292 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2296 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2301 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2306 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2313 bool success
= glGetError() == GL_NO_ERROR
;
2315 // Mark the previously allocated bytes as free.
2316 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2317 bytes_allocated_
= estimated_size
;
2318 // Track the newly allocated bytes.
2319 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2324 void BackRenderbuffer::Destroy() {
2326 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2327 state_
->GetErrorState());
2328 glDeleteRenderbuffersEXT(1, &id_
);
2331 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2332 bytes_allocated_
= 0;
2335 void BackRenderbuffer::Invalidate() {
2339 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2340 : decoder_(decoder
),
2344 BackFramebuffer::~BackFramebuffer() {
2345 // This does not destroy the frame buffer because that would require that
2346 // the associated GL context was current. Just check that it was explicitly
2351 void BackFramebuffer::Create() {
2352 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2353 decoder_
->GetErrorState());
2355 glGenFramebuffersEXT(1, &id_
);
2358 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2360 ScopedGLErrorSuppressor
suppressor(
2361 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2362 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2363 GLuint attach_id
= texture
? texture
->id() : 0;
2364 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2365 GL_COLOR_ATTACHMENT0
,
2371 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2372 BackRenderbuffer
* render_buffer
) {
2374 ScopedGLErrorSuppressor
suppressor(
2375 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2376 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2377 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2378 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2384 void BackFramebuffer::Destroy() {
2386 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2387 decoder_
->GetErrorState());
2388 glDeleteFramebuffersEXT(1, &id_
);
2393 void BackFramebuffer::Invalidate() {
2397 GLenum
BackFramebuffer::CheckStatus() {
2399 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2400 decoder_
->GetErrorState());
2401 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2402 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2405 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2406 return new GLES2DecoderImpl(group
);
2409 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2412 logger_(&debug_marker_manager_
),
2413 state_(group_
->feature_info(), this, &logger_
),
2414 unpack_flip_y_(false),
2415 unpack_premultiply_alpha_(false),
2416 unpack_unpremultiply_alpha_(false),
2417 attrib_0_buffer_id_(0),
2418 attrib_0_buffer_matches_value_(true),
2420 fixed_attrib_buffer_id_(0),
2421 fixed_attrib_buffer_size_(0),
2422 offscreen_target_color_format_(0),
2423 offscreen_target_depth_format_(0),
2424 offscreen_target_stencil_format_(0),
2425 offscreen_target_samples_(0),
2426 offscreen_target_buffer_preserved_(true),
2427 offscreen_saved_color_format_(0),
2428 back_buffer_color_format_(0),
2429 back_buffer_has_depth_(false),
2430 back_buffer_has_stencil_(false),
2431 surfaceless_(false),
2432 backbuffer_needs_clear_bits_(0),
2433 current_decoder_error_(error::kNoError
),
2434 use_shader_translator_(true),
2435 validators_(group_
->feature_info()->validators()),
2436 feature_info_(group_
->feature_info()),
2438 has_robustness_extension_(false),
2439 context_lost_reason_(error::kUnknown
),
2440 context_was_lost_(false),
2441 reset_by_robustness_extension_(false),
2442 supports_post_sub_buffer_(false),
2443 force_webgl_glsl_validation_(false),
2444 derivatives_explicitly_enabled_(false),
2445 frag_depth_explicitly_enabled_(false),
2446 draw_buffers_explicitly_enabled_(false),
2447 shader_texture_lod_explicitly_enabled_(false),
2448 compile_shader_always_succeeds_(false),
2449 lose_context_when_out_of_memory_(false),
2450 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2451 switches::kEnableGPUServiceLoggingGPU
)),
2452 viewport_max_width_(0),
2453 viewport_max_height_(0),
2454 texture_state_(group_
->feature_info()
2456 .texsubimage2d_faster_than_teximage2d
),
2457 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2458 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2459 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2460 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2461 gpu_trace_level_(2),
2462 gpu_trace_commands_(false),
2463 gpu_debug_commands_(false),
2464 validation_texture_(0),
2465 validation_fbo_multisample_(0),
2466 validation_fbo_(0) {
2469 attrib_0_value_
.v
[0] = 0.0f
;
2470 attrib_0_value_
.v
[1] = 0.0f
;
2471 attrib_0_value_
.v
[2] = 0.0f
;
2472 attrib_0_value_
.v
[3] = 1.0f
;
2474 // The shader translator is used for WebGL even when running on EGL
2475 // because additional restrictions are needed (like only enabling
2476 // GL_OES_standard_derivatives on demand). It is used for the unit
2477 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2478 // the empty string to CompileShader and this is not a valid shader.
2479 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2480 base::CommandLine::ForCurrentProcess()->HasSwitch(
2481 switches::kDisableGLSLTranslator
)) {
2482 use_shader_translator_
= false;
2486 GLES2DecoderImpl::~GLES2DecoderImpl() {
2489 bool GLES2DecoderImpl::Initialize(
2490 const scoped_refptr
<gfx::GLSurface
>& surface
,
2491 const scoped_refptr
<gfx::GLContext
>& context
,
2493 const gfx::Size
& offscreen_size
,
2494 const DisallowedFeatures
& disallowed_features
,
2495 const std::vector
<int32
>& attribs
) {
2496 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2497 DCHECK(context
->IsCurrent(surface
.get()));
2498 DCHECK(!context_
.get());
2499 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2501 ContextCreationAttribHelper attrib_parser
;
2502 if (!attrib_parser
.Parse(attribs
))
2505 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2508 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2510 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2511 switches::kEnableGPUDebugging
)) {
2515 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2516 switches::kEnableGPUCommandLogging
)) {
2517 set_log_commands(true);
2520 compile_shader_always_succeeds_
=
2521 base::CommandLine::ForCurrentProcess()->HasSwitch(
2522 switches::kCompileShaderAlwaysSucceeds
);
2524 // Take ownership of the context and surface. The surface can be replaced with
2529 // Create GPU Tracer for timing values.
2530 gpu_tracer_
.reset(new GPUTracer(this));
2532 // Save the loseContextWhenOutOfMemory context creation attribute.
2533 lose_context_when_out_of_memory_
=
2534 attrib_parser
.lose_context_when_out_of_memory
;
2536 // If the failIfMajorPerformanceCaveat context creation attribute was true
2537 // and we are using a software renderer, fail.
2538 if (attrib_parser
.fail_if_major_perf_caveat
&&
2539 feature_info_
->feature_flags().is_swiftshader
) {
2540 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2545 if (!group_
->Initialize(this, disallowed_features
)) {
2546 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2547 << "failed to initialize.";
2548 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2554 if (attrib_parser
.es3_context_required
&&
2555 feature_info_
->IsES3Capable()) {
2556 feature_info_
->EnableES3Validators();
2557 set_unsafe_es3_apis_enabled(true);
2560 disallowed_features_
= disallowed_features
;
2562 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2563 vertex_array_manager_
.reset(new VertexArrayManager());
2565 GLuint default_vertex_attrib_service_id
= 0;
2566 if (features().native_vertex_array_object
) {
2567 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2568 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2571 state_
.default_vertex_attrib_manager
=
2572 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2574 state_
.default_vertex_attrib_manager
->Initialize(
2575 group_
->max_vertex_attribs(),
2576 feature_info_
->workarounds().init_vertex_attributes
);
2578 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2579 DoBindVertexArrayOES(0);
2581 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2583 image_manager_
.reset(new ImageManager
);
2585 util_
.set_num_compressed_texture_formats(
2586 validators_
->compressed_texture_format
.GetValues().size());
2588 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2589 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2590 // OpenGL ES 2.0 does not have this issue.
2591 glEnableVertexAttribArray(0);
2593 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2594 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2595 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2596 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2597 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2599 state_
.texture_units
.resize(group_
->max_texture_units());
2600 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2601 glActiveTexture(GL_TEXTURE0
+ tt
);
2602 // We want the last bind to be 2D.
2604 if (features().oes_egl_image_external
) {
2605 ref
= texture_manager()->GetDefaultTextureInfo(
2606 GL_TEXTURE_EXTERNAL_OES
);
2607 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2608 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2610 if (features().arb_texture_rectangle
) {
2611 ref
= texture_manager()->GetDefaultTextureInfo(
2612 GL_TEXTURE_RECTANGLE_ARB
);
2613 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2614 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2616 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2617 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2618 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2619 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2620 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2621 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2623 glActiveTexture(GL_TEXTURE0
);
2626 // cache ALPHA_BITS result for re-use with clear behaviour
2627 GLint alpha_bits
= 0;
2630 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2631 features().chromium_framebuffer_multisample
) {
2632 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2633 // max_sample_count must be initialized to a sane value. If
2634 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2635 GLint max_sample_count
= 1;
2636 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2637 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2640 offscreen_target_samples_
= 1;
2642 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2644 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2645 const bool rgb8_supported
=
2646 context_
->HasExtension("GL_OES_rgb8_rgba8");
2647 // The only available default render buffer formats in GLES2 have very
2648 // little precision. Don't enable multisampling unless 8-bit render
2649 // buffer formats are available--instead fall back to 8-bit textures.
2650 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2651 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2654 offscreen_target_samples_
= 1;
2655 offscreen_target_color_format_
=
2656 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2661 // ANGLE only supports packed depth/stencil formats, so use it if it is
2663 const bool depth24_stencil8_supported
=
2664 feature_info_
->feature_flags().packed_depth24_stencil8
;
2665 VLOG(1) << "GL_OES_packed_depth_stencil "
2666 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2667 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2668 depth24_stencil8_supported
) {
2669 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2670 offscreen_target_stencil_format_
= 0;
2672 // It may be the case that this depth/stencil combination is not
2673 // supported, but this will be checked later by CheckFramebufferStatus.
2674 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2675 GL_DEPTH_COMPONENT16
: 0;
2676 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2677 GL_STENCIL_INDEX8
: 0;
2680 offscreen_target_color_format_
=
2681 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2685 // If depth is requested at all, use the packed depth stencil format if
2686 // it's available, as some desktop GL drivers don't support any non-packed
2687 // formats for depth attachments.
2688 const bool depth24_stencil8_supported
=
2689 feature_info_
->feature_flags().packed_depth24_stencil8
;
2690 VLOG(1) << "GL_EXT_packed_depth_stencil "
2691 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2693 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2694 depth24_stencil8_supported
) {
2695 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2696 offscreen_target_stencil_format_
= 0;
2698 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2699 GL_DEPTH_COMPONENT
: 0;
2700 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2701 GL_STENCIL_INDEX
: 0;
2705 offscreen_saved_color_format_
=
2706 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2710 // Create the target frame buffer. This is the one that the client renders
2712 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2713 offscreen_target_frame_buffer_
->Create();
2714 // Due to GLES2 format limitations, either the color texture (for
2715 // non-multisampling) or the color render buffer (for multisampling) will be
2716 // attached to the offscreen frame buffer. The render buffer has more
2717 // limited formats available to it, but the texture can't do multisampling.
2718 if (IsOffscreenBufferMultisampled()) {
2719 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2720 renderbuffer_manager(), memory_tracker(), &state_
));
2721 offscreen_target_color_render_buffer_
->Create();
2723 offscreen_target_color_texture_
.reset(new BackTexture(
2724 memory_tracker(), &state_
));
2725 offscreen_target_color_texture_
->Create();
2727 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2728 renderbuffer_manager(), memory_tracker(), &state_
));
2729 offscreen_target_depth_render_buffer_
->Create();
2730 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2731 renderbuffer_manager(), memory_tracker(), &state_
));
2732 offscreen_target_stencil_render_buffer_
->Create();
2734 // Create the saved offscreen texture. The target frame buffer is copied
2735 // here when SwapBuffers is called.
2736 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2737 offscreen_saved_frame_buffer_
->Create();
2739 offscreen_saved_color_texture_
.reset(new BackTexture(
2740 memory_tracker(), &state_
));
2741 offscreen_saved_color_texture_
->Create();
2743 // Allocate the render buffers at their initial size and check the status
2744 // of the frame buffers is okay.
2745 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2746 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2751 state_
.viewport_width
= offscreen_size
.width();
2752 state_
.viewport_height
= offscreen_size
.height();
2754 // Allocate the offscreen saved color texture.
2755 DCHECK(offscreen_saved_color_format_
);
2756 offscreen_saved_color_texture_
->AllocateStorage(
2757 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2759 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2760 offscreen_saved_color_texture_
.get());
2761 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2762 GL_FRAMEBUFFER_COMPLETE
) {
2763 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2768 // Bind to the new default frame buffer (the offscreen target frame buffer).
2769 // This should now be associated with ID zero.
2770 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2772 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2773 // These are NOT if the back buffer has these proprorties. They are
2774 // if we want the command buffer to enforce them regardless of what
2775 // the real backbuffer is assuming the real back buffer gives us more than
2776 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2777 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2778 // can't do anything about that.
2780 if (!surfaceless_
) {
2781 GLint depth_bits
= 0;
2782 GLint stencil_bits
= 0;
2784 bool default_fb
= (GetBackbufferServiceId() == 0);
2786 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2787 glGetFramebufferAttachmentParameterivEXT(
2789 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2790 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2791 glGetFramebufferAttachmentParameterivEXT(
2793 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2794 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2795 glGetFramebufferAttachmentParameterivEXT(
2797 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2798 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2800 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2801 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2802 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2805 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2806 // the user requested RGB then RGB. If the user did not specify a
2807 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2808 back_buffer_color_format_
=
2809 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2810 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2811 back_buffer_has_stencil_
=
2812 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2815 state_
.viewport_width
= surface
->GetSize().width();
2816 state_
.viewport_height
= surface
->GetSize().height();
2819 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2820 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2821 // isn't well documented; it was discovered in the Khronos OpenGL ES
2822 // mailing list archives. It also implicitly enables the desktop GL
2823 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2824 // variable in fragment shaders.
2825 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2826 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2827 glEnable(GL_POINT_SPRITE
);
2830 has_robustness_extension_
=
2831 context
->HasExtension("GL_ARB_robustness") ||
2832 context
->HasExtension("GL_KHR_robustness") ||
2833 context
->HasExtension("GL_EXT_robustness");
2835 if (!InitializeShaderTranslator()) {
2839 GLint viewport_params
[4] = { 0 };
2840 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2841 viewport_max_width_
= viewport_params
[0];
2842 viewport_max_height_
= viewport_params
[1];
2844 state_
.scissor_width
= state_
.viewport_width
;
2845 state_
.scissor_height
= state_
.viewport_height
;
2847 // Set all the default state because some GL drivers get it wrong.
2848 state_
.InitCapabilities(NULL
);
2849 state_
.InitState(NULL
);
2850 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2852 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2853 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2854 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2855 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2856 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2858 bool call_gl_clear
= !surfaceless_
;
2859 #if defined(OS_ANDROID)
2860 // Temporary workaround for Android WebView because this clear ignores the
2861 // clip and corrupts that external UI of the App. Not calling glClear is ok
2862 // because the system already clears the buffer before each draw. Proper
2863 // fix might be setting the scissor clip properly before initialize. See
2864 // crbug.com/259023 for details.
2865 call_gl_clear
= surface_
->GetHandle();
2867 if (call_gl_clear
) {
2868 // On configs where we report no alpha, if the underlying surface has
2869 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
2870 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
2872 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2875 // Clear the backbuffer.
2876 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2878 // Restore alpha clear value if we changed it.
2880 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
2884 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2885 if (feature_info_
->workarounds()
2886 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2887 !surface
->IsOffscreen())
2888 supports_post_sub_buffer_
= false;
2890 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2891 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2894 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2895 context_
->SetUnbindFboOnMakeCurrent();
2898 // Only compositor contexts are known to use only the subset of GL
2899 // that can be safely migrated between the iGPU and the dGPU. Mark
2900 // those contexts as safe to forcibly transition between the GPUs.
2901 // http://crbug.com/180876, http://crbug.com/227228
2903 context_
->SetSafeToForceGpuSwitch();
2905 async_pixel_transfer_manager_
.reset(
2906 AsyncPixelTransferManager::Create(context
.get()));
2907 async_pixel_transfer_manager_
->Initialize(texture_manager());
2909 if (workarounds().gl_clear_broken
) {
2910 DCHECK(!clear_framebuffer_blit_
.get());
2911 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2912 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2913 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2917 framebuffer_manager()->AddObserver(this);
2922 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2923 DCHECK(initialized());
2925 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2926 Capabilities::ShaderPrecision
* shader_precision
) {
2927 GLint range
[2] = {0, 0};
2928 GLint precision
= 0;
2929 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2930 shader_precision
->min_range
= range
[0];
2931 shader_precision
->max_range
= range
[1];
2932 shader_precision
->precision
= precision
;
2934 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2935 &caps
.max_combined_texture_image_units
);
2936 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2937 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2938 &caps
.max_fragment_uniform_vectors
);
2939 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2940 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2941 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2942 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2943 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2944 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2945 &caps
.max_vertex_texture_image_units
);
2946 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2947 &caps
.max_vertex_uniform_vectors
);
2948 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2949 &caps
.num_compressed_texture_formats
);
2950 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2951 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2952 &caps
.bind_generates_resource_chromium
);
2953 if (unsafe_es3_apis_enabled()) {
2954 // TODO(zmo): Note that some parameter values could be more than 32-bit,
2955 // but for now we clamp them to 32-bit max.
2956 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
2957 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
2958 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
2959 DoGetIntegerv(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
2960 &caps
.max_combined_fragment_uniform_components
);
2961 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
2962 &caps
.max_combined_uniform_blocks
);
2963 DoGetIntegerv(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
2964 &caps
.max_combined_vertex_uniform_components
);
2965 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
2966 DoGetIntegerv(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
2967 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
2968 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
2969 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
2970 &caps
.max_fragment_input_components
);
2971 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
2972 &caps
.max_fragment_uniform_blocks
);
2973 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
2974 &caps
.max_fragment_uniform_components
);
2975 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
2976 &caps
.max_program_texel_offset
);
2977 DoGetIntegerv(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
2978 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
2979 &caps
.max_transform_feedback_interleaved_components
);
2980 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
2981 &caps
.max_transform_feedback_separate_attribs
);
2982 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
2983 &caps
.max_transform_feedback_separate_components
);
2984 DoGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
2985 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
2986 &caps
.max_uniform_buffer_bindings
);
2987 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
2988 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
2989 &caps
.max_vertex_output_components
);
2990 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
2991 &caps
.max_vertex_uniform_blocks
);
2992 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
2993 &caps
.max_vertex_uniform_components
);
2994 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
2995 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
2996 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
2997 &caps
.num_program_binary_formats
);
2998 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
2999 &caps
.uniform_buffer_offset_alignment
);
3000 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3001 caps
.major_version
= 3;
3002 caps
.minor_version
= 0;
3004 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3005 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3006 unsafe_es3_apis_enabled()) {
3007 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3010 caps
.egl_image_external
=
3011 feature_info_
->feature_flags().oes_egl_image_external
;
3012 caps
.texture_format_atc
=
3013 feature_info_
->feature_flags().ext_texture_format_atc
;
3014 caps
.texture_format_bgra8888
=
3015 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3016 caps
.texture_format_dxt1
=
3017 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3018 caps
.texture_format_dxt5
=
3019 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3020 caps
.texture_format_etc1
=
3021 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3022 caps
.texture_format_etc1_npot
=
3023 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3024 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3025 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3026 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3027 caps
.discard_framebuffer
=
3028 feature_info_
->feature_flags().ext_discard_framebuffer
;
3029 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3031 #if defined(OS_MACOSX)
3032 // This is unconditionally true on mac, no need to test for it at runtime.
3033 caps
.iosurface
= true;
3036 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3039 caps
.blend_equation_advanced
=
3040 feature_info_
->feature_flags().blend_equation_advanced
;
3041 caps
.blend_equation_advanced_coherent
=
3042 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3043 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3047 void GLES2DecoderImpl::UpdateCapabilities() {
3048 util_
.set_num_compressed_texture_formats(
3049 validators_
->compressed_texture_format
.GetValues().size());
3050 util_
.set_num_shader_binary_formats(
3051 validators_
->shader_binary_format
.GetValues().size());
3054 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3055 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3057 if (!use_shader_translator_
) {
3060 ShBuiltInResources resources
;
3061 ShInitBuiltInResources(&resources
);
3062 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3063 resources
.MaxVertexUniformVectors
=
3064 group_
->max_vertex_uniform_vectors();
3065 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3066 resources
.MaxVertexTextureImageUnits
=
3067 group_
->max_vertex_texture_image_units();
3068 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3069 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3070 resources
.MaxFragmentUniformVectors
=
3071 group_
->max_fragment_uniform_vectors();
3072 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3073 resources
.MaxExpressionComplexity
= 256;
3074 resources
.MaxCallStackDepth
= 256;
3076 GLint range
[2] = { 0, 0 };
3077 GLint precision
= 0;
3078 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3080 resources
.FragmentPrecisionHigh
=
3081 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3083 if (force_webgl_glsl_validation_
) {
3084 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3085 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3086 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3087 if (!draw_buffers_explicitly_enabled_
)
3088 resources
.MaxDrawBuffers
= 1;
3089 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3090 resources
.NV_draw_buffers
=
3091 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3093 resources
.OES_standard_derivatives
=
3094 features().oes_standard_derivatives
? 1 : 0;
3095 resources
.ARB_texture_rectangle
=
3096 features().arb_texture_rectangle
? 1 : 0;
3097 resources
.OES_EGL_image_external
=
3098 features().oes_egl_image_external
? 1 : 0;
3099 resources
.EXT_draw_buffers
=
3100 features().ext_draw_buffers
? 1 : 0;
3101 resources
.EXT_frag_depth
=
3102 features().ext_frag_depth
? 1 : 0;
3103 resources
.EXT_shader_texture_lod
=
3104 features().ext_shader_texture_lod
? 1 : 0;
3105 resources
.NV_draw_buffers
=
3106 features().nv_draw_buffers
? 1 : 0;
3109 ShShaderSpec shader_spec
;
3110 if (force_webgl_glsl_validation_
) {
3111 shader_spec
= unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3113 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3116 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3117 features().enable_shader_name_hashing
)
3118 resources
.HashFunction
= &CityHash64
;
3120 resources
.HashFunction
= NULL
;
3121 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3122 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3123 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3124 int driver_bug_workarounds
= 0;
3125 if (workarounds().needs_glsl_built_in_function_emulation
)
3126 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3127 if (workarounds().init_gl_position_in_vertex_shader
)
3128 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3129 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3130 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3131 if (workarounds().init_varyings_without_static_use
)
3132 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3133 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3134 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3135 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3136 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3137 if (workarounds().regenerate_struct_names
)
3138 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3140 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3141 switches::kEmulateShaderPrecision
))
3142 resources
.WEBGL_debug_shader_precision
= true;
3144 vertex_translator_
= shader_translator_cache()->GetTranslator(
3148 implementation_type
,
3149 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3150 if (!vertex_translator_
.get()) {
3151 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3156 fragment_translator_
= shader_translator_cache()->GetTranslator(
3160 implementation_type
,
3161 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3162 if (!fragment_translator_
.get()) {
3163 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3170 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3171 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3172 if (GetBuffer(client_ids
[ii
])) {
3176 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3177 glGenBuffersARB(n
, service_ids
.get());
3178 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3179 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3184 bool GLES2DecoderImpl::GenFramebuffersHelper(
3185 GLsizei n
, const GLuint
* client_ids
) {
3186 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3187 if (GetFramebuffer(client_ids
[ii
])) {
3191 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3192 glGenFramebuffersEXT(n
, service_ids
.get());
3193 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3194 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3199 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3200 GLsizei n
, const GLuint
* client_ids
) {
3201 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3202 if (GetRenderbuffer(client_ids
[ii
])) {
3206 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3207 glGenRenderbuffersEXT(n
, service_ids
.get());
3208 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3209 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3214 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3215 const GLuint
* client_ids
) {
3216 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3217 if (GetValuebuffer(client_ids
[ii
])) {
3221 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3222 CreateValuebuffer(client_ids
[ii
]);
3227 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3228 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3229 if (GetTexture(client_ids
[ii
])) {
3233 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3234 glGenTextures(n
, service_ids
.get());
3235 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3236 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3241 void GLES2DecoderImpl::DeleteBuffersHelper(
3242 GLsizei n
, const GLuint
* client_ids
) {
3243 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3244 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3245 if (buffer
&& !buffer
->IsDeleted()) {
3246 buffer
->RemoveMappedRange();
3247 state_
.vertex_attrib_manager
->Unbind(buffer
);
3248 if (state_
.bound_array_buffer
.get() == buffer
) {
3249 state_
.bound_array_buffer
= NULL
;
3251 RemoveBuffer(client_ids
[ii
]);
3256 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3257 GLsizei n
, const GLuint
* client_ids
) {
3258 bool supports_separate_framebuffer_binds
=
3259 features().chromium_framebuffer_multisample
;
3261 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3262 Framebuffer
* framebuffer
=
3263 GetFramebuffer(client_ids
[ii
]);
3264 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3265 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3266 GLenum target
= supports_separate_framebuffer_binds
?
3267 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3269 // Unbind attachments on FBO before deletion.
3270 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3271 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3273 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3274 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3275 framebuffer_state_
.clear_state_dirty
= true;
3277 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3278 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3279 GLenum target
= supports_separate_framebuffer_binds
?
3280 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3281 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3284 RemoveFramebuffer(client_ids
[ii
]);
3289 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3290 GLsizei n
, const GLuint
* client_ids
) {
3291 bool supports_separate_framebuffer_binds
=
3292 features().chromium_framebuffer_multisample
;
3293 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3294 Renderbuffer
* renderbuffer
=
3295 GetRenderbuffer(client_ids
[ii
]);
3296 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3297 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3298 state_
.bound_renderbuffer
= NULL
;
3300 // Unbind from current framebuffers.
3301 if (supports_separate_framebuffer_binds
) {
3302 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3303 framebuffer_state_
.bound_read_framebuffer
3304 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3306 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3307 framebuffer_state_
.bound_draw_framebuffer
3308 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3311 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3312 framebuffer_state_
.bound_draw_framebuffer
3313 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3316 framebuffer_state_
.clear_state_dirty
= true;
3317 RemoveRenderbuffer(client_ids
[ii
]);
3322 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3324 const GLuint
* client_ids
) {
3325 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3326 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3328 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3329 state_
.bound_valuebuffer
= NULL
;
3331 RemoveValuebuffer(client_ids
[ii
]);
3336 void GLES2DecoderImpl::DeleteTexturesHelper(
3337 GLsizei n
, const GLuint
* client_ids
) {
3338 bool supports_separate_framebuffer_binds
=
3339 features().chromium_framebuffer_multisample
;
3340 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3341 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3343 Texture
* texture
= texture_ref
->texture();
3344 if (texture
->IsAttachedToFramebuffer()) {
3345 framebuffer_state_
.clear_state_dirty
= true;
3347 // Unbind texture_ref from texture_ref units.
3348 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3349 state_
.texture_units
[jj
].Unbind(texture_ref
);
3351 // Unbind from current framebuffers.
3352 if (supports_separate_framebuffer_binds
) {
3353 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3354 framebuffer_state_
.bound_read_framebuffer
3355 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3357 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3358 framebuffer_state_
.bound_draw_framebuffer
3359 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3362 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3363 framebuffer_state_
.bound_draw_framebuffer
3364 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3367 #if defined(OS_MACOSX)
3368 GLuint service_id
= texture
->service_id();
3369 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3370 ReleaseIOSurfaceForTexture(service_id
);
3373 RemoveTexture(client_ids
[ii
]);
3378 // } // anonymous namespace
3380 bool GLES2DecoderImpl::MakeCurrent() {
3381 if (!context_
.get())
3384 if (WasContextLost()) {
3385 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3389 if (!context_
->MakeCurrent(surface_
.get())) {
3390 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3391 MarkContextLost(error::kMakeCurrentFailed
);
3392 group_
->LoseContexts(error::kUnknown
);
3396 if (CheckResetStatus()) {
3398 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3399 group_
->LoseContexts(error::kUnknown
);
3403 ProcessFinishedAsyncTransfers();
3405 // Rebind the FBO if it was unbound by the context.
3406 if (workarounds().unbind_fbo_on_context_switch
)
3407 RestoreFramebufferBindings();
3409 framebuffer_state_
.clear_state_dirty
= true;
3414 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3415 ProcessPendingReadPixels();
3416 if (engine() && query_manager_
.get())
3417 query_manager_
->ProcessPendingTransferQueries();
3419 // TODO(epenner): Is there a better place to do this?
3420 // This needs to occur before we execute any batch of commands
3421 // from the client, as the client may have recieved an async
3422 // completion while issuing those commands.
3423 // "DidFlushStart" would be ideal if we had such a callback.
3424 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3427 static void RebindCurrentFramebuffer(
3429 Framebuffer
* framebuffer
,
3430 GLuint back_buffer_service_id
) {
3431 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3433 if (framebuffer_id
== 0) {
3434 framebuffer_id
= back_buffer_service_id
;
3437 glBindFramebufferEXT(target
, framebuffer_id
);
3440 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3441 framebuffer_state_
.clear_state_dirty
= true;
3443 if (!features().chromium_framebuffer_multisample
) {
3444 RebindCurrentFramebuffer(
3446 framebuffer_state_
.bound_draw_framebuffer
.get(),
3447 GetBackbufferServiceId());
3449 RebindCurrentFramebuffer(
3450 GL_READ_FRAMEBUFFER_EXT
,
3451 framebuffer_state_
.bound_read_framebuffer
.get(),
3452 GetBackbufferServiceId());
3453 RebindCurrentFramebuffer(
3454 GL_DRAW_FRAMEBUFFER_EXT
,
3455 framebuffer_state_
.bound_draw_framebuffer
.get(),
3456 GetBackbufferServiceId());
3461 bool GLES2DecoderImpl::CheckFramebufferValid(
3462 Framebuffer
* framebuffer
,
3463 GLenum target
, const char* func_name
) {
3467 if (backbuffer_needs_clear_bits_
) {
3468 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3469 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3470 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3472 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3473 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3475 state_
.SetDeviceDepthMask(GL_TRUE
);
3476 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3477 bool reset_draw_buffer
= false;
3478 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3479 group_
->draw_buffer() == GL_NONE
) {
3480 reset_draw_buffer
= true;
3481 GLenum buf
= GL_BACK
;
3482 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3483 buf
= GL_COLOR_ATTACHMENT0
;
3484 glDrawBuffersARB(1, &buf
);
3486 glClear(backbuffer_needs_clear_bits_
);
3487 if (reset_draw_buffer
) {
3488 GLenum buf
= GL_NONE
;
3489 glDrawBuffersARB(1, &buf
);
3491 backbuffer_needs_clear_bits_
= 0;
3492 RestoreClearState();
3497 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3501 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3502 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3504 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3508 // Are all the attachments cleared?
3509 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3510 texture_manager()->HaveUnclearedMips()) {
3511 if (!framebuffer
->IsCleared()) {
3512 // Can we clear them?
3513 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3514 GL_FRAMEBUFFER_COMPLETE
) {
3516 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3517 "framebuffer incomplete (clear)");
3520 ClearUnclearedAttachments(target
, framebuffer
);
3524 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3525 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3526 GL_FRAMEBUFFER_COMPLETE
) {
3528 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3529 "framebuffer incomplete (check)");
3532 framebuffer_manager()->MarkAsComplete(framebuffer
);
3535 // NOTE: At this point we don't know if the framebuffer is complete but
3536 // we DO know that everything that needs to be cleared has been cleared.
3540 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3541 if (!features().chromium_framebuffer_multisample
) {
3542 bool valid
= CheckFramebufferValid(
3543 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3551 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3552 GL_DRAW_FRAMEBUFFER_EXT
,
3554 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3555 GL_READ_FRAMEBUFFER_EXT
,
3559 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3560 const char* func_name
) {
3561 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3562 framebuffer_state_
.bound_read_framebuffer
.get() :
3563 framebuffer_state_
.bound_draw_framebuffer
.get();
3566 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3568 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3574 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3575 TextureRef
* texture
, GLint level
) {
3576 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3577 framebuffer_state_
.bound_read_framebuffer
.get() :
3578 framebuffer_state_
.bound_draw_framebuffer
.get();
3581 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3582 GL_COLOR_ATTACHMENT0
);
3585 return attachment
->FormsFeedbackLoop(texture
, level
);
3588 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3589 Framebuffer
* framebuffer
=
3590 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3591 if (framebuffer
!= NULL
) {
3592 const Framebuffer::Attachment
* attachment
=
3593 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3595 return gfx::Size(attachment
->width(), attachment
->height());
3597 return gfx::Size(0, 0);
3598 } else if (offscreen_target_frame_buffer_
.get()) {
3599 return offscreen_size_
;
3601 return surface_
->GetSize();
3605 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3606 Framebuffer
* framebuffer
=
3607 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3608 if (framebuffer
!= NULL
) {
3609 return framebuffer
->GetColorAttachmentTextureType();
3611 return GL_UNSIGNED_BYTE
;
3615 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3616 Framebuffer
* framebuffer
=
3617 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3618 if (framebuffer
!= NULL
) {
3619 return framebuffer
->GetColorAttachmentFormat();
3620 } else if (offscreen_target_frame_buffer_
.get()) {
3621 return offscreen_target_color_format_
;
3623 return back_buffer_color_format_
;
3627 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3628 Framebuffer
* framebuffer
=
3629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3630 if (framebuffer
!= NULL
) {
3631 return framebuffer
->GetColorAttachmentFormat();
3632 } else if (offscreen_target_frame_buffer_
.get()) {
3633 return offscreen_target_color_format_
;
3635 return back_buffer_color_format_
;
3639 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3640 if (!offscreen_saved_color_texture_info_
.get())
3642 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3643 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3644 texture_manager()->SetLevelInfo(
3645 offscreen_saved_color_texture_info_
.get(),
3649 offscreen_size_
.width(),
3650 offscreen_size_
.height(),
3656 texture_manager()->SetParameteri(
3657 "UpdateParentTextureInfo",
3659 offscreen_saved_color_texture_info_
.get(),
3660 GL_TEXTURE_MAG_FILTER
,
3662 texture_manager()->SetParameteri(
3663 "UpdateParentTextureInfo",
3665 offscreen_saved_color_texture_info_
.get(),
3666 GL_TEXTURE_MIN_FILTER
,
3668 texture_manager()->SetParameteri(
3669 "UpdateParentTextureInfo",
3671 offscreen_saved_color_texture_info_
.get(),
3674 texture_manager()->SetParameteri(
3675 "UpdateParentTextureInfo",
3677 offscreen_saved_color_texture_info_
.get(),
3680 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3682 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3685 void GLES2DecoderImpl::SetResizeCallback(
3686 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3687 resize_callback_
= callback
;
3690 Logger
* GLES2DecoderImpl::GetLogger() {
3694 void GLES2DecoderImpl::BeginDecoding() {
3695 gpu_tracer_
->BeginDecoding();
3696 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3697 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3698 (*cb_command_trace_category_
!= 0);
3701 void GLES2DecoderImpl::EndDecoding() {
3702 gpu_tracer_
->EndDecoding();
3705 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3706 return state_
.GetErrorState();
3709 void GLES2DecoderImpl::SetShaderCacheCallback(
3710 const ShaderCacheCallback
& callback
) {
3711 shader_cache_callback_
= callback
;
3714 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3715 const WaitSyncPointCallback
& callback
) {
3716 wait_sync_point_callback_
= callback
;
3719 AsyncPixelTransferManager
*
3720 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3721 return async_pixel_transfer_manager_
.get();
3724 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3725 async_pixel_transfer_manager_
.reset();
3728 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3729 AsyncPixelTransferManager
* manager
) {
3730 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3733 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3734 uint32
* service_texture_id
) {
3735 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3737 *service_texture_id
= texture_ref
->service_id();
3743 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3744 return texture_state_
.texture_upload_count
+
3745 async_pixel_transfer_manager_
->GetTextureUploadCount();
3748 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3749 return texture_state_
.total_texture_upload_time
+
3750 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3753 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3754 return total_processing_commands_time_
;
3757 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3758 total_processing_commands_time_
+= time
;
3761 void GLES2DecoderImpl::Destroy(bool have_context
) {
3765 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3767 // Unbind everything.
3768 state_
.vertex_attrib_manager
= NULL
;
3769 state_
.default_vertex_attrib_manager
= NULL
;
3770 state_
.texture_units
.clear();
3771 state_
.bound_array_buffer
= NULL
;
3772 state_
.current_queries
.clear();
3773 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3774 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3775 state_
.bound_renderbuffer
= NULL
;
3776 state_
.bound_valuebuffer
= NULL
;
3778 if (offscreen_saved_color_texture_info_
.get()) {
3779 DCHECK(offscreen_target_color_texture_
);
3780 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3781 offscreen_saved_color_texture_
->id());
3782 offscreen_saved_color_texture_
->Invalidate();
3783 offscreen_saved_color_texture_info_
= NULL
;
3786 if (copy_texture_CHROMIUM_
.get()) {
3787 copy_texture_CHROMIUM_
->Destroy();
3788 copy_texture_CHROMIUM_
.reset();
3791 clear_framebuffer_blit_
.reset();
3793 if (state_
.current_program
.get()) {
3794 program_manager()->UnuseProgram(shader_manager(),
3795 state_
.current_program
.get());
3798 if (attrib_0_buffer_id_
) {
3799 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3801 if (fixed_attrib_buffer_id_
) {
3802 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3805 if (validation_texture_
) {
3806 glDeleteTextures(1, &validation_texture_
);
3807 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3808 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3811 if (offscreen_target_frame_buffer_
.get())
3812 offscreen_target_frame_buffer_
->Destroy();
3813 if (offscreen_target_color_texture_
.get())
3814 offscreen_target_color_texture_
->Destroy();
3815 if (offscreen_target_color_render_buffer_
.get())
3816 offscreen_target_color_render_buffer_
->Destroy();
3817 if (offscreen_target_depth_render_buffer_
.get())
3818 offscreen_target_depth_render_buffer_
->Destroy();
3819 if (offscreen_target_stencil_render_buffer_
.get())
3820 offscreen_target_stencil_render_buffer_
->Destroy();
3821 if (offscreen_saved_frame_buffer_
.get())
3822 offscreen_saved_frame_buffer_
->Destroy();
3823 if (offscreen_saved_color_texture_
.get())
3824 offscreen_saved_color_texture_
->Destroy();
3825 if (offscreen_resolved_frame_buffer_
.get())
3826 offscreen_resolved_frame_buffer_
->Destroy();
3827 if (offscreen_resolved_color_texture_
.get())
3828 offscreen_resolved_color_texture_
->Destroy();
3830 if (offscreen_target_frame_buffer_
.get())
3831 offscreen_target_frame_buffer_
->Invalidate();
3832 if (offscreen_target_color_texture_
.get())
3833 offscreen_target_color_texture_
->Invalidate();
3834 if (offscreen_target_color_render_buffer_
.get())
3835 offscreen_target_color_render_buffer_
->Invalidate();
3836 if (offscreen_target_depth_render_buffer_
.get())
3837 offscreen_target_depth_render_buffer_
->Invalidate();
3838 if (offscreen_target_stencil_render_buffer_
.get())
3839 offscreen_target_stencil_render_buffer_
->Invalidate();
3840 if (offscreen_saved_frame_buffer_
.get())
3841 offscreen_saved_frame_buffer_
->Invalidate();
3842 if (offscreen_saved_color_texture_
.get())
3843 offscreen_saved_color_texture_
->Invalidate();
3844 if (offscreen_resolved_frame_buffer_
.get())
3845 offscreen_resolved_frame_buffer_
->Invalidate();
3846 if (offscreen_resolved_color_texture_
.get())
3847 offscreen_resolved_color_texture_
->Invalidate();
3850 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3851 // Otherwise, we can leak objects. http://crbug.com/258772.
3852 // state_.current_program must be reset before group_ is reset because
3853 // the later deletes the ProgramManager object that referred by
3854 // state_.current_program object.
3855 state_
.current_program
= NULL
;
3857 copy_texture_CHROMIUM_
.reset();
3858 clear_framebuffer_blit_
.reset();
3860 if (query_manager_
.get()) {
3861 query_manager_
->Destroy(have_context
);
3862 query_manager_
.reset();
3865 if (vertex_array_manager_
.get()) {
3866 vertex_array_manager_
->Destroy(have_context
);
3867 vertex_array_manager_
.reset();
3870 if (image_manager_
.get()) {
3871 image_manager_
->Destroy(have_context
);
3872 image_manager_
.reset();
3875 offscreen_target_frame_buffer_
.reset();
3876 offscreen_target_color_texture_
.reset();
3877 offscreen_target_color_render_buffer_
.reset();
3878 offscreen_target_depth_render_buffer_
.reset();
3879 offscreen_target_stencil_render_buffer_
.reset();
3880 offscreen_saved_frame_buffer_
.reset();
3881 offscreen_saved_color_texture_
.reset();
3882 offscreen_resolved_frame_buffer_
.reset();
3883 offscreen_resolved_color_texture_
.reset();
3885 // Need to release these before releasing |group_| which may own the
3886 // ShaderTranslatorCache.
3887 fragment_translator_
= NULL
;
3888 vertex_translator_
= NULL
;
3890 // Should destroy the transfer manager before the texture manager held
3891 // by the context group.
3892 async_pixel_transfer_manager_
.reset();
3894 // Destroy the GPU Tracer which may own some in process GPU Timings.
3896 gpu_tracer_
->Destroy(have_context
);
3897 gpu_tracer_
.reset();
3901 framebuffer_manager()->RemoveObserver(this);
3902 group_
->Destroy(this, have_context
);
3906 if (context_
.get()) {
3907 context_
->ReleaseCurrent(NULL
);
3911 #if defined(OS_MACOSX)
3912 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3913 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3914 CFRelease(it
->second
);
3916 texture_to_io_surface_map_
.clear();
3920 void GLES2DecoderImpl::SetSurface(
3921 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3922 DCHECK(context_
->IsCurrent(NULL
));
3923 DCHECK(surface_
.get());
3925 RestoreCurrentFramebufferBindings();
3928 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3929 if (!offscreen_saved_color_texture_
.get()) {
3930 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3933 if (!offscreen_saved_color_texture_info_
.get()) {
3934 GLuint service_id
= offscreen_saved_color_texture_
->id();
3935 offscreen_saved_color_texture_info_
= TextureRef::Create(
3936 texture_manager(), 0, service_id
);
3937 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3939 UpdateParentTextureInfo();
3941 mailbox_manager()->ProduceTexture(
3942 mailbox
, offscreen_saved_color_texture_info_
->texture());
3945 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3946 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3947 if (!is_offscreen
) {
3948 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3949 << " with an onscreen framebuffer.";
3953 if (offscreen_size_
== size
)
3956 offscreen_size_
= size
;
3957 int w
= offscreen_size_
.width();
3958 int h
= offscreen_size_
.height();
3959 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3960 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3961 << "to allocate storage due to excessive dimensions.";
3965 // Reallocate the offscreen target buffers.
3966 DCHECK(offscreen_target_color_format_
);
3967 if (IsOffscreenBufferMultisampled()) {
3968 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3969 feature_info_
.get(),
3971 offscreen_target_color_format_
,
3972 offscreen_target_samples_
)) {
3973 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3974 << "to allocate storage for offscreen target color buffer.";
3978 if (!offscreen_target_color_texture_
->AllocateStorage(
3979 offscreen_size_
, offscreen_target_color_format_
, false)) {
3980 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3981 << "to allocate storage for offscreen target color texture.";
3985 if (offscreen_target_depth_format_
&&
3986 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3987 feature_info_
.get(),
3989 offscreen_target_depth_format_
,
3990 offscreen_target_samples_
)) {
3991 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3992 << "to allocate storage for offscreen target depth buffer.";
3995 if (offscreen_target_stencil_format_
&&
3996 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3997 feature_info_
.get(),
3999 offscreen_target_stencil_format_
,
4000 offscreen_target_samples_
)) {
4001 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4002 << "to allocate storage for offscreen target stencil buffer.";
4006 // Attach the offscreen target buffers to the target frame buffer.
4007 if (IsOffscreenBufferMultisampled()) {
4008 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4009 GL_COLOR_ATTACHMENT0
,
4010 offscreen_target_color_render_buffer_
.get());
4012 offscreen_target_frame_buffer_
->AttachRenderTexture(
4013 offscreen_target_color_texture_
.get());
4015 if (offscreen_target_depth_format_
) {
4016 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4017 GL_DEPTH_ATTACHMENT
,
4018 offscreen_target_depth_render_buffer_
.get());
4020 const bool packed_depth_stencil
=
4021 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4022 if (packed_depth_stencil
) {
4023 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4024 GL_STENCIL_ATTACHMENT
,
4025 offscreen_target_depth_render_buffer_
.get());
4026 } else if (offscreen_target_stencil_format_
) {
4027 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4028 GL_STENCIL_ATTACHMENT
,
4029 offscreen_target_stencil_render_buffer_
.get());
4032 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4033 GL_FRAMEBUFFER_COMPLETE
) {
4034 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4035 << "because offscreen FBO was incomplete.";
4039 // Clear the target frame buffer.
4041 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4042 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
4043 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
4044 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4046 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4047 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4049 state_
.SetDeviceDepthMask(GL_TRUE
);
4050 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4051 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4052 RestoreClearState();
4055 // Destroy the offscreen resolved framebuffers.
4056 if (offscreen_resolved_frame_buffer_
.get())
4057 offscreen_resolved_frame_buffer_
->Destroy();
4058 if (offscreen_resolved_color_texture_
.get())
4059 offscreen_resolved_color_texture_
->Destroy();
4060 offscreen_resolved_color_texture_
.reset();
4061 offscreen_resolved_frame_buffer_
.reset();
4066 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4067 const void* cmd_data
) {
4068 const gles2::cmds::ResizeCHROMIUM
& c
=
4069 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4070 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4071 return error::kDeferCommandUntilLater
;
4073 GLuint width
= static_cast<GLuint
>(c
.width
);
4074 GLuint height
= static_cast<GLuint
>(c
.height
);
4075 GLfloat scale_factor
= c
.scale_factor
;
4076 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4078 width
= std::max(1U, width
);
4079 height
= std::max(1U, height
);
4081 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4082 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4083 // Make sure that we are done drawing to the back buffer before resizing.
4086 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4088 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4089 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4090 << "ResizeOffscreenFrameBuffer failed.";
4091 return error::kLostContext
;
4095 if (!resize_callback_
.is_null()) {
4096 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4097 DCHECK(context_
->IsCurrent(surface_
.get()));
4098 if (!context_
->IsCurrent(surface_
.get())) {
4099 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4100 << "current after resize callback.";
4101 return error::kLostContext
;
4105 return error::kNoError
;
4108 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4109 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4110 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4112 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4115 // Decode a command, and call the corresponding GL functions.
4116 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4117 // of commands at once, and is now only used for tests that need to track
4118 // individual commands.
4119 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4120 unsigned int arg_count
,
4121 const void* cmd_data
) {
4122 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4125 // Decode multiple commands, and call the corresponding GL functions.
4126 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4127 // changed by a (malicious) client at any time, so if validation has to happen,
4128 // it should operate on a copy of them.
4129 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4130 // interest of performance in this critical execution loop.
4131 template <bool DebugImpl
>
4132 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4135 int* entries_processed
) {
4136 commands_to_process_
= num_commands
;
4137 error::Error result
= error::kNoError
;
4138 const CommandBufferEntry
* cmd_data
=
4139 static_cast<const CommandBufferEntry
*>(buffer
);
4140 int process_pos
= 0;
4141 unsigned int command
= 0;
4143 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4144 commands_to_process_
--) {
4145 const unsigned int size
= cmd_data
->value_header
.size
;
4146 command
= cmd_data
->value_header
.command
;
4149 result
= error::kInvalidSize
;
4153 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4154 result
= error::kOutOfBounds
;
4159 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4160 GetCommandName(command
));
4162 if (log_commands()) {
4163 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4164 << "cmd: " << GetCommandName(command
);
4168 const unsigned int arg_count
= size
- 1;
4169 unsigned int command_index
= command
- kStartPoint
- 1;
4170 if (command_index
< arraysize(command_info
)) {
4171 const CommandInfo
& info
= command_info
[command_index
];
4172 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4173 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4174 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4175 bool doing_gpu_trace
= false;
4176 if (DebugImpl
&& gpu_trace_commands_
) {
4177 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4178 doing_gpu_trace
= true;
4179 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4180 GetCommandName(command
),
4185 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4186 sizeof(CommandBufferEntry
); // NOLINT
4188 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4190 if (DebugImpl
&& doing_gpu_trace
)
4191 gpu_tracer_
->End(kTraceDecoder
);
4193 if (DebugImpl
&& debug()) {
4195 while ((error
= glGetError()) != GL_NO_ERROR
) {
4196 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4197 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4198 << " : " << GetCommandName(command
);
4199 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4203 result
= error::kInvalidArguments
;
4206 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4210 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4211 GetCommandName(command
));
4214 if (result
== error::kNoError
&&
4215 current_decoder_error_
!= error::kNoError
) {
4216 result
= current_decoder_error_
;
4217 current_decoder_error_
= error::kNoError
;
4220 if (result
!= error::kDeferCommandUntilLater
) {
4221 process_pos
+= size
;
4226 if (entries_processed
)
4227 *entries_processed
= process_pos
;
4229 if (error::IsError(result
)) {
4230 LOG(ERROR
) << "Error: " << result
<< " for Command "
4231 << GetCommandName(command
);
4237 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4240 int* entries_processed
) {
4241 if (gpu_debug_commands_
) {
4242 return DoCommandsImpl
<true>(
4243 num_commands
, buffer
, num_entries
, entries_processed
);
4245 return DoCommandsImpl
<false>(
4246 num_commands
, buffer
, num_entries
, entries_processed
);
4250 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4251 buffer_manager()->RemoveBuffer(client_id
);
4254 void GLES2DecoderImpl::DoFinish() {
4256 ProcessPendingReadPixels();
4257 ProcessPendingQueries(true);
4260 void GLES2DecoderImpl::DoFlush() {
4262 ProcessPendingQueries(false);
4265 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4266 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4267 if (texture_index
>= state_
.texture_units
.size()) {
4268 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4269 "glActiveTexture", texture_unit
, "texture_unit");
4272 state_
.active_texture_unit
= texture_index
;
4273 glActiveTexture(texture_unit
);
4276 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4277 Buffer
* buffer
= NULL
;
4278 GLuint service_id
= 0;
4279 if (client_id
!= 0) {
4280 buffer
= GetBuffer(client_id
);
4282 if (!group_
->bind_generates_resource()) {
4283 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4285 "id not generated by glGenBuffers");
4289 // It's a new id so make a buffer buffer for it.
4290 glGenBuffersARB(1, &service_id
);
4291 CreateBuffer(client_id
, service_id
);
4292 buffer
= GetBuffer(client_id
);
4295 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4297 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4299 GL_INVALID_OPERATION
,
4300 "glBindBuffer", "buffer bound to more than 1 target");
4303 service_id
= buffer
->service_id();
4306 case GL_ARRAY_BUFFER
:
4307 state_
.bound_array_buffer
= buffer
;
4309 case GL_ELEMENT_ARRAY_BUFFER
:
4310 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
4313 NOTREACHED(); // Validation should prevent us getting here.
4316 glBindBuffer(target
, service_id
);
4319 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4320 bool all_draw_buffers
) {
4321 Framebuffer
* framebuffer
=
4322 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4323 if (!all_draw_buffers
|| !framebuffer
) {
4324 return (GLES2Util::GetChannelsForFormat(
4325 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4327 return framebuffer
->HasAlphaMRT();
4330 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4331 Framebuffer
* framebuffer
=
4332 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4334 return framebuffer
->HasDepthAttachment();
4336 if (offscreen_target_frame_buffer_
.get()) {
4337 return offscreen_target_depth_format_
!= 0;
4339 return back_buffer_has_depth_
;
4342 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4343 Framebuffer
* framebuffer
=
4344 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4346 return framebuffer
->HasStencilAttachment();
4348 if (offscreen_target_frame_buffer_
.get()) {
4349 return offscreen_target_stencil_format_
!= 0 ||
4350 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4352 return back_buffer_has_stencil_
;
4355 void GLES2DecoderImpl::ApplyDirtyState() {
4356 if (framebuffer_state_
.clear_state_dirty
) {
4357 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4358 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4359 state_
.color_mask_green
,
4360 state_
.color_mask_blue
,
4361 state_
.color_mask_alpha
&& have_alpha
);
4363 bool have_depth
= BoundFramebufferHasDepthAttachment();
4364 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4366 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4367 state_
.SetDeviceStencilMaskSeparate(
4368 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4369 state_
.SetDeviceStencilMaskSeparate(
4370 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4372 state_
.SetDeviceCapabilityState(
4373 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4374 state_
.SetDeviceCapabilityState(
4375 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4376 framebuffer_state_
.clear_state_dirty
= false;
4380 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4381 return (offscreen_target_frame_buffer_
.get())
4382 ? offscreen_target_frame_buffer_
->id()
4383 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4386 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4387 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4388 "context", logger_
.GetLogPrefix());
4389 // Restore the Framebuffer first because of bugs in Intel drivers.
4390 // Intel drivers incorrectly clip the viewport settings to
4391 // the size of the current framebuffer object.
4392 RestoreFramebufferBindings();
4393 state_
.RestoreState(prev_state
);
4396 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4398 framebuffer_state_
.bound_draw_framebuffer
.get()
4399 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4400 : GetBackbufferServiceId();
4401 if (!features().chromium_framebuffer_multisample
) {
4402 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4404 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4405 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4406 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4407 : GetBackbufferServiceId();
4408 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4413 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4414 state_
.RestoreRenderbufferBindings();
4417 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4418 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4420 GLenum target
= texture
->target();
4421 glBindTexture(target
, service_id
);
4423 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4425 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4427 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4429 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4430 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4434 void GLES2DecoderImpl::ClearAllAttributes() const {
4435 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4437 if (feature_info_
->feature_flags().native_vertex_array_object
)
4438 glBindVertexArrayOES(0);
4440 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4441 if (i
!= 0) // Never disable attribute 0
4442 glDisableVertexAttribArray(i
);
4443 if (features().angle_instanced_arrays
)
4444 glVertexAttribDivisorANGLE(i
, 0);
4448 void GLES2DecoderImpl::RestoreAllAttributes() const {
4449 state_
.RestoreVertexAttribs();
4452 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4453 state_
.SetIgnoreCachedStateForTest(ignore
);
4456 void GLES2DecoderImpl::OnFboChanged() const {
4457 if (workarounds().restore_scissor_on_fbo_change
)
4458 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4460 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4461 GLint bound_fbo_unsigned
= -1;
4462 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4463 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4464 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4465 surface_
->NotifyWasBound();
4469 // Called after the FBO is checked for completeness.
4470 void GLES2DecoderImpl::OnUseFramebuffer() const {
4471 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4472 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4473 // The driver forgets the correct scissor when modifying the FBO binding.
4474 glScissor(state_
.scissor_x
,
4476 state_
.scissor_width
,
4477 state_
.scissor_height
);
4479 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4480 // it's unclear how this bug works.
4485 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4486 Framebuffer
* framebuffer
= NULL
;
4487 GLuint service_id
= 0;
4488 if (client_id
!= 0) {
4489 framebuffer
= GetFramebuffer(client_id
);
4491 if (!group_
->bind_generates_resource()) {
4492 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4493 "glBindFramebuffer",
4494 "id not generated by glGenFramebuffers");
4498 // It's a new id so make a framebuffer framebuffer for it.
4499 glGenFramebuffersEXT(1, &service_id
);
4500 CreateFramebuffer(client_id
, service_id
);
4501 framebuffer
= GetFramebuffer(client_id
);
4503 service_id
= framebuffer
->service_id();
4505 framebuffer
->MarkAsValid();
4507 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4509 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4510 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4513 // vmiura: This looks like dup code
4514 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4515 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4518 framebuffer_state_
.clear_state_dirty
= true;
4520 // If we are rendering to the backbuffer get the FBO id for any simulated
4522 if (framebuffer
== NULL
) {
4523 service_id
= GetBackbufferServiceId();
4526 glBindFramebufferEXT(target
, service_id
);
4530 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4531 Renderbuffer
* renderbuffer
= NULL
;
4532 GLuint service_id
= 0;
4533 if (client_id
!= 0) {
4534 renderbuffer
= GetRenderbuffer(client_id
);
4535 if (!renderbuffer
) {
4536 if (!group_
->bind_generates_resource()) {
4537 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4538 "glBindRenderbuffer",
4539 "id not generated by glGenRenderbuffers");
4543 // It's a new id so make a renderbuffer for it.
4544 glGenRenderbuffersEXT(1, &service_id
);
4545 CreateRenderbuffer(client_id
, service_id
);
4546 renderbuffer
= GetRenderbuffer(client_id
);
4548 service_id
= renderbuffer
->service_id();
4550 renderbuffer
->MarkAsValid();
4552 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4553 state_
.bound_renderbuffer
= renderbuffer
;
4554 state_
.bound_renderbuffer_valid
= true;
4555 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4558 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4559 TextureRef
* texture_ref
= NULL
;
4560 GLuint service_id
= 0;
4561 if (client_id
!= 0) {
4562 texture_ref
= GetTexture(client_id
);
4564 if (!group_
->bind_generates_resource()) {
4565 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4567 "id not generated by glGenTextures");
4571 // It's a new id so make a texture texture for it.
4572 glGenTextures(1, &service_id
);
4573 DCHECK_NE(0u, service_id
);
4574 CreateTexture(client_id
, service_id
);
4575 texture_ref
= GetTexture(client_id
);
4578 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4581 // Check the texture exists
4583 Texture
* texture
= texture_ref
->texture();
4584 // Check that we are not trying to bind it to a different target.
4585 if (texture
->target() != 0 && texture
->target() != target
) {
4586 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4588 "texture bound to more than 1 target.");
4591 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4592 if (texture
->target() == 0) {
4593 texture_manager()->SetTarget(texture_ref
, target
);
4595 glBindTexture(target
, texture
->service_id());
4597 glBindTexture(target
, 0);
4600 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4601 unit
.bind_target
= target
;
4604 unit
.bound_texture_2d
= texture_ref
;
4606 case GL_TEXTURE_CUBE_MAP
:
4607 unit
.bound_texture_cube_map
= texture_ref
;
4609 case GL_TEXTURE_EXTERNAL_OES
:
4610 unit
.bound_texture_external_oes
= texture_ref
;
4612 case GL_TEXTURE_RECTANGLE_ARB
:
4613 unit
.bound_texture_rectangle_arb
= texture_ref
;
4616 unit
.bound_texture_3d
= texture_ref
;
4618 case GL_TEXTURE_2D_ARRAY
:
4619 unit
.bound_texture_2d_array
= texture_ref
;
4622 NOTREACHED(); // Validation should prevent us getting here.
4627 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4628 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4630 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4631 glDisableVertexAttribArray(index
);
4636 "glDisableVertexAttribArray", "index out of range");
4640 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4641 GLsizei numAttachments
,
4642 const GLenum
* attachments
) {
4643 if (workarounds().disable_discard_framebuffer
)
4646 Framebuffer
* framebuffer
=
4647 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4649 // Validates the attachments. If one of them fails
4650 // the whole command fails.
4651 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4653 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4655 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4656 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4657 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4662 // Marks each one of them as not cleared
4663 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4665 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4670 switch (attachments
[i
]) {
4672 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4675 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4676 case GL_STENCIL_EXT
:
4677 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4686 // If the default framebuffer is bound but we are still rendering to an
4687 // FBO, translate attachment names that refer to default framebuffer
4688 // channels to corresponding framebuffer attachments.
4689 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4690 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4691 GLenum attachment
= attachments
[i
];
4692 if (!framebuffer
&& GetBackbufferServiceId()) {
4693 switch (attachment
) {
4695 attachment
= GL_COLOR_ATTACHMENT0
;
4698 attachment
= GL_DEPTH_ATTACHMENT
;
4700 case GL_STENCIL_EXT
:
4701 attachment
= GL_STENCIL_ATTACHMENT
;
4708 translated_attachments
[i
] = attachment
;
4711 ScopedRenderTo
do_render(framebuffer
);
4712 if (feature_info_
->gl_version_info().is_es3
) {
4713 glInvalidateFramebuffer(
4714 target
, numAttachments
, translated_attachments
.get());
4716 glDiscardFramebufferEXT(
4717 target
, numAttachments
, translated_attachments
.get());
4721 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4722 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4723 glEnableVertexAttribArray(index
);
4726 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4730 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4731 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4734 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4736 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4740 if (target
== GL_TEXTURE_CUBE_MAP
) {
4741 for (int i
= 0; i
< 6; ++i
) {
4742 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4743 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4745 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4750 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4752 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4757 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4758 // Workaround for Mac driver bug. In the large scheme of things setting
4759 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4760 // hit so there's probably no need to make this conditional. The bug appears
4761 // to be that if the filtering mode is set to something that doesn't require
4762 // mipmaps for rendering, or is never set to something other than the default,
4763 // then glGenerateMipmap misbehaves.
4764 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4765 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4767 glGenerateMipmapEXT(target
);
4768 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4769 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4770 texture_ref
->texture()->min_filter());
4772 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4773 if (error
== GL_NO_ERROR
) {
4774 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4778 bool GLES2DecoderImpl::GetHelper(
4779 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4780 DCHECK(num_written
);
4781 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4783 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4785 // Return the GL implementation's preferred format and (see below type)
4786 // if we have the GL extension that exposes this. This allows the GPU
4787 // client to use the implementation's preferred format for glReadPixels
4788 // for optimisation.
4790 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4791 // case when requested on integer/floating point buffers but which is
4792 // acceptable on GLES2 and with the GL_OES_read_format extension.
4794 // Therefore if an error occurs we swallow the error and use the
4795 // internal implementation.
4797 if (context_
->HasExtension("GL_OES_read_format")) {
4798 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4800 glGetIntegerv(pname
, params
);
4801 if (glGetError() == GL_NO_ERROR
)
4804 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4805 GetBoundReadFrameBufferInternalFormat());
4808 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4811 if (context_
->HasExtension("GL_OES_read_format")) {
4812 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4814 glGetIntegerv(pname
, params
);
4815 if (glGetError() == GL_NO_ERROR
)
4818 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4819 GetBoundReadFrameBufferInternalFormat(),
4820 GetBoundReadFrameBufferTextureType());
4823 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4826 *params
= group_
->max_fragment_uniform_vectors();
4829 case GL_MAX_VARYING_VECTORS
:
4832 *params
= group_
->max_varying_vectors();
4835 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4838 *params
= group_
->max_vertex_uniform_vectors();
4844 case GL_MAX_VIEWPORT_DIMS
:
4845 if (offscreen_target_frame_buffer_
.get()) {
4848 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4849 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4854 case GL_MAX_SAMPLES
:
4857 params
[0] = renderbuffer_manager()->max_samples();
4860 case GL_MAX_RENDERBUFFER_SIZE
:
4863 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4866 case GL_MAX_TEXTURE_SIZE
:
4869 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4872 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4875 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4878 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4881 params
[0] = group_
->max_color_attachments();
4884 case GL_MAX_DRAW_BUFFERS_ARB
:
4887 params
[0] = group_
->max_draw_buffers();
4894 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4895 Framebuffer
* framebuffer
=
4896 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4898 glGetFramebufferAttachmentParameterivEXT(
4899 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
4900 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
4902 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
4905 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4908 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4915 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4916 Framebuffer
* framebuffer
=
4917 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4919 glGetFramebufferAttachmentParameterivEXT(
4920 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
4921 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
4923 v
= (back_buffer_has_depth_
? 24 : 0);
4926 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4928 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4937 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4938 Framebuffer
* framebuffer
=
4939 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4941 GLenum framebuffer_enum
= 0;
4944 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
4947 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
4950 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
4953 glGetFramebufferAttachmentParameterivEXT(
4954 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
4959 glGetIntegerv(pname
, &v
);
4964 case GL_STENCIL_BITS
:
4968 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4969 Framebuffer
* framebuffer
=
4970 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4972 glGetFramebufferAttachmentParameterivEXT(
4973 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
4974 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
4976 v
= (back_buffer_has_stencil_
? 8 : 0);
4979 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4981 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4984 case GL_COMPRESSED_TEXTURE_FORMATS
:
4985 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4987 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4988 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4992 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4995 *params
= validators_
->compressed_texture_format
.GetValues().size();
4998 case GL_NUM_SHADER_BINARY_FORMATS
:
5001 *params
= validators_
->shader_binary_format
.GetValues().size();
5004 case GL_SHADER_BINARY_FORMATS
:
5005 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5007 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5008 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5012 case GL_SHADER_COMPILER
:
5018 case GL_ARRAY_BUFFER_BINDING
:
5021 if (state_
.bound_array_buffer
.get()) {
5022 GLuint client_id
= 0;
5023 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
5025 *params
= client_id
;
5031 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5034 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
5035 GLuint client_id
= 0;
5036 buffer_manager()->GetClientId(
5037 state_
.vertex_attrib_manager
->element_array_buffer()->
5038 service_id(), &client_id
);
5039 *params
= client_id
;
5045 case GL_FRAMEBUFFER_BINDING
:
5046 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5049 Framebuffer
* framebuffer
=
5050 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5052 GLuint client_id
= 0;
5053 framebuffer_manager()->GetClientId(
5054 framebuffer
->service_id(), &client_id
);
5055 *params
= client_id
;
5061 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5064 Framebuffer
* framebuffer
=
5065 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
5067 GLuint client_id
= 0;
5068 framebuffer_manager()->GetClientId(
5069 framebuffer
->service_id(), &client_id
);
5070 *params
= client_id
;
5076 case GL_RENDERBUFFER_BINDING
:
5079 Renderbuffer
* renderbuffer
=
5080 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5082 *params
= renderbuffer
->client_id();
5088 case GL_CURRENT_PROGRAM
:
5091 if (state_
.current_program
.get()) {
5092 GLuint client_id
= 0;
5093 program_manager()->GetClientId(
5094 state_
.current_program
->service_id(), &client_id
);
5095 *params
= client_id
;
5101 case GL_VERTEX_ARRAY_BINDING_OES
:
5104 if (state_
.vertex_attrib_manager
.get() !=
5105 state_
.default_vertex_attrib_manager
.get()) {
5106 GLuint client_id
= 0;
5107 vertex_array_manager_
->GetClientId(
5108 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5109 *params
= client_id
;
5115 case GL_TEXTURE_BINDING_2D
:
5118 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5119 if (unit
.bound_texture_2d
.get()) {
5120 *params
= unit
.bound_texture_2d
->client_id();
5126 case GL_TEXTURE_BINDING_CUBE_MAP
:
5129 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5130 if (unit
.bound_texture_cube_map
.get()) {
5131 *params
= unit
.bound_texture_cube_map
->client_id();
5137 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5140 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5141 if (unit
.bound_texture_external_oes
.get()) {
5142 *params
= unit
.bound_texture_external_oes
->client_id();
5148 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5151 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5152 if (unit
.bound_texture_rectangle_arb
.get()) {
5153 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5159 case GL_UNPACK_FLIP_Y_CHROMIUM
:
5162 params
[0] = unpack_flip_y_
;
5165 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
5168 params
[0] = unpack_premultiply_alpha_
;
5171 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
5174 params
[0] = unpack_unpremultiply_alpha_
;
5177 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5180 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5184 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5185 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5188 Framebuffer
* framebuffer
=
5189 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5191 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5192 } else { // backbuffer
5193 if (pname
== GL_DRAW_BUFFER0_ARB
)
5194 params
[0] = group_
->draw_buffer();
5196 params
[0] = GL_NONE
;
5201 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5206 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5207 GLenum pname
, GLsizei
* num_values
) {
5208 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5211 return GetHelper(pname
, NULL
, num_values
);
5214 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5215 if (GL_MAX_SAMPLES
== pname
&&
5216 features().use_img_for_multisampled_render_to_texture
) {
5217 return GL_MAX_SAMPLES_IMG
;
5222 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5224 GLsizei num_written
= 0;
5225 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5226 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5227 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5228 GetHelper(pname
, values
.get(), &num_written
);
5230 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5231 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5234 pname
= AdjustGetPname(pname
);
5235 glGetBooleanv(pname
, params
);
5239 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5241 GLsizei num_written
= 0;
5242 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5243 if (GetHelper(pname
, NULL
, &num_written
)) {
5244 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5245 GetHelper(pname
, values
.get(), &num_written
);
5246 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5247 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5250 pname
= AdjustGetPname(pname
);
5251 glGetFloatv(pname
, params
);
5256 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5258 pname
= AdjustGetPname(pname
);
5259 glGetInteger64v(pname
, params
);
5262 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5264 GLsizei num_written
;
5265 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5266 !GetHelper(pname
, params
, &num_written
)) {
5267 pname
= AdjustGetPname(pname
);
5268 glGetIntegerv(pname
, params
);
5272 void GLES2DecoderImpl::DoGetProgramiv(
5273 GLuint program_id
, GLenum pname
, GLint
* params
) {
5274 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5278 program
->GetProgramiv(pname
, params
);
5281 void GLES2DecoderImpl::DoGetBufferParameteriv(
5282 GLenum target
, GLenum pname
, GLint
* params
) {
5283 // Just delegate it. Some validation is actually done before this.
5284 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5285 &state_
, target
, pname
, params
);
5288 void GLES2DecoderImpl::DoBindAttribLocation(
5289 GLuint program_id
, GLuint index
, const char* name
) {
5290 if (!StringIsValidForGLES(name
)) {
5292 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5295 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5297 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5300 if (index
>= group_
->max_vertex_attribs()) {
5302 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5305 Program
* program
= GetProgramInfoNotShader(
5306 program_id
, "glBindAttribLocation");
5310 // At this point, the program's shaders may not be translated yet,
5311 // therefore, we may not find the hashed attribute name.
5312 // glBindAttribLocation call with original name is useless.
5313 // So instead, we should simply cache the binding, and then call
5314 // Program::ExecuteBindAttribLocationCalls() right before link.
5315 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5316 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5317 glBindAttribLocation(program
->service_id(), index
, name
);
5320 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5321 uint32 immediate_data_size
,
5322 const void* cmd_data
) {
5323 const gles2::cmds::BindAttribLocationBucket
& c
=
5324 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5325 GLuint program
= static_cast<GLuint
>(c
.program
);
5326 GLuint index
= static_cast<GLuint
>(c
.index
);
5327 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5328 if (!bucket
|| bucket
->size() == 0) {
5329 return error::kInvalidArguments
;
5331 std::string name_str
;
5332 if (!bucket
->GetAsString(&name_str
)) {
5333 return error::kInvalidArguments
;
5335 DoBindAttribLocation(program
, index
, name_str
.c_str());
5336 return error::kNoError
;
5339 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5340 GLuint program_id
, GLint location
, const char* name
) {
5341 if (!StringIsValidForGLES(name
)) {
5344 "glBindUniformLocationCHROMIUM", "Invalid character");
5347 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5349 GL_INVALID_OPERATION
,
5350 "glBindUniformLocationCHROMIUM", "reserved prefix");
5353 if (location
< 0 || static_cast<uint32
>(location
) >=
5354 (group_
->max_fragment_uniform_vectors() +
5355 group_
->max_vertex_uniform_vectors()) * 4) {
5358 "glBindUniformLocationCHROMIUM", "location out of range");
5361 Program
* program
= GetProgramInfoNotShader(
5362 program_id
, "glBindUniformLocationCHROMIUM");
5366 if (!program
->SetUniformLocationBinding(name
, location
)) {
5369 "glBindUniformLocationCHROMIUM", "location out of range");
5373 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5374 uint32 immediate_data_size
,
5375 const void* cmd_data
) {
5376 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5377 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5379 GLuint program
= static_cast<GLuint
>(c
.program
);
5380 GLint location
= static_cast<GLint
>(c
.location
);
5381 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5382 if (!bucket
|| bucket
->size() == 0) {
5383 return error::kInvalidArguments
;
5385 std::string name_str
;
5386 if (!bucket
->GetAsString(&name_str
)) {
5387 return error::kInvalidArguments
;
5389 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5390 return error::kNoError
;
5393 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5394 const void* cmd_data
) {
5395 const gles2::cmds::DeleteShader
& c
=
5396 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5397 GLuint client_id
= c
.shader
;
5399 Shader
* shader
= GetShader(client_id
);
5401 if (!shader
->IsDeleted()) {
5402 shader_manager()->Delete(shader
);
5405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5408 return error::kNoError
;
5411 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5412 const void* cmd_data
) {
5413 const gles2::cmds::DeleteProgram
& c
=
5414 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5415 GLuint client_id
= c
.program
;
5417 Program
* program
= GetProgram(client_id
);
5419 if (!program
->IsDeleted()) {
5420 program_manager()->MarkAsDeleted(shader_manager(), program
);
5424 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5427 return error::kNoError
;
5430 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5431 DCHECK(!ShouldDeferDraws());
5432 if (CheckBoundFramebuffersValid("glClear")) {
5434 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5435 if (workarounds().gl_clear_broken
) {
5436 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5438 if (!BoundFramebufferHasDepthAttachment())
5439 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5440 if (!BoundFramebufferHasStencilAttachment())
5441 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5442 clear_framebuffer_blit_
->ClearFramebuffer(
5443 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5444 state_
.color_clear_green
, state_
.color_clear_blue
,
5445 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5446 return error::kNoError
;
5450 return error::kNoError
;
5453 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5454 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5455 GLuint client_renderbuffer_id
) {
5456 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5459 GL_INVALID_OPERATION
,
5460 "glFramebufferRenderbuffer", "no framebuffer bound");
5463 GLuint service_id
= 0;
5464 Renderbuffer
* renderbuffer
= NULL
;
5465 if (client_renderbuffer_id
) {
5466 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5467 if (!renderbuffer
) {
5469 GL_INVALID_OPERATION
,
5470 "glFramebufferRenderbuffer", "unknown renderbuffer");
5473 service_id
= renderbuffer
->service_id();
5475 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5476 glFramebufferRenderbufferEXT(
5477 target
, attachment
, renderbuffertarget
, service_id
);
5478 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5479 if (error
== GL_NO_ERROR
) {
5480 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5482 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5483 framebuffer_state_
.clear_state_dirty
= true;
5488 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5489 if (SetCapabilityState(cap
, false)) {
5494 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5495 if (SetCapabilityState(cap
, true)) {
5500 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5501 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5502 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5503 glDepthRange(znear
, zfar
);
5506 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5507 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5508 state_
.sample_coverage_invert
= (invert
!= 0);
5509 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5512 // Assumes framebuffer is complete.
5513 void GLES2DecoderImpl::ClearUnclearedAttachments(
5514 GLenum target
, Framebuffer
* framebuffer
) {
5515 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5516 // bind this to the DRAW point, clear then bind back to READ
5517 // TODO(gman): I don't think there is any guarantee that an FBO that
5518 // is complete on the READ attachment will be complete as a DRAW
5520 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5521 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5523 GLbitfield clear_bits
= 0;
5524 if (framebuffer
->HasUnclearedColorAttachments()) {
5527 (GLES2Util::GetChannelsForFormat(
5528 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5530 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5531 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5532 if (feature_info_
->feature_flags().ext_draw_buffers
)
5533 framebuffer
->PrepareDrawBuffersForClear();
5536 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5537 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5539 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5540 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5541 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5544 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5545 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5547 state_
.SetDeviceDepthMask(GL_TRUE
);
5548 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5551 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5552 glClear(clear_bits
);
5554 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5555 feature_info_
->feature_flags().ext_draw_buffers
)
5556 framebuffer
->RestoreDrawBuffersAfterClear();
5558 framebuffer_manager()->MarkAttachmentsAsCleared(
5559 framebuffer
, renderbuffer_manager(), texture_manager());
5561 RestoreClearState();
5563 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5564 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5565 Framebuffer
* draw_framebuffer
=
5566 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5567 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5568 GetBackbufferServiceId();
5569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5573 void GLES2DecoderImpl::RestoreClearState() {
5574 framebuffer_state_
.clear_state_dirty
= true;
5576 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5577 state_
.color_clear_alpha
);
5578 glClearStencil(state_
.stencil_clear
);
5579 glClearDepth(state_
.depth_clear
);
5580 if (state_
.enable_flags
.scissor_test
) {
5581 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5585 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5586 Framebuffer
* framebuffer
=
5587 GetFramebufferInfoForTarget(target
);
5589 return GL_FRAMEBUFFER_COMPLETE
;
5591 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5592 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5593 return completeness
;
5595 return framebuffer
->GetStatus(texture_manager(), target
);
5598 void GLES2DecoderImpl::DoFramebufferTexture2D(
5599 GLenum target
, GLenum attachment
, GLenum textarget
,
5600 GLuint client_texture_id
, GLint level
) {
5601 DoFramebufferTexture2DCommon(
5602 "glFramebufferTexture2D", target
, attachment
,
5603 textarget
, client_texture_id
, level
, 0);
5606 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5607 GLenum target
, GLenum attachment
, GLenum textarget
,
5608 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5609 DoFramebufferTexture2DCommon(
5610 "glFramebufferTexture2DMultisample", target
, attachment
,
5611 textarget
, client_texture_id
, level
, samples
);
5614 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5615 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5616 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5617 if (samples
> renderbuffer_manager()->max_samples()) {
5620 "glFramebufferTexture2DMultisample", "samples too large");
5623 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5626 GL_INVALID_OPERATION
,
5627 name
, "no framebuffer bound.");
5630 GLuint service_id
= 0;
5631 TextureRef
* texture_ref
= NULL
;
5632 if (client_texture_id
) {
5633 texture_ref
= GetTexture(client_texture_id
);
5636 GL_INVALID_OPERATION
,
5637 name
, "unknown texture_ref");
5640 service_id
= texture_ref
->service_id();
5643 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5646 name
, "level out of range");
5651 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5653 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5655 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5657 if (features().use_img_for_multisampled_render_to_texture
) {
5658 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5659 service_id
, level
, samples
);
5661 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5662 service_id
, level
, samples
);
5665 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5666 if (error
== GL_NO_ERROR
) {
5667 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5670 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5671 framebuffer_state_
.clear_state_dirty
= true;
5675 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5680 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5681 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5682 GLint level
, GLint layer
) {
5683 // TODO(zmo): Unsafe ES3 API, missing states update.
5684 GLuint service_id
= 0;
5685 TextureRef
* texture_ref
= NULL
;
5686 if (client_texture_id
) {
5687 texture_ref
= GetTexture(client_texture_id
);
5690 GL_INVALID_OPERATION
,
5691 "glFramebufferTextureLayer", "unknown texture_ref");
5694 service_id
= texture_ref
->service_id();
5696 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5699 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5700 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5701 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5704 GL_INVALID_OPERATION
,
5705 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5708 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5709 const Framebuffer::Attachment
* attachment_object
=
5710 framebuffer
->GetAttachment(attachment
);
5711 *params
= attachment_object
? attachment_object
->object_name() : 0;
5713 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5714 features().use_img_for_multisampled_render_to_texture
) {
5715 pname
= GL_TEXTURE_SAMPLES_IMG
;
5717 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5721 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5722 GLenum target
, GLenum pname
, GLint
* params
) {
5723 Renderbuffer
* renderbuffer
=
5724 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5725 if (!renderbuffer
) {
5727 GL_INVALID_OPERATION
,
5728 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5732 EnsureRenderbufferBound();
5734 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5735 *params
= renderbuffer
->internal_format();
5737 case GL_RENDERBUFFER_WIDTH
:
5738 *params
= renderbuffer
->width();
5740 case GL_RENDERBUFFER_HEIGHT
:
5741 *params
= renderbuffer
->height();
5743 case GL_RENDERBUFFER_SAMPLES_EXT
:
5744 if (features().use_img_for_multisampled_render_to_texture
) {
5745 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5748 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5752 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5757 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5758 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5759 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5760 GLbitfield mask
, GLenum filter
) {
5761 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5763 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5767 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5768 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5769 BlitFramebufferHelper(
5770 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5771 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5772 state_
.enable_flags
.scissor_test
);
5775 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5776 if (!state_
.bound_renderbuffer_valid
) {
5777 state_
.bound_renderbuffer_valid
= true;
5778 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5779 state_
.bound_renderbuffer
.get()
5780 ? state_
.bound_renderbuffer
->service_id()
5785 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5786 const FeatureInfo
* feature_info
,
5789 GLenum internal_format
,
5792 // TODO(sievers): This could be resolved at the GL binding level, but the
5793 // binding process is currently a bit too 'brute force'.
5794 if (feature_info
->gl_version_info().is_angle
) {
5795 glRenderbufferStorageMultisampleANGLE(
5796 target
, samples
, internal_format
, width
, height
);
5797 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5798 glRenderbufferStorageMultisample(
5799 target
, samples
, internal_format
, width
, height
);
5801 glRenderbufferStorageMultisampleEXT(
5802 target
, samples
, internal_format
, width
, height
);
5806 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5816 // TODO(sievers): This could be resolved at the GL binding level, but the
5817 // binding process is currently a bit too 'brute force'.
5818 if (feature_info_
->gl_version_info().is_angle
) {
5819 glBlitFramebufferANGLE(
5820 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5821 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5823 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5825 glBlitFramebufferEXT(
5826 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5830 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5832 GLenum internalformat
,
5835 if (samples
> renderbuffer_manager()->max_samples()) {
5838 "glRenderbufferStorageMultisample", "samples too large");
5842 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5843 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5846 "glRenderbufferStorageMultisample", "dimensions too large");
5850 uint32 estimated_size
= 0;
5851 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5852 width
, height
, samples
, internalformat
, &estimated_size
)) {
5855 "glRenderbufferStorageMultisample", "dimensions too large");
5859 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5862 "glRenderbufferStorageMultisample", "out of memory");
5869 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5870 GLenum target
, GLsizei samples
, GLenum internalformat
,
5871 GLsizei width
, GLsizei height
) {
5872 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5873 if (!renderbuffer
) {
5874 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5875 "glRenderbufferStorageMultisampleCHROMIUM",
5876 "no renderbuffer bound");
5880 if (!ValidateRenderbufferStorageMultisample(
5881 samples
, internalformat
, width
, height
)) {
5885 EnsureRenderbufferBound();
5886 GLenum impl_format
=
5887 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5889 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5890 "glRenderbufferStorageMultisampleCHROMIUM");
5891 RenderbufferStorageMultisampleHelper(
5892 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5894 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5895 if (error
== GL_NO_ERROR
) {
5896 if (workarounds().validate_multisample_buffer_allocation
) {
5897 if (!VerifyMultisampleRenderbufferIntegrity(
5898 renderbuffer
->service_id(), impl_format
)) {
5901 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5906 // TODO(gman): If renderbuffers tracked which framebuffers they were
5907 // attached to we could just mark those framebuffers as not complete.
5908 framebuffer_manager()->IncFramebufferStateChangeCount();
5909 renderbuffer_manager()->SetInfo(
5910 renderbuffer
, samples
, internalformat
, width
, height
);
5914 // This is the handler for multisampled_render_to_texture extensions.
5915 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5916 GLenum target
, GLsizei samples
, GLenum internalformat
,
5917 GLsizei width
, GLsizei height
) {
5918 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5919 if (!renderbuffer
) {
5920 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5921 "glRenderbufferStorageMultisampleEXT",
5922 "no renderbuffer bound");
5926 if (!ValidateRenderbufferStorageMultisample(
5927 samples
, internalformat
, width
, height
)) {
5931 EnsureRenderbufferBound();
5932 GLenum impl_format
=
5933 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5935 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5936 if (features().use_img_for_multisampled_render_to_texture
) {
5937 glRenderbufferStorageMultisampleIMG(
5938 target
, samples
, impl_format
, width
, height
);
5940 glRenderbufferStorageMultisampleEXT(
5941 target
, samples
, impl_format
, width
, height
);
5943 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5944 if (error
== GL_NO_ERROR
) {
5945 // TODO(gman): If renderbuffers tracked which framebuffers they were
5946 // attached to we could just mark those framebuffers as not complete.
5947 framebuffer_manager()->IncFramebufferStateChangeCount();
5948 renderbuffer_manager()->SetInfo(
5949 renderbuffer
, samples
, internalformat
, width
, height
);
5953 // This function validates the allocation of a multisampled renderbuffer
5954 // by clearing it to a key color, blitting the contents to a texture, and
5955 // reading back the color to ensure it matches the key.
5956 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5957 GLuint renderbuffer
, GLenum format
) {
5959 // Only validate color buffers.
5960 // These formats have been selected because they are very common or are known
5961 // to be used by the WebGL backbuffer. If problems are observed with other
5962 // color formats they can be added here.
5973 GLint draw_framebuffer
, read_framebuffer
;
5975 // Cache framebuffer and texture bindings.
5976 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5977 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5979 if (!validation_texture_
) {
5980 GLint bound_texture
;
5981 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5983 // Create additional resources needed for the verification.
5984 glGenTextures(1, &validation_texture_
);
5985 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5986 glGenFramebuffersEXT(1, &validation_fbo_
);
5988 // Texture only needs to be 1x1.
5989 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5990 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5991 GL_UNSIGNED_BYTE
, NULL
);
5993 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5994 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5995 GL_TEXTURE_2D
, validation_texture_
, 0);
5997 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6000 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6001 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6002 GL_RENDERBUFFER
, renderbuffer
);
6004 // Cache current state and reset it to the values we require.
6005 GLboolean scissor_enabled
= false;
6006 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6007 if (scissor_enabled
)
6008 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6010 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6011 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6012 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6014 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6015 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6016 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6018 // Clear the buffer to the desired key color.
6019 glClear(GL_COLOR_BUFFER_BIT
);
6021 // Blit from the multisample buffer to a standard texture.
6022 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6023 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6025 BlitFramebufferHelper(
6026 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6028 // Read a pixel from the buffer.
6029 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6031 unsigned char pixel
[3] = {0, 0, 0};
6032 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6034 // Detach the renderbuffer.
6035 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6036 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6037 GL_RENDERBUFFER
, 0);
6039 // Restore cached state.
6040 if (scissor_enabled
)
6041 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6043 state_
.SetDeviceColorMask(
6044 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6045 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6046 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6047 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6049 // Return true if the pixel matched the desired key color.
6050 return (pixel
[0] == 0xFF &&
6055 void GLES2DecoderImpl::DoRenderbufferStorage(
6056 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6057 Renderbuffer
* renderbuffer
=
6058 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6059 if (!renderbuffer
) {
6061 GL_INVALID_OPERATION
,
6062 "glRenderbufferStorage", "no renderbuffer bound");
6066 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6067 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6069 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6073 uint32 estimated_size
= 0;
6074 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6075 width
, height
, 1, internalformat
, &estimated_size
)) {
6077 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6081 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6083 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6087 EnsureRenderbufferBound();
6088 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6089 glRenderbufferStorageEXT(
6091 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6095 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6096 if (error
== GL_NO_ERROR
) {
6097 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6098 // we could just mark those framebuffers as not complete.
6099 framebuffer_manager()->IncFramebufferStateChangeCount();
6100 renderbuffer_manager()->SetInfo(
6101 renderbuffer
, 1, internalformat
, width
, height
);
6105 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6106 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6107 Program
* program
= GetProgramInfoNotShader(
6108 program_id
, "glLinkProgram");
6113 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6114 if (program
->Link(shader_manager(),
6115 workarounds().count_all_in_varyings_packing
?
6116 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6117 shader_cache_callback_
)) {
6118 if (program
== state_
.current_program
.get()) {
6119 if (workarounds().use_current_program_after_successful_link
)
6120 glUseProgram(program
->service_id());
6121 if (workarounds().clear_uniforms_before_first_program_use
)
6122 program_manager()->ClearUniforms(program
);
6126 // LinkProgram can be very slow. Exit command processing to allow for
6127 // context preemption and GPU watchdog checks.
6128 ExitCommandProcessingEarly();
6131 void GLES2DecoderImpl::DoSamplerParameterfv(
6132 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6134 glSamplerParameterf(sampler
, pname
, params
[0]);
6137 void GLES2DecoderImpl::DoSamplerParameteriv(
6138 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6140 glSamplerParameteri(sampler
, pname
, params
[0]);
6143 void GLES2DecoderImpl::DoTexParameterf(
6144 GLenum target
, GLenum pname
, GLfloat param
) {
6145 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6148 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6152 texture_manager()->SetParameterf(
6153 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6156 void GLES2DecoderImpl::DoTexParameteri(
6157 GLenum target
, GLenum pname
, GLint param
) {
6158 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6161 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6165 texture_manager()->SetParameteri(
6166 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6169 void GLES2DecoderImpl::DoTexParameterfv(
6170 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6171 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6174 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6178 texture_manager()->SetParameterf(
6179 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6182 void GLES2DecoderImpl::DoTexParameteriv(
6183 GLenum target
, GLenum pname
, const GLint
* params
) {
6184 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6188 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6192 texture_manager()->SetParameteri(
6193 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6196 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6197 if (!state_
.bound_valuebuffer
.get()) {
6198 // There is no valuebuffer bound
6199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6200 "no valuebuffer in use");
6206 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6207 GLenum subscription
,
6208 const char* function_name
) {
6209 if (!CheckCurrentValuebuffer(function_name
)) {
6212 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6213 // The valuebuffer is not subscribed to the target
6214 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6215 "valuebuffer is not subscribed");
6221 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6222 GLenum subscription
,
6223 const char* function_name
) {
6224 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6227 GLint real_location
= -1;
6228 GLint array_index
= -1;
6229 const Program::UniformInfo
* info
=
6230 state_
.current_program
->GetUniformInfoByFakeLocation(
6231 location
, &real_location
, &array_index
);
6233 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6236 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6237 info
->accepts_api_type
) == 0) {
6238 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6239 "wrong type for subscription");
6245 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6246 if (!state_
.current_program
.get()) {
6247 // The program does not exist.
6249 GL_INVALID_OPERATION
, function_name
, "no program in use");
6252 if (!state_
.current_program
->InUse()) {
6254 GL_INVALID_OPERATION
, function_name
, "program not linked");
6260 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6261 GLint location
, const char* function_name
) {
6262 if (!CheckCurrentProgram(function_name
)) {
6265 return location
!= -1;
6268 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6269 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6272 const Framebuffer::Attachment
* attachment
=
6273 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6277 DCHECK(state_
.current_program
.get());
6278 const Program::SamplerIndices
& sampler_indices
=
6279 state_
.current_program
->sampler_indices();
6280 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6281 const Program::UniformInfo
* uniform_info
=
6282 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6283 DCHECK(uniform_info
);
6284 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6286 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6287 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6288 if (texture_unit_index
>= state_
.texture_units
.size())
6290 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6291 TextureRef
* texture_ref
=
6292 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6293 if (attachment
->IsTexture(texture_ref
))
6300 bool GLES2DecoderImpl::CheckUniformForApiType(
6301 const Program::UniformInfo
* info
,
6302 const char* function_name
,
6303 Program::UniformApiType api_type
) {
6305 if ((api_type
& info
->accepts_api_type
) == 0) {
6306 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6307 "wrong uniform function for type");
6313 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6314 GLint fake_location
,
6315 const char* function_name
,
6316 Program::UniformApiType api_type
,
6317 GLint
* real_location
,
6322 DCHECK(real_location
);
6324 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6327 GLint array_index
= -1;
6328 const Program::UniformInfo
* info
=
6329 state_
.current_program
->GetUniformInfoByFakeLocation(
6330 fake_location
, real_location
, &array_index
);
6333 GL_INVALID_OPERATION
, function_name
, "unknown location");
6336 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6339 if (*count
> 1 && !info
->is_array
) {
6341 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6344 *count
= std::min(info
->size
- array_index
, *count
);
6352 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6355 GLint real_location
= -1;
6356 if (!PrepForSetUniformByLocation(fake_location
,
6358 Program::kUniform1i
,
6364 if (!state_
.current_program
->SetSamplers(
6365 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6367 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6370 glUniform1i(real_location
, v0
);
6373 void GLES2DecoderImpl::DoUniform1iv(
6374 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6376 GLint real_location
= -1;
6377 if (!PrepForSetUniformByLocation(fake_location
,
6379 Program::kUniform1i
,
6385 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6386 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6387 if (!state_
.current_program
->SetSamplers(
6388 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6390 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6394 glUniform1iv(real_location
, count
, value
);
6397 void GLES2DecoderImpl::DoUniform1fv(
6398 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6400 GLint real_location
= -1;
6401 if (!PrepForSetUniformByLocation(fake_location
,
6403 Program::kUniform1f
,
6409 if (type
== GL_BOOL
) {
6410 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6411 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6412 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6414 DoUniform1iv(real_location
, count
, temp
.get());
6416 glUniform1fv(real_location
, count
, value
);
6420 void GLES2DecoderImpl::DoUniform2fv(
6421 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6423 GLint real_location
= -1;
6424 if (!PrepForSetUniformByLocation(fake_location
,
6426 Program::kUniform2f
,
6432 if (type
== GL_BOOL_VEC2
) {
6433 GLsizei num_values
= count
* 2;
6434 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6435 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6436 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6438 glUniform2iv(real_location
, count
, temp
.get());
6440 glUniform2fv(real_location
, count
, value
);
6444 void GLES2DecoderImpl::DoUniform3fv(
6445 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6447 GLint real_location
= -1;
6448 if (!PrepForSetUniformByLocation(fake_location
,
6450 Program::kUniform3f
,
6456 if (type
== GL_BOOL_VEC3
) {
6457 GLsizei num_values
= count
* 3;
6458 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6459 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6460 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6462 glUniform3iv(real_location
, count
, temp
.get());
6464 glUniform3fv(real_location
, count
, value
);
6468 void GLES2DecoderImpl::DoUniform4fv(
6469 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6471 GLint real_location
= -1;
6472 if (!PrepForSetUniformByLocation(fake_location
,
6474 Program::kUniform4f
,
6480 if (type
== GL_BOOL_VEC4
) {
6481 GLsizei num_values
= count
* 4;
6482 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6483 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6484 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6486 glUniform4iv(real_location
, count
, temp
.get());
6488 glUniform4fv(real_location
, count
, value
);
6492 void GLES2DecoderImpl::DoUniform2iv(
6493 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6495 GLint real_location
= -1;
6496 if (!PrepForSetUniformByLocation(fake_location
,
6498 Program::kUniform2i
,
6504 glUniform2iv(real_location
, count
, value
);
6507 void GLES2DecoderImpl::DoUniform3iv(
6508 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6510 GLint real_location
= -1;
6511 if (!PrepForSetUniformByLocation(fake_location
,
6513 Program::kUniform3i
,
6519 glUniform3iv(real_location
, count
, value
);
6522 void GLES2DecoderImpl::DoUniform4iv(
6523 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6525 GLint real_location
= -1;
6526 if (!PrepForSetUniformByLocation(fake_location
,
6528 Program::kUniform4i
,
6534 glUniform4iv(real_location
, count
, value
);
6537 void GLES2DecoderImpl::DoUniformMatrix2fv(
6538 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6539 const GLfloat
* value
) {
6541 GLint real_location
= -1;
6542 if (!PrepForSetUniformByLocation(fake_location
,
6543 "glUniformMatrix2fv",
6544 Program::kUniformMatrix2f
,
6550 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6553 void GLES2DecoderImpl::DoUniformMatrix3fv(
6554 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6555 const GLfloat
* value
) {
6557 GLint real_location
= -1;
6558 if (!PrepForSetUniformByLocation(fake_location
,
6559 "glUniformMatrix3fv",
6560 Program::kUniformMatrix3f
,
6566 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6569 void GLES2DecoderImpl::DoUniformMatrix4fv(
6570 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6571 const GLfloat
* value
) {
6573 GLint real_location
= -1;
6574 if (!PrepForSetUniformByLocation(fake_location
,
6575 "glUniformMatrix4fv",
6576 Program::kUniformMatrix4f
,
6582 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6585 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6586 GLuint service_id
= 0;
6587 Program
* program
= NULL
;
6589 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6593 if (!program
->IsValid()) {
6594 // Program was not linked successfully. (ie, glLinkProgram)
6596 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6599 service_id
= program
->service_id();
6601 if (state_
.current_program
.get()) {
6602 program_manager()->UnuseProgram(shader_manager(),
6603 state_
.current_program
.get());
6605 state_
.current_program
= program
;
6606 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6607 glUseProgram(service_id
);
6608 if (state_
.current_program
.get()) {
6609 program_manager()->UseProgram(state_
.current_program
.get());
6610 if (workarounds().clear_uniforms_before_first_program_use
)
6611 program_manager()->ClearUniforms(program
);
6615 void GLES2DecoderImpl::RenderWarning(
6616 const char* filename
, int line
, const std::string
& msg
) {
6617 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6620 void GLES2DecoderImpl::PerformanceWarning(
6621 const char* filename
, int line
, const std::string
& msg
) {
6622 logger_
.LogMessage(filename
, line
,
6623 std::string("PERFORMANCE WARNING: ") + msg
);
6626 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6627 Texture
* texture
, GLenum textarget
) {
6628 // Image is already in use if texture is attached to a framebuffer.
6629 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6630 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6632 ScopedGLErrorSuppressor
suppressor(
6633 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6635 glBindTexture(textarget
, texture
->service_id());
6636 image
->WillUseTexImage();
6637 RestoreCurrentTextureBindings(&state_
, textarget
);
6642 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6643 Texture
* texture
, GLenum textarget
) {
6644 // Image is still in use if texture is attached to a framebuffer.
6645 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6646 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6648 ScopedGLErrorSuppressor
suppressor(
6649 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6651 glBindTexture(textarget
, texture
->service_id());
6652 image
->DidUseTexImage();
6653 RestoreCurrentTextureBindings(&state_
, textarget
);
6658 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6659 DCHECK(state_
.current_program
.get());
6660 if (!texture_manager()->HaveUnrenderableTextures() &&
6661 !texture_manager()->HaveImages()) {
6665 bool textures_set
= false;
6666 const Program::SamplerIndices
& sampler_indices
=
6667 state_
.current_program
->sampler_indices();
6668 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6669 const Program::UniformInfo
* uniform_info
=
6670 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6671 DCHECK(uniform_info
);
6672 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6673 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6674 if (texture_unit_index
< state_
.texture_units
.size()) {
6675 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6676 TextureRef
* texture_ref
=
6677 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6678 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6679 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6680 textures_set
= true;
6681 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6684 texture_manager()->black_texture_id(uniform_info
->type
));
6686 LOCAL_RENDER_WARNING(
6687 std::string("there is no texture bound to the unit ") +
6688 base::IntToString(texture_unit_index
));
6690 LOCAL_RENDER_WARNING(
6691 std::string("texture bound to texture unit ") +
6692 base::IntToString(texture_unit_index
) +
6693 " is not renderable. It maybe non-power-of-2 and have"
6694 " incompatible texture filtering.");
6699 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6700 Texture
* texture
= texture_ref
->texture();
6701 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6702 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6703 ScopedGLErrorSuppressor
suppressor(
6704 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6705 textures_set
= true;
6706 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6707 image
->WillUseTexImage();
6712 // else: should this be an error?
6715 return !textures_set
;
6718 void GLES2DecoderImpl::RestoreStateForTextures() {
6719 DCHECK(state_
.current_program
.get());
6720 const Program::SamplerIndices
& sampler_indices
=
6721 state_
.current_program
->sampler_indices();
6722 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6723 const Program::UniformInfo
* uniform_info
=
6724 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6725 DCHECK(uniform_info
);
6726 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6727 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6728 if (texture_unit_index
< state_
.texture_units
.size()) {
6729 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6730 TextureRef
* texture_ref
=
6731 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6732 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6733 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6734 // Get the texture_ref info that was previously bound here.
6735 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6736 ? texture_unit
.bound_texture_2d
.get()
6737 : texture_unit
.bound_texture_cube_map
.get();
6738 glBindTexture(texture_unit
.bind_target
,
6739 texture_ref
? texture_ref
->service_id() : 0);
6743 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6744 Texture
* texture
= texture_ref
->texture();
6745 gfx::GLImage
* image
=
6746 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6747 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6748 ScopedGLErrorSuppressor
suppressor(
6749 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6750 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6751 image
->DidUseTexImage();
6758 // Set the active texture back to whatever the user had it as.
6759 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6762 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6763 // Only check if there are some uncleared textures.
6764 if (!texture_manager()->HaveUnsafeTextures()) {
6768 // 1: Check all textures we are about to render with.
6769 if (state_
.current_program
.get()) {
6770 const Program::SamplerIndices
& sampler_indices
=
6771 state_
.current_program
->sampler_indices();
6772 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6773 const Program::UniformInfo
* uniform_info
=
6774 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6775 DCHECK(uniform_info
);
6776 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6777 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6778 if (texture_unit_index
< state_
.texture_units
.size()) {
6779 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6780 TextureRef
* texture_ref
=
6781 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6782 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6783 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6794 bool GLES2DecoderImpl::IsDrawValid(
6795 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6796 GLsizei primcount
) {
6797 DCHECK(instanced
|| primcount
== 1);
6799 // NOTE: We specifically do not check current_program->IsValid() because
6800 // it could never be invalid since glUseProgram would have failed. While
6801 // glLinkProgram could later mark the program as invalid the previous
6802 // valid program will still function if it is still the current program.
6803 if (!state_
.current_program
.get()) {
6804 // The program does not exist.
6805 // But GL says no ERROR.
6806 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6810 if (CheckDrawingFeedbackLoops()) {
6812 GL_INVALID_OPERATION
, function_name
,
6813 "Source and destination textures of the draw are the same.");
6817 return state_
.vertex_attrib_manager
6818 ->ValidateBindings(function_name
,
6820 feature_info_
.get(),
6821 state_
.current_program
.get(),
6822 max_vertex_accessed
,
6827 bool GLES2DecoderImpl::SimulateAttrib0(
6828 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6832 if (feature_info_
->gl_version_info().BehavesLikeGLES())
6835 const VertexAttrib
* attrib
=
6836 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6837 // If it's enabled or it's not used then we don't need to do anything.
6838 bool attrib_0_used
=
6839 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6840 if (attrib
->enabled() && attrib_0_used
) {
6844 // Make a buffer with a single repeated vec4 value enough to
6845 // simulate the constant value that is supposed to be here.
6846 // This is required to emulate GLES2 on GL.
6847 GLuint num_vertices
= max_vertex_accessed
+ 1;
6848 uint32 size_needed
= 0;
6850 if (num_vertices
== 0 ||
6851 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6852 size_needed
> 0x7FFFFFFFU
) {
6853 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6857 LOCAL_PERFORMANCE_WARNING(
6858 "Attribute 0 is disabled. This has signficant performance penalty");
6860 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6861 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6863 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6865 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6866 GLenum error
= glGetError();
6867 if (error
!= GL_NO_ERROR
) {
6869 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6874 const Vec4
& value
= state_
.attrib_values
[0];
6877 (!attrib_0_buffer_matches_value_
||
6878 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6879 value
.v
[1] != attrib_0_value_
.v
[1] ||
6880 value
.v
[2] != attrib_0_value_
.v
[2] ||
6881 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6882 std::vector
<Vec4
> temp(num_vertices
, value
);
6883 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6884 attrib_0_buffer_matches_value_
= true;
6885 attrib_0_value_
= value
;
6886 attrib_0_size_
= size_needed
;
6889 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6891 if (attrib
->divisor())
6892 glVertexAttribDivisorANGLE(0, 0);
6898 void GLES2DecoderImpl::RestoreStateForAttrib(
6899 GLuint attrib_index
, bool restore_array_binding
) {
6900 const VertexAttrib
* attrib
=
6901 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6902 if (restore_array_binding
) {
6903 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6904 Buffer
* buffer
= attrib
->buffer();
6905 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6906 glVertexAttribPointer(
6907 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6908 attrib
->gl_stride(), ptr
);
6910 if (attrib
->divisor())
6911 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6913 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6914 state_
.bound_array_buffer
->service_id() : 0);
6916 // Never touch vertex attribute 0's state (in particular, never
6917 // disable it) when running on desktop GL because it will never be
6919 if (attrib_index
!= 0 ||
6920 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6921 if (attrib
->enabled()) {
6922 glEnableVertexAttribArray(attrib_index
);
6924 glDisableVertexAttribArray(attrib_index
);
6929 bool GLES2DecoderImpl::SimulateFixedAttribs(
6930 const char* function_name
,
6931 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6934 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6937 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6941 LOCAL_PERFORMANCE_WARNING(
6942 "GL_FIXED attributes have a signficant performance penalty");
6944 // NOTE: we could be smart and try to check if a buffer is used
6945 // twice in 2 different attribs, find the overlapping parts and therefore
6946 // duplicate the minimum amount of data but this whole code path is not meant
6947 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6948 // tests so we just add to the buffer attrib used.
6950 GLuint elements_needed
= 0;
6951 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6952 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6953 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6954 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6955 const VertexAttrib
* attrib
= *it
;
6956 const Program::VertexAttrib
* attrib_info
=
6957 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6958 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6959 max_vertex_accessed
);
6960 GLuint num_vertices
= max_accessed
+ 1;
6961 if (num_vertices
== 0) {
6963 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6967 attrib
->CanAccess(max_accessed
) &&
6968 attrib
->type() == GL_FIXED
) {
6969 uint32 elements_used
= 0;
6970 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6971 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6973 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6979 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6980 uint32 size_needed
= 0;
6981 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6982 size_needed
> 0x7FFFFFFFU
) {
6984 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6988 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6990 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6991 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6992 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6993 GLenum error
= glGetError();
6994 if (error
!= GL_NO_ERROR
) {
6996 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7001 // Copy the elements and convert to float
7002 GLintptr offset
= 0;
7003 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7004 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7005 const VertexAttrib
* attrib
= *it
;
7006 const Program::VertexAttrib
* attrib_info
=
7007 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7008 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7009 max_vertex_accessed
);
7010 GLuint num_vertices
= max_accessed
+ 1;
7011 if (num_vertices
== 0) {
7013 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7017 attrib
->CanAccess(max_accessed
) &&
7018 attrib
->type() == GL_FIXED
) {
7019 int num_elements
= attrib
->size() * num_vertices
;
7020 const int src_size
= num_elements
* sizeof(int32
);
7021 const int dst_size
= num_elements
* sizeof(float);
7022 scoped_ptr
<float[]> data(new float[num_elements
]);
7023 const int32
* src
= reinterpret_cast<const int32
*>(
7024 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7025 const int32
* end
= src
+ num_elements
;
7026 float* dst
= data
.get();
7027 while (src
!= end
) {
7028 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7030 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7031 glVertexAttribPointer(
7032 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7033 reinterpret_cast<GLvoid
*>(offset
));
7041 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7042 // There's no need to call glVertexAttribPointer because we shadow all the
7043 // settings and passing GL_FIXED to it will not work.
7046 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7050 error::Error
GLES2DecoderImpl::DoDrawArrays(
7051 const char* function_name
,
7056 GLsizei primcount
) {
7057 error::Error error
= WillAccessBoundFramebufferForDraw();
7058 if (error
!= error::kNoError
)
7060 if (!validators_
->draw_mode
.IsValid(mode
)) {
7061 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7062 return error::kNoError
;
7065 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7066 return error::kNoError
;
7068 if (primcount
< 0) {
7069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7070 return error::kNoError
;
7072 if (!CheckBoundFramebuffersValid(function_name
)) {
7073 return error::kNoError
;
7075 // We have to check this here because the prototype for glDrawArrays
7076 // is GLint not GLsizei.
7078 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7079 return error::kNoError
;
7082 if (count
== 0 || primcount
== 0) {
7083 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7084 return error::kNoError
;
7087 GLuint max_vertex_accessed
= first
+ count
- 1;
7088 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7089 if (!ClearUnclearedTextures()) {
7090 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7091 return error::kNoError
;
7093 bool simulated_attrib_0
= false;
7094 if (!SimulateAttrib0(
7095 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7096 return error::kNoError
;
7098 bool simulated_fixed_attribs
= false;
7099 if (SimulateFixedAttribs(
7100 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7102 bool textures_set
= !PrepareTexturesForRender();
7104 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7106 glDrawArrays(mode
, first
, count
);
7108 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7111 RestoreStateForTextures();
7113 if (simulated_fixed_attribs
) {
7114 RestoreStateForSimulatedFixedAttribs();
7117 if (simulated_attrib_0
) {
7118 // We don't have to restore attrib 0 generic data at the end of this
7119 // function even if it is simulated. This is because we will simulate
7120 // it in each draw call, and attrib 0 generic data queries use cached
7121 // values instead of passing down to the underlying driver.
7122 RestoreStateForAttrib(0, false);
7125 return error::kNoError
;
7128 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7129 const void* cmd_data
) {
7130 // TODO(zmo): crbug.com/481184
7131 // On Desktop GL with versions lower than 4.3, we need to emulate
7132 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7133 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7134 return DoDrawArrays("glDrawArrays",
7136 static_cast<GLenum
>(c
.mode
),
7137 static_cast<GLint
>(c
.first
),
7138 static_cast<GLsizei
>(c
.count
),
7142 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7143 uint32 immediate_data_size
,
7144 const void* cmd_data
) {
7145 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7146 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7147 if (!features().angle_instanced_arrays
) {
7149 GL_INVALID_OPERATION
,
7150 "glDrawArraysInstancedANGLE", "function not available");
7151 return error::kNoError
;
7153 return DoDrawArrays("glDrawArraysIntancedANGLE",
7155 static_cast<GLenum
>(c
.mode
),
7156 static_cast<GLint
>(c
.first
),
7157 static_cast<GLsizei
>(c
.count
),
7158 static_cast<GLsizei
>(c
.primcount
));
7161 error::Error
GLES2DecoderImpl::DoDrawElements(
7162 const char* function_name
,
7168 GLsizei primcount
) {
7169 error::Error error
= WillAccessBoundFramebufferForDraw();
7170 if (error
!= error::kNoError
)
7172 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7174 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7175 return error::kNoError
;
7179 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7180 return error::kNoError
;
7183 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7184 return error::kNoError
;
7186 if (!validators_
->draw_mode
.IsValid(mode
)) {
7187 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7188 return error::kNoError
;
7190 if (!validators_
->index_type
.IsValid(type
)) {
7191 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7192 return error::kNoError
;
7194 if (primcount
< 0) {
7195 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7196 return error::kNoError
;
7199 if (!CheckBoundFramebuffersValid(function_name
)) {
7200 return error::kNoError
;
7203 if (count
== 0 || primcount
== 0) {
7204 return error::kNoError
;
7207 GLuint max_vertex_accessed
;
7208 Buffer
* element_array_buffer
=
7209 state_
.vertex_attrib_manager
->element_array_buffer();
7211 if (!element_array_buffer
->GetMaxValueForRange(
7212 offset
, count
, type
, &max_vertex_accessed
)) {
7214 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7215 return error::kNoError
;
7218 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7219 if (!ClearUnclearedTextures()) {
7220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7221 return error::kNoError
;
7223 bool simulated_attrib_0
= false;
7224 if (!SimulateAttrib0(
7225 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7226 return error::kNoError
;
7228 bool simulated_fixed_attribs
= false;
7229 if (SimulateFixedAttribs(
7230 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7232 bool textures_set
= !PrepareTexturesForRender();
7234 // TODO(gman): Refactor to hide these details in BufferManager or
7235 // VertexAttribManager.
7236 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7237 bool used_client_side_array
= false;
7238 if (element_array_buffer
->IsClientSideArray()) {
7239 used_client_side_array
= true;
7240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7241 indices
= element_array_buffer
->GetRange(offset
, 0);
7244 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7246 glDrawElements(mode
, count
, type
, indices
);
7248 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7251 if (used_client_side_array
) {
7252 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7253 element_array_buffer
->service_id());
7257 RestoreStateForTextures();
7259 if (simulated_fixed_attribs
) {
7260 RestoreStateForSimulatedFixedAttribs();
7263 if (simulated_attrib_0
) {
7264 // We don't have to restore attrib 0 generic data at the end of this
7265 // function even if it is simulated. This is because we will simulate
7266 // it in each draw call, and attrib 0 generic data queries use cached
7267 // values instead of passing down to the underlying driver.
7268 RestoreStateForAttrib(0, false);
7271 return error::kNoError
;
7274 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7275 const void* cmd_data
) {
7276 // TODO(zmo): crbug.com/481184
7277 // On Desktop GL with versions lower than 4.3, we need to emulate
7278 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7279 const gles2::cmds::DrawElements
& c
=
7280 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7281 return DoDrawElements("glDrawElements",
7283 static_cast<GLenum
>(c
.mode
),
7284 static_cast<GLsizei
>(c
.count
),
7285 static_cast<GLenum
>(c
.type
),
7286 static_cast<int32
>(c
.index_offset
),
7290 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7291 uint32 immediate_data_size
,
7292 const void* cmd_data
) {
7293 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7294 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7295 if (!features().angle_instanced_arrays
) {
7297 GL_INVALID_OPERATION
,
7298 "glDrawElementsInstancedANGLE", "function not available");
7299 return error::kNoError
;
7301 return DoDrawElements("glDrawElementsInstancedANGLE",
7303 static_cast<GLenum
>(c
.mode
),
7304 static_cast<GLsizei
>(c
.count
),
7305 static_cast<GLenum
>(c
.type
),
7306 static_cast<int32
>(c
.index_offset
),
7307 static_cast<GLsizei
>(c
.primcount
));
7310 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7311 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7312 GLuint max_vertex_accessed
= 0;
7313 Buffer
* buffer
= GetBuffer(buffer_id
);
7315 // TODO(gman): Should this be a GL error or a command buffer error?
7317 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7319 if (!buffer
->GetMaxValueForRange(
7320 offset
, count
, type
, &max_vertex_accessed
)) {
7321 // TODO(gman): Should this be a GL error or a command buffer error?
7323 GL_INVALID_OPERATION
,
7324 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7327 return max_vertex_accessed
;
7330 void GLES2DecoderImpl::DoShaderSource(
7331 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7333 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7334 if (length
&& length
[ii
] > 0)
7335 str
.append(data
[ii
], length
[ii
]);
7337 str
.append(data
[ii
]);
7339 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7343 // Note: We don't actually call glShaderSource here. We wait until
7344 // we actually compile the shader.
7345 shader
->set_source(str
);
7348 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7349 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7350 GLenum buffer_mode
) {
7351 Program
* program
= GetProgramInfoNotShader(
7352 client_program_id
, "glTransformFeedbackVaryings");
7356 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7357 glTransformFeedbackVaryings(
7358 program
->service_id(), count
, varyings
, buffer_mode
);
7361 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7362 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7363 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7368 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7369 if (use_shader_translator_
) {
7370 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7371 vertex_translator_
: fragment_translator_
;
7374 const Shader::TranslatedShaderSourceType source_type
=
7375 feature_info_
->feature_flags().angle_translated_shader_source
?
7376 Shader::kANGLE
: Shader::kGL
;
7377 shader
->RequestCompile(translator
, source_type
);
7380 void GLES2DecoderImpl::DoGetShaderiv(
7381 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7382 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7387 // Compile now for statuses that require it.
7389 case GL_COMPILE_STATUS
:
7390 case GL_INFO_LOG_LENGTH
:
7391 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7392 shader
->DoCompile();
7400 case GL_SHADER_SOURCE_LENGTH
:
7401 *params
= shader
->source().size();
7405 case GL_COMPILE_STATUS
:
7406 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7408 case GL_INFO_LOG_LENGTH
:
7409 *params
= shader
->log_info().size();
7413 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7414 *params
= shader
->translated_source().size();
7421 glGetShaderiv(shader
->service_id(), pname
, params
);
7424 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7425 const void* cmd_data
) {
7426 const gles2::cmds::GetShaderSource
& c
=
7427 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7428 GLuint shader_id
= c
.shader
;
7429 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7430 Bucket
* bucket
= CreateBucket(bucket_id
);
7431 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7432 if (!shader
|| shader
->source().empty()) {
7434 return error::kNoError
;
7436 bucket
->SetFromString(shader
->source().c_str());
7437 return error::kNoError
;
7440 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7441 uint32 immediate_data_size
,
7442 const void* cmd_data
) {
7443 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7444 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7446 GLuint shader_id
= c
.shader
;
7447 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7448 Bucket
* bucket
= CreateBucket(bucket_id
);
7449 Shader
* shader
= GetShaderInfoNotProgram(
7450 shader_id
, "glGetTranslatedShaderSourceANGLE");
7453 return error::kNoError
;
7456 // Make sure translator has been utilized in compile.
7457 shader
->DoCompile();
7459 bucket
->SetFromString(shader
->translated_source().c_str());
7460 return error::kNoError
;
7463 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7464 uint32 immediate_data_size
,
7465 const void* cmd_data
) {
7466 const gles2::cmds::GetProgramInfoLog
& c
=
7467 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7468 GLuint program_id
= c
.program
;
7469 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7470 Bucket
* bucket
= CreateBucket(bucket_id
);
7471 Program
* program
= GetProgramInfoNotShader(
7472 program_id
, "glGetProgramInfoLog");
7473 if (!program
|| !program
->log_info()) {
7474 bucket
->SetFromString("");
7475 return error::kNoError
;
7477 bucket
->SetFromString(program
->log_info()->c_str());
7478 return error::kNoError
;
7481 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7482 uint32 immediate_data_size
,
7483 const void* cmd_data
) {
7484 const gles2::cmds::GetShaderInfoLog
& c
=
7485 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7486 GLuint shader_id
= c
.shader
;
7487 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7488 Bucket
* bucket
= CreateBucket(bucket_id
);
7489 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7491 bucket
->SetFromString("");
7492 return error::kNoError
;
7495 // Shader must be compiled in order to get the info log.
7496 shader
->DoCompile();
7498 bucket
->SetFromString(shader
->log_info().c_str());
7499 return error::kNoError
;
7502 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7503 return state_
.GetEnabled(cap
);
7506 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7507 const Buffer
* buffer
= GetBuffer(client_id
);
7508 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7511 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7512 const Framebuffer
* framebuffer
=
7513 GetFramebuffer(client_id
);
7514 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7517 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7518 // IsProgram is true for programs as soon as they are created, until they are
7519 // deleted and no longer in use.
7520 const Program
* program
= GetProgram(client_id
);
7521 return program
!= NULL
&& !program
->IsDeleted();
7524 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7525 const Renderbuffer
* renderbuffer
=
7526 GetRenderbuffer(client_id
);
7527 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7530 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7531 // IsShader is true for shaders as soon as they are created, until they
7532 // are deleted and not attached to any programs.
7533 const Shader
* shader
= GetShader(client_id
);
7534 return shader
!= NULL
&& !shader
->IsDeleted();
7537 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7538 const TextureRef
* texture_ref
= GetTexture(client_id
);
7539 return texture_ref
&& texture_ref
->texture()->IsValid();
7542 void GLES2DecoderImpl::DoAttachShader(
7543 GLuint program_client_id
, GLint shader_client_id
) {
7544 Program
* program
= GetProgramInfoNotShader(
7545 program_client_id
, "glAttachShader");
7549 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7553 if (!program
->AttachShader(shader_manager(), shader
)) {
7555 GL_INVALID_OPERATION
,
7557 "can not attach more than one shader of the same type.");
7560 glAttachShader(program
->service_id(), shader
->service_id());
7563 void GLES2DecoderImpl::DoDetachShader(
7564 GLuint program_client_id
, GLint shader_client_id
) {
7565 Program
* program
= GetProgramInfoNotShader(
7566 program_client_id
, "glDetachShader");
7570 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7574 if (!program
->DetachShader(shader_manager(), shader
)) {
7576 GL_INVALID_OPERATION
,
7577 "glDetachShader", "shader not attached to program");
7580 glDetachShader(program
->service_id(), shader
->service_id());
7583 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7584 Program
* program
= GetProgramInfoNotShader(
7585 program_client_id
, "glValidateProgram");
7589 program
->Validate();
7592 void GLES2DecoderImpl::GetVertexAttribHelper(
7593 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7595 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7596 Buffer
* buffer
= attrib
->buffer();
7597 if (buffer
&& !buffer
->IsDeleted()) {
7599 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7600 *params
= client_id
;
7604 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7605 *params
= attrib
->enabled();
7607 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7608 *params
= attrib
->size();
7610 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7611 *params
= attrib
->gl_stride();
7613 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7614 *params
= attrib
->type();
7616 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7617 *params
= attrib
->normalized();
7619 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7620 *params
= attrib
->divisor();
7628 void GLES2DecoderImpl::DoGetTexParameterfv(
7629 GLenum target
, GLenum pname
, GLfloat
* params
) {
7630 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7631 glGetTexParameterfv(target
, pname
, params
);
7634 void GLES2DecoderImpl::DoGetTexParameteriv(
7635 GLenum target
, GLenum pname
, GLint
* params
) {
7636 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7637 glGetTexParameteriv(target
, pname
, params
);
7640 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7641 GLenum target
, GLenum pname
) {
7642 if (!workarounds().init_texture_max_anisotropy
)
7644 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7645 !validators_
->texture_parameter
.IsValid(pname
)) {
7649 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7653 GL_INVALID_OPERATION
,
7654 "glGetTexParamter{fi}v", "unknown texture for target");
7657 Texture
* texture
= texture_ref
->texture();
7658 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7661 void GLES2DecoderImpl::DoGetVertexAttribfv(
7662 GLuint index
, GLenum pname
, GLfloat
* params
) {
7663 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7666 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7670 case GL_CURRENT_VERTEX_ATTRIB
: {
7671 const Vec4
& value
= state_
.attrib_values
[index
];
7672 params
[0] = value
.v
[0];
7673 params
[1] = value
.v
[1];
7674 params
[2] = value
.v
[2];
7675 params
[3] = value
.v
[3];
7680 GetVertexAttribHelper(attrib
, pname
, &value
);
7681 *params
= static_cast<GLfloat
>(value
);
7687 void GLES2DecoderImpl::DoGetVertexAttribiv(
7688 GLuint index
, GLenum pname
, GLint
* params
) {
7689 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7692 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7696 case GL_CURRENT_VERTEX_ATTRIB
: {
7697 const Vec4
& value
= state_
.attrib_values
[index
];
7698 params
[0] = static_cast<GLint
>(value
.v
[0]);
7699 params
[1] = static_cast<GLint
>(value
.v
[1]);
7700 params
[2] = static_cast<GLint
>(value
.v
[2]);
7701 params
[3] = static_cast<GLint
>(value
.v
[3]);
7705 GetVertexAttribHelper(attrib
, pname
, params
);
7710 bool GLES2DecoderImpl::SetVertexAttribValue(
7711 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7712 if (index
>= state_
.attrib_values
.size()) {
7713 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7716 Vec4
& v
= state_
.attrib_values
[index
];
7724 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7725 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7726 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7727 glVertexAttrib1f(index
, v0
);
7731 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7732 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7733 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7734 glVertexAttrib2f(index
, v0
, v1
);
7738 void GLES2DecoderImpl::DoVertexAttrib3f(
7739 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7740 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7741 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7742 glVertexAttrib3f(index
, v0
, v1
, v2
);
7746 void GLES2DecoderImpl::DoVertexAttrib4f(
7747 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7748 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7749 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7750 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7754 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7755 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7756 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7757 glVertexAttrib1fv(index
, v
);
7761 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7762 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7763 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7764 glVertexAttrib2fv(index
, v
);
7768 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7769 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7770 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7771 glVertexAttrib3fv(index
, v
);
7775 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7776 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7777 glVertexAttrib4fv(index
, v
);
7781 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7782 uint32 immediate_data_size
,
7783 const void* cmd_data
) {
7784 if (!unsafe_es3_apis_enabled())
7785 return error::kUnknownCommand
;
7786 const gles2::cmds::VertexAttribIPointer
& c
=
7787 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7789 if (!state_
.bound_array_buffer
.get() ||
7790 state_
.bound_array_buffer
->IsDeleted()) {
7791 if (state_
.vertex_attrib_manager
.get() ==
7792 state_
.default_vertex_attrib_manager
.get()) {
7794 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
7795 return error::kNoError
;
7796 } else if (c
.offset
!= 0) {
7799 "glVertexAttribIPointer", "client side arrays are not allowed");
7800 return error::kNoError
;
7804 GLuint indx
= c
.indx
;
7805 GLint size
= c
.size
;
7806 GLenum type
= c
.type
;
7807 GLsizei stride
= c
.stride
;
7808 GLsizei offset
= c
.offset
;
7809 const void* ptr
= reinterpret_cast<const void*>(offset
);
7810 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
7811 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
7812 return error::kNoError
;
7814 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7816 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
7817 return error::kNoError
;
7819 if (indx
>= group_
->max_vertex_attribs()) {
7821 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
7822 return error::kNoError
;
7826 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
7827 return error::kNoError
;
7831 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
7832 return error::kNoError
;
7836 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
7837 return error::kNoError
;
7839 GLsizei component_size
=
7840 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7841 // component_size must be a power of two to use & as optimized modulo.
7842 DCHECK(GLES2Util::IsPOT(component_size
));
7843 if (offset
& (component_size
- 1)) {
7845 GL_INVALID_OPERATION
,
7846 "glVertexAttribIPointer", "offset not valid for type");
7847 return error::kNoError
;
7849 if (stride
& (component_size
- 1)) {
7851 GL_INVALID_OPERATION
,
7852 "glVertexAttribIPointer", "stride not valid for type");
7853 return error::kNoError
;
7855 state_
.vertex_attrib_manager
7856 ->SetAttribInfo(indx
,
7857 state_
.bound_array_buffer
.get(),
7862 stride
!= 0 ? stride
: component_size
* size
,
7864 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7865 return error::kNoError
;
7868 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7869 uint32 immediate_data_size
,
7870 const void* cmd_data
) {
7871 const gles2::cmds::VertexAttribPointer
& c
=
7872 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7874 if (!state_
.bound_array_buffer
.get() ||
7875 state_
.bound_array_buffer
->IsDeleted()) {
7876 if (state_
.vertex_attrib_manager
.get() ==
7877 state_
.default_vertex_attrib_manager
.get()) {
7879 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7880 return error::kNoError
;
7881 } else if (c
.offset
!= 0) {
7884 "glVertexAttribPointer", "client side arrays are not allowed");
7885 return error::kNoError
;
7889 GLuint indx
= c
.indx
;
7890 GLint size
= c
.size
;
7891 GLenum type
= c
.type
;
7892 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
7893 GLsizei stride
= c
.stride
;
7894 GLsizei offset
= c
.offset
;
7895 const void* ptr
= reinterpret_cast<const void*>(offset
);
7896 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7897 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7898 return error::kNoError
;
7900 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7902 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7903 return error::kNoError
;
7905 if (indx
>= group_
->max_vertex_attribs()) {
7907 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7908 return error::kNoError
;
7912 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7913 return error::kNoError
;
7917 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7918 return error::kNoError
;
7922 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7923 return error::kNoError
;
7925 GLsizei component_size
=
7926 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7927 // component_size must be a power of two to use & as optimized modulo.
7928 DCHECK(GLES2Util::IsPOT(component_size
));
7929 if (offset
& (component_size
- 1)) {
7931 GL_INVALID_OPERATION
,
7932 "glVertexAttribPointer", "offset not valid for type");
7933 return error::kNoError
;
7935 if (stride
& (component_size
- 1)) {
7937 GL_INVALID_OPERATION
,
7938 "glVertexAttribPointer", "stride not valid for type");
7939 return error::kNoError
;
7941 state_
.vertex_attrib_manager
7942 ->SetAttribInfo(indx
,
7943 state_
.bound_array_buffer
.get(),
7948 stride
!= 0 ? stride
: component_size
* size
,
7950 // We support GL_FIXED natively on EGL/GLES2 implementations
7951 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
7952 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7954 return error::kNoError
;
7957 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7959 state_
.viewport_x
= x
;
7960 state_
.viewport_y
= y
;
7961 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7962 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7963 glViewport(x
, y
, width
, height
);
7966 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7967 uint32 immediate_data_size
,
7968 const void* cmd_data
) {
7969 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7970 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7971 if (!features().angle_instanced_arrays
) {
7973 GL_INVALID_OPERATION
,
7974 "glVertexAttribDivisorANGLE", "function not available");
7975 return error::kNoError
;
7977 GLuint index
= c
.index
;
7978 GLuint divisor
= c
.divisor
;
7979 if (index
>= group_
->max_vertex_attribs()) {
7982 "glVertexAttribDivisorANGLE", "index out of range");
7983 return error::kNoError
;
7986 state_
.vertex_attrib_manager
->SetDivisor(
7989 glVertexAttribDivisorANGLE(index
, divisor
);
7990 return error::kNoError
;
7993 template <typename pixel_data_type
>
7994 static void WriteAlphaData(
7995 void* pixels
, uint32 row_count
, uint32 channel_count
,
7996 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7997 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7998 DCHECK_GT(channel_count
, 0U);
7999 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8000 uint32 unpadded_row_size_in_elements
=
8001 unpadded_row_size
/ sizeof(pixel_data_type
);
8002 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8003 uint32 padded_row_size_in_elements
=
8004 padded_row_size
/ sizeof(pixel_data_type
);
8005 pixel_data_type
* dst
=
8006 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8007 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8008 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8009 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8012 dst
+= padded_row_size_in_elements
;
8016 void GLES2DecoderImpl::FinishReadPixels(
8017 const cmds::ReadPixels
& c
,
8019 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8020 GLsizei width
= c
.width
;
8021 GLsizei height
= c
.height
;
8022 GLenum format
= c
.format
;
8023 GLenum type
= c
.type
;
8024 typedef cmds::ReadPixels::Result Result
;
8026 Result
* result
= NULL
;
8027 if (c
.result_shm_id
!= 0) {
8028 result
= GetSharedMemoryAs
<Result
*>(
8029 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8032 glDeleteBuffersARB(1, &buffer
);
8037 GLES2Util::ComputeImageDataSizes(
8038 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8040 void* pixels
= GetSharedMemoryAs
<void*>(
8041 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8044 glDeleteBuffersARB(1, &buffer
);
8050 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8052 if (features().map_buffer_range
) {
8053 data
= glMapBufferRange(
8054 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8056 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8059 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8060 "Unable to map memory for readback.");
8063 memcpy(pixels
, data
, pixels_size
);
8064 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8065 // have to restore the state.
8066 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8067 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8068 glDeleteBuffersARB(1, &buffer
);
8071 if (result
!= NULL
) {
8075 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8076 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8077 if ((channels_exist
& 0x0008) == 0 &&
8078 workarounds().clear_alpha_in_readpixels
) {
8079 // Set the alpha to 255 because some drivers are buggy in this regard.
8082 uint32 unpadded_row_size
;
8083 uint32 padded_row_size
;
8084 if (!GLES2Util::ComputeImageDataSizes(
8085 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8086 &unpadded_row_size
, &padded_row_size
)) {
8090 uint32 channel_count
= 0;
8091 uint32 alpha_channel
= 0;
8104 if (channel_count
> 0) {
8106 case GL_UNSIGNED_BYTE
:
8107 WriteAlphaData
<uint8
>(
8108 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8109 padded_row_size
, 0xFF);
8112 WriteAlphaData
<float>(
8113 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8114 padded_row_size
, 1.0f
);
8117 WriteAlphaData
<uint16
>(
8118 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8119 padded_row_size
, 0x3C00);
8126 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8127 const void* cmd_data
) {
8128 const gles2::cmds::ReadPixels
& c
=
8129 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8130 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8131 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8132 if (fbo_error
!= error::kNoError
)
8136 GLsizei width
= c
.width
;
8137 GLsizei height
= c
.height
;
8138 GLenum format
= c
.format
;
8139 GLenum type
= c
.type
;
8140 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8141 if (width
< 0 || height
< 0) {
8142 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8143 return error::kNoError
;
8145 typedef cmds::ReadPixels::Result Result
;
8147 if (!GLES2Util::ComputeImageDataSizes(
8148 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8150 return error::kOutOfBounds
;
8152 void* pixels
= GetSharedMemoryAs
<void*>(
8153 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8155 return error::kOutOfBounds
;
8157 Result
* result
= NULL
;
8158 if (c
.result_shm_id
!= 0) {
8159 result
= GetSharedMemoryAs
<Result
*>(
8160 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8162 return error::kOutOfBounds
;
8166 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8167 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8168 return error::kNoError
;
8170 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8171 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8172 return error::kNoError
;
8174 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
8175 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
8176 // format and type are acceptable enums but not guaranteed to be supported
8177 // for this framebuffer. Have to ask gl if they are valid.
8178 GLint preferred_format
= 0;
8179 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
8180 GLint preferred_type
= 0;
8181 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
8182 if (format
!= static_cast<GLenum
>(preferred_format
) ||
8183 type
!= static_cast<GLenum
>(preferred_type
)) {
8185 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
8186 "with the current read framebuffer");
8187 return error::kNoError
;
8190 if (width
== 0 || height
== 0) {
8191 return error::kNoError
;
8194 // Get the size of the current fbo or backbuffer.
8195 gfx::Size max_size
= GetBoundReadFrameBufferSize();
8199 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8201 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8202 return error::kNoError
;
8205 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8206 return error::kNoError
;
8209 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8210 return error::kNoError
;
8213 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8215 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8217 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8218 // The user requested an out of range area. Get the results 1 line
8221 uint32 unpadded_row_size
;
8222 uint32 padded_row_size
;
8223 if (!GLES2Util::ComputeImageDataSizes(
8224 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8225 &unpadded_row_size
, &padded_row_size
)) {
8227 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8228 return error::kNoError
;
8231 GLint dest_x_offset
= std::max(-x
, 0);
8232 uint32 dest_row_offset
;
8233 if (!GLES2Util::ComputeImageDataSizes(
8234 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8235 &dest_row_offset
, NULL
, NULL
)) {
8237 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8238 return error::kNoError
;
8241 // Copy each row into the larger dest rect.
8242 int8
* dst
= static_cast<int8
*>(pixels
);
8243 GLint read_x
= std::max(0, x
);
8244 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8245 GLint read_width
= read_end_x
- read_x
;
8246 for (GLint yy
= 0; yy
< height
; ++yy
) {
8250 memset(dst
, 0, unpadded_row_size
);
8252 // If the row is in range, copy it.
8253 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8255 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8257 dst
+= padded_row_size
;
8260 if (async
&& features().use_async_readpixels
) {
8262 glGenBuffersARB(1, &buffer
);
8263 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8264 // For ANGLE client version 2, GL_STREAM_READ is not available.
8265 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8266 GL_STATIC_DRAW
: GL_STREAM_READ
;
8267 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8268 GLenum error
= glGetError();
8269 if (error
== GL_NO_ERROR
) {
8270 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8271 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8272 new FenceCallback()));
8273 WaitForReadPixels(base::Bind(
8274 &GLES2DecoderImpl::FinishReadPixels
,
8275 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8276 <GLES2DecoderImpl
>(this),
8278 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8279 return error::kNoError
;
8281 // On error, unbind pack buffer and fall through to sync readpixels
8282 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8283 glDeleteBuffersARB(1, &buffer
);
8286 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8288 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8289 if (error
== GL_NO_ERROR
) {
8290 if (result
!= NULL
) {
8293 FinishReadPixels(c
, 0);
8296 return error::kNoError
;
8299 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8300 const void* cmd_data
) {
8301 const gles2::cmds::PixelStorei
& c
=
8302 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8303 GLenum pname
= c
.pname
;
8304 GLenum param
= c
.param
;
8305 if (!validators_
->pixel_store
.IsValid(pname
)) {
8306 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8307 return error::kNoError
;
8310 case GL_PACK_ALIGNMENT
:
8311 case GL_UNPACK_ALIGNMENT
:
8312 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8314 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8315 return error::kNoError
;
8318 case GL_UNPACK_FLIP_Y_CHROMIUM
:
8319 unpack_flip_y_
= (param
!= 0);
8320 return error::kNoError
;
8321 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
8322 unpack_premultiply_alpha_
= (param
!= 0);
8323 return error::kNoError
;
8324 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
8325 unpack_unpremultiply_alpha_
= (param
!= 0);
8326 return error::kNoError
;
8330 glPixelStorei(pname
, param
);
8332 case GL_PACK_ALIGNMENT
:
8333 state_
.pack_alignment
= param
;
8335 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8336 state_
.pack_reverse_row_order
= (param
!= 0);
8338 case GL_UNPACK_ALIGNMENT
:
8339 state_
.unpack_alignment
= param
;
8342 // Validation should have prevented us from getting here.
8346 return error::kNoError
;
8349 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8350 uint32 immediate_data_size
,
8351 const void* cmd_data
) {
8352 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8353 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8354 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8356 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8358 if (!supports_post_sub_buffer_
) {
8360 GL_INVALID_OPERATION
,
8361 "glPostSubBufferCHROMIUM", "command not supported by surface");
8362 return error::kNoError
;
8365 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8368 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8369 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8370 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8371 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8373 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8374 return error::kNoError
;
8376 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8377 return error::kLostContext
;
8381 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8382 uint32 immediate_data_size
,
8383 const void* cmd_data
) {
8384 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8385 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8386 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8388 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8389 "glScheduleOverlayPlaneCHROMIUM",
8391 return error::kNoError
;
8393 gfx::GLImage
* image
=
8394 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8396 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8397 "glScheduleOverlayPlaneCHROMIUM",
8398 "unsupported texture format");
8399 return error::kNoError
;
8401 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8402 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8403 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8404 "glScheduleOverlayPlaneCHROMIUM",
8405 "invalid transform enum");
8406 return error::kNoError
;
8408 if (!surface_
->ScheduleOverlayPlane(
8412 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8413 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8414 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8415 "glScheduleOverlayPlaneCHROMIUM",
8416 "failed to schedule overlay");
8418 return error::kNoError
;
8421 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8422 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8423 const std::string
& name_str
) {
8424 if (!StringIsValidForGLES(name_str
.c_str())) {
8426 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8427 return error::kNoError
;
8429 Program
* program
= GetProgramInfoNotShader(
8430 client_id
, "glGetAttribLocation");
8432 return error::kNoError
;
8434 if (!program
->IsValid()) {
8436 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8437 return error::kNoError
;
8439 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8440 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8442 return error::kOutOfBounds
;
8444 // Require the client to init this incase the context is lost and we are no
8445 // longer executing commands.
8446 if (*location
!= -1) {
8447 return error::kGenericError
;
8449 *location
= program
->GetAttribLocation(name_str
);
8450 return error::kNoError
;
8453 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8454 uint32 immediate_data_size
,
8455 const void* cmd_data
) {
8456 const gles2::cmds::GetAttribLocation
& c
=
8457 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8458 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8460 return error::kInvalidArguments
;
8462 std::string name_str
;
8463 if (!bucket
->GetAsString(&name_str
)) {
8464 return error::kInvalidArguments
;
8466 return GetAttribLocationHelper(
8467 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8470 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8471 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8472 const std::string
& name_str
) {
8473 if (!StringIsValidForGLES(name_str
.c_str())) {
8475 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8476 return error::kNoError
;
8478 Program
* program
= GetProgramInfoNotShader(
8479 client_id
, "glGetUniformLocation");
8481 return error::kNoError
;
8483 if (!program
->IsValid()) {
8485 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8486 return error::kNoError
;
8488 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8489 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8491 return error::kOutOfBounds
;
8493 // Require the client to init this incase the context is lost an we are no
8494 // longer executing commands.
8495 if (*location
!= -1) {
8496 return error::kGenericError
;
8498 *location
= program
->GetUniformFakeLocation(name_str
);
8499 return error::kNoError
;
8502 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8503 uint32 immediate_data_size
,
8504 const void* cmd_data
) {
8505 const gles2::cmds::GetUniformLocation
& c
=
8506 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8507 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8509 return error::kInvalidArguments
;
8511 std::string name_str
;
8512 if (!bucket
->GetAsString(&name_str
)) {
8513 return error::kInvalidArguments
;
8515 return GetUniformLocationHelper(
8516 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8519 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8520 uint32 immediate_data_size
,
8521 const void* cmd_data
) {
8522 if (!unsafe_es3_apis_enabled())
8523 return error::kUnknownCommand
;
8524 const gles2::cmds::GetUniformIndices
& c
=
8525 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8526 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8528 return error::kInvalidArguments
;
8531 std::vector
<char*> names
;
8532 std::vector
<GLint
> len
;
8533 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8534 return error::kInvalidArguments
;
8536 typedef cmds::GetUniformIndices::Result Result
;
8537 Result
* result
= GetSharedMemoryAs
<Result
*>(
8538 c
.indices_shm_id
, c
.indices_shm_offset
,
8539 Result::ComputeSize(static_cast<size_t>(count
)));
8540 GLuint
* indices
= result
? result
->GetData() : NULL
;
8541 if (indices
== NULL
) {
8542 return error::kOutOfBounds
;
8544 // Check that the client initialized the result.
8545 if (result
->size
!= 0) {
8546 return error::kInvalidArguments
;
8548 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8550 return error::kNoError
;
8552 GLuint service_id
= program
->service_id();
8553 GLint link_status
= GL_FALSE
;
8554 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8555 if (link_status
!= GL_TRUE
) {
8556 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8557 "glGetUniformIndices", "program not linked");
8558 return error::kNoError
;
8560 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8561 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8562 GLenum error
= glGetError();
8563 if (error
== GL_NO_ERROR
) {
8564 result
->SetNumResults(count
);
8566 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8568 return error::kNoError
;
8571 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8572 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8573 const std::string
& name_str
) {
8574 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8575 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8577 return error::kOutOfBounds
;
8579 // Require the client to init this incase the context is lost and we are no
8580 // longer executing commands.
8581 if (*location
!= -1) {
8582 return error::kGenericError
;
8584 Program
* program
= GetProgramInfoNotShader(
8585 client_id
, "glGetFragDataLocation");
8587 return error::kNoError
;
8589 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8590 return error::kNoError
;
8593 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8594 uint32 immediate_data_size
,
8595 const void* cmd_data
) {
8596 if (!unsafe_es3_apis_enabled())
8597 return error::kUnknownCommand
;
8598 const gles2::cmds::GetFragDataLocation
& c
=
8599 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8600 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8602 return error::kInvalidArguments
;
8604 std::string name_str
;
8605 if (!bucket
->GetAsString(&name_str
)) {
8606 return error::kInvalidArguments
;
8608 return GetFragDataLocationHelper(
8609 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8612 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8613 uint32 immediate_data_size
, const void* cmd_data
) {
8614 if (!unsafe_es3_apis_enabled())
8615 return error::kUnknownCommand
;
8616 const gles2::cmds::GetUniformBlockIndex
& c
=
8617 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8618 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8620 return error::kInvalidArguments
;
8622 std::string name_str
;
8623 if (!bucket
->GetAsString(&name_str
)) {
8624 return error::kInvalidArguments
;
8626 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8627 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8629 return error::kOutOfBounds
;
8631 // Require the client to init this in case the context is lost and we are no
8632 // longer executing commands.
8633 if (*index
!= GL_INVALID_INDEX
) {
8634 return error::kGenericError
;
8636 Program
* program
= GetProgramInfoNotShader(
8637 c
.program
, "glGetUniformBlockIndex");
8639 return error::kNoError
;
8641 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8642 return error::kNoError
;
8645 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8646 const void* cmd_data
) {
8647 const gles2::cmds::GetString
& c
=
8648 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8649 GLenum name
= static_cast<GLenum
>(c
.name
);
8650 if (!validators_
->string_type
.IsValid(name
)) {
8651 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8652 return error::kNoError
;
8655 const char* str
= nullptr;
8656 std::string extensions
;
8659 str
= "OpenGL ES 2.0 Chromium";
8661 case GL_SHADING_LANGUAGE_VERSION
:
8662 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8666 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8667 // They are used by WEBGL_debug_renderer_info.
8668 if (!force_webgl_glsl_validation_
)
8671 str
= reinterpret_cast<const char*>(glGetString(name
));
8675 // For WebGL contexts, strip out the OES derivatives and
8676 // EXT frag depth extensions if they have not been enabled.
8677 if (force_webgl_glsl_validation_
) {
8678 extensions
= feature_info_
->extensions();
8679 if (!derivatives_explicitly_enabled_
) {
8680 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8681 if (std::string::npos
!= offset
) {
8682 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8686 if (!frag_depth_explicitly_enabled_
) {
8687 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8688 if (std::string::npos
!= offset
) {
8689 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8693 if (!draw_buffers_explicitly_enabled_
) {
8694 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8695 if (std::string::npos
!= offset
) {
8696 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8700 if (!shader_texture_lod_explicitly_enabled_
) {
8701 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8702 if (std::string::npos
!= offset
) {
8703 extensions
.replace(offset
,
8704 arraysize(kEXTShaderTextureLodExtension
),
8709 extensions
= feature_info_
->extensions().c_str();
8711 if (supports_post_sub_buffer_
)
8712 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8713 str
= extensions
.c_str();
8717 str
= reinterpret_cast<const char*>(glGetString(name
));
8720 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8721 bucket
->SetFromString(str
);
8722 return error::kNoError
;
8725 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8726 const void* cmd_data
) {
8727 const gles2::cmds::BufferData
& c
=
8728 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8729 GLenum target
= static_cast<GLenum
>(c
.target
);
8730 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8731 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8732 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8733 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8734 const void* data
= NULL
;
8735 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8736 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8738 return error::kOutOfBounds
;
8741 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8742 return error::kNoError
;
8745 void GLES2DecoderImpl::DoBufferSubData(
8746 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8747 // Just delegate it. Some validation is actually done before this.
8748 buffer_manager()->ValidateAndDoBufferSubData(
8749 &state_
, target
, offset
, size
, data
);
8752 bool GLES2DecoderImpl::ClearLevel(
8756 unsigned internal_format
,
8761 bool is_texture_immutable
) {
8762 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8763 if (feature_info_
->feature_flags().angle_depth_texture
&&
8764 (channels
& GLES2Util::kDepth
) != 0) {
8765 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8766 // on depth formats.
8768 glGenFramebuffersEXT(1, &fb
);
8769 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8771 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8772 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8773 GL_DEPTH_ATTACHMENT
;
8775 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8776 texture
->service_id(), level
);
8777 // ANGLE promises a depth only attachment ok.
8778 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8779 GL_FRAMEBUFFER_COMPLETE
) {
8783 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8784 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8786 state_
.SetDeviceDepthMask(GL_TRUE
);
8787 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8788 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8790 RestoreClearState();
8792 glDeleteFramebuffersEXT(1, &fb
);
8793 Framebuffer
* framebuffer
=
8794 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8795 GLuint fb_service_id
=
8796 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8797 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8801 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8804 uint32 padded_row_size
;
8805 if (!GLES2Util::ComputeImageDataSizes(
8806 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8807 NULL
, &padded_row_size
)) {
8811 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8815 if (size
> kMaxZeroSize
) {
8816 if (kMaxZeroSize
< padded_row_size
) {
8817 // That'd be an awfully large texture.
8820 // We should never have a large total size with a zero row size.
8821 DCHECK_GT(padded_row_size
, 0U);
8822 tile_height
= kMaxZeroSize
/ padded_row_size
;
8823 if (!GLES2Util::ComputeImageDataSizes(
8824 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8829 tile_height
= height
;
8832 // Assumes the size has already been checked.
8833 scoped_ptr
<char[]> zero(new char[size
]);
8834 memset(zero
.get(), 0, size
);
8835 glBindTexture(texture
->target(), texture
->service_id());
8837 bool has_images
= texture
->HasImages();
8839 while (y
< height
) {
8840 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8841 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8842 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8845 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8850 TextureRef
* bound_texture
=
8851 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8852 glBindTexture(texture
->target(),
8853 bound_texture
? bound_texture
->service_id() : 0);
8859 const int kS3TCBlockWidth
= 4;
8860 const int kS3TCBlockHeight
= 4;
8861 const int kS3TCDXT1BlockSize
= 8;
8862 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8863 const int kEACAndETC2BlockSize
= 4;
8865 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8866 return (size
== 1) ||
8867 (size
== 2) || !(size
% kS3TCBlockWidth
);
8870 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8871 return GLES2Util::IsPOT(size
);
8874 } // anonymous namespace.
8876 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8877 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
8878 GLenum format
, GLsizei size
) {
8879 base::CheckedNumeric
<GLsizei
> bytes_required(0);
8882 case GL_ATC_RGB_AMD
:
8883 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8884 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8885 case GL_ETC1_RGB8_OES
:
8887 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8889 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8890 bytes_required
*= kS3TCDXT1BlockSize
;
8892 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8893 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8894 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8895 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
8897 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8899 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8900 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
8902 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8903 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8904 bytes_required
= std::max(width
, 8);
8905 bytes_required
*= std::max(height
, 8);
8906 bytes_required
*= 4;
8907 bytes_required
+= 7;
8908 bytes_required
/= 8;
8910 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8911 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
8912 bytes_required
= std::max(width
, 16);
8913 bytes_required
*= std::max(height
, 8);
8914 bytes_required
*= 2;
8915 bytes_required
+= 7;
8916 bytes_required
/= 8;
8920 case GL_COMPRESSED_R11_EAC
:
8921 case GL_COMPRESSED_SIGNED_R11_EAC
:
8922 case GL_COMPRESSED_RGB8_ETC2
:
8923 case GL_COMPRESSED_SRGB8_ETC2
:
8924 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8925 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
8927 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8929 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8930 bytes_required
*= 8;
8931 bytes_required
*= depth
;
8933 case GL_COMPRESSED_RG11_EAC
:
8934 case GL_COMPRESSED_SIGNED_RG11_EAC
:
8935 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
8936 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
8938 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8940 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
8941 bytes_required
*= 16;
8942 bytes_required
*= depth
;
8945 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8949 if (!bytes_required
.IsValid() || size
!= bytes_required
.ValueOrDefault(0)) {
8951 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8958 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8959 const char* function_name
, GLenum target
, GLint level
,
8960 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
8962 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8963 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8964 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8965 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
8966 DCHECK_EQ(1, depth
); // 2D formats.
8967 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8969 GL_INVALID_OPERATION
, function_name
,
8970 "width or height invalid for level");
8974 case GL_ATC_RGB_AMD
:
8975 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8976 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8977 case GL_ETC1_RGB8_OES
:
8978 DCHECK_EQ(1, depth
); // 2D formats.
8979 if (width
<= 0 || height
<= 0) {
8981 GL_INVALID_OPERATION
, function_name
,
8982 "width or height invalid for level");
8986 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8987 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8988 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8989 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
8990 DCHECK_EQ(1, depth
); // 2D formats.
8991 if (!IsValidPVRTCSize(level
, width
) ||
8992 !IsValidPVRTCSize(level
, height
)) {
8994 GL_INVALID_OPERATION
, function_name
,
8995 "width or height invalid for level");
9001 case GL_COMPRESSED_R11_EAC
:
9002 case GL_COMPRESSED_SIGNED_R11_EAC
:
9003 case GL_COMPRESSED_RG11_EAC
:
9004 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9005 case GL_COMPRESSED_RGB8_ETC2
:
9006 case GL_COMPRESSED_SRGB8_ETC2
:
9007 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9008 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9009 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9010 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9011 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9013 GL_INVALID_OPERATION
, function_name
,
9014 "width, height, or depth invalid");
9017 if (target
== GL_TEXTURE_3D
) {
9019 GL_INVALID_OPERATION
, function_name
,
9020 "target invalid for format");
9029 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9030 const char* function_name
,
9031 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9032 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9034 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9036 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9041 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9042 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9043 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9044 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9045 const int kBlockWidth
= 4;
9046 const int kBlockHeight
= 4;
9047 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9049 GL_INVALID_OPERATION
, function_name
,
9050 "xoffset or yoffset not multiple of 4");
9053 GLsizei tex_width
= 0;
9054 GLsizei tex_height
= 0;
9055 if (!texture
->GetLevelSize(target
, level
,
9056 &tex_width
, &tex_height
, nullptr) ||
9057 width
- xoffset
> tex_width
||
9058 height
- yoffset
> tex_height
) {
9060 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
9063 return ValidateCompressedTexDimensions(
9064 function_name
, target
, level
, width
, height
, 1, format
);
9066 case GL_ATC_RGB_AMD
:
9067 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9068 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
9070 GL_INVALID_OPERATION
, function_name
,
9071 "not supported for ATC textures");
9074 case GL_ETC1_RGB8_OES
: {
9076 GL_INVALID_OPERATION
, function_name
,
9077 "not supported for ECT1_RGB8_OES textures");
9080 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9081 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9082 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9083 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
9084 if ((xoffset
!= 0) || (yoffset
!= 0)) {
9086 GL_INVALID_OPERATION
, function_name
,
9087 "xoffset and yoffset must be zero");
9090 GLsizei tex_width
= 0;
9091 GLsizei tex_height
= 0;
9092 if (!texture
->GetLevelSize(target
, level
,
9093 &tex_width
, &tex_height
, nullptr) ||
9094 width
!= tex_width
||
9095 height
!= tex_height
) {
9097 GL_INVALID_OPERATION
, function_name
,
9098 "dimensions must match existing texture level dimensions");
9101 return ValidateCompressedTexDimensions(
9102 function_name
, target
, level
, width
, height
, 1, format
);
9106 case GL_COMPRESSED_R11_EAC
:
9107 case GL_COMPRESSED_SIGNED_R11_EAC
:
9108 case GL_COMPRESSED_RG11_EAC
:
9109 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9110 case GL_COMPRESSED_RGB8_ETC2
:
9111 case GL_COMPRESSED_SRGB8_ETC2
:
9112 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9113 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9114 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9115 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9117 const int kBlockSize
= 4;
9118 GLsizei tex_width
, tex_height
;
9119 if (target
== GL_TEXTURE_3D
||
9120 !texture
->GetLevelSize(target
, level
,
9121 &tex_width
, &tex_height
, nullptr) ||
9122 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
9123 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
9124 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
9126 GL_INVALID_OPERATION
, function_name
,
9127 "dimensions must match existing texture level dimensions");
9137 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
9140 GLenum internal_format
,
9146 if (!validators_
->texture_target
.IsValid(target
)) {
9147 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9148 "glCompressedTexImage2D", target
, "target");
9149 return error::kNoError
;
9151 if (!validators_
->compressed_texture_format
.IsValid(
9153 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9154 "glCompressedTexImage2D", internal_format
, "internal_format");
9155 return error::kNoError
;
9157 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9161 "glCompressedTexImage2D", "dimensions out of range");
9162 return error::kNoError
;
9164 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9169 "glCompressedTexImage2D", "unknown texture target");
9170 return error::kNoError
;
9172 Texture
* texture
= texture_ref
->texture();
9173 if (texture
->IsImmutable()) {
9175 GL_INVALID_OPERATION
,
9176 "glCompressedTexImage2D", "texture is immutable");
9177 return error::kNoError
;
9180 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
9181 width
, height
, 1, internal_format
) ||
9182 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
9183 1, internal_format
, image_size
)) {
9184 return error::kNoError
;
9187 if (!EnsureGPUMemoryAvailable(image_size
)) {
9189 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
9190 return error::kNoError
;
9193 if (texture
->IsAttachedToFramebuffer()) {
9194 framebuffer_state_
.clear_state_dirty
= true;
9197 scoped_ptr
<int8
[]> zero
;
9199 zero
.reset(new int8
[image_size
]);
9200 memset(zero
.get(), 0, image_size
);
9203 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9204 glCompressedTexImage2D(
9205 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9206 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9207 if (error
== GL_NO_ERROR
) {
9208 texture_manager()->SetLevelInfo(
9209 texture_ref
, target
, level
, internal_format
,
9210 width
, height
, 1, border
, 0, 0, true);
9213 // This may be a slow command. Exit command processing to allow for
9214 // context preemption and GPU watchdog checks.
9215 ExitCommandProcessingEarly();
9216 return error::kNoError
;
9219 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
9220 uint32 immediate_data_size
,
9221 const void* cmd_data
) {
9222 const gles2::cmds::CompressedTexImage2D
& c
=
9223 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
9224 GLenum target
= static_cast<GLenum
>(c
.target
);
9225 GLint level
= static_cast<GLint
>(c
.level
);
9226 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9227 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9228 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9229 GLint border
= static_cast<GLint
>(c
.border
);
9230 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9231 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9232 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9233 const void* data
= NULL
;
9234 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9235 data
= GetSharedMemoryAs
<const void*>(
9236 data_shm_id
, data_shm_offset
, image_size
);
9238 return error::kOutOfBounds
;
9241 return DoCompressedTexImage2D(
9242 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
9245 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9246 uint32 immediate_data_size
,
9247 const void* cmd_data
) {
9248 const gles2::cmds::CompressedTexImage2DBucket
& c
=
9249 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
9250 GLenum target
= static_cast<GLenum
>(c
.target
);
9251 GLint level
= static_cast<GLint
>(c
.level
);
9252 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9253 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9254 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9255 GLint border
= static_cast<GLint
>(c
.border
);
9256 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9258 return error::kInvalidArguments
;
9260 uint32 data_size
= bucket
->size();
9261 GLsizei imageSize
= data_size
;
9262 const void* data
= bucket
->GetData(0, data_size
);
9264 return error::kInvalidArguments
;
9266 return DoCompressedTexImage2D(
9267 target
, level
, internal_format
, width
, height
, border
,
9271 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9272 uint32 immediate_data_size
,
9273 const void* cmd_data
) {
9274 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
9275 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
9276 GLenum target
= static_cast<GLenum
>(c
.target
);
9277 GLint level
= static_cast<GLint
>(c
.level
);
9278 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9279 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9280 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9281 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9282 GLenum format
= static_cast<GLenum
>(c
.format
);
9283 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9285 return error::kInvalidArguments
;
9287 uint32 data_size
= bucket
->size();
9288 GLsizei imageSize
= data_size
;
9289 const void* data
= bucket
->GetData(0, data_size
);
9291 return error::kInvalidArguments
;
9293 if (!validators_
->texture_target
.IsValid(target
)) {
9295 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9296 return error::kNoError
;
9298 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9299 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9300 "glCompressedTexSubImage2D", format
, "format");
9301 return error::kNoError
;
9305 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9306 return error::kNoError
;
9310 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9311 return error::kNoError
;
9313 if (imageSize
< 0) {
9315 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9316 return error::kNoError
;
9318 DoCompressedTexSubImage2D(
9319 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9320 return error::kNoError
;
9323 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
9326 GLenum internal_format
,
9333 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9334 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9335 "glCompressedTexImage3D", target
, "target");
9336 return error::kNoError
;
9338 if (!validators_
->compressed_texture_format
.IsValid(
9340 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9341 "glCompressedTexImage3D", internal_format
, "internal_format");
9342 return error::kNoError
;
9344 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
9348 "glCompressedTexImage3D", "dimensions out of range");
9349 return error::kNoError
;
9351 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9356 "glCompressedTexImage3D", "unknown texture target");
9357 return error::kNoError
;
9359 Texture
* texture
= texture_ref
->texture();
9360 if (texture
->IsImmutable()) {
9362 GL_INVALID_OPERATION
,
9363 "glCompressedTexImage3D", "texture is immutable");
9364 return error::kNoError
;
9367 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
9368 width
, height
, depth
, internal_format
) ||
9369 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
9370 depth
, internal_format
, image_size
)) {
9371 return error::kNoError
;
9374 if (!EnsureGPUMemoryAvailable(image_size
)) {
9376 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
9377 return error::kNoError
;
9380 if (texture
->IsAttachedToFramebuffer()) {
9381 framebuffer_state_
.clear_state_dirty
= true;
9384 scoped_ptr
<int8
[]> zero
;
9386 zero
.reset(new int8
[image_size
]);
9387 memset(zero
.get(), 0, image_size
);
9390 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9391 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
9392 border
, image_size
, data
);
9393 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9394 if (error
== GL_NO_ERROR
) {
9395 texture_manager()->SetLevelInfo(
9396 texture_ref
, target
, level
, internal_format
,
9397 width
, height
, depth
, border
, 0, 0, true);
9400 // This may be a slow command. Exit command processing to allow for
9401 // context preemption and GPU watchdog checks.
9402 ExitCommandProcessingEarly();
9403 return error::kNoError
;
9406 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
9407 uint32 immediate_data_size
, const void* cmd_data
) {
9408 if (!unsafe_es3_apis_enabled())
9409 return error::kUnknownCommand
;
9411 const gles2::cmds::CompressedTexImage3D
& c
=
9412 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
9413 GLenum target
= static_cast<GLenum
>(c
.target
);
9414 GLint level
= static_cast<GLint
>(c
.level
);
9415 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9416 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9417 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9418 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9419 GLint border
= static_cast<GLint
>(c
.border
);
9420 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
9421 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9422 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9423 const void* data
= NULL
;
9424 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9425 data
= GetSharedMemoryAs
<const void*>(
9426 data_shm_id
, data_shm_offset
, image_size
);
9428 return error::kOutOfBounds
;
9431 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9432 depth
, border
, image_size
, data
);
9435 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9436 uint32 immediate_data_size
, const void* cmd_data
) {
9437 if (!unsafe_es3_apis_enabled())
9438 return error::kUnknownCommand
;
9440 const gles2::cmds::CompressedTexImage3DBucket
& c
=
9441 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
9442 GLenum target
= static_cast<GLenum
>(c
.target
);
9443 GLint level
= static_cast<GLint
>(c
.level
);
9444 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9445 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9446 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9447 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9448 GLint border
= static_cast<GLint
>(c
.border
);
9449 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9451 return error::kInvalidArguments
;
9453 uint32 data_size
= bucket
->size();
9454 GLsizei imageSize
= data_size
;
9455 const void* data
= bucket
->GetData(0, data_size
);
9457 return error::kInvalidArguments
;
9459 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
9460 depth
, border
, imageSize
, data
);
9463 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9464 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9465 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9466 GLsizei image_size
, const void* data
) {
9467 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
9469 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
9472 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9473 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9474 "glCompressedTexSubImage3D", format
, "format");
9477 if (width
< 0 || height
< 0 || depth
< 0) {
9479 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
9482 if (image_size
< 0) {
9484 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
9487 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9491 "unknown texture for target");
9494 Texture
* texture
= texture_ref
->texture();
9495 GLenum type
= 0, internal_format
= 0;
9496 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9497 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9498 "level does not exist");
9501 if (internal_format
!= format
) {
9502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
9503 "format does not match internal format");
9506 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
9507 width
, height
, depth
, type
)) {
9508 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
9512 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9513 width
, height
, depth
, format
,
9515 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9516 target
, level
, xoffset
, yoffset
,
9517 zoffset
, width
, height
, depth
,
9522 // Note: There is no need to deal with texture cleared tracking here
9523 // because the validation above means you can only get here if the level
9524 // is already a matching compressed format and in that case
9525 // CompressedTexImage3D already cleared the texture.
9526 glCompressedTexSubImage3D(
9527 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9530 // This may be a slow command. Exit command processing to allow for
9531 // context preemption and GPU watchdog checks.
9532 ExitCommandProcessingEarly();
9535 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9536 uint32 immediate_data_size
, const void* cmd_data
) {
9537 if (!unsafe_es3_apis_enabled())
9538 return error::kUnknownCommand
;
9539 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
9540 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
9541 GLenum target
= static_cast<GLenum
>(c
.target
);
9542 GLint level
= static_cast<GLint
>(c
.level
);
9543 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9544 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9545 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9546 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9547 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9548 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9549 GLenum format
= static_cast<GLenum
>(c
.format
);
9550 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9552 return error::kInvalidArguments
;
9554 uint32 data_size
= bucket
->size();
9555 GLsizei image_size
= data_size
;
9556 const void* data
= bucket
->GetData(0, data_size
);
9558 return error::kInvalidArguments
;
9560 DoCompressedTexSubImage3D(
9561 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
9563 return error::kNoError
;
9566 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9567 const void* cmd_data
) {
9568 const gles2::cmds::TexImage2D
& c
=
9569 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9570 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9571 "width", c
.width
, "height", c
.height
);
9572 // Set as failed for now, but if it successed, this will be set to not failed.
9573 texture_state_
.tex_image_2d_failed
= true;
9574 GLenum target
= static_cast<GLenum
>(c
.target
);
9575 GLint level
= static_cast<GLint
>(c
.level
);
9576 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9577 // for internalformat.
9578 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9579 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9580 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9581 GLint border
= static_cast<GLint
>(c
.border
);
9582 GLenum format
= static_cast<GLenum
>(c
.format
);
9583 GLenum type
= static_cast<GLenum
>(c
.type
);
9584 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9585 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9587 if (!GLES2Util::ComputeImageDataSizes(
9588 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9590 return error::kOutOfBounds
;
9592 const void* pixels
= NULL
;
9593 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9594 pixels
= GetSharedMemoryAs
<const void*>(
9595 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9597 return error::kOutOfBounds
;
9601 // For testing only. Allows us to stress the ability to respond to OOM errors.
9602 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9603 (width
* height
>= 4096 * 4096)) {
9606 "glTexImage2D", "synthetic out of memory");
9607 return error::kNoError
;
9610 TextureManager::DoTextImage2DArguments args
= {
9611 target
, level
, internal_format
, width
, height
, border
, format
, type
,
9612 pixels
, pixels_size
};
9613 texture_manager()->ValidateAndDoTexImage2D(
9614 &texture_state_
, &state_
, &framebuffer_state_
, args
);
9616 // This may be a slow command. Exit command processing to allow for
9617 // context preemption and GPU watchdog checks.
9618 ExitCommandProcessingEarly();
9619 return error::kNoError
;
9622 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9623 const void* cmd_data
) {
9624 // TODO(zmo): Unsafe ES3 API.
9625 if (!unsafe_es3_apis_enabled())
9626 return error::kUnknownCommand
;
9628 const gles2::cmds::TexImage3D
& c
=
9629 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9630 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9631 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9632 GLenum target
= static_cast<GLenum
>(c
.target
);
9633 GLint level
= static_cast<GLint
>(c
.level
);
9634 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9635 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9636 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9637 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9638 GLint border
= static_cast<GLint
>(c
.border
);
9639 GLenum format
= static_cast<GLenum
>(c
.format
);
9640 GLenum type
= static_cast<GLenum
>(c
.type
);
9641 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9642 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9644 if (!GLES2Util::ComputeImageDataSizes(
9645 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9647 return error::kOutOfBounds
;
9649 const void* pixels
= NULL
;
9650 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9651 pixels
= GetSharedMemoryAs
<const void*>(
9652 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9654 return error::kOutOfBounds
;
9658 glTexImage3D(target
, level
, internal_format
, width
, height
, depth
, border
,
9659 format
, type
, pixels
);
9661 // This may be a slow command. Exit command processing to allow for
9662 // context preemption and GPU watchdog checks.
9663 ExitCommandProcessingEarly();
9664 return error::kNoError
;
9667 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9676 const void * data
) {
9677 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9681 GL_INVALID_OPERATION
,
9682 "glCompressedTexSubImage2D", "unknown texture for target");
9685 Texture
* texture
= texture_ref
->texture();
9687 GLenum internal_format
= 0;
9688 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9690 GL_INVALID_OPERATION
,
9691 "glCompressedTexSubImage2D", "level does not exist.");
9694 if (internal_format
!= format
) {
9696 GL_INVALID_OPERATION
,
9697 "glCompressedTexSubImage2D", "format does not match internal format.");
9700 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
9703 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9707 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
9708 width
, height
, 1, format
, image_size
) ||
9709 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
9710 target
, level
, xoffset
, yoffset
, 0,
9711 width
, height
, 1, format
, texture
)) {
9716 // Note: There is no need to deal with texture cleared tracking here
9717 // because the validation above means you can only get here if the level
9718 // is already a matching compressed format and in that case
9719 // CompressedTexImage2D already cleared the texture.
9720 glCompressedTexSubImage2D(
9721 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9723 // This may be a slow command. Exit command processing to allow for
9724 // context preemption and GPU watchdog checks.
9725 ExitCommandProcessingEarly();
9729 GLint start
, GLint range
, GLint sourceRange
,
9730 GLint
* out_start
, GLint
* out_range
) {
9737 GLint end
= start
+ range
;
9738 if (end
> sourceRange
) {
9739 range
-= end
- sourceRange
;
9745 void GLES2DecoderImpl::DoCopyTexImage2D(
9748 GLenum internal_format
,
9754 DCHECK(!ShouldDeferReads());
9755 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9759 GL_INVALID_OPERATION
,
9760 "glCopyTexImage2D", "unknown texture for target");
9763 Texture
* texture
= texture_ref
->texture();
9764 if (texture
->IsImmutable()) {
9766 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9769 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9772 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9775 if (!texture_manager()->ValidateFormatAndTypeCombination(
9776 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9777 GL_UNSIGNED_BYTE
)) {
9781 // Check we have compatible formats.
9782 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9783 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9784 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9786 if ((channels_needed
& channels_exist
) != channels_needed
) {
9788 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9792 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9794 GL_INVALID_OPERATION
,
9795 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9799 uint32 estimated_size
= 0;
9800 if (!GLES2Util::ComputeImageDataSizes(
9801 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9802 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9804 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9808 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9809 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9813 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9817 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9819 GL_INVALID_OPERATION
,
9820 "glCopyTexImage2D", "source and destination textures are the same");
9824 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9828 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9829 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9830 gfx::Size size
= GetBoundReadFrameBufferSize();
9832 if (texture
->IsAttachedToFramebuffer()) {
9833 framebuffer_state_
.clear_state_dirty
= true;
9836 // Clip to size to source dimensions
9839 GLint copyWidth
= 0;
9840 GLint copyHeight
= 0;
9841 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9842 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9846 copyWidth
!= width
||
9847 copyHeight
!= height
) {
9848 // some part was clipped so clear the texture.
9849 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9850 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9852 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9855 if (copyHeight
> 0 && copyWidth
> 0) {
9856 GLint dx
= copyX
- x
;
9857 GLint dy
= copyY
- y
;
9860 ScopedModifyPixels
modify(texture_ref
);
9861 glCopyTexSubImage2D(target
, level
,
9862 destX
, destY
, copyX
, copyY
,
9863 copyWidth
, copyHeight
);
9866 ScopedModifyPixels
modify(texture_ref
);
9867 glCopyTexImage2D(target
, level
, internal_format
,
9868 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9870 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9871 if (error
== GL_NO_ERROR
) {
9872 texture_manager()->SetLevelInfo(
9873 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
9874 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
9877 // This may be a slow command. Exit command processing to allow for
9878 // context preemption and GPU watchdog checks.
9879 ExitCommandProcessingEarly();
9882 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9891 DCHECK(!ShouldDeferReads());
9892 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9896 GL_INVALID_OPERATION
,
9897 "glCopyTexSubImage2D", "unknown texture for target");
9900 Texture
* texture
= texture_ref
->texture();
9903 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
9904 !texture
->ValidForTexture(
9905 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
9907 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
9910 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9912 GL_INVALID_OPERATION
,
9913 "glCopyTexSubImage2D", "async upload pending for texture");
9917 // Check we have compatible formats.
9918 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9919 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9920 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
9922 if (!channels_needed
||
9923 (channels_needed
& channels_exist
) != channels_needed
) {
9925 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
9929 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9931 GL_INVALID_OPERATION
,
9932 "glCopySubImage2D", "can not be used with depth or stencil textures");
9936 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9940 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9942 GL_INVALID_OPERATION
,
9943 "glCopyTexSubImage2D", "source and destination textures are the same");
9947 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9951 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9952 gfx::Size size
= GetBoundReadFrameBufferSize();
9955 GLint copyWidth
= 0;
9956 GLint copyHeight
= 0;
9957 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9958 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9960 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
9961 height
!= size
.height()) {
9962 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
9964 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
9965 "dimensions too big");
9969 // Write all pixels in below.
9970 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9975 copyWidth
!= width
||
9976 copyHeight
!= height
) {
9977 // some part was clipped so clear the sub rect.
9978 uint32 pixels_size
= 0;
9979 if (!GLES2Util::ComputeImageDataSizes(
9980 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9983 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
9986 scoped_ptr
<char[]> zero(new char[pixels_size
]);
9987 memset(zero
.get(), 0, pixels_size
);
9988 ScopedModifyPixels
modify(texture_ref
);
9990 target
, level
, xoffset
, yoffset
, width
, height
,
9991 format
, type
, zero
.get());
9994 if (copyHeight
> 0 && copyWidth
> 0) {
9995 GLint dx
= copyX
- x
;
9996 GLint dy
= copyY
- y
;
9997 GLint destX
= xoffset
+ dx
;
9998 GLint destY
= yoffset
+ dy
;
9999 ScopedModifyPixels
modify(texture_ref
);
10000 glCopyTexSubImage2D(target
, level
,
10001 destX
, destY
, copyX
, copyY
,
10002 copyWidth
, copyHeight
);
10005 // This may be a slow command. Exit command processing to allow for
10006 // context preemption and GPU watchdog checks.
10007 ExitCommandProcessingEarly();
10010 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10011 error::Error
* error
,
10012 const char* function_name
,
10021 const void * data
) {
10022 (*error
) = error::kNoError
;
10023 if (!validators_
->texture_target
.IsValid(target
)) {
10024 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10032 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10035 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10037 if (!texture_ref
) {
10038 LOCAL_SET_GL_ERROR(
10039 GL_INVALID_OPERATION
,
10040 function_name
, "unknown texture for target");
10043 Texture
* texture
= texture_ref
->texture();
10044 GLenum current_type
= 0;
10045 GLenum internal_format
= 0;
10046 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
10047 LOCAL_SET_GL_ERROR(
10048 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
10051 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
10052 function_name
, format
, type
, internal_format
, level
)) {
10055 if (type
!= current_type
) {
10056 LOCAL_SET_GL_ERROR(
10057 GL_INVALID_OPERATION
,
10058 function_name
, "type does not match type of texture.");
10061 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
10062 LOCAL_SET_GL_ERROR(
10063 GL_INVALID_OPERATION
,
10064 function_name
, "async upload pending for texture");
10067 if (!texture
->ValidForTexture(
10068 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1, type
)) {
10069 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
10072 if ((GLES2Util::GetChannelsForFormat(format
) &
10073 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10074 LOCAL_SET_GL_ERROR(
10075 GL_INVALID_OPERATION
,
10076 function_name
, "can not supply data for depth or stencil textures");
10079 if (data
== NULL
) {
10080 (*error
) = error::kOutOfBounds
;
10086 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
10095 const void * data
) {
10096 error::Error error
= error::kNoError
;
10097 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
10098 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
10101 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10103 Texture
* texture
= texture_ref
->texture();
10104 GLsizei tex_width
= 0;
10105 GLsizei tex_height
= 0;
10106 bool ok
= texture
->GetLevelSize(
10107 target
, level
, &tex_width
, &tex_height
, nullptr);
10109 if (xoffset
!= 0 || yoffset
!= 0 ||
10110 width
!= tex_width
|| height
!= tex_height
) {
10111 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
10113 LOCAL_SET_GL_ERROR(
10114 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
10115 return error::kNoError
;
10117 ScopedTextureUploadTimer
timer(&texture_state_
);
10119 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10120 return error::kNoError
;
10123 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
10124 !texture
->IsImmutable() &&
10125 !texture
->HasImages()) {
10126 ScopedTextureUploadTimer
timer(&texture_state_
);
10127 GLenum internal_format
;
10129 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
10130 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10133 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
10135 ScopedTextureUploadTimer
timer(&texture_state_
);
10137 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
10139 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10141 // This may be a slow command. Exit command processing to allow for
10142 // context preemption and GPU watchdog checks.
10143 ExitCommandProcessingEarly();
10144 return error::kNoError
;
10147 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
10148 const void* cmd_data
) {
10149 const gles2::cmds::TexSubImage2D
& c
=
10150 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
10151 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10152 "width", c
.width
, "height", c
.height
);
10153 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
10154 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
10155 return error::kNoError
;
10157 GLenum target
= static_cast<GLenum
>(c
.target
);
10158 GLint level
= static_cast<GLint
>(c
.level
);
10159 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10160 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10161 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10162 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10163 GLenum format
= static_cast<GLenum
>(c
.format
);
10164 GLenum type
= static_cast<GLenum
>(c
.type
);
10166 if (!GLES2Util::ComputeImageDataSizes(
10167 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
10169 return error::kOutOfBounds
;
10171 const void* pixels
= GetSharedMemoryAs
<const void*>(
10172 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10173 return DoTexSubImage2D(
10174 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
10177 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
10178 const void* cmd_data
) {
10179 // TODO(zmo): Unsafe ES3 API.
10180 if (!unsafe_es3_apis_enabled())
10181 return error::kUnknownCommand
;
10183 const gles2::cmds::TexSubImage3D
& c
=
10184 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
10185 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10186 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10187 GLenum target
= static_cast<GLenum
>(c
.target
);
10188 GLint level
= static_cast<GLint
>(c
.level
);
10189 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10190 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10191 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10192 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10193 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10194 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10195 GLenum format
= static_cast<GLenum
>(c
.format
);
10196 GLenum type
= static_cast<GLenum
>(c
.type
);
10198 if (!GLES2Util::ComputeImageDataSizes(
10199 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
10201 return error::kOutOfBounds
;
10203 const void* pixels
= GetSharedMemoryAs
<const void*>(
10204 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
10205 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
10206 depth
, format
, type
, pixels
);
10207 return error::kNoError
;
10210 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10211 uint32 immediate_data_size
,
10212 const void* cmd_data
) {
10213 const gles2::cmds::GetVertexAttribPointerv
& c
=
10214 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
10215 GLuint index
= static_cast<GLuint
>(c
.index
);
10216 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10217 typedef cmds::GetVertexAttribPointerv::Result Result
;
10218 Result
* result
= GetSharedMemoryAs
<Result
*>(
10219 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
10221 return error::kOutOfBounds
;
10223 // Check that the client initialized the result.
10224 if (result
->size
!= 0) {
10225 return error::kInvalidArguments
;
10227 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
10228 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10229 "glGetVertexAttribPointerv", pname
, "pname");
10230 return error::kNoError
;
10232 if (index
>= group_
->max_vertex_attribs()) {
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
10235 return error::kNoError
;
10237 result
->SetNumResults(1);
10238 *result
->GetData() =
10239 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
10240 return error::kNoError
;
10244 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
10245 GLint fake_location
,
10248 error::Error
* error
,
10249 GLint
* real_location
,
10250 GLuint
* service_id
,
10251 SizedResult
<T
>** result_pointer
,
10252 GLenum
* result_type
,
10253 GLsizei
* result_size
) {
10255 DCHECK(service_id
);
10256 DCHECK(result_pointer
);
10257 DCHECK(result_type
);
10258 DCHECK(result_size
);
10259 DCHECK(real_location
);
10260 *error
= error::kNoError
;
10261 // Make sure we have enough room for the result on failure.
10262 SizedResult
<T
>* result
;
10263 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10264 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
10266 *error
= error::kOutOfBounds
;
10269 *result_pointer
= result
;
10270 // Set the result size to 0 so the client does not have to check for success.
10271 result
->SetNumResults(0);
10272 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
10276 if (!program
->IsValid()) {
10277 // Program was not linked successfully. (ie, glLinkProgram)
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
10282 *service_id
= program
->service_id();
10283 GLint array_index
= -1;
10284 const Program::UniformInfo
* uniform_info
=
10285 program
->GetUniformInfoByFakeLocation(
10286 fake_location
, real_location
, &array_index
);
10287 if (!uniform_info
) {
10288 // No such location.
10289 LOCAL_SET_GL_ERROR(
10290 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
10293 GLenum type
= uniform_info
->type
;
10294 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
10295 if (num_elements
== 0) {
10296 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
10299 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
10300 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
10302 *error
= error::kOutOfBounds
;
10305 result
->SetNumResults(num_elements
);
10306 *result_size
= num_elements
* sizeof(T
);
10307 *result_type
= type
;
10311 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
10312 const void* cmd_data
) {
10313 const gles2::cmds::GetUniformiv
& c
=
10314 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
10315 GLuint program
= c
.program
;
10316 GLint fake_location
= c
.location
;
10318 GLenum result_type
;
10319 GLsizei result_size
;
10320 GLint real_location
= -1;
10322 cmds::GetUniformiv::Result
* result
;
10323 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
10324 c
.params_shm_offset
, &error
, &real_location
,
10325 &service_id
, &result
, &result_type
,
10328 service_id
, real_location
, result
->GetData());
10333 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
10334 const void* cmd_data
) {
10335 if (!unsafe_es3_apis_enabled())
10336 return error::kUnknownCommand
;
10338 const gles2::cmds::GetUniformuiv
& c
=
10339 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
10340 GLuint program
= c
.program
;
10341 GLint fake_location
= c
.location
;
10343 GLenum result_type
;
10344 GLsizei result_size
;
10345 GLint real_location
= -1;
10347 cmds::GetUniformuiv::Result
* result
;
10348 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
10349 c
.params_shm_offset
, &error
, &real_location
,
10350 &service_id
, &result
, &result_type
,
10353 service_id
, real_location
, result
->GetData());
10358 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
10359 const void* cmd_data
) {
10360 const gles2::cmds::GetUniformfv
& c
=
10361 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
10362 GLuint program
= c
.program
;
10363 GLint fake_location
= c
.location
;
10365 GLint real_location
= -1;
10367 cmds::GetUniformfv::Result
* result
;
10368 GLenum result_type
;
10369 GLsizei result_size
;
10370 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
10371 c
.params_shm_offset
, &error
, &real_location
,
10372 &service_id
, &result
, &result_type
,
10374 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
10375 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
10376 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
10377 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
10378 glGetUniformiv(service_id
, real_location
, temp
.get());
10379 GLfloat
* dst
= result
->GetData();
10380 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
10381 dst
[ii
] = (temp
[ii
] != 0);
10384 glGetUniformfv(service_id
, real_location
, result
->GetData());
10390 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10391 uint32 immediate_data_size
,
10392 const void* cmd_data
) {
10393 const gles2::cmds::GetShaderPrecisionFormat
& c
=
10394 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
10395 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
10396 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
10397 typedef cmds::GetShaderPrecisionFormat::Result Result
;
10398 Result
* result
= GetSharedMemoryAs
<Result
*>(
10399 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10401 return error::kOutOfBounds
;
10403 // Check that the client initialized the result.
10404 if (result
->success
!= 0) {
10405 return error::kInvalidArguments
;
10407 if (!validators_
->shader_type
.IsValid(shader_type
)) {
10408 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10409 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
10410 return error::kNoError
;
10412 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
10413 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10414 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
10415 return error::kNoError
;
10418 result
->success
= 1; // true
10420 GLint range
[2] = { 0, 0 };
10421 GLint precision
= 0;
10422 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
10424 result
->min_range
= range
[0];
10425 result
->max_range
= range
[1];
10426 result
->precision
= precision
;
10428 return error::kNoError
;
10431 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
10432 uint32 immediate_data_size
,
10433 const void* cmd_data
) {
10434 const gles2::cmds::GetAttachedShaders
& c
=
10435 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
10436 uint32 result_size
= c
.result_size
;
10437 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10438 Program
* program
= GetProgramInfoNotShader(
10439 program_id
, "glGetAttachedShaders");
10441 return error::kNoError
;
10443 typedef cmds::GetAttachedShaders::Result Result
;
10444 uint32 max_count
= Result::ComputeMaxResults(result_size
);
10445 Result
* result
= GetSharedMemoryAs
<Result
*>(
10446 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
10448 return error::kOutOfBounds
;
10450 // Check that the client initialized the result.
10451 if (result
->size
!= 0) {
10452 return error::kInvalidArguments
;
10455 glGetAttachedShaders(
10456 program
->service_id(), max_count
, &count
, result
->GetData());
10457 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
10458 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
10459 &result
->GetData()[ii
])) {
10461 return error::kGenericError
;
10464 result
->SetNumResults(count
);
10465 return error::kNoError
;
10468 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
10469 uint32 immediate_data_size
,
10470 const void* cmd_data
) {
10471 const gles2::cmds::GetActiveUniform
& c
=
10472 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
10473 GLuint program_id
= c
.program
;
10474 GLuint index
= c
.index
;
10475 uint32 name_bucket_id
= c
.name_bucket_id
;
10476 typedef cmds::GetActiveUniform::Result Result
;
10477 Result
* result
= GetSharedMemoryAs
<Result
*>(
10478 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10480 return error::kOutOfBounds
;
10482 // Check that the client initialized the result.
10483 if (result
->success
!= 0) {
10484 return error::kInvalidArguments
;
10486 Program
* program
= GetProgramInfoNotShader(
10487 program_id
, "glGetActiveUniform");
10489 return error::kNoError
;
10491 const Program::UniformInfo
* uniform_info
=
10492 program
->GetUniformInfo(index
);
10493 if (!uniform_info
) {
10494 LOCAL_SET_GL_ERROR(
10495 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
10496 return error::kNoError
;
10498 result
->success
= 1; // true.
10499 result
->size
= uniform_info
->size
;
10500 result
->type
= uniform_info
->type
;
10501 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10502 bucket
->SetFromString(uniform_info
->name
.c_str());
10503 return error::kNoError
;
10506 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10507 uint32 immediate_data_size
, const void* cmd_data
) {
10508 if (!unsafe_es3_apis_enabled())
10509 return error::kUnknownCommand
;
10510 const gles2::cmds::GetActiveUniformBlockiv
& c
=
10511 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
10512 GLuint program_id
= c
.program
;
10513 GLuint index
= static_cast<GLuint
>(c
.index
);
10514 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10515 Program
* program
= GetProgramInfoNotShader(
10516 program_id
, "glGetActiveUniformBlockiv");
10518 return error::kNoError
;
10520 GLuint service_id
= program
->service_id();
10521 GLint link_status
= GL_FALSE
;
10522 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10523 if (link_status
!= GL_TRUE
) {
10524 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10525 "glGetActiveActiveUniformBlockiv", "program not linked");
10526 return error::kNoError
;
10528 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10529 GLsizei num_values
= 1;
10530 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
10532 glGetActiveUniformBlockiv(
10533 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
10534 GLenum error
= glGetError();
10535 if (error
!= GL_NO_ERROR
) {
10536 // Assume this will the same error if calling with pname.
10537 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10538 return error::kNoError
;
10540 num_values
= static_cast<GLsizei
>(num
);
10542 typedef cmds::GetActiveUniformBlockiv::Result Result
;
10543 Result
* result
= GetSharedMemoryAs
<Result
*>(
10544 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10545 GLint
* params
= result
? result
->GetData() : NULL
;
10546 if (params
== NULL
) {
10547 return error::kOutOfBounds
;
10549 // Check that the client initialized the result.
10550 if (result
->size
!= 0) {
10551 return error::kInvalidArguments
;
10553 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10554 GLenum error
= glGetError();
10555 if (error
== GL_NO_ERROR
) {
10556 result
->SetNumResults(num_values
);
10558 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10560 return error::kNoError
;
10563 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10564 uint32 immediate_data_size
, const void* cmd_data
) {
10565 if (!unsafe_es3_apis_enabled())
10566 return error::kUnknownCommand
;
10567 const gles2::cmds::GetActiveUniformBlockName
& c
=
10568 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10569 GLuint program_id
= c
.program
;
10570 GLuint index
= c
.index
;
10571 uint32 name_bucket_id
= c
.name_bucket_id
;
10572 typedef cmds::GetActiveUniformBlockName::Result Result
;
10573 Result
* result
= GetSharedMemoryAs
<Result
*>(
10574 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10576 return error::kOutOfBounds
;
10578 // Check that the client initialized the result.
10579 if (*result
!= 0) {
10580 return error::kInvalidArguments
;
10582 Program
* program
= GetProgramInfoNotShader(
10583 program_id
, "glGetActiveUniformBlockName");
10585 return error::kNoError
;
10587 GLuint service_id
= program
->service_id();
10588 GLint link_status
= GL_FALSE
;
10589 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10590 if (link_status
!= GL_TRUE
) {
10591 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10592 "glGetActiveActiveUniformBlockName", "program not linked");
10593 return error::kNoError
;
10595 GLint max_length
= 0;
10597 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10598 // Increase one so &buffer[0] is always valid.
10599 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10600 std::vector
<char> buffer(buf_size
);
10601 GLsizei length
= 0;
10602 glGetActiveUniformBlockName(
10603 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10606 return error::kNoError
;
10609 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10610 DCHECK_GT(buf_size
, length
);
10611 DCHECK_EQ(0, buffer
[length
]);
10612 bucket
->SetFromString(&buffer
[0]);
10613 return error::kNoError
;
10616 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10617 uint32 immediate_data_size
, const void* cmd_data
) {
10618 if (!unsafe_es3_apis_enabled())
10619 return error::kUnknownCommand
;
10620 const gles2::cmds::GetActiveUniformsiv
& c
=
10621 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10622 GLuint program_id
= c
.program
;
10623 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10624 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10626 return error::kInvalidArguments
;
10628 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10629 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10630 typedef cmds::GetActiveUniformsiv::Result Result
;
10631 Result
* result
= GetSharedMemoryAs
<Result
*>(
10632 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10633 GLint
* params
= result
? result
->GetData() : NULL
;
10634 if (params
== NULL
) {
10635 return error::kOutOfBounds
;
10637 // Check that the client initialized the result.
10638 if (result
->size
!= 0) {
10639 return error::kInvalidArguments
;
10641 Program
* program
= GetProgramInfoNotShader(
10642 program_id
, "glGetActiveUniformsiv");
10644 return error::kNoError
;
10646 GLuint service_id
= program
->service_id();
10647 GLint link_status
= GL_FALSE
;
10648 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10649 if (link_status
!= GL_TRUE
) {
10650 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10651 "glGetActiveUniformsiv", "program not linked");
10652 return error::kNoError
;
10654 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10655 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10656 GLenum error
= glGetError();
10657 if (error
== GL_NO_ERROR
) {
10658 result
->SetNumResults(count
);
10660 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10662 return error::kNoError
;
10665 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10666 const void* cmd_data
) {
10667 const gles2::cmds::GetActiveAttrib
& c
=
10668 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10669 GLuint program_id
= c
.program
;
10670 GLuint index
= c
.index
;
10671 uint32 name_bucket_id
= c
.name_bucket_id
;
10672 typedef cmds::GetActiveAttrib::Result Result
;
10673 Result
* result
= GetSharedMemoryAs
<Result
*>(
10674 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10676 return error::kOutOfBounds
;
10678 // Check that the client initialized the result.
10679 if (result
->success
!= 0) {
10680 return error::kInvalidArguments
;
10682 Program
* program
= GetProgramInfoNotShader(
10683 program_id
, "glGetActiveAttrib");
10685 return error::kNoError
;
10687 const Program::VertexAttrib
* attrib_info
=
10688 program
->GetAttribInfo(index
);
10689 if (!attrib_info
) {
10690 LOCAL_SET_GL_ERROR(
10691 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10692 return error::kNoError
;
10694 result
->success
= 1; // true.
10695 result
->size
= attrib_info
->size
;
10696 result
->type
= attrib_info
->type
;
10697 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10698 bucket
->SetFromString(attrib_info
->name
.c_str());
10699 return error::kNoError
;
10702 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10703 const void* cmd_data
) {
10704 #if 1 // No binary shader support.
10705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10706 return error::kNoError
;
10708 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10710 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10711 return error::kNoError
;
10713 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10715 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10716 return error::kNoError
;
10719 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10720 return error::kOutOfBounds
;
10722 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10723 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10724 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10725 const void* binary
= GetSharedMemoryAs
<const void*>(
10726 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10727 if (shaders
== NULL
|| binary
== NULL
) {
10728 return error::kOutOfBounds
;
10730 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10731 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10732 Shader
* shader
= GetShader(shaders
[ii
]);
10734 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10735 return error::kNoError
;
10737 service_ids
[ii
] = shader
->service_id();
10739 // TODO(gman): call glShaderBinary
10740 return error::kNoError
;
10744 void GLES2DecoderImpl::DoSwapBuffers() {
10745 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10747 int this_frame_number
= frame_number_
++;
10748 // TRACE_EVENT for gpu tests:
10749 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10750 TRACE_EVENT_SCOPE_THREAD
,
10751 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10752 "width", (is_offscreen
? offscreen_size_
.width() :
10753 surface_
->GetSize().width()));
10754 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10755 "offscreen", is_offscreen
,
10756 "frame", this_frame_number
);
10758 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10761 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10762 "gpu_toplevel", "SwapBuffer");
10765 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10768 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10769 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10770 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10773 // If offscreen then don't actually SwapBuffers to the display. Just copy
10774 // the rendered frame to another frame buffer.
10775 if (is_offscreen
) {
10776 TRACE_EVENT2("gpu", "Offscreen",
10777 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10778 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10779 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10780 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10782 if (workarounds().needs_offscreen_buffer_workaround
) {
10783 offscreen_saved_frame_buffer_
->Create();
10787 // Allocate the offscreen saved color texture.
10788 DCHECK(offscreen_saved_color_format_
);
10789 offscreen_saved_color_texture_
->AllocateStorage(
10790 offscreen_size_
, offscreen_saved_color_format_
, false);
10792 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10793 offscreen_saved_color_texture_
.get());
10794 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10795 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10796 GL_FRAMEBUFFER_COMPLETE
) {
10797 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10798 << "because offscreen saved FBO was incomplete.";
10799 MarkContextLost(error::kUnknown
);
10800 group_
->LoseContexts(error::kUnknown
);
10804 // Clear the offscreen color texture.
10805 // TODO(piman): Is this still necessary?
10807 ScopedFrameBufferBinder
binder(this,
10808 offscreen_saved_frame_buffer_
->id());
10809 glClearColor(0, 0, 0, 0);
10810 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10811 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10812 glClear(GL_COLOR_BUFFER_BIT
);
10813 RestoreClearState();
10817 UpdateParentTextureInfo();
10820 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10822 ScopedGLErrorSuppressor
suppressor(
10823 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10825 if (IsOffscreenBufferMultisampled()) {
10826 // For multisampled buffers, resolve the frame buffer.
10827 ScopedResolvedFrameBufferBinder
binder(this, true, false);
10829 ScopedFrameBufferBinder
binder(this,
10830 offscreen_target_frame_buffer_
->id());
10832 if (offscreen_target_buffer_preserved_
) {
10833 // Copy the target frame buffer to the saved offscreen texture.
10834 offscreen_saved_color_texture_
->Copy(
10835 offscreen_saved_color_texture_
->size(),
10836 offscreen_saved_color_format_
);
10838 // Flip the textures in the parent context via the texture manager.
10839 if (!!offscreen_saved_color_texture_info_
.get())
10840 offscreen_saved_color_texture_info_
->texture()->
10841 SetServiceId(offscreen_target_color_texture_
->id());
10843 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
10844 offscreen_target_frame_buffer_
->AttachRenderTexture(
10845 offscreen_target_color_texture_
.get());
10848 // Ensure the side effects of the copy are visible to the parent
10849 // context. There is no need to do this for ANGLE because it uses a
10850 // single D3D device for all contexts.
10851 if (!feature_info_
->gl_version_info().is_angle
)
10855 if (!surface_
->SwapBuffers()) {
10856 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
10857 if (!CheckResetStatus()) {
10858 MarkContextLost(error::kUnknown
);
10859 group_
->LoseContexts(error::kUnknown
);
10864 // This may be a slow command. Exit command processing to allow for
10865 // context preemption and GPU watchdog checks.
10866 ExitCommandProcessingEarly();
10869 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
10870 context_
->SetSwapInterval(interval
);
10873 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10874 uint32 immediate_data_size
,
10875 const void* cmd_data
) {
10876 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
10877 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
10878 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10879 if (!bucket
|| bucket
->size() == 0) {
10880 return error::kInvalidArguments
;
10882 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
10883 Result
* result
= GetSharedMemoryAs
<Result
*>(
10884 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10886 return error::kOutOfBounds
;
10888 // Check that the client initialized the result.
10889 if (*result
!= 0) {
10890 return error::kInvalidArguments
;
10892 std::string feature_str
;
10893 if (!bucket
->GetAsString(&feature_str
)) {
10894 return error::kInvalidArguments
;
10897 // TODO(gman): make this some kind of table to function pointer thingy.
10898 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10899 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10900 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
10901 buffer_manager()->set_allow_fixed_attribs(true);
10902 // TODO(gman): decide how to remove the need for this const_cast.
10903 // I could make validators_ non const but that seems bad as this is the only
10904 // place it is needed. I could make some special friend class of validators
10905 // just to allow this to set them. That seems silly. I could refactor this
10906 // code to use the extension mechanism or the initialization attributes to
10907 // turn this feature on. Given that the only real point of this is to make
10908 // the conformance tests pass and given that there is lots of real work that
10909 // needs to be done it seems like refactoring for one to one of those
10910 // methods is a very low priority.
10911 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
10912 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
10913 force_webgl_glsl_validation_
= true;
10914 InitializeShaderTranslator();
10916 return error::kNoError
;
10919 *result
= 1; // true.
10920 return error::kNoError
;
10923 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10924 uint32 immediate_data_size
,
10925 const void* cmd_data
) {
10926 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
10927 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
10929 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
10930 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
10931 info
->Initialize(disallowed_features_
);
10932 bucket
->SetFromString(info
->extensions().c_str());
10933 return error::kNoError
;
10936 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10937 uint32 immediate_data_size
,
10938 const void* cmd_data
) {
10939 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
10940 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
10941 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10942 if (!bucket
|| bucket
->size() == 0) {
10943 return error::kInvalidArguments
;
10945 std::string feature_str
;
10946 if (!bucket
->GetAsString(&feature_str
)) {
10947 return error::kInvalidArguments
;
10950 bool desire_webgl_glsl_validation
=
10951 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
10952 bool desire_standard_derivatives
= false;
10953 bool desire_frag_depth
= false;
10954 bool desire_draw_buffers
= false;
10955 bool desire_shader_texture_lod
= false;
10956 if (force_webgl_glsl_validation_
) {
10957 desire_standard_derivatives
=
10958 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
10959 desire_frag_depth
=
10960 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
10961 desire_draw_buffers
=
10962 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
10963 desire_shader_texture_lod
=
10964 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
10967 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
10968 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
10969 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
10970 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
10971 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
10972 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
10973 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
10974 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
10975 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
10976 InitializeShaderTranslator();
10979 UpdateCapabilities();
10981 return error::kNoError
;
10984 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10985 uint32 immediate_data_size
,
10986 const void* cmd_data
) {
10987 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
10988 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
10989 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10990 uint32 bucket_id
= c
.bucket_id
;
10991 Bucket
* bucket
= CreateBucket(bucket_id
);
10992 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
10993 Program
* program
= NULL
;
10994 program
= GetProgram(program_id
);
10995 if (!program
|| !program
->IsValid()) {
10996 return error::kNoError
;
10998 program
->GetProgramInfo(program_manager(), bucket
);
10999 return error::kNoError
;
11002 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11003 uint32 immediate_data_size
, const void* cmd_data
) {
11004 if (!unsafe_es3_apis_enabled())
11005 return error::kUnknownCommand
;
11006 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
11007 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
11008 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11009 uint32 bucket_id
= c
.bucket_id
;
11010 Bucket
* bucket
= CreateBucket(bucket_id
);
11011 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
11012 Program
* program
= NULL
;
11013 program
= GetProgram(program_id
);
11014 if (!program
|| !program
->IsValid()) {
11015 return error::kNoError
;
11017 program
->GetUniformBlocks(bucket
);
11018 return error::kNoError
;
11021 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11022 uint32 immediate_data_size
, const void* cmd_data
) {
11023 if (!unsafe_es3_apis_enabled())
11024 return error::kUnknownCommand
;
11025 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
11026 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
11027 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11028 uint32 bucket_id
= c
.bucket_id
;
11029 Bucket
* bucket
= CreateBucket(bucket_id
);
11030 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
11031 Program
* program
= NULL
;
11032 program
= GetProgram(program_id
);
11033 if (!program
|| !program
->IsValid()) {
11034 return error::kNoError
;
11036 program
->GetUniformsES3(bucket
);
11037 return error::kNoError
;
11040 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11041 uint32 immediate_data_size
,
11042 const void* cmd_data
) {
11043 if (!unsafe_es3_apis_enabled())
11044 return error::kUnknownCommand
;
11045 const gles2::cmds::GetTransformFeedbackVarying
& c
=
11046 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
11047 GLuint program_id
= c
.program
;
11048 GLuint index
= c
.index
;
11049 uint32 name_bucket_id
= c
.name_bucket_id
;
11050 typedef cmds::GetTransformFeedbackVarying::Result Result
;
11051 Result
* result
= GetSharedMemoryAs
<Result
*>(
11052 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11054 return error::kOutOfBounds
;
11056 // Check that the client initialized the result.
11057 if (result
->success
!= 0) {
11058 return error::kInvalidArguments
;
11060 Program
* program
= GetProgramInfoNotShader(
11061 program_id
, "glGetTransformFeedbackVarying");
11063 return error::kNoError
;
11065 GLuint service_id
= program
->service_id();
11066 GLint link_status
= GL_FALSE
;
11067 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11068 if (link_status
!= GL_TRUE
) {
11069 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11070 "glGetTransformFeedbackVarying", "program not linked");
11071 return error::kNoError
;
11073 GLint max_length
= 0;
11075 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
11076 max_length
= std::max(1, max_length
);
11077 std::vector
<char> buffer(max_length
);
11078 GLsizei length
= 0;
11081 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11082 glGetTransformFeedbackVarying(
11083 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
11084 GLenum error
= glGetError();
11085 if (error
!= GL_NO_ERROR
) {
11086 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
11087 return error::kNoError
;
11089 result
->success
= 1; // true.
11090 result
->size
= static_cast<int32_t>(size
);
11091 result
->type
= static_cast<uint32_t>(type
);
11092 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11093 DCHECK(length
>= 0 && length
< max_length
);
11094 buffer
[length
] = '\0'; // Just to be safe.
11095 bucket
->SetFromString(&buffer
[0]);
11096 return error::kNoError
;
11099 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11100 uint32 immediate_data_size
, const void* cmd_data
) {
11101 if (!unsafe_es3_apis_enabled())
11102 return error::kUnknownCommand
;
11103 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
11104 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
11106 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11107 uint32 bucket_id
= c
.bucket_id
;
11108 Bucket
* bucket
= CreateBucket(bucket_id
);
11109 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
11110 Program
* program
= NULL
;
11111 program
= GetProgram(program_id
);
11112 if (!program
|| !program
->IsValid()) {
11113 return error::kNoError
;
11115 program
->GetTransformFeedbackVaryings(bucket
);
11116 return error::kNoError
;
11119 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
11120 return context_lost_reason_
;
11123 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11124 GLenum reset_status
) const {
11125 switch (reset_status
) {
11127 // TODO(kbr): improve the precision of the error code in this case.
11128 // Consider delegating to context for error code if MakeCurrent fails.
11129 return error::kUnknown
;
11130 case GL_GUILTY_CONTEXT_RESET_ARB
:
11131 return error::kGuilty
;
11132 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11133 return error::kInnocent
;
11134 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11135 return error::kUnknown
;
11139 return error::kUnknown
;
11142 bool GLES2DecoderImpl::WasContextLost() const {
11143 return context_was_lost_
;
11146 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11147 return WasContextLost() && reset_by_robustness_extension_
;
11150 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
11151 // Only lose the context once.
11152 if (WasContextLost())
11155 // Don't make GL calls in here, the context might not be current.
11156 context_lost_reason_
= reason
;
11157 current_decoder_error_
= error::kLostContext
;
11158 context_was_lost_
= true;
11160 // Some D3D drivers cannot recover from device lost in the GPU process
11161 // sandbox. Allow a new GPU process to launch.
11162 if (workarounds().exit_on_context_lost
) {
11163 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
11164 << " a D3D device in the Chrome GPU process sandbox.";
11165 #if defined(OS_WIN)
11166 base::win::SetShouldCrashOnProcessDetach(false);
11172 bool GLES2DecoderImpl::CheckResetStatus() {
11173 DCHECK(!WasContextLost());
11174 DCHECK(context_
->IsCurrent(NULL
));
11176 if (IsRobustnessSupported()) {
11177 // If the reason for the call was a GL error, we can try to determine the
11178 // reset status more accurately.
11179 GLenum driver_status
= glGetGraphicsResetStatusARB();
11180 if (driver_status
== GL_NO_ERROR
)
11183 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
11184 << " context lost via ARB/EXT_robustness. Reset status = "
11185 << GLES2Util::GetStringEnum(driver_status
);
11187 // Don't pretend we know which client was responsible.
11188 if (workarounds().use_virtualized_gl_contexts
)
11189 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
11191 switch (driver_status
) {
11192 case GL_GUILTY_CONTEXT_RESET_ARB
:
11193 MarkContextLost(error::kGuilty
);
11195 case GL_INNOCENT_CONTEXT_RESET_ARB
:
11196 MarkContextLost(error::kInnocent
);
11198 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
11199 MarkContextLost(error::kUnknown
);
11205 reset_by_robustness_extension_
= true;
11211 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11212 uint32 immediate_data_size
,
11213 const void* cmd_data
) {
11214 return error::kUnknownCommand
;
11217 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11218 uint32 immediate_data_size
,
11219 const void* cmd_data
) {
11220 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
11221 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
11222 uint32 sync_point
= c
.sync_point
;
11223 if (wait_sync_point_callback_
.is_null())
11224 return error::kNoError
;
11226 return wait_sync_point_callback_
.Run(sync_point
) ?
11227 error::kNoError
: error::kDeferCommandUntilLater
;
11230 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11231 uint32 immediate_data_size
,
11232 const void* cmd_data
) {
11233 if (surface_
->DeferDraws())
11234 return error::kDeferCommandUntilLater
;
11235 if (!surface_
->SetBackbufferAllocation(false))
11236 return error::kLostContext
;
11237 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
11238 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
11239 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
11240 return error::kNoError
;
11243 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11244 GLsizei n
, const GLuint
* client_ids
) {
11245 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11246 if (query_manager_
->GetQuery(client_ids
[ii
])) {
11250 query_manager_
->GenQueries(n
, client_ids
);
11254 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11255 GLsizei n
, const GLuint
* client_ids
) {
11256 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11257 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
11258 if (query
&& !query
->IsDeleted()) {
11259 ContextState::QueryMap::iterator it
=
11260 state_
.current_queries
.find(query
->target());
11261 if (it
!= state_
.current_queries
.end())
11262 state_
.current_queries
.erase(it
);
11264 query
->Destroy(true);
11266 query_manager_
->RemoveQuery(client_ids
[ii
]);
11270 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
11271 if (query_manager_
.get() == NULL
) {
11274 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
11275 current_decoder_error_
= error::kOutOfBounds
;
11277 return query_manager_
->HavePendingQueries();
11280 // Note that if there are no pending readpixels right now,
11281 // this function will call the callback immediately.
11282 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
11283 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
11284 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
11290 void GLES2DecoderImpl::ProcessPendingReadPixels() {
11291 while (!pending_readpixel_fences_
.empty() &&
11292 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
11293 std::vector
<base::Closure
> callbacks
=
11294 pending_readpixel_fences_
.front()->callbacks
;
11295 pending_readpixel_fences_
.pop();
11296 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
11297 callbacks
[i
].Run();
11302 bool GLES2DecoderImpl::HasMoreIdleWork() {
11303 return !pending_readpixel_fences_
.empty() ||
11304 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
11307 void GLES2DecoderImpl::PerformIdleWork() {
11308 ProcessPendingReadPixels();
11309 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
11311 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
11312 ProcessFinishedAsyncTransfers();
11315 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
11316 const void* cmd_data
) {
11317 const gles2::cmds::BeginQueryEXT
& c
=
11318 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
11319 GLenum target
= static_cast<GLenum
>(c
.target
);
11320 GLuint client_id
= static_cast<GLuint
>(c
.id
);
11321 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
11322 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
11325 case GL_COMMANDS_ISSUED_CHROMIUM
:
11326 case GL_LATENCY_QUERY_CHROMIUM
:
11327 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
11328 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
11329 case GL_GET_ERROR_QUERY_CHROMIUM
:
11331 case GL_COMMANDS_COMPLETED_CHROMIUM
:
11332 if (!features().chromium_sync_query
) {
11333 LOCAL_SET_GL_ERROR(
11334 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11335 "not enabled for commands completed queries");
11336 return error::kNoError
;
11340 if (!features().occlusion_query_boolean
) {
11341 LOCAL_SET_GL_ERROR(
11342 GL_INVALID_OPERATION
, "glBeginQueryEXT",
11343 "not enabled for occlusion queries");
11344 return error::kNoError
;
11349 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
11350 LOCAL_SET_GL_ERROR(
11351 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
11352 return error::kNoError
;
11355 if (client_id
== 0) {
11356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
11357 return error::kNoError
;
11360 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
11362 if (!query_manager_
->IsValidQuery(client_id
)) {
11363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11365 "id not made by glGenQueriesEXT");
11366 return error::kNoError
;
11368 query
= query_manager_
->CreateQuery(
11369 target
, client_id
, sync_shm_id
, sync_shm_offset
);
11372 if (query
->target() != target
) {
11373 LOCAL_SET_GL_ERROR(
11374 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
11375 return error::kNoError
;
11376 } else if (query
->shm_id() != sync_shm_id
||
11377 query
->shm_offset() != sync_shm_offset
) {
11378 DLOG(ERROR
) << "Shared memory used by query not the same as before";
11379 return error::kInvalidArguments
;
11382 if (!query_manager_
->BeginQuery(query
)) {
11383 return error::kOutOfBounds
;
11386 state_
.current_queries
[target
] = query
;
11387 return error::kNoError
;
11390 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
11391 const void* cmd_data
) {
11392 const gles2::cmds::EndQueryEXT
& c
=
11393 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
11394 GLenum target
= static_cast<GLenum
>(c
.target
);
11395 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
11396 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
11398 if (it
== state_
.current_queries
.end()) {
11399 LOCAL_SET_GL_ERROR(
11400 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
11401 return error::kNoError
;
11404 QueryManager::Query
* query
= it
->second
.get();
11405 if (!query_manager_
->EndQuery(query
, submit_count
)) {
11406 return error::kOutOfBounds
;
11409 query_manager_
->ProcessPendingTransferQueries();
11411 state_
.current_queries
.erase(it
);
11412 return error::kNoError
;
11415 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11416 GLsizei n
, const GLuint
* client_ids
) {
11417 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11418 if (GetVertexAttribManager(client_ids
[ii
])) {
11423 if (!features().native_vertex_array_object
) {
11425 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11426 CreateVertexAttribManager(client_ids
[ii
], 0, true);
11429 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11431 glGenVertexArraysOES(n
, service_ids
.get());
11432 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11433 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
11440 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11441 GLsizei n
, const GLuint
* client_ids
) {
11442 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11443 VertexAttribManager
* vao
=
11444 GetVertexAttribManager(client_ids
[ii
]);
11445 if (vao
&& !vao
->IsDeleted()) {
11446 if (state_
.vertex_attrib_manager
.get() == vao
) {
11447 DoBindVertexArrayOES(0);
11449 RemoveVertexAttribManager(client_ids
[ii
]);
11454 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
11455 VertexAttribManager
* vao
= NULL
;
11456 if (client_id
!= 0) {
11457 vao
= GetVertexAttribManager(client_id
);
11459 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11460 // only allows names that have been previously generated. As such, we do
11461 // not generate new names here.
11462 LOCAL_SET_GL_ERROR(
11463 GL_INVALID_OPERATION
,
11464 "glBindVertexArrayOES", "bad vertex array id.");
11465 current_decoder_error_
= error::kNoError
;
11469 vao
= state_
.default_vertex_attrib_manager
.get();
11472 // Only set the VAO state if it's changed
11473 if (state_
.vertex_attrib_manager
.get() != vao
) {
11474 state_
.vertex_attrib_manager
= vao
;
11475 if (!features().native_vertex_array_object
) {
11476 EmulateVertexArrayState();
11478 GLuint service_id
= vao
->service_id();
11479 glBindVertexArrayOES(service_id
);
11484 // Used when OES_vertex_array_object isn't natively supported
11485 void GLES2DecoderImpl::EmulateVertexArrayState() {
11486 // Setup the Vertex attribute state
11487 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
11488 RestoreStateForAttrib(vv
, true);
11491 // Setup the element buffer
11492 Buffer
* element_array_buffer
=
11493 state_
.vertex_attrib_manager
->element_array_buffer();
11494 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
11495 element_array_buffer
? element_array_buffer
->service_id() : 0);
11498 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
11499 const VertexAttribManager
* vao
=
11500 GetVertexAttribManager(client_id
);
11501 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
11504 #if defined(OS_MACOSX)
11505 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
11506 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
11508 if (it
!= texture_to_io_surface_map_
.end()) {
11509 // Found a previous IOSurface bound to this texture; release it.
11510 IOSurfaceRef surface
= it
->second
;
11511 CFRelease(surface
);
11512 texture_to_io_surface_map_
.erase(it
);
11517 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
11518 GLenum target
, GLsizei width
, GLsizei height
,
11519 GLuint io_surface_id
, GLuint plane
) {
11520 #if defined(OS_MACOSX)
11521 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
11522 LOCAL_SET_GL_ERROR(
11523 GL_INVALID_OPERATION
,
11524 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
11528 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
11529 // This might be supported in the future, and if we could require
11530 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
11531 // could delete a lot of code. For now, perform strict validation so we
11532 // know what's going on.
11533 LOCAL_SET_GL_ERROR(
11534 GL_INVALID_OPERATION
,
11535 "glTexImageIOSurface2DCHROMIUM",
11536 "requires TEXTURE_RECTANGLE_ARB target");
11540 // Default target might be conceptually valid, but disallow it to avoid
11542 TextureRef
* texture_ref
=
11543 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11544 if (!texture_ref
) {
11545 LOCAL_SET_GL_ERROR(
11546 GL_INVALID_OPERATION
,
11547 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
11551 // Look up the new IOSurface. Note that because of asynchrony
11552 // between processes this might fail; during live resizing the
11553 // plugin process might allocate and release an IOSurface before
11554 // this process gets a chance to look it up. Hold on to any old
11555 // IOSurface in this case.
11556 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11558 LOCAL_SET_GL_ERROR(
11559 GL_INVALID_OPERATION
,
11560 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11564 // Release any IOSurface previously bound to this texture.
11565 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11567 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11568 texture_to_io_surface_map_
.insert(
11569 std::make_pair(texture_ref
->service_id(), surface
));
11571 CGLContextObj context
=
11572 static_cast<CGLContextObj
>(context_
->GetHandle());
11574 CGLError err
= CGLTexImageIOSurface2D(
11581 GL_UNSIGNED_INT_8_8_8_8_REV
,
11585 if (err
!= kCGLNoError
) {
11586 LOCAL_SET_GL_ERROR(
11587 GL_INVALID_OPERATION
,
11588 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11592 texture_manager()->SetLevelInfo(
11593 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
11594 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
11597 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11598 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11602 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11603 switch (internalformat
) {
11614 case GL_LUMINANCE8_ALPHA8_EXT
:
11615 return GL_LUMINANCE_ALPHA
;
11616 case GL_LUMINANCE8_EXT
:
11617 return GL_LUMINANCE
;
11618 case GL_ALPHA8_EXT
:
11620 case GL_RGBA32F_EXT
:
11622 case GL_RGB32F_EXT
:
11624 case GL_ALPHA32F_EXT
:
11626 case GL_LUMINANCE32F_EXT
:
11627 return GL_LUMINANCE
;
11628 case GL_LUMINANCE_ALPHA32F_EXT
:
11629 return GL_LUMINANCE_ALPHA
;
11630 case GL_RGBA16F_EXT
:
11632 case GL_RGB16F_EXT
:
11634 case GL_ALPHA16F_EXT
:
11636 case GL_LUMINANCE16F_EXT
:
11637 return GL_LUMINANCE
;
11638 case GL_LUMINANCE_ALPHA16F_EXT
:
11639 return GL_LUMINANCE_ALPHA
;
11641 return GL_BGRA_EXT
;
11642 case GL_SRGB8_ALPHA8_EXT
:
11643 return GL_SRGB_ALPHA_EXT
;
11649 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11650 const char* function_name
,
11652 TextureRef
* source_texture_ref
,
11653 TextureRef
* dest_texture_ref
,
11654 GLenum dest_internal_format
) {
11655 if (!source_texture_ref
|| !dest_texture_ref
) {
11656 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
11660 if (GL_TEXTURE_2D
!= target
) {
11661 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11662 "invalid texture target");
11666 Texture
* source_texture
= source_texture_ref
->texture();
11667 Texture
* dest_texture
= dest_texture_ref
->texture();
11668 if (source_texture
== dest_texture
) {
11669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11670 "source and destination textures are the same");
11674 if (dest_texture
->target() != GL_TEXTURE_2D
||
11675 (source_texture
->target() != GL_TEXTURE_2D
&&
11676 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
11677 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
11678 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11679 "invalid texture target binding");
11683 GLenum source_type
= 0;
11684 GLenum source_internal_format
= 0;
11685 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11686 &source_internal_format
);
11688 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11689 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11690 // renderable on some platforms.
11691 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
11692 dest_internal_format
== GL_RGBA
||
11693 dest_internal_format
== GL_BGRA_EXT
;
11694 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11695 source_internal_format
== GL_RGB
||
11696 source_internal_format
== GL_RGBA
||
11697 source_internal_format
== GL_LUMINANCE
||
11698 source_internal_format
== GL_LUMINANCE_ALPHA
||
11699 source_internal_format
== GL_BGRA_EXT
;
11700 if (!valid_source_format
|| !valid_dest_format
) {
11701 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11702 "invalid internal format");
11708 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target
,
11711 GLenum internal_format
,
11712 GLenum dest_type
) {
11713 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11715 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11716 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11717 Texture
* source_texture
= source_texture_ref
->texture();
11718 Texture
* dest_texture
= dest_texture_ref
->texture();
11719 int source_width
= 0;
11720 int source_height
= 0;
11721 gfx::GLImage
* image
=
11722 source_texture
->GetLevelImage(source_texture
->target(), 0);
11724 gfx::Size size
= image
->GetSize();
11725 source_width
= size
.width();
11726 source_height
= size
.height();
11727 if (source_width
<= 0 || source_height
<= 0) {
11728 LOCAL_SET_GL_ERROR(
11730 "glCopyTextureChromium", "invalid image size");
11734 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11735 &source_width
, &source_height
, nullptr)) {
11736 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
11737 "glCopyTextureChromium",
11738 "source texture has no level 0");
11742 // Check that this type of texture is allowed.
11743 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11744 source_width
, source_height
, 1)) {
11745 LOCAL_SET_GL_ERROR(
11746 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11751 GLenum source_type
= 0;
11752 GLenum source_internal_format
= 0;
11753 source_texture
->GetLevelType(
11754 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11756 if (dest_texture
->IsImmutable()) {
11757 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
11758 "texture is immutable");
11762 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
11763 source_texture_ref
, dest_texture_ref
,
11764 internal_format
)) {
11768 // Clear the source texture if necessary.
11769 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11770 source_texture
->target(), 0)) {
11771 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
11772 "dimensions too big");
11776 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11777 // needed because it takes 10s of milliseconds to initialize.
11778 if (!copy_texture_CHROMIUM_
.get()) {
11779 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11780 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11781 copy_texture_CHROMIUM_
->Initialize(this);
11782 RestoreCurrentFramebufferBindings();
11783 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11787 GLenum dest_type_previous
= dest_type
;
11788 GLenum dest_internal_format
= internal_format
;
11789 int dest_width
= 0;
11790 int dest_height
= 0;
11791 bool dest_level_defined
= dest_texture
->GetLevelSize(
11792 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
11794 if (dest_level_defined
) {
11795 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
11796 &dest_internal_format
);
11799 // Resize the destination texture to the dimensions of the source texture.
11800 if (!dest_level_defined
|| dest_width
!= source_width
||
11801 dest_height
!= source_height
||
11802 dest_internal_format
!= internal_format
||
11803 dest_type_previous
!= dest_type
) {
11804 // Ensure that the glTexImage2D succeeds.
11805 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11806 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11807 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
11808 0, internal_format
, dest_type
, NULL
);
11809 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11810 if (error
!= GL_NO_ERROR
) {
11811 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11815 texture_manager()->SetLevelInfo(
11816 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
11817 source_height
, 1, 0, internal_format
, dest_type
, true);
11819 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11823 ScopedModifyPixels
modify(dest_texture_ref
);
11825 // Try using GLImage::CopyTexImage when possible.
11826 bool unpack_premultiply_alpha_change
=
11827 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11828 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
11829 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11830 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11834 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11836 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11837 // before presenting.
11838 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11839 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11840 // instead of using kIdentityMatrix crbug.com/226218.
11841 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
11842 this, source_texture
->target(), source_texture
->service_id(),
11843 dest_texture
->service_id(), source_width
, source_height
, unpack_flip_y_
,
11844 unpack_premultiply_alpha_
, unpack_unpremultiply_alpha_
,
11847 copy_texture_CHROMIUM_
->DoCopyTexture(
11848 this, source_texture
->target(), source_texture
->service_id(),
11849 source_internal_format
, dest_texture
->service_id(), internal_format
,
11850 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11851 unpack_unpremultiply_alpha_
);
11854 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11857 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target
,
11862 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11864 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11865 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11866 Texture
* source_texture
= source_texture_ref
->texture();
11867 Texture
* dest_texture
= dest_texture_ref
->texture();
11868 int source_width
= 0;
11869 int source_height
= 0;
11870 gfx::GLImage
* image
=
11871 source_texture
->GetLevelImage(source_texture
->target(), 0);
11873 gfx::Size size
= image
->GetSize();
11874 source_width
= size
.width();
11875 source_height
= size
.height();
11876 if (source_width
<= 0 || source_height
<= 0) {
11877 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11878 "invalid image size");
11882 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11883 &source_width
, &source_height
, nullptr)) {
11884 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11885 "source texture has no level 0");
11889 // Check that this type of texture is allowed.
11890 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11891 source_width
, source_height
, 1)) {
11892 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11893 "source texture bad dimensions");
11898 GLenum source_type
= 0;
11899 GLenum source_internal_format
= 0;
11900 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11901 &source_internal_format
);
11902 GLenum dest_type
= 0;
11903 GLenum dest_internal_format
= 0;
11904 bool dest_level_defined
= dest_texture
->GetLevelType(
11905 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
11906 if (!dest_level_defined
) {
11907 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
11908 "destination texture is not defined");
11911 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
11912 yoffset
, 0, source_width
, source_height
,
11914 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11915 "destination texture bad dimensions.");
11919 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
11920 source_texture_ref
, dest_texture_ref
,
11921 dest_internal_format
)) {
11925 // Clear the source texture if necessary.
11926 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11927 source_texture
->target(), 0)) {
11928 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11929 "source texture dimensions too big");
11933 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11934 // needed because it takes 10s of milliseconds to initialize.
11935 if (!copy_texture_CHROMIUM_
.get()) {
11936 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11937 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11938 copy_texture_CHROMIUM_
->Initialize(this);
11939 RestoreCurrentFramebufferBindings();
11940 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
11944 int dest_width
= 0;
11945 int dest_height
= 0;
11946 bool ok
= dest_texture
->GetLevelSize(
11947 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
11949 if (xoffset
!= 0 || yoffset
!= 0 || source_width
!= dest_width
||
11950 source_height
!= dest_height
) {
11951 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
11953 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11954 "destination texture dimensions too big");
11958 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11962 ScopedModifyPixels
modify(dest_texture_ref
);
11964 // Try using GLImage::CopyTexSubImage when possible.
11965 bool unpack_premultiply_alpha_change
=
11966 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11967 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&&
11968 !xoffset
&& !yoffset
) {
11969 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11970 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11974 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11976 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11977 // before presenting.
11978 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11979 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11980 // instead of using kIdentityMatrix crbug.com/226218.
11981 copy_texture_CHROMIUM_
->DoCopySubTextureWithTransform(
11982 this, source_texture
->target(), source_texture
->service_id(),
11983 dest_texture
->service_id(), xoffset
, yoffset
, dest_width
, dest_height
,
11984 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11985 unpack_unpremultiply_alpha_
, kIdentityMatrix
);
11987 copy_texture_CHROMIUM_
->DoCopySubTexture(
11988 this, source_texture
->target(), source_texture
->service_id(),
11989 source_internal_format
, dest_texture
->service_id(),
11990 dest_internal_format
, xoffset
, yoffset
, dest_width
, dest_height
,
11991 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11992 unpack_unpremultiply_alpha_
);
11995 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11998 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
11999 switch (internalformat
) {
12001 return GL_UNSIGNED_SHORT_5_6_5
;
12003 return GL_UNSIGNED_SHORT_4_4_4_4
;
12005 return GL_UNSIGNED_SHORT_5_5_5_1
;
12007 return GL_UNSIGNED_BYTE
;
12009 return GL_UNSIGNED_BYTE
;
12010 case GL_LUMINANCE8_ALPHA8_EXT
:
12011 return GL_UNSIGNED_BYTE
;
12012 case GL_LUMINANCE8_EXT
:
12013 return GL_UNSIGNED_BYTE
;
12014 case GL_ALPHA8_EXT
:
12015 return GL_UNSIGNED_BYTE
;
12016 case GL_RGBA32F_EXT
:
12018 case GL_RGB32F_EXT
:
12020 case GL_ALPHA32F_EXT
:
12022 case GL_LUMINANCE32F_EXT
:
12024 case GL_LUMINANCE_ALPHA32F_EXT
:
12026 case GL_RGBA16F_EXT
:
12027 return GL_HALF_FLOAT_OES
;
12028 case GL_RGB16F_EXT
:
12029 return GL_HALF_FLOAT_OES
;
12030 case GL_ALPHA16F_EXT
:
12031 return GL_HALF_FLOAT_OES
;
12032 case GL_LUMINANCE16F_EXT
:
12033 return GL_HALF_FLOAT_OES
;
12034 case GL_LUMINANCE_ALPHA16F_EXT
:
12035 return GL_HALF_FLOAT_OES
;
12037 return GL_UNSIGNED_BYTE
;
12043 void GLES2DecoderImpl::DoTexStorage2DEXT(
12046 GLenum internal_format
,
12049 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
12050 "width", width
, "height", height
);
12051 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
12052 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
12053 LOCAL_SET_GL_ERROR(
12054 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
12057 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12059 if (!texture_ref
) {
12060 LOCAL_SET_GL_ERROR(
12061 GL_INVALID_OPERATION
,
12062 "glTexStorage2DEXT", "unknown texture for target");
12065 Texture
* texture
= texture_ref
->texture();
12066 if (texture
->IsAttachedToFramebuffer()) {
12067 framebuffer_state_
.clear_state_dirty
= true;
12069 if (texture
->IsImmutable()) {
12070 LOCAL_SET_GL_ERROR(
12071 GL_INVALID_OPERATION
,
12072 "glTexStorage2DEXT", "texture is immutable");
12076 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
12077 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
12080 GLsizei level_width
= width
;
12081 GLsizei level_height
= height
;
12082 uint32 estimated_size
= 0;
12083 for (int ii
= 0; ii
< levels
; ++ii
) {
12084 uint32 level_size
= 0;
12085 if (!GLES2Util::ComputeImageDataSizes(
12086 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
12087 &estimated_size
, NULL
, NULL
) ||
12088 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
12089 LOCAL_SET_GL_ERROR(
12090 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
12093 level_width
= std::max(1, level_width
>> 1);
12094 level_height
= std::max(1, level_height
>> 1);
12096 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
12103 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
12104 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
12105 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
12106 if (error
== GL_NO_ERROR
) {
12107 GLsizei level_width
= width
;
12108 GLsizei level_height
= height
;
12109 for (int ii
= 0; ii
< levels
; ++ii
) {
12110 texture_manager()->SetLevelInfo(
12111 texture_ref
, target
, ii
, format
,
12112 level_width
, level_height
, 1, 0, format
, type
, false);
12113 level_width
= std::max(1, level_width
>> 1);
12114 level_height
= std::max(1, level_height
>> 1);
12116 texture
->SetImmutable(true);
12120 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
12121 uint32 immediate_data_size
,
12122 const void* cmd_data
) {
12123 return error::kUnknownCommand
;
12126 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
12127 const GLbyte
* data
) {
12128 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
12129 "context", logger_
.GetLogPrefix(),
12130 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12132 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12134 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
12137 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
12138 GLenum target
, const GLbyte
* data
) {
12139 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
12140 "context", logger_
.GetLogPrefix(),
12141 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12143 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
12147 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
12148 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
12149 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12150 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
12151 "mailbox that was not generated by "
12152 "GenMailboxCHROMIUM.";
12154 if (!texture_ref
) {
12155 LOCAL_SET_GL_ERROR(
12156 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
12160 Texture
* produced
= texture_manager()->Produce(texture_ref
);
12162 LOCAL_SET_GL_ERROR(
12163 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
12167 if (produced
->target() != target
) {
12168 LOCAL_SET_GL_ERROR(
12169 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
12173 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
12176 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
12177 const GLbyte
* data
) {
12178 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
12179 "context", logger_
.GetLogPrefix(),
12180 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12181 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12182 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
12183 "mailbox that was not generated by "
12184 "GenMailboxCHROMIUM.";
12186 scoped_refptr
<TextureRef
> texture_ref
=
12187 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12188 if (!texture_ref
.get()) {
12189 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12190 "glConsumeTextureCHROMIUM",
12191 "unknown texture for target");
12194 GLuint client_id
= texture_ref
->client_id();
12196 LOCAL_SET_GL_ERROR(
12197 GL_INVALID_OPERATION
,
12198 "glConsumeTextureCHROMIUM", "unknown texture for target");
12201 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12203 LOCAL_SET_GL_ERROR(
12204 GL_INVALID_OPERATION
,
12205 "glConsumeTextureCHROMIUM", "invalid mailbox name");
12208 if (texture
->target() != target
) {
12209 LOCAL_SET_GL_ERROR(
12210 GL_INVALID_OPERATION
,
12211 "glConsumeTextureCHROMIUM", "invalid target");
12215 DeleteTexturesHelper(1, &client_id
);
12216 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12217 glBindTexture(target
, texture_ref
->service_id());
12219 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
12220 unit
.bind_target
= target
;
12222 case GL_TEXTURE_2D
:
12223 unit
.bound_texture_2d
= texture_ref
;
12225 case GL_TEXTURE_CUBE_MAP
:
12226 unit
.bound_texture_cube_map
= texture_ref
;
12228 case GL_TEXTURE_EXTERNAL_OES
:
12229 unit
.bound_texture_external_oes
= texture_ref
;
12231 case GL_TEXTURE_RECTANGLE_ARB
:
12232 unit
.bound_texture_rectangle_arb
= texture_ref
;
12235 NOTREACHED(); // Validation should prevent us getting here.
12240 void GLES2DecoderImpl::EnsureTextureForClientId(
12242 GLuint client_id
) {
12243 TextureRef
* texture_ref
= GetTexture(client_id
);
12244 if (!texture_ref
) {
12246 glGenTextures(1, &service_id
);
12247 DCHECK_NE(0u, service_id
);
12248 texture_ref
= CreateTexture(client_id
, service_id
);
12249 texture_manager()->SetTarget(texture_ref
, target
);
12250 glBindTexture(target
, service_id
);
12251 RestoreCurrentTextureBindings(&state_
, target
);
12255 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
12256 // provided is associated with a service_id/TextureRef for consistency, even if
12257 // the resulting texture is incomplete.
12258 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
12259 uint32_t immediate_data_size
,
12260 const void* cmd_data
) {
12261 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
12263 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
12265 GLenum target
= static_cast<GLenum
>(c
.target
);
12266 uint32_t data_size
;
12267 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
12268 return error::kOutOfBounds
;
12270 if (data_size
> immediate_data_size
) {
12271 return error::kOutOfBounds
;
12273 const GLbyte
* mailbox
=
12274 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
12275 if (!validators_
->texture_bind_target
.IsValid(target
)) {
12276 LOCAL_SET_GL_ERROR_INVALID_ENUM(
12277 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
12278 return error::kNoError
;
12280 if (mailbox
== NULL
) {
12281 return error::kOutOfBounds
;
12283 uint32_t client_id
= c
.client_id
;
12284 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
12285 return error::kNoError
;
12288 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
12289 const GLbyte
* data
, GLuint client_id
) {
12290 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
12291 "context", logger_
.GetLogPrefix(),
12292 "mailbox[0]", static_cast<unsigned char>(data
[0]));
12293 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
12294 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
12295 "passed a mailbox that was not "
12296 "generated by GenMailboxCHROMIUM.";
12298 TextureRef
* texture_ref
= GetTexture(client_id
);
12300 // No need to call EnsureTextureForClientId here, the client_id already has
12301 // an associated texture.
12302 LOCAL_SET_GL_ERROR(
12303 GL_INVALID_OPERATION
,
12304 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
12307 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
12309 EnsureTextureForClientId(target
, client_id
);
12310 LOCAL_SET_GL_ERROR(
12311 GL_INVALID_OPERATION
,
12312 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
12316 if (texture
->target() != target
) {
12317 EnsureTextureForClientId(target
, client_id
);
12318 LOCAL_SET_GL_ERROR(
12319 GL_INVALID_OPERATION
,
12320 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
12324 texture_ref
= texture_manager()->Consume(client_id
, texture
);
12327 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
12328 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
12329 return valuebuffer
&& valuebuffer
->IsValid();
12332 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
12333 GLuint client_id
) {
12334 Valuebuffer
* valuebuffer
= NULL
;
12335 if (client_id
!= 0) {
12336 valuebuffer
= GetValuebuffer(client_id
);
12337 if (!valuebuffer
) {
12338 if (!group_
->bind_generates_resource()) {
12339 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
12340 "id not generated by glBindValuebufferCHROMIUM");
12344 // It's a new id so make a valuebuffer for it.
12345 CreateValuebuffer(client_id
);
12346 valuebuffer
= GetValuebuffer(client_id
);
12348 valuebuffer
->MarkAsValid();
12350 state_
.bound_valuebuffer
= valuebuffer
;
12353 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
12354 GLenum subscription
) {
12355 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
12358 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
12361 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
12362 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
12365 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
12368 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
12370 GLenum subscription
) {
12371 if (!CheckCurrentValuebufferForSubscription(
12372 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
12375 if (!CheckSubscriptionTarget(location
, subscription
,
12376 "glPopulateSubscribedValuesCHROMIUM")) {
12379 const ValueState
* state
=
12380 state_
.bound_valuebuffer
.get()->GetState(subscription
);
12382 switch (subscription
) {
12383 case GL_MOUSE_POSITION_CHROMIUM
:
12384 DoUniform2iv(location
, 1, state
->int_value
);
12387 NOTREACHED() << "Unhandled uniform subscription target "
12394 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
12395 GLsizei length
, const GLchar
* marker
) {
12399 debug_marker_manager_
.SetMarker(
12400 length
? std::string(marker
, length
) : std::string(marker
));
12403 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
12404 GLsizei length
, const GLchar
* marker
) {
12408 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
12409 debug_marker_manager_
.PushGroup(name
);
12410 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
12411 kTraceGroupMarker
);
12414 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
12415 debug_marker_manager_
.PopGroup();
12416 gpu_tracer_
->End(kTraceGroupMarker
);
12419 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
12420 GLenum target
, GLint image_id
) {
12421 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
12423 if (target
== GL_TEXTURE_CUBE_MAP
) {
12424 LOCAL_SET_GL_ERROR(
12426 "glBindTexImage2DCHROMIUM", "invalid target");
12430 // Default target might be conceptually valid, but disallow it to avoid
12432 TextureRef
* texture_ref
=
12433 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12434 if (!texture_ref
) {
12435 LOCAL_SET_GL_ERROR(
12436 GL_INVALID_OPERATION
,
12437 "glBindTexImage2DCHROMIUM", "no texture bound");
12441 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12443 LOCAL_SET_GL_ERROR(
12444 GL_INVALID_OPERATION
,
12445 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
12450 ScopedGLErrorSuppressor
suppressor(
12451 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
12452 if (!gl_image
->BindTexImage(target
)) {
12453 LOCAL_SET_GL_ERROR(
12454 GL_INVALID_OPERATION
,
12455 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
12460 gfx::Size size
= gl_image
->GetSize();
12461 texture_manager()->SetLevelInfo(
12462 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
12463 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
12464 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
12467 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
12468 GLenum target
, GLint image_id
) {
12469 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
12471 // Default target might be conceptually valid, but disallow it to avoid
12473 TextureRef
* texture_ref
=
12474 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12475 if (!texture_ref
) {
12476 LOCAL_SET_GL_ERROR(
12477 GL_INVALID_OPERATION
,
12478 "glReleaseTexImage2DCHROMIUM", "no texture bound");
12482 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
12484 LOCAL_SET_GL_ERROR(
12485 GL_INVALID_OPERATION
,
12486 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
12490 // Do nothing when image is not currently bound.
12491 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
12495 ScopedGLErrorSuppressor
suppressor(
12496 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
12497 gl_image
->ReleaseTexImage(target
);
12500 texture_manager()->SetLevelInfo(
12501 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
12502 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
12505 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
12506 uint32 immediate_data_size
,
12507 const void* cmd_data
) {
12508 const gles2::cmds::TraceBeginCHROMIUM
& c
=
12509 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
12510 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
12511 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
12512 if (!category_bucket
|| category_bucket
->size() == 0 ||
12513 !name_bucket
|| name_bucket
->size() == 0) {
12514 return error::kInvalidArguments
;
12517 std::string category_name
;
12518 std::string trace_name
;
12519 if (!category_bucket
->GetAsString(&category_name
) ||
12520 !name_bucket
->GetAsString(&trace_name
)) {
12521 return error::kInvalidArguments
;
12524 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
12525 LOCAL_SET_GL_ERROR(
12526 GL_INVALID_OPERATION
,
12527 "glTraceBeginCHROMIUM", "unable to create begin trace");
12528 return error::kNoError
;
12530 return error::kNoError
;
12533 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
12534 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
12535 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12536 "glTraceEndCHROMIUM", "no trace begin found");
12541 void GLES2DecoderImpl::DoDrawBuffersEXT(
12542 GLsizei count
, const GLenum
* bufs
) {
12543 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
12544 LOCAL_SET_GL_ERROR(
12546 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
12550 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
12552 for (GLsizei i
= 0; i
< count
; ++i
) {
12553 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
12554 bufs
[i
] != GL_NONE
) {
12555 LOCAL_SET_GL_ERROR(
12556 GL_INVALID_OPERATION
,
12557 "glDrawBuffersEXT",
12558 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12562 glDrawBuffersARB(count
, bufs
);
12563 framebuffer
->SetDrawBuffers(count
, bufs
);
12564 } else { // backbuffer
12566 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
12567 LOCAL_SET_GL_ERROR(
12568 GL_INVALID_OPERATION
,
12569 "glDrawBuffersEXT",
12570 "more than one buffer or bufs not GL_NONE or GL_BACK");
12573 GLenum mapped_buf
= bufs
[0];
12574 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12575 bufs
[0] == GL_BACK
) {
12576 mapped_buf
= GL_COLOR_ATTACHMENT0
;
12578 glDrawBuffersARB(count
, &mapped_buf
);
12579 group_
->set_draw_buffer(bufs
[0]);
12583 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
12584 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
12585 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
12586 reset_by_robustness_extension_
= true;
12589 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
12590 const GLfloat
* matrix
) {
12591 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12592 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12593 if (!features().chromium_path_rendering
) {
12594 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12595 "glMatrixLoadfCHROMIUM",
12596 "function not available");
12600 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12601 ? state_
.projection_matrix
12602 : state_
.modelview_matrix
;
12603 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
12604 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12605 // since the values of the _NV and _CHROMIUM tokens match.
12606 glMatrixLoadfEXT(matrix_mode
, matrix
);
12609 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
12610 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12611 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12613 if (!features().chromium_path_rendering
) {
12614 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12615 "glMatrixLoadIdentityCHROMIUM",
12616 "function not available");
12620 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12621 ? state_
.projection_matrix
12622 : state_
.modelview_matrix
;
12623 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
12624 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12625 // since the values of the _NV and _CHROMIUM tokens match.
12626 glMatrixLoadIdentityEXT(matrix_mode
);
12629 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12630 const char* function_name
,
12631 TextureRef
* texture_ref
,
12634 const void * data
) {
12635 // We only support async uploads to 2D textures for now.
12636 if (GL_TEXTURE_2D
!= target
) {
12637 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
12640 // We only support uploads to level zero for now.
12642 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
12645 // A transfer buffer must be bound, even for asyncTexImage2D.
12646 if (data
== NULL
) {
12647 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
12650 // We only support one async transfer in progress.
12651 if (!texture_ref
||
12652 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
12653 LOCAL_SET_GL_ERROR(
12654 GL_INVALID_OPERATION
,
12655 function_name
, "transfer already in progress");
12661 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12662 uint32 async_upload_token
,
12663 uint32 sync_data_shm_id
,
12664 uint32 sync_data_shm_offset
) {
12665 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
12666 if (!buffer
.get() ||
12667 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
12668 return base::Closure();
12670 AsyncMemoryParams
mem_params(buffer
,
12671 sync_data_shm_offset
,
12672 sizeof(AsyncUploadSync
));
12674 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
12675 new AsyncUploadTokenCompletionObserver(async_upload_token
));
12678 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
12679 base::Unretained(GetAsyncPixelTransferManager()),
12684 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12685 uint32 immediate_data_size
,
12686 const void* cmd_data
) {
12687 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
12688 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
12689 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12690 GLenum target
= static_cast<GLenum
>(c
.target
);
12691 GLint level
= static_cast<GLint
>(c
.level
);
12692 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
12693 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12694 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12695 GLint border
= static_cast<GLint
>(c
.border
);
12696 GLenum format
= static_cast<GLenum
>(c
.format
);
12697 GLenum type
= static_cast<GLenum
>(c
.type
);
12698 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
12699 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
12700 uint32 pixels_size
;
12701 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12702 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12703 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12705 base::ScopedClosureRunner scoped_completion_callback
;
12706 if (async_upload_token
) {
12707 base::Closure completion_closure
=
12708 AsyncUploadTokenCompletionClosure(async_upload_token
,
12710 sync_data_shm_offset
);
12711 if (completion_closure
.is_null())
12712 return error::kInvalidArguments
;
12714 scoped_completion_callback
.Reset(completion_closure
);
12717 // TODO(epenner): Move this and copies of this memory validation
12718 // into ValidateTexImage2D step.
12719 if (!GLES2Util::ComputeImageDataSizes(
12720 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
12722 return error::kOutOfBounds
;
12724 const void* pixels
= NULL
;
12725 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
12726 pixels
= GetSharedMemoryAs
<const void*>(
12727 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
12729 return error::kOutOfBounds
;
12733 TextureManager::DoTextImage2DArguments args
= {
12734 target
, level
, internal_format
, width
, height
, border
, format
, type
,
12735 pixels
, pixels_size
};
12736 TextureRef
* texture_ref
;
12737 // All the normal glTexSubImage2D validation.
12738 if (!texture_manager()->ValidateTexImage2D(
12739 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
12740 return error::kNoError
;
12743 // Extra async validation.
12744 Texture
* texture
= texture_ref
->texture();
12745 if (!ValidateAsyncTransfer(
12746 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12747 return error::kNoError
;
12749 // Don't allow async redefinition of a textures.
12750 if (texture
->IsDefined()) {
12751 LOCAL_SET_GL_ERROR(
12752 GL_INVALID_OPERATION
,
12753 "glAsyncTexImage2DCHROMIUM", "already defined");
12754 return error::kNoError
;
12757 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
12758 LOCAL_SET_GL_ERROR(
12759 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
12760 return error::kNoError
;
12763 // Setup the parameters.
12764 AsyncTexImage2DParams tex_params
= {
12765 target
, level
, static_cast<GLenum
>(internal_format
),
12766 width
, height
, border
, format
, type
};
12767 AsyncMemoryParams
mem_params(
12768 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
12770 // Set up the async state if needed, and make the texture
12771 // immutable so the async state stays valid. The level info
12772 // is set up lazily when the transfer completes.
12773 AsyncPixelTransferDelegate
* delegate
=
12774 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
12776 texture
->SetImmutable(true);
12778 delegate
->AsyncTexImage2D(
12781 base::Bind(&TextureManager::SetLevelInfoFromParams
,
12782 // The callback is only invoked if the transfer delegate still
12783 // exists, which implies through manager->texture_ref->state
12784 // ownership that both of these pointers are valid.
12785 base::Unretained(texture_manager()),
12786 base::Unretained(texture_ref
),
12788 return error::kNoError
;
12791 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12792 uint32 immediate_data_size
,
12793 const void* cmd_data
) {
12794 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
12795 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
12796 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12797 GLenum target
= static_cast<GLenum
>(c
.target
);
12798 GLint level
= static_cast<GLint
>(c
.level
);
12799 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
12800 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
12801 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12802 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12803 GLenum format
= static_cast<GLenum
>(c
.format
);
12804 GLenum type
= static_cast<GLenum
>(c
.type
);
12805 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12806 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12807 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12809 base::ScopedClosureRunner scoped_completion_callback
;
12810 if (async_upload_token
) {
12811 base::Closure completion_closure
=
12812 AsyncUploadTokenCompletionClosure(async_upload_token
,
12814 sync_data_shm_offset
);
12815 if (completion_closure
.is_null())
12816 return error::kInvalidArguments
;
12818 scoped_completion_callback
.Reset(completion_closure
);
12821 // TODO(epenner): Move this and copies of this memory validation
12822 // into ValidateTexSubImage2D step.
12824 if (!GLES2Util::ComputeImageDataSizes(
12825 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
12827 return error::kOutOfBounds
;
12829 const void* pixels
= GetSharedMemoryAs
<const void*>(
12830 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
12832 // All the normal glTexSubImage2D validation.
12833 error::Error error
= error::kNoError
;
12834 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
12835 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
12839 // Extra async validation.
12840 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12842 Texture
* texture
= texture_ref
->texture();
12843 if (!ValidateAsyncTransfer(
12844 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12845 return error::kNoError
;
12847 // Guarantee async textures are always 'cleared' as follows:
12848 // - AsyncTexImage2D can not redefine an existing texture
12849 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12850 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12851 // - Textures become immutable after an async call.
12852 // This way we know in all cases that an async texture is always clear.
12853 if (!texture
->SafeToRenderFrom()) {
12854 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
12856 LOCAL_SET_GL_ERROR(
12858 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12859 return error::kNoError
;
12863 // Setup the parameters.
12864 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
12865 width
, height
, format
, type
};
12866 AsyncMemoryParams
mem_params(
12867 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
12868 AsyncPixelTransferDelegate
* delegate
=
12869 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12871 // TODO(epenner): We may want to enforce exclusive use
12872 // of async APIs in which case this should become an error,
12873 // (the texture should have been async defined).
12874 AsyncTexImage2DParams define_params
= {target
, level
,
12876 texture
->GetLevelSize(
12877 target
, level
, &define_params
.width
, &define_params
.height
, nullptr);
12878 texture
->GetLevelType(
12879 target
, level
, &define_params
.type
, &define_params
.internal_format
);
12880 // Set up the async state if needed, and make the texture
12881 // immutable so the async state stays valid.
12882 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
12883 texture_ref
, define_params
);
12884 texture
->SetImmutable(true);
12887 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
12888 return error::kNoError
;
12891 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12892 uint32 immediate_data_size
,
12893 const void* cmd_data
) {
12894 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
12895 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
12896 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12897 GLenum target
= static_cast<GLenum
>(c
.target
);
12899 if (GL_TEXTURE_2D
!= target
) {
12900 LOCAL_SET_GL_ERROR(
12901 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
12902 return error::kNoError
;
12904 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12906 if (!texture_ref
) {
12907 LOCAL_SET_GL_ERROR(
12908 GL_INVALID_OPERATION
,
12909 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12910 return error::kNoError
;
12912 AsyncPixelTransferDelegate
* delegate
=
12913 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12915 LOCAL_SET_GL_ERROR(
12916 GL_INVALID_OPERATION
,
12917 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12918 return error::kNoError
;
12920 delegate
->WaitForTransferCompletion();
12921 ProcessFinishedAsyncTransfers();
12922 return error::kNoError
;
12925 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12926 uint32 immediate_data_size
,
12927 const void* data
) {
12928 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12930 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12931 ProcessFinishedAsyncTransfers();
12932 return error::kNoError
;
12935 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
12936 uint32_t immediate_data_size
, const void* cmd_data
) {
12937 if (!unsafe_es3_apis_enabled())
12938 return error::kUnknownCommand
;
12939 const gles2::cmds::UniformBlockBinding
& c
=
12940 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
12941 GLuint client_id
= c
.program
;
12942 GLuint index
= static_cast<GLuint
>(c
.index
);
12943 GLuint binding
= static_cast<GLuint
>(c
.binding
);
12944 Program
* program
= GetProgramInfoNotShader(
12945 client_id
, "glUniformBlockBinding");
12947 return error::kNoError
;
12949 GLuint service_id
= program
->service_id();
12950 glUniformBlockBinding(service_id
, index
, binding
);
12951 return error::kNoError
;
12954 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
12955 uint32_t immediate_data_size
, const void* cmd_data
) {
12956 if (!unsafe_es3_apis_enabled())
12957 return error::kUnknownCommand
;
12958 const gles2::cmds::ClientWaitSync
& c
=
12959 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
12960 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12961 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12962 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12963 typedef cmds::ClientWaitSync::Result Result
;
12964 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
12965 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
12967 return error::kOutOfBounds
;
12969 if (*result_dst
!= GL_WAIT_FAILED
) {
12970 return error::kInvalidArguments
;
12972 GLsync service_sync
= 0;
12973 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12974 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
12975 return error::kNoError
;
12977 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
12978 return error::kNoError
;
12981 error::Error
GLES2DecoderImpl::HandleWaitSync(
12982 uint32_t immediate_data_size
, const void* cmd_data
) {
12983 if (!unsafe_es3_apis_enabled())
12984 return error::kUnknownCommand
;
12985 const gles2::cmds::WaitSync
& c
=
12986 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
12987 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12988 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12989 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12990 GLsync service_sync
= 0;
12991 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12992 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
12993 return error::kNoError
;
12995 glWaitSync(service_sync
, flags
, timeout
);
12996 return error::kNoError
;
12999 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
13000 uint32_t immediate_data_size
, const void* cmd_data
) {
13001 if (!unsafe_es3_apis_enabled()) {
13002 return error::kUnknownCommand
;
13004 const gles2::cmds::MapBufferRange
& c
=
13005 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
13006 GLenum target
= static_cast<GLenum
>(c
.target
);
13007 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
13008 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
13009 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
13011 typedef cmds::MapBufferRange::Result Result
;
13012 Result
* result
= GetSharedMemoryAs
<Result
*>(
13013 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
13015 return error::kOutOfBounds
;
13017 if (*result
!= 0) {
13019 return error::kInvalidArguments
;
13022 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
13024 return error::kOutOfBounds
;
13027 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
13028 if ((access
& mask
) == mask
) {
13029 // TODO(zmo): To be on the safe side, always map
13030 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
13031 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
13032 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
13034 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
13035 // undefined behaviors.
13036 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
13037 if ((access
& mask
) == mask
) {
13038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
13039 "incompatible access bits");
13040 return error::kNoError
;
13042 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
13043 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
13044 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13045 access
= (access
| GL_MAP_READ_BIT
);
13047 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
13048 if (ptr
== nullptr) {
13049 return error::kNoError
;
13051 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13053 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
13054 GetSharedMemoryBuffer(c
.data_shm_id
));
13055 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
13056 memcpy(mem
, ptr
, size
);
13059 return error::kNoError
;
13062 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
13063 uint32_t immediate_data_size
, const void* cmd_data
) {
13064 if (!unsafe_es3_apis_enabled()) {
13065 return error::kUnknownCommand
;
13067 const gles2::cmds::UnmapBuffer
& c
=
13068 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
13069 GLenum target
= static_cast<GLenum
>(c
.target
);
13071 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
13073 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
13074 return error::kNoError
;
13076 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
13077 if (!mapped_range
) {
13078 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
13079 "buffer is unmapped");
13080 return error::kNoError
;
13082 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
13083 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
13084 GL_MAP_FLUSH_EXPLICIT_BIT
) {
13085 // If we don't need to write back, or explict flush is required, no copying
13088 void* mem
= mapped_range
->GetShmPointer();
13090 return error::kOutOfBounds
;
13092 DCHECK(mapped_range
->pointer
);
13093 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
13095 buffer
->RemoveMappedRange();
13096 GLboolean rt
= glUnmapBuffer(target
);
13097 if (rt
== GL_FALSE
) {
13098 // At this point, we have already done the necessary validation, so
13099 // GL_FALSE indicates data corruption.
13100 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
13101 // the second unmap could still return GL_FALSE. For now, we simply lose
13102 // the contexts in the share group.
13103 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
13104 // Need to lose current context before broadcasting!
13105 MarkContextLost(error::kGuilty
);
13106 group_
->LoseContexts(error::kInnocent
);
13107 return error::kLostContext
;
13109 return error::kNoError
;
13112 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
13113 TextureRef
* texture_ref
) {
13114 Texture
* texture
= texture_ref
->texture();
13115 DoDidUseTexImageIfNeeded(texture
, texture
->target());
13118 // Note that GL_LOST_CONTEXT is specific to GLES.
13119 // For desktop GL we have to query the reset status proactively.
13120 void GLES2DecoderImpl::OnContextLostError() {
13121 if (!WasContextLost()) {
13122 // Need to lose current context before broadcasting!
13123 CheckResetStatus();
13124 group_
->LoseContexts(error::kUnknown
);
13125 reset_by_robustness_extension_
= true;
13129 void GLES2DecoderImpl::OnOutOfMemoryError() {
13130 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
13131 error::ContextLostReason other
= error::kOutOfMemory
;
13132 if (CheckResetStatus()) {
13133 other
= error::kUnknown
;
13135 // Need to lose current context before broadcasting!
13136 MarkContextLost(error::kOutOfMemory
);
13138 group_
->LoseContexts(other
);
13142 // Include the auto-generated part of this file. We split this because it means
13143 // we can easily edit the non-auto generated parts right here in this file
13144 // instead of having to edit some template or the code generator.
13145 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
13147 } // namespace gles2