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"
17 #include "base/at_exit.h"
18 #include "base/bind.h"
19 #include "base/callback_helpers.h"
20 #include "base/command_line.h"
21 #include "base/float_util.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 // TODO(gman): Cache these pointers?
764 BufferManager
* buffer_manager() {
765 return group_
->buffer_manager();
768 RenderbufferManager
* renderbuffer_manager() {
769 return group_
->renderbuffer_manager();
772 FramebufferManager
* framebuffer_manager() {
773 return group_
->framebuffer_manager();
776 ValuebufferManager
* valuebuffer_manager() {
777 return group_
->valuebuffer_manager();
780 ProgramManager
* program_manager() {
781 return group_
->program_manager();
784 ShaderManager
* shader_manager() {
785 return group_
->shader_manager();
788 ShaderTranslatorCache
* shader_translator_cache() {
789 return group_
->shader_translator_cache();
792 const TextureManager
* texture_manager() const {
793 return group_
->texture_manager();
796 TextureManager
* texture_manager() {
797 return group_
->texture_manager();
800 MailboxManager
* mailbox_manager() {
801 return group_
->mailbox_manager();
804 ImageManager
* image_manager() { return image_manager_
.get(); }
806 VertexArrayManager
* vertex_array_manager() {
807 return vertex_array_manager_
.get();
810 MemoryTracker
* memory_tracker() {
811 return group_
->memory_tracker();
814 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
815 MemoryTracker
* tracker
= memory_tracker();
817 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
822 bool IsOffscreenBufferMultisampled() const {
823 return offscreen_target_samples_
> 1;
826 // Creates a Texture for the given texture.
827 TextureRef
* CreateTexture(
828 GLuint client_id
, GLuint service_id
) {
829 return texture_manager()->CreateTexture(client_id
, service_id
);
832 // Gets the texture info for the given texture. Returns NULL if none exists.
833 TextureRef
* GetTexture(GLuint client_id
) const {
834 return texture_manager()->GetTexture(client_id
);
837 // Deletes the texture info for the given texture.
838 void RemoveTexture(GLuint client_id
) {
839 texture_manager()->RemoveTexture(client_id
);
842 // Get the size (in pixels) of the currently bound frame buffer (either FBO
843 // or regular back buffer).
844 gfx::Size
GetBoundReadFrameBufferSize();
846 // Get the format of the currently bound frame buffer (either FBO or regular
848 GLenum
GetBoundReadFrameBufferTextureType();
849 GLenum
GetBoundReadFrameBufferInternalFormat();
850 GLenum
GetBoundDrawFrameBufferInternalFormat();
852 // Wrapper for CompressedTexImage2D commands.
853 error::Error
DoCompressedTexImage2D(
856 GLenum internal_format
,
863 // Wrapper for CompressedTexSubImage2D.
864 void DoCompressedTexSubImage2D(
875 // Wrapper for CopyTexImage2D.
876 void DoCopyTexImage2D(
879 GLenum internal_format
,
886 // Wrapper for SwapBuffers.
887 void DoSwapBuffers();
889 // Wrapper for SwapInterval.
890 void DoSwapInterval(int interval
);
892 // Wrapper for CopyTexSubImage2D.
893 void DoCopyTexSubImage2D(
903 // Validation for TexSubImage2D.
904 bool ValidateTexSubImage2D(
906 const char* function_name
,
917 // Wrapper for TexSubImage2D.
918 error::Error
DoTexSubImage2D(
929 // Extra validation for async tex(Sub)Image2D.
930 bool ValidateAsyncTransfer(
931 const char* function_name
,
932 TextureRef
* texture_ref
,
937 // Wrapper for TexImageIOSurface2DCHROMIUM.
938 void DoTexImageIOSurface2DCHROMIUM(
942 GLuint io_surface_id
,
945 void DoCopyTextureCHROMIUM(GLenum target
,
948 GLenum internal_format
,
951 void DoCopySubTextureCHROMIUM(GLenum target
,
957 // Wrapper for TexStorage2DEXT.
958 void DoTexStorage2DEXT(
961 GLenum internal_format
,
965 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
966 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
968 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
969 GLenum target
, const GLbyte
* data
);
971 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
972 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
973 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
976 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
977 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
978 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
979 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
980 void DoUniformValueBufferCHROMIUM(GLint location
,
982 GLenum subscription
);
984 void DoBindTexImage2DCHROMIUM(
987 void DoReleaseTexImage2DCHROMIUM(
991 void DoTraceEndCHROMIUM(void);
993 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
995 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
997 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
998 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1000 // Creates a Program for the given program.
1001 Program
* CreateProgram(
1002 GLuint client_id
, GLuint service_id
) {
1003 return program_manager()->CreateProgram(client_id
, service_id
);
1006 // Gets the program info for the given program. Returns NULL if none exists.
1007 Program
* GetProgram(GLuint client_id
) {
1008 return program_manager()->GetProgram(client_id
);
1012 void LogClientServiceMapping(
1013 const char* /* function_name */,
1014 GLuint
/* client_id */,
1015 GLuint
/* service_id */) {
1017 template<typename T
>
1018 void LogClientServiceForInfo(
1019 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1022 void LogClientServiceMapping(
1023 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1024 if (service_logging_
) {
1025 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1026 << ": client_id = " << client_id
1027 << ", service_id = " << service_id
;
1030 template<typename T
>
1031 void LogClientServiceForInfo(
1032 T
* info
, GLuint client_id
, const char* function_name
) {
1034 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1039 // Gets the program info for the given program. If it's not a program
1040 // generates a GL error. Returns NULL if not program.
1041 Program
* GetProgramInfoNotShader(
1042 GLuint client_id
, const char* function_name
) {
1043 Program
* program
= GetProgram(client_id
);
1045 if (GetShader(client_id
)) {
1047 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1049 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1052 LogClientServiceForInfo(program
, client_id
, function_name
);
1057 // Creates a Shader for the given shader.
1058 Shader
* CreateShader(
1061 GLenum shader_type
) {
1062 return shader_manager()->CreateShader(
1063 client_id
, service_id
, shader_type
);
1066 // Gets the shader info for the given shader. Returns NULL if none exists.
1067 Shader
* GetShader(GLuint client_id
) {
1068 return shader_manager()->GetShader(client_id
);
1071 // Gets the shader info for the given shader. If it's not a shader generates a
1072 // GL error. Returns NULL if not shader.
1073 Shader
* GetShaderInfoNotProgram(
1074 GLuint client_id
, const char* function_name
) {
1075 Shader
* shader
= GetShader(client_id
);
1077 if (GetProgram(client_id
)) {
1079 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1082 GL_INVALID_VALUE
, function_name
, "unknown shader");
1085 LogClientServiceForInfo(shader
, client_id
, function_name
);
1089 // Creates a buffer info for the given buffer.
1090 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1091 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1094 // Gets the buffer info for the given buffer.
1095 Buffer
* GetBuffer(GLuint client_id
) {
1096 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1100 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1101 // on glDeleteBuffers so we can make sure the user does not try to render
1102 // with deleted buffers.
1103 void RemoveBuffer(GLuint client_id
);
1105 // Creates a framebuffer info for the given framebuffer.
1106 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1107 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1110 // Gets the framebuffer info for the given framebuffer.
1111 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1112 return framebuffer_manager()->GetFramebuffer(client_id
);
1115 // Removes the framebuffer info for the given framebuffer.
1116 void RemoveFramebuffer(GLuint client_id
) {
1117 framebuffer_manager()->RemoveFramebuffer(client_id
);
1120 // Creates a renderbuffer info for the given renderbuffer.
1121 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1122 return renderbuffer_manager()->CreateRenderbuffer(
1123 client_id
, service_id
);
1126 // Gets the renderbuffer info for the given renderbuffer.
1127 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1128 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1131 // Removes the renderbuffer info for the given renderbuffer.
1132 void RemoveRenderbuffer(GLuint client_id
) {
1133 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1136 // Creates a valuebuffer info for the given valuebuffer.
1137 void CreateValuebuffer(GLuint client_id
) {
1138 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1141 // Gets the valuebuffer info for a given valuebuffer.
1142 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1143 return valuebuffer_manager()->GetValuebuffer(client_id
);
1146 // Removes the valuebuffer info for the given valuebuffer.
1147 void RemoveValuebuffer(GLuint client_id
) {
1148 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1151 // Gets the vertex attrib manager for the given vertex array.
1152 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1153 VertexAttribManager
* info
=
1154 vertex_array_manager()->GetVertexAttribManager(client_id
);
1158 // Removes the vertex attrib manager for the given vertex array.
1159 void RemoveVertexAttribManager(GLuint client_id
) {
1160 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1163 // Creates a vertex attrib manager for the given vertex array.
1164 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1167 bool client_visible
) {
1168 return vertex_array_manager()->CreateVertexAttribManager(
1169 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1172 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1173 void DoBindUniformLocationCHROMIUM(
1174 GLuint client_id
, GLint location
, const char* name
);
1176 error::Error
GetAttribLocationHelper(
1177 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1178 const std::string
& name_str
);
1180 error::Error
GetUniformLocationHelper(
1181 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1182 const std::string
& name_str
);
1184 error::Error
GetFragDataLocationHelper(
1185 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1186 const std::string
& name_str
);
1188 // Wrapper for glShaderSource.
1189 void DoShaderSource(
1190 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1192 // Wrapper for glTransformFeedbackVaryings.
1193 void DoTransformFeedbackVaryings(
1194 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1195 GLenum buffer_mode
);
1197 // Clear any textures used by the current program.
1198 bool ClearUnclearedTextures();
1200 // Clears any uncleared attachments attached to the given frame buffer.
1201 // Returns false if there was a generated GL error.
1202 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1204 // overridden from GLES2Decoder
1205 bool ClearLevel(Texture
* texture
,
1208 unsigned internal_format
,
1213 bool is_texture_immutable
) override
;
1215 // Restore all GL state that affects clearing.
1216 void RestoreClearState();
1218 // Remembers the state of some capabilities.
1219 // Returns: true if glEnable/glDisable should actually be called.
1220 bool SetCapabilityState(GLenum cap
, bool enabled
);
1222 // Check that the currently bound framebuffers are valid.
1223 // Generates GL error if not.
1224 bool CheckBoundFramebuffersValid(const char* func_name
);
1226 // Check that the currently bound read framebuffer has a color image
1227 // attached. Generates GL error if not.
1228 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1230 // Check that the currently bound read framebuffer's color image
1231 // isn't the target texture of the glCopyTex{Sub}Image2D.
1232 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1234 // Check if a framebuffer meets our requirements.
1235 bool CheckFramebufferValid(
1236 Framebuffer
* framebuffer
,
1238 const char* func_name
);
1240 // Check if the current valuebuffer exists and is valid. If not generates
1241 // the appropriate GL error. Returns true if the current valuebuffer is in
1243 bool CheckCurrentValuebuffer(const char* function_name
);
1245 // Check if the current valuebuffer exists and is valiud and that the
1246 // value buffer is actually subscribed to the given subscription
1247 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1248 const char* function_name
);
1250 // Check if the location can be used for the given subscription target. If not
1251 // generates the appropriate GL error. Returns true if the location is usable
1252 bool CheckSubscriptionTarget(GLint location
,
1253 GLenum subscription
,
1254 const char* function_name
);
1256 // Checks if the current program exists and is valid. If not generates the
1257 // appropriate GL error. Returns true if the current program is in a usable
1259 bool CheckCurrentProgram(const char* function_name
);
1261 // Checks if the current program exists and is valid and that location is not
1262 // -1. If the current program is not valid generates the appropriate GL
1263 // error. Returns true if the current program is in a usable state and
1264 // location is not -1.
1265 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1267 // Checks if the current program samples a texture that is also the color
1268 // image of the current bound framebuffer, i.e., the source and destination
1269 // of the draw operation are the same.
1270 bool CheckDrawingFeedbackLoops();
1272 // Checks if |api_type| is valid for the given uniform
1273 // If the api type is not valid generates the appropriate GL
1274 // error. Returns true if |api_type| is valid for the uniform
1275 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1276 const char* function_name
,
1277 Program::UniformApiType api_type
);
1279 // Gets the type of a uniform for a location in the current program. Sets GL
1280 // errors if the current program is not valid. Returns true if the current
1281 // program is valid and the location exists. Adjusts count so it
1282 // does not overflow the uniform.
1283 bool PrepForSetUniformByLocation(GLint fake_location
,
1284 const char* function_name
,
1285 Program::UniformApiType api_type
,
1286 GLint
* real_location
,
1290 // Gets the service id for any simulated backbuffer fbo.
1291 GLuint
GetBackbufferServiceId() const;
1293 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1294 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1296 // Helper for glGetVertexAttrib
1297 void GetVertexAttribHelper(
1298 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1300 // Wrapper for glActiveTexture
1301 void DoActiveTexture(GLenum texture_unit
);
1303 // Wrapper for glAttachShader
1304 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1306 // Wrapper for glBindBuffer since we need to track the current targets.
1307 void DoBindBuffer(GLenum target
, GLuint buffer
);
1309 // Wrapper for glBindFramebuffer since we need to track the current targets.
1310 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1312 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1313 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1315 // Wrapper for glBindTexture since we need to track the current targets.
1316 void DoBindTexture(GLenum target
, GLuint texture
);
1318 // Wrapper for glBindVertexArrayOES
1319 void DoBindVertexArrayOES(GLuint array
);
1320 void EmulateVertexArrayState();
1322 // Wrapper for glBlitFramebufferCHROMIUM.
1323 void DoBlitFramebufferCHROMIUM(
1324 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1325 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1326 GLbitfield mask
, GLenum filter
);
1328 // Wrapper for glBufferSubData.
1329 void DoBufferSubData(
1330 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1332 // Wrapper for glCheckFramebufferStatus
1333 GLenum
DoCheckFramebufferStatus(GLenum target
);
1335 // Wrapper for glClear
1336 error::Error
DoClear(GLbitfield mask
);
1338 // Wrappers for various state.
1339 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1340 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1342 // Wrapper for glCompileShader.
1343 void DoCompileShader(GLuint shader
);
1345 // Wrapper for glDetachShader
1346 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1348 // Wrapper for glDisable
1349 void DoDisable(GLenum cap
);
1351 // Wrapper for glDisableVertexAttribArray.
1352 void DoDisableVertexAttribArray(GLuint index
);
1354 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1356 void DoDiscardFramebufferEXT(GLenum target
,
1357 GLsizei numAttachments
,
1358 const GLenum
* attachments
);
1360 // Wrapper for glEnable
1361 void DoEnable(GLenum cap
);
1363 // Wrapper for glEnableVertexAttribArray.
1364 void DoEnableVertexAttribArray(GLuint index
);
1366 // Wrapper for glFinish.
1369 // Wrapper for glFlush.
1372 // Wrapper for glFramebufferRenderbufffer.
1373 void DoFramebufferRenderbuffer(
1374 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1375 GLuint renderbuffer
);
1377 // Wrapper for glFramebufferTexture2D.
1378 void DoFramebufferTexture2D(
1379 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1382 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1383 void DoFramebufferTexture2DMultisample(
1384 GLenum target
, GLenum attachment
, GLenum textarget
,
1385 GLuint texture
, GLint level
, GLsizei samples
);
1387 // Common implementation for both DoFramebufferTexture2D wrappers.
1388 void DoFramebufferTexture2DCommon(const char* name
,
1389 GLenum target
, GLenum attachment
, GLenum textarget
,
1390 GLuint texture
, GLint level
, GLsizei samples
);
1392 // Wrapper for glFramebufferTextureLayer.
1393 void DoFramebufferTextureLayer(
1394 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1397 // Wrapper for glGenerateMipmap
1398 void DoGenerateMipmap(GLenum target
);
1400 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1401 // to account for different pname values defined in different extension
1403 GLenum
AdjustGetPname(GLenum pname
);
1405 // Wrapper for DoGetBooleanv.
1406 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1408 // Wrapper for DoGetFloatv.
1409 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1411 // Wrapper for glGetFramebufferAttachmentParameteriv.
1412 void DoGetFramebufferAttachmentParameteriv(
1413 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1415 // Wrapper for glGetIntegerv.
1416 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1418 // Gets the max value in a range in a buffer.
1419 GLuint
DoGetMaxValueInBufferCHROMIUM(
1420 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1422 // Wrapper for glGetBufferParameteriv.
1423 void DoGetBufferParameteriv(
1424 GLenum target
, GLenum pname
, GLint
* params
);
1426 // Wrapper for glGetProgramiv.
1427 void DoGetProgramiv(
1428 GLuint program_id
, GLenum pname
, GLint
* params
);
1430 // Wrapper for glRenderbufferParameteriv.
1431 void DoGetRenderbufferParameteriv(
1432 GLenum target
, GLenum pname
, GLint
* params
);
1434 // Wrapper for glGetShaderiv
1435 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1437 // Wrappers for glGetTexParameter.
1438 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1439 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1440 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1442 // Wrappers for glGetVertexAttrib.
1443 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
*params
);
1444 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
*params
);
1446 // Wrappers for glIsXXX functions.
1447 bool DoIsEnabled(GLenum cap
);
1448 bool DoIsBuffer(GLuint client_id
);
1449 bool DoIsFramebuffer(GLuint client_id
);
1450 bool DoIsProgram(GLuint client_id
);
1451 bool DoIsRenderbuffer(GLuint client_id
);
1452 bool DoIsShader(GLuint client_id
);
1453 bool DoIsTexture(GLuint client_id
);
1454 bool DoIsVertexArrayOES(GLuint client_id
);
1456 // Wrapper for glLinkProgram
1457 void DoLinkProgram(GLuint program
);
1459 // Wrapper for glRenderbufferStorage.
1460 void DoRenderbufferStorage(
1461 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1463 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1464 void DoRenderbufferStorageMultisampleCHROMIUM(
1465 GLenum target
, GLsizei samples
, GLenum internalformat
,
1466 GLsizei width
, GLsizei height
);
1468 // Handler for glRenderbufferStorageMultisampleEXT
1469 // (multisampled_render_to_texture).
1470 void DoRenderbufferStorageMultisampleEXT(
1471 GLenum target
, GLsizei samples
, GLenum internalformat
,
1472 GLsizei width
, GLsizei height
);
1474 // Common validation for multisample extensions.
1475 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1476 GLenum internalformat
,
1480 // Verifies that the currently bound multisample renderbuffer is valid
1481 // Very slow! Only done on platforms with driver bugs that return invalid
1482 // buffers under memory pressure
1483 bool VerifyMultisampleRenderbufferIntegrity(
1484 GLuint renderbuffer
, GLenum format
);
1486 // Wrapper for glReleaseShaderCompiler.
1487 void DoReleaseShaderCompiler() { }
1489 // Wrappers for glSamplerParameter*v functions.
1490 void DoSamplerParameterfv(
1491 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1492 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1494 // Wrappers for glTexParameter functions.
1495 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1496 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1497 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1498 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1500 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1501 // spec only these 2 functions can be used to set sampler uniforms.
1502 void DoUniform1i(GLint fake_location
, GLint v0
);
1503 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1504 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1505 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1506 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1508 // Wrappers for glUniformfv because some drivers don't correctly accept
1510 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1511 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1512 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1513 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1515 void DoUniformMatrix2fv(
1516 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1517 const GLfloat
* value
);
1518 void DoUniformMatrix3fv(
1519 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1520 const GLfloat
* value
);
1521 void DoUniformMatrix4fv(
1522 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1523 const GLfloat
* value
);
1525 bool SetVertexAttribValue(
1526 const char* function_name
, GLuint index
, const GLfloat
* value
);
1528 // Wrappers for glVertexAttrib??
1529 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1530 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1531 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1532 void DoVertexAttrib4f(
1533 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1534 void DoVertexAttrib1fv(GLuint index
, const GLfloat
*v
);
1535 void DoVertexAttrib2fv(GLuint index
, const GLfloat
*v
);
1536 void DoVertexAttrib3fv(GLuint index
, const GLfloat
*v
);
1537 void DoVertexAttrib4fv(GLuint index
, const GLfloat
*v
);
1539 // Wrapper for glViewport
1540 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1542 // Wrapper for glUseProgram
1543 void DoUseProgram(GLuint program
);
1545 // Wrapper for glValidateProgram.
1546 void DoValidateProgram(GLuint program_client_id
);
1548 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1549 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1550 void DoPopGroupMarkerEXT(void);
1552 // Gets the number of values that will be returned by glGetXXX. Returns
1553 // false if pname is unknown.
1554 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1556 // Checks if the current program and vertex attributes are valid for drawing.
1558 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1561 // Returns true if successful, simulated will be true if attrib0 was
1563 bool SimulateAttrib0(
1564 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1565 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1567 // If an image is bound to texture, this will call Will/DidUseTexImage
1569 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1570 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1572 // Returns false if textures were replaced.
1573 bool PrepareTexturesForRender();
1574 void RestoreStateForTextures();
1576 // Returns true if GL_FIXED attribs were simulated.
1577 bool SimulateFixedAttribs(
1578 const char* function_name
,
1579 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1580 void RestoreStateForSimulatedFixedAttribs();
1582 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1583 // cases (primcount is always 1 for non-instanced).
1584 error::Error
DoDrawArrays(
1585 const char* function_name
,
1586 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1588 error::Error
DoDrawElements(
1589 const char* function_name
,
1590 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1591 int32 offset
, GLsizei primcount
);
1593 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1594 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1595 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1598 return GL_TEXTURE_2D
;
1599 case GL_SAMPLER_CUBE
:
1600 return GL_TEXTURE_CUBE_MAP
;
1601 case GL_SAMPLER_EXTERNAL_OES
:
1602 return GL_TEXTURE_EXTERNAL_OES
;
1603 case GL_SAMPLER_2D_RECT_ARB
:
1604 return GL_TEXTURE_RECTANGLE_ARB
;
1611 // Gets the framebuffer info for a particular target.
1612 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1613 Framebuffer
* framebuffer
= NULL
;
1615 case GL_FRAMEBUFFER
:
1616 case GL_DRAW_FRAMEBUFFER_EXT
:
1617 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1619 case GL_READ_FRAMEBUFFER_EXT
:
1620 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1629 Renderbuffer
* GetRenderbufferInfoForTarget(
1631 Renderbuffer
* renderbuffer
= NULL
;
1633 case GL_RENDERBUFFER
:
1634 renderbuffer
= state_
.bound_renderbuffer
.get();
1640 return renderbuffer
;
1643 // Validates the program and location for a glGetUniform call and returns
1644 // a SizeResult setup to receive the result. Returns true if glGetUniform
1645 // should be called.
1646 bool GetUniformSetup(GLuint program
,
1647 GLint fake_location
,
1650 error::Error
* error
,
1651 GLint
* real_location
,
1654 GLenum
* result_type
,
1655 GLsizei
* result_size
);
1657 void MaybeExitOnContextLost();
1658 bool WasContextLost() override
;
1659 bool WasContextLostByRobustnessExtension() override
;
1660 void LoseContext(uint32 reset_status
) override
;
1662 #if defined(OS_MACOSX)
1663 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1666 bool ValidateCompressedTexDimensions(
1667 const char* function_name
,
1668 GLint level
, GLsizei width
, GLsizei height
, GLenum format
);
1669 bool ValidateCompressedTexFuncData(
1670 const char* function_name
,
1671 GLsizei width
, GLsizei height
, GLenum format
, size_t size
);
1672 bool ValidateCompressedTexSubDimensions(
1673 const char* function_name
,
1674 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
1675 GLsizei width
, GLsizei height
, GLenum format
,
1677 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1679 TextureRef
* source_texture_ref
,
1680 TextureRef
* dest_texture_ref
,
1681 GLenum dest_internal_format
);
1683 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1684 void PerformanceWarning(
1685 const char* filename
, int line
, const std::string
& msg
);
1687 const FeatureInfo::FeatureFlags
& features() const {
1688 return feature_info_
->feature_flags();
1691 const FeatureInfo::Workarounds
& workarounds() const {
1692 return feature_info_
->workarounds();
1695 bool ShouldDeferDraws() {
1696 return !offscreen_target_frame_buffer_
.get() &&
1697 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1698 surface_
->DeferDraws();
1701 bool ShouldDeferReads() {
1702 return !offscreen_target_frame_buffer_
.get() &&
1703 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1704 surface_
->DeferDraws();
1707 bool IsRobustnessSupported() {
1708 return has_robustness_extension_
&&
1709 context_
->WasAllocatedUsingRobustnessExtension();
1712 error::Error
WillAccessBoundFramebufferForDraw() {
1713 if (ShouldDeferDraws())
1714 return error::kDeferCommandUntilLater
;
1715 if (!offscreen_target_frame_buffer_
.get() &&
1716 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1717 !surface_
->SetBackbufferAllocation(true))
1718 return error::kLostContext
;
1719 return error::kNoError
;
1722 error::Error
WillAccessBoundFramebufferForRead() {
1723 if (ShouldDeferReads())
1724 return error::kDeferCommandUntilLater
;
1725 if (!offscreen_target_frame_buffer_
.get() &&
1726 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1727 !surface_
->SetBackbufferAllocation(true))
1728 return error::kLostContext
;
1729 return error::kNoError
;
1732 // Set remaining commands to process to 0 to force DoCommands to return
1733 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1734 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1736 void ProcessPendingReadPixels();
1737 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1739 // Generate a member function prototype for each command in an automated and
1741 #define GLES2_CMD_OP(name) \
1742 Error Handle##name(uint32 immediate_data_size, const void* data);
1744 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1748 // The GL context this decoder renders to on behalf of the client.
1749 scoped_refptr
<gfx::GLSurface
> surface_
;
1750 scoped_refptr
<gfx::GLContext
> context_
;
1752 // The ContextGroup for this decoder uses to track resources.
1753 scoped_refptr
<ContextGroup
> group_
;
1755 DebugMarkerManager debug_marker_manager_
;
1758 // All the state for this context.
1759 ContextState state_
;
1761 // Current width and height of the offscreen frame buffer.
1762 gfx::Size offscreen_size_
;
1764 // Util to help with GL.
1767 // unpack flip y as last set by glPixelStorei
1768 bool unpack_flip_y_
;
1770 // unpack (un)premultiply alpha as last set by glPixelStorei
1771 bool unpack_premultiply_alpha_
;
1772 bool unpack_unpremultiply_alpha_
;
1774 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1775 GLuint attrib_0_buffer_id_
;
1777 // The value currently in attrib_0.
1778 Vec4 attrib_0_value_
;
1780 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1781 bool attrib_0_buffer_matches_value_
;
1783 // The size of attrib 0.
1784 GLsizei attrib_0_size_
;
1786 // The buffer used to simulate GL_FIXED attribs.
1787 GLuint fixed_attrib_buffer_id_
;
1789 // The size of fiixed attrib buffer.
1790 GLsizei fixed_attrib_buffer_size_
;
1792 // The offscreen frame buffer that the client renders to. With EGL, the
1793 // depth and stencil buffers are separate. With regular GL there is a single
1794 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1795 // offscreen_target_stencil_render_buffer_ is unused.
1796 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1797 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1798 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1799 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1800 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1801 GLenum offscreen_target_color_format_
;
1802 GLenum offscreen_target_depth_format_
;
1803 GLenum offscreen_target_stencil_format_
;
1804 GLsizei offscreen_target_samples_
;
1805 GLboolean offscreen_target_buffer_preserved_
;
1807 // The copy that is saved when SwapBuffers is called.
1808 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1809 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1810 scoped_refptr
<TextureRef
>
1811 offscreen_saved_color_texture_info_
;
1813 // The copy that is used as the destination for multi-sample resolves.
1814 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1815 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1816 GLenum offscreen_saved_color_format_
;
1818 scoped_ptr
<QueryManager
> query_manager_
;
1820 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1822 scoped_ptr
<ImageManager
> image_manager_
;
1824 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1826 WaitSyncPointCallback wait_sync_point_callback_
;
1828 ShaderCacheCallback shader_cache_callback_
;
1830 scoped_ptr
<AsyncPixelTransferManager
> async_pixel_transfer_manager_
;
1832 // The format of the back buffer_
1833 GLenum back_buffer_color_format_
;
1834 bool back_buffer_has_depth_
;
1835 bool back_buffer_has_stencil_
;
1839 // Backbuffer attachments that are currently undefined.
1840 uint32 backbuffer_needs_clear_bits_
;
1842 // The current decoder error communicates the decoder error through command
1843 // processing functions that do not return the error value. Should be set only
1844 // if not returning an error.
1845 error::Error current_decoder_error_
;
1847 bool use_shader_translator_
;
1848 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
1849 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
1851 DisallowedFeatures disallowed_features_
;
1853 // Cached from ContextGroup
1854 const Validators
* validators_
;
1855 scoped_refptr
<FeatureInfo
> feature_info_
;
1859 // Number of commands remaining to be processed in DoCommands().
1860 int commands_to_process_
;
1862 bool has_robustness_extension_
;
1863 GLenum reset_status_
;
1864 bool reset_by_robustness_extension_
;
1865 bool supports_post_sub_buffer_
;
1867 // These flags are used to override the state of the shared feature_info_
1868 // member. Because the same FeatureInfo instance may be shared among many
1869 // contexts, the assumptions on the availablity of extensions in WebGL
1870 // contexts may be broken. These flags override the shared state to preserve
1872 bool force_webgl_glsl_validation_
;
1873 bool derivatives_explicitly_enabled_
;
1874 bool frag_depth_explicitly_enabled_
;
1875 bool draw_buffers_explicitly_enabled_
;
1876 bool shader_texture_lod_explicitly_enabled_
;
1878 bool compile_shader_always_succeeds_
;
1880 // An optional behaviour to lose the context and group when OOM.
1881 bool lose_context_when_out_of_memory_
;
1884 bool service_logging_
;
1886 #if defined(OS_MACOSX)
1887 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
1888 TextureToIOSurfaceMap texture_to_io_surface_map_
;
1891 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
1892 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
1894 // Cached values of the currently assigned viewport dimensions.
1895 GLsizei viewport_max_width_
;
1896 GLsizei viewport_max_height_
;
1898 // Command buffer stats.
1899 base::TimeDelta total_processing_commands_time_
;
1901 // States related to each manager.
1902 DecoderTextureState texture_state_
;
1903 DecoderFramebufferState framebuffer_state_
;
1905 scoped_ptr
<GPUTracer
> gpu_tracer_
;
1906 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
1907 const unsigned char* cb_command_trace_category_
;
1908 const unsigned char* gpu_decoder_category_
;
1909 int gpu_trace_level_
;
1910 bool gpu_trace_commands_
;
1911 bool gpu_debug_commands_
;
1913 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
1915 // Used to validate multisample renderbuffers if needed
1916 GLuint validation_texture_
;
1917 GLuint validation_fbo_multisample_
;
1918 GLuint validation_fbo_
;
1920 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
1921 uint32 immediate_data_size
,
1924 // A struct to hold info about each command.
1925 struct CommandInfo
{
1926 CmdHandler cmd_handler
;
1927 uint8 arg_flags
; // How to handle the arguments for this command
1928 uint8 cmd_flags
; // How to handle this command
1929 uint16 arg_count
; // How many arguments are expected for this command.
1932 // A table of CommandInfo for all the commands.
1933 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
1935 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
1938 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
1939 #define GLES2_CMD_OP(name) \
1941 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1942 cmds::name::cmd_flags, \
1943 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1946 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1950 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1951 const char* function_name
, ErrorState
* error_state
)
1952 : function_name_(function_name
),
1953 error_state_(error_state
) {
1954 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
1957 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1958 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
1961 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
1962 TextureUnit
& info
= state
->texture_units
[0];
1964 scoped_refptr
<TextureRef
> texture_ref
;
1967 texture_ref
= info
.bound_texture_2d
;
1969 case GL_TEXTURE_CUBE_MAP
:
1970 texture_ref
= info
.bound_texture_cube_map
;
1972 case GL_TEXTURE_EXTERNAL_OES
:
1973 texture_ref
= info
.bound_texture_external_oes
;
1975 case GL_TEXTURE_RECTANGLE_ARB
:
1976 texture_ref
= info
.bound_texture_rectangle_arb
;
1982 if (texture_ref
.get()) {
1983 last_id
= texture_ref
->service_id();
1988 glBindTexture(target
, last_id
);
1989 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
1992 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
1997 ScopedGLErrorSuppressor
suppressor(
1998 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2000 // TODO(apatrick): Check if there are any other states that need to be reset
2001 // before binding a new texture.
2002 glActiveTexture(GL_TEXTURE0
);
2003 glBindTexture(target
, id
);
2006 ScopedTextureBinder::~ScopedTextureBinder() {
2007 ScopedGLErrorSuppressor
suppressor(
2008 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2009 RestoreCurrentTextureBindings(state_
, target_
);
2012 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2015 ScopedGLErrorSuppressor
suppressor(
2016 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2017 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2020 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2021 ScopedGLErrorSuppressor
suppressor(
2022 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2023 state_
->RestoreRenderbufferBindings();
2026 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2028 : decoder_(decoder
) {
2029 ScopedGLErrorSuppressor
suppressor(
2030 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2031 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2032 decoder
->OnFboChanged();
2035 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2036 ScopedGLErrorSuppressor
suppressor(
2037 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2038 decoder_
->RestoreCurrentFramebufferBindings();
2041 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2042 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2043 : decoder_(decoder
) {
2044 resolve_and_bind_
= (
2045 decoder_
->offscreen_target_frame_buffer_
.get() &&
2046 decoder_
->IsOffscreenBufferMultisampled() &&
2047 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2048 enforce_internal_framebuffer
));
2049 if (!resolve_and_bind_
)
2052 ScopedGLErrorSuppressor
suppressor(
2053 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2054 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2055 decoder_
->offscreen_target_frame_buffer_
->id());
2058 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2059 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2060 new BackFramebuffer(decoder_
));
2061 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2062 decoder_
->offscreen_resolved_color_texture_
.reset(
2063 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2064 decoder_
->offscreen_resolved_color_texture_
->Create();
2066 DCHECK(decoder_
->offscreen_saved_color_format_
);
2067 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2068 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2070 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2071 decoder_
->offscreen_resolved_color_texture_
.get());
2072 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2073 GL_FRAMEBUFFER_COMPLETE
) {
2074 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2075 << "because offscreen resolved FBO was incomplete.";
2079 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2081 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2083 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2084 const int width
= decoder_
->offscreen_size_
.width();
2085 const int height
= decoder_
->offscreen_size_
.height();
2086 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2087 decoder
->BlitFramebufferHelper(0,
2095 GL_COLOR_BUFFER_BIT
,
2097 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2100 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2101 if (!resolve_and_bind_
)
2104 ScopedGLErrorSuppressor
suppressor(
2105 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2106 decoder_
->RestoreCurrentFramebufferBindings();
2107 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2108 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2112 BackTexture::BackTexture(
2113 MemoryTracker
* memory_tracker
,
2114 ContextState
* state
)
2115 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2117 bytes_allocated_(0),
2121 BackTexture::~BackTexture() {
2122 // This does not destroy the render texture because that would require that
2123 // the associated GL context was current. Just check that it was explicitly
2128 void BackTexture::Create() {
2129 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2130 state_
->GetErrorState());
2132 glGenTextures(1, &id_
);
2133 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2134 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2135 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2136 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2137 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2139 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2140 // never called on an offscreen context, no data will ever be uploaded to the
2141 // saved offscreen color texture (it is deferred until to when SwapBuffers
2142 // is called). My idea is that some nvidia drivers might have a bug where
2143 // deleting a texture that has never been populated might cause a
2146 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2148 bytes_allocated_
= 16u * 16u * 4u;
2149 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2152 bool BackTexture::AllocateStorage(
2153 const gfx::Size
& size
, GLenum format
, bool zero
) {
2155 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2156 state_
->GetErrorState());
2157 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2158 uint32 image_size
= 0;
2159 GLES2Util::ComputeImageDataSizes(
2160 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2163 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2167 scoped_ptr
<char[]> zero_data
;
2169 zero_data
.reset(new char[image_size
]);
2170 memset(zero_data
.get(), 0, image_size
);
2173 glTexImage2D(GL_TEXTURE_2D
,
2185 bool success
= glGetError() == GL_NO_ERROR
;
2187 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2188 bytes_allocated_
= image_size
;
2189 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2194 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2196 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2197 state_
->GetErrorState());
2198 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2199 glCopyTexImage2D(GL_TEXTURE_2D
,
2208 void BackTexture::Destroy() {
2210 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2211 state_
->GetErrorState());
2212 glDeleteTextures(1, &id_
);
2215 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2216 bytes_allocated_
= 0;
2219 void BackTexture::Invalidate() {
2223 BackRenderbuffer::BackRenderbuffer(
2224 RenderbufferManager
* renderbuffer_manager
,
2225 MemoryTracker
* memory_tracker
,
2226 ContextState
* state
)
2227 : renderbuffer_manager_(renderbuffer_manager
),
2228 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2230 bytes_allocated_(0),
2234 BackRenderbuffer::~BackRenderbuffer() {
2235 // This does not destroy the render buffer because that would require that
2236 // the associated GL context was current. Just check that it was explicitly
2241 void BackRenderbuffer::Create() {
2242 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2243 state_
->GetErrorState());
2245 glGenRenderbuffersEXT(1, &id_
);
2248 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2249 const gfx::Size
& size
,
2252 ScopedGLErrorSuppressor
suppressor(
2253 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2254 ScopedRenderBufferBinder
binder(state_
, id_
);
2256 uint32 estimated_size
= 0;
2257 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2258 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2262 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2267 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2272 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2279 bool success
= glGetError() == GL_NO_ERROR
;
2281 // Mark the previously allocated bytes as free.
2282 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2283 bytes_allocated_
= estimated_size
;
2284 // Track the newly allocated bytes.
2285 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2290 void BackRenderbuffer::Destroy() {
2292 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2293 state_
->GetErrorState());
2294 glDeleteRenderbuffersEXT(1, &id_
);
2297 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2298 bytes_allocated_
= 0;
2301 void BackRenderbuffer::Invalidate() {
2305 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2306 : decoder_(decoder
),
2310 BackFramebuffer::~BackFramebuffer() {
2311 // This does not destroy the frame buffer because that would require that
2312 // the associated GL context was current. Just check that it was explicitly
2317 void BackFramebuffer::Create() {
2318 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2319 decoder_
->GetErrorState());
2321 glGenFramebuffersEXT(1, &id_
);
2324 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2326 ScopedGLErrorSuppressor
suppressor(
2327 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2328 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2329 GLuint attach_id
= texture
? texture
->id() : 0;
2330 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2331 GL_COLOR_ATTACHMENT0
,
2337 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2338 BackRenderbuffer
* render_buffer
) {
2340 ScopedGLErrorSuppressor
suppressor(
2341 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2342 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2343 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2344 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2350 void BackFramebuffer::Destroy() {
2352 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2353 decoder_
->GetErrorState());
2354 glDeleteFramebuffersEXT(1, &id_
);
2359 void BackFramebuffer::Invalidate() {
2363 GLenum
BackFramebuffer::CheckStatus() {
2365 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2366 decoder_
->GetErrorState());
2367 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2368 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2371 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2372 return new GLES2DecoderImpl(group
);
2375 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2378 logger_(&debug_marker_manager_
),
2379 state_(group_
->feature_info(), this, &logger_
),
2380 unpack_flip_y_(false),
2381 unpack_premultiply_alpha_(false),
2382 unpack_unpremultiply_alpha_(false),
2383 attrib_0_buffer_id_(0),
2384 attrib_0_buffer_matches_value_(true),
2386 fixed_attrib_buffer_id_(0),
2387 fixed_attrib_buffer_size_(0),
2388 offscreen_target_color_format_(0),
2389 offscreen_target_depth_format_(0),
2390 offscreen_target_stencil_format_(0),
2391 offscreen_target_samples_(0),
2392 offscreen_target_buffer_preserved_(true),
2393 offscreen_saved_color_format_(0),
2394 back_buffer_color_format_(0),
2395 back_buffer_has_depth_(false),
2396 back_buffer_has_stencil_(false),
2397 surfaceless_(false),
2398 backbuffer_needs_clear_bits_(0),
2399 current_decoder_error_(error::kNoError
),
2400 use_shader_translator_(true),
2401 validators_(group_
->feature_info()->validators()),
2402 feature_info_(group_
->feature_info()),
2404 has_robustness_extension_(false),
2405 reset_status_(GL_NO_ERROR
),
2406 reset_by_robustness_extension_(false),
2407 supports_post_sub_buffer_(false),
2408 force_webgl_glsl_validation_(false),
2409 derivatives_explicitly_enabled_(false),
2410 frag_depth_explicitly_enabled_(false),
2411 draw_buffers_explicitly_enabled_(false),
2412 shader_texture_lod_explicitly_enabled_(false),
2413 compile_shader_always_succeeds_(false),
2414 lose_context_when_out_of_memory_(false),
2415 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2416 switches::kEnableGPUServiceLoggingGPU
)),
2417 viewport_max_width_(0),
2418 viewport_max_height_(0),
2419 texture_state_(group_
->feature_info()
2421 .texsubimage2d_faster_than_teximage2d
),
2422 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2423 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2424 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2425 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2426 gpu_trace_level_(2),
2427 gpu_trace_commands_(false),
2428 gpu_debug_commands_(false),
2429 validation_texture_(0),
2430 validation_fbo_multisample_(0),
2431 validation_fbo_(0) {
2434 attrib_0_value_
.v
[0] = 0.0f
;
2435 attrib_0_value_
.v
[1] = 0.0f
;
2436 attrib_0_value_
.v
[2] = 0.0f
;
2437 attrib_0_value_
.v
[3] = 1.0f
;
2439 // The shader translator is used for WebGL even when running on EGL
2440 // because additional restrictions are needed (like only enabling
2441 // GL_OES_standard_derivatives on demand). It is used for the unit
2442 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2443 // the empty string to CompileShader and this is not a valid shader.
2444 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL
||
2445 base::CommandLine::ForCurrentProcess()->HasSwitch(
2446 switches::kDisableGLSLTranslator
)) {
2447 use_shader_translator_
= false;
2451 GLES2DecoderImpl::~GLES2DecoderImpl() {
2454 bool GLES2DecoderImpl::Initialize(
2455 const scoped_refptr
<gfx::GLSurface
>& surface
,
2456 const scoped_refptr
<gfx::GLContext
>& context
,
2458 const gfx::Size
& offscreen_size
,
2459 const DisallowedFeatures
& disallowed_features
,
2460 const std::vector
<int32
>& attribs
) {
2461 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2462 DCHECK(context
->IsCurrent(surface
.get()));
2463 DCHECK(!context_
.get());
2465 ContextCreationAttribHelper attrib_parser
;
2466 if (!attrib_parser
.Parse(attribs
))
2469 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2472 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2474 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2475 switches::kEnableGPUDebugging
)) {
2479 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2480 switches::kEnableGPUCommandLogging
)) {
2481 set_log_commands(true);
2484 compile_shader_always_succeeds_
=
2485 base::CommandLine::ForCurrentProcess()->HasSwitch(
2486 switches::kCompileShaderAlwaysSucceeds
);
2488 // Take ownership of the context and surface. The surface can be replaced with
2493 // Create GPU Tracer for timing values.
2494 gpu_tracer_
.reset(new GPUTracer(this));
2496 // Save the loseContextWhenOutOfMemory context creation attribute.
2497 lose_context_when_out_of_memory_
=
2498 attrib_parser
.lose_context_when_out_of_memory
;
2500 // If the failIfMajorPerformanceCaveat context creation attribute was true
2501 // and we are using a software renderer, fail.
2502 if (attrib_parser
.fail_if_major_perf_caveat
&&
2503 feature_info_
->feature_flags().is_swiftshader
) {
2504 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2509 if (!group_
->Initialize(this, disallowed_features
)) {
2510 LOG(ERROR
) << "GpuScheduler::InitializeCommon failed because group "
2511 << "failed to initialize.";
2512 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2518 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2519 switches::kEnableUnsafeES3APIs
) &&
2520 attrib_parser
.es3_context_required
&&
2521 feature_info_
->IsES3Capable()) {
2522 feature_info_
->EnableES3Validators();
2523 set_unsafe_es3_apis_enabled(true);
2526 disallowed_features_
= disallowed_features
;
2528 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2529 vertex_array_manager_
.reset(new VertexArrayManager());
2531 GLuint default_vertex_attrib_service_id
= 0;
2532 if (features().native_vertex_array_object
) {
2533 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2534 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2537 state_
.default_vertex_attrib_manager
=
2538 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2540 state_
.default_vertex_attrib_manager
->Initialize(
2541 group_
->max_vertex_attribs(),
2542 feature_info_
->workarounds().init_vertex_attributes
);
2544 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2545 DoBindVertexArrayOES(0);
2547 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2549 image_manager_
.reset(new ImageManager
);
2551 util_
.set_num_compressed_texture_formats(
2552 validators_
->compressed_texture_format
.GetValues().size());
2554 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2555 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2556 // OpenGL ES 2.0 does not have this issue.
2557 glEnableVertexAttribArray(0);
2559 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2560 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2561 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2562 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2563 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2565 state_
.texture_units
.resize(group_
->max_texture_units());
2566 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2567 glActiveTexture(GL_TEXTURE0
+ tt
);
2568 // We want the last bind to be 2D.
2570 if (features().oes_egl_image_external
) {
2571 ref
= texture_manager()->GetDefaultTextureInfo(
2572 GL_TEXTURE_EXTERNAL_OES
);
2573 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2574 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2576 if (features().arb_texture_rectangle
) {
2577 ref
= texture_manager()->GetDefaultTextureInfo(
2578 GL_TEXTURE_RECTANGLE_ARB
);
2579 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2580 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2582 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2583 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2584 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2585 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2586 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2587 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2589 glActiveTexture(GL_TEXTURE0
);
2593 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2594 features().chromium_framebuffer_multisample
) {
2595 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2596 // max_sample_count must be initialized to a sane value. If
2597 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2598 GLint max_sample_count
= 1;
2599 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2600 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2603 offscreen_target_samples_
= 1;
2605 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2607 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2608 const bool rgb8_supported
=
2609 context_
->HasExtension("GL_OES_rgb8_rgba8");
2610 // The only available default render buffer formats in GLES2 have very
2611 // little precision. Don't enable multisampling unless 8-bit render
2612 // buffer formats are available--instead fall back to 8-bit textures.
2613 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2614 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2617 offscreen_target_samples_
= 1;
2618 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2622 // ANGLE only supports packed depth/stencil formats, so use it if it is
2624 const bool depth24_stencil8_supported
=
2625 feature_info_
->feature_flags().packed_depth24_stencil8
;
2626 VLOG(1) << "GL_OES_packed_depth_stencil "
2627 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2628 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2629 depth24_stencil8_supported
) {
2630 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2631 offscreen_target_stencil_format_
= 0;
2633 // It may be the case that this depth/stencil combination is not
2634 // supported, but this will be checked later by CheckFramebufferStatus.
2635 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2636 GL_DEPTH_COMPONENT16
: 0;
2637 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2638 GL_STENCIL_INDEX8
: 0;
2641 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2644 // If depth is requested at all, use the packed depth stencil format if
2645 // it's available, as some desktop GL drivers don't support any non-packed
2646 // formats for depth attachments.
2647 const bool depth24_stencil8_supported
=
2648 feature_info_
->feature_flags().packed_depth24_stencil8
;
2649 VLOG(1) << "GL_EXT_packed_depth_stencil "
2650 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2652 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2653 depth24_stencil8_supported
) {
2654 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2655 offscreen_target_stencil_format_
= 0;
2657 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2658 GL_DEPTH_COMPONENT
: 0;
2659 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2660 GL_STENCIL_INDEX
: 0;
2664 offscreen_saved_color_format_
= attrib_parser
.alpha_size
> 0 ?
2667 // Create the target frame buffer. This is the one that the client renders
2669 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2670 offscreen_target_frame_buffer_
->Create();
2671 // Due to GLES2 format limitations, either the color texture (for
2672 // non-multisampling) or the color render buffer (for multisampling) will be
2673 // attached to the offscreen frame buffer. The render buffer has more
2674 // limited formats available to it, but the texture can't do multisampling.
2675 if (IsOffscreenBufferMultisampled()) {
2676 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2677 renderbuffer_manager(), memory_tracker(), &state_
));
2678 offscreen_target_color_render_buffer_
->Create();
2680 offscreen_target_color_texture_
.reset(new BackTexture(
2681 memory_tracker(), &state_
));
2682 offscreen_target_color_texture_
->Create();
2684 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2685 renderbuffer_manager(), memory_tracker(), &state_
));
2686 offscreen_target_depth_render_buffer_
->Create();
2687 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2688 renderbuffer_manager(), memory_tracker(), &state_
));
2689 offscreen_target_stencil_render_buffer_
->Create();
2691 // Create the saved offscreen texture. The target frame buffer is copied
2692 // here when SwapBuffers is called.
2693 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2694 offscreen_saved_frame_buffer_
->Create();
2696 offscreen_saved_color_texture_
.reset(new BackTexture(
2697 memory_tracker(), &state_
));
2698 offscreen_saved_color_texture_
->Create();
2700 // Allocate the render buffers at their initial size and check the status
2701 // of the frame buffers is okay.
2702 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2703 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2708 state_
.viewport_width
= offscreen_size
.width();
2709 state_
.viewport_height
= offscreen_size
.height();
2711 // Allocate the offscreen saved color texture.
2712 DCHECK(offscreen_saved_color_format_
);
2713 offscreen_saved_color_texture_
->AllocateStorage(
2714 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2716 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2717 offscreen_saved_color_texture_
.get());
2718 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2719 GL_FRAMEBUFFER_COMPLETE
) {
2720 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2725 // Bind to the new default frame buffer (the offscreen target frame buffer).
2726 // This should now be associated with ID zero.
2727 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2729 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2730 // These are NOT if the back buffer has these proprorties. They are
2731 // if we want the command buffer to enforce them regardless of what
2732 // the real backbuffer is assuming the real back buffer gives us more than
2733 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2734 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2735 // can't do anything about that.
2737 if (!surfaceless_
) {
2738 GLint alpha_bits
= 0;
2739 GLint depth_bits
= 0;
2740 GLint stencil_bits
= 0;
2742 bool default_fb
= (GetBackbufferServiceId() == 0);
2744 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2745 glGetFramebufferAttachmentParameterivEXT(
2747 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2748 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2749 glGetFramebufferAttachmentParameterivEXT(
2751 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2752 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2753 glGetFramebufferAttachmentParameterivEXT(
2755 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2756 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2758 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2759 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2760 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2763 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2764 // the user requested RGB then RGB. If the user did not specify a
2765 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2766 back_buffer_color_format_
=
2767 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2768 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2769 back_buffer_has_stencil_
=
2770 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2773 state_
.viewport_width
= surface
->GetSize().width();
2774 state_
.viewport_height
= surface
->GetSize().height();
2777 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2778 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2779 // isn't well documented; it was discovered in the Khronos OpenGL ES
2780 // mailing list archives. It also implicitly enables the desktop GL
2781 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2782 // variable in fragment shaders.
2783 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2784 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2785 glEnable(GL_POINT_SPRITE
);
2788 has_robustness_extension_
=
2789 context
->HasExtension("GL_ARB_robustness") ||
2790 context
->HasExtension("GL_KHR_robustness") ||
2791 context
->HasExtension("GL_EXT_robustness");
2793 if (!InitializeShaderTranslator()) {
2797 GLint viewport_params
[4] = { 0 };
2798 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2799 viewport_max_width_
= viewport_params
[0];
2800 viewport_max_height_
= viewport_params
[1];
2802 state_
.scissor_width
= state_
.viewport_width
;
2803 state_
.scissor_height
= state_
.viewport_height
;
2805 // Set all the default state because some GL drivers get it wrong.
2806 state_
.InitCapabilities(NULL
);
2807 state_
.InitState(NULL
);
2808 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2810 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2811 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2812 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2813 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2814 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
2816 bool call_gl_clear
= !surfaceless_
;
2817 #if defined(OS_ANDROID)
2818 // Temporary workaround for Android WebView because this clear ignores the
2819 // clip and corrupts that external UI of the App. Not calling glClear is ok
2820 // because the system already clears the buffer before each draw. Proper
2821 // fix might be setting the scissor clip properly before initialize. See
2822 // crbug.com/259023 for details.
2823 call_gl_clear
= surface_
->GetHandle();
2825 if (call_gl_clear
) {
2826 // Clear the backbuffer.
2827 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
2830 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
2831 if (feature_info_
->workarounds()
2832 .disable_post_sub_buffers_for_onscreen_surfaces
&&
2833 !surface
->IsOffscreen())
2834 supports_post_sub_buffer_
= false;
2836 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
2837 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
2840 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
2841 context_
->SetUnbindFboOnMakeCurrent();
2844 // Only compositor contexts are known to use only the subset of GL
2845 // that can be safely migrated between the iGPU and the dGPU. Mark
2846 // those contexts as safe to forcibly transition between the GPUs.
2847 // http://crbug.com/180876, http://crbug.com/227228
2849 context_
->SetSafeToForceGpuSwitch();
2851 async_pixel_transfer_manager_
.reset(
2852 AsyncPixelTransferManager::Create(context
.get()));
2853 async_pixel_transfer_manager_
->Initialize(texture_manager());
2855 if (workarounds().gl_clear_broken
) {
2856 DCHECK(!clear_framebuffer_blit_
.get());
2857 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2858 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
2859 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
2863 framebuffer_manager()->AddObserver(this);
2868 Capabilities
GLES2DecoderImpl::GetCapabilities() {
2869 DCHECK(initialized());
2872 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
2873 Capabilities::ShaderPrecision
* shader_precision
) {
2874 GLint range
[2] = {0, 0};
2875 GLint precision
= 0;
2876 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
2877 shader_precision
->min_range
= range
[0];
2878 shader_precision
->max_range
= range
[1];
2879 shader_precision
->precision
= precision
;
2881 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
2882 &caps
.max_combined_texture_image_units
);
2883 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
2884 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
2885 &caps
.max_fragment_uniform_vectors
);
2886 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
2887 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
2888 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
2889 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
2890 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
2891 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
2892 &caps
.max_vertex_texture_image_units
);
2893 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
2894 &caps
.max_vertex_uniform_vectors
);
2895 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
2896 &caps
.num_compressed_texture_formats
);
2897 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
2898 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
2899 &caps
.bind_generates_resource_chromium
);
2900 if (unsafe_es3_apis_enabled()) {
2901 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
2902 &caps
.max_transform_feedback_separate_attribs
);
2903 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
2904 &caps
.max_uniform_buffer_bindings
);
2905 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
2906 &caps
.uniform_buffer_offset_alignment
);
2909 caps
.egl_image_external
=
2910 feature_info_
->feature_flags().oes_egl_image_external
;
2911 caps
.texture_format_atc
=
2912 feature_info_
->feature_flags().ext_texture_format_atc
;
2913 caps
.texture_format_bgra8888
=
2914 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
2915 caps
.texture_format_dxt1
=
2916 feature_info_
->feature_flags().ext_texture_format_dxt1
;
2917 caps
.texture_format_dxt5
=
2918 feature_info_
->feature_flags().ext_texture_format_dxt5
;
2919 caps
.texture_format_etc1
=
2920 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
2921 caps
.texture_format_etc1_npot
=
2922 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
2923 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
2924 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
2925 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
2926 caps
.discard_framebuffer
=
2927 feature_info_
->feature_flags().ext_discard_framebuffer
;
2928 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
2930 #if defined(OS_MACOSX)
2931 // This is unconditionally true on mac, no need to test for it at runtime.
2932 caps
.iosurface
= true;
2935 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
2938 caps
.blend_equation_advanced
=
2939 feature_info_
->feature_flags().blend_equation_advanced
;
2940 caps
.blend_equation_advanced_coherent
=
2941 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
2942 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
2946 void GLES2DecoderImpl::UpdateCapabilities() {
2947 util_
.set_num_compressed_texture_formats(
2948 validators_
->compressed_texture_format
.GetValues().size());
2949 util_
.set_num_shader_binary_formats(
2950 validators_
->shader_binary_format
.GetValues().size());
2953 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2954 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2956 if (!use_shader_translator_
) {
2959 ShBuiltInResources resources
;
2960 ShInitBuiltInResources(&resources
);
2961 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
2962 resources
.MaxVertexUniformVectors
=
2963 group_
->max_vertex_uniform_vectors();
2964 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
2965 resources
.MaxVertexTextureImageUnits
=
2966 group_
->max_vertex_texture_image_units();
2967 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
2968 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
2969 resources
.MaxFragmentUniformVectors
=
2970 group_
->max_fragment_uniform_vectors();
2971 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
2972 resources
.MaxExpressionComplexity
= 256;
2973 resources
.MaxCallStackDepth
= 256;
2975 GLint range
[2] = { 0, 0 };
2976 GLint precision
= 0;
2977 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
2979 resources
.FragmentPrecisionHigh
=
2980 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
2982 if (force_webgl_glsl_validation_
) {
2983 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
2984 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
2985 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
2986 if (!draw_buffers_explicitly_enabled_
)
2987 resources
.MaxDrawBuffers
= 1;
2988 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
2989 resources
.NV_draw_buffers
=
2990 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
2992 resources
.OES_standard_derivatives
=
2993 features().oes_standard_derivatives
? 1 : 0;
2994 resources
.ARB_texture_rectangle
=
2995 features().arb_texture_rectangle
? 1 : 0;
2996 resources
.OES_EGL_image_external
=
2997 features().oes_egl_image_external
? 1 : 0;
2998 resources
.EXT_draw_buffers
=
2999 features().ext_draw_buffers
? 1 : 0;
3000 resources
.EXT_frag_depth
=
3001 features().ext_frag_depth
? 1 : 0;
3002 resources
.EXT_shader_texture_lod
=
3003 features().ext_shader_texture_lod
? 1 : 0;
3004 resources
.NV_draw_buffers
=
3005 features().nv_draw_buffers
? 1 : 0;
3008 ShShaderSpec shader_spec
;
3009 if (force_webgl_glsl_validation_
) {
3010 shader_spec
= unsafe_es3_apis_enabled() ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3012 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3015 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3016 features().enable_shader_name_hashing
)
3017 resources
.HashFunction
= &CityHash64
;
3019 resources
.HashFunction
= NULL
;
3020 ShaderTranslatorInterface::GlslImplementationType implementation_type
=
3021 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
?
3022 ShaderTranslatorInterface::kGlslES
: ShaderTranslatorInterface::kGlsl
;
3023 int driver_bug_workarounds
= 0;
3024 if (workarounds().needs_glsl_built_in_function_emulation
)
3025 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3026 if (workarounds().init_gl_position_in_vertex_shader
)
3027 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3028 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3029 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3030 if (workarounds().init_varyings_without_static_use
)
3031 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3032 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3033 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3034 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3035 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3036 if (workarounds().regenerate_struct_names
)
3037 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3039 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
3040 switches::kEmulateShaderPrecision
))
3041 resources
.WEBGL_debug_shader_precision
= true;
3043 vertex_translator_
= shader_translator_cache()->GetTranslator(
3047 implementation_type
,
3048 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3049 if (!vertex_translator_
.get()) {
3050 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3055 fragment_translator_
= shader_translator_cache()->GetTranslator(
3059 implementation_type
,
3060 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3061 if (!fragment_translator_
.get()) {
3062 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3069 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3070 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3071 if (GetBuffer(client_ids
[ii
])) {
3075 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3076 glGenBuffersARB(n
, service_ids
.get());
3077 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3078 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3083 bool GLES2DecoderImpl::GenFramebuffersHelper(
3084 GLsizei n
, const GLuint
* client_ids
) {
3085 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3086 if (GetFramebuffer(client_ids
[ii
])) {
3090 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3091 glGenFramebuffersEXT(n
, service_ids
.get());
3092 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3093 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3098 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3099 GLsizei n
, const GLuint
* client_ids
) {
3100 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3101 if (GetRenderbuffer(client_ids
[ii
])) {
3105 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3106 glGenRenderbuffersEXT(n
, service_ids
.get());
3107 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3108 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3113 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3114 const GLuint
* client_ids
) {
3115 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3116 if (GetValuebuffer(client_ids
[ii
])) {
3120 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3121 CreateValuebuffer(client_ids
[ii
]);
3126 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3127 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3128 if (GetTexture(client_ids
[ii
])) {
3132 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3133 glGenTextures(n
, service_ids
.get());
3134 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3135 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3140 void GLES2DecoderImpl::DeleteBuffersHelper(
3141 GLsizei n
, const GLuint
* client_ids
) {
3142 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3143 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3144 if (buffer
&& !buffer
->IsDeleted()) {
3145 buffer
->RemoveMappedRange();
3146 state_
.vertex_attrib_manager
->Unbind(buffer
);
3147 if (state_
.bound_array_buffer
.get() == buffer
) {
3148 state_
.bound_array_buffer
= NULL
;
3150 RemoveBuffer(client_ids
[ii
]);
3155 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3156 GLsizei n
, const GLuint
* client_ids
) {
3157 bool supports_separate_framebuffer_binds
=
3158 features().chromium_framebuffer_multisample
;
3160 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3161 Framebuffer
* framebuffer
=
3162 GetFramebuffer(client_ids
[ii
]);
3163 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3164 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3165 GLenum target
= supports_separate_framebuffer_binds
?
3166 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3168 // Unbind attachments on FBO before deletion.
3169 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3170 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3172 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3173 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3174 framebuffer_state_
.clear_state_dirty
= true;
3176 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3177 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3178 GLenum target
= supports_separate_framebuffer_binds
?
3179 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3180 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3183 RemoveFramebuffer(client_ids
[ii
]);
3188 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3189 GLsizei n
, const GLuint
* client_ids
) {
3190 bool supports_separate_framebuffer_binds
=
3191 features().chromium_framebuffer_multisample
;
3192 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3193 Renderbuffer
* renderbuffer
=
3194 GetRenderbuffer(client_ids
[ii
]);
3195 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3196 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3197 state_
.bound_renderbuffer
= NULL
;
3199 // Unbind from current framebuffers.
3200 if (supports_separate_framebuffer_binds
) {
3201 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3202 framebuffer_state_
.bound_read_framebuffer
3203 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3205 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3206 framebuffer_state_
.bound_draw_framebuffer
3207 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3210 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3211 framebuffer_state_
.bound_draw_framebuffer
3212 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3215 framebuffer_state_
.clear_state_dirty
= true;
3216 RemoveRenderbuffer(client_ids
[ii
]);
3221 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3223 const GLuint
* client_ids
) {
3224 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3225 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3227 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3228 state_
.bound_valuebuffer
= NULL
;
3230 RemoveValuebuffer(client_ids
[ii
]);
3235 void GLES2DecoderImpl::DeleteTexturesHelper(
3236 GLsizei n
, const GLuint
* client_ids
) {
3237 bool supports_separate_framebuffer_binds
=
3238 features().chromium_framebuffer_multisample
;
3239 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3240 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3242 Texture
* texture
= texture_ref
->texture();
3243 if (texture
->IsAttachedToFramebuffer()) {
3244 framebuffer_state_
.clear_state_dirty
= true;
3246 // Unbind texture_ref from texture_ref units.
3247 for (size_t jj
= 0; jj
< state_
.texture_units
.size(); ++jj
) {
3248 state_
.texture_units
[jj
].Unbind(texture_ref
);
3250 // Unbind from current framebuffers.
3251 if (supports_separate_framebuffer_binds
) {
3252 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3253 framebuffer_state_
.bound_read_framebuffer
3254 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3256 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3257 framebuffer_state_
.bound_draw_framebuffer
3258 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3261 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3262 framebuffer_state_
.bound_draw_framebuffer
3263 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3266 #if defined(OS_MACOSX)
3267 GLuint service_id
= texture
->service_id();
3268 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3269 ReleaseIOSurfaceForTexture(service_id
);
3272 RemoveTexture(client_ids
[ii
]);
3277 // } // anonymous namespace
3279 bool GLES2DecoderImpl::MakeCurrent() {
3280 if (!context_
.get())
3283 if (!context_
->MakeCurrent(surface_
.get()) || WasContextLost()) {
3284 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3286 MaybeExitOnContextLost();
3291 ProcessFinishedAsyncTransfers();
3293 // Rebind the FBO if it was unbound by the context.
3294 if (workarounds().unbind_fbo_on_context_switch
)
3295 RestoreFramebufferBindings();
3297 framebuffer_state_
.clear_state_dirty
= true;
3302 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3303 ProcessPendingReadPixels();
3304 if (engine() && query_manager_
.get())
3305 query_manager_
->ProcessPendingTransferQueries();
3307 // TODO(epenner): Is there a better place to do this?
3308 // This needs to occur before we execute any batch of commands
3309 // from the client, as the client may have recieved an async
3310 // completion while issuing those commands.
3311 // "DidFlushStart" would be ideal if we had such a callback.
3312 async_pixel_transfer_manager_
->BindCompletedAsyncTransfers();
3315 static void RebindCurrentFramebuffer(
3317 Framebuffer
* framebuffer
,
3318 GLuint back_buffer_service_id
) {
3319 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3321 if (framebuffer_id
== 0) {
3322 framebuffer_id
= back_buffer_service_id
;
3325 glBindFramebufferEXT(target
, framebuffer_id
);
3328 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3329 framebuffer_state_
.clear_state_dirty
= true;
3331 if (!features().chromium_framebuffer_multisample
) {
3332 RebindCurrentFramebuffer(
3334 framebuffer_state_
.bound_draw_framebuffer
.get(),
3335 GetBackbufferServiceId());
3337 RebindCurrentFramebuffer(
3338 GL_READ_FRAMEBUFFER_EXT
,
3339 framebuffer_state_
.bound_read_framebuffer
.get(),
3340 GetBackbufferServiceId());
3341 RebindCurrentFramebuffer(
3342 GL_DRAW_FRAMEBUFFER_EXT
,
3343 framebuffer_state_
.bound_draw_framebuffer
.get(),
3344 GetBackbufferServiceId());
3349 bool GLES2DecoderImpl::CheckFramebufferValid(
3350 Framebuffer
* framebuffer
,
3351 GLenum target
, const char* func_name
) {
3355 if (backbuffer_needs_clear_bits_
) {
3356 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3357 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3358 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3360 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3361 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3363 state_
.SetDeviceDepthMask(GL_TRUE
);
3364 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3365 bool reset_draw_buffer
= false;
3366 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3367 group_
->draw_buffer() == GL_NONE
) {
3368 reset_draw_buffer
= true;
3369 GLenum buf
= GL_BACK
;
3370 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3371 buf
= GL_COLOR_ATTACHMENT0
;
3372 glDrawBuffersARB(1, &buf
);
3374 glClear(backbuffer_needs_clear_bits_
);
3375 if (reset_draw_buffer
) {
3376 GLenum buf
= GL_NONE
;
3377 glDrawBuffersARB(1, &buf
);
3379 backbuffer_needs_clear_bits_
= 0;
3380 RestoreClearState();
3385 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3389 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3390 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3392 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3396 // Are all the attachments cleared?
3397 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3398 texture_manager()->HaveUnclearedMips()) {
3399 if (!framebuffer
->IsCleared()) {
3400 // Can we clear them?
3401 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3402 GL_FRAMEBUFFER_COMPLETE
) {
3404 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3405 "framebuffer incomplete (clear)");
3408 ClearUnclearedAttachments(target
, framebuffer
);
3412 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3413 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3414 GL_FRAMEBUFFER_COMPLETE
) {
3416 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3417 "framebuffer incomplete (check)");
3420 framebuffer_manager()->MarkAsComplete(framebuffer
);
3423 // NOTE: At this point we don't know if the framebuffer is complete but
3424 // we DO know that everything that needs to be cleared has been cleared.
3428 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3429 if (!features().chromium_framebuffer_multisample
) {
3430 bool valid
= CheckFramebufferValid(
3431 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3439 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3440 GL_DRAW_FRAMEBUFFER_EXT
,
3442 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3443 GL_READ_FRAMEBUFFER_EXT
,
3447 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3448 const char* func_name
) {
3449 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3450 framebuffer_state_
.bound_read_framebuffer
.get() :
3451 framebuffer_state_
.bound_draw_framebuffer
.get();
3454 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3456 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3462 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3463 TextureRef
* texture
, GLint level
) {
3464 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3465 framebuffer_state_
.bound_read_framebuffer
.get() :
3466 framebuffer_state_
.bound_draw_framebuffer
.get();
3469 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3470 GL_COLOR_ATTACHMENT0
);
3473 return attachment
->FormsFeedbackLoop(texture
, level
);
3476 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3477 Framebuffer
* framebuffer
=
3478 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3479 if (framebuffer
!= NULL
) {
3480 const Framebuffer::Attachment
* attachment
=
3481 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3483 return gfx::Size(attachment
->width(), attachment
->height());
3485 return gfx::Size(0, 0);
3486 } else if (offscreen_target_frame_buffer_
.get()) {
3487 return offscreen_size_
;
3489 return surface_
->GetSize();
3493 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3494 Framebuffer
* framebuffer
=
3495 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3496 if (framebuffer
!= NULL
) {
3497 return framebuffer
->GetColorAttachmentTextureType();
3499 return GL_UNSIGNED_BYTE
;
3503 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3504 Framebuffer
* framebuffer
=
3505 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3506 if (framebuffer
!= NULL
) {
3507 return framebuffer
->GetColorAttachmentFormat();
3508 } else if (offscreen_target_frame_buffer_
.get()) {
3509 return offscreen_target_color_format_
;
3511 return back_buffer_color_format_
;
3515 GLenum
GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3516 Framebuffer
* framebuffer
=
3517 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
3518 if (framebuffer
!= NULL
) {
3519 return framebuffer
->GetColorAttachmentFormat();
3520 } else if (offscreen_target_frame_buffer_
.get()) {
3521 return offscreen_target_color_format_
;
3523 return back_buffer_color_format_
;
3527 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3528 if (!offscreen_saved_color_texture_info_
.get())
3530 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3531 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3532 texture_manager()->SetLevelInfo(
3533 offscreen_saved_color_texture_info_
.get(),
3537 offscreen_size_
.width(),
3538 offscreen_size_
.height(),
3544 texture_manager()->SetParameteri(
3545 "UpdateParentTextureInfo",
3547 offscreen_saved_color_texture_info_
.get(),
3548 GL_TEXTURE_MAG_FILTER
,
3550 texture_manager()->SetParameteri(
3551 "UpdateParentTextureInfo",
3553 offscreen_saved_color_texture_info_
.get(),
3554 GL_TEXTURE_MIN_FILTER
,
3556 texture_manager()->SetParameteri(
3557 "UpdateParentTextureInfo",
3559 offscreen_saved_color_texture_info_
.get(),
3562 texture_manager()->SetParameteri(
3563 "UpdateParentTextureInfo",
3565 offscreen_saved_color_texture_info_
.get(),
3568 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3570 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3573 void GLES2DecoderImpl::SetResizeCallback(
3574 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3575 resize_callback_
= callback
;
3578 Logger
* GLES2DecoderImpl::GetLogger() {
3582 void GLES2DecoderImpl::BeginDecoding() {
3583 gpu_tracer_
->BeginDecoding();
3584 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3585 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
||
3586 (*cb_command_trace_category_
!= 0);
3589 void GLES2DecoderImpl::EndDecoding() {
3590 gpu_tracer_
->EndDecoding();
3593 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3594 return state_
.GetErrorState();
3597 void GLES2DecoderImpl::SetShaderCacheCallback(
3598 const ShaderCacheCallback
& callback
) {
3599 shader_cache_callback_
= callback
;
3602 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3603 const WaitSyncPointCallback
& callback
) {
3604 wait_sync_point_callback_
= callback
;
3607 AsyncPixelTransferManager
*
3608 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3609 return async_pixel_transfer_manager_
.get();
3612 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3613 async_pixel_transfer_manager_
.reset();
3616 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3617 AsyncPixelTransferManager
* manager
) {
3618 async_pixel_transfer_manager_
= make_scoped_ptr(manager
);
3621 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3622 uint32
* service_texture_id
) {
3623 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3625 *service_texture_id
= texture_ref
->service_id();
3631 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3632 return texture_state_
.texture_upload_count
+
3633 async_pixel_transfer_manager_
->GetTextureUploadCount();
3636 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3637 return texture_state_
.total_texture_upload_time
+
3638 async_pixel_transfer_manager_
->GetTotalTextureUploadTime();
3641 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3642 return total_processing_commands_time_
;
3645 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3646 total_processing_commands_time_
+= time
;
3649 void GLES2DecoderImpl::Destroy(bool have_context
) {
3653 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3655 // Unbind everything.
3656 state_
.vertex_attrib_manager
= NULL
;
3657 state_
.default_vertex_attrib_manager
= NULL
;
3658 state_
.texture_units
.clear();
3659 state_
.bound_array_buffer
= NULL
;
3660 state_
.current_queries
.clear();
3661 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3662 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3663 state_
.bound_renderbuffer
= NULL
;
3664 state_
.bound_valuebuffer
= NULL
;
3666 if (offscreen_saved_color_texture_info_
.get()) {
3667 DCHECK(offscreen_target_color_texture_
);
3668 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
3669 offscreen_saved_color_texture_
->id());
3670 offscreen_saved_color_texture_
->Invalidate();
3671 offscreen_saved_color_texture_info_
= NULL
;
3674 if (copy_texture_CHROMIUM_
.get()) {
3675 copy_texture_CHROMIUM_
->Destroy();
3676 copy_texture_CHROMIUM_
.reset();
3679 clear_framebuffer_blit_
.reset();
3681 if (state_
.current_program
.get()) {
3682 program_manager()->UnuseProgram(shader_manager(),
3683 state_
.current_program
.get());
3686 if (attrib_0_buffer_id_
) {
3687 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
3689 if (fixed_attrib_buffer_id_
) {
3690 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
3693 if (validation_texture_
) {
3694 glDeleteTextures(1, &validation_texture_
);
3695 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
3696 glDeleteFramebuffersEXT(1, &validation_fbo_
);
3699 if (offscreen_target_frame_buffer_
.get())
3700 offscreen_target_frame_buffer_
->Destroy();
3701 if (offscreen_target_color_texture_
.get())
3702 offscreen_target_color_texture_
->Destroy();
3703 if (offscreen_target_color_render_buffer_
.get())
3704 offscreen_target_color_render_buffer_
->Destroy();
3705 if (offscreen_target_depth_render_buffer_
.get())
3706 offscreen_target_depth_render_buffer_
->Destroy();
3707 if (offscreen_target_stencil_render_buffer_
.get())
3708 offscreen_target_stencil_render_buffer_
->Destroy();
3709 if (offscreen_saved_frame_buffer_
.get())
3710 offscreen_saved_frame_buffer_
->Destroy();
3711 if (offscreen_saved_color_texture_
.get())
3712 offscreen_saved_color_texture_
->Destroy();
3713 if (offscreen_resolved_frame_buffer_
.get())
3714 offscreen_resolved_frame_buffer_
->Destroy();
3715 if (offscreen_resolved_color_texture_
.get())
3716 offscreen_resolved_color_texture_
->Destroy();
3718 if (offscreen_target_frame_buffer_
.get())
3719 offscreen_target_frame_buffer_
->Invalidate();
3720 if (offscreen_target_color_texture_
.get())
3721 offscreen_target_color_texture_
->Invalidate();
3722 if (offscreen_target_color_render_buffer_
.get())
3723 offscreen_target_color_render_buffer_
->Invalidate();
3724 if (offscreen_target_depth_render_buffer_
.get())
3725 offscreen_target_depth_render_buffer_
->Invalidate();
3726 if (offscreen_target_stencil_render_buffer_
.get())
3727 offscreen_target_stencil_render_buffer_
->Invalidate();
3728 if (offscreen_saved_frame_buffer_
.get())
3729 offscreen_saved_frame_buffer_
->Invalidate();
3730 if (offscreen_saved_color_texture_
.get())
3731 offscreen_saved_color_texture_
->Invalidate();
3732 if (offscreen_resolved_frame_buffer_
.get())
3733 offscreen_resolved_frame_buffer_
->Invalidate();
3734 if (offscreen_resolved_color_texture_
.get())
3735 offscreen_resolved_color_texture_
->Invalidate();
3738 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3739 // Otherwise, we can leak objects. http://crbug.com/258772.
3740 // state_.current_program must be reset before group_ is reset because
3741 // the later deletes the ProgramManager object that referred by
3742 // state_.current_program object.
3743 state_
.current_program
= NULL
;
3745 copy_texture_CHROMIUM_
.reset();
3746 clear_framebuffer_blit_
.reset();
3748 if (query_manager_
.get()) {
3749 query_manager_
->Destroy(have_context
);
3750 query_manager_
.reset();
3753 if (vertex_array_manager_
.get()) {
3754 vertex_array_manager_
->Destroy(have_context
);
3755 vertex_array_manager_
.reset();
3758 if (image_manager_
.get()) {
3759 image_manager_
->Destroy(have_context
);
3760 image_manager_
.reset();
3763 offscreen_target_frame_buffer_
.reset();
3764 offscreen_target_color_texture_
.reset();
3765 offscreen_target_color_render_buffer_
.reset();
3766 offscreen_target_depth_render_buffer_
.reset();
3767 offscreen_target_stencil_render_buffer_
.reset();
3768 offscreen_saved_frame_buffer_
.reset();
3769 offscreen_saved_color_texture_
.reset();
3770 offscreen_resolved_frame_buffer_
.reset();
3771 offscreen_resolved_color_texture_
.reset();
3773 // Need to release these before releasing |group_| which may own the
3774 // ShaderTranslatorCache.
3775 fragment_translator_
= NULL
;
3776 vertex_translator_
= NULL
;
3778 // Should destroy the transfer manager before the texture manager held
3779 // by the context group.
3780 async_pixel_transfer_manager_
.reset();
3782 // Destroy the GPU Tracer which may own some in process GPU Timings.
3784 gpu_tracer_
->Destroy(have_context
);
3785 gpu_tracer_
.reset();
3789 framebuffer_manager()->RemoveObserver(this);
3790 group_
->Destroy(this, have_context
);
3794 if (context_
.get()) {
3795 context_
->ReleaseCurrent(NULL
);
3799 #if defined(OS_MACOSX)
3800 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
3801 it
!= texture_to_io_surface_map_
.end(); ++it
) {
3802 CFRelease(it
->second
);
3804 texture_to_io_surface_map_
.clear();
3808 void GLES2DecoderImpl::SetSurface(
3809 const scoped_refptr
<gfx::GLSurface
>& surface
) {
3810 DCHECK(context_
->IsCurrent(NULL
));
3811 DCHECK(surface_
.get());
3813 RestoreCurrentFramebufferBindings();
3816 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
3817 if (!offscreen_saved_color_texture_
.get()) {
3818 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
3821 if (!offscreen_saved_color_texture_info_
.get()) {
3822 GLuint service_id
= offscreen_saved_color_texture_
->id();
3823 offscreen_saved_color_texture_info_
= TextureRef::Create(
3824 texture_manager(), 0, service_id
);
3825 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
3827 UpdateParentTextureInfo();
3829 mailbox_manager()->ProduceTexture(
3830 mailbox
, offscreen_saved_color_texture_info_
->texture());
3833 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
3834 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3835 if (!is_offscreen
) {
3836 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3837 << " with an onscreen framebuffer.";
3841 if (offscreen_size_
== size
)
3844 offscreen_size_
= size
;
3845 int w
= offscreen_size_
.width();
3846 int h
= offscreen_size_
.height();
3847 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
3848 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3849 << "to allocate storage due to excessive dimensions.";
3853 // Reallocate the offscreen target buffers.
3854 DCHECK(offscreen_target_color_format_
);
3855 if (IsOffscreenBufferMultisampled()) {
3856 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
3857 feature_info_
.get(),
3859 offscreen_target_color_format_
,
3860 offscreen_target_samples_
)) {
3861 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3862 << "to allocate storage for offscreen target color buffer.";
3866 if (!offscreen_target_color_texture_
->AllocateStorage(
3867 offscreen_size_
, offscreen_target_color_format_
, false)) {
3868 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3869 << "to allocate storage for offscreen target color texture.";
3873 if (offscreen_target_depth_format_
&&
3874 !offscreen_target_depth_render_buffer_
->AllocateStorage(
3875 feature_info_
.get(),
3877 offscreen_target_depth_format_
,
3878 offscreen_target_samples_
)) {
3879 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3880 << "to allocate storage for offscreen target depth buffer.";
3883 if (offscreen_target_stencil_format_
&&
3884 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
3885 feature_info_
.get(),
3887 offscreen_target_stencil_format_
,
3888 offscreen_target_samples_
)) {
3889 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3890 << "to allocate storage for offscreen target stencil buffer.";
3894 // Attach the offscreen target buffers to the target frame buffer.
3895 if (IsOffscreenBufferMultisampled()) {
3896 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3897 GL_COLOR_ATTACHMENT0
,
3898 offscreen_target_color_render_buffer_
.get());
3900 offscreen_target_frame_buffer_
->AttachRenderTexture(
3901 offscreen_target_color_texture_
.get());
3903 if (offscreen_target_depth_format_
) {
3904 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3905 GL_DEPTH_ATTACHMENT
,
3906 offscreen_target_depth_render_buffer_
.get());
3908 const bool packed_depth_stencil
=
3909 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
3910 if (packed_depth_stencil
) {
3911 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3912 GL_STENCIL_ATTACHMENT
,
3913 offscreen_target_depth_render_buffer_
.get());
3914 } else if (offscreen_target_stencil_format_
) {
3915 offscreen_target_frame_buffer_
->AttachRenderBuffer(
3916 GL_STENCIL_ATTACHMENT
,
3917 offscreen_target_stencil_render_buffer_
.get());
3920 if (offscreen_target_frame_buffer_
->CheckStatus() !=
3921 GL_FRAMEBUFFER_COMPLETE
) {
3922 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3923 << "because offscreen FBO was incomplete.";
3927 // Clear the target frame buffer.
3929 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
3930 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3931 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3932 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3934 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3935 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3937 state_
.SetDeviceDepthMask(GL_TRUE
);
3938 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3939 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3940 RestoreClearState();
3943 // Destroy the offscreen resolved framebuffers.
3944 if (offscreen_resolved_frame_buffer_
.get())
3945 offscreen_resolved_frame_buffer_
->Destroy();
3946 if (offscreen_resolved_color_texture_
.get())
3947 offscreen_resolved_color_texture_
->Destroy();
3948 offscreen_resolved_color_texture_
.reset();
3949 offscreen_resolved_frame_buffer_
.reset();
3954 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
3955 const void* cmd_data
) {
3956 const gles2::cmds::ResizeCHROMIUM
& c
=
3957 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
3958 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
3959 return error::kDeferCommandUntilLater
;
3961 GLuint width
= static_cast<GLuint
>(c
.width
);
3962 GLuint height
= static_cast<GLuint
>(c
.height
);
3963 GLfloat scale_factor
= c
.scale_factor
;
3964 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
3966 width
= std::max(1U, width
);
3967 height
= std::max(1U, height
);
3969 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3970 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3971 // Make sure that we are done drawing to the back buffer before resizing.
3974 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
3976 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
3977 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
3978 << "ResizeOffscreenFrameBuffer failed.";
3979 return error::kLostContext
;
3983 if (!resize_callback_
.is_null()) {
3984 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
3985 DCHECK(context_
->IsCurrent(surface_
.get()));
3986 if (!context_
->IsCurrent(surface_
.get())) {
3987 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
3988 << "current after resize callback.";
3989 return error::kLostContext
;
3993 return error::kNoError
;
3996 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
3997 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
3998 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4000 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4003 // Decode a command, and call the corresponding GL functions.
4004 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4005 // of commands at once, and is now only used for tests that need to track
4006 // individual commands.
4007 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4008 unsigned int arg_count
,
4009 const void* cmd_data
) {
4010 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4013 // Decode multiple commands, and call the corresponding GL functions.
4014 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4015 // changed by a (malicious) client at any time, so if validation has to happen,
4016 // it should operate on a copy of them.
4017 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4018 // interest of performance in this critical execution loop.
4019 template <bool DebugImpl
>
4020 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4023 int* entries_processed
) {
4024 commands_to_process_
= num_commands
;
4025 error::Error result
= error::kNoError
;
4026 const CommandBufferEntry
* cmd_data
=
4027 static_cast<const CommandBufferEntry
*>(buffer
);
4028 int process_pos
= 0;
4029 unsigned int command
= 0;
4031 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4032 commands_to_process_
--) {
4033 const unsigned int size
= cmd_data
->value_header
.size
;
4034 command
= cmd_data
->value_header
.command
;
4037 result
= error::kInvalidSize
;
4041 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4042 result
= error::kOutOfBounds
;
4047 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4048 GetCommandName(command
));
4050 if (log_commands()) {
4051 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4052 << "cmd: " << GetCommandName(command
);
4056 const unsigned int arg_count
= size
- 1;
4057 unsigned int command_index
= command
- kStartPoint
- 1;
4058 if (command_index
< arraysize(command_info
)) {
4059 const CommandInfo
& info
= command_info
[command_index
];
4060 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4061 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4062 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4063 bool doing_gpu_trace
= false;
4064 if (DebugImpl
&& gpu_trace_commands_
) {
4065 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4066 doing_gpu_trace
= true;
4067 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4068 GetCommandName(command
),
4073 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4074 sizeof(CommandBufferEntry
); // NOLINT
4076 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4078 if (DebugImpl
&& doing_gpu_trace
)
4079 gpu_tracer_
->End(kTraceDecoder
);
4081 if (DebugImpl
&& debug()) {
4083 while ((error
= glGetError()) != GL_NO_ERROR
) {
4084 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4085 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4086 << " : " << GetCommandName(command
);
4087 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4091 result
= error::kInvalidArguments
;
4094 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4098 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4099 GetCommandName(command
));
4102 if (result
== error::kNoError
&&
4103 current_decoder_error_
!= error::kNoError
) {
4104 result
= current_decoder_error_
;
4105 current_decoder_error_
= error::kNoError
;
4108 if (result
!= error::kDeferCommandUntilLater
) {
4109 process_pos
+= size
;
4114 if (entries_processed
)
4115 *entries_processed
= process_pos
;
4117 if (error::IsError(result
)) {
4118 LOG(ERROR
) << "Error: " << result
<< " for Command "
4119 << GetCommandName(command
);
4125 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4128 int* entries_processed
) {
4129 if (gpu_debug_commands_
) {
4130 return DoCommandsImpl
<true>(
4131 num_commands
, buffer
, num_entries
, entries_processed
);
4133 return DoCommandsImpl
<false>(
4134 num_commands
, buffer
, num_entries
, entries_processed
);
4138 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4139 buffer_manager()->RemoveBuffer(client_id
);
4142 void GLES2DecoderImpl::DoFinish() {
4144 ProcessPendingReadPixels();
4145 ProcessPendingQueries(true);
4148 void GLES2DecoderImpl::DoFlush() {
4150 ProcessPendingQueries(false);
4153 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4154 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4155 if (texture_index
>= state_
.texture_units
.size()) {
4156 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4157 "glActiveTexture", texture_unit
, "texture_unit");
4160 state_
.active_texture_unit
= texture_index
;
4161 glActiveTexture(texture_unit
);
4164 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4165 Buffer
* buffer
= NULL
;
4166 GLuint service_id
= 0;
4167 if (client_id
!= 0) {
4168 buffer
= GetBuffer(client_id
);
4170 if (!group_
->bind_generates_resource()) {
4171 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4173 "id not generated by glGenBuffers");
4177 // It's a new id so make a buffer buffer for it.
4178 glGenBuffersARB(1, &service_id
);
4179 CreateBuffer(client_id
, service_id
);
4180 buffer
= GetBuffer(client_id
);
4183 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4185 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4187 GL_INVALID_OPERATION
,
4188 "glBindBuffer", "buffer bound to more than 1 target");
4191 service_id
= buffer
->service_id();
4194 case GL_ARRAY_BUFFER
:
4195 state_
.bound_array_buffer
= buffer
;
4197 case GL_ELEMENT_ARRAY_BUFFER
:
4198 state_
.vertex_attrib_manager
->SetElementArrayBuffer(buffer
);
4201 NOTREACHED(); // Validation should prevent us getting here.
4204 glBindBuffer(target
, service_id
);
4207 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4208 bool all_draw_buffers
) {
4209 Framebuffer
* framebuffer
=
4210 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4211 if (!all_draw_buffers
|| !framebuffer
) {
4212 return (GLES2Util::GetChannelsForFormat(
4213 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4215 return framebuffer
->HasAlphaMRT();
4218 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4219 Framebuffer
* framebuffer
=
4220 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4222 return framebuffer
->HasDepthAttachment();
4224 if (offscreen_target_frame_buffer_
.get()) {
4225 return offscreen_target_depth_format_
!= 0;
4227 return back_buffer_has_depth_
;
4230 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4231 Framebuffer
* framebuffer
=
4232 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4234 return framebuffer
->HasStencilAttachment();
4236 if (offscreen_target_frame_buffer_
.get()) {
4237 return offscreen_target_stencil_format_
!= 0 ||
4238 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4240 return back_buffer_has_stencil_
;
4243 void GLES2DecoderImpl::ApplyDirtyState() {
4244 if (framebuffer_state_
.clear_state_dirty
) {
4245 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha(true);
4246 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4247 state_
.color_mask_green
,
4248 state_
.color_mask_blue
,
4249 state_
.color_mask_alpha
&& have_alpha
);
4251 bool have_depth
= BoundFramebufferHasDepthAttachment();
4252 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4254 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4255 state_
.SetDeviceStencilMaskSeparate(
4256 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4257 state_
.SetDeviceStencilMaskSeparate(
4258 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4260 state_
.SetDeviceCapabilityState(
4261 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4262 state_
.SetDeviceCapabilityState(
4263 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4264 framebuffer_state_
.clear_state_dirty
= false;
4268 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4269 return (offscreen_target_frame_buffer_
.get())
4270 ? offscreen_target_frame_buffer_
->id()
4271 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4274 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4275 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4276 "context", logger_
.GetLogPrefix());
4277 // Restore the Framebuffer first because of bugs in Intel drivers.
4278 // Intel drivers incorrectly clip the viewport settings to
4279 // the size of the current framebuffer object.
4280 RestoreFramebufferBindings();
4281 state_
.RestoreState(prev_state
);
4284 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4286 framebuffer_state_
.bound_draw_framebuffer
.get()
4287 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4288 : GetBackbufferServiceId();
4289 if (!features().chromium_framebuffer_multisample
) {
4290 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4292 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4293 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4294 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4295 : GetBackbufferServiceId();
4296 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4301 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4302 state_
.RestoreRenderbufferBindings();
4305 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4306 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4308 GLenum target
= texture
->target();
4309 glBindTexture(target
, service_id
);
4311 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4313 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4315 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4317 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4318 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4322 void GLES2DecoderImpl::ClearAllAttributes() const {
4323 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4325 if (feature_info_
->feature_flags().native_vertex_array_object
)
4326 glBindVertexArrayOES(0);
4328 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4329 if (i
!= 0) // Never disable attribute 0
4330 glDisableVertexAttribArray(i
);
4331 if (features().angle_instanced_arrays
)
4332 glVertexAttribDivisorANGLE(i
, 0);
4336 void GLES2DecoderImpl::RestoreAllAttributes() const {
4337 state_
.RestoreVertexAttribs();
4340 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4341 state_
.SetIgnoreCachedStateForTest(ignore
);
4344 void GLES2DecoderImpl::OnFboChanged() const {
4345 if (workarounds().restore_scissor_on_fbo_change
)
4346 state_
.fbo_binding_for_scissor_workaround_dirty_
= true;
4348 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4349 GLint bound_fbo_unsigned
= -1;
4350 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4351 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4352 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4353 surface_
->NotifyWasBound();
4357 // Called after the FBO is checked for completeness.
4358 void GLES2DecoderImpl::OnUseFramebuffer() const {
4359 if (state_
.fbo_binding_for_scissor_workaround_dirty_
) {
4360 state_
.fbo_binding_for_scissor_workaround_dirty_
= false;
4361 // The driver forgets the correct scissor when modifying the FBO binding.
4362 glScissor(state_
.scissor_x
,
4364 state_
.scissor_width
,
4365 state_
.scissor_height
);
4367 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4368 // it's unclear how this bug works.
4373 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4374 Framebuffer
* framebuffer
= NULL
;
4375 GLuint service_id
= 0;
4376 if (client_id
!= 0) {
4377 framebuffer
= GetFramebuffer(client_id
);
4379 if (!group_
->bind_generates_resource()) {
4380 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4381 "glBindFramebuffer",
4382 "id not generated by glGenFramebuffers");
4386 // It's a new id so make a framebuffer framebuffer for it.
4387 glGenFramebuffersEXT(1, &service_id
);
4388 CreateFramebuffer(client_id
, service_id
);
4389 framebuffer
= GetFramebuffer(client_id
);
4391 service_id
= framebuffer
->service_id();
4393 framebuffer
->MarkAsValid();
4395 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4397 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4398 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4401 // vmiura: This looks like dup code
4402 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4403 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4406 framebuffer_state_
.clear_state_dirty
= true;
4408 // If we are rendering to the backbuffer get the FBO id for any simulated
4410 if (framebuffer
== NULL
) {
4411 service_id
= GetBackbufferServiceId();
4414 glBindFramebufferEXT(target
, service_id
);
4418 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4419 Renderbuffer
* renderbuffer
= NULL
;
4420 GLuint service_id
= 0;
4421 if (client_id
!= 0) {
4422 renderbuffer
= GetRenderbuffer(client_id
);
4423 if (!renderbuffer
) {
4424 if (!group_
->bind_generates_resource()) {
4425 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4426 "glBindRenderbuffer",
4427 "id not generated by glGenRenderbuffers");
4431 // It's a new id so make a renderbuffer for it.
4432 glGenRenderbuffersEXT(1, &service_id
);
4433 CreateRenderbuffer(client_id
, service_id
);
4434 renderbuffer
= GetRenderbuffer(client_id
);
4436 service_id
= renderbuffer
->service_id();
4438 renderbuffer
->MarkAsValid();
4440 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4441 state_
.bound_renderbuffer
= renderbuffer
;
4442 state_
.bound_renderbuffer_valid
= true;
4443 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4446 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4447 TextureRef
* texture_ref
= NULL
;
4448 GLuint service_id
= 0;
4449 if (client_id
!= 0) {
4450 texture_ref
= GetTexture(client_id
);
4452 if (!group_
->bind_generates_resource()) {
4453 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4455 "id not generated by glGenTextures");
4459 // It's a new id so make a texture texture for it.
4460 glGenTextures(1, &service_id
);
4461 DCHECK_NE(0u, service_id
);
4462 CreateTexture(client_id
, service_id
);
4463 texture_ref
= GetTexture(client_id
);
4466 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4469 // Check the texture exists
4471 Texture
* texture
= texture_ref
->texture();
4472 // Check that we are not trying to bind it to a different target.
4473 if (texture
->target() != 0 && texture
->target() != target
) {
4474 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4476 "texture bound to more than 1 target.");
4479 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4480 if (texture
->target() == 0) {
4481 texture_manager()->SetTarget(texture_ref
, target
);
4483 glBindTexture(target
, texture
->service_id());
4485 glBindTexture(target
, 0);
4488 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4489 unit
.bind_target
= target
;
4492 unit
.bound_texture_2d
= texture_ref
;
4494 case GL_TEXTURE_CUBE_MAP
:
4495 unit
.bound_texture_cube_map
= texture_ref
;
4497 case GL_TEXTURE_EXTERNAL_OES
:
4498 unit
.bound_texture_external_oes
= texture_ref
;
4500 case GL_TEXTURE_RECTANGLE_ARB
:
4501 unit
.bound_texture_rectangle_arb
= texture_ref
;
4504 NOTREACHED(); // Validation should prevent us getting here.
4509 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4510 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4512 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4513 glDisableVertexAttribArray(index
);
4518 "glDisableVertexAttribArray", "index out of range");
4522 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4523 GLsizei numAttachments
,
4524 const GLenum
* attachments
) {
4525 if (workarounds().disable_discard_framebuffer
)
4528 Framebuffer
* framebuffer
=
4529 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4531 // Validates the attachments. If one of them fails
4532 // the whole command fails.
4533 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4535 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4537 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4538 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4539 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4544 // Marks each one of them as not cleared
4545 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4547 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4552 switch (attachments
[i
]) {
4554 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4557 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4558 case GL_STENCIL_EXT
:
4559 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4568 // If the default framebuffer is bound but we are still rendering to an
4569 // FBO, translate attachment names that refer to default framebuffer
4570 // channels to corresponding framebuffer attachments.
4571 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4572 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4573 GLenum attachment
= attachments
[i
];
4574 if (!framebuffer
&& GetBackbufferServiceId()) {
4575 switch (attachment
) {
4577 attachment
= GL_COLOR_ATTACHMENT0
;
4580 attachment
= GL_DEPTH_ATTACHMENT
;
4582 case GL_STENCIL_EXT
:
4583 attachment
= GL_STENCIL_ATTACHMENT
;
4590 translated_attachments
[i
] = attachment
;
4593 ScopedRenderTo
do_render(framebuffer
);
4594 if (feature_info_
->gl_version_info().is_es3
) {
4595 glInvalidateFramebuffer(
4596 target
, numAttachments
, translated_attachments
.get());
4598 glDiscardFramebufferEXT(
4599 target
, numAttachments
, translated_attachments
.get());
4603 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4604 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4605 glEnableVertexAttribArray(index
);
4608 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4612 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4613 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4616 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4618 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4622 if (target
== GL_TEXTURE_CUBE_MAP
) {
4623 for (int i
= 0; i
< 6; ++i
) {
4624 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4625 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4627 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4632 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
4634 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
4639 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4640 // Workaround for Mac driver bug. In the large scheme of things setting
4641 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4642 // hit so there's probably no need to make this conditional. The bug appears
4643 // to be that if the filtering mode is set to something that doesn't require
4644 // mipmaps for rendering, or is never set to something other than the default,
4645 // then glGenerateMipmap misbehaves.
4646 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4647 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
4649 glGenerateMipmapEXT(target
);
4650 if (workarounds().set_texture_filter_before_generating_mipmap
) {
4651 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
4652 texture_ref
->texture()->min_filter());
4654 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4655 if (error
== GL_NO_ERROR
) {
4656 texture_manager()->MarkMipmapsGenerated(texture_ref
);
4660 bool GLES2DecoderImpl::GetHelper(
4661 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
4662 DCHECK(num_written
);
4663 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
4665 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
4667 // Return the GL implementation's preferred format and (see below type)
4668 // if we have the GL extension that exposes this. This allows the GPU
4669 // client to use the implementation's preferred format for glReadPixels
4670 // for optimisation.
4672 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4673 // case when requested on integer/floating point buffers but which is
4674 // acceptable on GLES2 and with the GL_OES_read_format extension.
4676 // Therefore if an error occurs we swallow the error and use the
4677 // internal implementation.
4679 if (context_
->HasExtension("GL_OES_read_format")) {
4680 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4682 glGetIntegerv(pname
, params
);
4683 if (glGetError() == GL_NO_ERROR
)
4686 *params
= GLES2Util::GetPreferredGLReadPixelsFormat(
4687 GetBoundReadFrameBufferInternalFormat());
4690 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
4693 if (context_
->HasExtension("GL_OES_read_format")) {
4694 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
4696 glGetIntegerv(pname
, params
);
4697 if (glGetError() == GL_NO_ERROR
)
4700 *params
= GLES2Util::GetPreferredGLReadPixelsType(
4701 GetBoundReadFrameBufferInternalFormat(),
4702 GetBoundReadFrameBufferTextureType());
4705 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
4708 *params
= group_
->max_fragment_uniform_vectors();
4711 case GL_MAX_VARYING_VECTORS
:
4714 *params
= group_
->max_varying_vectors();
4717 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
4720 *params
= group_
->max_vertex_uniform_vectors();
4726 case GL_MAX_VIEWPORT_DIMS
:
4727 if (offscreen_target_frame_buffer_
.get()) {
4730 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4731 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
4736 case GL_MAX_SAMPLES
:
4739 params
[0] = renderbuffer_manager()->max_samples();
4742 case GL_MAX_RENDERBUFFER_SIZE
:
4745 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
4748 case GL_MAX_TEXTURE_SIZE
:
4751 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
4754 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
4757 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
4760 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
4763 params
[0] = group_
->max_color_attachments();
4766 case GL_MAX_DRAW_BUFFERS_ARB
:
4769 params
[0] = group_
->max_draw_buffers();
4776 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4777 Framebuffer
* framebuffer
=
4778 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4780 glGetFramebufferAttachmentParameterivEXT(
4781 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
4782 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
4784 v
= (back_buffer_color_format_
== GL_RGBA
? 8 : 0);
4787 glGetIntegerv(GL_ALPHA_BITS
, &v
);
4790 BoundFramebufferHasColorAttachmentWithAlpha(false) ? v
: 0;
4797 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4798 Framebuffer
* framebuffer
=
4799 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4801 glGetFramebufferAttachmentParameterivEXT(
4802 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
4803 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
4805 v
= (back_buffer_has_depth_
? 24 : 0);
4808 glGetIntegerv(GL_DEPTH_BITS
, &v
);
4810 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
4819 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4820 Framebuffer
* framebuffer
=
4821 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4823 GLenum framebuffer_enum
= 0;
4826 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
4829 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
4832 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
4835 glGetFramebufferAttachmentParameterivEXT(
4836 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
4841 glGetIntegerv(pname
, &v
);
4846 case GL_STENCIL_BITS
:
4850 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
4851 Framebuffer
* framebuffer
=
4852 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4854 glGetFramebufferAttachmentParameterivEXT(
4855 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
4856 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
4858 v
= (back_buffer_has_stencil_
? 8 : 0);
4861 glGetIntegerv(GL_STENCIL_BITS
, &v
);
4863 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
4866 case GL_COMPRESSED_TEXTURE_FORMATS
:
4867 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
4869 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4870 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
4874 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
4877 *params
= validators_
->compressed_texture_format
.GetValues().size();
4880 case GL_NUM_SHADER_BINARY_FORMATS
:
4883 *params
= validators_
->shader_binary_format
.GetValues().size();
4886 case GL_SHADER_BINARY_FORMATS
:
4887 *num_written
= validators_
->shader_binary_format
.GetValues().size();
4889 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
4890 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
4894 case GL_SHADER_COMPILER
:
4900 case GL_ARRAY_BUFFER_BINDING
:
4903 if (state_
.bound_array_buffer
.get()) {
4904 GLuint client_id
= 0;
4905 buffer_manager()->GetClientId(state_
.bound_array_buffer
->service_id(),
4907 *params
= client_id
;
4913 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
4916 if (state_
.vertex_attrib_manager
->element_array_buffer()) {
4917 GLuint client_id
= 0;
4918 buffer_manager()->GetClientId(
4919 state_
.vertex_attrib_manager
->element_array_buffer()->
4920 service_id(), &client_id
);
4921 *params
= client_id
;
4927 case GL_FRAMEBUFFER_BINDING
:
4928 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4931 Framebuffer
* framebuffer
=
4932 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4934 GLuint client_id
= 0;
4935 framebuffer_manager()->GetClientId(
4936 framebuffer
->service_id(), &client_id
);
4937 *params
= client_id
;
4943 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
4946 Framebuffer
* framebuffer
=
4947 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
4949 GLuint client_id
= 0;
4950 framebuffer_manager()->GetClientId(
4951 framebuffer
->service_id(), &client_id
);
4952 *params
= client_id
;
4958 case GL_RENDERBUFFER_BINDING
:
4961 Renderbuffer
* renderbuffer
=
4962 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
4964 *params
= renderbuffer
->client_id();
4970 case GL_CURRENT_PROGRAM
:
4973 if (state_
.current_program
.get()) {
4974 GLuint client_id
= 0;
4975 program_manager()->GetClientId(
4976 state_
.current_program
->service_id(), &client_id
);
4977 *params
= client_id
;
4983 case GL_VERTEX_ARRAY_BINDING_OES
:
4986 if (state_
.vertex_attrib_manager
.get() !=
4987 state_
.default_vertex_attrib_manager
.get()) {
4988 GLuint client_id
= 0;
4989 vertex_array_manager_
->GetClientId(
4990 state_
.vertex_attrib_manager
->service_id(), &client_id
);
4991 *params
= client_id
;
4997 case GL_TEXTURE_BINDING_2D
:
5000 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5001 if (unit
.bound_texture_2d
.get()) {
5002 *params
= unit
.bound_texture_2d
->client_id();
5008 case GL_TEXTURE_BINDING_CUBE_MAP
:
5011 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5012 if (unit
.bound_texture_cube_map
.get()) {
5013 *params
= unit
.bound_texture_cube_map
->client_id();
5019 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5022 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5023 if (unit
.bound_texture_external_oes
.get()) {
5024 *params
= unit
.bound_texture_external_oes
->client_id();
5030 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5033 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5034 if (unit
.bound_texture_rectangle_arb
.get()) {
5035 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5041 case GL_UNPACK_FLIP_Y_CHROMIUM
:
5044 params
[0] = unpack_flip_y_
;
5047 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
5050 params
[0] = unpack_premultiply_alpha_
;
5053 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
5056 params
[0] = unpack_unpremultiply_alpha_
;
5059 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5062 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5066 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5067 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5070 Framebuffer
* framebuffer
=
5071 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5073 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5074 } else { // backbuffer
5075 if (pname
== GL_DRAW_BUFFER0_ARB
)
5076 params
[0] = group_
->draw_buffer();
5078 params
[0] = GL_NONE
;
5083 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5088 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5089 GLenum pname
, GLsizei
* num_values
) {
5090 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5093 return GetHelper(pname
, NULL
, num_values
);
5096 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5097 if (GL_MAX_SAMPLES
== pname
&&
5098 features().use_img_for_multisampled_render_to_texture
) {
5099 return GL_MAX_SAMPLES_IMG
;
5104 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5106 GLsizei num_written
= 0;
5107 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5108 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5109 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5110 GetHelper(pname
, values
.get(), &num_written
);
5112 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5113 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5116 pname
= AdjustGetPname(pname
);
5117 glGetBooleanv(pname
, params
);
5121 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5123 GLsizei num_written
= 0;
5124 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5125 if (GetHelper(pname
, NULL
, &num_written
)) {
5126 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5127 GetHelper(pname
, values
.get(), &num_written
);
5128 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5129 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5132 pname
= AdjustGetPname(pname
);
5133 glGetFloatv(pname
, params
);
5138 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5140 GLsizei num_written
;
5141 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5142 !GetHelper(pname
, params
, &num_written
)) {
5143 pname
= AdjustGetPname(pname
);
5144 glGetIntegerv(pname
, params
);
5148 void GLES2DecoderImpl::DoGetProgramiv(
5149 GLuint program_id
, GLenum pname
, GLint
* params
) {
5150 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5154 program
->GetProgramiv(pname
, params
);
5157 void GLES2DecoderImpl::DoGetBufferParameteriv(
5158 GLenum target
, GLenum pname
, GLint
* params
) {
5159 // Just delegate it. Some validation is actually done before this.
5160 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5161 &state_
, target
, pname
, params
);
5164 void GLES2DecoderImpl::DoBindAttribLocation(
5165 GLuint program_id
, GLuint index
, const char* name
) {
5166 if (!StringIsValidForGLES(name
)) {
5168 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5171 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5173 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5176 if (index
>= group_
->max_vertex_attribs()) {
5178 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5181 Program
* program
= GetProgramInfoNotShader(
5182 program_id
, "glBindAttribLocation");
5186 // At this point, the program's shaders may not be translated yet,
5187 // therefore, we may not find the hashed attribute name.
5188 // glBindAttribLocation call with original name is useless.
5189 // So instead, we should simply cache the binding, and then call
5190 // Program::ExecuteBindAttribLocationCalls() right before link.
5191 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5192 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5193 glBindAttribLocation(program
->service_id(), index
, name
);
5196 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5197 uint32 immediate_data_size
,
5198 const void* cmd_data
) {
5199 const gles2::cmds::BindAttribLocationBucket
& c
=
5200 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5201 GLuint program
= static_cast<GLuint
>(c
.program
);
5202 GLuint index
= static_cast<GLuint
>(c
.index
);
5203 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5204 if (!bucket
|| bucket
->size() == 0) {
5205 return error::kInvalidArguments
;
5207 std::string name_str
;
5208 if (!bucket
->GetAsString(&name_str
)) {
5209 return error::kInvalidArguments
;
5211 DoBindAttribLocation(program
, index
, name_str
.c_str());
5212 return error::kNoError
;
5215 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5216 GLuint program_id
, GLint location
, const char* name
) {
5217 if (!StringIsValidForGLES(name
)) {
5220 "glBindUniformLocationCHROMIUM", "Invalid character");
5223 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5225 GL_INVALID_OPERATION
,
5226 "glBindUniformLocationCHROMIUM", "reserved prefix");
5229 if (location
< 0 || static_cast<uint32
>(location
) >=
5230 (group_
->max_fragment_uniform_vectors() +
5231 group_
->max_vertex_uniform_vectors()) * 4) {
5234 "glBindUniformLocationCHROMIUM", "location out of range");
5237 Program
* program
= GetProgramInfoNotShader(
5238 program_id
, "glBindUniformLocationCHROMIUM");
5242 if (!program
->SetUniformLocationBinding(name
, location
)) {
5245 "glBindUniformLocationCHROMIUM", "location out of range");
5249 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5250 uint32 immediate_data_size
,
5251 const void* cmd_data
) {
5252 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5253 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5255 GLuint program
= static_cast<GLuint
>(c
.program
);
5256 GLint location
= static_cast<GLint
>(c
.location
);
5257 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5258 if (!bucket
|| bucket
->size() == 0) {
5259 return error::kInvalidArguments
;
5261 std::string name_str
;
5262 if (!bucket
->GetAsString(&name_str
)) {
5263 return error::kInvalidArguments
;
5265 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5266 return error::kNoError
;
5269 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5270 const void* cmd_data
) {
5271 const gles2::cmds::DeleteShader
& c
=
5272 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5273 GLuint client_id
= c
.shader
;
5275 Shader
* shader
= GetShader(client_id
);
5277 if (!shader
->IsDeleted()) {
5278 shader_manager()->Delete(shader
);
5281 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5284 return error::kNoError
;
5287 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5288 const void* cmd_data
) {
5289 const gles2::cmds::DeleteProgram
& c
=
5290 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5291 GLuint client_id
= c
.program
;
5293 Program
* program
= GetProgram(client_id
);
5295 if (!program
->IsDeleted()) {
5296 program_manager()->MarkAsDeleted(shader_manager(), program
);
5300 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5303 return error::kNoError
;
5306 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5307 DCHECK(!ShouldDeferDraws());
5308 if (CheckBoundFramebuffersValid("glClear")) {
5310 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5311 if (workarounds().gl_clear_broken
) {
5312 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5314 if (!BoundFramebufferHasDepthAttachment())
5315 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5316 if (!BoundFramebufferHasStencilAttachment())
5317 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5318 clear_framebuffer_blit_
->ClearFramebuffer(
5319 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5320 state_
.color_clear_green
, state_
.color_clear_blue
,
5321 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5322 return error::kNoError
;
5326 return error::kNoError
;
5329 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5330 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5331 GLuint client_renderbuffer_id
) {
5332 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5335 GL_INVALID_OPERATION
,
5336 "glFramebufferRenderbuffer", "no framebuffer bound");
5339 GLuint service_id
= 0;
5340 Renderbuffer
* renderbuffer
= NULL
;
5341 if (client_renderbuffer_id
) {
5342 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5343 if (!renderbuffer
) {
5345 GL_INVALID_OPERATION
,
5346 "glFramebufferRenderbuffer", "unknown renderbuffer");
5349 service_id
= renderbuffer
->service_id();
5351 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5352 glFramebufferRenderbufferEXT(
5353 target
, attachment
, renderbuffertarget
, service_id
);
5354 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5355 if (error
== GL_NO_ERROR
) {
5356 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5358 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5359 framebuffer_state_
.clear_state_dirty
= true;
5364 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5365 if (SetCapabilityState(cap
, false)) {
5370 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5371 if (SetCapabilityState(cap
, true)) {
5376 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5377 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5378 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5379 glDepthRange(znear
, zfar
);
5382 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5383 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5384 state_
.sample_coverage_invert
= (invert
!= 0);
5385 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5388 // Assumes framebuffer is complete.
5389 void GLES2DecoderImpl::ClearUnclearedAttachments(
5390 GLenum target
, Framebuffer
* framebuffer
) {
5391 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5392 // bind this to the DRAW point, clear then bind back to READ
5393 // TODO(gman): I don't think there is any guarantee that an FBO that
5394 // is complete on the READ attachment will be complete as a DRAW
5396 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
5397 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5399 GLbitfield clear_bits
= 0;
5400 if (framebuffer
->HasUnclearedColorAttachments()) {
5403 (GLES2Util::GetChannelsForFormat(
5404 framebuffer
->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f
:
5406 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5407 clear_bits
|= GL_COLOR_BUFFER_BIT
;
5408 if (feature_info_
->feature_flags().ext_draw_buffers
)
5409 framebuffer
->PrepareDrawBuffersForClear();
5412 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
5413 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5415 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
5416 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
5417 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
5420 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
5421 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
5423 state_
.SetDeviceDepthMask(GL_TRUE
);
5424 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
5427 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5428 glClear(clear_bits
);
5430 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
5431 feature_info_
->feature_flags().ext_draw_buffers
)
5432 framebuffer
->RestoreDrawBuffersAfterClear();
5434 framebuffer_manager()->MarkAttachmentsAsCleared(
5435 framebuffer
, renderbuffer_manager(), texture_manager());
5437 RestoreClearState();
5439 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5440 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
5441 Framebuffer
* draw_framebuffer
=
5442 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5443 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
5444 GetBackbufferServiceId();
5445 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
5449 void GLES2DecoderImpl::RestoreClearState() {
5450 framebuffer_state_
.clear_state_dirty
= true;
5452 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
5453 state_
.color_clear_alpha
);
5454 glClearStencil(state_
.stencil_clear
);
5455 glClearDepth(state_
.depth_clear
);
5456 if (state_
.enable_flags
.scissor_test
) {
5457 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5461 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
5462 Framebuffer
* framebuffer
=
5463 GetFramebufferInfoForTarget(target
);
5465 return GL_FRAMEBUFFER_COMPLETE
;
5467 GLenum completeness
= framebuffer
->IsPossiblyComplete();
5468 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
5469 return completeness
;
5471 return framebuffer
->GetStatus(texture_manager(), target
);
5474 void GLES2DecoderImpl::DoFramebufferTexture2D(
5475 GLenum target
, GLenum attachment
, GLenum textarget
,
5476 GLuint client_texture_id
, GLint level
) {
5477 DoFramebufferTexture2DCommon(
5478 "glFramebufferTexture2D", target
, attachment
,
5479 textarget
, client_texture_id
, level
, 0);
5482 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5483 GLenum target
, GLenum attachment
, GLenum textarget
,
5484 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5485 DoFramebufferTexture2DCommon(
5486 "glFramebufferTexture2DMultisample", target
, attachment
,
5487 textarget
, client_texture_id
, level
, samples
);
5490 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5491 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
5492 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
5493 if (samples
> renderbuffer_manager()->max_samples()) {
5496 "glFramebufferTexture2DMultisample", "samples too large");
5499 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5502 GL_INVALID_OPERATION
,
5503 name
, "no framebuffer bound.");
5506 GLuint service_id
= 0;
5507 TextureRef
* texture_ref
= NULL
;
5508 if (client_texture_id
) {
5509 texture_ref
= GetTexture(client_texture_id
);
5512 GL_INVALID_OPERATION
,
5513 name
, "unknown texture_ref");
5516 service_id
= texture_ref
->service_id();
5519 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
5522 name
, "level out of range");
5527 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5529 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
5531 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
5533 if (features().use_img_for_multisampled_render_to_texture
) {
5534 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
5535 service_id
, level
, samples
);
5537 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
5538 service_id
, level
, samples
);
5541 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
5542 if (error
== GL_NO_ERROR
) {
5543 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
5546 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5547 framebuffer_state_
.clear_state_dirty
= true;
5551 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
5556 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5557 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
5558 GLint level
, GLint layer
) {
5559 // TODO(zmo): Unsafe ES3 API, missing states update.
5560 GLuint service_id
= 0;
5561 TextureRef
* texture_ref
= NULL
;
5562 if (client_texture_id
) {
5563 texture_ref
= GetTexture(client_texture_id
);
5566 GL_INVALID_OPERATION
,
5567 "glFramebufferTextureLayer", "unknown texture_ref");
5570 service_id
= texture_ref
->service_id();
5572 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
5575 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5576 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
5577 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5580 GL_INVALID_OPERATION
,
5581 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5584 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
5585 const Framebuffer::Attachment
* attachment_object
=
5586 framebuffer
->GetAttachment(attachment
);
5587 *params
= attachment_object
? attachment_object
->object_name() : 0;
5589 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
5590 features().use_img_for_multisampled_render_to_texture
) {
5591 pname
= GL_TEXTURE_SAMPLES_IMG
;
5593 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
5597 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5598 GLenum target
, GLenum pname
, GLint
* params
) {
5599 Renderbuffer
* renderbuffer
=
5600 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5601 if (!renderbuffer
) {
5603 GL_INVALID_OPERATION
,
5604 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5608 EnsureRenderbufferBound();
5610 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
5611 *params
= renderbuffer
->internal_format();
5613 case GL_RENDERBUFFER_WIDTH
:
5614 *params
= renderbuffer
->width();
5616 case GL_RENDERBUFFER_HEIGHT
:
5617 *params
= renderbuffer
->height();
5619 case GL_RENDERBUFFER_SAMPLES_EXT
:
5620 if (features().use_img_for_multisampled_render_to_texture
) {
5621 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
5624 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
5628 glGetRenderbufferParameterivEXT(target
, pname
, params
);
5633 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5634 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
5635 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
5636 GLbitfield mask
, GLenum filter
) {
5637 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5639 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5643 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5644 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5645 BlitFramebufferHelper(
5646 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5647 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
5648 state_
.enable_flags
.scissor_test
);
5651 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5652 if (!state_
.bound_renderbuffer_valid
) {
5653 state_
.bound_renderbuffer_valid
= true;
5654 glBindRenderbufferEXT(GL_RENDERBUFFER
,
5655 state_
.bound_renderbuffer
.get()
5656 ? state_
.bound_renderbuffer
->service_id()
5661 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5662 const FeatureInfo
* feature_info
,
5665 GLenum internal_format
,
5668 // TODO(sievers): This could be resolved at the GL binding level, but the
5669 // binding process is currently a bit too 'brute force'.
5670 if (feature_info
->gl_version_info().is_angle
) {
5671 glRenderbufferStorageMultisampleANGLE(
5672 target
, samples
, internal_format
, width
, height
);
5673 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
5674 glRenderbufferStorageMultisample(
5675 target
, samples
, internal_format
, width
, height
);
5677 glRenderbufferStorageMultisampleEXT(
5678 target
, samples
, internal_format
, width
, height
);
5682 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
5692 // TODO(sievers): This could be resolved at the GL binding level, but the
5693 // binding process is currently a bit too 'brute force'.
5694 if (feature_info_
->gl_version_info().is_angle
) {
5695 glBlitFramebufferANGLE(
5696 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5697 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
5699 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5701 glBlitFramebufferEXT(
5702 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
5706 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5708 GLenum internalformat
,
5711 if (samples
> renderbuffer_manager()->max_samples()) {
5714 "glRenderbufferStorageMultisample", "samples too large");
5718 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5719 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5722 "glRenderbufferStorageMultisample", "dimensions too large");
5726 uint32 estimated_size
= 0;
5727 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5728 width
, height
, samples
, internalformat
, &estimated_size
)) {
5731 "glRenderbufferStorageMultisample", "dimensions too large");
5735 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5738 "glRenderbufferStorageMultisample", "out of memory");
5745 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5746 GLenum target
, GLsizei samples
, GLenum internalformat
,
5747 GLsizei width
, GLsizei height
) {
5748 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5749 if (!renderbuffer
) {
5750 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5751 "glRenderbufferStorageMultisampleCHROMIUM",
5752 "no renderbuffer bound");
5756 if (!ValidateRenderbufferStorageMultisample(
5757 samples
, internalformat
, width
, height
)) {
5761 EnsureRenderbufferBound();
5762 GLenum impl_format
=
5763 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5765 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5766 "glRenderbufferStorageMultisampleCHROMIUM");
5767 RenderbufferStorageMultisampleHelper(
5768 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
5770 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5771 if (error
== GL_NO_ERROR
) {
5772 if (workarounds().validate_multisample_buffer_allocation
) {
5773 if (!VerifyMultisampleRenderbufferIntegrity(
5774 renderbuffer
->service_id(), impl_format
)) {
5777 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5782 // TODO(gman): If renderbuffers tracked which framebuffers they were
5783 // attached to we could just mark those framebuffers as not complete.
5784 framebuffer_manager()->IncFramebufferStateChangeCount();
5785 renderbuffer_manager()->SetInfo(
5786 renderbuffer
, samples
, internalformat
, width
, height
);
5790 // This is the handler for multisampled_render_to_texture extensions.
5791 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5792 GLenum target
, GLsizei samples
, GLenum internalformat
,
5793 GLsizei width
, GLsizei height
) {
5794 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5795 if (!renderbuffer
) {
5796 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
5797 "glRenderbufferStorageMultisampleEXT",
5798 "no renderbuffer bound");
5802 if (!ValidateRenderbufferStorageMultisample(
5803 samples
, internalformat
, width
, height
)) {
5807 EnsureRenderbufferBound();
5808 GLenum impl_format
=
5809 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5811 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5812 if (features().use_img_for_multisampled_render_to_texture
) {
5813 glRenderbufferStorageMultisampleIMG(
5814 target
, samples
, impl_format
, width
, height
);
5816 glRenderbufferStorageMultisampleEXT(
5817 target
, samples
, impl_format
, width
, height
);
5819 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5820 if (error
== GL_NO_ERROR
) {
5821 // TODO(gman): If renderbuffers tracked which framebuffers they were
5822 // attached to we could just mark those framebuffers as not complete.
5823 framebuffer_manager()->IncFramebufferStateChangeCount();
5824 renderbuffer_manager()->SetInfo(
5825 renderbuffer
, samples
, internalformat
, width
, height
);
5829 // This function validates the allocation of a multisampled renderbuffer
5830 // by clearing it to a key color, blitting the contents to a texture, and
5831 // reading back the color to ensure it matches the key.
5832 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5833 GLuint renderbuffer
, GLenum format
) {
5835 // Only validate color buffers.
5836 // These formats have been selected because they are very common or are known
5837 // to be used by the WebGL backbuffer. If problems are observed with other
5838 // color formats they can be added here.
5849 GLint draw_framebuffer
, read_framebuffer
;
5851 // Cache framebuffer and texture bindings.
5852 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
5853 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
5855 if (!validation_texture_
) {
5856 GLint bound_texture
;
5857 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
5859 // Create additional resources needed for the verification.
5860 glGenTextures(1, &validation_texture_
);
5861 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
5862 glGenFramebuffersEXT(1, &validation_fbo_
);
5864 // Texture only needs to be 1x1.
5865 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
5866 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 1, 1, 0, GL_RGB
,
5867 GL_UNSIGNED_BYTE
, NULL
);
5869 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5870 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5871 GL_TEXTURE_2D
, validation_texture_
, 0);
5873 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
5876 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5877 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5878 GL_RENDERBUFFER
, renderbuffer
);
5880 // Cache current state and reset it to the values we require.
5881 GLboolean scissor_enabled
= false;
5882 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
5883 if (scissor_enabled
)
5884 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
5886 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
5887 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
5888 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5890 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
5891 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
5892 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
5894 // Clear the buffer to the desired key color.
5895 glClear(GL_COLOR_BUFFER_BIT
);
5897 // Blit from the multisample buffer to a standard texture.
5898 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
5899 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
5901 BlitFramebufferHelper(
5902 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
5904 // Read a pixel from the buffer.
5905 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
5907 unsigned char pixel
[3] = {0, 0, 0};
5908 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
5910 // Detach the renderbuffer.
5911 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
5912 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5913 GL_RENDERBUFFER
, 0);
5915 // Restore cached state.
5916 if (scissor_enabled
)
5917 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
5919 state_
.SetDeviceColorMask(
5920 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
5921 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
5922 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
5923 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
5925 // Return true if the pixel matched the desired key color.
5926 return (pixel
[0] == 0xFF &&
5931 void GLES2DecoderImpl::DoRenderbufferStorage(
5932 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
5933 Renderbuffer
* renderbuffer
=
5934 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5935 if (!renderbuffer
) {
5937 GL_INVALID_OPERATION
,
5938 "glRenderbufferStorage", "no renderbuffer bound");
5942 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
5943 height
> renderbuffer_manager()->max_renderbuffer_size()) {
5945 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
5949 uint32 estimated_size
= 0;
5950 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5951 width
, height
, 1, internalformat
, &estimated_size
)) {
5953 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
5957 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
5959 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
5963 EnsureRenderbufferBound();
5964 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5965 glRenderbufferStorageEXT(
5967 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5971 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5972 if (error
== GL_NO_ERROR
) {
5973 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5974 // we could just mark those framebuffers as not complete.
5975 framebuffer_manager()->IncFramebufferStateChangeCount();
5976 renderbuffer_manager()->SetInfo(
5977 renderbuffer
, 1, internalformat
, width
, height
);
5981 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
5982 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5983 Program
* program
= GetProgramInfoNotShader(
5984 program_id
, "glLinkProgram");
5989 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
5990 if (program
->Link(shader_manager(),
5991 workarounds().count_all_in_varyings_packing
?
5992 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
5993 shader_cache_callback_
)) {
5994 if (program
== state_
.current_program
.get()) {
5995 if (workarounds().use_current_program_after_successful_link
)
5996 glUseProgram(program
->service_id());
5997 if (workarounds().clear_uniforms_before_first_program_use
)
5998 program_manager()->ClearUniforms(program
);
6002 // LinkProgram can be very slow. Exit command processing to allow for
6003 // context preemption and GPU watchdog checks.
6004 ExitCommandProcessingEarly();
6007 void GLES2DecoderImpl::DoSamplerParameterfv(
6008 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6010 glSamplerParameterf(sampler
, pname
, params
[0]);
6013 void GLES2DecoderImpl::DoSamplerParameteriv(
6014 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6016 glSamplerParameteri(sampler
, pname
, params
[0]);
6019 void GLES2DecoderImpl::DoTexParameterf(
6020 GLenum target
, GLenum pname
, GLfloat param
) {
6021 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6028 texture_manager()->SetParameterf(
6029 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6032 void GLES2DecoderImpl::DoTexParameteri(
6033 GLenum target
, GLenum pname
, GLint param
) {
6034 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6037 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6041 texture_manager()->SetParameteri(
6042 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6045 void GLES2DecoderImpl::DoTexParameterfv(
6046 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6047 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6050 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6054 texture_manager()->SetParameterf(
6055 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6058 void GLES2DecoderImpl::DoTexParameteriv(
6059 GLenum target
, GLenum pname
, const GLint
* params
) {
6060 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6064 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6068 texture_manager()->SetParameteri(
6069 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6072 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6073 if (!state_
.bound_valuebuffer
.get()) {
6074 // There is no valuebuffer bound
6075 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6076 "no valuebuffer in use");
6082 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6083 GLenum subscription
,
6084 const char* function_name
) {
6085 if (!CheckCurrentValuebuffer(function_name
)) {
6088 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6089 // The valuebuffer is not subscribed to the target
6090 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6091 "valuebuffer is not subscribed");
6097 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6098 GLenum subscription
,
6099 const char* function_name
) {
6100 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6103 GLint real_location
= -1;
6104 GLint array_index
= -1;
6105 const Program::UniformInfo
* info
=
6106 state_
.current_program
->GetUniformInfoByFakeLocation(
6107 location
, &real_location
, &array_index
);
6109 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6112 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6113 info
->accepts_api_type
) == 0) {
6114 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6115 "wrong type for subscription");
6121 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6122 if (!state_
.current_program
.get()) {
6123 // The program does not exist.
6125 GL_INVALID_OPERATION
, function_name
, "no program in use");
6128 if (!state_
.current_program
->InUse()) {
6130 GL_INVALID_OPERATION
, function_name
, "program not linked");
6136 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6137 GLint location
, const char* function_name
) {
6138 if (!CheckCurrentProgram(function_name
)) {
6141 return location
!= -1;
6144 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6145 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6148 const Framebuffer::Attachment
* attachment
=
6149 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6153 DCHECK(state_
.current_program
.get());
6154 const Program::SamplerIndices
& sampler_indices
=
6155 state_
.current_program
->sampler_indices();
6156 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6157 const Program::UniformInfo
* uniform_info
=
6158 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6159 DCHECK(uniform_info
);
6160 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6162 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6163 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6164 if (texture_unit_index
>= state_
.texture_units
.size())
6166 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6167 TextureRef
* texture_ref
=
6168 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6169 if (attachment
->IsTexture(texture_ref
))
6176 bool GLES2DecoderImpl::CheckUniformForApiType(
6177 const Program::UniformInfo
* info
,
6178 const char* function_name
,
6179 Program::UniformApiType api_type
) {
6181 if ((api_type
& info
->accepts_api_type
) == 0) {
6182 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6183 "wrong uniform function for type");
6189 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6190 GLint fake_location
,
6191 const char* function_name
,
6192 Program::UniformApiType api_type
,
6193 GLint
* real_location
,
6198 DCHECK(real_location
);
6200 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6203 GLint array_index
= -1;
6204 const Program::UniformInfo
* info
=
6205 state_
.current_program
->GetUniformInfoByFakeLocation(
6206 fake_location
, real_location
, &array_index
);
6209 GL_INVALID_OPERATION
, function_name
, "unknown location");
6212 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6215 if (*count
> 1 && !info
->is_array
) {
6217 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6220 *count
= std::min(info
->size
- array_index
, *count
);
6228 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6231 GLint real_location
= -1;
6232 if (!PrepForSetUniformByLocation(fake_location
,
6234 Program::kUniform1i
,
6240 if (!state_
.current_program
->SetSamplers(
6241 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6243 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6246 glUniform1i(real_location
, v0
);
6249 void GLES2DecoderImpl::DoUniform1iv(
6250 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6252 GLint real_location
= -1;
6253 if (!PrepForSetUniformByLocation(fake_location
,
6255 Program::kUniform1i
,
6261 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6262 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6263 if (!state_
.current_program
->SetSamplers(
6264 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6266 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6270 glUniform1iv(real_location
, count
, value
);
6273 void GLES2DecoderImpl::DoUniform1fv(
6274 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6276 GLint real_location
= -1;
6277 if (!PrepForSetUniformByLocation(fake_location
,
6279 Program::kUniform1f
,
6285 if (type
== GL_BOOL
) {
6286 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
6287 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
6288 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6290 DoUniform1iv(real_location
, count
, temp
.get());
6292 glUniform1fv(real_location
, count
, value
);
6296 void GLES2DecoderImpl::DoUniform2fv(
6297 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6299 GLint real_location
= -1;
6300 if (!PrepForSetUniformByLocation(fake_location
,
6302 Program::kUniform2f
,
6308 if (type
== GL_BOOL_VEC2
) {
6309 GLsizei num_values
= count
* 2;
6310 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6311 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6312 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6314 glUniform2iv(real_location
, count
, temp
.get());
6316 glUniform2fv(real_location
, count
, value
);
6320 void GLES2DecoderImpl::DoUniform3fv(
6321 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6323 GLint real_location
= -1;
6324 if (!PrepForSetUniformByLocation(fake_location
,
6326 Program::kUniform3f
,
6332 if (type
== GL_BOOL_VEC3
) {
6333 GLsizei num_values
= count
* 3;
6334 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6335 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6336 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6338 glUniform3iv(real_location
, count
, temp
.get());
6340 glUniform3fv(real_location
, count
, value
);
6344 void GLES2DecoderImpl::DoUniform4fv(
6345 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6347 GLint real_location
= -1;
6348 if (!PrepForSetUniformByLocation(fake_location
,
6350 Program::kUniform4f
,
6356 if (type
== GL_BOOL_VEC4
) {
6357 GLsizei num_values
= count
* 4;
6358 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
6359 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
6360 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
6362 glUniform4iv(real_location
, count
, temp
.get());
6364 glUniform4fv(real_location
, count
, value
);
6368 void GLES2DecoderImpl::DoUniform2iv(
6369 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6371 GLint real_location
= -1;
6372 if (!PrepForSetUniformByLocation(fake_location
,
6374 Program::kUniform2i
,
6380 glUniform2iv(real_location
, count
, value
);
6383 void GLES2DecoderImpl::DoUniform3iv(
6384 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6386 GLint real_location
= -1;
6387 if (!PrepForSetUniformByLocation(fake_location
,
6389 Program::kUniform3i
,
6395 glUniform3iv(real_location
, count
, value
);
6398 void GLES2DecoderImpl::DoUniform4iv(
6399 GLint fake_location
, GLsizei count
, const GLint
* value
) {
6401 GLint real_location
= -1;
6402 if (!PrepForSetUniformByLocation(fake_location
,
6404 Program::kUniform4i
,
6410 glUniform4iv(real_location
, count
, value
);
6413 void GLES2DecoderImpl::DoUniformMatrix2fv(
6414 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6415 const GLfloat
* value
) {
6417 GLint real_location
= -1;
6418 if (!PrepForSetUniformByLocation(fake_location
,
6419 "glUniformMatrix2fv",
6420 Program::kUniformMatrix2f
,
6426 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
6429 void GLES2DecoderImpl::DoUniformMatrix3fv(
6430 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6431 const GLfloat
* value
) {
6433 GLint real_location
= -1;
6434 if (!PrepForSetUniformByLocation(fake_location
,
6435 "glUniformMatrix3fv",
6436 Program::kUniformMatrix3f
,
6442 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
6445 void GLES2DecoderImpl::DoUniformMatrix4fv(
6446 GLint fake_location
, GLsizei count
, GLboolean transpose
,
6447 const GLfloat
* value
) {
6449 GLint real_location
= -1;
6450 if (!PrepForSetUniformByLocation(fake_location
,
6451 "glUniformMatrix4fv",
6452 Program::kUniformMatrix4f
,
6458 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
6461 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
6462 GLuint service_id
= 0;
6463 Program
* program
= NULL
;
6465 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
6469 if (!program
->IsValid()) {
6470 // Program was not linked successfully. (ie, glLinkProgram)
6472 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
6475 service_id
= program
->service_id();
6477 if (state_
.current_program
.get()) {
6478 program_manager()->UnuseProgram(shader_manager(),
6479 state_
.current_program
.get());
6481 state_
.current_program
= program
;
6482 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
6483 glUseProgram(service_id
);
6484 if (state_
.current_program
.get()) {
6485 program_manager()->UseProgram(state_
.current_program
.get());
6486 if (workarounds().clear_uniforms_before_first_program_use
)
6487 program_manager()->ClearUniforms(program
);
6491 void GLES2DecoderImpl::RenderWarning(
6492 const char* filename
, int line
, const std::string
& msg
) {
6493 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
6496 void GLES2DecoderImpl::PerformanceWarning(
6497 const char* filename
, int line
, const std::string
& msg
) {
6498 logger_
.LogMessage(filename
, line
,
6499 std::string("PERFORMANCE WARNING: ") + msg
);
6502 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6503 Texture
* texture
, GLenum textarget
) {
6504 // Image is already in use if texture is attached to a framebuffer.
6505 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6506 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6508 ScopedGLErrorSuppressor
suppressor(
6509 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6511 glBindTexture(textarget
, texture
->service_id());
6512 image
->WillUseTexImage();
6513 RestoreCurrentTextureBindings(&state_
, textarget
);
6518 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6519 Texture
* texture
, GLenum textarget
) {
6520 // Image is still in use if texture is attached to a framebuffer.
6521 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
6522 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6524 ScopedGLErrorSuppressor
suppressor(
6525 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6527 glBindTexture(textarget
, texture
->service_id());
6528 image
->DidUseTexImage();
6529 RestoreCurrentTextureBindings(&state_
, textarget
);
6534 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6535 DCHECK(state_
.current_program
.get());
6536 if (!texture_manager()->HaveUnrenderableTextures() &&
6537 !texture_manager()->HaveImages()) {
6541 bool textures_set
= false;
6542 const Program::SamplerIndices
& sampler_indices
=
6543 state_
.current_program
->sampler_indices();
6544 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6545 const Program::UniformInfo
* uniform_info
=
6546 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6547 DCHECK(uniform_info
);
6548 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6549 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6550 if (texture_unit_index
< state_
.texture_units
.size()) {
6551 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6552 TextureRef
* texture_ref
=
6553 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6554 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
6555 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6556 textures_set
= true;
6557 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6560 texture_manager()->black_texture_id(uniform_info
->type
));
6562 LOCAL_RENDER_WARNING(
6563 std::string("there is no texture bound to the unit ") +
6564 base::IntToString(texture_unit_index
));
6566 LOCAL_RENDER_WARNING(
6567 std::string("texture bound to texture unit ") +
6568 base::IntToString(texture_unit_index
) +
6569 " is not renderable. It maybe non-power-of-2 and have"
6570 " incompatible texture filtering.");
6575 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
6576 Texture
* texture
= texture_ref
->texture();
6577 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
6578 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6579 ScopedGLErrorSuppressor
suppressor(
6580 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6581 textures_set
= true;
6582 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6583 image
->WillUseTexImage();
6588 // else: should this be an error?
6591 return !textures_set
;
6594 void GLES2DecoderImpl::RestoreStateForTextures() {
6595 DCHECK(state_
.current_program
.get());
6596 const Program::SamplerIndices
& sampler_indices
=
6597 state_
.current_program
->sampler_indices();
6598 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6599 const Program::UniformInfo
* uniform_info
=
6600 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6601 DCHECK(uniform_info
);
6602 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6603 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6604 if (texture_unit_index
< state_
.texture_units
.size()) {
6605 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6606 TextureRef
* texture_ref
=
6607 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6608 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
6609 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6610 // Get the texture_ref info that was previously bound here.
6611 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
6612 ? texture_unit
.bound_texture_2d
.get()
6613 : texture_unit
.bound_texture_cube_map
.get();
6614 glBindTexture(texture_unit
.bind_target
,
6615 texture_ref
? texture_ref
->service_id() : 0);
6619 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
6620 Texture
* texture
= texture_ref
->texture();
6621 gfx::GLImage
* image
=
6622 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
6623 if (image
&& !texture
->IsAttachedToFramebuffer()) {
6624 ScopedGLErrorSuppressor
suppressor(
6625 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6626 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
6627 image
->DidUseTexImage();
6634 // Set the active texture back to whatever the user had it as.
6635 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
6638 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6639 // Only check if there are some uncleared textures.
6640 if (!texture_manager()->HaveUnsafeTextures()) {
6644 // 1: Check all textures we are about to render with.
6645 if (state_
.current_program
.get()) {
6646 const Program::SamplerIndices
& sampler_indices
=
6647 state_
.current_program
->sampler_indices();
6648 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6649 const Program::UniformInfo
* uniform_info
=
6650 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6651 DCHECK(uniform_info
);
6652 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6653 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6654 if (texture_unit_index
< state_
.texture_units
.size()) {
6655 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6656 TextureRef
* texture_ref
=
6657 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
6658 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
6659 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
6670 bool GLES2DecoderImpl::IsDrawValid(
6671 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
6672 GLsizei primcount
) {
6673 DCHECK(instanced
|| primcount
== 1);
6675 // NOTE: We specifically do not check current_program->IsValid() because
6676 // it could never be invalid since glUseProgram would have failed. While
6677 // glLinkProgram could later mark the program as invalid the previous
6678 // valid program will still function if it is still the current program.
6679 if (!state_
.current_program
.get()) {
6680 // The program does not exist.
6681 // But GL says no ERROR.
6682 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6686 if (CheckDrawingFeedbackLoops()) {
6688 GL_INVALID_OPERATION
, function_name
,
6689 "Source and destination textures of the draw are the same.");
6693 return state_
.vertex_attrib_manager
6694 ->ValidateBindings(function_name
,
6696 feature_info_
.get(),
6697 state_
.current_program
.get(),
6698 max_vertex_accessed
,
6703 bool GLES2DecoderImpl::SimulateAttrib0(
6704 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
6708 if (feature_info_
->gl_version_info().BehavesLikeGLES())
6711 const VertexAttrib
* attrib
=
6712 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
6713 // If it's enabled or it's not used then we don't need to do anything.
6714 bool attrib_0_used
=
6715 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
6716 if (attrib
->enabled() && attrib_0_used
) {
6720 // Make a buffer with a single repeated vec4 value enough to
6721 // simulate the constant value that is supposed to be here.
6722 // This is required to emulate GLES2 on GL.
6723 GLuint num_vertices
= max_vertex_accessed
+ 1;
6724 uint32 size_needed
= 0;
6726 if (num_vertices
== 0 ||
6727 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4
), &size_needed
) ||
6728 size_needed
> 0x7FFFFFFFU
) {
6729 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6733 LOCAL_PERFORMANCE_WARNING(
6734 "Attribute 0 is disabled. This has signficant performance penalty");
6736 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6737 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
6739 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
6741 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6742 GLenum error
= glGetError();
6743 if (error
!= GL_NO_ERROR
) {
6745 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6750 const Vec4
& value
= state_
.attrib_values
[0];
6753 (!attrib_0_buffer_matches_value_
||
6754 (value
.v
[0] != attrib_0_value_
.v
[0] ||
6755 value
.v
[1] != attrib_0_value_
.v
[1] ||
6756 value
.v
[2] != attrib_0_value_
.v
[2] ||
6757 value
.v
[3] != attrib_0_value_
.v
[3])))) {
6758 std::vector
<Vec4
> temp(num_vertices
, value
);
6759 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
6760 attrib_0_buffer_matches_value_
= true;
6761 attrib_0_value_
= value
;
6762 attrib_0_size_
= size_needed
;
6765 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
6767 if (attrib
->divisor())
6768 glVertexAttribDivisorANGLE(0, 0);
6774 void GLES2DecoderImpl::RestoreStateForAttrib(
6775 GLuint attrib_index
, bool restore_array_binding
) {
6776 const VertexAttrib
* attrib
=
6777 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
6778 if (restore_array_binding
) {
6779 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
6780 Buffer
* buffer
= attrib
->buffer();
6781 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
6782 glVertexAttribPointer(
6783 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
6784 attrib
->gl_stride(), ptr
);
6786 if (attrib
->divisor())
6787 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
6789 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
6790 state_
.bound_array_buffer
->service_id() : 0);
6792 // Never touch vertex attribute 0's state (in particular, never
6793 // disable it) when running on desktop GL because it will never be
6795 if (attrib_index
!= 0 ||
6796 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
6797 if (attrib
->enabled()) {
6798 glEnableVertexAttribArray(attrib_index
);
6800 glDisableVertexAttribArray(attrib_index
);
6805 bool GLES2DecoderImpl::SimulateFixedAttribs(
6806 const char* function_name
,
6807 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
6810 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
6813 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
6817 LOCAL_PERFORMANCE_WARNING(
6818 "GL_FIXED attributes have a signficant performance penalty");
6820 // NOTE: we could be smart and try to check if a buffer is used
6821 // twice in 2 different attribs, find the overlapping parts and therefore
6822 // duplicate the minimum amount of data but this whole code path is not meant
6823 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6824 // tests so we just add to the buffer attrib used.
6826 GLuint elements_needed
= 0;
6827 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
6828 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
6829 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6830 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6831 const VertexAttrib
* attrib
= *it
;
6832 const Program::VertexAttrib
* attrib_info
=
6833 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6834 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6835 max_vertex_accessed
);
6836 GLuint num_vertices
= max_accessed
+ 1;
6837 if (num_vertices
== 0) {
6839 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6843 attrib
->CanAccess(max_accessed
) &&
6844 attrib
->type() == GL_FIXED
) {
6845 uint32 elements_used
= 0;
6846 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
6847 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
6849 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6855 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
6856 uint32 size_needed
= 0;
6857 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
6858 size_needed
> 0x7FFFFFFFU
) {
6860 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
6866 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
6867 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
6868 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
6869 GLenum error
= glGetError();
6870 if (error
!= GL_NO_ERROR
) {
6872 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
6877 // Copy the elements and convert to float
6878 GLintptr offset
= 0;
6879 for (VertexAttribManager::VertexAttribList::const_iterator it
=
6880 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
6881 const VertexAttrib
* attrib
= *it
;
6882 const Program::VertexAttrib
* attrib_info
=
6883 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
6884 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
6885 max_vertex_accessed
);
6886 GLuint num_vertices
= max_accessed
+ 1;
6887 if (num_vertices
== 0) {
6889 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
6893 attrib
->CanAccess(max_accessed
) &&
6894 attrib
->type() == GL_FIXED
) {
6895 int num_elements
= attrib
->size() * num_vertices
;
6896 const int src_size
= num_elements
* sizeof(int32
);
6897 const int dst_size
= num_elements
* sizeof(float);
6898 scoped_ptr
<float[]> data(new float[num_elements
]);
6899 const int32
* src
= reinterpret_cast<const int32
*>(
6900 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
6901 const int32
* end
= src
+ num_elements
;
6902 float* dst
= data
.get();
6903 while (src
!= end
) {
6904 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
6906 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
6907 glVertexAttribPointer(
6908 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
6909 reinterpret_cast<GLvoid
*>(offset
));
6917 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6918 // There's no need to call glVertexAttribPointer because we shadow all the
6919 // settings and passing GL_FIXED to it will not work.
6922 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
6926 error::Error
GLES2DecoderImpl::DoDrawArrays(
6927 const char* function_name
,
6932 GLsizei primcount
) {
6933 error::Error error
= WillAccessBoundFramebufferForDraw();
6934 if (error
!= error::kNoError
)
6936 if (!validators_
->draw_mode
.IsValid(mode
)) {
6937 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
6938 return error::kNoError
;
6941 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
6942 return error::kNoError
;
6944 if (primcount
< 0) {
6945 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
6946 return error::kNoError
;
6948 if (!CheckBoundFramebuffersValid(function_name
)) {
6949 return error::kNoError
;
6951 // We have to check this here because the prototype for glDrawArrays
6952 // is GLint not GLsizei.
6954 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
6955 return error::kNoError
;
6958 if (count
== 0 || primcount
== 0) {
6959 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6960 return error::kNoError
;
6963 GLuint max_vertex_accessed
= first
+ count
- 1;
6964 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
6965 if (!ClearUnclearedTextures()) {
6966 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
6967 return error::kNoError
;
6969 bool simulated_attrib_0
= false;
6970 if (!SimulateAttrib0(
6971 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
6972 return error::kNoError
;
6974 bool simulated_fixed_attribs
= false;
6975 if (SimulateFixedAttribs(
6976 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
6978 bool textures_set
= !PrepareTexturesForRender();
6980 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6982 glDrawArrays(mode
, first
, count
);
6984 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
6987 RestoreStateForTextures();
6989 if (simulated_fixed_attribs
) {
6990 RestoreStateForSimulatedFixedAttribs();
6993 if (simulated_attrib_0
) {
6994 // We don't have to restore attrib 0 generic data at the end of this
6995 // function even if it is simulated. This is because we will simulate
6996 // it in each draw call, and attrib 0 generic data queries use cached
6997 // values instead of passing down to the underlying driver.
6998 RestoreStateForAttrib(0, false);
7001 return error::kNoError
;
7004 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7005 const void* cmd_data
) {
7006 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7007 return DoDrawArrays("glDrawArrays",
7009 static_cast<GLenum
>(c
.mode
),
7010 static_cast<GLint
>(c
.first
),
7011 static_cast<GLsizei
>(c
.count
),
7015 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7016 uint32 immediate_data_size
,
7017 const void* cmd_data
) {
7018 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7019 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7020 if (!features().angle_instanced_arrays
) {
7022 GL_INVALID_OPERATION
,
7023 "glDrawArraysInstancedANGLE", "function not available");
7024 return error::kNoError
;
7026 return DoDrawArrays("glDrawArraysIntancedANGLE",
7028 static_cast<GLenum
>(c
.mode
),
7029 static_cast<GLint
>(c
.first
),
7030 static_cast<GLsizei
>(c
.count
),
7031 static_cast<GLsizei
>(c
.primcount
));
7034 error::Error
GLES2DecoderImpl::DoDrawElements(
7035 const char* function_name
,
7041 GLsizei primcount
) {
7042 error::Error error
= WillAccessBoundFramebufferForDraw();
7043 if (error
!= error::kNoError
)
7045 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7047 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7048 return error::kNoError
;
7052 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7053 return error::kNoError
;
7056 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7057 return error::kNoError
;
7059 if (!validators_
->draw_mode
.IsValid(mode
)) {
7060 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7061 return error::kNoError
;
7063 if (!validators_
->index_type
.IsValid(type
)) {
7064 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7065 return error::kNoError
;
7067 if (primcount
< 0) {
7068 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7069 return error::kNoError
;
7072 if (!CheckBoundFramebuffersValid(function_name
)) {
7073 return error::kNoError
;
7076 if (count
== 0 || primcount
== 0) {
7077 return error::kNoError
;
7080 GLuint max_vertex_accessed
;
7081 Buffer
* element_array_buffer
=
7082 state_
.vertex_attrib_manager
->element_array_buffer();
7084 if (!element_array_buffer
->GetMaxValueForRange(
7085 offset
, count
, type
, &max_vertex_accessed
)) {
7087 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7088 return error::kNoError
;
7091 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7092 if (!ClearUnclearedTextures()) {
7093 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7094 return error::kNoError
;
7096 bool simulated_attrib_0
= false;
7097 if (!SimulateAttrib0(
7098 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7099 return error::kNoError
;
7101 bool simulated_fixed_attribs
= false;
7102 if (SimulateFixedAttribs(
7103 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7105 bool textures_set
= !PrepareTexturesForRender();
7107 // TODO(gman): Refactor to hide these details in BufferManager or
7108 // VertexAttribManager.
7109 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7110 bool used_client_side_array
= false;
7111 if (element_array_buffer
->IsClientSideArray()) {
7112 used_client_side_array
= true;
7113 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7114 indices
= element_array_buffer
->GetRange(offset
, 0);
7117 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7119 glDrawElements(mode
, count
, type
, indices
);
7121 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7124 if (used_client_side_array
) {
7125 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7126 element_array_buffer
->service_id());
7130 RestoreStateForTextures();
7132 if (simulated_fixed_attribs
) {
7133 RestoreStateForSimulatedFixedAttribs();
7136 if (simulated_attrib_0
) {
7137 // We don't have to restore attrib 0 generic data at the end of this
7138 // function even if it is simulated. This is because we will simulate
7139 // it in each draw call, and attrib 0 generic data queries use cached
7140 // values instead of passing down to the underlying driver.
7141 RestoreStateForAttrib(0, false);
7144 return error::kNoError
;
7147 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
7148 const void* cmd_data
) {
7149 const gles2::cmds::DrawElements
& c
=
7150 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
7151 return DoDrawElements("glDrawElements",
7153 static_cast<GLenum
>(c
.mode
),
7154 static_cast<GLsizei
>(c
.count
),
7155 static_cast<GLenum
>(c
.type
),
7156 static_cast<int32
>(c
.index_offset
),
7160 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7161 uint32 immediate_data_size
,
7162 const void* cmd_data
) {
7163 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
7164 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
7165 if (!features().angle_instanced_arrays
) {
7167 GL_INVALID_OPERATION
,
7168 "glDrawElementsInstancedANGLE", "function not available");
7169 return error::kNoError
;
7171 return DoDrawElements("glDrawElementsInstancedANGLE",
7173 static_cast<GLenum
>(c
.mode
),
7174 static_cast<GLsizei
>(c
.count
),
7175 static_cast<GLenum
>(c
.type
),
7176 static_cast<int32
>(c
.index_offset
),
7177 static_cast<GLsizei
>(c
.primcount
));
7180 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7181 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
7182 GLuint max_vertex_accessed
= 0;
7183 Buffer
* buffer
= GetBuffer(buffer_id
);
7185 // TODO(gman): Should this be a GL error or a command buffer error?
7187 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7189 if (!buffer
->GetMaxValueForRange(
7190 offset
, count
, type
, &max_vertex_accessed
)) {
7191 // TODO(gman): Should this be a GL error or a command buffer error?
7193 GL_INVALID_OPERATION
,
7194 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7197 return max_vertex_accessed
;
7200 void GLES2DecoderImpl::DoShaderSource(
7201 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
7203 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7204 if (length
&& length
[ii
] > 0)
7205 str
.append(data
[ii
], length
[ii
]);
7207 str
.append(data
[ii
]);
7209 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
7213 // Note: We don't actually call glShaderSource here. We wait until
7214 // we actually compile the shader.
7215 shader
->set_source(str
);
7218 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7219 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
7220 GLenum buffer_mode
) {
7221 Program
* program
= GetProgramInfoNotShader(
7222 client_program_id
, "glTransformFeedbackVaryings");
7226 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
7227 glTransformFeedbackVaryings(
7228 program
->service_id(), count
, varyings
, buffer_mode
);
7231 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
7232 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7233 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
7238 scoped_refptr
<ShaderTranslatorInterface
> translator
;
7239 if (use_shader_translator_
) {
7240 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
7241 vertex_translator_
: fragment_translator_
;
7244 const Shader::TranslatedShaderSourceType source_type
=
7245 feature_info_
->feature_flags().angle_translated_shader_source
?
7246 Shader::kANGLE
: Shader::kGL
;
7247 shader
->RequestCompile(translator
, source_type
);
7250 void GLES2DecoderImpl::DoGetShaderiv(
7251 GLuint shader_id
, GLenum pname
, GLint
* params
) {
7252 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
7257 // Compile now for statuses that require it.
7259 case GL_COMPILE_STATUS
:
7260 case GL_INFO_LOG_LENGTH
:
7261 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7262 shader
->DoCompile();
7270 case GL_SHADER_SOURCE_LENGTH
:
7271 *params
= shader
->source().size();
7275 case GL_COMPILE_STATUS
:
7276 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
7278 case GL_INFO_LOG_LENGTH
:
7279 *params
= shader
->log_info().size();
7283 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
7284 *params
= shader
->translated_source().size();
7291 glGetShaderiv(shader
->service_id(), pname
, params
);
7294 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
7295 const void* cmd_data
) {
7296 const gles2::cmds::GetShaderSource
& c
=
7297 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
7298 GLuint shader_id
= c
.shader
;
7299 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7300 Bucket
* bucket
= CreateBucket(bucket_id
);
7301 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
7302 if (!shader
|| shader
->source().empty()) {
7304 return error::kNoError
;
7306 bucket
->SetFromString(shader
->source().c_str());
7307 return error::kNoError
;
7310 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7311 uint32 immediate_data_size
,
7312 const void* cmd_data
) {
7313 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
7314 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
7316 GLuint shader_id
= c
.shader
;
7317 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7318 Bucket
* bucket
= CreateBucket(bucket_id
);
7319 Shader
* shader
= GetShaderInfoNotProgram(
7320 shader_id
, "glGetTranslatedShaderSourceANGLE");
7323 return error::kNoError
;
7326 // Make sure translator has been utilized in compile.
7327 shader
->DoCompile();
7329 bucket
->SetFromString(shader
->translated_source().c_str());
7330 return error::kNoError
;
7333 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
7334 uint32 immediate_data_size
,
7335 const void* cmd_data
) {
7336 const gles2::cmds::GetProgramInfoLog
& c
=
7337 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
7338 GLuint program_id
= c
.program
;
7339 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7340 Bucket
* bucket
= CreateBucket(bucket_id
);
7341 Program
* program
= GetProgramInfoNotShader(
7342 program_id
, "glGetProgramInfoLog");
7343 if (!program
|| !program
->log_info()) {
7344 bucket
->SetFromString("");
7345 return error::kNoError
;
7347 bucket
->SetFromString(program
->log_info()->c_str());
7348 return error::kNoError
;
7351 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
7352 uint32 immediate_data_size
,
7353 const void* cmd_data
) {
7354 const gles2::cmds::GetShaderInfoLog
& c
=
7355 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
7356 GLuint shader_id
= c
.shader
;
7357 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
7358 Bucket
* bucket
= CreateBucket(bucket_id
);
7359 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
7361 bucket
->SetFromString("");
7362 return error::kNoError
;
7365 // Shader must be compiled in order to get the info log.
7366 shader
->DoCompile();
7368 bucket
->SetFromString(shader
->log_info().c_str());
7369 return error::kNoError
;
7372 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
7373 return state_
.GetEnabled(cap
);
7376 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
7377 const Buffer
* buffer
= GetBuffer(client_id
);
7378 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
7381 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
7382 const Framebuffer
* framebuffer
=
7383 GetFramebuffer(client_id
);
7384 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
7387 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
7388 // IsProgram is true for programs as soon as they are created, until they are
7389 // deleted and no longer in use.
7390 const Program
* program
= GetProgram(client_id
);
7391 return program
!= NULL
&& !program
->IsDeleted();
7394 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
7395 const Renderbuffer
* renderbuffer
=
7396 GetRenderbuffer(client_id
);
7397 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
7400 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
7401 // IsShader is true for shaders as soon as they are created, until they
7402 // are deleted and not attached to any programs.
7403 const Shader
* shader
= GetShader(client_id
);
7404 return shader
!= NULL
&& !shader
->IsDeleted();
7407 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
7408 const TextureRef
* texture_ref
= GetTexture(client_id
);
7409 return texture_ref
&& texture_ref
->texture()->IsValid();
7412 void GLES2DecoderImpl::DoAttachShader(
7413 GLuint program_client_id
, GLint shader_client_id
) {
7414 Program
* program
= GetProgramInfoNotShader(
7415 program_client_id
, "glAttachShader");
7419 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
7423 if (!program
->AttachShader(shader_manager(), shader
)) {
7425 GL_INVALID_OPERATION
,
7427 "can not attach more than one shader of the same type.");
7430 glAttachShader(program
->service_id(), shader
->service_id());
7433 void GLES2DecoderImpl::DoDetachShader(
7434 GLuint program_client_id
, GLint shader_client_id
) {
7435 Program
* program
= GetProgramInfoNotShader(
7436 program_client_id
, "glDetachShader");
7440 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
7444 if (!program
->DetachShader(shader_manager(), shader
)) {
7446 GL_INVALID_OPERATION
,
7447 "glDetachShader", "shader not attached to program");
7450 glDetachShader(program
->service_id(), shader
->service_id());
7453 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
7454 Program
* program
= GetProgramInfoNotShader(
7455 program_client_id
, "glValidateProgram");
7459 program
->Validate();
7462 void GLES2DecoderImpl::GetVertexAttribHelper(
7463 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
7465 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
: {
7466 Buffer
* buffer
= attrib
->buffer();
7467 if (buffer
&& !buffer
->IsDeleted()) {
7469 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
7470 *params
= client_id
;
7474 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
7475 *params
= attrib
->enabled();
7477 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
7478 *params
= attrib
->size();
7480 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
7481 *params
= attrib
->gl_stride();
7483 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
7484 *params
= attrib
->type();
7486 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
7487 *params
= attrib
->normalized();
7489 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE
:
7490 *params
= attrib
->divisor();
7498 void GLES2DecoderImpl::DoGetTexParameterfv(
7499 GLenum target
, GLenum pname
, GLfloat
* params
) {
7500 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7501 glGetTexParameterfv(target
, pname
, params
);
7504 void GLES2DecoderImpl::DoGetTexParameteriv(
7505 GLenum target
, GLenum pname
, GLint
* params
) {
7506 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
7507 glGetTexParameteriv(target
, pname
, params
);
7510 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7511 GLenum target
, GLenum pname
) {
7512 if (!workarounds().init_texture_max_anisotropy
)
7514 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
7515 !validators_
->texture_parameter
.IsValid(pname
)) {
7519 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
7523 GL_INVALID_OPERATION
,
7524 "glGetTexParamter{fi}v", "unknown texture for target");
7527 Texture
* texture
= texture_ref
->texture();
7528 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
7531 void GLES2DecoderImpl::DoGetVertexAttribfv(
7532 GLuint index
, GLenum pname
, GLfloat
* params
) {
7533 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7536 GL_INVALID_VALUE
, "glGetVertexAttribfv", "index out of range");
7540 case GL_CURRENT_VERTEX_ATTRIB
: {
7541 const Vec4
& value
= state_
.attrib_values
[index
];
7542 params
[0] = value
.v
[0];
7543 params
[1] = value
.v
[1];
7544 params
[2] = value
.v
[2];
7545 params
[3] = value
.v
[3];
7550 GetVertexAttribHelper(attrib
, pname
, &value
);
7551 *params
= static_cast<GLfloat
>(value
);
7557 void GLES2DecoderImpl::DoGetVertexAttribiv(
7558 GLuint index
, GLenum pname
, GLint
* params
) {
7559 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
7562 GL_INVALID_VALUE
, "glGetVertexAttribiv", "index out of range");
7566 case GL_CURRENT_VERTEX_ATTRIB
: {
7567 const Vec4
& value
= state_
.attrib_values
[index
];
7568 params
[0] = static_cast<GLint
>(value
.v
[0]);
7569 params
[1] = static_cast<GLint
>(value
.v
[1]);
7570 params
[2] = static_cast<GLint
>(value
.v
[2]);
7571 params
[3] = static_cast<GLint
>(value
.v
[3]);
7575 GetVertexAttribHelper(attrib
, pname
, params
);
7580 bool GLES2DecoderImpl::SetVertexAttribValue(
7581 const char* function_name
, GLuint index
, const GLfloat
* value
) {
7582 if (index
>= state_
.attrib_values
.size()) {
7583 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
7586 Vec4
& v
= state_
.attrib_values
[index
];
7594 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
7595 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
7596 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
7597 glVertexAttrib1f(index
, v0
);
7601 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
7602 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
7603 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
7604 glVertexAttrib2f(index
, v0
, v1
);
7608 void GLES2DecoderImpl::DoVertexAttrib3f(
7609 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
7610 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
7611 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
7612 glVertexAttrib3f(index
, v0
, v1
, v2
);
7616 void GLES2DecoderImpl::DoVertexAttrib4f(
7617 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
7618 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
7619 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
7620 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
7624 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
7625 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
7626 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
7627 glVertexAttrib1fv(index
, v
);
7631 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
7632 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
7633 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
7634 glVertexAttrib2fv(index
, v
);
7638 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
7639 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
7640 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
7641 glVertexAttrib3fv(index
, v
);
7645 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
7646 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
7647 glVertexAttrib4fv(index
, v
);
7651 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
7652 uint32 immediate_data_size
,
7653 const void* cmd_data
) {
7654 // TODO(zmo): Unsafe ES3 API, missing states update.
7655 if (!unsafe_es3_apis_enabled())
7656 return error::kUnknownCommand
;
7657 const gles2::cmds::VertexAttribIPointer
& c
=
7658 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
7659 GLuint indx
= c
.indx
;
7660 GLint size
= c
.size
;
7661 GLenum type
= c
.type
;
7662 GLsizei stride
= c
.stride
;
7663 GLsizei offset
= c
.offset
;
7664 const void* ptr
= reinterpret_cast<const void*>(offset
);
7665 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
7666 return error::kNoError
;
7669 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
7670 uint32 immediate_data_size
,
7671 const void* cmd_data
) {
7672 const gles2::cmds::VertexAttribPointer
& c
=
7673 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
7675 if (!state_
.bound_array_buffer
.get() ||
7676 state_
.bound_array_buffer
->IsDeleted()) {
7677 if (state_
.vertex_attrib_manager
.get() ==
7678 state_
.default_vertex_attrib_manager
.get()) {
7680 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
7681 return error::kNoError
;
7682 } else if (c
.offset
!= 0) {
7685 "glVertexAttribPointer", "client side arrays are not allowed");
7686 return error::kNoError
;
7690 GLuint indx
= c
.indx
;
7691 GLint size
= c
.size
;
7692 GLenum type
= c
.type
;
7693 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
7694 GLsizei stride
= c
.stride
;
7695 GLsizei offset
= c
.offset
;
7696 const void* ptr
= reinterpret_cast<const void*>(offset
);
7697 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
7698 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
7699 return error::kNoError
;
7701 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
7703 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7704 return error::kNoError
;
7706 if (indx
>= group_
->max_vertex_attribs()) {
7708 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
7709 return error::kNoError
;
7713 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
7714 return error::kNoError
;
7718 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
7719 return error::kNoError
;
7723 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
7724 return error::kNoError
;
7726 GLsizei component_size
=
7727 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
7728 // component_size must be a power of two to use & as optimized modulo.
7729 DCHECK(GLES2Util::IsPOT(component_size
));
7730 if (offset
& (component_size
- 1)) {
7732 GL_INVALID_OPERATION
,
7733 "glVertexAttribPointer", "offset not valid for type");
7734 return error::kNoError
;
7736 if (stride
& (component_size
- 1)) {
7738 GL_INVALID_OPERATION
,
7739 "glVertexAttribPointer", "stride not valid for type");
7740 return error::kNoError
;
7742 state_
.vertex_attrib_manager
7743 ->SetAttribInfo(indx
,
7744 state_
.bound_array_buffer
.get(),
7749 stride
!= 0 ? stride
: component_size
* size
,
7751 if (type
!= GL_FIXED
) {
7752 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
7754 return error::kNoError
;
7757 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
7759 state_
.viewport_x
= x
;
7760 state_
.viewport_y
= y
;
7761 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
7762 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
7763 glViewport(x
, y
, width
, height
);
7766 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7767 uint32 immediate_data_size
,
7768 const void* cmd_data
) {
7769 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
7770 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
7771 if (!features().angle_instanced_arrays
) {
7773 GL_INVALID_OPERATION
,
7774 "glVertexAttribDivisorANGLE", "function not available");
7775 return error::kNoError
;
7777 GLuint index
= c
.index
;
7778 GLuint divisor
= c
.divisor
;
7779 if (index
>= group_
->max_vertex_attribs()) {
7782 "glVertexAttribDivisorANGLE", "index out of range");
7783 return error::kNoError
;
7786 state_
.vertex_attrib_manager
->SetDivisor(
7789 glVertexAttribDivisorANGLE(index
, divisor
);
7790 return error::kNoError
;
7793 template <typename pixel_data_type
>
7794 static void WriteAlphaData(
7795 void* pixels
, uint32 row_count
, uint32 channel_count
,
7796 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
7797 uint32 padded_row_size
, pixel_data_type alpha_value
) {
7798 DCHECK_GT(channel_count
, 0U);
7799 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
7800 uint32 unpadded_row_size_in_elements
=
7801 unpadded_row_size
/ sizeof(pixel_data_type
);
7802 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
7803 uint32 padded_row_size_in_elements
=
7804 padded_row_size
/ sizeof(pixel_data_type
);
7805 pixel_data_type
* dst
=
7806 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
7807 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
7808 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
7809 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
7812 dst
+= padded_row_size_in_elements
;
7816 void GLES2DecoderImpl::FinishReadPixels(
7817 const cmds::ReadPixels
& c
,
7819 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7820 GLsizei width
= c
.width
;
7821 GLsizei height
= c
.height
;
7822 GLenum format
= c
.format
;
7823 GLenum type
= c
.type
;
7824 typedef cmds::ReadPixels::Result Result
;
7826 Result
* result
= NULL
;
7827 if (c
.result_shm_id
!= 0) {
7828 result
= GetSharedMemoryAs
<Result
*>(
7829 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7832 glDeleteBuffersARB(1, &buffer
);
7837 GLES2Util::ComputeImageDataSizes(
7838 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7840 void* pixels
= GetSharedMemoryAs
<void*>(
7841 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7844 glDeleteBuffersARB(1, &buffer
);
7850 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
7852 if (features().map_buffer_range
) {
7853 data
= glMapBufferRange(
7854 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
7856 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
7859 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
7860 "Unable to map memory for readback.");
7863 memcpy(pixels
, data
, pixels_size
);
7864 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7865 // have to restore the state.
7866 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
7867 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
7868 glDeleteBuffersARB(1, &buffer
);
7871 if (result
!= NULL
) {
7875 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
7876 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
7877 if ((channels_exist
& 0x0008) == 0 &&
7878 workarounds().clear_alpha_in_readpixels
) {
7879 // Set the alpha to 255 because some drivers are buggy in this regard.
7882 uint32 unpadded_row_size
;
7883 uint32 padded_row_size
;
7884 if (!GLES2Util::ComputeImageDataSizes(
7885 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
7886 &unpadded_row_size
, &padded_row_size
)) {
7890 uint32 channel_count
= 0;
7891 uint32 alpha_channel
= 0;
7904 if (channel_count
> 0) {
7906 case GL_UNSIGNED_BYTE
:
7907 WriteAlphaData
<uint8
>(
7908 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7909 padded_row_size
, 0xFF);
7912 WriteAlphaData
<float>(
7913 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7914 padded_row_size
, 1.0f
);
7917 WriteAlphaData
<uint16
>(
7918 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
7919 padded_row_size
, 0x3C00);
7926 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
7927 const void* cmd_data
) {
7928 const gles2::cmds::ReadPixels
& c
=
7929 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
7930 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7931 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
7932 if (fbo_error
!= error::kNoError
)
7936 GLsizei width
= c
.width
;
7937 GLsizei height
= c
.height
;
7938 GLenum format
= c
.format
;
7939 GLenum type
= c
.type
;
7940 GLboolean async
= static_cast<GLboolean
>(c
.async
);
7941 if (width
< 0 || height
< 0) {
7942 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
7943 return error::kNoError
;
7945 typedef cmds::ReadPixels::Result Result
;
7947 if (!GLES2Util::ComputeImageDataSizes(
7948 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
7950 return error::kOutOfBounds
;
7952 void* pixels
= GetSharedMemoryAs
<void*>(
7953 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
7955 return error::kOutOfBounds
;
7957 Result
* result
= NULL
;
7958 if (c
.result_shm_id
!= 0) {
7959 result
= GetSharedMemoryAs
<Result
*>(
7960 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
7962 return error::kOutOfBounds
;
7966 if (!validators_
->read_pixel_format
.IsValid(format
)) {
7967 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
7968 return error::kNoError
;
7970 if (!validators_
->read_pixel_type
.IsValid(type
)) {
7971 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
7972 return error::kNoError
;
7974 if ((format
!= GL_RGBA
&& format
!= GL_BGRA_EXT
&& format
!= GL_RGB
&&
7975 format
!= GL_ALPHA
) || type
!= GL_UNSIGNED_BYTE
) {
7976 // format and type are acceptable enums but not guaranteed to be supported
7977 // for this framebuffer. Have to ask gl if they are valid.
7978 GLint preferred_format
= 0;
7979 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
7980 GLint preferred_type
= 0;
7981 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
7982 if (format
!= static_cast<GLenum
>(preferred_format
) ||
7983 type
!= static_cast<GLenum
>(preferred_type
)) {
7985 GL_INVALID_OPERATION
, "glReadPixels", "format and type incompatible "
7986 "with the current read framebuffer");
7987 return error::kNoError
;
7990 if (width
== 0 || height
== 0) {
7991 return error::kNoError
;
7994 // Get the size of the current fbo or backbuffer.
7995 gfx::Size max_size
= GetBoundReadFrameBufferSize();
7999 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
8001 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8002 return error::kNoError
;
8005 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
8006 return error::kNoError
;
8009 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8010 return error::kNoError
;
8013 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8015 ScopedResolvedFrameBufferBinder
binder(this, false, true);
8017 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
8018 // The user requested an out of range area. Get the results 1 line
8021 uint32 unpadded_row_size
;
8022 uint32 padded_row_size
;
8023 if (!GLES2Util::ComputeImageDataSizes(
8024 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8025 &unpadded_row_size
, &padded_row_size
)) {
8027 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8028 return error::kNoError
;
8031 GLint dest_x_offset
= std::max(-x
, 0);
8032 uint32 dest_row_offset
;
8033 if (!GLES2Util::ComputeImageDataSizes(
8034 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
8035 &dest_row_offset
, NULL
, NULL
)) {
8037 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
8038 return error::kNoError
;
8041 // Copy each row into the larger dest rect.
8042 int8
* dst
= static_cast<int8
*>(pixels
);
8043 GLint read_x
= std::max(0, x
);
8044 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
8045 GLint read_width
= read_end_x
- read_x
;
8046 for (GLint yy
= 0; yy
< height
; ++yy
) {
8050 memset(dst
, 0, unpadded_row_size
);
8052 // If the row is in range, copy it.
8053 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
8055 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
8057 dst
+= padded_row_size
;
8060 if (async
&& features().use_async_readpixels
) {
8062 glGenBuffersARB(1, &buffer
);
8063 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8064 // For ANGLE client version 2, GL_STREAM_READ is not available.
8065 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
8066 GL_STATIC_DRAW
: GL_STREAM_READ
;
8067 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
8068 GLenum error
= glGetError();
8069 if (error
== GL_NO_ERROR
) {
8070 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
8071 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
8072 new FenceCallback()));
8073 WaitForReadPixels(base::Bind(
8074 &GLES2DecoderImpl::FinishReadPixels
,
8075 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8076 <GLES2DecoderImpl
>(this),
8078 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8079 return error::kNoError
;
8081 // On error, unbind pack buffer and fall through to sync readpixels
8082 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8083 glDeleteBuffersARB(1, &buffer
);
8086 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
8088 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
8089 if (error
== GL_NO_ERROR
) {
8090 if (result
!= NULL
) {
8093 FinishReadPixels(c
, 0);
8096 return error::kNoError
;
8099 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
8100 const void* cmd_data
) {
8101 const gles2::cmds::PixelStorei
& c
=
8102 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
8103 GLenum pname
= c
.pname
;
8104 GLenum param
= c
.param
;
8105 if (!validators_
->pixel_store
.IsValid(pname
)) {
8106 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
8107 return error::kNoError
;
8110 case GL_PACK_ALIGNMENT
:
8111 case GL_UNPACK_ALIGNMENT
:
8112 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
8114 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
8115 return error::kNoError
;
8118 case GL_UNPACK_FLIP_Y_CHROMIUM
:
8119 unpack_flip_y_
= (param
!= 0);
8120 return error::kNoError
;
8121 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM
:
8122 unpack_premultiply_alpha_
= (param
!= 0);
8123 return error::kNoError
;
8124 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM
:
8125 unpack_unpremultiply_alpha_
= (param
!= 0);
8126 return error::kNoError
;
8130 glPixelStorei(pname
, param
);
8132 case GL_PACK_ALIGNMENT
:
8133 state_
.pack_alignment
= param
;
8135 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
8136 state_
.pack_reverse_row_order
= (param
!= 0);
8138 case GL_UNPACK_ALIGNMENT
:
8139 state_
.unpack_alignment
= param
;
8142 // Validation should have prevented us from getting here.
8146 return error::kNoError
;
8149 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8150 uint32 immediate_data_size
,
8151 const void* cmd_data
) {
8152 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
8153 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
8154 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8156 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8158 if (!supports_post_sub_buffer_
) {
8160 GL_INVALID_OPERATION
,
8161 "glPostSubBufferCHROMIUM", "command not supported by surface");
8162 return error::kNoError
;
8165 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8168 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
8169 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
8170 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
8171 is_offscreen
? offscreen_size_
: surface_
->GetSize());
8173 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
)) {
8174 return error::kNoError
;
8176 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
8177 return error::kLostContext
;
8181 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8182 uint32 immediate_data_size
,
8183 const void* cmd_data
) {
8184 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
8185 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
8186 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
8188 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8189 "glScheduleOverlayPlaneCHROMIUM",
8191 return error::kNoError
;
8193 gfx::GLImage
* image
=
8194 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
8196 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
8197 "glScheduleOverlayPlaneCHROMIUM",
8198 "unsupported texture format");
8199 return error::kNoError
;
8201 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
8202 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
8203 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
8204 "glScheduleOverlayPlaneCHROMIUM",
8205 "invalid transform enum");
8206 return error::kNoError
;
8208 if (!surface_
->ScheduleOverlayPlane(
8212 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
8213 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
8214 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8215 "glScheduleOverlayPlaneCHROMIUM",
8216 "failed to schedule overlay");
8218 return error::kNoError
;
8221 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
8222 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8223 const std::string
& name_str
) {
8224 if (!StringIsValidForGLES(name_str
.c_str())) {
8226 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
8227 return error::kNoError
;
8229 Program
* program
= GetProgramInfoNotShader(
8230 client_id
, "glGetAttribLocation");
8232 return error::kNoError
;
8234 if (!program
->IsValid()) {
8236 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
8237 return error::kNoError
;
8239 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8240 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8242 return error::kOutOfBounds
;
8244 // Require the client to init this incase the context is lost and we are no
8245 // longer executing commands.
8246 if (*location
!= -1) {
8247 return error::kGenericError
;
8249 *location
= program
->GetAttribLocation(name_str
);
8250 return error::kNoError
;
8253 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
8254 uint32 immediate_data_size
,
8255 const void* cmd_data
) {
8256 const gles2::cmds::GetAttribLocation
& c
=
8257 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
8258 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8260 return error::kInvalidArguments
;
8262 std::string name_str
;
8263 if (!bucket
->GetAsString(&name_str
)) {
8264 return error::kInvalidArguments
;
8266 return GetAttribLocationHelper(
8267 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8270 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
8271 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8272 const std::string
& name_str
) {
8273 if (!StringIsValidForGLES(name_str
.c_str())) {
8275 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
8276 return error::kNoError
;
8278 Program
* program
= GetProgramInfoNotShader(
8279 client_id
, "glGetUniformLocation");
8281 return error::kNoError
;
8283 if (!program
->IsValid()) {
8285 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
8286 return error::kNoError
;
8288 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8289 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8291 return error::kOutOfBounds
;
8293 // Require the client to init this incase the context is lost an we are no
8294 // longer executing commands.
8295 if (*location
!= -1) {
8296 return error::kGenericError
;
8298 *location
= program
->GetUniformFakeLocation(name_str
);
8299 return error::kNoError
;
8302 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
8303 uint32 immediate_data_size
,
8304 const void* cmd_data
) {
8305 const gles2::cmds::GetUniformLocation
& c
=
8306 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
8307 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8309 return error::kInvalidArguments
;
8311 std::string name_str
;
8312 if (!bucket
->GetAsString(&name_str
)) {
8313 return error::kInvalidArguments
;
8315 return GetUniformLocationHelper(
8316 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8319 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
8320 uint32 immediate_data_size
,
8321 const void* cmd_data
) {
8322 if (!unsafe_es3_apis_enabled())
8323 return error::kUnknownCommand
;
8324 const gles2::cmds::GetUniformIndices
& c
=
8325 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
8326 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
8328 return error::kInvalidArguments
;
8331 std::vector
<char*> names
;
8332 std::vector
<GLint
> len
;
8333 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
8334 return error::kInvalidArguments
;
8336 typedef cmds::GetUniformIndices::Result Result
;
8337 Result
* result
= GetSharedMemoryAs
<Result
*>(
8338 c
.indices_shm_id
, c
.indices_shm_offset
,
8339 Result::ComputeSize(static_cast<size_t>(count
)));
8340 GLuint
* indices
= result
? result
->GetData() : NULL
;
8341 if (indices
== NULL
) {
8342 return error::kOutOfBounds
;
8344 // Check that the client initialized the result.
8345 if (result
->size
!= 0) {
8346 return error::kInvalidArguments
;
8348 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
8350 return error::kNoError
;
8352 GLuint service_id
= program
->service_id();
8353 GLint link_status
= GL_FALSE
;
8354 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
8355 if (link_status
!= GL_TRUE
) {
8356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
8357 "glGetUniformIndices", "program not linked");
8358 return error::kNoError
;
8360 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8361 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
8362 GLenum error
= glGetError();
8363 if (error
== GL_NO_ERROR
) {
8364 result
->SetNumResults(count
);
8366 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
8368 return error::kNoError
;
8371 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
8372 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
8373 const std::string
& name_str
) {
8374 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
8375 location_shm_id
, location_shm_offset
, sizeof(GLint
));
8377 return error::kOutOfBounds
;
8379 // Require the client to init this incase the context is lost and we are no
8380 // longer executing commands.
8381 if (*location
!= -1) {
8382 return error::kGenericError
;
8384 Program
* program
= GetProgramInfoNotShader(
8385 client_id
, "glGetFragDataLocation");
8387 return error::kNoError
;
8389 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
8390 return error::kNoError
;
8393 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
8394 uint32 immediate_data_size
,
8395 const void* cmd_data
) {
8396 if (!unsafe_es3_apis_enabled())
8397 return error::kUnknownCommand
;
8398 const gles2::cmds::GetFragDataLocation
& c
=
8399 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
8400 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8402 return error::kInvalidArguments
;
8404 std::string name_str
;
8405 if (!bucket
->GetAsString(&name_str
)) {
8406 return error::kInvalidArguments
;
8408 return GetFragDataLocationHelper(
8409 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
8412 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
8413 uint32 immediate_data_size
, const void* cmd_data
) {
8414 if (!unsafe_es3_apis_enabled())
8415 return error::kUnknownCommand
;
8416 const gles2::cmds::GetUniformBlockIndex
& c
=
8417 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
8418 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
8420 return error::kInvalidArguments
;
8422 std::string name_str
;
8423 if (!bucket
->GetAsString(&name_str
)) {
8424 return error::kInvalidArguments
;
8426 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
8427 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
8429 return error::kOutOfBounds
;
8431 // Require the client to init this in case the context is lost and we are no
8432 // longer executing commands.
8433 if (*index
!= GL_INVALID_INDEX
) {
8434 return error::kGenericError
;
8436 Program
* program
= GetProgramInfoNotShader(
8437 c
.program
, "glGetUniformBlockIndex");
8439 return error::kNoError
;
8441 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
8442 return error::kNoError
;
8445 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
8446 const void* cmd_data
) {
8447 const gles2::cmds::GetString
& c
=
8448 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
8449 GLenum name
= static_cast<GLenum
>(c
.name
);
8450 if (!validators_
->string_type
.IsValid(name
)) {
8451 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
8452 return error::kNoError
;
8455 const char* str
= nullptr;
8456 std::string extensions
;
8459 str
= "OpenGL ES 2.0 Chromium";
8461 case GL_SHADING_LANGUAGE_VERSION
:
8462 str
= "OpenGL ES GLSL ES 1.0 Chromium";
8466 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8467 // They are used by WEBGL_debug_renderer_info.
8468 if (!force_webgl_glsl_validation_
)
8471 str
= reinterpret_cast<const char*>(glGetString(name
));
8475 // For WebGL contexts, strip out the OES derivatives and
8476 // EXT frag depth extensions if they have not been enabled.
8477 if (force_webgl_glsl_validation_
) {
8478 extensions
= feature_info_
->extensions();
8479 if (!derivatives_explicitly_enabled_
) {
8480 size_t offset
= extensions
.find(kOESDerivativeExtension
);
8481 if (std::string::npos
!= offset
) {
8482 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
8486 if (!frag_depth_explicitly_enabled_
) {
8487 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
8488 if (std::string::npos
!= offset
) {
8489 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
8493 if (!draw_buffers_explicitly_enabled_
) {
8494 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
8495 if (std::string::npos
!= offset
) {
8496 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
8500 if (!shader_texture_lod_explicitly_enabled_
) {
8501 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
8502 if (std::string::npos
!= offset
) {
8503 extensions
.replace(offset
,
8504 arraysize(kEXTShaderTextureLodExtension
),
8509 extensions
= feature_info_
->extensions().c_str();
8511 if (supports_post_sub_buffer_
)
8512 extensions
+= " GL_CHROMIUM_post_sub_buffer";
8513 str
= extensions
.c_str();
8517 str
= reinterpret_cast<const char*>(glGetString(name
));
8520 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
8521 bucket
->SetFromString(str
);
8522 return error::kNoError
;
8525 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
8526 const void* cmd_data
) {
8527 const gles2::cmds::BufferData
& c
=
8528 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
8529 GLenum target
= static_cast<GLenum
>(c
.target
);
8530 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
8531 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8532 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8533 GLenum usage
= static_cast<GLenum
>(c
.usage
);
8534 const void* data
= NULL
;
8535 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8536 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
8538 return error::kOutOfBounds
;
8541 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
8542 return error::kNoError
;
8545 void GLES2DecoderImpl::DoBufferSubData(
8546 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
8547 // Just delegate it. Some validation is actually done before this.
8548 buffer_manager()->ValidateAndDoBufferSubData(
8549 &state_
, target
, offset
, size
, data
);
8552 bool GLES2DecoderImpl::ClearLevel(
8556 unsigned internal_format
,
8561 bool is_texture_immutable
) {
8562 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
8563 if (feature_info_
->feature_flags().angle_depth_texture
&&
8564 (channels
& GLES2Util::kDepth
) != 0) {
8565 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8566 // on depth formats.
8568 glGenFramebuffersEXT(1, &fb
);
8569 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
8571 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
8572 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
8573 GL_DEPTH_ATTACHMENT
;
8575 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
8576 texture
->service_id(), level
);
8577 // ANGLE promises a depth only attachment ok.
8578 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
8579 GL_FRAMEBUFFER_COMPLETE
) {
8583 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
8584 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
8586 state_
.SetDeviceDepthMask(GL_TRUE
);
8587 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
8588 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
8590 RestoreClearState();
8592 glDeleteFramebuffersEXT(1, &fb
);
8593 Framebuffer
* framebuffer
=
8594 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
8595 GLuint fb_service_id
=
8596 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
8597 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
8601 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
8604 uint32 padded_row_size
;
8605 if (!GLES2Util::ComputeImageDataSizes(
8606 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8607 NULL
, &padded_row_size
)) {
8611 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
8615 if (size
> kMaxZeroSize
) {
8616 if (kMaxZeroSize
< padded_row_size
) {
8617 // That'd be an awfully large texture.
8620 // We should never have a large total size with a zero row size.
8621 DCHECK_GT(padded_row_size
, 0U);
8622 tile_height
= kMaxZeroSize
/ padded_row_size
;
8623 if (!GLES2Util::ComputeImageDataSizes(
8624 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
8629 tile_height
= height
;
8632 // Assumes the size has already been checked.
8633 scoped_ptr
<char[]> zero(new char[size
]);
8634 memset(zero
.get(), 0, size
);
8635 glBindTexture(texture
->target(), texture
->service_id());
8637 bool has_images
= texture
->HasImages();
8639 while (y
< height
) {
8640 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
8641 if (is_texture_immutable
|| h
!= height
|| has_images
) {
8642 glTexSubImage2D(target
, level
, 0, y
, width
, h
, format
, type
, zero
.get());
8645 target
, level
, internal_format
, width
, h
, 0, format
, type
,
8650 TextureRef
* bound_texture
=
8651 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
8652 glBindTexture(texture
->target(),
8653 bound_texture
? bound_texture
->service_id() : 0);
8659 const int kS3TCBlockWidth
= 4;
8660 const int kS3TCBlockHeight
= 4;
8661 const int kS3TCDXT1BlockSize
= 8;
8662 const int kS3TCDXT3AndDXT5BlockSize
= 16;
8664 bool IsValidDXTSize(GLint level
, GLsizei size
) {
8665 return (size
== 1) ||
8666 (size
== 2) || !(size
% kS3TCBlockWidth
);
8669 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
8670 return GLES2Util::IsPOT(size
);
8673 } // anonymous namespace.
8675 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8676 const char* function_name
,
8677 GLsizei width
, GLsizei height
, GLenum format
, size_t size
) {
8678 unsigned int bytes_required
= 0;
8681 case GL_ATC_RGB_AMD
:
8682 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8683 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8684 case GL_ETC1_RGB8_OES
: {
8685 int num_blocks_across
=
8686 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8687 int num_blocks_down
=
8688 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8689 int num_blocks
= num_blocks_across
* num_blocks_down
;
8690 bytes_required
= num_blocks
* kS3TCDXT1BlockSize
;
8693 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8694 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8695 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8696 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8697 int num_blocks_across
=
8698 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
8699 int num_blocks_down
=
8700 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
8701 int num_blocks
= num_blocks_across
* num_blocks_down
;
8702 bytes_required
= num_blocks
* kS3TCDXT3AndDXT5BlockSize
;
8705 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8706 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
: {
8707 bytes_required
= (std::max(width
, 8) * std::max(height
, 8) * 4 + 7)/8;
8710 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8711 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8712 bytes_required
= (std::max(width
, 16) * std::max(height
, 8) * 2 + 7)/8;
8716 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
8720 if (size
!= bytes_required
) {
8722 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
8729 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8730 const char* function_name
,
8731 GLint level
, GLsizei width
, GLsizei height
, GLenum format
) {
8733 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8734 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8735 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8736 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8737 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
8739 GL_INVALID_OPERATION
, function_name
,
8740 "width or height invalid for level");
8745 case GL_ATC_RGB_AMD
:
8746 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8747 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
8748 case GL_ETC1_RGB8_OES
: {
8749 if (width
<= 0 || height
<= 0) {
8751 GL_INVALID_OPERATION
, function_name
,
8752 "width or height invalid for level");
8757 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8758 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8759 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8760 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8761 if (!IsValidPVRTCSize(level
, width
) ||
8762 !IsValidPVRTCSize(level
, height
)) {
8764 GL_INVALID_OPERATION
, function_name
,
8765 "width or height invalid for level");
8775 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8776 const char* function_name
,
8777 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
,
8778 GLsizei width
, GLsizei height
, GLenum format
,
8780 if (xoffset
< 0 || yoffset
< 0) {
8782 GL_INVALID_VALUE
, function_name
, "xoffset or yoffset < 0");
8787 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
8788 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
8789 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
8790 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
8791 const int kBlockWidth
= 4;
8792 const int kBlockHeight
= 4;
8793 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
8795 GL_INVALID_OPERATION
, function_name
,
8796 "xoffset or yoffset not multiple of 4");
8799 GLsizei tex_width
= 0;
8800 GLsizei tex_height
= 0;
8801 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8802 width
- xoffset
> tex_width
||
8803 height
- yoffset
> tex_height
) {
8805 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
8808 return ValidateCompressedTexDimensions(
8809 function_name
, level
, width
, height
, format
);
8811 case GL_ATC_RGB_AMD
:
8812 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
8813 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
8815 GL_INVALID_OPERATION
, function_name
,
8816 "not supported for ATC textures");
8819 case GL_ETC1_RGB8_OES
: {
8821 GL_INVALID_OPERATION
, function_name
,
8822 "not supported for ECT1_RGB8_OES textures");
8825 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
8826 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
8827 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
8828 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
8829 if ((xoffset
!= 0) || (yoffset
!= 0)) {
8831 GL_INVALID_OPERATION
, function_name
,
8832 "xoffset and yoffset must be zero");
8835 GLsizei tex_width
= 0;
8836 GLsizei tex_height
= 0;
8837 if (!texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
) ||
8838 width
!= tex_width
||
8839 height
!= tex_height
) {
8841 GL_INVALID_OPERATION
, function_name
,
8842 "dimensions must match existing texture level dimensions");
8845 return ValidateCompressedTexDimensions(
8846 function_name
, level
, width
, height
, format
);
8853 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
8856 GLenum internal_format
,
8862 // TODO(gman): Validate image_size is correct for width, height and format.
8863 if (!validators_
->texture_target
.IsValid(target
)) {
8864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8865 "glCompressedTexImage2D", target
, "target");
8866 return error::kNoError
;
8868 if (!validators_
->compressed_texture_format
.IsValid(
8870 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8871 "glCompressedTexImage2D", internal_format
, "internal_format");
8872 return error::kNoError
;
8874 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
8878 "glCompressedTexImage2D", "dimensions out of range");
8879 return error::kNoError
;
8881 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8886 "glCompressedTexImage2D", "unknown texture target");
8887 return error::kNoError
;
8889 Texture
* texture
= texture_ref
->texture();
8890 if (texture
->IsImmutable()) {
8892 GL_INVALID_OPERATION
,
8893 "glCompressedTexImage2D", "texture is immutable");
8894 return error::kNoError
;
8897 if (!ValidateCompressedTexDimensions(
8898 "glCompressedTexImage2D", level
, width
, height
, internal_format
) ||
8899 !ValidateCompressedTexFuncData(
8900 "glCompressedTexImage2D", width
, height
, internal_format
, image_size
)) {
8901 return error::kNoError
;
8904 if (!EnsureGPUMemoryAvailable(image_size
)) {
8906 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
8907 return error::kNoError
;
8910 if (texture
->IsAttachedToFramebuffer()) {
8911 framebuffer_state_
.clear_state_dirty
= true;
8914 scoped_ptr
<int8
[]> zero
;
8916 zero
.reset(new int8
[image_size
]);
8917 memset(zero
.get(), 0, image_size
);
8920 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8921 glCompressedTexImage2D(
8922 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8923 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8924 if (error
== GL_NO_ERROR
) {
8925 texture_manager()->SetLevelInfo(
8926 texture_ref
, target
, level
, internal_format
,
8927 width
, height
, 1, border
, 0, 0, true);
8930 // This may be a slow command. Exit command processing to allow for
8931 // context preemption and GPU watchdog checks.
8932 ExitCommandProcessingEarly();
8933 return error::kNoError
;
8936 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
8937 uint32 immediate_data_size
,
8938 const void* cmd_data
) {
8939 const gles2::cmds::CompressedTexImage2D
& c
=
8940 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
8941 GLenum target
= static_cast<GLenum
>(c
.target
);
8942 GLint level
= static_cast<GLint
>(c
.level
);
8943 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8944 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8945 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8946 GLint border
= static_cast<GLint
>(c
.border
);
8947 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
8948 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
8949 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
8950 const void* data
= NULL
;
8951 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
8952 data
= GetSharedMemoryAs
<const void*>(
8953 data_shm_id
, data_shm_offset
, image_size
);
8955 return error::kOutOfBounds
;
8958 return DoCompressedTexImage2D(
8959 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
8962 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8963 uint32 immediate_data_size
,
8964 const void* cmd_data
) {
8965 const gles2::cmds::CompressedTexImage2DBucket
& c
=
8966 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
8967 GLenum target
= static_cast<GLenum
>(c
.target
);
8968 GLint level
= static_cast<GLint
>(c
.level
);
8969 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
8970 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8971 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8972 GLint border
= static_cast<GLint
>(c
.border
);
8973 Bucket
* bucket
= GetBucket(c
.bucket_id
);
8975 return error::kInvalidArguments
;
8977 uint32 data_size
= bucket
->size();
8978 GLsizei imageSize
= data_size
;
8979 const void* data
= bucket
->GetData(0, data_size
);
8981 return error::kInvalidArguments
;
8983 return DoCompressedTexImage2D(
8984 target
, level
, internal_format
, width
, height
, border
,
8988 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8989 uint32 immediate_data_size
,
8990 const void* cmd_data
) {
8991 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
8992 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
8993 GLenum target
= static_cast<GLenum
>(c
.target
);
8994 GLint level
= static_cast<GLint
>(c
.level
);
8995 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
8996 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
8997 GLsizei width
= static_cast<GLsizei
>(c
.width
);
8998 GLsizei height
= static_cast<GLsizei
>(c
.height
);
8999 GLenum format
= static_cast<GLenum
>(c
.format
);
9000 Bucket
* bucket
= GetBucket(c
.bucket_id
);
9002 return error::kInvalidArguments
;
9004 uint32 data_size
= bucket
->size();
9005 GLsizei imageSize
= data_size
;
9006 const void* data
= bucket
->GetData(0, data_size
);
9008 return error::kInvalidArguments
;
9010 if (!validators_
->texture_target
.IsValid(target
)) {
9012 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
9013 return error::kNoError
;
9015 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
9016 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9017 "glCompressedTexSubImage2D", format
, "format");
9018 return error::kNoError
;
9022 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
9023 return error::kNoError
;
9027 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
9028 return error::kNoError
;
9030 if (imageSize
< 0) {
9032 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
9033 return error::kNoError
;
9035 DoCompressedTexSubImage2D(
9036 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
9037 return error::kNoError
;
9040 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
9041 const void* cmd_data
) {
9042 const gles2::cmds::TexImage2D
& c
=
9043 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
9044 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9045 "width", c
.width
, "height", c
.height
);
9046 // Set as failed for now, but if it successed, this will be set to not failed.
9047 texture_state_
.tex_image_2d_failed
= true;
9048 GLenum target
= static_cast<GLenum
>(c
.target
);
9049 GLint level
= static_cast<GLint
>(c
.level
);
9050 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9051 // for internalformat.
9052 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9053 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9054 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9055 GLint border
= static_cast<GLint
>(c
.border
);
9056 GLenum format
= static_cast<GLenum
>(c
.format
);
9057 GLenum type
= static_cast<GLenum
>(c
.type
);
9058 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9059 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9061 if (!GLES2Util::ComputeImageDataSizes(
9062 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9064 return error::kOutOfBounds
;
9066 const void* pixels
= NULL
;
9067 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9068 pixels
= GetSharedMemoryAs
<const void*>(
9069 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9071 return error::kOutOfBounds
;
9075 // For testing only. Allows us to stress the ability to respond to OOM errors.
9076 if (workarounds().simulate_out_of_memory_on_large_textures
&&
9077 (width
* height
>= 4096 * 4096)) {
9080 "glTexImage2D", "synthetic out of memory");
9081 return error::kNoError
;
9084 TextureManager::DoTextImage2DArguments args
= {
9085 target
, level
, internal_format
, width
, height
, border
, format
, type
,
9086 pixels
, pixels_size
};
9087 texture_manager()->ValidateAndDoTexImage2D(
9088 &texture_state_
, &state_
, &framebuffer_state_
, args
);
9090 // This may be a slow command. Exit command processing to allow for
9091 // context preemption and GPU watchdog checks.
9092 ExitCommandProcessingEarly();
9093 return error::kNoError
;
9096 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
9097 const void* cmd_data
) {
9098 // TODO(zmo): Unsafe ES3 API.
9099 if (!unsafe_es3_apis_enabled())
9100 return error::kUnknownCommand
;
9102 const gles2::cmds::TexImage3D
& c
=
9103 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
9104 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
9105 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9106 GLenum target
= static_cast<GLenum
>(c
.target
);
9107 GLint level
= static_cast<GLint
>(c
.level
);
9108 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
9109 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9110 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9111 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9112 GLint border
= static_cast<GLint
>(c
.border
);
9113 GLenum format
= static_cast<GLenum
>(c
.format
);
9114 GLenum type
= static_cast<GLenum
>(c
.type
);
9115 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
9116 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
9118 if (!GLES2Util::ComputeImageDataSizes(
9119 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9121 return error::kOutOfBounds
;
9123 const void* pixels
= NULL
;
9124 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
9125 pixels
= GetSharedMemoryAs
<const void*>(
9126 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
9128 return error::kOutOfBounds
;
9132 glTexImage3D(target
, level
, internal_format
, width
, height
, depth
, border
,
9133 format
, type
, pixels
);
9135 // This may be a slow command. Exit command processing to allow for
9136 // context preemption and GPU watchdog checks.
9137 ExitCommandProcessingEarly();
9138 return error::kNoError
;
9141 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
9150 const void * data
) {
9151 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9155 GL_INVALID_OPERATION
,
9156 "glCompressedTexSubImage2D", "unknown texture for target");
9159 Texture
* texture
= texture_ref
->texture();
9161 GLenum internal_format
= 0;
9162 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
9164 GL_INVALID_OPERATION
,
9165 "glCompressedTexSubImage2D", "level does not exist.");
9168 if (internal_format
!= format
) {
9170 GL_INVALID_OPERATION
,
9171 "glCompressedTexSubImage2D", "format does not match internal format.");
9174 if (!texture
->ValidForTexture(
9175 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9177 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
9181 if (!ValidateCompressedTexFuncData(
9182 "glCompressedTexSubImage2D", width
, height
, format
, image_size
) ||
9183 !ValidateCompressedTexSubDimensions(
9184 "glCompressedTexSubImage2D",
9185 target
, level
, xoffset
, yoffset
, width
, height
, format
, texture
)) {
9190 // Note: There is no need to deal with texture cleared tracking here
9191 // because the validation above means you can only get here if the level
9192 // is already a matching compressed format and in that case
9193 // CompressedTexImage2D already cleared the texture.
9194 glCompressedTexSubImage2D(
9195 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
9197 // This may be a slow command. Exit command processing to allow for
9198 // context preemption and GPU watchdog checks.
9199 ExitCommandProcessingEarly();
9203 GLint start
, GLint range
, GLint sourceRange
,
9204 GLint
* out_start
, GLint
* out_range
) {
9211 GLint end
= start
+ range
;
9212 if (end
> sourceRange
) {
9213 range
-= end
- sourceRange
;
9219 void GLES2DecoderImpl::DoCopyTexImage2D(
9222 GLenum internal_format
,
9228 DCHECK(!ShouldDeferReads());
9229 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9233 GL_INVALID_OPERATION
,
9234 "glCopyTexImage2D", "unknown texture for target");
9237 Texture
* texture
= texture_ref
->texture();
9238 if (texture
->IsImmutable()) {
9240 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
9243 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
9246 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
9249 if (!texture_manager()->ValidateFormatAndTypeCombination(
9250 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
9251 GL_UNSIGNED_BYTE
)) {
9255 // Check we have compatible formats.
9256 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9257 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9258 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
9260 if ((channels_needed
& channels_exist
) != channels_needed
) {
9262 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
9266 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9268 GL_INVALID_OPERATION
,
9269 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9273 uint32 estimated_size
= 0;
9274 if (!GLES2Util::ComputeImageDataSizes(
9275 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
9276 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
9278 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
9282 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
9283 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
9287 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9291 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9293 GL_INVALID_OPERATION
,
9294 "glCopyTexImage2D", "source and destination textures are the same");
9298 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9302 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9303 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9304 gfx::Size size
= GetBoundReadFrameBufferSize();
9306 if (texture
->IsAttachedToFramebuffer()) {
9307 framebuffer_state_
.clear_state_dirty
= true;
9310 // Clip to size to source dimensions
9313 GLint copyWidth
= 0;
9314 GLint copyHeight
= 0;
9315 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9316 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9320 copyWidth
!= width
||
9321 copyHeight
!= height
) {
9322 // some part was clipped so clear the texture.
9323 if (!ClearLevel(texture
, target
, level
, internal_format
, internal_format
,
9324 GL_UNSIGNED_BYTE
, width
, height
, texture
->IsImmutable())) {
9326 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
9329 if (copyHeight
> 0 && copyWidth
> 0) {
9330 GLint dx
= copyX
- x
;
9331 GLint dy
= copyY
- y
;
9334 ScopedModifyPixels
modify(texture_ref
);
9335 glCopyTexSubImage2D(target
, level
,
9336 destX
, destY
, copyX
, copyY
,
9337 copyWidth
, copyHeight
);
9340 ScopedModifyPixels
modify(texture_ref
);
9341 glCopyTexImage2D(target
, level
, internal_format
,
9342 copyX
, copyY
, copyWidth
, copyHeight
, border
);
9344 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9345 if (error
== GL_NO_ERROR
) {
9346 texture_manager()->SetLevelInfo(
9347 texture_ref
, target
, level
, internal_format
, width
, height
, 1,
9348 border
, internal_format
, GL_UNSIGNED_BYTE
, true);
9351 // This may be a slow command. Exit command processing to allow for
9352 // context preemption and GPU watchdog checks.
9353 ExitCommandProcessingEarly();
9356 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9365 DCHECK(!ShouldDeferReads());
9366 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9370 GL_INVALID_OPERATION
,
9371 "glCopyTexSubImage2D", "unknown texture for target");
9374 Texture
* texture
= texture_ref
->texture();
9377 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
9378 !texture
->ValidForTexture(
9379 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9381 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
9384 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9386 GL_INVALID_OPERATION
,
9387 "glCopyTexSubImage2D", "async upload pending for texture");
9391 // Check we have compatible formats.
9392 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
9393 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
9394 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
9396 if (!channels_needed
||
9397 (channels_needed
& channels_exist
) != channels_needed
) {
9399 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
9403 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9405 GL_INVALID_OPERATION
,
9406 "glCopySubImage2D", "can not be used with depth or stencil textures");
9410 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9414 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
9416 GL_INVALID_OPERATION
,
9417 "glCopyTexSubImage2D", "source and destination textures are the same");
9421 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9425 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9426 gfx::Size size
= GetBoundReadFrameBufferSize();
9429 GLint copyWidth
= 0;
9430 GLint copyHeight
= 0;
9431 Clip(x
, width
, size
.width(), ©X
, ©Width
);
9432 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
9434 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
9435 height
!= size
.height()) {
9436 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
9438 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
9439 "dimensions too big");
9443 // Write all pixels in below.
9444 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9449 copyWidth
!= width
||
9450 copyHeight
!= height
) {
9451 // some part was clipped so clear the sub rect.
9452 uint32 pixels_size
= 0;
9453 if (!GLES2Util::ComputeImageDataSizes(
9454 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
9457 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
9460 scoped_ptr
<char[]> zero(new char[pixels_size
]);
9461 memset(zero
.get(), 0, pixels_size
);
9462 ScopedModifyPixels
modify(texture_ref
);
9464 target
, level
, xoffset
, yoffset
, width
, height
,
9465 format
, type
, zero
.get());
9468 if (copyHeight
> 0 && copyWidth
> 0) {
9469 GLint dx
= copyX
- x
;
9470 GLint dy
= copyY
- y
;
9471 GLint destX
= xoffset
+ dx
;
9472 GLint destY
= yoffset
+ dy
;
9473 ScopedModifyPixels
modify(texture_ref
);
9474 glCopyTexSubImage2D(target
, level
,
9475 destX
, destY
, copyX
, copyY
,
9476 copyWidth
, copyHeight
);
9479 // This may be a slow command. Exit command processing to allow for
9480 // context preemption and GPU watchdog checks.
9481 ExitCommandProcessingEarly();
9484 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9485 error::Error
* error
,
9486 const char* function_name
,
9495 const void * data
) {
9496 (*error
) = error::kNoError
;
9497 if (!validators_
->texture_target
.IsValid(target
)) {
9498 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
9502 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
9506 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
9509 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9513 GL_INVALID_OPERATION
,
9514 function_name
, "unknown texture for target");
9517 Texture
* texture
= texture_ref
->texture();
9518 GLenum current_type
= 0;
9519 GLenum internal_format
= 0;
9520 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
9522 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
9525 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
9526 function_name
, format
, type
, internal_format
, level
)) {
9529 if (type
!= current_type
) {
9531 GL_INVALID_OPERATION
,
9532 function_name
, "type does not match type of texture.");
9535 if (async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
9537 GL_INVALID_OPERATION
,
9538 function_name
, "async upload pending for texture");
9541 if (!texture
->ValidForTexture(
9542 target
, level
, xoffset
, yoffset
, width
, height
, type
)) {
9543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
9546 if ((GLES2Util::GetChannelsForFormat(format
) &
9547 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
9549 GL_INVALID_OPERATION
,
9550 function_name
, "can not supply data for depth or stencil textures");
9554 (*error
) = error::kOutOfBounds
;
9560 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
9569 const void * data
) {
9570 error::Error error
= error::kNoError
;
9571 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
9572 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
9575 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
9577 Texture
* texture
= texture_ref
->texture();
9578 GLsizei tex_width
= 0;
9579 GLsizei tex_height
= 0;
9580 bool ok
= texture
->GetLevelSize(target
, level
, &tex_width
, &tex_height
);
9582 if (xoffset
!= 0 || yoffset
!= 0 ||
9583 width
!= tex_width
|| height
!= tex_height
) {
9584 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
9587 GL_OUT_OF_MEMORY
, "glTexSubImage2D", "dimensions too big");
9588 return error::kNoError
;
9590 ScopedTextureUploadTimer
timer(&texture_state_
);
9592 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9593 return error::kNoError
;
9596 if (!texture_state_
.texsubimage2d_faster_than_teximage2d
&&
9597 !texture
->IsImmutable() &&
9598 !texture
->HasImages()) {
9599 ScopedTextureUploadTimer
timer(&texture_state_
);
9600 GLenum internal_format
;
9602 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
9603 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9606 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
9608 ScopedTextureUploadTimer
timer(&texture_state_
);
9610 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
9612 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
9614 // This may be a slow command. Exit command processing to allow for
9615 // context preemption and GPU watchdog checks.
9616 ExitCommandProcessingEarly();
9617 return error::kNoError
;
9620 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
9621 const void* cmd_data
) {
9622 const gles2::cmds::TexSubImage2D
& c
=
9623 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
9624 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9625 "width", c
.width
, "height", c
.height
);
9626 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
9627 if (internal
== GL_TRUE
&& texture_state_
.tex_image_2d_failed
)
9628 return error::kNoError
;
9630 GLenum target
= static_cast<GLenum
>(c
.target
);
9631 GLint level
= static_cast<GLint
>(c
.level
);
9632 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9633 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9634 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9635 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9636 GLenum format
= static_cast<GLenum
>(c
.format
);
9637 GLenum type
= static_cast<GLenum
>(c
.type
);
9639 if (!GLES2Util::ComputeImageDataSizes(
9640 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
9642 return error::kOutOfBounds
;
9644 const void* pixels
= GetSharedMemoryAs
<const void*>(
9645 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9646 return DoTexSubImage2D(
9647 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
9650 // TODO(zmo): Remove the below stub once we add the real function binding.
9651 // Currently it's missing due to a gmock limitation.
9652 static void glTexSubImage3D(
9653 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9654 GLsizei height
, GLsizei width
, GLsizei depth
, GLenum format
, GLenum type
,
9655 const void* pixels
) {
9659 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
9660 const void* cmd_data
) {
9661 // TODO(zmo): Unsafe ES3 API.
9662 if (!unsafe_es3_apis_enabled())
9663 return error::kUnknownCommand
;
9665 const gles2::cmds::TexSubImage3D
& c
=
9666 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
9667 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9668 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
9669 GLenum target
= static_cast<GLenum
>(c
.target
);
9670 GLint level
= static_cast<GLint
>(c
.level
);
9671 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
9672 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
9673 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
9674 GLsizei width
= static_cast<GLsizei
>(c
.width
);
9675 GLsizei height
= static_cast<GLsizei
>(c
.height
);
9676 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
9677 GLenum format
= static_cast<GLenum
>(c
.format
);
9678 GLenum type
= static_cast<GLenum
>(c
.type
);
9680 if (!GLES2Util::ComputeImageDataSizes(
9681 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
9683 return error::kOutOfBounds
;
9685 const void* pixels
= GetSharedMemoryAs
<const void*>(
9686 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
9687 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
9688 depth
, format
, type
, pixels
);
9689 return error::kNoError
;
9692 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9693 uint32 immediate_data_size
,
9694 const void* cmd_data
) {
9695 const gles2::cmds::GetVertexAttribPointerv
& c
=
9696 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
9697 GLuint index
= static_cast<GLuint
>(c
.index
);
9698 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9699 typedef cmds::GetVertexAttribPointerv::Result Result
;
9700 Result
* result
= GetSharedMemoryAs
<Result
*>(
9701 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
9703 return error::kOutOfBounds
;
9705 // Check that the client initialized the result.
9706 if (result
->size
!= 0) {
9707 return error::kInvalidArguments
;
9709 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
9710 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9711 "glGetVertexAttribPointerv", pname
, "pname");
9712 return error::kNoError
;
9714 if (index
>= group_
->max_vertex_attribs()) {
9716 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
9717 return error::kNoError
;
9719 result
->SetNumResults(1);
9720 *result
->GetData() =
9721 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
9722 return error::kNoError
;
9725 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
9726 GLint fake_location
,
9729 error::Error
* error
,
9730 GLint
* real_location
,
9732 void** result_pointer
,
9733 GLenum
* result_type
,
9734 GLsizei
* result_size
) {
9737 DCHECK(result_pointer
);
9738 DCHECK(result_type
);
9739 DCHECK(real_location
);
9740 *error
= error::kNoError
;
9741 // Make sure we have enough room for the result on failure.
9742 SizedResult
<GLint
>* result
;
9743 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9744 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSize(0));
9746 *error
= error::kOutOfBounds
;
9749 *result_pointer
= result
;
9750 // Set the result size to 0 so the client does not have to check for success.
9751 result
->SetNumResults(0);
9752 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
9756 if (!program
->IsValid()) {
9757 // Program was not linked successfully. (ie, glLinkProgram)
9759 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
9762 *service_id
= program
->service_id();
9763 GLint array_index
= -1;
9764 const Program::UniformInfo
* uniform_info
=
9765 program
->GetUniformInfoByFakeLocation(
9766 fake_location
, real_location
, &array_index
);
9767 if (!uniform_info
) {
9768 // No such location.
9770 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
9773 GLenum type
= uniform_info
->type
;
9774 GLsizei size
= GLES2Util::GetGLDataTypeSizeForUniforms(type
);
9776 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
9779 result
= GetSharedMemoryAs
<SizedResult
<GLint
>*>(
9780 shm_id
, shm_offset
, SizedResult
<GLint
>::ComputeSizeFromBytes(size
));
9782 *error
= error::kOutOfBounds
;
9785 result
->size
= size
;
9786 *result_size
= size
;
9787 *result_type
= type
;
9791 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
9792 const void* cmd_data
) {
9793 const gles2::cmds::GetUniformiv
& c
=
9794 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
9795 GLuint program
= c
.program
;
9796 GLint fake_location
= c
.location
;
9799 GLsizei result_size
;
9800 GLint real_location
= -1;
9803 if (GetUniformSetup(program
, fake_location
, c
.params_shm_id
,
9804 c
.params_shm_offset
, &error
, &real_location
, &service_id
,
9805 &result
, &result_type
, &result_size
)) {
9807 service_id
, real_location
,
9808 static_cast<cmds::GetUniformiv::Result
*>(result
)->GetData());
9813 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
9814 const void* cmd_data
) {
9815 const gles2::cmds::GetUniformfv
& c
=
9816 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
9817 GLuint program
= c
.program
;
9818 GLint fake_location
= c
.location
;
9820 GLint real_location
= -1;
9822 typedef cmds::GetUniformfv::Result Result
;
9825 GLsizei result_size
;
9826 if (GetUniformSetup(program
, fake_location
, c
.params_shm_id
,
9827 c
.params_shm_offset
, &error
, &real_location
, &service_id
,
9828 reinterpret_cast<void**>(&result
), &result_type
,
9830 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
9831 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
9832 GLsizei num_values
= result_size
/ sizeof(Result::Type
);
9833 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
9834 glGetUniformiv(service_id
, real_location
, temp
.get());
9835 GLfloat
* dst
= result
->GetData();
9836 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
9837 dst
[ii
] = (temp
[ii
] != 0);
9840 glGetUniformfv(service_id
, real_location
, result
->GetData());
9846 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9847 uint32 immediate_data_size
,
9848 const void* cmd_data
) {
9849 const gles2::cmds::GetShaderPrecisionFormat
& c
=
9850 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
9851 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
9852 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
9853 typedef cmds::GetShaderPrecisionFormat::Result Result
;
9854 Result
* result
= GetSharedMemoryAs
<Result
*>(
9855 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9857 return error::kOutOfBounds
;
9859 // Check that the client initialized the result.
9860 if (result
->success
!= 0) {
9861 return error::kInvalidArguments
;
9863 if (!validators_
->shader_type
.IsValid(shader_type
)) {
9864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9865 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
9866 return error::kNoError
;
9868 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
9869 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9870 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
9871 return error::kNoError
;
9874 result
->success
= 1; // true
9876 GLint range
[2] = { 0, 0 };
9877 GLint precision
= 0;
9878 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
9880 result
->min_range
= range
[0];
9881 result
->max_range
= range
[1];
9882 result
->precision
= precision
;
9884 return error::kNoError
;
9887 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
9888 uint32 immediate_data_size
,
9889 const void* cmd_data
) {
9890 const gles2::cmds::GetAttachedShaders
& c
=
9891 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
9892 uint32 result_size
= c
.result_size
;
9893 GLuint program_id
= static_cast<GLuint
>(c
.program
);
9894 Program
* program
= GetProgramInfoNotShader(
9895 program_id
, "glGetAttachedShaders");
9897 return error::kNoError
;
9899 typedef cmds::GetAttachedShaders::Result Result
;
9900 uint32 max_count
= Result::ComputeMaxResults(result_size
);
9901 Result
* result
= GetSharedMemoryAs
<Result
*>(
9902 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
9904 return error::kOutOfBounds
;
9906 // Check that the client initialized the result.
9907 if (result
->size
!= 0) {
9908 return error::kInvalidArguments
;
9911 glGetAttachedShaders(
9912 program
->service_id(), max_count
, &count
, result
->GetData());
9913 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
9914 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
9915 &result
->GetData()[ii
])) {
9917 return error::kGenericError
;
9920 result
->SetNumResults(count
);
9921 return error::kNoError
;
9924 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
9925 uint32 immediate_data_size
,
9926 const void* cmd_data
) {
9927 const gles2::cmds::GetActiveUniform
& c
=
9928 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
9929 GLuint program_id
= c
.program
;
9930 GLuint index
= c
.index
;
9931 uint32 name_bucket_id
= c
.name_bucket_id
;
9932 typedef cmds::GetActiveUniform::Result Result
;
9933 Result
* result
= GetSharedMemoryAs
<Result
*>(
9934 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
9936 return error::kOutOfBounds
;
9938 // Check that the client initialized the result.
9939 if (result
->success
!= 0) {
9940 return error::kInvalidArguments
;
9942 Program
* program
= GetProgramInfoNotShader(
9943 program_id
, "glGetActiveUniform");
9945 return error::kNoError
;
9947 const Program::UniformInfo
* uniform_info
=
9948 program
->GetUniformInfo(index
);
9949 if (!uniform_info
) {
9951 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
9952 return error::kNoError
;
9954 result
->success
= 1; // true.
9955 result
->size
= uniform_info
->size
;
9956 result
->type
= uniform_info
->type
;
9957 Bucket
* bucket
= CreateBucket(name_bucket_id
);
9958 bucket
->SetFromString(uniform_info
->name
.c_str());
9959 return error::kNoError
;
9962 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
9963 uint32 immediate_data_size
, const void* cmd_data
) {
9964 if (!unsafe_es3_apis_enabled())
9965 return error::kUnknownCommand
;
9966 const gles2::cmds::GetActiveUniformBlockiv
& c
=
9967 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
9968 GLuint program_id
= c
.program
;
9969 GLuint index
= static_cast<GLuint
>(c
.index
);
9970 GLenum pname
= static_cast<GLenum
>(c
.pname
);
9971 Program
* program
= GetProgramInfoNotShader(
9972 program_id
, "glGetActiveUniformBlockiv");
9974 return error::kNoError
;
9976 GLuint service_id
= program
->service_id();
9977 GLint link_status
= GL_FALSE
;
9978 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9979 if (link_status
!= GL_TRUE
) {
9980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9981 "glGetActiveActiveUniformBlockiv", "program not linked");
9982 return error::kNoError
;
9984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
9985 GLsizei num_values
= 1;
9986 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
9988 glGetActiveUniformBlockiv(
9989 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
9990 GLenum error
= glGetError();
9991 if (error
!= GL_NO_ERROR
) {
9992 // Assume this will the same error if calling with pname.
9993 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
9994 return error::kNoError
;
9996 num_values
= static_cast<GLsizei
>(num
);
9998 typedef cmds::GetActiveUniformBlockiv::Result Result
;
9999 Result
* result
= GetSharedMemoryAs
<Result
*>(
10000 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
10001 GLint
* params
= result
? result
->GetData() : NULL
;
10002 if (params
== NULL
) {
10003 return error::kOutOfBounds
;
10005 // Check that the client initialized the result.
10006 if (result
->size
!= 0) {
10007 return error::kInvalidArguments
;
10009 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
10010 GLenum error
= glGetError();
10011 if (error
== GL_NO_ERROR
) {
10012 result
->SetNumResults(num_values
);
10014 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
10016 return error::kNoError
;
10019 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
10020 uint32 immediate_data_size
, const void* cmd_data
) {
10021 if (!unsafe_es3_apis_enabled())
10022 return error::kUnknownCommand
;
10023 const gles2::cmds::GetActiveUniformBlockName
& c
=
10024 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
10025 GLuint program_id
= c
.program
;
10026 GLuint index
= c
.index
;
10027 uint32 name_bucket_id
= c
.name_bucket_id
;
10028 typedef cmds::GetActiveUniformBlockName::Result Result
;
10029 Result
* result
= GetSharedMemoryAs
<Result
*>(
10030 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10032 return error::kOutOfBounds
;
10034 // Check that the client initialized the result.
10035 if (*result
!= 0) {
10036 return error::kInvalidArguments
;
10038 Program
* program
= GetProgramInfoNotShader(
10039 program_id
, "glGetActiveUniformBlockName");
10041 return error::kNoError
;
10043 GLuint service_id
= program
->service_id();
10044 GLint link_status
= GL_FALSE
;
10045 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10046 if (link_status
!= GL_TRUE
) {
10047 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10048 "glGetActiveActiveUniformBlockName", "program not linked");
10049 return error::kNoError
;
10051 GLint max_length
= 0;
10053 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
10054 // Increase one so &buffer[0] is always valid.
10055 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
10056 std::vector
<char> buffer(buf_size
);
10057 GLsizei length
= 0;
10058 glGetActiveUniformBlockName(
10059 service_id
, index
, buf_size
, &length
, &buffer
[0]);
10062 return error::kNoError
;
10065 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10066 DCHECK_GT(buf_size
, length
);
10067 DCHECK_EQ(0, buffer
[length
]);
10068 bucket
->SetFromString(&buffer
[0]);
10069 return error::kNoError
;
10072 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
10073 uint32 immediate_data_size
, const void* cmd_data
) {
10074 if (!unsafe_es3_apis_enabled())
10075 return error::kUnknownCommand
;
10076 const gles2::cmds::GetActiveUniformsiv
& c
=
10077 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
10078 GLuint program_id
= c
.program
;
10079 GLenum pname
= static_cast<GLenum
>(c
.pname
);
10080 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
10082 return error::kInvalidArguments
;
10084 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
10085 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
10086 typedef cmds::GetActiveUniformsiv::Result Result
;
10087 Result
* result
= GetSharedMemoryAs
<Result
*>(
10088 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
10089 GLint
* params
= result
? result
->GetData() : NULL
;
10090 if (params
== NULL
) {
10091 return error::kOutOfBounds
;
10093 // Check that the client initialized the result.
10094 if (result
->size
!= 0) {
10095 return error::kInvalidArguments
;
10097 Program
* program
= GetProgramInfoNotShader(
10098 program_id
, "glGetActiveUniformsiv");
10100 return error::kNoError
;
10102 GLuint service_id
= program
->service_id();
10103 GLint link_status
= GL_FALSE
;
10104 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10105 if (link_status
!= GL_TRUE
) {
10106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10107 "glGetActiveUniformsiv", "program not linked");
10108 return error::kNoError
;
10110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
10111 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
10112 GLenum error
= glGetError();
10113 if (error
== GL_NO_ERROR
) {
10114 result
->SetNumResults(count
);
10116 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
10118 return error::kNoError
;
10121 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
10122 const void* cmd_data
) {
10123 const gles2::cmds::GetActiveAttrib
& c
=
10124 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
10125 GLuint program_id
= c
.program
;
10126 GLuint index
= c
.index
;
10127 uint32 name_bucket_id
= c
.name_bucket_id
;
10128 typedef cmds::GetActiveAttrib::Result Result
;
10129 Result
* result
= GetSharedMemoryAs
<Result
*>(
10130 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10132 return error::kOutOfBounds
;
10134 // Check that the client initialized the result.
10135 if (result
->success
!= 0) {
10136 return error::kInvalidArguments
;
10138 Program
* program
= GetProgramInfoNotShader(
10139 program_id
, "glGetActiveAttrib");
10141 return error::kNoError
;
10143 const Program::VertexAttrib
* attrib_info
=
10144 program
->GetAttribInfo(index
);
10145 if (!attrib_info
) {
10146 LOCAL_SET_GL_ERROR(
10147 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
10148 return error::kNoError
;
10150 result
->success
= 1; // true.
10151 result
->size
= attrib_info
->size
;
10152 result
->type
= attrib_info
->type
;
10153 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10154 bucket
->SetFromString(attrib_info
->name
.c_str());
10155 return error::kNoError
;
10158 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
10159 const void* cmd_data
) {
10160 #if 1 // No binary shader support.
10161 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
10162 return error::kNoError
;
10164 GLsizei n
= static_cast<GLsizei
>(c
.n
);
10166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
10167 return error::kNoError
;
10169 GLsizei length
= static_cast<GLsizei
>(c
.length
);
10171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
10172 return error::kNoError
;
10175 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
10176 return error::kOutOfBounds
;
10178 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
10179 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
10180 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
10181 const void* binary
= GetSharedMemoryAs
<const void*>(
10182 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
10183 if (shaders
== NULL
|| binary
== NULL
) {
10184 return error::kOutOfBounds
;
10186 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10187 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10188 Shader
* shader
= GetShader(shaders
[ii
]);
10190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
10191 return error::kNoError
;
10193 service_ids
[ii
] = shader
->service_id();
10195 // TODO(gman): call glShaderBinary
10196 return error::kNoError
;
10200 void GLES2DecoderImpl::DoSwapBuffers() {
10201 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
10203 int this_frame_number
= frame_number_
++;
10204 // TRACE_EVENT for gpu tests:
10205 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
10206 TRACE_EVENT_SCOPE_THREAD
,
10207 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
10208 "width", (is_offscreen
? offscreen_size_
.width() :
10209 surface_
->GetSize().width()));
10210 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
10211 "offscreen", is_offscreen
,
10212 "frame", this_frame_number
);
10214 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
10217 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
10218 "gpu_toplevel", "SwapBuffer");
10221 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
10224 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
10225 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
10226 is_offscreen
? offscreen_size_
: surface_
->GetSize());
10229 // If offscreen then don't actually SwapBuffers to the display. Just copy
10230 // the rendered frame to another frame buffer.
10231 if (is_offscreen
) {
10232 TRACE_EVENT2("gpu", "Offscreen",
10233 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
10234 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
10235 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
10236 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
10238 if (workarounds().needs_offscreen_buffer_workaround
) {
10239 offscreen_saved_frame_buffer_
->Create();
10243 // Allocate the offscreen saved color texture.
10244 DCHECK(offscreen_saved_color_format_
);
10245 offscreen_saved_color_texture_
->AllocateStorage(
10246 offscreen_size_
, offscreen_saved_color_format_
, false);
10248 offscreen_saved_frame_buffer_
->AttachRenderTexture(
10249 offscreen_saved_color_texture_
.get());
10250 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
10251 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
10252 GL_FRAMEBUFFER_COMPLETE
) {
10253 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
10254 << "because offscreen saved FBO was incomplete.";
10255 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10259 // Clear the offscreen color texture.
10260 // TODO(piman): Is this still necessary?
10262 ScopedFrameBufferBinder
binder(this,
10263 offscreen_saved_frame_buffer_
->id());
10264 glClearColor(0, 0, 0, 0);
10265 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
10266 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
10267 glClear(GL_COLOR_BUFFER_BIT
);
10268 RestoreClearState();
10272 UpdateParentTextureInfo();
10275 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
10277 ScopedGLErrorSuppressor
suppressor(
10278 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
10280 if (IsOffscreenBufferMultisampled()) {
10281 // For multisampled buffers, resolve the frame buffer.
10282 ScopedResolvedFrameBufferBinder
binder(this, true, false);
10284 ScopedFrameBufferBinder
binder(this,
10285 offscreen_target_frame_buffer_
->id());
10287 if (offscreen_target_buffer_preserved_
) {
10288 // Copy the target frame buffer to the saved offscreen texture.
10289 offscreen_saved_color_texture_
->Copy(
10290 offscreen_saved_color_texture_
->size(),
10291 offscreen_saved_color_format_
);
10293 // Flip the textures in the parent context via the texture manager.
10294 if (!!offscreen_saved_color_texture_info_
.get())
10295 offscreen_saved_color_texture_info_
->texture()->
10296 SetServiceId(offscreen_target_color_texture_
->id());
10298 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
10299 offscreen_target_frame_buffer_
->AttachRenderTexture(
10300 offscreen_target_color_texture_
.get());
10303 // Ensure the side effects of the copy are visible to the parent
10304 // context. There is no need to do this for ANGLE because it uses a
10305 // single D3D device for all contexts.
10306 if (!feature_info_
->gl_version_info().is_angle
)
10310 if (!surface_
->SwapBuffers()) {
10311 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
10312 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB
);
10316 // This may be a slow command. Exit command processing to allow for
10317 // context preemption and GPU watchdog checks.
10318 ExitCommandProcessingEarly();
10321 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
10322 context_
->SetSwapInterval(interval
);
10325 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
10326 uint32 immediate_data_size
,
10327 const void* cmd_data
) {
10328 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
10329 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
10330 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10331 if (!bucket
|| bucket
->size() == 0) {
10332 return error::kInvalidArguments
;
10334 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
10335 Result
* result
= GetSharedMemoryAs
<Result
*>(
10336 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10338 return error::kOutOfBounds
;
10340 // Check that the client initialized the result.
10341 if (*result
!= 0) {
10342 return error::kInvalidArguments
;
10344 std::string feature_str
;
10345 if (!bucket
->GetAsString(&feature_str
)) {
10346 return error::kInvalidArguments
;
10349 // TODO(gman): make this some kind of table to function pointer thingy.
10350 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
10351 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
10352 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
10353 buffer_manager()->set_allow_fixed_attribs(true);
10354 // TODO(gman): decide how to remove the need for this const_cast.
10355 // I could make validators_ non const but that seems bad as this is the only
10356 // place it is needed. I could make some special friend class of validators
10357 // just to allow this to set them. That seems silly. I could refactor this
10358 // code to use the extension mechanism or the initialization attributes to
10359 // turn this feature on. Given that the only real point of this is to make
10360 // the conformance tests pass and given that there is lots of real work that
10361 // needs to be done it seems like refactoring for one to one of those
10362 // methods is a very low priority.
10363 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
10364 } else if (feature_str
.compare("webgl_enable_glsl_webgl_validation") == 0) {
10365 force_webgl_glsl_validation_
= true;
10366 InitializeShaderTranslator();
10368 return error::kNoError
;
10371 *result
= 1; // true.
10372 return error::kNoError
;
10375 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
10376 uint32 immediate_data_size
,
10377 const void* cmd_data
) {
10378 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
10379 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
10381 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
10382 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
10383 info
->Initialize(disallowed_features_
);
10384 bucket
->SetFromString(info
->extensions().c_str());
10385 return error::kNoError
;
10388 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
10389 uint32 immediate_data_size
,
10390 const void* cmd_data
) {
10391 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
10392 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
10393 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10394 if (!bucket
|| bucket
->size() == 0) {
10395 return error::kInvalidArguments
;
10397 std::string feature_str
;
10398 if (!bucket
->GetAsString(&feature_str
)) {
10399 return error::kInvalidArguments
;
10402 bool desire_webgl_glsl_validation
=
10403 feature_str
.find("GL_CHROMIUM_webglsl") != std::string::npos
;
10404 bool desire_standard_derivatives
= false;
10405 bool desire_frag_depth
= false;
10406 bool desire_draw_buffers
= false;
10407 bool desire_shader_texture_lod
= false;
10408 if (force_webgl_glsl_validation_
) {
10409 desire_standard_derivatives
=
10410 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
10411 desire_frag_depth
=
10412 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
10413 desire_draw_buffers
=
10414 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
10415 desire_shader_texture_lod
=
10416 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
10419 if (desire_webgl_glsl_validation
!= force_webgl_glsl_validation_
||
10420 desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
10421 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
10422 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
) {
10423 force_webgl_glsl_validation_
|= desire_webgl_glsl_validation
;
10424 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
10425 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
10426 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
10427 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
10428 InitializeShaderTranslator();
10431 UpdateCapabilities();
10433 return error::kNoError
;
10436 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10437 uint32 immediate_data_size
,
10438 const void* cmd_data
) {
10439 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
10440 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
10441 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10442 uint32 bucket_id
= c
.bucket_id
;
10443 Bucket
* bucket
= CreateBucket(bucket_id
);
10444 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
10445 Program
* program
= NULL
;
10446 program
= GetProgram(program_id
);
10447 if (!program
|| !program
->IsValid()) {
10448 return error::kNoError
;
10450 program
->GetProgramInfo(program_manager(), bucket
);
10451 return error::kNoError
;
10454 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
10455 uint32 immediate_data_size
, const void* cmd_data
) {
10456 if (!unsafe_es3_apis_enabled())
10457 return error::kUnknownCommand
;
10458 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
10459 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
10460 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10461 uint32 bucket_id
= c
.bucket_id
;
10462 Bucket
* bucket
= CreateBucket(bucket_id
);
10463 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
10464 Program
* program
= NULL
;
10465 program
= GetProgram(program_id
);
10466 if (!program
|| !program
->IsValid()) {
10467 return error::kNoError
;
10469 program
->GetUniformBlocks(bucket
);
10470 return error::kNoError
;
10473 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
10474 uint32 immediate_data_size
, const void* cmd_data
) {
10475 if (!unsafe_es3_apis_enabled())
10476 return error::kUnknownCommand
;
10477 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
10478 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
10479 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10480 uint32 bucket_id
= c
.bucket_id
;
10481 Bucket
* bucket
= CreateBucket(bucket_id
);
10482 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
10483 Program
* program
= NULL
;
10484 program
= GetProgram(program_id
);
10485 if (!program
|| !program
->IsValid()) {
10486 return error::kNoError
;
10488 program
->GetUniformsES3(bucket
);
10489 return error::kNoError
;
10492 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
10493 uint32 immediate_data_size
,
10494 const void* cmd_data
) {
10495 if (!unsafe_es3_apis_enabled())
10496 return error::kUnknownCommand
;
10497 const gles2::cmds::GetTransformFeedbackVarying
& c
=
10498 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
10499 GLuint program_id
= c
.program
;
10500 GLuint index
= c
.index
;
10501 uint32 name_bucket_id
= c
.name_bucket_id
;
10502 typedef cmds::GetTransformFeedbackVarying::Result Result
;
10503 Result
* result
= GetSharedMemoryAs
<Result
*>(
10504 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
10506 return error::kOutOfBounds
;
10508 // Check that the client initialized the result.
10509 if (result
->success
!= 0) {
10510 return error::kInvalidArguments
;
10512 Program
* program
= GetProgramInfoNotShader(
10513 program_id
, "glGetTransformFeedbackVarying");
10515 return error::kNoError
;
10517 GLuint service_id
= program
->service_id();
10518 GLint link_status
= GL_FALSE
;
10519 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
10520 if (link_status
!= GL_TRUE
) {
10521 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10522 "glGetTransformFeedbackVarying", "program not linked");
10523 return error::kNoError
;
10525 GLint max_length
= 0;
10527 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
10528 max_length
= std::max(1, max_length
);
10529 std::vector
<char> buffer(max_length
);
10530 GLsizei length
= 0;
10533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
10534 glGetTransformFeedbackVarying(
10535 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
10536 GLenum error
= glGetError();
10537 if (error
!= GL_NO_ERROR
) {
10538 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
10539 return error::kNoError
;
10541 result
->success
= 1; // true.
10542 result
->size
= static_cast<int32_t>(size
);
10543 result
->type
= static_cast<uint32_t>(type
);
10544 Bucket
* bucket
= CreateBucket(name_bucket_id
);
10545 DCHECK(length
>= 0 && length
< max_length
);
10546 buffer
[length
] = '\0'; // Just to be safe.
10547 bucket
->SetFromString(&buffer
[0]);
10548 return error::kNoError
;
10551 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
10552 uint32 immediate_data_size
, const void* cmd_data
) {
10553 if (!unsafe_es3_apis_enabled())
10554 return error::kUnknownCommand
;
10555 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
10556 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
10558 GLuint program_id
= static_cast<GLuint
>(c
.program
);
10559 uint32 bucket_id
= c
.bucket_id
;
10560 Bucket
* bucket
= CreateBucket(bucket_id
);
10561 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
10562 Program
* program
= NULL
;
10563 program
= GetProgram(program_id
);
10564 if (!program
|| !program
->IsValid()) {
10565 return error::kNoError
;
10567 program
->GetTransformFeedbackVaryings(bucket
);
10568 return error::kNoError
;
10571 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
10572 switch (reset_status_
) {
10574 // TODO(kbr): improve the precision of the error code in this case.
10575 // Consider delegating to context for error code if MakeCurrent fails.
10576 return error::kUnknown
;
10577 case GL_GUILTY_CONTEXT_RESET_ARB
:
10578 return error::kGuilty
;
10579 case GL_INNOCENT_CONTEXT_RESET_ARB
:
10580 return error::kInnocent
;
10581 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
10582 return error::kUnknown
;
10586 return error::kUnknown
;
10589 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10590 // Some D3D drivers cannot recover from device lost in the GPU process
10591 // sandbox. Allow a new GPU process to launch.
10592 if (workarounds().exit_on_context_lost
) {
10593 LOG(ERROR
) << "Exiting GPU process because some drivers cannot reset"
10594 << " a D3D device in the Chrome GPU process sandbox.";
10595 #if defined(OS_WIN)
10596 base::win::SetShouldCrashOnProcessDetach(false);
10602 bool GLES2DecoderImpl::WasContextLost() {
10603 if (reset_status_
!= GL_NO_ERROR
) {
10604 MaybeExitOnContextLost();
10607 if (IsRobustnessSupported()) {
10608 GLenum status
= glGetGraphicsResetStatusARB();
10609 if (status
!= GL_NO_ERROR
) {
10610 // The graphics card was reset. Signal a lost context to the application.
10611 reset_status_
= status
;
10612 reset_by_robustness_extension_
= true;
10613 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
10614 << " context lost via ARB/EXT_robustness. Reset status = "
10615 << GLES2Util::GetStringEnum(status
);
10616 MaybeExitOnContextLost();
10623 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10624 return WasContextLost() && reset_by_robustness_extension_
;
10627 void GLES2DecoderImpl::LoseContext(uint32 reset_status
) {
10628 // Only loses the context once.
10629 if (reset_status_
!= GL_NO_ERROR
) {
10633 if (workarounds().use_virtualized_gl_contexts
) {
10634 // If the context is virtual, the real context being guilty does not ensure
10635 // that the virtual context is guilty.
10636 if (reset_status
== GL_GUILTY_CONTEXT_RESET_ARB
) {
10637 reset_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
10639 } else if (reset_status
== GL_UNKNOWN_CONTEXT_RESET_ARB
&&
10640 IsRobustnessSupported()) {
10641 // If the reason for the call was a GL error, we can try to determine the
10642 // reset status more accurately.
10643 GLenum driver_status
= glGetGraphicsResetStatusARB();
10644 if (driver_status
== GL_GUILTY_CONTEXT_RESET_ARB
||
10645 driver_status
== GL_INNOCENT_CONTEXT_RESET_ARB
) {
10646 reset_status
= driver_status
;
10650 // Marks this context as lost.
10651 reset_status_
= reset_status
;
10652 current_decoder_error_
= error::kLostContext
;
10655 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10656 uint32 immediate_data_size
,
10657 const void* cmd_data
) {
10658 return error::kUnknownCommand
;
10661 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10662 uint32 immediate_data_size
,
10663 const void* cmd_data
) {
10664 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
10665 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
10666 uint32 sync_point
= c
.sync_point
;
10667 if (wait_sync_point_callback_
.is_null())
10668 return error::kNoError
;
10670 return wait_sync_point_callback_
.Run(sync_point
) ?
10671 error::kNoError
: error::kDeferCommandUntilLater
;
10674 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10675 uint32 immediate_data_size
,
10676 const void* cmd_data
) {
10677 if (surface_
->DeferDraws())
10678 return error::kDeferCommandUntilLater
;
10679 if (!surface_
->SetBackbufferAllocation(false))
10680 return error::kLostContext
;
10681 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
10682 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
10683 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
10684 return error::kNoError
;
10687 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10688 GLsizei n
, const GLuint
* client_ids
) {
10689 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10690 if (query_manager_
->GetQuery(client_ids
[ii
])) {
10694 query_manager_
->GenQueries(n
, client_ids
);
10698 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10699 GLsizei n
, const GLuint
* client_ids
) {
10700 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10701 QueryManager::Query
* query
= query_manager_
->GetQuery(client_ids
[ii
]);
10702 if (query
&& !query
->IsDeleted()) {
10703 ContextState::QueryMap::iterator it
=
10704 state_
.current_queries
.find(query
->target());
10705 if (it
!= state_
.current_queries
.end())
10706 state_
.current_queries
.erase(it
);
10708 query
->Destroy(true);
10710 query_manager_
->RemoveQuery(client_ids
[ii
]);
10714 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
10715 if (query_manager_
.get() == NULL
) {
10718 if (!query_manager_
->ProcessPendingQueries(did_finish
)) {
10719 current_decoder_error_
= error::kOutOfBounds
;
10721 return query_manager_
->HavePendingQueries();
10724 // Note that if there are no pending readpixels right now,
10725 // this function will call the callback immediately.
10726 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
10727 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
10728 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
10734 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10735 while (!pending_readpixel_fences_
.empty() &&
10736 pending_readpixel_fences_
.front()->fence
->HasCompleted()) {
10737 std::vector
<base::Closure
> callbacks
=
10738 pending_readpixel_fences_
.front()->callbacks
;
10739 pending_readpixel_fences_
.pop();
10740 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
10741 callbacks
[i
].Run();
10746 bool GLES2DecoderImpl::HasMoreIdleWork() {
10747 return !pending_readpixel_fences_
.empty() ||
10748 async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers();
10751 void GLES2DecoderImpl::PerformIdleWork() {
10752 ProcessPendingReadPixels();
10753 if (!async_pixel_transfer_manager_
->NeedsProcessMorePendingTransfers())
10755 async_pixel_transfer_manager_
->ProcessMorePendingTransfers();
10756 ProcessFinishedAsyncTransfers();
10759 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
10760 const void* cmd_data
) {
10761 const gles2::cmds::BeginQueryEXT
& c
=
10762 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
10763 GLenum target
= static_cast<GLenum
>(c
.target
);
10764 GLuint client_id
= static_cast<GLuint
>(c
.id
);
10765 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
10766 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
10769 case GL_COMMANDS_ISSUED_CHROMIUM
:
10770 case GL_LATENCY_QUERY_CHROMIUM
:
10771 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM
:
10772 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
10773 case GL_GET_ERROR_QUERY_CHROMIUM
:
10775 case GL_COMMANDS_COMPLETED_CHROMIUM
:
10776 if (!features().chromium_sync_query
) {
10777 LOCAL_SET_GL_ERROR(
10778 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10779 "not enabled for commands completed queries");
10780 return error::kNoError
;
10784 if (!features().occlusion_query_boolean
) {
10785 LOCAL_SET_GL_ERROR(
10786 GL_INVALID_OPERATION
, "glBeginQueryEXT",
10787 "not enabled for occlusion queries");
10788 return error::kNoError
;
10793 if (state_
.current_queries
.find(target
) != state_
.current_queries
.end()) {
10794 LOCAL_SET_GL_ERROR(
10795 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
10796 return error::kNoError
;
10799 if (client_id
== 0) {
10800 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
10801 return error::kNoError
;
10804 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
10806 if (!query_manager_
->IsValidQuery(client_id
)) {
10807 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
10809 "id not made by glGenQueriesEXT");
10810 return error::kNoError
;
10812 query
= query_manager_
->CreateQuery(
10813 target
, client_id
, sync_shm_id
, sync_shm_offset
);
10816 if (query
->target() != target
) {
10817 LOCAL_SET_GL_ERROR(
10818 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
10819 return error::kNoError
;
10820 } else if (query
->shm_id() != sync_shm_id
||
10821 query
->shm_offset() != sync_shm_offset
) {
10822 DLOG(ERROR
) << "Shared memory used by query not the same as before";
10823 return error::kInvalidArguments
;
10826 if (!query_manager_
->BeginQuery(query
)) {
10827 return error::kOutOfBounds
;
10830 state_
.current_queries
[target
] = query
;
10831 return error::kNoError
;
10834 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
10835 const void* cmd_data
) {
10836 const gles2::cmds::EndQueryEXT
& c
=
10837 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
10838 GLenum target
= static_cast<GLenum
>(c
.target
);
10839 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
10840 ContextState::QueryMap::iterator it
= state_
.current_queries
.find(target
);
10842 if (it
== state_
.current_queries
.end()) {
10843 LOCAL_SET_GL_ERROR(
10844 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
10845 return error::kNoError
;
10848 QueryManager::Query
* query
= it
->second
.get();
10849 if (!query_manager_
->EndQuery(query
, submit_count
)) {
10850 return error::kOutOfBounds
;
10853 query_manager_
->ProcessPendingTransferQueries();
10855 state_
.current_queries
.erase(it
);
10856 return error::kNoError
;
10859 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10860 GLsizei n
, const GLuint
* client_ids
) {
10861 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10862 if (GetVertexAttribManager(client_ids
[ii
])) {
10867 if (!features().native_vertex_array_object
) {
10869 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10870 CreateVertexAttribManager(client_ids
[ii
], 0, true);
10873 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
10875 glGenVertexArraysOES(n
, service_ids
.get());
10876 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10877 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
10884 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10885 GLsizei n
, const GLuint
* client_ids
) {
10886 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
10887 VertexAttribManager
* vao
=
10888 GetVertexAttribManager(client_ids
[ii
]);
10889 if (vao
&& !vao
->IsDeleted()) {
10890 if (state_
.vertex_attrib_manager
.get() == vao
) {
10891 DoBindVertexArrayOES(0);
10893 RemoveVertexAttribManager(client_ids
[ii
]);
10898 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
10899 VertexAttribManager
* vao
= NULL
;
10900 if (client_id
!= 0) {
10901 vao
= GetVertexAttribManager(client_id
);
10903 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10904 // only allows names that have been previously generated. As such, we do
10905 // not generate new names here.
10906 LOCAL_SET_GL_ERROR(
10907 GL_INVALID_OPERATION
,
10908 "glBindVertexArrayOES", "bad vertex array id.");
10909 current_decoder_error_
= error::kNoError
;
10913 vao
= state_
.default_vertex_attrib_manager
.get();
10916 // Only set the VAO state if it's changed
10917 if (state_
.vertex_attrib_manager
.get() != vao
) {
10918 state_
.vertex_attrib_manager
= vao
;
10919 if (!features().native_vertex_array_object
) {
10920 EmulateVertexArrayState();
10922 GLuint service_id
= vao
->service_id();
10923 glBindVertexArrayOES(service_id
);
10928 // Used when OES_vertex_array_object isn't natively supported
10929 void GLES2DecoderImpl::EmulateVertexArrayState() {
10930 // Setup the Vertex attribute state
10931 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
10932 RestoreStateForAttrib(vv
, true);
10935 // Setup the element buffer
10936 Buffer
* element_array_buffer
=
10937 state_
.vertex_attrib_manager
->element_array_buffer();
10938 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
10939 element_array_buffer
? element_array_buffer
->service_id() : 0);
10942 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
10943 const VertexAttribManager
* vao
=
10944 GetVertexAttribManager(client_id
);
10945 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
10948 #if defined(OS_MACOSX)
10949 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
10950 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
10952 if (it
!= texture_to_io_surface_map_
.end()) {
10953 // Found a previous IOSurface bound to this texture; release it.
10954 IOSurfaceRef surface
= it
->second
;
10955 CFRelease(surface
);
10956 texture_to_io_surface_map_
.erase(it
);
10961 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10962 GLenum target
, GLsizei width
, GLsizei height
,
10963 GLuint io_surface_id
, GLuint plane
) {
10964 #if defined(OS_MACOSX)
10965 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
10966 LOCAL_SET_GL_ERROR(
10967 GL_INVALID_OPERATION
,
10968 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10972 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
10973 // This might be supported in the future, and if we could require
10974 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10975 // could delete a lot of code. For now, perform strict validation so we
10976 // know what's going on.
10977 LOCAL_SET_GL_ERROR(
10978 GL_INVALID_OPERATION
,
10979 "glTexImageIOSurface2DCHROMIUM",
10980 "requires TEXTURE_RECTANGLE_ARB target");
10984 // Default target might be conceptually valid, but disallow it to avoid
10986 TextureRef
* texture_ref
=
10987 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
10988 if (!texture_ref
) {
10989 LOCAL_SET_GL_ERROR(
10990 GL_INVALID_OPERATION
,
10991 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10995 // Look up the new IOSurface. Note that because of asynchrony
10996 // between processes this might fail; during live resizing the
10997 // plugin process might allocate and release an IOSurface before
10998 // this process gets a chance to look it up. Hold on to any old
10999 // IOSurface in this case.
11000 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
11002 LOCAL_SET_GL_ERROR(
11003 GL_INVALID_OPERATION
,
11004 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
11008 // Release any IOSurface previously bound to this texture.
11009 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
11011 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
11012 texture_to_io_surface_map_
.insert(
11013 std::make_pair(texture_ref
->service_id(), surface
));
11015 CGLContextObj context
=
11016 static_cast<CGLContextObj
>(context_
->GetHandle());
11018 CGLError err
= CGLTexImageIOSurface2D(
11025 GL_UNSIGNED_INT_8_8_8_8_REV
,
11029 if (err
!= kCGLNoError
) {
11030 LOCAL_SET_GL_ERROR(
11031 GL_INVALID_OPERATION
,
11032 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
11036 texture_manager()->SetLevelInfo(
11037 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0,
11038 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
, true);
11041 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11042 "glTexImageIOSurface2DCHROMIUM", "not supported.");
11046 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
11047 switch (internalformat
) {
11058 case GL_LUMINANCE8_ALPHA8_EXT
:
11059 return GL_LUMINANCE_ALPHA
;
11060 case GL_LUMINANCE8_EXT
:
11061 return GL_LUMINANCE
;
11062 case GL_ALPHA8_EXT
:
11064 case GL_RGBA32F_EXT
:
11066 case GL_RGB32F_EXT
:
11068 case GL_ALPHA32F_EXT
:
11070 case GL_LUMINANCE32F_EXT
:
11071 return GL_LUMINANCE
;
11072 case GL_LUMINANCE_ALPHA32F_EXT
:
11073 return GL_LUMINANCE_ALPHA
;
11074 case GL_RGBA16F_EXT
:
11076 case GL_RGB16F_EXT
:
11078 case GL_ALPHA16F_EXT
:
11080 case GL_LUMINANCE16F_EXT
:
11081 return GL_LUMINANCE
;
11082 case GL_LUMINANCE_ALPHA16F_EXT
:
11083 return GL_LUMINANCE_ALPHA
;
11085 return GL_BGRA_EXT
;
11086 case GL_SRGB8_ALPHA8_EXT
:
11087 return GL_SRGB_ALPHA_EXT
;
11093 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
11094 const char* function_name
,
11096 TextureRef
* source_texture_ref
,
11097 TextureRef
* dest_texture_ref
,
11098 GLenum dest_internal_format
) {
11099 if (!source_texture_ref
|| !dest_texture_ref
) {
11100 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
11104 if (GL_TEXTURE_2D
!= target
) {
11105 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11106 "invalid texture target");
11110 Texture
* source_texture
= source_texture_ref
->texture();
11111 Texture
* dest_texture
= dest_texture_ref
->texture();
11112 if (source_texture
== dest_texture
) {
11113 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11114 "source and destination textures are the same");
11118 if (dest_texture
->target() != GL_TEXTURE_2D
||
11119 (source_texture
->target() != GL_TEXTURE_2D
&&
11120 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
11121 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
11122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
11123 "invalid texture target binding");
11127 GLenum source_type
= 0;
11128 GLenum source_internal_format
= 0;
11129 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11130 &source_internal_format
);
11132 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
11133 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
11134 // renderable on some platforms.
11135 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
11136 dest_internal_format
== GL_RGBA
||
11137 dest_internal_format
== GL_BGRA_EXT
;
11138 bool valid_source_format
= source_internal_format
== GL_ALPHA
||
11139 source_internal_format
== GL_RGB
||
11140 source_internal_format
== GL_RGBA
||
11141 source_internal_format
== GL_LUMINANCE
||
11142 source_internal_format
== GL_LUMINANCE_ALPHA
||
11143 source_internal_format
== GL_BGRA_EXT
;
11144 if (!valid_source_format
|| !valid_dest_format
) {
11145 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
11146 "invalid internal format");
11152 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target
,
11155 GLenum internal_format
,
11156 GLenum dest_type
) {
11157 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
11159 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11160 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11161 Texture
* source_texture
= source_texture_ref
->texture();
11162 Texture
* dest_texture
= dest_texture_ref
->texture();
11163 int source_width
= 0;
11164 int source_height
= 0;
11165 gfx::GLImage
* image
=
11166 source_texture
->GetLevelImage(source_texture
->target(), 0);
11168 gfx::Size size
= image
->GetSize();
11169 source_width
= size
.width();
11170 source_height
= size
.height();
11171 if (source_width
<= 0 || source_height
<= 0) {
11172 LOCAL_SET_GL_ERROR(
11174 "glCopyTextureChromium", "invalid image size");
11178 if (!source_texture
->GetLevelSize(
11179 source_texture
->target(), 0, &source_width
, &source_height
)) {
11180 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
11181 "glCopyTextureChromium",
11182 "source texture has no level 0");
11186 // Check that this type of texture is allowed.
11187 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11188 source_width
, source_height
, 1)) {
11189 LOCAL_SET_GL_ERROR(
11190 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
11195 GLenum source_type
= 0;
11196 GLenum source_internal_format
= 0;
11197 source_texture
->GetLevelType(
11198 source_texture
->target(), 0, &source_type
, &source_internal_format
);
11200 if (dest_texture
->IsImmutable()) {
11201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
11202 "texture is immutable");
11206 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
11207 source_texture_ref
, dest_texture_ref
,
11208 internal_format
)) {
11212 // Clear the source texture if necessary.
11213 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11214 source_texture
->target(), 0)) {
11215 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
11216 "dimensions too big");
11220 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11221 // needed because it takes 10s of milliseconds to initialize.
11222 if (!copy_texture_CHROMIUM_
.get()) {
11223 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11224 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11225 copy_texture_CHROMIUM_
->Initialize(this);
11226 RestoreCurrentFramebufferBindings();
11227 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
11231 GLenum dest_type_previous
= dest_type
;
11232 GLenum dest_internal_format
= internal_format
;
11233 int dest_width
= 0;
11234 int dest_height
= 0;
11235 bool dest_level_defined
=
11236 dest_texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
);
11238 if (dest_level_defined
) {
11239 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
11240 &dest_internal_format
);
11243 // Resize the destination texture to the dimensions of the source texture.
11244 if (!dest_level_defined
|| dest_width
!= source_width
||
11245 dest_height
!= source_height
||
11246 dest_internal_format
!= internal_format
||
11247 dest_type_previous
!= dest_type
) {
11248 // Ensure that the glTexImage2D succeeds.
11249 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
11250 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11251 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
11252 0, internal_format
, dest_type
, NULL
);
11253 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
11254 if (error
!= GL_NO_ERROR
) {
11255 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
11259 texture_manager()->SetLevelInfo(
11260 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
11261 source_height
, 1, 0, internal_format
, dest_type
, true);
11263 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11267 ScopedModifyPixels
modify(dest_texture_ref
);
11269 // Try using GLImage::CopyTexImage when possible.
11270 bool unpack_premultiply_alpha_change
=
11271 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11272 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
) {
11273 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11274 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11278 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11280 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11281 // before presenting.
11282 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11283 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11284 // instead of using kIdentityMatrix crbug.com/226218.
11285 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
11286 this, source_texture
->target(), source_texture
->service_id(),
11287 dest_texture
->service_id(), source_width
, source_height
, unpack_flip_y_
,
11288 unpack_premultiply_alpha_
, unpack_unpremultiply_alpha_
,
11291 copy_texture_CHROMIUM_
->DoCopyTexture(
11292 this, source_texture
->target(), source_texture
->service_id(),
11293 source_internal_format
, dest_texture
->service_id(), internal_format
,
11294 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11295 unpack_unpremultiply_alpha_
);
11298 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11301 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target
,
11306 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
11308 TextureRef
* source_texture_ref
= GetTexture(source_id
);
11309 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
11310 Texture
* source_texture
= source_texture_ref
->texture();
11311 Texture
* dest_texture
= dest_texture_ref
->texture();
11312 int source_width
= 0;
11313 int source_height
= 0;
11314 gfx::GLImage
* image
=
11315 source_texture
->GetLevelImage(source_texture
->target(), 0);
11317 gfx::Size size
= image
->GetSize();
11318 source_width
= size
.width();
11319 source_height
= size
.height();
11320 if (source_width
<= 0 || source_height
<= 0) {
11321 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11322 "invalid image size");
11326 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
11327 &source_width
, &source_height
)) {
11328 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11329 "source texture has no level 0");
11333 // Check that this type of texture is allowed.
11334 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
11335 source_width
, source_height
, 1)) {
11336 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11337 "source texture bad dimensions");
11342 GLenum source_type
= 0;
11343 GLenum source_internal_format
= 0;
11344 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
11345 &source_internal_format
);
11346 GLenum dest_type
= 0;
11347 GLenum dest_internal_format
= 0;
11348 bool dest_level_defined
= dest_texture
->GetLevelType(
11349 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
11350 if (!dest_level_defined
) {
11351 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
11352 "destination texture is not defined");
11355 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
11356 yoffset
, source_width
, source_height
,
11358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
11359 "destination texture bad dimensions.");
11363 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
11364 source_texture_ref
, dest_texture_ref
,
11365 dest_internal_format
)) {
11369 // Clear the source texture if necessary.
11370 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
11371 source_texture
->target(), 0)) {
11372 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11373 "source texture dimensions too big");
11377 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
11378 // needed because it takes 10s of milliseconds to initialize.
11379 if (!copy_texture_CHROMIUM_
.get()) {
11380 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
11381 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
11382 copy_texture_CHROMIUM_
->Initialize(this);
11383 RestoreCurrentFramebufferBindings();
11384 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
11388 int dest_width
= 0;
11389 int dest_height
= 0;
11391 dest_texture
->GetLevelSize(GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
);
11393 if (xoffset
!= 0 || yoffset
!= 0 || source_width
!= dest_width
||
11394 source_height
!= dest_height
) {
11395 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
11397 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
11398 "destination texture dimensions too big");
11402 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
11406 ScopedModifyPixels
modify(dest_texture_ref
);
11408 // Try using GLImage::CopyTexSubImage when possible.
11409 bool unpack_premultiply_alpha_change
=
11410 unpack_premultiply_alpha_
^ unpack_unpremultiply_alpha_
;
11411 if (image
&& !unpack_flip_y_
&& !unpack_premultiply_alpha_change
&&
11412 !xoffset
&& !yoffset
) {
11413 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
11414 if (image
->CopyTexImage(GL_TEXTURE_2D
))
11418 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
11420 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
11421 // before presenting.
11422 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
11423 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
11424 // instead of using kIdentityMatrix crbug.com/226218.
11425 copy_texture_CHROMIUM_
->DoCopySubTextureWithTransform(
11426 this, source_texture
->target(), source_texture
->service_id(),
11427 dest_texture
->service_id(), xoffset
, yoffset
, dest_width
, dest_height
,
11428 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11429 unpack_unpremultiply_alpha_
, kIdentityMatrix
);
11431 copy_texture_CHROMIUM_
->DoCopySubTexture(
11432 this, source_texture
->target(), source_texture
->service_id(),
11433 source_internal_format
, dest_texture
->service_id(),
11434 dest_internal_format
, xoffset
, yoffset
, dest_width
, dest_height
,
11435 source_width
, source_height
, unpack_flip_y_
, unpack_premultiply_alpha_
,
11436 unpack_unpremultiply_alpha_
);
11439 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
11442 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
11443 switch (internalformat
) {
11445 return GL_UNSIGNED_SHORT_5_6_5
;
11447 return GL_UNSIGNED_SHORT_4_4_4_4
;
11449 return GL_UNSIGNED_SHORT_5_5_5_1
;
11451 return GL_UNSIGNED_BYTE
;
11453 return GL_UNSIGNED_BYTE
;
11454 case GL_LUMINANCE8_ALPHA8_EXT
:
11455 return GL_UNSIGNED_BYTE
;
11456 case GL_LUMINANCE8_EXT
:
11457 return GL_UNSIGNED_BYTE
;
11458 case GL_ALPHA8_EXT
:
11459 return GL_UNSIGNED_BYTE
;
11460 case GL_RGBA32F_EXT
:
11462 case GL_RGB32F_EXT
:
11464 case GL_ALPHA32F_EXT
:
11466 case GL_LUMINANCE32F_EXT
:
11468 case GL_LUMINANCE_ALPHA32F_EXT
:
11470 case GL_RGBA16F_EXT
:
11471 return GL_HALF_FLOAT_OES
;
11472 case GL_RGB16F_EXT
:
11473 return GL_HALF_FLOAT_OES
;
11474 case GL_ALPHA16F_EXT
:
11475 return GL_HALF_FLOAT_OES
;
11476 case GL_LUMINANCE16F_EXT
:
11477 return GL_HALF_FLOAT_OES
;
11478 case GL_LUMINANCE_ALPHA16F_EXT
:
11479 return GL_HALF_FLOAT_OES
;
11481 return GL_UNSIGNED_BYTE
;
11487 void GLES2DecoderImpl::DoTexStorage2DEXT(
11490 GLenum internal_format
,
11493 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
11494 "width", width
, "height", height
);
11495 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
11496 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
11497 LOCAL_SET_GL_ERROR(
11498 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
11501 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11503 if (!texture_ref
) {
11504 LOCAL_SET_GL_ERROR(
11505 GL_INVALID_OPERATION
,
11506 "glTexStorage2DEXT", "unknown texture for target");
11509 Texture
* texture
= texture_ref
->texture();
11510 if (texture
->IsAttachedToFramebuffer()) {
11511 framebuffer_state_
.clear_state_dirty
= true;
11513 if (texture
->IsImmutable()) {
11514 LOCAL_SET_GL_ERROR(
11515 GL_INVALID_OPERATION
,
11516 "glTexStorage2DEXT", "texture is immutable");
11520 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
11521 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
11524 GLsizei level_width
= width
;
11525 GLsizei level_height
= height
;
11526 uint32 estimated_size
= 0;
11527 for (int ii
= 0; ii
< levels
; ++ii
) {
11528 uint32 level_size
= 0;
11529 if (!GLES2Util::ComputeImageDataSizes(
11530 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
11531 &estimated_size
, NULL
, NULL
) ||
11532 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
11533 LOCAL_SET_GL_ERROR(
11534 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
11537 level_width
= std::max(1, level_width
>> 1);
11538 level_height
= std::max(1, level_height
>> 1);
11540 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
11541 LOCAL_SET_GL_ERROR(
11542 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
11547 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
11548 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
11549 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
11550 if (error
== GL_NO_ERROR
) {
11551 GLsizei level_width
= width
;
11552 GLsizei level_height
= height
;
11553 for (int ii
= 0; ii
< levels
; ++ii
) {
11554 texture_manager()->SetLevelInfo(
11555 texture_ref
, target
, ii
, format
,
11556 level_width
, level_height
, 1, 0, format
, type
, false);
11557 level_width
= std::max(1, level_width
>> 1);
11558 level_height
= std::max(1, level_height
>> 1);
11560 texture
->SetImmutable(true);
11564 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
11565 uint32 immediate_data_size
,
11566 const void* cmd_data
) {
11567 return error::kUnknownCommand
;
11570 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
11571 const GLbyte
* data
) {
11572 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
11573 "context", logger_
.GetLogPrefix(),
11574 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11576 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11578 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
11581 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
11582 GLenum target
, const GLbyte
* data
) {
11583 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
11584 "context", logger_
.GetLogPrefix(),
11585 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11587 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
11591 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
11592 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
11593 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11594 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
11595 "mailbox that was not generated by "
11596 "GenMailboxCHROMIUM.";
11598 if (!texture_ref
) {
11599 LOCAL_SET_GL_ERROR(
11600 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
11604 Texture
* produced
= texture_manager()->Produce(texture_ref
);
11606 LOCAL_SET_GL_ERROR(
11607 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
11611 if (produced
->target() != target
) {
11612 LOCAL_SET_GL_ERROR(
11613 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
11617 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
11620 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
11621 const GLbyte
* data
) {
11622 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
11623 "context", logger_
.GetLogPrefix(),
11624 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11625 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11626 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
11627 "mailbox that was not generated by "
11628 "GenMailboxCHROMIUM.";
11630 scoped_refptr
<TextureRef
> texture_ref
=
11631 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11632 if (!texture_ref
.get()) {
11633 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11634 "glConsumeTextureCHROMIUM",
11635 "unknown texture for target");
11638 GLuint client_id
= texture_ref
->client_id();
11640 LOCAL_SET_GL_ERROR(
11641 GL_INVALID_OPERATION
,
11642 "glConsumeTextureCHROMIUM", "unknown texture for target");
11645 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
11647 LOCAL_SET_GL_ERROR(
11648 GL_INVALID_OPERATION
,
11649 "glConsumeTextureCHROMIUM", "invalid mailbox name");
11652 if (texture
->target() != target
) {
11653 LOCAL_SET_GL_ERROR(
11654 GL_INVALID_OPERATION
,
11655 "glConsumeTextureCHROMIUM", "invalid target");
11659 DeleteTexturesHelper(1, &client_id
);
11660 texture_ref
= texture_manager()->Consume(client_id
, texture
);
11661 glBindTexture(target
, texture_ref
->service_id());
11663 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
11664 unit
.bind_target
= target
;
11666 case GL_TEXTURE_2D
:
11667 unit
.bound_texture_2d
= texture_ref
;
11669 case GL_TEXTURE_CUBE_MAP
:
11670 unit
.bound_texture_cube_map
= texture_ref
;
11672 case GL_TEXTURE_EXTERNAL_OES
:
11673 unit
.bound_texture_external_oes
= texture_ref
;
11675 case GL_TEXTURE_RECTANGLE_ARB
:
11676 unit
.bound_texture_rectangle_arb
= texture_ref
;
11679 NOTREACHED(); // Validation should prevent us getting here.
11684 void GLES2DecoderImpl::EnsureTextureForClientId(
11686 GLuint client_id
) {
11687 TextureRef
* texture_ref
= GetTexture(client_id
);
11688 if (!texture_ref
) {
11690 glGenTextures(1, &service_id
);
11691 DCHECK_NE(0u, service_id
);
11692 texture_ref
= CreateTexture(client_id
, service_id
);
11693 texture_manager()->SetTarget(texture_ref
, target
);
11694 glBindTexture(target
, service_id
);
11695 RestoreCurrentTextureBindings(&state_
, target
);
11699 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
11700 // provided is associated with a service_id/TextureRef for consistency, even if
11701 // the resulting texture is incomplete.
11702 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
11703 uint32_t immediate_data_size
,
11704 const void* cmd_data
) {
11705 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
11707 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
11709 GLenum target
= static_cast<GLenum
>(c
.target
);
11710 uint32_t data_size
;
11711 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
11712 return error::kOutOfBounds
;
11714 if (data_size
> immediate_data_size
) {
11715 return error::kOutOfBounds
;
11717 const GLbyte
* mailbox
=
11718 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
11719 if (!validators_
->texture_bind_target
.IsValid(target
)) {
11720 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11721 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
11722 return error::kNoError
;
11724 if (mailbox
== NULL
) {
11725 return error::kOutOfBounds
;
11727 uint32_t client_id
= c
.client_id
;
11728 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
11729 return error::kNoError
;
11732 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
11733 const GLbyte
* data
, GLuint client_id
) {
11734 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11735 "context", logger_
.GetLogPrefix(),
11736 "mailbox[0]", static_cast<unsigned char>(data
[0]));
11737 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
11738 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11739 "passed a mailbox that was not "
11740 "generated by GenMailboxCHROMIUM.";
11742 TextureRef
* texture_ref
= GetTexture(client_id
);
11744 // No need to call EnsureTextureForClientId here, the client_id already has
11745 // an associated texture.
11746 LOCAL_SET_GL_ERROR(
11747 GL_INVALID_OPERATION
,
11748 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11751 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
11753 EnsureTextureForClientId(target
, client_id
);
11754 LOCAL_SET_GL_ERROR(
11755 GL_INVALID_OPERATION
,
11756 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11760 if (texture
->target() != target
) {
11761 EnsureTextureForClientId(target
, client_id
);
11762 LOCAL_SET_GL_ERROR(
11763 GL_INVALID_OPERATION
,
11764 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11768 texture_ref
= texture_manager()->Consume(client_id
, texture
);
11771 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
11772 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
11773 return valuebuffer
&& valuebuffer
->IsValid();
11776 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
11777 GLuint client_id
) {
11778 Valuebuffer
* valuebuffer
= NULL
;
11779 if (client_id
!= 0) {
11780 valuebuffer
= GetValuebuffer(client_id
);
11781 if (!valuebuffer
) {
11782 if (!group_
->bind_generates_resource()) {
11783 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
11784 "id not generated by glBindValuebufferCHROMIUM");
11788 // It's a new id so make a valuebuffer for it.
11789 CreateValuebuffer(client_id
);
11790 valuebuffer
= GetValuebuffer(client_id
);
11792 valuebuffer
->MarkAsValid();
11794 state_
.bound_valuebuffer
= valuebuffer
;
11797 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
11798 GLenum subscription
) {
11799 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11802 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
11805 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
11806 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11809 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
11812 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
11814 GLenum subscription
) {
11815 if (!CheckCurrentValuebufferForSubscription(
11816 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
11819 if (!CheckSubscriptionTarget(location
, subscription
,
11820 "glPopulateSubscribedValuesCHROMIUM")) {
11823 const ValueState
* state
=
11824 state_
.bound_valuebuffer
.get()->GetState(subscription
);
11826 switch (subscription
) {
11827 case GL_MOUSE_POSITION_CHROMIUM
:
11828 DoUniform2iv(location
, 1, state
->int_value
);
11831 NOTREACHED() << "Unhandled uniform subscription target "
11838 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11839 GLsizei length
, const GLchar
* marker
) {
11843 debug_marker_manager_
.SetMarker(
11844 length
? std::string(marker
, length
) : std::string(marker
));
11847 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11848 GLsizei length
, const GLchar
* marker
) {
11852 std::string name
= length
? std::string(marker
, length
) : std::string(marker
);
11853 debug_marker_manager_
.PushGroup(name
);
11854 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name
,
11855 kTraceGroupMarker
);
11858 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11859 debug_marker_manager_
.PopGroup();
11860 gpu_tracer_
->End(kTraceGroupMarker
);
11863 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11864 GLenum target
, GLint image_id
) {
11865 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11867 if (target
== GL_TEXTURE_CUBE_MAP
) {
11868 LOCAL_SET_GL_ERROR(
11870 "glBindTexImage2DCHROMIUM", "invalid target");
11874 // Default target might be conceptually valid, but disallow it to avoid
11876 TextureRef
* texture_ref
=
11877 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11878 if (!texture_ref
) {
11879 LOCAL_SET_GL_ERROR(
11880 GL_INVALID_OPERATION
,
11881 "glBindTexImage2DCHROMIUM", "no texture bound");
11885 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11887 LOCAL_SET_GL_ERROR(
11888 GL_INVALID_OPERATION
,
11889 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11894 ScopedGLErrorSuppressor
suppressor(
11895 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11896 if (!gl_image
->BindTexImage(target
)) {
11897 LOCAL_SET_GL_ERROR(
11898 GL_INVALID_OPERATION
,
11899 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11904 gfx::Size size
= gl_image
->GetSize();
11905 texture_manager()->SetLevelInfo(
11906 texture_ref
, target
, 0, GL_RGBA
, size
.width(), size
.height(), 1, 0,
11907 GL_RGBA
, GL_UNSIGNED_BYTE
, true);
11908 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
11911 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11912 GLenum target
, GLint image_id
) {
11913 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11915 // Default target might be conceptually valid, but disallow it to avoid
11917 TextureRef
* texture_ref
=
11918 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
11919 if (!texture_ref
) {
11920 LOCAL_SET_GL_ERROR(
11921 GL_INVALID_OPERATION
,
11922 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11926 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
11928 LOCAL_SET_GL_ERROR(
11929 GL_INVALID_OPERATION
,
11930 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11934 // Do nothing when image is not currently bound.
11935 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
11939 ScopedGLErrorSuppressor
suppressor(
11940 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11941 gl_image
->ReleaseTexImage(target
);
11944 texture_manager()->SetLevelInfo(
11945 texture_ref
, target
, 0, GL_RGBA
, 0, 0, 1, 0,
11946 GL_RGBA
, GL_UNSIGNED_BYTE
, false);
11949 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11950 uint32 immediate_data_size
,
11951 const void* cmd_data
) {
11952 const gles2::cmds::TraceBeginCHROMIUM
& c
=
11953 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
11954 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
11955 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
11956 if (!category_bucket
|| category_bucket
->size() == 0 ||
11957 !name_bucket
|| name_bucket
->size() == 0) {
11958 return error::kInvalidArguments
;
11961 std::string category_name
;
11962 std::string trace_name
;
11963 if (!category_bucket
->GetAsString(&category_name
) ||
11964 !name_bucket
->GetAsString(&trace_name
)) {
11965 return error::kInvalidArguments
;
11968 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
11969 LOCAL_SET_GL_ERROR(
11970 GL_INVALID_OPERATION
,
11971 "glTraceBeginCHROMIUM", "unable to create begin trace");
11972 return error::kNoError
;
11974 return error::kNoError
;
11977 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11978 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
11979 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11980 "glTraceEndCHROMIUM", "no trace begin found");
11985 void GLES2DecoderImpl::DoDrawBuffersEXT(
11986 GLsizei count
, const GLenum
* bufs
) {
11987 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
11988 LOCAL_SET_GL_ERROR(
11990 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11994 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
11996 for (GLsizei i
= 0; i
< count
; ++i
) {
11997 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
11998 bufs
[i
] != GL_NONE
) {
11999 LOCAL_SET_GL_ERROR(
12000 GL_INVALID_OPERATION
,
12001 "glDrawBuffersEXT",
12002 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
12006 glDrawBuffersARB(count
, bufs
);
12007 framebuffer
->SetDrawBuffers(count
, bufs
);
12008 } else { // backbuffer
12010 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
12011 LOCAL_SET_GL_ERROR(
12012 GL_INVALID_OPERATION
,
12013 "glDrawBuffersEXT",
12014 "more than one buffer or bufs not GL_NONE or GL_BACK");
12017 GLenum mapped_buf
= bufs
[0];
12018 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
12019 bufs
[0] == GL_BACK
) {
12020 mapped_buf
= GL_COLOR_ATTACHMENT0
;
12022 glDrawBuffersARB(count
, &mapped_buf
);
12023 group_
->set_draw_buffer(bufs
[0]);
12027 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
12028 group_
->LoseContexts(other
);
12029 reset_status_
= current
;
12030 current_decoder_error_
= error::kLostContext
;
12033 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
12034 const GLfloat
* matrix
) {
12035 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12036 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12037 if (!features().chromium_path_rendering
) {
12038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12039 "glMatrixLoadfCHROMIUM",
12040 "function not available");
12044 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12045 ? state_
.projection_matrix
12046 : state_
.modelview_matrix
;
12047 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
12048 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12049 // since the values of the _NV and _CHROMIUM tokens match.
12050 glMatrixLoadfEXT(matrix_mode
, matrix
);
12053 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
12054 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
12055 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
12057 if (!features().chromium_path_rendering
) {
12058 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12059 "glMatrixLoadIdentityCHROMIUM",
12060 "function not available");
12064 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
12065 ? state_
.projection_matrix
12066 : state_
.modelview_matrix
;
12067 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
12068 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
12069 // since the values of the _NV and _CHROMIUM tokens match.
12070 glMatrixLoadIdentityEXT(matrix_mode
);
12073 bool GLES2DecoderImpl::ValidateAsyncTransfer(
12074 const char* function_name
,
12075 TextureRef
* texture_ref
,
12078 const void * data
) {
12079 // We only support async uploads to 2D textures for now.
12080 if (GL_TEXTURE_2D
!= target
) {
12081 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
12084 // We only support uploads to level zero for now.
12086 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "level != 0");
12089 // A transfer buffer must be bound, even for asyncTexImage2D.
12090 if (data
== NULL
) {
12091 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "buffer == 0");
12094 // We only support one async transfer in progress.
12095 if (!texture_ref
||
12096 async_pixel_transfer_manager_
->AsyncTransferIsInProgress(texture_ref
)) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_INVALID_OPERATION
,
12099 function_name
, "transfer already in progress");
12105 base::Closure
GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
12106 uint32 async_upload_token
,
12107 uint32 sync_data_shm_id
,
12108 uint32 sync_data_shm_offset
) {
12109 scoped_refptr
<gpu::Buffer
> buffer
= GetSharedMemoryBuffer(sync_data_shm_id
);
12110 if (!buffer
.get() ||
12111 !buffer
->GetDataAddress(sync_data_shm_offset
, sizeof(AsyncUploadSync
)))
12112 return base::Closure();
12114 AsyncMemoryParams
mem_params(buffer
,
12115 sync_data_shm_offset
,
12116 sizeof(AsyncUploadSync
));
12118 scoped_refptr
<AsyncUploadTokenCompletionObserver
> observer(
12119 new AsyncUploadTokenCompletionObserver(async_upload_token
));
12122 &AsyncPixelTransferManager::AsyncNotifyCompletion
,
12123 base::Unretained(GetAsyncPixelTransferManager()),
12128 error::Error
GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
12129 uint32 immediate_data_size
,
12130 const void* cmd_data
) {
12131 const gles2::cmds::AsyncTexImage2DCHROMIUM
& c
=
12132 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM
*>(cmd_data
);
12133 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
12134 GLenum target
= static_cast<GLenum
>(c
.target
);
12135 GLint level
= static_cast<GLint
>(c
.level
);
12136 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
12137 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12138 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12139 GLint border
= static_cast<GLint
>(c
.border
);
12140 GLenum format
= static_cast<GLenum
>(c
.format
);
12141 GLenum type
= static_cast<GLenum
>(c
.type
);
12142 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
12143 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
12144 uint32 pixels_size
;
12145 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12146 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12147 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12149 base::ScopedClosureRunner scoped_completion_callback
;
12150 if (async_upload_token
) {
12151 base::Closure completion_closure
=
12152 AsyncUploadTokenCompletionClosure(async_upload_token
,
12154 sync_data_shm_offset
);
12155 if (completion_closure
.is_null())
12156 return error::kInvalidArguments
;
12158 scoped_completion_callback
.Reset(completion_closure
);
12161 // TODO(epenner): Move this and copies of this memory validation
12162 // into ValidateTexImage2D step.
12163 if (!GLES2Util::ComputeImageDataSizes(
12164 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
12166 return error::kOutOfBounds
;
12168 const void* pixels
= NULL
;
12169 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
12170 pixels
= GetSharedMemoryAs
<const void*>(
12171 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
12173 return error::kOutOfBounds
;
12177 TextureManager::DoTextImage2DArguments args
= {
12178 target
, level
, internal_format
, width
, height
, border
, format
, type
,
12179 pixels
, pixels_size
};
12180 TextureRef
* texture_ref
;
12181 // All the normal glTexSubImage2D validation.
12182 if (!texture_manager()->ValidateTexImage2D(
12183 &state_
, "glAsyncTexImage2DCHROMIUM", args
, &texture_ref
)) {
12184 return error::kNoError
;
12187 // Extra async validation.
12188 Texture
* texture
= texture_ref
->texture();
12189 if (!ValidateAsyncTransfer(
12190 "glAsyncTexImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12191 return error::kNoError
;
12193 // Don't allow async redefinition of a textures.
12194 if (texture
->IsDefined()) {
12195 LOCAL_SET_GL_ERROR(
12196 GL_INVALID_OPERATION
,
12197 "glAsyncTexImage2DCHROMIUM", "already defined");
12198 return error::kNoError
;
12201 if (!EnsureGPUMemoryAvailable(pixels_size
)) {
12202 LOCAL_SET_GL_ERROR(
12203 GL_OUT_OF_MEMORY
, "glAsyncTexImage2DCHROMIUM", "out of memory");
12204 return error::kNoError
;
12207 // Setup the parameters.
12208 AsyncTexImage2DParams tex_params
= {
12209 target
, level
, static_cast<GLenum
>(internal_format
),
12210 width
, height
, border
, format
, type
};
12211 AsyncMemoryParams
mem_params(
12212 GetSharedMemoryBuffer(c
.pixels_shm_id
), c
.pixels_shm_offset
, pixels_size
);
12214 // Set up the async state if needed, and make the texture
12215 // immutable so the async state stays valid. The level info
12216 // is set up lazily when the transfer completes.
12217 AsyncPixelTransferDelegate
* delegate
=
12218 async_pixel_transfer_manager_
->CreatePixelTransferDelegate(texture_ref
,
12220 texture
->SetImmutable(true);
12222 delegate
->AsyncTexImage2D(
12225 base::Bind(&TextureManager::SetLevelInfoFromParams
,
12226 // The callback is only invoked if the transfer delegate still
12227 // exists, which implies through manager->texture_ref->state
12228 // ownership that both of these pointers are valid.
12229 base::Unretained(texture_manager()),
12230 base::Unretained(texture_ref
),
12232 return error::kNoError
;
12235 error::Error
GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
12236 uint32 immediate_data_size
,
12237 const void* cmd_data
) {
12238 const gles2::cmds::AsyncTexSubImage2DCHROMIUM
& c
=
12239 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM
*>(cmd_data
);
12240 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
12241 GLenum target
= static_cast<GLenum
>(c
.target
);
12242 GLint level
= static_cast<GLint
>(c
.level
);
12243 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
12244 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
12245 GLsizei width
= static_cast<GLsizei
>(c
.width
);
12246 GLsizei height
= static_cast<GLsizei
>(c
.height
);
12247 GLenum format
= static_cast<GLenum
>(c
.format
);
12248 GLenum type
= static_cast<GLenum
>(c
.type
);
12249 uint32 async_upload_token
= static_cast<uint32
>(c
.async_upload_token
);
12250 uint32 sync_data_shm_id
= static_cast<uint32
>(c
.sync_data_shm_id
);
12251 uint32 sync_data_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12253 base::ScopedClosureRunner scoped_completion_callback
;
12254 if (async_upload_token
) {
12255 base::Closure completion_closure
=
12256 AsyncUploadTokenCompletionClosure(async_upload_token
,
12258 sync_data_shm_offset
);
12259 if (completion_closure
.is_null())
12260 return error::kInvalidArguments
;
12262 scoped_completion_callback
.Reset(completion_closure
);
12265 // TODO(epenner): Move this and copies of this memory validation
12266 // into ValidateTexSubImage2D step.
12268 if (!GLES2Util::ComputeImageDataSizes(
12269 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
12271 return error::kOutOfBounds
;
12273 const void* pixels
= GetSharedMemoryAs
<const void*>(
12274 c
.data_shm_id
, c
.data_shm_offset
, data_size
);
12276 // All the normal glTexSubImage2D validation.
12277 error::Error error
= error::kNoError
;
12278 if (!ValidateTexSubImage2D(&error
, "glAsyncTexSubImage2DCHROMIUM",
12279 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
)) {
12283 // Extra async validation.
12284 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12286 Texture
* texture
= texture_ref
->texture();
12287 if (!ValidateAsyncTransfer(
12288 "glAsyncTexSubImage2DCHROMIUM", texture_ref
, target
, level
, pixels
))
12289 return error::kNoError
;
12291 // Guarantee async textures are always 'cleared' as follows:
12292 // - AsyncTexImage2D can not redefine an existing texture
12293 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
12294 // - AsyncTexSubImage2D clears synchronously if not already cleared.
12295 // - Textures become immutable after an async call.
12296 // This way we know in all cases that an async texture is always clear.
12297 if (!texture
->SafeToRenderFrom()) {
12298 if (!texture_manager()->ClearTextureLevel(this, texture_ref
,
12300 LOCAL_SET_GL_ERROR(
12302 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
12303 return error::kNoError
;
12307 // Setup the parameters.
12308 AsyncTexSubImage2DParams tex_params
= {target
, level
, xoffset
, yoffset
,
12309 width
, height
, format
, type
};
12310 AsyncMemoryParams
mem_params(
12311 GetSharedMemoryBuffer(c
.data_shm_id
), c
.data_shm_offset
, data_size
);
12312 AsyncPixelTransferDelegate
* delegate
=
12313 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12315 // TODO(epenner): We may want to enforce exclusive use
12316 // of async APIs in which case this should become an error,
12317 // (the texture should have been async defined).
12318 AsyncTexImage2DParams define_params
= {target
, level
,
12320 texture
->GetLevelSize(target
, level
, &define_params
.width
,
12321 &define_params
.height
);
12322 texture
->GetLevelType(target
, level
, &define_params
.type
,
12323 &define_params
.internal_format
);
12324 // Set up the async state if needed, and make the texture
12325 // immutable so the async state stays valid.
12326 delegate
= async_pixel_transfer_manager_
->CreatePixelTransferDelegate(
12327 texture_ref
, define_params
);
12328 texture
->SetImmutable(true);
12331 delegate
->AsyncTexSubImage2D(tex_params
, mem_params
);
12332 return error::kNoError
;
12335 error::Error
GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
12336 uint32 immediate_data_size
,
12337 const void* cmd_data
) {
12338 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
& c
=
12339 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM
*>(cmd_data
);
12340 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12341 GLenum target
= static_cast<GLenum
>(c
.target
);
12343 if (GL_TEXTURE_2D
!= target
) {
12344 LOCAL_SET_GL_ERROR(
12345 GL_INVALID_ENUM
, "glWaitAsyncTexImage2DCHROMIUM", "target");
12346 return error::kNoError
;
12348 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
12350 if (!texture_ref
) {
12351 LOCAL_SET_GL_ERROR(
12352 GL_INVALID_OPERATION
,
12353 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
12354 return error::kNoError
;
12356 AsyncPixelTransferDelegate
* delegate
=
12357 async_pixel_transfer_manager_
->GetPixelTransferDelegate(texture_ref
);
12359 LOCAL_SET_GL_ERROR(
12360 GL_INVALID_OPERATION
,
12361 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
12362 return error::kNoError
;
12364 delegate
->WaitForTransferCompletion();
12365 ProcessFinishedAsyncTransfers();
12366 return error::kNoError
;
12369 error::Error
GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
12370 uint32 immediate_data_size
,
12371 const void* data
) {
12372 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
12374 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
12375 ProcessFinishedAsyncTransfers();
12376 return error::kNoError
;
12379 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
12380 uint32_t immediate_data_size
, const void* cmd_data
) {
12381 if (!unsafe_es3_apis_enabled())
12382 return error::kUnknownCommand
;
12383 const gles2::cmds::UniformBlockBinding
& c
=
12384 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
12385 GLuint client_id
= c
.program
;
12386 GLuint index
= static_cast<GLuint
>(c
.index
);
12387 GLuint binding
= static_cast<GLuint
>(c
.binding
);
12388 Program
* program
= GetProgramInfoNotShader(
12389 client_id
, "glUniformBlockBinding");
12391 return error::kNoError
;
12393 GLuint service_id
= program
->service_id();
12394 glUniformBlockBinding(service_id
, index
, binding
);
12395 return error::kNoError
;
12398 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
12399 uint32_t immediate_data_size
, const void* cmd_data
) {
12400 if (!unsafe_es3_apis_enabled())
12401 return error::kUnknownCommand
;
12402 const gles2::cmds::ClientWaitSync
& c
=
12403 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
12404 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12405 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12406 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12407 typedef cmds::ClientWaitSync::Result Result
;
12408 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
12409 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
12411 return error::kOutOfBounds
;
12413 if (*result_dst
!= GL_WAIT_FAILED
) {
12414 return error::kInvalidArguments
;
12416 GLsync service_sync
= 0;
12417 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
12419 return error::kNoError
;
12421 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
12422 return error::kNoError
;
12425 error::Error
GLES2DecoderImpl::HandleWaitSync(
12426 uint32_t immediate_data_size
, const void* cmd_data
) {
12427 if (!unsafe_es3_apis_enabled())
12428 return error::kUnknownCommand
;
12429 const gles2::cmds::WaitSync
& c
=
12430 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
12431 GLuint sync
= static_cast<GLuint
>(c
.sync
);
12432 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
12433 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
12434 GLsync service_sync
= 0;
12435 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
12436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
12437 return error::kNoError
;
12439 glWaitSync(service_sync
, flags
, timeout
);
12440 return error::kNoError
;
12443 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
12444 uint32_t immediate_data_size
, const void* cmd_data
) {
12445 if (!unsafe_es3_apis_enabled()) {
12446 return error::kUnknownCommand
;
12448 const gles2::cmds::MapBufferRange
& c
=
12449 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
12450 GLenum target
= static_cast<GLenum
>(c
.target
);
12451 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
12452 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
12453 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
12455 typedef cmds::MapBufferRange::Result Result
;
12456 Result
* result
= GetSharedMemoryAs
<Result
*>(
12457 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
12459 return error::kOutOfBounds
;
12461 if (*result
!= 0) {
12463 return error::kInvalidArguments
;
12466 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
12468 return error::kOutOfBounds
;
12471 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
12472 if ((access
& mask
) == mask
) {
12473 // TODO(zmo): To be on the safe side, always map
12474 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
12475 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
12476 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
12478 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
12479 // undefined behaviors.
12480 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
12481 if ((access
& mask
) == mask
) {
12482 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
12483 "incompatible access bits");
12484 return error::kNoError
;
12486 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
12487 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
12488 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
12489 access
= (access
| GL_MAP_READ_BIT
);
12491 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
12492 if (ptr
== nullptr) {
12493 return error::kNoError
;
12495 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
12497 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
12498 GetSharedMemoryBuffer(c
.data_shm_id
));
12499 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
12500 memcpy(mem
, ptr
, size
);
12503 return error::kNoError
;
12506 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
12507 uint32_t immediate_data_size
, const void* cmd_data
) {
12508 if (!unsafe_es3_apis_enabled()) {
12509 return error::kUnknownCommand
;
12511 const gles2::cmds::UnmapBuffer
& c
=
12512 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
12513 GLenum target
= static_cast<GLenum
>(c
.target
);
12515 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
12517 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
12518 return error::kNoError
;
12520 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
12521 if (!mapped_range
) {
12522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
12523 "buffer is unmapped");
12524 return error::kNoError
;
12526 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
12527 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
12528 GL_MAP_FLUSH_EXPLICIT_BIT
) {
12529 // If we don't need to write back, or explict flush is required, no copying
12532 void* mem
= mapped_range
->GetShmPointer();
12534 return error::kOutOfBounds
;
12536 DCHECK(mapped_range
->pointer
);
12537 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
12539 buffer
->RemoveMappedRange();
12540 GLboolean rt
= glUnmapBuffer(target
);
12541 if (rt
== GL_FALSE
) {
12542 // At this point, we have already done the necessary validation, so
12543 // GL_FALSE indicates data corruption.
12544 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
12545 // the second unmap could still return GL_FALSE. For now, we simply lose
12546 // the contexts in the share group.
12547 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
12548 group_
->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB
);
12549 reset_status_
= GL_GUILTY_CONTEXT_RESET_ARB
;
12550 return error::kLostContext
;
12552 return error::kNoError
;
12555 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
12556 TextureRef
* texture_ref
) {
12557 Texture
* texture
= texture_ref
->texture();
12558 DoDidUseTexImageIfNeeded(texture
, texture
->target());
12561 void GLES2DecoderImpl::OnContextLostError() {
12562 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
12565 void GLES2DecoderImpl::OnOutOfMemoryError() {
12566 if (lose_context_when_out_of_memory_
) {
12567 group_
->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB
);
12571 // Include the auto-generated part of this file. We split this because it means
12572 // we can easily edit the non-auto generated parts right here in this file
12573 // instead of having to edit some template or the code generator.
12574 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
12576 } // namespace gles2