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"
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/trace_event_synthetic_delay.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/mailbox.h"
32 #include "gpu/command_buffer/service/buffer_manager.h"
33 #include "gpu/command_buffer/service/context_group.h"
34 #include "gpu/command_buffer/service/context_state.h"
35 #include "gpu/command_buffer/service/error_state.h"
36 #include "gpu/command_buffer/service/feature_info.h"
37 #include "gpu/command_buffer/service/framebuffer_manager.h"
38 #include "gpu/command_buffer/service/gl_utils.h"
39 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
40 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
41 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
42 #include "gpu/command_buffer/service/gpu_state_tracer.h"
43 #include "gpu/command_buffer/service/gpu_switches.h"
44 #include "gpu/command_buffer/service/gpu_tracer.h"
45 #include "gpu/command_buffer/service/image_manager.h"
46 #include "gpu/command_buffer/service/logger.h"
47 #include "gpu/command_buffer/service/mailbox_manager.h"
48 #include "gpu/command_buffer/service/memory_tracking.h"
49 #include "gpu/command_buffer/service/path_manager.h"
50 #include "gpu/command_buffer/service/program_manager.h"
51 #include "gpu/command_buffer/service/query_manager.h"
52 #include "gpu/command_buffer/service/renderbuffer_manager.h"
53 #include "gpu/command_buffer/service/shader_manager.h"
54 #include "gpu/command_buffer/service/shader_translator.h"
55 #include "gpu/command_buffer/service/texture_manager.h"
56 #include "gpu/command_buffer/service/valuebuffer_manager.h"
57 #include "gpu/command_buffer/service/vertex_array_manager.h"
58 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
59 #include "third_party/smhasher/src/City.h"
60 #include "ui/gfx/geometry/point.h"
61 #include "ui/gfx/geometry/rect.h"
62 #include "ui/gfx/geometry/size.h"
63 #include "ui/gfx/overlay_transform.h"
64 #include "ui/gl/gl_bindings.h"
65 #include "ui/gl/gl_context.h"
66 #include "ui/gl/gl_fence.h"
67 #include "ui/gl/gl_image.h"
68 #include "ui/gl/gl_implementation.h"
69 #include "ui/gl/gl_surface.h"
70 #include "ui/gl/gl_version_info.h"
71 #include "ui/gl/gpu_timing.h"
73 #if defined(OS_MACOSX)
74 #include <IOSurface/IOSurface.h>
75 // Note that this must be included after gl_bindings.h to avoid conflicts.
76 #include <OpenGL/CGLIOSurface.h>
84 const char kOESDerivativeExtension
[] = "GL_OES_standard_derivatives";
85 const char kEXTFragDepthExtension
[] = "GL_EXT_frag_depth";
86 const char kEXTDrawBuffersExtension
[] = "GL_EXT_draw_buffers";
87 const char kEXTShaderTextureLodExtension
[] = "GL_EXT_shader_texture_lod";
89 const GLfloat kIdentityMatrix
[16] = {1.0f
, 0.0f
, 0.0f
, 0.0f
,
90 0.0f
, 1.0f
, 0.0f
, 0.0f
,
91 0.0f
, 0.0f
, 1.0f
, 0.0f
,
92 0.0f
, 0.0f
, 0.0f
, 1.0f
};
94 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin
,
97 return (rangeMin
>= 62) && (rangeMax
>= 62) && (precision
>= 16);
100 void GetShaderPrecisionFormatImpl(GLenum shader_type
,
101 GLenum precision_type
,
102 GLint
* range
, GLint
* precision
) {
103 switch (precision_type
) {
107 // These values are for a 32-bit twos-complement integer format.
113 case GL_MEDIUM_FLOAT
:
115 // These values are for an IEEE single-precision floating-point format.
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
&&
126 gfx::g_driver_gl
.fn
.glGetShaderPrecisionFormatFn
) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 glGetShaderPrecisionFormat(shader_type
, precision_type
,
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range
[0] = abs(range
[0]);
142 range
[1] = abs(range
[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
147 if (precision_type
== GL_HIGH_FLOAT
&&
148 !PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], *precision
)) {
156 gfx::OverlayTransform
GetGFXOverlayTransform(GLenum plane_transform
) {
157 switch (plane_transform
) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM
:
159 return gfx::OVERLAY_TRANSFORM_NONE
;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM
:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL
;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM
:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL
;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM
:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90
;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM
:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180
;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM
:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270
;
171 return gfx::OVERLAY_TRANSFORM_INVALID
;
175 template <typename MANAGER_TYPE
, typename OBJECT_TYPE
>
176 GLuint
GetClientId(const MANAGER_TYPE
* manager
, const OBJECT_TYPE
* object
) {
178 GLuint client_id
= 0;
180 manager
->GetClientId(object
->service_id(), &client_id
);
186 explicit Vec4f(const Vec4
& data
) {
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
194 // contains the other rectangle or shares an edge with the other rectangle.
195 bool CombineAdjacentRects(const gfx::Rect
& rect1
,
196 const gfx::Rect
& rect2
,
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
199 if (rect1
.IsEmpty() || rect2
.Contains(rect1
)) {
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
205 if (rect2
.IsEmpty() || rect1
.Contains(rect2
)) {
210 // Return the union of |rect1| and |rect2| if they share an edge.
211 if (rect1
.SharesEdgeWith(rect2
)) {
212 *result
= gfx::UnionRects(rect1
, rect2
);
216 // Return false if it's not possible to combine |rect1| and |rect2|.
222 class GLES2DecoderImpl
;
224 // Local versions of the SET_GL_ERROR macros
225 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
226 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
227 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
228 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
229 function_name, value, label)
230 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
231 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
232 function_name, pname)
233 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
234 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
236 #define LOCAL_PEEK_GL_ERROR(function_name) \
237 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
238 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
239 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
240 #define LOCAL_PERFORMANCE_WARNING(msg) \
241 PerformanceWarning(__FILE__, __LINE__, msg)
242 #define LOCAL_RENDER_WARNING(msg) \
243 RenderWarning(__FILE__, __LINE__, msg)
245 // Check that certain assumptions the code makes are true. There are places in
246 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
247 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
248 // a few others) are 32bits. If they are not 32bits the code will have to change
249 // to call those GL functions with service side memory and then copy the results
250 // to shared memory, converting the sizes.
251 static_assert(sizeof(GLint
) == sizeof(uint32
), // NOLINT
252 "GLint should be the same size as uint32");
253 static_assert(sizeof(GLsizei
) == sizeof(uint32
), // NOLINT
254 "GLsizei should be the same size as uint32");
255 static_assert(sizeof(GLfloat
) == sizeof(float), // NOLINT
256 "GLfloat should be the same size as float");
258 // TODO(kbr): the use of this anonymous namespace core dumps the
259 // linker on Mac OS X 10.6 when the symbol ordering file is used
262 // Returns the address of the first byte after a struct.
263 template <typename T
>
264 const void* AddressAfterStruct(const T
& pod
) {
265 return reinterpret_cast<const uint8
*>(&pod
) + sizeof(pod
);
268 // Returns the address of the frst byte after the struct or NULL if size >
269 // immediate_data_size.
270 template <typename RETURN_TYPE
, typename COMMAND_TYPE
>
271 RETURN_TYPE
GetImmediateDataAs(const COMMAND_TYPE
& pod
,
273 uint32 immediate_data_size
) {
274 return (size
<= immediate_data_size
) ?
275 static_cast<RETURN_TYPE
>(const_cast<void*>(AddressAfterStruct(pod
))) :
279 // Computes the data size for certain gl commands like glUniform.
280 bool ComputeDataSize(
283 unsigned int elements_per_unit
,
286 if (!SafeMultiplyUint32(count
, size
, &value
)) {
289 if (!SafeMultiplyUint32(value
, elements_per_unit
, &value
)) {
296 // Return true if a character belongs to the ASCII subset as defined in
297 // GLSL ES 1.0 spec section 3.1.
298 static bool CharacterIsValidForGLES(unsigned char c
) {
299 // Printing characters are valid except " $ ` @ \ ' DEL.
300 if (c
>= 32 && c
<= 126 &&
309 // Horizontal tab, line feed, vertical tab, form feed, carriage return
311 if (c
>= 9 && c
<= 13) {
318 static bool StringIsValidForGLES(const char* str
) {
319 for (; *str
; ++str
) {
320 if (!CharacterIsValidForGLES(*str
)) {
327 // This class prevents any GL errors that occur when it is in scope from
328 // being reported to the client.
329 class ScopedGLErrorSuppressor
{
331 explicit ScopedGLErrorSuppressor(
332 const char* function_name
, ErrorState
* error_state
);
333 ~ScopedGLErrorSuppressor();
335 const char* function_name_
;
336 ErrorState
* error_state_
;
337 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor
);
340 // Temporarily changes a decoder's bound texture and restore it when this
341 // object goes out of scope. Also temporarily switches to using active texture
342 // unit zero in case the client has changed that to something invalid.
343 class ScopedTextureBinder
{
345 explicit ScopedTextureBinder(ContextState
* state
, GLuint id
, GLenum target
);
346 ~ScopedTextureBinder();
349 ContextState
* state_
;
351 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder
);
354 // Temporarily changes a decoder's bound render buffer and restore it when this
355 // object goes out of scope.
356 class ScopedRenderBufferBinder
{
358 explicit ScopedRenderBufferBinder(ContextState
* state
, GLuint id
);
359 ~ScopedRenderBufferBinder();
362 ContextState
* state_
;
363 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder
);
366 // Temporarily changes a decoder's bound frame buffer and restore it when this
367 // object goes out of scope.
368 class ScopedFrameBufferBinder
{
370 explicit ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
, GLuint id
);
371 ~ScopedFrameBufferBinder();
374 GLES2DecoderImpl
* decoder_
;
375 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder
);
378 // Temporarily changes a decoder's bound frame buffer to a resolved version of
379 // the multisampled offscreen render buffer if that buffer is multisampled, and,
380 // if it is bound or enforce_internal_framebuffer is true. If internal is
381 // true, the resolved framebuffer is not visible to the parent.
382 class ScopedResolvedFrameBufferBinder
{
384 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
385 bool enforce_internal_framebuffer
,
387 ~ScopedResolvedFrameBufferBinder();
390 GLES2DecoderImpl
* decoder_
;
391 bool resolve_and_bind_
;
392 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder
);
395 class ScopedModifyPixels
{
397 explicit ScopedModifyPixels(TextureRef
* ref
);
398 ~ScopedModifyPixels();
404 ScopedModifyPixels::ScopedModifyPixels(TextureRef
* ref
) : ref_(ref
) {
406 ref_
->texture()->OnWillModifyPixels();
409 ScopedModifyPixels::~ScopedModifyPixels() {
411 ref_
->texture()->OnDidModifyPixels();
414 class ScopedRenderTo
{
416 explicit ScopedRenderTo(Framebuffer
* framebuffer
)
417 : ScopedRenderTo(framebuffer
, 0) {}
418 ScopedRenderTo(Framebuffer
* framebuffer
, GLenum attachment
);
422 const Framebuffer
* framebuffer_
;
426 ScopedRenderTo::ScopedRenderTo(Framebuffer
* framebuffer
, GLenum attachment
)
427 : framebuffer_(framebuffer
),
428 attachment_(attachment
) {
430 framebuffer_
->OnWillRenderTo(attachment_
);
433 ScopedRenderTo::~ScopedRenderTo() {
435 framebuffer_
->OnDidRenderTo(attachment_
);
438 // Encapsulates an OpenGL texture.
441 explicit BackTexture(MemoryTracker
* memory_tracker
, ContextState
* state
);
444 // Create a new render texture.
447 // Set the initial size and format of a render texture or resize it.
448 bool AllocateStorage(const gfx::Size
& size
, GLenum format
, bool zero
);
450 // Copy the contents of the currently bound frame buffer.
451 void Copy(const gfx::Size
& size
, GLenum format
);
453 // Destroy the render texture. This must be explicitly called before
454 // destroying this object.
457 // Invalidate the texture. This can be used when a context is lost and it is
458 // not possible to make it current in order to free the resource.
465 gfx::Size
size() const {
470 MemoryTypeTracker memory_tracker_
;
471 ContextState
* state_
;
472 size_t bytes_allocated_
;
475 DISALLOW_COPY_AND_ASSIGN(BackTexture
);
478 // Encapsulates an OpenGL render buffer of any format.
479 class BackRenderbuffer
{
481 explicit BackRenderbuffer(
482 RenderbufferManager
* renderbuffer_manager
,
483 MemoryTracker
* memory_tracker
,
484 ContextState
* state
);
487 // Create a new render buffer.
490 // Set the initial size and format of a render buffer or resize it.
491 bool AllocateStorage(const FeatureInfo
* feature_info
,
492 const gfx::Size
& size
,
496 // Destroy the render buffer. This must be explicitly called before destroying
500 // Invalidate the render buffer. This can be used when a context is lost and
501 // it is not possible to make it current in order to free the resource.
509 RenderbufferManager
* renderbuffer_manager_
;
510 MemoryTypeTracker memory_tracker_
;
511 ContextState
* state_
;
512 size_t bytes_allocated_
;
514 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer
);
517 // Encapsulates an OpenGL frame buffer.
518 class BackFramebuffer
{
520 explicit BackFramebuffer(GLES2DecoderImpl
* decoder
);
523 // Create a new frame buffer.
526 // Attach a color render buffer to a frame buffer.
527 void AttachRenderTexture(BackTexture
* texture
);
529 // Attach a render buffer to a frame buffer. Note that this unbinds any
530 // currently bound frame buffer.
531 void AttachRenderBuffer(GLenum target
, BackRenderbuffer
* render_buffer
);
533 // Destroy the frame buffer. This must be explicitly called before destroying
537 // Invalidate the frame buffer. This can be used when a context is lost and it
538 // is not possible to make it current in order to free the resource.
541 // See glCheckFramebufferStatusEXT.
542 GLenum
CheckStatus();
549 GLES2DecoderImpl
* decoder_
;
551 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer
);
554 struct FenceCallback
{
556 : fence(gfx::GLFence::Create()) {
559 std::vector
<base::Closure
> callbacks
;
560 scoped_ptr
<gfx::GLFence
> fence
;
563 // } // anonymous namespace.
566 const unsigned int GLES2Decoder::kDefaultStencilMask
=
567 static_cast<unsigned int>(-1);
569 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id
,
570 uint32
* service_texture_id
) {
574 GLES2Decoder::GLES2Decoder()
575 : initialized_(false),
577 log_commands_(false),
578 unsafe_es3_apis_enabled_(false) {
581 GLES2Decoder::~GLES2Decoder() {
584 void GLES2Decoder::BeginDecoding() {}
586 void GLES2Decoder::EndDecoding() {}
588 // This class implements GLES2Decoder so we don't have to expose all the GLES2
589 // cmd stuff to outside this class.
590 class GLES2DecoderImpl
: public GLES2Decoder
,
591 public FramebufferManager::TextureDetachObserver
,
592 public ErrorStateClient
{
594 explicit GLES2DecoderImpl(ContextGroup
* group
);
595 ~GLES2DecoderImpl() override
;
597 // Overridden from AsyncAPIInterface.
598 Error
DoCommand(unsigned int command
,
599 unsigned int arg_count
,
600 const void* args
) override
;
602 error::Error
DoCommands(unsigned int num_commands
,
605 int* entries_processed
) override
;
607 template <bool DebugImpl
>
608 error::Error
DoCommandsImpl(unsigned int num_commands
,
611 int* entries_processed
);
613 // Overridden from AsyncAPIInterface.
614 const char* GetCommandName(unsigned int command_id
) const override
;
616 // Overridden from GLES2Decoder.
617 bool Initialize(const scoped_refptr
<gfx::GLSurface
>& surface
,
618 const scoped_refptr
<gfx::GLContext
>& context
,
620 const gfx::Size
& offscreen_size
,
621 const DisallowedFeatures
& disallowed_features
,
622 const std::vector
<int32
>& attribs
) override
;
623 void Destroy(bool have_context
) override
;
624 void SetSurface(const scoped_refptr
<gfx::GLSurface
>& surface
) override
;
625 void ProduceFrontBuffer(const Mailbox
& mailbox
) override
;
626 bool ResizeOffscreenFrameBuffer(const gfx::Size
& size
) override
;
627 void UpdateParentTextureInfo();
628 bool MakeCurrent() override
;
629 GLES2Util
* GetGLES2Util() override
{ return &util_
; }
630 gfx::GLContext
* GetGLContext() override
{ return context_
.get(); }
631 ContextGroup
* GetContextGroup() override
{ return group_
.get(); }
632 Capabilities
GetCapabilities() override
;
633 void RestoreState(const ContextState
* prev_state
) override
;
635 void RestoreActiveTexture() const override
{ state_
.RestoreActiveTexture(); }
636 void RestoreAllTextureUnitBindings(
637 const ContextState
* prev_state
) const override
{
638 state_
.RestoreAllTextureUnitBindings(prev_state
);
640 void RestoreActiveTextureUnitBinding(unsigned int target
) const override
{
641 state_
.RestoreActiveTextureUnitBinding(target
);
643 void RestoreBufferBindings() const override
{
644 state_
.RestoreBufferBindings();
646 void RestoreGlobalState() const override
{ state_
.RestoreGlobalState(NULL
); }
647 void RestoreProgramBindings() const override
{
648 state_
.RestoreProgramBindings();
650 void RestoreTextureUnitBindings(unsigned unit
) const override
{
651 state_
.RestoreTextureUnitBindings(unit
, NULL
);
653 void RestoreFramebufferBindings() const override
;
654 void RestoreRenderbufferBindings() override
;
655 void RestoreTextureState(unsigned service_id
) const override
;
657 void ClearAllAttributes() const override
;
658 void RestoreAllAttributes() const override
;
660 QueryManager
* GetQueryManager() override
{ return query_manager_
.get(); }
661 VertexArrayManager
* GetVertexArrayManager() override
{
662 return vertex_array_manager_
.get();
664 ImageManager
* GetImageManager() override
{ return image_manager_
.get(); }
666 ValuebufferManager
* GetValuebufferManager() override
{
667 return valuebuffer_manager();
670 bool HasPendingQueries() const override
;
671 void ProcessPendingQueries(bool did_finish
) override
;
673 bool HasMoreIdleWork() const override
;
674 void PerformIdleWork() override
;
676 void WaitForReadPixels(base::Closure callback
) override
;
678 void SetResizeCallback(
679 const base::Callback
<void(gfx::Size
, float)>& callback
) override
;
681 Logger
* GetLogger() override
;
683 void BeginDecoding() override
;
684 void EndDecoding() override
;
686 ErrorState
* GetErrorState() override
;
687 const ContextState
* GetContextState() override
{ return &state_
; }
689 void SetShaderCacheCallback(const ShaderCacheCallback
& callback
) override
;
690 void SetWaitSyncPointCallback(const WaitSyncPointCallback
& callback
) override
;
692 void SetIgnoreCachedStateForTest(bool ignore
) override
;
693 void ProcessFinishedAsyncTransfers();
695 bool GetServiceTextureId(uint32 client_texture_id
,
696 uint32
* service_texture_id
) override
;
698 uint32
GetTextureUploadCount() override
;
699 base::TimeDelta
GetTotalTextureUploadTime() override
;
700 base::TimeDelta
GetTotalProcessingCommandsTime() override
;
701 void AddProcessingCommandsTime(base::TimeDelta
) override
;
703 // Restores the current state to the user's settings.
704 void RestoreCurrentFramebufferBindings();
706 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
707 void ApplyDirtyState();
709 // These check the state of the currently bound framebuffer or the
710 // backbuffer if no framebuffer is bound.
711 // Check with all attached and enabled color attachments.
712 bool BoundFramebufferHasColorAttachmentWithAlpha();
713 bool BoundFramebufferHasDepthAttachment();
714 bool BoundFramebufferHasStencilAttachment();
716 error::ContextLostReason
GetContextLostReason() override
;
718 // Overridden from FramebufferManager::TextureDetachObserver:
719 void OnTextureRefDetachedFromFramebuffer(TextureRef
* texture
) override
;
721 // Overriden from ErrorStateClient.
722 void OnContextLostError() override
;
723 void OnOutOfMemoryError() override
;
725 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
726 void EnsureRenderbufferBound();
728 // Helpers to facilitate calling into compatible extensions.
729 static void RenderbufferStorageMultisampleHelper(
730 const FeatureInfo
* feature_info
,
733 GLenum internal_format
,
737 void BlitFramebufferHelper(GLint srcX0
,
749 friend class ScopedFrameBufferBinder
;
750 friend class ScopedResolvedFrameBufferBinder
;
751 friend class BackFramebuffer
;
753 // Initialize or re-initialize the shader translator.
754 bool InitializeShaderTranslator();
756 void UpdateCapabilities();
758 // Helpers for the glGen and glDelete functions.
759 bool GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
760 void DeleteTexturesHelper(GLsizei n
, const GLuint
* client_ids
);
761 bool GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
762 void DeleteBuffersHelper(GLsizei n
, const GLuint
* client_ids
);
763 bool GenFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
764 void DeleteFramebuffersHelper(GLsizei n
, const GLuint
* client_ids
);
765 bool GenRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
766 void DeleteRenderbuffersHelper(GLsizei n
, const GLuint
* client_ids
);
767 bool GenValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
768 void DeleteValuebuffersCHROMIUMHelper(GLsizei n
, const GLuint
* client_ids
);
769 bool GenQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
770 void DeleteQueriesEXTHelper(GLsizei n
, const GLuint
* client_ids
);
771 bool GenVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
772 void DeleteVertexArraysOESHelper(GLsizei n
, const GLuint
* client_ids
);
773 bool GenPathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
774 bool DeletePathsCHROMIUMHelper(GLuint first_client_id
, GLsizei range
);
777 void OnFboChanged() const;
778 void OnUseFramebuffer() const;
780 error::ContextLostReason
GetContextLostReasonFromResetStatus(
781 GLenum reset_status
) const;
783 // TODO(gman): Cache these pointers?
784 BufferManager
* buffer_manager() {
785 return group_
->buffer_manager();
788 RenderbufferManager
* renderbuffer_manager() {
789 return group_
->renderbuffer_manager();
792 FramebufferManager
* framebuffer_manager() {
793 return group_
->framebuffer_manager();
796 ValuebufferManager
* valuebuffer_manager() {
797 return group_
->valuebuffer_manager();
800 PathManager
* path_manager() { return group_
->path_manager(); }
802 ProgramManager
* program_manager() {
803 return group_
->program_manager();
806 ShaderManager
* shader_manager() {
807 return group_
->shader_manager();
810 ShaderTranslatorCache
* shader_translator_cache() {
811 return group_
->shader_translator_cache();
814 const TextureManager
* texture_manager() const {
815 return group_
->texture_manager();
818 TextureManager
* texture_manager() {
819 return group_
->texture_manager();
822 MailboxManager
* mailbox_manager() {
823 return group_
->mailbox_manager();
826 ImageManager
* image_manager() { return image_manager_
.get(); }
828 VertexArrayManager
* vertex_array_manager() {
829 return vertex_array_manager_
.get();
832 MemoryTracker
* memory_tracker() {
833 return group_
->memory_tracker();
836 bool EnsureGPUMemoryAvailable(size_t estimated_size
) {
837 MemoryTracker
* tracker
= memory_tracker();
839 return tracker
->EnsureGPUMemoryAvailable(estimated_size
);
844 bool IsWebGLContext() const {
845 return webgl_version_
== 1 || webgl_version_
== 2;
848 bool IsOffscreenBufferMultisampled() const {
849 return offscreen_target_samples_
> 1;
852 // Creates a Texture for the given texture.
853 TextureRef
* CreateTexture(
854 GLuint client_id
, GLuint service_id
) {
855 return texture_manager()->CreateTexture(client_id
, service_id
);
858 // Gets the texture info for the given texture. Returns NULL if none exists.
859 TextureRef
* GetTexture(GLuint client_id
) const {
860 return texture_manager()->GetTexture(client_id
);
863 // Deletes the texture info for the given texture.
864 void RemoveTexture(GLuint client_id
) {
865 texture_manager()->RemoveTexture(client_id
);
868 // Get the size (in pixels) of the currently bound frame buffer (either FBO
869 // or regular back buffer).
870 gfx::Size
GetBoundReadFrameBufferSize();
872 // Get the format/type of the currently bound frame buffer (either FBO or
873 // regular back buffer).
874 // If the color image is a renderbuffer, returns 0 for type.
875 GLenum
GetBoundReadFrameBufferTextureType();
876 GLenum
GetBoundReadFrameBufferInternalFormat();
878 // Get the i-th draw buffer's internal format from the bound framebuffer.
879 // If no framebuffer is bound, or no image is attached, or the DrawBuffers
880 // setting for that image is GL_NONE, return 0.
881 GLenum
GetBoundColorDrawBufferInternalFormat(GLint drawbuffer_i
);
883 void MarkDrawBufferAsCleared(GLenum buffer
, GLint drawbuffer_i
);
885 // Wrapper for CompressedTexImage2D commands.
886 error::Error
DoCompressedTexImage2D(
889 GLenum internal_format
,
896 // Wrapper for CompressedTexImage3D commands.
897 error::Error
DoCompressedTexImage3D(
900 GLenum internal_format
,
908 // Wrapper for CompressedTexSubImage2D.
909 void DoCompressedTexSubImage2D(
920 // Wrapper for CompressedTexSubImage3D.
921 void DoCompressedTexSubImage3D(
934 // Wrapper for CopyTexImage2D.
935 void DoCopyTexImage2D(
938 GLenum internal_format
,
945 // Wrapper for SwapBuffers.
946 void DoSwapBuffers();
948 // Wrapper for SwapInterval.
949 void DoSwapInterval(int interval
);
951 // Wrapper for CopyTexSubImage2D.
952 void DoCopyTexSubImage2D(
962 // Validation for TexSubImage2D.
963 bool ValidateTexSubImage2D(
965 const char* function_name
,
976 // Wrapper for TexSubImage2D.
977 error::Error
DoTexSubImage2D(
988 // Wrapper for TexSubImage3D.
989 error::Error
DoTexSubImage3D(
1002 // Wrapper for TexImageIOSurface2DCHROMIUM.
1003 void DoTexImageIOSurface2DCHROMIUM(
1007 GLuint io_surface_id
,
1010 void DoCopyTextureCHROMIUM(GLenum target
,
1013 GLenum internal_format
,
1015 GLboolean unpack_flip_y
,
1016 GLboolean unpack_premultiply_alpha
,
1017 GLboolean unpack_unmultiply_alpha
);
1019 void DoCopySubTextureCHROMIUM(GLenum target
,
1028 GLboolean unpack_flip_y
,
1029 GLboolean unpack_premultiply_alpha
,
1030 GLboolean unpack_unmultiply_alpha
);
1032 void DoCompressedCopyTextureCHROMIUM(GLenum target
,
1036 void DoCompressedCopySubTextureCHROMIUM(GLenum target
,
1046 // Wrapper for TexStorage2DEXT.
1047 void DoTexStorage2DEXT(
1050 GLenum internal_format
,
1054 void DoProduceTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1055 void DoProduceTextureDirectCHROMIUM(GLuint texture
, GLenum target
,
1057 void ProduceTextureRef(std::string func_name
, TextureRef
* texture_ref
,
1058 GLenum target
, const GLbyte
* data
);
1060 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1061 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1062 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1064 void DoApplyScreenSpaceAntialiasingCHROMIUM();
1066 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1067 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1068 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1069 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1070 void DoUniformValueBufferCHROMIUM(GLint location
,
1072 GLenum subscription
);
1074 void DoBindTexImage2DCHROMIUM(
1077 void DoReleaseTexImage2DCHROMIUM(
1081 void DoTraceEndCHROMIUM(void);
1083 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1085 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1087 void DoFlushDriverCachesCHROMIUM(void);
1089 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1090 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1092 // Creates a Program for the given program.
1093 Program
* CreateProgram(
1094 GLuint client_id
, GLuint service_id
) {
1095 return program_manager()->CreateProgram(client_id
, service_id
);
1098 // Gets the program info for the given program. Returns NULL if none exists.
1099 Program
* GetProgram(GLuint client_id
) {
1100 return program_manager()->GetProgram(client_id
);
1104 void LogClientServiceMapping(
1105 const char* /* function_name */,
1106 GLuint
/* client_id */,
1107 GLuint
/* service_id */) {
1109 template<typename T
>
1110 void LogClientServiceForInfo(
1111 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1114 void LogClientServiceMapping(
1115 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1116 if (service_logging_
) {
1117 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1118 << ": client_id = " << client_id
1119 << ", service_id = " << service_id
;
1122 template<typename T
>
1123 void LogClientServiceForInfo(
1124 T
* info
, GLuint client_id
, const char* function_name
) {
1126 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1131 // Gets the program info for the given program. If it's not a program
1132 // generates a GL error. Returns NULL if not program.
1133 Program
* GetProgramInfoNotShader(
1134 GLuint client_id
, const char* function_name
) {
1135 Program
* program
= GetProgram(client_id
);
1137 if (GetShader(client_id
)) {
1139 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1141 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1144 LogClientServiceForInfo(program
, client_id
, function_name
);
1149 // Creates a Shader for the given shader.
1150 Shader
* CreateShader(
1153 GLenum shader_type
) {
1154 return shader_manager()->CreateShader(
1155 client_id
, service_id
, shader_type
);
1158 // Gets the shader info for the given shader. Returns NULL if none exists.
1159 Shader
* GetShader(GLuint client_id
) {
1160 return shader_manager()->GetShader(client_id
);
1163 // Gets the shader info for the given shader. If it's not a shader generates a
1164 // GL error. Returns NULL if not shader.
1165 Shader
* GetShaderInfoNotProgram(
1166 GLuint client_id
, const char* function_name
) {
1167 Shader
* shader
= GetShader(client_id
);
1169 if (GetProgram(client_id
)) {
1171 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1174 GL_INVALID_VALUE
, function_name
, "unknown shader");
1177 LogClientServiceForInfo(shader
, client_id
, function_name
);
1181 // Creates a buffer info for the given buffer.
1182 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1183 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1186 // Gets the buffer info for the given buffer.
1187 Buffer
* GetBuffer(GLuint client_id
) {
1188 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1192 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1193 // on glDeleteBuffers so we can make sure the user does not try to render
1194 // with deleted buffers.
1195 void RemoveBuffer(GLuint client_id
);
1197 // Creates a framebuffer info for the given framebuffer.
1198 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1199 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1202 // Gets the framebuffer info for the given framebuffer.
1203 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1204 return framebuffer_manager()->GetFramebuffer(client_id
);
1207 // Removes the framebuffer info for the given framebuffer.
1208 void RemoveFramebuffer(GLuint client_id
) {
1209 framebuffer_manager()->RemoveFramebuffer(client_id
);
1212 // Creates a renderbuffer info for the given renderbuffer.
1213 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1214 return renderbuffer_manager()->CreateRenderbuffer(
1215 client_id
, service_id
);
1218 // Gets the renderbuffer info for the given renderbuffer.
1219 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1220 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1223 // Removes the renderbuffer info for the given renderbuffer.
1224 void RemoveRenderbuffer(GLuint client_id
) {
1225 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1228 // Creates a valuebuffer info for the given valuebuffer.
1229 void CreateValuebuffer(GLuint client_id
) {
1230 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1233 // Gets the valuebuffer info for a given valuebuffer.
1234 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1235 return valuebuffer_manager()->GetValuebuffer(client_id
);
1238 // Removes the valuebuffer info for the given valuebuffer.
1239 void RemoveValuebuffer(GLuint client_id
) {
1240 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1243 // Gets the vertex attrib manager for the given vertex array.
1244 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1245 VertexAttribManager
* info
=
1246 vertex_array_manager()->GetVertexAttribManager(client_id
);
1250 // Removes the vertex attrib manager for the given vertex array.
1251 void RemoveVertexAttribManager(GLuint client_id
) {
1252 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1255 // Creates a vertex attrib manager for the given vertex array.
1256 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1259 bool client_visible
) {
1260 return vertex_array_manager()->CreateVertexAttribManager(
1261 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1264 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1265 void DoBindUniformLocationCHROMIUM(
1266 GLuint client_id
, GLint location
, const char* name
);
1268 error::Error
GetAttribLocationHelper(
1269 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1270 const std::string
& name_str
);
1272 error::Error
GetUniformLocationHelper(
1273 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1274 const std::string
& name_str
);
1276 error::Error
GetFragDataLocationHelper(
1277 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1278 const std::string
& name_str
);
1280 // Wrapper for glShaderSource.
1281 void DoShaderSource(
1282 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1284 // Wrapper for glTransformFeedbackVaryings.
1285 void DoTransformFeedbackVaryings(
1286 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1287 GLenum buffer_mode
);
1289 // Clear any textures used by the current program.
1290 bool ClearUnclearedTextures();
1292 // Clears any uncleared attachments attached to the given frame buffer.
1293 // Returns false if there was a generated GL error.
1294 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1296 // overridden from GLES2Decoder
1297 bool ClearLevel(Texture
* texture
,
1305 int height
) override
;
1307 // Restore all GL state that affects clearing.
1308 void RestoreClearState();
1310 // Remembers the state of some capabilities.
1311 // Returns: true if glEnable/glDisable should actually be called.
1312 bool SetCapabilityState(GLenum cap
, bool enabled
);
1314 // Check that the currently bound framebuffers are valid.
1315 // Generates GL error if not.
1316 bool CheckBoundFramebuffersValid(const char* func_name
);
1318 // Check that the currently bound read framebuffer has a color image
1319 // attached. Generates GL error if not.
1320 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1322 // Check that the currently bound read framebuffer's color image
1323 // isn't the target texture of the glCopyTex{Sub}Image2D.
1324 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1326 // Check if a framebuffer meets our requirements.
1327 bool CheckFramebufferValid(
1328 Framebuffer
* framebuffer
,
1330 const char* func_name
);
1332 bool CheckBoundDrawFramebufferValid(const char* func_name
);
1334 // Check if the current valuebuffer exists and is valid. If not generates
1335 // the appropriate GL error. Returns true if the current valuebuffer is in
1337 bool CheckCurrentValuebuffer(const char* function_name
);
1339 // Check if the current valuebuffer exists and is valiud and that the
1340 // value buffer is actually subscribed to the given subscription
1341 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1342 const char* function_name
);
1344 // Check if the location can be used for the given subscription target. If not
1345 // generates the appropriate GL error. Returns true if the location is usable
1346 bool CheckSubscriptionTarget(GLint location
,
1347 GLenum subscription
,
1348 const char* function_name
);
1350 // Checks if the current program exists and is valid. If not generates the
1351 // appropriate GL error. Returns true if the current program is in a usable
1353 bool CheckCurrentProgram(const char* function_name
);
1355 // Checks if the current program exists and is valid and that location is not
1356 // -1. If the current program is not valid generates the appropriate GL
1357 // error. Returns true if the current program is in a usable state and
1358 // location is not -1.
1359 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1361 // Checks if the current program samples a texture that is also the color
1362 // image of the current bound framebuffer, i.e., the source and destination
1363 // of the draw operation are the same.
1364 bool CheckDrawingFeedbackLoops();
1366 // Checks if |api_type| is valid for the given uniform
1367 // If the api type is not valid generates the appropriate GL
1368 // error. Returns true if |api_type| is valid for the uniform
1369 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1370 const char* function_name
,
1371 Program::UniformApiType api_type
);
1373 // Gets the type of a uniform for a location in the current program. Sets GL
1374 // errors if the current program is not valid. Returns true if the current
1375 // program is valid and the location exists. Adjusts count so it
1376 // does not overflow the uniform.
1377 bool PrepForSetUniformByLocation(GLint fake_location
,
1378 const char* function_name
,
1379 Program::UniformApiType api_type
,
1380 GLint
* real_location
,
1384 // Gets the service id for any simulated backbuffer fbo.
1385 GLuint
GetBackbufferServiceId() const;
1387 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1388 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1390 // Helper for glGetVertexAttrib
1391 void GetVertexAttribHelper(
1392 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1394 // Wrapper for glActiveTexture
1395 void DoActiveTexture(GLenum texture_unit
);
1397 // Wrapper for glAttachShader
1398 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1400 // Wrapper for glBindBuffer since we need to track the current targets.
1401 void DoBindBuffer(GLenum target
, GLuint buffer
);
1403 // Wrapper for glBindBufferBase since we need to track the current targets.
1404 void DoBindBufferBase(GLenum target
, GLuint index
, GLuint buffer
);
1406 // Wrapper for glBindBufferRange since we need to track the current targets.
1407 void DoBindBufferRange(GLenum target
, GLuint index
, GLuint buffer
,
1408 GLintptr offset
, GLsizeiptr size
);
1410 // Wrapper for glBindFramebuffer since we need to track the current targets.
1411 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1413 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1414 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1416 // Wrapper for glBindTexture since we need to track the current targets.
1417 void DoBindTexture(GLenum target
, GLuint texture
);
1419 // Wrapper for glBindVertexArrayOES
1420 void DoBindVertexArrayOES(GLuint array
);
1421 void EmulateVertexArrayState();
1423 // Wrapper for glBlitFramebufferCHROMIUM.
1424 void DoBlitFramebufferCHROMIUM(
1425 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1426 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1427 GLbitfield mask
, GLenum filter
);
1429 // Wrapper for glBufferSubData.
1430 void DoBufferSubData(
1431 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1433 // Wrapper for glCheckFramebufferStatus
1434 GLenum
DoCheckFramebufferStatus(GLenum target
);
1436 // Wrapper for glClear*()
1437 error::Error
DoClear(GLbitfield mask
);
1438 void DoClearBufferiv(
1439 GLenum buffer
, GLint drawbuffer
, const GLint
* value
);
1440 void DoClearBufferuiv(
1441 GLenum buffer
, GLint drawbuffer
, const GLuint
* value
);
1442 void DoClearBufferfv(
1443 GLenum buffer
, GLint drawbuffer
, const GLfloat
* value
);
1444 void DoClearBufferfi(
1445 GLenum buffer
, GLint drawbuffer
, GLfloat depth
, GLint stencil
);
1447 // Wrappers for various state.
1448 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1449 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1451 // Wrapper for glCompileShader.
1452 void DoCompileShader(GLuint shader
);
1454 // Wrapper for glDetachShader
1455 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1457 // Wrapper for glDisable
1458 void DoDisable(GLenum cap
);
1460 // Wrapper for glDisableVertexAttribArray.
1461 void DoDisableVertexAttribArray(GLuint index
);
1463 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1465 void DoDiscardFramebufferEXT(GLenum target
,
1466 GLsizei numAttachments
,
1467 const GLenum
* attachments
);
1469 // Wrapper for glEnable
1470 void DoEnable(GLenum cap
);
1472 // Wrapper for glEnableVertexAttribArray.
1473 void DoEnableVertexAttribArray(GLuint index
);
1475 // Wrapper for glFinish.
1478 // Wrapper for glFlush.
1481 // Wrapper for glFramebufferRenderbufffer.
1482 void DoFramebufferRenderbuffer(
1483 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1484 GLuint renderbuffer
);
1486 // Wrapper for glFramebufferTexture2D.
1487 void DoFramebufferTexture2D(
1488 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1491 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1492 void DoFramebufferTexture2DMultisample(
1493 GLenum target
, GLenum attachment
, GLenum textarget
,
1494 GLuint texture
, GLint level
, GLsizei samples
);
1496 // Common implementation for both DoFramebufferTexture2D wrappers.
1497 void DoFramebufferTexture2DCommon(const char* name
,
1498 GLenum target
, GLenum attachment
, GLenum textarget
,
1499 GLuint texture
, GLint level
, GLsizei samples
);
1501 // Wrapper for glFramebufferTextureLayer.
1502 void DoFramebufferTextureLayer(
1503 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1506 // Wrapper for glGenerateMipmap
1507 void DoGenerateMipmap(GLenum target
);
1509 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1510 // to account for different pname values defined in different extension
1512 GLenum
AdjustGetPname(GLenum pname
);
1514 // Wrapper for DoGetBooleanv.
1515 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1517 // Wrapper for DoGetFloatv.
1518 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1520 // Wrapper for glGetFramebufferAttachmentParameteriv.
1521 void DoGetFramebufferAttachmentParameteriv(
1522 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1524 // Wrapper for glGetInteger64v.
1525 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1527 // Wrapper for glGetIntegerv.
1528 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1530 // Gets the max value in a range in a buffer.
1531 GLuint
DoGetMaxValueInBufferCHROMIUM(
1532 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1534 // Wrapper for glGetBufferParameteri64v.
1535 void DoGetBufferParameteri64v(
1536 GLenum target
, GLenum pname
, GLint64
* params
);
1538 // Wrapper for glGetBufferParameteriv.
1539 void DoGetBufferParameteriv(
1540 GLenum target
, GLenum pname
, GLint
* params
);
1542 // Wrapper for glGetProgramiv.
1543 void DoGetProgramiv(
1544 GLuint program_id
, GLenum pname
, GLint
* params
);
1546 // Wrapper for glRenderbufferParameteriv.
1547 void DoGetRenderbufferParameteriv(
1548 GLenum target
, GLenum pname
, GLint
* params
);
1550 // Wrapper for glGetShaderiv
1551 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1553 // Wrappers for glGetTexParameter.
1554 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1555 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1556 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1558 // Wrappers for glGetVertexAttrib.
1559 template <typename T
>
1560 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1561 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1562 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1563 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1564 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1566 // Wrappers for glIsXXX functions.
1567 bool DoIsEnabled(GLenum cap
);
1568 bool DoIsBuffer(GLuint client_id
);
1569 bool DoIsFramebuffer(GLuint client_id
);
1570 bool DoIsProgram(GLuint client_id
);
1571 bool DoIsRenderbuffer(GLuint client_id
);
1572 bool DoIsShader(GLuint client_id
);
1573 bool DoIsTexture(GLuint client_id
);
1574 bool DoIsVertexArrayOES(GLuint client_id
);
1575 bool DoIsPathCHROMIUM(GLuint client_id
);
1577 // Wrapper for glLinkProgram
1578 void DoLinkProgram(GLuint program
);
1580 // Wrapper for glReadBuffer
1581 void DoReadBuffer(GLenum src
);
1583 // Wrapper for glRenderbufferStorage.
1584 void DoRenderbufferStorage(
1585 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1587 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1588 void DoRenderbufferStorageMultisampleCHROMIUM(
1589 GLenum target
, GLsizei samples
, GLenum internalformat
,
1590 GLsizei width
, GLsizei height
);
1592 // Handler for glRenderbufferStorageMultisampleEXT
1593 // (multisampled_render_to_texture).
1594 void DoRenderbufferStorageMultisampleEXT(
1595 GLenum target
, GLsizei samples
, GLenum internalformat
,
1596 GLsizei width
, GLsizei height
);
1598 // Common validation for multisample extensions.
1599 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1600 GLenum internalformat
,
1604 // Verifies that the currently bound multisample renderbuffer is valid
1605 // Very slow! Only done on platforms with driver bugs that return invalid
1606 // buffers under memory pressure
1607 bool VerifyMultisampleRenderbufferIntegrity(
1608 GLuint renderbuffer
, GLenum format
);
1610 // Wrapper for glReleaseShaderCompiler.
1611 void DoReleaseShaderCompiler() { }
1613 // Wrappers for glSamplerParameter*v functions.
1614 void DoSamplerParameterfv(
1615 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1616 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1618 // Wrappers for glTexParameter functions.
1619 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1620 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1621 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1622 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1624 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1625 // spec only these 2 functions can be used to set sampler uniforms.
1626 void DoUniform1i(GLint fake_location
, GLint v0
);
1627 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1628 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1629 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1630 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1632 void DoUniform1ui(GLint fake_location
, GLuint v0
);
1633 void DoUniform1uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1634 void DoUniform2uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1635 void DoUniform3uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1636 void DoUniform4uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1638 // Wrappers for glUniformfv because some drivers don't correctly accept
1640 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1641 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1642 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1643 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1645 void DoUniformMatrix2fv(
1646 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1647 const GLfloat
* value
);
1648 void DoUniformMatrix3fv(
1649 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1650 const GLfloat
* value
);
1651 void DoUniformMatrix4fv(
1652 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1653 const GLfloat
* value
);
1654 void DoUniformMatrix2x3fv(
1655 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1656 const GLfloat
* value
);
1657 void DoUniformMatrix2x4fv(
1658 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1659 const GLfloat
* value
);
1660 void DoUniformMatrix3x2fv(
1661 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1662 const GLfloat
* value
);
1663 void DoUniformMatrix3x4fv(
1664 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1665 const GLfloat
* value
);
1666 void DoUniformMatrix4x2fv(
1667 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1668 const GLfloat
* value
);
1669 void DoUniformMatrix4x3fv(
1670 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1671 const GLfloat
* value
);
1673 template <typename T
>
1674 bool SetVertexAttribValue(
1675 const char* function_name
, GLuint index
, const T
* value
);
1677 // Wrappers for glVertexAttrib??
1678 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1679 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1680 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1681 void DoVertexAttrib4f(
1682 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1683 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1684 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1685 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1686 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1687 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1688 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1689 void DoVertexAttribI4ui(
1690 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1691 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1693 // Wrapper for glViewport
1694 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1696 // Wrapper for glUseProgram
1697 void DoUseProgram(GLuint program
);
1699 // Wrapper for glValidateProgram.
1700 void DoValidateProgram(GLuint program_client_id
);
1702 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1703 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1704 void DoPopGroupMarkerEXT(void);
1706 // Gets the number of values that will be returned by glGetXXX. Returns
1707 // false if pname is unknown.
1708 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1710 // Checks if the current program and vertex attributes are valid for drawing.
1712 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1715 // Returns true if successful, simulated will be true if attrib0 was
1717 bool SimulateAttrib0(
1718 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1719 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1721 // If an image is bound to texture, this will call Will/DidUseTexImage
1723 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1724 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1726 // Returns false if textures were replaced.
1727 bool PrepareTexturesForRender();
1728 void RestoreStateForTextures();
1730 // Returns true if GL_FIXED attribs were simulated.
1731 bool SimulateFixedAttribs(
1732 const char* function_name
,
1733 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1734 void RestoreStateForSimulatedFixedAttribs();
1736 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1737 // cases (primcount is always 1 for non-instanced).
1738 error::Error
DoDrawArrays(
1739 const char* function_name
,
1740 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1742 error::Error
DoDrawElements(
1743 const char* function_name
,
1744 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1745 int32 offset
, GLsizei primcount
);
1747 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1748 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1749 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1752 return GL_TEXTURE_2D
;
1753 case GL_SAMPLER_CUBE
:
1754 return GL_TEXTURE_CUBE_MAP
;
1755 case GL_SAMPLER_EXTERNAL_OES
:
1756 return GL_TEXTURE_EXTERNAL_OES
;
1757 case GL_SAMPLER_2D_RECT_ARB
:
1758 return GL_TEXTURE_RECTANGLE_ARB
;
1765 // Gets the framebuffer info for a particular target.
1766 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1767 Framebuffer
* framebuffer
= NULL
;
1769 case GL_FRAMEBUFFER
:
1770 case GL_DRAW_FRAMEBUFFER_EXT
:
1771 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1773 case GL_READ_FRAMEBUFFER_EXT
:
1774 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1783 Renderbuffer
* GetRenderbufferInfoForTarget(
1785 Renderbuffer
* renderbuffer
= NULL
;
1787 case GL_RENDERBUFFER
:
1788 renderbuffer
= state_
.bound_renderbuffer
.get();
1794 return renderbuffer
;
1797 // Validates the program and location for a glGetUniform call and returns
1798 // a SizeResult setup to receive the result. Returns true if glGetUniform
1799 // should be called.
1801 bool GetUniformSetup(GLuint program
,
1802 GLint fake_location
,
1805 error::Error
* error
,
1806 GLint
* real_location
,
1808 SizedResult
<T
>** result
,
1809 GLenum
* result_type
,
1810 GLsizei
* result_size
);
1812 bool WasContextLost() const override
;
1813 bool WasContextLostByRobustnessExtension() const override
;
1814 void MarkContextLost(error::ContextLostReason reason
) override
;
1815 bool CheckResetStatus();
1817 #if defined(OS_MACOSX)
1818 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1821 bool GetCompressedTexSizeInBytes(
1822 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1823 GLenum format
, GLsizei
* size_in_bytes
);
1825 bool ValidateCompressedTexDimensions(
1826 const char* function_name
, GLenum target
, GLint level
,
1827 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1828 bool ValidateCompressedTexFuncData(
1829 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1830 GLenum format
, GLsizei size
);
1831 bool ValidateCompressedTexSubDimensions(
1832 const char* function_name
,
1833 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1834 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1836 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1838 TextureRef
* source_texture_ref
,
1839 TextureRef
* dest_texture_ref
,
1840 GLenum dest_internal_format
);
1841 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1843 TextureRef
* source_texture_ref
,
1844 TextureRef
* dest_texture_ref
);
1846 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1847 void PerformanceWarning(
1848 const char* filename
, int line
, const std::string
& msg
);
1850 const FeatureInfo::FeatureFlags
& features() const {
1851 return feature_info_
->feature_flags();
1854 const FeatureInfo::Workarounds
& workarounds() const {
1855 return feature_info_
->workarounds();
1858 bool ShouldDeferDraws() {
1859 return !offscreen_target_frame_buffer_
.get() &&
1860 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1861 surface_
->DeferDraws();
1864 bool ShouldDeferReads() {
1865 return !offscreen_target_frame_buffer_
.get() &&
1866 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1867 surface_
->DeferDraws();
1870 bool IsRobustnessSupported() {
1871 return has_robustness_extension_
&&
1872 context_
->WasAllocatedUsingRobustnessExtension();
1875 error::Error
WillAccessBoundFramebufferForDraw() {
1876 if (ShouldDeferDraws())
1877 return error::kDeferCommandUntilLater
;
1878 if (!offscreen_target_frame_buffer_
.get() &&
1879 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1880 !surface_
->SetBackbufferAllocation(true))
1881 return error::kLostContext
;
1882 return error::kNoError
;
1885 error::Error
WillAccessBoundFramebufferForRead() {
1886 if (ShouldDeferReads())
1887 return error::kDeferCommandUntilLater
;
1888 if (!offscreen_target_frame_buffer_
.get() &&
1889 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1890 !surface_
->SetBackbufferAllocation(true))
1891 return error::kLostContext
;
1892 return error::kNoError
;
1895 bool BackBufferHasAlpha() const {
1896 if (back_buffer_draw_buffer_
== GL_NONE
)
1898 if (offscreen_target_frame_buffer_
.get()) {
1899 return (offscreen_target_color_format_
== GL_RGBA
||
1900 offscreen_target_color_format_
== GL_RGBA8
);
1902 return (back_buffer_color_format_
== GL_RGBA
||
1903 back_buffer_color_format_
== GL_RGBA8
);
1906 // Set remaining commands to process to 0 to force DoCommands to return
1907 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1908 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1910 void ProcessPendingReadPixels(bool did_finish
);
1911 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1913 // Generate a member function prototype for each command in an automated and
1915 #define GLES2_CMD_OP(name) \
1916 Error Handle##name(uint32 immediate_data_size, const void* data);
1918 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1922 // The GL context this decoder renders to on behalf of the client.
1923 scoped_refptr
<gfx::GLSurface
> surface_
;
1924 scoped_refptr
<gfx::GLContext
> context_
;
1926 // The ContextGroup for this decoder uses to track resources.
1927 scoped_refptr
<ContextGroup
> group_
;
1929 DebugMarkerManager debug_marker_manager_
;
1932 // All the state for this context.
1933 ContextState state_
;
1935 // Current width and height of the offscreen frame buffer.
1936 gfx::Size offscreen_size_
;
1938 // Util to help with GL.
1941 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1942 GLuint attrib_0_buffer_id_
;
1944 // The value currently in attrib_0.
1945 Vec4 attrib_0_value_
;
1947 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1948 bool attrib_0_buffer_matches_value_
;
1950 // The size of attrib 0.
1951 GLsizei attrib_0_size_
;
1953 // The buffer used to simulate GL_FIXED attribs.
1954 GLuint fixed_attrib_buffer_id_
;
1956 // The size of fiixed attrib buffer.
1957 GLsizei fixed_attrib_buffer_size_
;
1959 // The offscreen frame buffer that the client renders to. With EGL, the
1960 // depth and stencil buffers are separate. With regular GL there is a single
1961 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1962 // offscreen_target_stencil_render_buffer_ is unused.
1963 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1964 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1965 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1966 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1967 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1968 GLenum offscreen_target_color_format_
;
1969 GLenum offscreen_target_depth_format_
;
1970 GLenum offscreen_target_stencil_format_
;
1971 GLsizei offscreen_target_samples_
;
1972 GLboolean offscreen_target_buffer_preserved_
;
1974 // The copy that is saved when SwapBuffers is called.
1975 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1976 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1977 scoped_refptr
<TextureRef
>
1978 offscreen_saved_color_texture_info_
;
1980 // The copy that is used as the destination for multi-sample resolves.
1981 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1982 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1983 GLenum offscreen_saved_color_format_
;
1985 scoped_ptr
<QueryManager
> query_manager_
;
1987 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1989 scoped_ptr
<ImageManager
> image_manager_
;
1991 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1993 WaitSyncPointCallback wait_sync_point_callback_
;
1995 ShaderCacheCallback shader_cache_callback_
;
1997 // The format of the back buffer_
1998 GLenum back_buffer_color_format_
;
1999 bool back_buffer_has_depth_
;
2000 bool back_buffer_has_stencil_
;
2002 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
2004 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
2005 // setting is set correctly when SwapBuffers().
2006 GLenum back_buffer_read_buffer_
;
2007 GLenum back_buffer_draw_buffer_
;
2011 // Backbuffer attachments that are currently undefined.
2012 uint32 backbuffer_needs_clear_bits_
;
2014 // The current decoder error communicates the decoder error through command
2015 // processing functions that do not return the error value. Should be set only
2016 // if not returning an error.
2017 error::Error current_decoder_error_
;
2019 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
2020 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
2022 DisallowedFeatures disallowed_features_
;
2024 // Cached from ContextGroup
2025 const Validators
* validators_
;
2026 scoped_refptr
<FeatureInfo
> feature_info_
;
2030 // Number of commands remaining to be processed in DoCommands().
2031 int commands_to_process_
;
2033 bool has_robustness_extension_
;
2034 error::ContextLostReason context_lost_reason_
;
2035 bool context_was_lost_
;
2036 bool reset_by_robustness_extension_
;
2037 bool supports_post_sub_buffer_
;
2039 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2043 unsigned webgl_version_
;
2045 // These flags are used to override the state of the shared feature_info_
2046 // member. Because the same FeatureInfo instance may be shared among many
2047 // contexts, the assumptions on the availablity of extensions in WebGL
2048 // contexts may be broken. These flags override the shared state to preserve
2050 bool derivatives_explicitly_enabled_
;
2051 bool frag_depth_explicitly_enabled_
;
2052 bool draw_buffers_explicitly_enabled_
;
2053 bool shader_texture_lod_explicitly_enabled_
;
2055 bool compile_shader_always_succeeds_
;
2057 // An optional behaviour to lose the context and group when OOM.
2058 bool lose_context_when_out_of_memory_
;
2061 bool service_logging_
;
2063 #if defined(OS_MACOSX)
2064 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2065 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2068 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2069 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2071 // Cached values of the currently assigned viewport dimensions.
2072 GLsizei viewport_max_width_
;
2073 GLsizei viewport_max_height_
;
2075 // Command buffer stats.
2076 base::TimeDelta total_processing_commands_time_
;
2078 // States related to each manager.
2079 DecoderTextureState texture_state_
;
2080 DecoderFramebufferState framebuffer_state_
;
2082 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2083 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2084 const unsigned char* gpu_decoder_category_
;
2085 int gpu_trace_level_
;
2086 bool gpu_trace_commands_
;
2087 bool gpu_debug_commands_
;
2089 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2091 // Used to validate multisample renderbuffers if needed
2092 GLuint validation_texture_
;
2093 GLuint validation_fbo_multisample_
;
2094 GLuint validation_fbo_
;
2096 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2097 uint32 immediate_data_size
,
2100 // A struct to hold info about each command.
2101 struct CommandInfo
{
2102 CmdHandler cmd_handler
;
2103 uint8 arg_flags
; // How to handle the arguments for this command
2104 uint8 cmd_flags
; // How to handle this command
2105 uint16 arg_count
; // How many arguments are expected for this command.
2108 // A table of CommandInfo for all the commands.
2109 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2111 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2114 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2115 #define GLES2_CMD_OP(name) \
2117 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2118 cmds::name::cmd_flags, \
2119 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2122 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2126 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2127 const char* function_name
, ErrorState
* error_state
)
2128 : function_name_(function_name
),
2129 error_state_(error_state
) {
2130 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2133 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2134 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2137 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2138 TextureUnit
& info
= state
->texture_units
[0];
2140 scoped_refptr
<TextureRef
> texture_ref
;
2143 texture_ref
= info
.bound_texture_2d
;
2145 case GL_TEXTURE_CUBE_MAP
:
2146 texture_ref
= info
.bound_texture_cube_map
;
2148 case GL_TEXTURE_EXTERNAL_OES
:
2149 texture_ref
= info
.bound_texture_external_oes
;
2151 case GL_TEXTURE_RECTANGLE_ARB
:
2152 texture_ref
= info
.bound_texture_rectangle_arb
;
2158 if (texture_ref
.get()) {
2159 last_id
= texture_ref
->service_id();
2164 glBindTexture(target
, last_id
);
2165 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2168 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2173 ScopedGLErrorSuppressor
suppressor(
2174 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2176 // TODO(apatrick): Check if there are any other states that need to be reset
2177 // before binding a new texture.
2178 glActiveTexture(GL_TEXTURE0
);
2179 glBindTexture(target
, id
);
2182 ScopedTextureBinder::~ScopedTextureBinder() {
2183 ScopedGLErrorSuppressor
suppressor(
2184 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2185 RestoreCurrentTextureBindings(state_
, target_
);
2188 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2191 ScopedGLErrorSuppressor
suppressor(
2192 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2193 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2196 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2197 ScopedGLErrorSuppressor
suppressor(
2198 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2199 state_
->RestoreRenderbufferBindings();
2202 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2204 : decoder_(decoder
) {
2205 ScopedGLErrorSuppressor
suppressor(
2206 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2207 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2208 decoder
->OnFboChanged();
2211 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2212 ScopedGLErrorSuppressor
suppressor(
2213 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2214 decoder_
->RestoreCurrentFramebufferBindings();
2217 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2218 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2219 : decoder_(decoder
) {
2220 resolve_and_bind_
= (
2221 decoder_
->offscreen_target_frame_buffer_
.get() &&
2222 decoder_
->IsOffscreenBufferMultisampled() &&
2223 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2224 enforce_internal_framebuffer
));
2225 if (!resolve_and_bind_
)
2228 ScopedGLErrorSuppressor
suppressor(
2229 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2230 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2231 decoder_
->offscreen_target_frame_buffer_
->id());
2234 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2235 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2236 new BackFramebuffer(decoder_
));
2237 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2238 decoder_
->offscreen_resolved_color_texture_
.reset(
2239 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2240 decoder_
->offscreen_resolved_color_texture_
->Create();
2242 DCHECK(decoder_
->offscreen_saved_color_format_
);
2243 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2244 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2246 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2247 decoder_
->offscreen_resolved_color_texture_
.get());
2248 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2249 GL_FRAMEBUFFER_COMPLETE
) {
2250 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2251 << "because offscreen resolved FBO was incomplete.";
2255 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2257 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2259 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2260 const int width
= decoder_
->offscreen_size_
.width();
2261 const int height
= decoder_
->offscreen_size_
.height();
2262 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2263 decoder
->BlitFramebufferHelper(0,
2271 GL_COLOR_BUFFER_BIT
,
2273 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2276 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2277 if (!resolve_and_bind_
)
2280 ScopedGLErrorSuppressor
suppressor(
2281 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2282 decoder_
->RestoreCurrentFramebufferBindings();
2283 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2284 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2288 BackTexture::BackTexture(
2289 MemoryTracker
* memory_tracker
,
2290 ContextState
* state
)
2291 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2293 bytes_allocated_(0),
2297 BackTexture::~BackTexture() {
2298 // This does not destroy the render texture because that would require that
2299 // the associated GL context was current. Just check that it was explicitly
2304 void BackTexture::Create() {
2305 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2306 state_
->GetErrorState());
2308 glGenTextures(1, &id_
);
2309 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2310 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2311 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2312 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2313 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2315 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2316 // never called on an offscreen context, no data will ever be uploaded to the
2317 // saved offscreen color texture (it is deferred until to when SwapBuffers
2318 // is called). My idea is that some nvidia drivers might have a bug where
2319 // deleting a texture that has never been populated might cause a
2322 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2324 bytes_allocated_
= 16u * 16u * 4u;
2325 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2328 bool BackTexture::AllocateStorage(
2329 const gfx::Size
& size
, GLenum format
, bool zero
) {
2331 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2332 state_
->GetErrorState());
2333 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2334 uint32 image_size
= 0;
2335 GLES2Util::ComputeImageDataSizes(
2336 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2339 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2343 scoped_ptr
<char[]> zero_data
;
2345 zero_data
.reset(new char[image_size
]);
2346 memset(zero_data
.get(), 0, image_size
);
2349 glTexImage2D(GL_TEXTURE_2D
,
2361 bool success
= glGetError() == GL_NO_ERROR
;
2363 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2364 bytes_allocated_
= image_size
;
2365 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2370 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2372 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2373 state_
->GetErrorState());
2374 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2375 glCopyTexImage2D(GL_TEXTURE_2D
,
2384 void BackTexture::Destroy() {
2386 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2387 state_
->GetErrorState());
2388 glDeleteTextures(1, &id_
);
2391 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2392 bytes_allocated_
= 0;
2395 void BackTexture::Invalidate() {
2399 BackRenderbuffer::BackRenderbuffer(
2400 RenderbufferManager
* renderbuffer_manager
,
2401 MemoryTracker
* memory_tracker
,
2402 ContextState
* state
)
2403 : renderbuffer_manager_(renderbuffer_manager
),
2404 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2406 bytes_allocated_(0),
2410 BackRenderbuffer::~BackRenderbuffer() {
2411 // This does not destroy the render buffer because that would require that
2412 // the associated GL context was current. Just check that it was explicitly
2417 void BackRenderbuffer::Create() {
2418 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2419 state_
->GetErrorState());
2421 glGenRenderbuffersEXT(1, &id_
);
2424 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2425 const gfx::Size
& size
,
2428 ScopedGLErrorSuppressor
suppressor(
2429 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2430 ScopedRenderBufferBinder
binder(state_
, id_
);
2432 uint32 estimated_size
= 0;
2433 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2434 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2438 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2443 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2448 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2455 bool success
= glGetError() == GL_NO_ERROR
;
2457 // Mark the previously allocated bytes as free.
2458 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2459 bytes_allocated_
= estimated_size
;
2460 // Track the newly allocated bytes.
2461 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2466 void BackRenderbuffer::Destroy() {
2468 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2469 state_
->GetErrorState());
2470 glDeleteRenderbuffersEXT(1, &id_
);
2473 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2474 bytes_allocated_
= 0;
2477 void BackRenderbuffer::Invalidate() {
2481 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2482 : decoder_(decoder
),
2486 BackFramebuffer::~BackFramebuffer() {
2487 // This does not destroy the frame buffer because that would require that
2488 // the associated GL context was current. Just check that it was explicitly
2493 void BackFramebuffer::Create() {
2494 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2495 decoder_
->GetErrorState());
2497 glGenFramebuffersEXT(1, &id_
);
2500 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2502 ScopedGLErrorSuppressor
suppressor(
2503 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2504 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2505 GLuint attach_id
= texture
? texture
->id() : 0;
2506 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2507 GL_COLOR_ATTACHMENT0
,
2513 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2514 BackRenderbuffer
* render_buffer
) {
2516 ScopedGLErrorSuppressor
suppressor(
2517 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2518 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2519 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2520 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2526 void BackFramebuffer::Destroy() {
2528 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2529 decoder_
->GetErrorState());
2530 glDeleteFramebuffersEXT(1, &id_
);
2535 void BackFramebuffer::Invalidate() {
2539 GLenum
BackFramebuffer::CheckStatus() {
2541 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2542 decoder_
->GetErrorState());
2543 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2544 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2547 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2548 return new GLES2DecoderImpl(group
);
2551 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2554 logger_(&debug_marker_manager_
),
2555 state_(group_
->feature_info(), this, &logger_
),
2556 attrib_0_buffer_id_(0),
2557 attrib_0_buffer_matches_value_(true),
2559 fixed_attrib_buffer_id_(0),
2560 fixed_attrib_buffer_size_(0),
2561 offscreen_target_color_format_(0),
2562 offscreen_target_depth_format_(0),
2563 offscreen_target_stencil_format_(0),
2564 offscreen_target_samples_(0),
2565 offscreen_target_buffer_preserved_(true),
2566 offscreen_saved_color_format_(0),
2567 back_buffer_color_format_(0),
2568 back_buffer_has_depth_(false),
2569 back_buffer_has_stencil_(false),
2570 back_buffer_read_buffer_(GL_BACK
),
2571 back_buffer_draw_buffer_(GL_BACK
),
2572 surfaceless_(false),
2573 backbuffer_needs_clear_bits_(0),
2574 current_decoder_error_(error::kNoError
),
2575 validators_(group_
->feature_info()->validators()),
2576 feature_info_(group_
->feature_info()),
2578 has_robustness_extension_(false),
2579 context_lost_reason_(error::kUnknown
),
2580 context_was_lost_(false),
2581 reset_by_robustness_extension_(false),
2582 supports_post_sub_buffer_(false),
2584 derivatives_explicitly_enabled_(false),
2585 frag_depth_explicitly_enabled_(false),
2586 draw_buffers_explicitly_enabled_(false),
2587 shader_texture_lod_explicitly_enabled_(false),
2588 compile_shader_always_succeeds_(false),
2589 lose_context_when_out_of_memory_(false),
2590 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2591 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2592 switches::kEnableGPUServiceLoggingGPU
)
2594 viewport_max_width_(0),
2595 viewport_max_height_(0),
2596 texture_state_(group_
->feature_info()->workarounds()),
2597 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2598 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2599 gpu_trace_level_(2),
2600 gpu_trace_commands_(false),
2601 gpu_debug_commands_(false),
2602 validation_texture_(0),
2603 validation_fbo_multisample_(0),
2604 validation_fbo_(0) {
2608 GLES2DecoderImpl::~GLES2DecoderImpl() {
2611 bool GLES2DecoderImpl::Initialize(
2612 const scoped_refptr
<gfx::GLSurface
>& surface
,
2613 const scoped_refptr
<gfx::GLContext
>& context
,
2615 const gfx::Size
& offscreen_size
,
2616 const DisallowedFeatures
& disallowed_features
,
2617 const std::vector
<int32
>& attribs
) {
2618 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2619 DCHECK(context
->IsCurrent(surface
.get()));
2620 DCHECK(!context_
.get());
2621 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2623 ContextCreationAttribHelper attrib_parser
;
2624 if (!attrib_parser
.Parse(attribs
))
2626 webgl_version_
= attrib_parser
.webgl_version
;
2628 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2631 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2633 if (base::CommandLine::InitializedForCurrentProcess()) {
2634 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2635 switches::kEnableGPUDebugging
)) {
2639 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2640 switches::kEnableGPUCommandLogging
)) {
2641 set_log_commands(true);
2644 compile_shader_always_succeeds_
=
2645 base::CommandLine::ForCurrentProcess()->HasSwitch(
2646 switches::kCompileShaderAlwaysSucceeds
);
2649 // Take ownership of the context and surface. The surface can be replaced with
2654 // Create GPU Tracer for timing values.
2655 gpu_tracer_
.reset(new GPUTracer(this));
2657 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2658 // Forcing time elapsed query for any GPU Timing Client forces it for all
2659 // clients in the context.
2660 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2663 // Save the loseContextWhenOutOfMemory context creation attribute.
2664 lose_context_when_out_of_memory_
=
2665 attrib_parser
.lose_context_when_out_of_memory
;
2667 // If the failIfMajorPerformanceCaveat context creation attribute was true
2668 // and we are using a software renderer, fail.
2669 if (attrib_parser
.fail_if_major_perf_caveat
&&
2670 feature_info_
->feature_flags().is_swiftshader
) {
2671 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2676 disallowed_features_
= disallowed_features
;
2677 if (webgl_version_
== 1) {
2678 disallowed_features_
.npot_support
= true;
2681 if (!group_
->Initialize(this,
2682 ContextGroup::GetContextType(webgl_version_
),
2683 disallowed_features_
)) {
2684 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2690 if (webgl_version_
== 2) {
2691 if (!feature_info_
->IsES3Capable()) {
2692 LOG(ERROR
) << "Underlying driver does not support ES3.";
2696 feature_info_
->EnableES3Validators();
2697 set_unsafe_es3_apis_enabled(true);
2699 frag_depth_explicitly_enabled_
= true;
2700 draw_buffers_explicitly_enabled_
= true;
2701 // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation.
2704 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2705 vertex_array_manager_
.reset(new VertexArrayManager());
2707 GLuint default_vertex_attrib_service_id
= 0;
2708 if (features().native_vertex_array_object
) {
2709 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2710 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2713 state_
.default_vertex_attrib_manager
=
2714 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2716 state_
.default_vertex_attrib_manager
->Initialize(
2717 group_
->max_vertex_attribs(),
2718 feature_info_
->workarounds().init_vertex_attributes
);
2720 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2721 DoBindVertexArrayOES(0);
2723 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2725 image_manager_
.reset(new ImageManager
);
2727 util_
.set_num_compressed_texture_formats(
2728 validators_
->compressed_texture_format
.GetValues().size());
2730 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2731 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2732 // OpenGL ES 2.0 does not have this issue.
2733 glEnableVertexAttribArray(0);
2735 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2736 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2737 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2738 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2739 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2741 state_
.texture_units
.resize(group_
->max_texture_units());
2742 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2743 glActiveTexture(GL_TEXTURE0
+ tt
);
2744 // We want the last bind to be 2D.
2746 if (features().oes_egl_image_external
) {
2747 ref
= texture_manager()->GetDefaultTextureInfo(
2748 GL_TEXTURE_EXTERNAL_OES
);
2749 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2750 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2752 if (features().arb_texture_rectangle
) {
2753 ref
= texture_manager()->GetDefaultTextureInfo(
2754 GL_TEXTURE_RECTANGLE_ARB
);
2755 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2756 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2758 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2759 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2760 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2761 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2762 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2763 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2765 glActiveTexture(GL_TEXTURE0
);
2768 // cache ALPHA_BITS result for re-use with clear behaviour
2769 GLint alpha_bits
= 0;
2772 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2773 features().chromium_framebuffer_multisample
) {
2774 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2775 // max_sample_count must be initialized to a sane value. If
2776 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2777 GLint max_sample_count
= 1;
2778 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2779 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2782 offscreen_target_samples_
= 1;
2784 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2786 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2787 const bool rgb8_supported
=
2788 context_
->HasExtension("GL_OES_rgb8_rgba8");
2789 // The only available default render buffer formats in GLES2 have very
2790 // little precision. Don't enable multisampling unless 8-bit render
2791 // buffer formats are available--instead fall back to 8-bit textures.
2792 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2793 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2796 offscreen_target_samples_
= 1;
2797 offscreen_target_color_format_
=
2798 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2803 // ANGLE only supports packed depth/stencil formats, so use it if it is
2805 const bool depth24_stencil8_supported
=
2806 feature_info_
->feature_flags().packed_depth24_stencil8
;
2807 VLOG(1) << "GL_OES_packed_depth_stencil "
2808 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2809 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2810 depth24_stencil8_supported
) {
2811 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2812 offscreen_target_stencil_format_
= 0;
2814 // It may be the case that this depth/stencil combination is not
2815 // supported, but this will be checked later by CheckFramebufferStatus.
2816 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2817 GL_DEPTH_COMPONENT16
: 0;
2818 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2819 GL_STENCIL_INDEX8
: 0;
2822 offscreen_target_color_format_
=
2823 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2827 // If depth is requested at all, use the packed depth stencil format if
2828 // it's available, as some desktop GL drivers don't support any non-packed
2829 // formats for depth attachments.
2830 const bool depth24_stencil8_supported
=
2831 feature_info_
->feature_flags().packed_depth24_stencil8
;
2832 VLOG(1) << "GL_EXT_packed_depth_stencil "
2833 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2835 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2836 depth24_stencil8_supported
) {
2837 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2838 offscreen_target_stencil_format_
= 0;
2840 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2841 GL_DEPTH_COMPONENT
: 0;
2842 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2843 GL_STENCIL_INDEX
: 0;
2847 offscreen_saved_color_format_
=
2848 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2852 // Create the target frame buffer. This is the one that the client renders
2854 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2855 offscreen_target_frame_buffer_
->Create();
2856 // Due to GLES2 format limitations, either the color texture (for
2857 // non-multisampling) or the color render buffer (for multisampling) will be
2858 // attached to the offscreen frame buffer. The render buffer has more
2859 // limited formats available to it, but the texture can't do multisampling.
2860 if (IsOffscreenBufferMultisampled()) {
2861 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2862 renderbuffer_manager(), memory_tracker(), &state_
));
2863 offscreen_target_color_render_buffer_
->Create();
2865 offscreen_target_color_texture_
.reset(new BackTexture(
2866 memory_tracker(), &state_
));
2867 offscreen_target_color_texture_
->Create();
2869 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2870 renderbuffer_manager(), memory_tracker(), &state_
));
2871 offscreen_target_depth_render_buffer_
->Create();
2872 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2873 renderbuffer_manager(), memory_tracker(), &state_
));
2874 offscreen_target_stencil_render_buffer_
->Create();
2876 // Create the saved offscreen texture. The target frame buffer is copied
2877 // here when SwapBuffers is called.
2878 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2879 offscreen_saved_frame_buffer_
->Create();
2881 offscreen_saved_color_texture_
.reset(new BackTexture(
2882 memory_tracker(), &state_
));
2883 offscreen_saved_color_texture_
->Create();
2885 // Allocate the render buffers at their initial size and check the status
2886 // of the frame buffers is okay.
2887 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2888 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2893 state_
.viewport_width
= offscreen_size
.width();
2894 state_
.viewport_height
= offscreen_size
.height();
2896 // Allocate the offscreen saved color texture.
2897 DCHECK(offscreen_saved_color_format_
);
2898 offscreen_saved_color_texture_
->AllocateStorage(
2899 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2901 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2902 offscreen_saved_color_texture_
.get());
2903 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2904 GL_FRAMEBUFFER_COMPLETE
) {
2905 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2910 // Bind to the new default frame buffer (the offscreen target frame buffer).
2911 // This should now be associated with ID zero.
2912 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2914 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2915 // These are NOT if the back buffer has these proprorties. They are
2916 // if we want the command buffer to enforce them regardless of what
2917 // the real backbuffer is assuming the real back buffer gives us more than
2918 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2919 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2920 // can't do anything about that.
2922 if (!surfaceless_
) {
2923 GLint depth_bits
= 0;
2924 GLint stencil_bits
= 0;
2926 bool default_fb
= (GetBackbufferServiceId() == 0);
2928 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2929 glGetFramebufferAttachmentParameterivEXT(
2931 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2932 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2933 glGetFramebufferAttachmentParameterivEXT(
2935 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2936 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2937 glGetFramebufferAttachmentParameterivEXT(
2939 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2940 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2942 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2943 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2944 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2947 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2948 // the user requested RGB then RGB. If the user did not specify a
2949 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2950 back_buffer_color_format_
=
2951 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2952 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2953 back_buffer_has_stencil_
=
2954 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2957 state_
.viewport_width
= surface
->GetSize().width();
2958 state_
.viewport_height
= surface
->GetSize().height();
2961 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2962 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2963 // isn't well documented; it was discovered in the Khronos OpenGL ES
2964 // mailing list archives. It also implicitly enables the desktop GL
2965 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2966 // variable in fragment shaders.
2967 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2968 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2969 glEnable(GL_POINT_SPRITE
);
2972 has_robustness_extension_
=
2973 context
->HasExtension("GL_ARB_robustness") ||
2974 context
->HasExtension("GL_KHR_robustness") ||
2975 context
->HasExtension("GL_EXT_robustness");
2977 if (!InitializeShaderTranslator()) {
2981 GLint viewport_params
[4] = { 0 };
2982 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2983 viewport_max_width_
= viewport_params
[0];
2984 viewport_max_height_
= viewport_params
[1];
2986 state_
.scissor_width
= state_
.viewport_width
;
2987 state_
.scissor_height
= state_
.viewport_height
;
2989 // Set all the default state because some GL drivers get it wrong.
2990 state_
.InitCapabilities(NULL
);
2991 state_
.InitState(NULL
);
2992 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2994 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2995 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2996 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2997 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
2998 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
3000 bool call_gl_clear
= !surfaceless_
;
3001 #if defined(OS_ANDROID)
3002 // Temporary workaround for Android WebView because this clear ignores the
3003 // clip and corrupts that external UI of the App. Not calling glClear is ok
3004 // because the system already clears the buffer before each draw. Proper
3005 // fix might be setting the scissor clip properly before initialize. See
3006 // crbug.com/259023 for details.
3007 call_gl_clear
= surface_
->GetHandle();
3009 if (call_gl_clear
) {
3010 // On configs where we report no alpha, if the underlying surface has
3011 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3012 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
3014 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
3017 // Clear the backbuffer.
3018 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3020 // Restore alpha clear value if we changed it.
3022 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
3026 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
3027 if (feature_info_
->workarounds()
3028 .disable_post_sub_buffers_for_onscreen_surfaces
&&
3029 !surface
->IsOffscreen())
3030 supports_post_sub_buffer_
= false;
3032 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
3033 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
3036 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3037 context_
->SetUnbindFboOnMakeCurrent();
3040 // Only compositor contexts are known to use only the subset of GL
3041 // that can be safely migrated between the iGPU and the dGPU. Mark
3042 // those contexts as safe to forcibly transition between the GPUs.
3043 // http://crbug.com/180876, http://crbug.com/227228
3045 context_
->SetSafeToForceGpuSwitch();
3047 if (workarounds().gl_clear_broken
) {
3048 DCHECK(!clear_framebuffer_blit_
.get());
3049 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3050 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3051 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3055 framebuffer_manager()->AddObserver(this);
3060 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3061 DCHECK(initialized());
3063 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3064 Capabilities::ShaderPrecision
* shader_precision
) {
3065 GLint range
[2] = {0, 0};
3066 GLint precision
= 0;
3067 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3068 shader_precision
->min_range
= range
[0];
3069 shader_precision
->max_range
= range
[1];
3070 shader_precision
->precision
= precision
;
3072 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3073 &caps
.max_combined_texture_image_units
);
3074 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3075 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3076 &caps
.max_fragment_uniform_vectors
);
3077 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3078 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3079 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3080 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3081 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3082 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3083 &caps
.max_vertex_texture_image_units
);
3084 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3085 &caps
.max_vertex_uniform_vectors
);
3086 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3087 &caps
.num_compressed_texture_formats
);
3088 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3089 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3090 &caps
.bind_generates_resource_chromium
);
3091 if (unsafe_es3_apis_enabled()) {
3092 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3093 // but for now we clamp them to 32-bit max.
3094 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3095 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3096 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3097 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3098 &caps
.max_combined_fragment_uniform_components
);
3099 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3100 &caps
.max_combined_uniform_blocks
);
3101 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3102 &caps
.max_combined_vertex_uniform_components
);
3103 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3104 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3105 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3106 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3107 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3108 &caps
.max_fragment_input_components
);
3109 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3110 &caps
.max_fragment_uniform_blocks
);
3111 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3112 &caps
.max_fragment_uniform_components
);
3113 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3114 &caps
.max_program_texel_offset
);
3115 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3116 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3118 if (caps
.max_server_wait_timeout
< 0)
3119 caps
.max_server_wait_timeout
= 0;
3120 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3121 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3122 &caps
.max_transform_feedback_interleaved_components
);
3123 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3124 &caps
.max_transform_feedback_separate_attribs
);
3125 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3126 &caps
.max_transform_feedback_separate_components
);
3127 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3128 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3129 &caps
.max_uniform_buffer_bindings
);
3130 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3131 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3132 &caps
.max_vertex_output_components
);
3133 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3134 &caps
.max_vertex_uniform_blocks
);
3135 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3136 &caps
.max_vertex_uniform_components
);
3137 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3138 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3139 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3140 &caps
.num_program_binary_formats
);
3141 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3142 &caps
.uniform_buffer_offset_alignment
);
3143 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3144 caps
.major_version
= 3;
3145 caps
.minor_version
= 0;
3147 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3148 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3149 unsafe_es3_apis_enabled()) {
3150 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3153 caps
.egl_image_external
=
3154 feature_info_
->feature_flags().oes_egl_image_external
;
3155 caps
.texture_format_astc
=
3156 feature_info_
->feature_flags().ext_texture_format_astc
;
3157 caps
.texture_format_atc
=
3158 feature_info_
->feature_flags().ext_texture_format_atc
;
3159 caps
.texture_format_bgra8888
=
3160 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3161 caps
.texture_format_dxt1
=
3162 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3163 caps
.texture_format_dxt5
=
3164 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3165 caps
.texture_format_etc1
=
3166 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3167 caps
.texture_format_etc1_npot
=
3168 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3169 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3170 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3171 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3172 caps
.discard_framebuffer
=
3173 feature_info_
->feature_flags().ext_discard_framebuffer
;
3174 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3176 #if defined(OS_MACOSX)
3177 // This is unconditionally true on mac, no need to test for it at runtime.
3178 caps
.iosurface
= true;
3181 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3183 caps
.surfaceless
= surfaceless_
;
3185 caps
.blend_equation_advanced
=
3186 feature_info_
->feature_flags().blend_equation_advanced
;
3187 caps
.blend_equation_advanced_coherent
=
3188 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3189 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3190 caps
.image_ycbcr_422
=
3191 feature_info_
->feature_flags().chromium_image_ycbcr_422
;
3192 caps
.max_copy_texture_chromium_size
=
3193 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3194 caps
.render_buffer_format_bgra8888
=
3195 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3196 caps
.occlusion_query_boolean
=
3197 feature_info_
->feature_flags().occlusion_query_boolean
;
3198 caps
.timer_queries
=
3199 query_manager_
->GPUTimingAvailable();
3203 void GLES2DecoderImpl::UpdateCapabilities() {
3204 util_
.set_num_compressed_texture_formats(
3205 validators_
->compressed_texture_format
.GetValues().size());
3206 util_
.set_num_shader_binary_formats(
3207 validators_
->shader_binary_format
.GetValues().size());
3210 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3211 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3212 if (feature_info_
->disable_shader_translator()) {
3215 ShBuiltInResources resources
;
3216 ShInitBuiltInResources(&resources
);
3217 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3218 resources
.MaxVertexUniformVectors
=
3219 group_
->max_vertex_uniform_vectors();
3220 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3221 resources
.MaxVertexTextureImageUnits
=
3222 group_
->max_vertex_texture_image_units();
3223 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3224 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3225 resources
.MaxFragmentUniformVectors
=
3226 group_
->max_fragment_uniform_vectors();
3227 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3228 resources
.MaxExpressionComplexity
= 256;
3229 resources
.MaxCallStackDepth
= 256;
3231 GLint range
[2] = { 0, 0 };
3232 GLint precision
= 0;
3233 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3235 resources
.FragmentPrecisionHigh
=
3236 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3238 if (IsWebGLContext()) {
3239 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3240 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3241 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3242 if (!draw_buffers_explicitly_enabled_
)
3243 resources
.MaxDrawBuffers
= 1;
3244 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3245 resources
.NV_draw_buffers
=
3246 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3248 resources
.OES_standard_derivatives
=
3249 features().oes_standard_derivatives
? 1 : 0;
3250 resources
.ARB_texture_rectangle
=
3251 features().arb_texture_rectangle
? 1 : 0;
3252 resources
.OES_EGL_image_external
=
3253 features().oes_egl_image_external
? 1 : 0;
3254 resources
.EXT_draw_buffers
=
3255 features().ext_draw_buffers
? 1 : 0;
3256 resources
.EXT_frag_depth
=
3257 features().ext_frag_depth
? 1 : 0;
3258 resources
.EXT_shader_texture_lod
=
3259 features().ext_shader_texture_lod
? 1 : 0;
3260 resources
.NV_draw_buffers
=
3261 features().nv_draw_buffers
? 1 : 0;
3264 ShShaderSpec shader_spec
;
3265 if (IsWebGLContext()) {
3266 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3268 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3271 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3272 features().enable_shader_name_hashing
)
3273 resources
.HashFunction
= &CityHash64
;
3275 resources
.HashFunction
= NULL
;
3277 int driver_bug_workarounds
= 0;
3278 if (workarounds().needs_glsl_built_in_function_emulation
)
3279 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3280 if (workarounds().init_gl_position_in_vertex_shader
)
3281 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3282 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3283 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3284 if (workarounds().init_varyings_without_static_use
)
3285 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3286 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3287 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3288 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3289 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3290 if (workarounds().regenerate_struct_names
)
3291 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3292 if (workarounds().remove_pow_with_constant_exponent
)
3293 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3295 if (base::CommandLine::InitializedForCurrentProcess() &&
3296 base::CommandLine::ForCurrentProcess()->HasSwitch(
3297 switches::kEmulateShaderPrecision
))
3298 resources
.WEBGL_debug_shader_precision
= true;
3300 ShShaderOutput shader_output_language
=
3301 ShaderTranslator::GetShaderOutputLanguageForContext(
3302 feature_info_
->gl_version_info());
3304 vertex_translator_
= shader_translator_cache()->GetTranslator(
3305 GL_VERTEX_SHADER
, shader_spec
, &resources
, shader_output_language
,
3306 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3307 if (!vertex_translator_
.get()) {
3308 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3313 fragment_translator_
= shader_translator_cache()->GetTranslator(
3314 GL_FRAGMENT_SHADER
, shader_spec
, &resources
, shader_output_language
,
3315 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3316 if (!fragment_translator_
.get()) {
3317 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3324 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3325 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3326 if (GetBuffer(client_ids
[ii
])) {
3330 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3331 glGenBuffersARB(n
, service_ids
.get());
3332 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3333 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3338 bool GLES2DecoderImpl::GenFramebuffersHelper(
3339 GLsizei n
, const GLuint
* client_ids
) {
3340 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3341 if (GetFramebuffer(client_ids
[ii
])) {
3345 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3346 glGenFramebuffersEXT(n
, service_ids
.get());
3347 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3348 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3353 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3354 GLsizei n
, const GLuint
* client_ids
) {
3355 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3356 if (GetRenderbuffer(client_ids
[ii
])) {
3360 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3361 glGenRenderbuffersEXT(n
, service_ids
.get());
3362 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3363 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3368 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3369 const GLuint
* client_ids
) {
3370 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3371 if (GetValuebuffer(client_ids
[ii
])) {
3375 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3376 CreateValuebuffer(client_ids
[ii
]);
3381 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3382 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3383 if (GetTexture(client_ids
[ii
])) {
3387 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3388 glGenTextures(n
, service_ids
.get());
3389 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3390 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3395 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3397 GLuint last_client_id
;
3398 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3401 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3404 GLuint first_service_id
= glGenPathsNV(range
);
3405 if (first_service_id
== 0) {
3406 // We have to fail the connection here, because client has already
3407 // succeeded in allocating the ids. This happens if we allocate
3408 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3412 // GenPathsNV does not wrap.
3413 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3415 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3421 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3423 GLuint last_client_id
;
3424 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3427 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3431 void GLES2DecoderImpl::DeleteBuffersHelper(
3432 GLsizei n
, const GLuint
* client_ids
) {
3433 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3434 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3435 if (buffer
&& !buffer
->IsDeleted()) {
3436 buffer
->RemoveMappedRange();
3437 state_
.RemoveBoundBuffer(buffer
);
3438 RemoveBuffer(client_ids
[ii
]);
3443 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3444 GLsizei n
, const GLuint
* client_ids
) {
3445 bool supports_separate_framebuffer_binds
=
3446 features().chromium_framebuffer_multisample
;
3448 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3449 Framebuffer
* framebuffer
=
3450 GetFramebuffer(client_ids
[ii
]);
3451 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3452 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3453 GLenum target
= supports_separate_framebuffer_binds
?
3454 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3456 // Unbind attachments on FBO before deletion.
3457 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3458 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3460 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3461 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3462 framebuffer_state_
.clear_state_dirty
= true;
3464 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3465 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3466 GLenum target
= supports_separate_framebuffer_binds
?
3467 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3468 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3471 RemoveFramebuffer(client_ids
[ii
]);
3476 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3477 GLsizei n
, const GLuint
* client_ids
) {
3478 bool supports_separate_framebuffer_binds
=
3479 features().chromium_framebuffer_multisample
;
3480 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3481 Renderbuffer
* renderbuffer
=
3482 GetRenderbuffer(client_ids
[ii
]);
3483 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3484 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3485 state_
.bound_renderbuffer
= NULL
;
3487 // Unbind from current framebuffers.
3488 if (supports_separate_framebuffer_binds
) {
3489 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3490 framebuffer_state_
.bound_read_framebuffer
3491 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3493 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3494 framebuffer_state_
.bound_draw_framebuffer
3495 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3498 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3499 framebuffer_state_
.bound_draw_framebuffer
3500 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3503 framebuffer_state_
.clear_state_dirty
= true;
3504 RemoveRenderbuffer(client_ids
[ii
]);
3509 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3511 const GLuint
* client_ids
) {
3512 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3513 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3515 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3516 state_
.bound_valuebuffer
= NULL
;
3518 RemoveValuebuffer(client_ids
[ii
]);
3523 void GLES2DecoderImpl::DeleteTexturesHelper(
3524 GLsizei n
, const GLuint
* client_ids
) {
3525 bool supports_separate_framebuffer_binds
=
3526 features().chromium_framebuffer_multisample
;
3527 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3528 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3530 Texture
* texture
= texture_ref
->texture();
3531 if (texture
->IsAttachedToFramebuffer()) {
3532 framebuffer_state_
.clear_state_dirty
= true;
3534 // Unbind texture_ref from texture_ref units.
3535 state_
.UnbindTexture(texture_ref
);
3537 // Unbind from current framebuffers.
3538 if (supports_separate_framebuffer_binds
) {
3539 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3540 framebuffer_state_
.bound_read_framebuffer
3541 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3543 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3544 framebuffer_state_
.bound_draw_framebuffer
3545 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3548 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3549 framebuffer_state_
.bound_draw_framebuffer
3550 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3553 #if defined(OS_MACOSX)
3554 GLuint service_id
= texture
->service_id();
3555 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3556 ReleaseIOSurfaceForTexture(service_id
);
3559 RemoveTexture(client_ids
[ii
]);
3564 // } // anonymous namespace
3566 bool GLES2DecoderImpl::MakeCurrent() {
3567 if (!context_
.get())
3570 if (WasContextLost()) {
3571 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3575 if (!context_
->MakeCurrent(surface_
.get())) {
3576 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3577 MarkContextLost(error::kMakeCurrentFailed
);
3578 group_
->LoseContexts(error::kUnknown
);
3582 if (CheckResetStatus()) {
3584 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3585 group_
->LoseContexts(error::kUnknown
);
3589 ProcessFinishedAsyncTransfers();
3591 // Rebind the FBO if it was unbound by the context.
3592 if (workarounds().unbind_fbo_on_context_switch
)
3593 RestoreFramebufferBindings();
3595 framebuffer_state_
.clear_state_dirty
= true;
3600 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3601 ProcessPendingReadPixels(false);
3602 if (engine() && query_manager_
.get())
3603 query_manager_
->ProcessPendingTransferQueries();
3606 static void RebindCurrentFramebuffer(
3608 Framebuffer
* framebuffer
,
3609 GLuint back_buffer_service_id
) {
3610 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3612 if (framebuffer_id
== 0) {
3613 framebuffer_id
= back_buffer_service_id
;
3616 glBindFramebufferEXT(target
, framebuffer_id
);
3619 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3620 framebuffer_state_
.clear_state_dirty
= true;
3622 if (!features().chromium_framebuffer_multisample
) {
3623 RebindCurrentFramebuffer(
3625 framebuffer_state_
.bound_draw_framebuffer
.get(),
3626 GetBackbufferServiceId());
3628 RebindCurrentFramebuffer(
3629 GL_READ_FRAMEBUFFER_EXT
,
3630 framebuffer_state_
.bound_read_framebuffer
.get(),
3631 GetBackbufferServiceId());
3632 RebindCurrentFramebuffer(
3633 GL_DRAW_FRAMEBUFFER_EXT
,
3634 framebuffer_state_
.bound_draw_framebuffer
.get(),
3635 GetBackbufferServiceId());
3640 bool GLES2DecoderImpl::CheckFramebufferValid(
3641 Framebuffer
* framebuffer
,
3642 GLenum target
, const char* func_name
) {
3646 if (backbuffer_needs_clear_bits_
) {
3647 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3648 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3649 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3651 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3652 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3654 state_
.SetDeviceDepthMask(GL_TRUE
);
3655 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3656 bool reset_draw_buffer
= false;
3657 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3658 back_buffer_draw_buffer_
== GL_NONE
) {
3659 reset_draw_buffer
= true;
3660 GLenum buf
= GL_BACK
;
3661 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3662 buf
= GL_COLOR_ATTACHMENT0
;
3663 glDrawBuffersARB(1, &buf
);
3665 glClear(backbuffer_needs_clear_bits_
);
3666 if (reset_draw_buffer
) {
3667 GLenum buf
= GL_NONE
;
3668 glDrawBuffersARB(1, &buf
);
3670 backbuffer_needs_clear_bits_
= 0;
3671 RestoreClearState();
3676 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3680 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3681 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3683 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3687 // Are all the attachments cleared?
3688 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3689 texture_manager()->HaveUnclearedMips()) {
3690 if (!framebuffer
->IsCleared()) {
3691 // Can we clear them?
3692 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3693 GL_FRAMEBUFFER_COMPLETE
) {
3695 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3696 "framebuffer incomplete (clear)");
3699 ClearUnclearedAttachments(target
, framebuffer
);
3703 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3704 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3705 GL_FRAMEBUFFER_COMPLETE
) {
3707 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3708 "framebuffer incomplete (check)");
3711 framebuffer_manager()->MarkAsComplete(framebuffer
);
3714 // NOTE: At this point we don't know if the framebuffer is complete but
3715 // we DO know that everything that needs to be cleared has been cleared.
3719 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3720 if (!features().chromium_framebuffer_multisample
) {
3721 bool valid
= CheckFramebufferValid(
3722 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3730 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3731 GL_DRAW_FRAMEBUFFER_EXT
,
3733 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3734 GL_READ_FRAMEBUFFER_EXT
,
3738 bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid(const char* func_name
) {
3739 Framebuffer
* framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
3741 // Assume the default back buffer is always complete.
3744 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3745 if (framebuffer
->GetStatus(texture_manager(), GL_DRAW_FRAMEBUFFER
) !=
3746 GL_FRAMEBUFFER_COMPLETE
) {
3748 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3749 "framebuffer incomplete (check)");
3752 framebuffer_manager()->MarkAsComplete(framebuffer
);
3757 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3758 const char* func_name
) {
3759 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3760 framebuffer_state_
.bound_read_framebuffer
.get() :
3761 framebuffer_state_
.bound_draw_framebuffer
.get();
3764 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3766 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3772 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3773 TextureRef
* texture
, GLint level
) {
3774 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3775 framebuffer_state_
.bound_read_framebuffer
.get() :
3776 framebuffer_state_
.bound_draw_framebuffer
.get();
3779 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3780 GL_COLOR_ATTACHMENT0
);
3783 return attachment
->FormsFeedbackLoop(texture
, level
);
3786 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3787 Framebuffer
* framebuffer
=
3788 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3789 if (framebuffer
!= NULL
) {
3790 const Framebuffer::Attachment
* attachment
=
3791 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3793 return gfx::Size(attachment
->width(), attachment
->height());
3795 return gfx::Size(0, 0);
3796 } else if (offscreen_target_frame_buffer_
.get()) {
3797 return offscreen_size_
;
3799 return surface_
->GetSize();
3803 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3804 Framebuffer
* framebuffer
=
3805 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3807 return framebuffer
->GetReadBufferTextureType();
3808 } else { // Back buffer.
3809 if (back_buffer_read_buffer_
== GL_NONE
)
3811 return GL_UNSIGNED_BYTE
;
3815 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3816 Framebuffer
* framebuffer
=
3817 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3819 return framebuffer
->GetReadBufferInternalFormat();
3820 } else { // Back buffer.
3821 if (back_buffer_read_buffer_
== GL_NONE
)
3823 if (offscreen_target_frame_buffer_
.get()) {
3824 return offscreen_target_color_format_
;
3826 return back_buffer_color_format_
;
3830 GLenum
GLES2DecoderImpl::GetBoundColorDrawBufferInternalFormat(
3831 GLint drawbuffer_i
) {
3832 DCHECK(drawbuffer_i
>= 0 &&
3833 drawbuffer_i
< static_cast<GLint
>(group_
->max_draw_buffers()));
3834 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER
);
3838 GLenum drawbuffer
= static_cast<GLenum
>(GL_DRAW_BUFFER0
+ drawbuffer_i
);
3839 if (framebuffer
->GetDrawBuffer(drawbuffer
) == GL_NONE
) {
3842 GLenum attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer_i
);
3843 const Framebuffer::Attachment
* buffer
=
3844 framebuffer
->GetAttachment(attachment
);
3848 return buffer
->internal_format();
3851 void GLES2DecoderImpl::MarkDrawBufferAsCleared(
3852 GLenum buffer
, GLint drawbuffer_i
) {
3853 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER
);
3856 GLenum attachment
= 0;
3859 DCHECK(drawbuffer_i
>= 0 &&
3860 drawbuffer_i
< static_cast<GLint
>(group_
->max_draw_buffers()));
3861 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer_i
);
3864 attachment
= GL_DEPTH
;
3867 attachment
= GL_STENCIL
;
3870 // Caller is responsible for breaking GL_DEPTH_STENCIL into GL_DEPTH and
3874 framebuffer
->MarkAttachmentAsCleared(
3875 renderbuffer_manager(), texture_manager(), attachment
, true);
3878 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3879 if (!offscreen_saved_color_texture_info_
.get())
3881 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3882 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3883 texture_manager()->SetLevelInfo(
3884 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3886 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3889 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3890 texture_manager()->SetParameteri(
3891 "UpdateParentTextureInfo",
3893 offscreen_saved_color_texture_info_
.get(),
3894 GL_TEXTURE_MAG_FILTER
,
3896 texture_manager()->SetParameteri(
3897 "UpdateParentTextureInfo",
3899 offscreen_saved_color_texture_info_
.get(),
3900 GL_TEXTURE_MIN_FILTER
,
3902 texture_manager()->SetParameteri(
3903 "UpdateParentTextureInfo",
3905 offscreen_saved_color_texture_info_
.get(),
3908 texture_manager()->SetParameteri(
3909 "UpdateParentTextureInfo",
3911 offscreen_saved_color_texture_info_
.get(),
3914 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3916 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3919 void GLES2DecoderImpl::SetResizeCallback(
3920 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3921 resize_callback_
= callback
;
3924 Logger
* GLES2DecoderImpl::GetLogger() {
3928 void GLES2DecoderImpl::BeginDecoding() {
3929 gpu_tracer_
->BeginDecoding();
3930 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3931 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
;
3932 query_manager_
->ProcessFrameBeginUpdates();
3935 void GLES2DecoderImpl::EndDecoding() {
3936 gpu_tracer_
->EndDecoding();
3939 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3940 return state_
.GetErrorState();
3943 void GLES2DecoderImpl::SetShaderCacheCallback(
3944 const ShaderCacheCallback
& callback
) {
3945 shader_cache_callback_
= callback
;
3948 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3949 const WaitSyncPointCallback
& callback
) {
3950 wait_sync_point_callback_
= callback
;
3953 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3954 uint32
* service_texture_id
) {
3955 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3957 *service_texture_id
= texture_ref
->service_id();
3963 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3964 return texture_state_
.texture_upload_count
;
3967 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3968 return texture_state_
.total_texture_upload_time
;
3971 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3972 return total_processing_commands_time_
;
3975 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3976 total_processing_commands_time_
+= time
;
3979 void GLES2DecoderImpl::Destroy(bool have_context
) {
3983 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3985 // Unbind everything.
3986 state_
.vertex_attrib_manager
= NULL
;
3987 state_
.default_vertex_attrib_manager
= NULL
;
3988 state_
.texture_units
.clear();
3989 state_
.bound_array_buffer
= NULL
;
3990 state_
.bound_copy_read_buffer
= NULL
;
3991 state_
.bound_copy_write_buffer
= NULL
;
3992 state_
.bound_pixel_pack_buffer
= NULL
;
3993 state_
.bound_pixel_unpack_buffer
= NULL
;
3994 state_
.bound_transform_feedback_buffer
= NULL
;
3995 state_
.bound_uniform_buffer
= NULL
;
3996 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3997 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3998 state_
.bound_renderbuffer
= NULL
;
3999 state_
.bound_valuebuffer
= NULL
;
4001 if (offscreen_saved_color_texture_info_
.get()) {
4002 DCHECK(offscreen_target_color_texture_
);
4003 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
4004 offscreen_saved_color_texture_
->id());
4005 offscreen_saved_color_texture_
->Invalidate();
4006 offscreen_saved_color_texture_info_
= NULL
;
4009 if (copy_texture_CHROMIUM_
.get()) {
4010 copy_texture_CHROMIUM_
->Destroy();
4011 copy_texture_CHROMIUM_
.reset();
4014 clear_framebuffer_blit_
.reset();
4016 if (state_
.current_program
.get()) {
4017 program_manager()->UnuseProgram(shader_manager(),
4018 state_
.current_program
.get());
4021 if (attrib_0_buffer_id_
) {
4022 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
4024 if (fixed_attrib_buffer_id_
) {
4025 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
4028 if (validation_texture_
) {
4029 glDeleteTextures(1, &validation_texture_
);
4030 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
4031 glDeleteFramebuffersEXT(1, &validation_fbo_
);
4034 if (offscreen_target_frame_buffer_
.get())
4035 offscreen_target_frame_buffer_
->Destroy();
4036 if (offscreen_target_color_texture_
.get())
4037 offscreen_target_color_texture_
->Destroy();
4038 if (offscreen_target_color_render_buffer_
.get())
4039 offscreen_target_color_render_buffer_
->Destroy();
4040 if (offscreen_target_depth_render_buffer_
.get())
4041 offscreen_target_depth_render_buffer_
->Destroy();
4042 if (offscreen_target_stencil_render_buffer_
.get())
4043 offscreen_target_stencil_render_buffer_
->Destroy();
4044 if (offscreen_saved_frame_buffer_
.get())
4045 offscreen_saved_frame_buffer_
->Destroy();
4046 if (offscreen_saved_color_texture_
.get())
4047 offscreen_saved_color_texture_
->Destroy();
4048 if (offscreen_resolved_frame_buffer_
.get())
4049 offscreen_resolved_frame_buffer_
->Destroy();
4050 if (offscreen_resolved_color_texture_
.get())
4051 offscreen_resolved_color_texture_
->Destroy();
4053 if (offscreen_target_frame_buffer_
.get())
4054 offscreen_target_frame_buffer_
->Invalidate();
4055 if (offscreen_target_color_texture_
.get())
4056 offscreen_target_color_texture_
->Invalidate();
4057 if (offscreen_target_color_render_buffer_
.get())
4058 offscreen_target_color_render_buffer_
->Invalidate();
4059 if (offscreen_target_depth_render_buffer_
.get())
4060 offscreen_target_depth_render_buffer_
->Invalidate();
4061 if (offscreen_target_stencil_render_buffer_
.get())
4062 offscreen_target_stencil_render_buffer_
->Invalidate();
4063 if (offscreen_saved_frame_buffer_
.get())
4064 offscreen_saved_frame_buffer_
->Invalidate();
4065 if (offscreen_saved_color_texture_
.get())
4066 offscreen_saved_color_texture_
->Invalidate();
4067 if (offscreen_resolved_frame_buffer_
.get())
4068 offscreen_resolved_frame_buffer_
->Invalidate();
4069 if (offscreen_resolved_color_texture_
.get())
4070 offscreen_resolved_color_texture_
->Invalidate();
4073 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4074 // Otherwise, we can leak objects. http://crbug.com/258772.
4075 // state_.current_program must be reset before group_ is reset because
4076 // the later deletes the ProgramManager object that referred by
4077 // state_.current_program object.
4078 state_
.current_program
= NULL
;
4080 copy_texture_CHROMIUM_
.reset();
4081 clear_framebuffer_blit_
.reset();
4083 if (query_manager_
.get()) {
4084 query_manager_
->Destroy(have_context
);
4085 query_manager_
.reset();
4088 if (vertex_array_manager_
.get()) {
4089 vertex_array_manager_
->Destroy(have_context
);
4090 vertex_array_manager_
.reset();
4093 if (image_manager_
.get()) {
4094 image_manager_
->Destroy(have_context
);
4095 image_manager_
.reset();
4098 offscreen_target_frame_buffer_
.reset();
4099 offscreen_target_color_texture_
.reset();
4100 offscreen_target_color_render_buffer_
.reset();
4101 offscreen_target_depth_render_buffer_
.reset();
4102 offscreen_target_stencil_render_buffer_
.reset();
4103 offscreen_saved_frame_buffer_
.reset();
4104 offscreen_saved_color_texture_
.reset();
4105 offscreen_resolved_frame_buffer_
.reset();
4106 offscreen_resolved_color_texture_
.reset();
4108 // Need to release these before releasing |group_| which may own the
4109 // ShaderTranslatorCache.
4110 fragment_translator_
= NULL
;
4111 vertex_translator_
= NULL
;
4113 // Destroy the GPU Tracer which may own some in process GPU Timings.
4115 gpu_tracer_
->Destroy(have_context
);
4116 gpu_tracer_
.reset();
4120 framebuffer_manager()->RemoveObserver(this);
4121 group_
->Destroy(this, have_context
);
4125 if (context_
.get()) {
4126 context_
->ReleaseCurrent(NULL
);
4130 #if defined(OS_MACOSX)
4131 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4132 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4133 CFRelease(it
->second
);
4135 texture_to_io_surface_map_
.clear();
4139 void GLES2DecoderImpl::SetSurface(
4140 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4141 DCHECK(context_
->IsCurrent(NULL
));
4142 DCHECK(surface_
.get());
4144 RestoreCurrentFramebufferBindings();
4147 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4148 if (!offscreen_saved_color_texture_
.get()) {
4149 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4152 if (!offscreen_saved_color_texture_info_
.get()) {
4153 GLuint service_id
= offscreen_saved_color_texture_
->id();
4154 offscreen_saved_color_texture_info_
= TextureRef::Create(
4155 texture_manager(), 0, service_id
);
4156 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4158 UpdateParentTextureInfo();
4160 mailbox_manager()->ProduceTexture(
4161 mailbox
, offscreen_saved_color_texture_info_
->texture());
4164 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4165 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4166 if (!is_offscreen
) {
4167 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4168 << " with an onscreen framebuffer.";
4172 if (offscreen_size_
== size
)
4175 offscreen_size_
= size
;
4176 int w
= offscreen_size_
.width();
4177 int h
= offscreen_size_
.height();
4178 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4179 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4180 << "to allocate storage due to excessive dimensions.";
4184 // Reallocate the offscreen target buffers.
4185 DCHECK(offscreen_target_color_format_
);
4186 if (IsOffscreenBufferMultisampled()) {
4187 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4188 feature_info_
.get(),
4190 offscreen_target_color_format_
,
4191 offscreen_target_samples_
)) {
4192 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4193 << "to allocate storage for offscreen target color buffer.";
4197 if (!offscreen_target_color_texture_
->AllocateStorage(
4198 offscreen_size_
, offscreen_target_color_format_
, false)) {
4199 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4200 << "to allocate storage for offscreen target color texture.";
4204 if (offscreen_target_depth_format_
&&
4205 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4206 feature_info_
.get(),
4208 offscreen_target_depth_format_
,
4209 offscreen_target_samples_
)) {
4210 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4211 << "to allocate storage for offscreen target depth buffer.";
4214 if (offscreen_target_stencil_format_
&&
4215 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4216 feature_info_
.get(),
4218 offscreen_target_stencil_format_
,
4219 offscreen_target_samples_
)) {
4220 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4221 << "to allocate storage for offscreen target stencil buffer.";
4225 // Attach the offscreen target buffers to the target frame buffer.
4226 if (IsOffscreenBufferMultisampled()) {
4227 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4228 GL_COLOR_ATTACHMENT0
,
4229 offscreen_target_color_render_buffer_
.get());
4231 offscreen_target_frame_buffer_
->AttachRenderTexture(
4232 offscreen_target_color_texture_
.get());
4234 if (offscreen_target_depth_format_
) {
4235 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4236 GL_DEPTH_ATTACHMENT
,
4237 offscreen_target_depth_render_buffer_
.get());
4239 const bool packed_depth_stencil
=
4240 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4241 if (packed_depth_stencil
) {
4242 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4243 GL_STENCIL_ATTACHMENT
,
4244 offscreen_target_depth_render_buffer_
.get());
4245 } else if (offscreen_target_stencil_format_
) {
4246 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4247 GL_STENCIL_ATTACHMENT
,
4248 offscreen_target_stencil_render_buffer_
.get());
4251 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4252 GL_FRAMEBUFFER_COMPLETE
) {
4253 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4254 << "because offscreen FBO was incomplete.";
4258 // Clear the target frame buffer.
4260 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4261 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f
);
4262 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4264 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4265 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4267 state_
.SetDeviceDepthMask(GL_TRUE
);
4268 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4269 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4270 RestoreClearState();
4273 // Destroy the offscreen resolved framebuffers.
4274 if (offscreen_resolved_frame_buffer_
.get())
4275 offscreen_resolved_frame_buffer_
->Destroy();
4276 if (offscreen_resolved_color_texture_
.get())
4277 offscreen_resolved_color_texture_
->Destroy();
4278 offscreen_resolved_color_texture_
.reset();
4279 offscreen_resolved_frame_buffer_
.reset();
4284 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4285 const void* cmd_data
) {
4286 const gles2::cmds::ResizeCHROMIUM
& c
=
4287 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4288 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4289 return error::kDeferCommandUntilLater
;
4291 GLuint width
= static_cast<GLuint
>(c
.width
);
4292 GLuint height
= static_cast<GLuint
>(c
.height
);
4293 GLfloat scale_factor
= c
.scale_factor
;
4294 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4296 width
= std::max(1U, width
);
4297 height
= std::max(1U, height
);
4299 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4300 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4301 // Make sure that we are done drawing to the back buffer before resizing.
4304 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4306 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4307 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4308 << "ResizeOffscreenFrameBuffer failed.";
4309 return error::kLostContext
;
4313 if (!resize_callback_
.is_null()) {
4314 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4315 DCHECK(context_
->IsCurrent(surface_
.get()));
4316 if (!context_
->IsCurrent(surface_
.get())) {
4317 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4318 << "current after resize callback.";
4319 return error::kLostContext
;
4323 return error::kNoError
;
4326 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4327 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4328 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4330 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4333 // Decode a command, and call the corresponding GL functions.
4334 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4335 // of commands at once, and is now only used for tests that need to track
4336 // individual commands.
4337 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4338 unsigned int arg_count
,
4339 const void* cmd_data
) {
4340 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4343 // Decode multiple commands, and call the corresponding GL functions.
4344 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4345 // changed by a (malicious) client at any time, so if validation has to happen,
4346 // it should operate on a copy of them.
4347 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4348 // interest of performance in this critical execution loop.
4349 template <bool DebugImpl
>
4350 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4353 int* entries_processed
) {
4354 commands_to_process_
= num_commands
;
4355 error::Error result
= error::kNoError
;
4356 const CommandBufferEntry
* cmd_data
=
4357 static_cast<const CommandBufferEntry
*>(buffer
);
4358 int process_pos
= 0;
4359 unsigned int command
= 0;
4361 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4362 commands_to_process_
--) {
4363 const unsigned int size
= cmd_data
->value_header
.size
;
4364 command
= cmd_data
->value_header
.command
;
4367 result
= error::kInvalidSize
;
4371 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4372 result
= error::kOutOfBounds
;
4376 if (DebugImpl
&& log_commands()) {
4377 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4378 << "cmd: " << GetCommandName(command
);
4381 const unsigned int arg_count
= size
- 1;
4382 unsigned int command_index
= command
- kStartPoint
- 1;
4383 if (command_index
< arraysize(command_info
)) {
4384 const CommandInfo
& info
= command_info
[command_index
];
4385 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4386 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4387 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4388 bool doing_gpu_trace
= false;
4389 if (DebugImpl
&& gpu_trace_commands_
) {
4390 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4391 doing_gpu_trace
= true;
4392 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4393 GetCommandName(command
),
4398 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4399 sizeof(CommandBufferEntry
); // NOLINT
4401 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4403 if (DebugImpl
&& doing_gpu_trace
)
4404 gpu_tracer_
->End(kTraceDecoder
);
4406 if (DebugImpl
&& debug()) {
4408 while ((error
= glGetError()) != GL_NO_ERROR
) {
4409 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4410 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4411 << " : " << GetCommandName(command
);
4412 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4416 result
= error::kInvalidArguments
;
4419 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4422 if (result
== error::kNoError
&&
4423 current_decoder_error_
!= error::kNoError
) {
4424 result
= current_decoder_error_
;
4425 current_decoder_error_
= error::kNoError
;
4428 if (result
!= error::kDeferCommandUntilLater
) {
4429 process_pos
+= size
;
4434 if (entries_processed
)
4435 *entries_processed
= process_pos
;
4437 if (error::IsError(result
)) {
4438 LOG(ERROR
) << "Error: " << result
<< " for Command "
4439 << GetCommandName(command
);
4445 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4448 int* entries_processed
) {
4449 if (gpu_debug_commands_
) {
4450 return DoCommandsImpl
<true>(
4451 num_commands
, buffer
, num_entries
, entries_processed
);
4453 return DoCommandsImpl
<false>(
4454 num_commands
, buffer
, num_entries
, entries_processed
);
4458 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4459 buffer_manager()->RemoveBuffer(client_id
);
4462 void GLES2DecoderImpl::DoFinish() {
4464 ProcessPendingReadPixels(true);
4465 ProcessPendingQueries(true);
4468 void GLES2DecoderImpl::DoFlush() {
4470 ProcessPendingQueries(false);
4473 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4474 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4475 if (texture_index
>= state_
.texture_units
.size()) {
4476 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4477 "glActiveTexture", texture_unit
, "texture_unit");
4480 state_
.active_texture_unit
= texture_index
;
4481 glActiveTexture(texture_unit
);
4484 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4485 Buffer
* buffer
= NULL
;
4486 GLuint service_id
= 0;
4487 if (client_id
!= 0) {
4488 buffer
= GetBuffer(client_id
);
4490 if (!group_
->bind_generates_resource()) {
4491 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4493 "id not generated by glGenBuffers");
4497 // It's a new id so make a buffer buffer for it.
4498 glGenBuffersARB(1, &service_id
);
4499 CreateBuffer(client_id
, service_id
);
4500 buffer
= GetBuffer(client_id
);
4503 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4505 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4507 GL_INVALID_OPERATION
,
4508 "glBindBuffer", "buffer bound to more than 1 target");
4511 service_id
= buffer
->service_id();
4513 state_
.SetBoundBuffer(target
, buffer
);
4514 glBindBuffer(target
, service_id
);
4517 void GLES2DecoderImpl::DoBindBufferBase(GLenum target
, GLuint index
,
4519 Buffer
* buffer
= NULL
;
4520 GLuint service_id
= 0;
4521 if (client_id
!= 0) {
4522 buffer
= GetBuffer(client_id
);
4524 if (!group_
->bind_generates_resource()) {
4525 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4527 "id not generated by glGenBuffers");
4531 // It's a new id so make a buffer for it.
4532 glGenBuffersARB(1, &service_id
);
4533 CreateBuffer(client_id
, service_id
);
4534 buffer
= GetBuffer(client_id
);
4537 LogClientServiceForInfo(buffer
, client_id
, "glBindBufferBase");
4539 // TODO(kbr): track indexed bound buffers.
4540 service_id
= buffer
->service_id();
4542 glBindBufferBase(target
, index
, service_id
);
4545 void GLES2DecoderImpl::DoBindBufferRange(GLenum target
, GLuint index
,
4549 Buffer
* buffer
= NULL
;
4550 GLuint service_id
= 0;
4551 if (client_id
!= 0) {
4552 buffer
= GetBuffer(client_id
);
4554 if (!group_
->bind_generates_resource()) {
4555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4556 "glBindBufferRange",
4557 "id not generated by glGenBuffers");
4561 // It's a new id so make a buffer for it.
4562 glGenBuffersARB(1, &service_id
);
4563 CreateBuffer(client_id
, service_id
);
4564 buffer
= GetBuffer(client_id
);
4567 LogClientServiceForInfo(buffer
, client_id
, "glBindBufferRange");
4569 // TODO(kbr): track indexed bound buffers.
4570 service_id
= buffer
->service_id();
4572 glBindBufferRange(target
, index
, service_id
, offset
, size
);
4575 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4576 Framebuffer
* framebuffer
=
4577 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4579 return framebuffer
->HasAlphaMRT();
4580 return BackBufferHasAlpha();
4583 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4584 Framebuffer
* framebuffer
=
4585 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4587 return framebuffer
->HasDepthAttachment();
4589 if (offscreen_target_frame_buffer_
.get()) {
4590 return offscreen_target_depth_format_
!= 0;
4592 return back_buffer_has_depth_
;
4595 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4596 Framebuffer
* framebuffer
=
4597 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4599 return framebuffer
->HasStencilAttachment();
4601 if (offscreen_target_frame_buffer_
.get()) {
4602 return offscreen_target_stencil_format_
!= 0 ||
4603 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4605 return back_buffer_has_stencil_
;
4608 void GLES2DecoderImpl::ApplyDirtyState() {
4609 if (framebuffer_state_
.clear_state_dirty
) {
4610 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha();
4611 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4612 state_
.color_mask_green
,
4613 state_
.color_mask_blue
,
4614 state_
.color_mask_alpha
&& have_alpha
);
4616 bool have_depth
= BoundFramebufferHasDepthAttachment();
4617 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4619 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4620 state_
.SetDeviceStencilMaskSeparate(
4621 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4622 state_
.SetDeviceStencilMaskSeparate(
4623 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4625 state_
.SetDeviceCapabilityState(
4626 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4627 state_
.SetDeviceCapabilityState(
4628 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4629 framebuffer_state_
.clear_state_dirty
= false;
4633 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4634 return (offscreen_target_frame_buffer_
.get())
4635 ? offscreen_target_frame_buffer_
->id()
4636 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4639 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4640 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4641 "context", logger_
.GetLogPrefix());
4642 // Restore the Framebuffer first because of bugs in Intel drivers.
4643 // Intel drivers incorrectly clip the viewport settings to
4644 // the size of the current framebuffer object.
4645 RestoreFramebufferBindings();
4646 state_
.RestoreState(prev_state
);
4649 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4651 framebuffer_state_
.bound_draw_framebuffer
.get()
4652 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4653 : GetBackbufferServiceId();
4654 if (!features().chromium_framebuffer_multisample
) {
4655 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4657 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4658 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4659 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4660 : GetBackbufferServiceId();
4661 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4666 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4667 state_
.RestoreRenderbufferBindings();
4670 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4671 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4673 GLenum target
= texture
->target();
4674 glBindTexture(target
, service_id
);
4676 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4678 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4680 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4682 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4683 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4687 void GLES2DecoderImpl::ClearAllAttributes() const {
4688 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4690 if (feature_info_
->feature_flags().native_vertex_array_object
)
4691 glBindVertexArrayOES(0);
4693 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4694 if (i
!= 0) // Never disable attribute 0
4695 glDisableVertexAttribArray(i
);
4696 if (features().angle_instanced_arrays
)
4697 glVertexAttribDivisorANGLE(i
, 0);
4701 void GLES2DecoderImpl::RestoreAllAttributes() const {
4702 state_
.RestoreVertexAttribs();
4705 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4706 state_
.SetIgnoreCachedStateForTest(ignore
);
4709 void GLES2DecoderImpl::OnFboChanged() const {
4710 if (workarounds().restore_scissor_on_fbo_change
)
4711 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4713 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4714 GLint bound_fbo_unsigned
= -1;
4715 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4716 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4717 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4718 surface_
->NotifyWasBound();
4722 // Called after the FBO is checked for completeness.
4723 void GLES2DecoderImpl::OnUseFramebuffer() const {
4724 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4725 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4726 // The driver forgets the correct scissor when modifying the FBO binding.
4727 glScissor(state_
.scissor_x
,
4729 state_
.scissor_width
,
4730 state_
.scissor_height
);
4732 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4733 // it's unclear how this bug works.
4738 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4739 Framebuffer
* framebuffer
= NULL
;
4740 GLuint service_id
= 0;
4741 if (client_id
!= 0) {
4742 framebuffer
= GetFramebuffer(client_id
);
4744 if (!group_
->bind_generates_resource()) {
4745 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4746 "glBindFramebuffer",
4747 "id not generated by glGenFramebuffers");
4751 // It's a new id so make a framebuffer framebuffer for it.
4752 glGenFramebuffersEXT(1, &service_id
);
4753 CreateFramebuffer(client_id
, service_id
);
4754 framebuffer
= GetFramebuffer(client_id
);
4756 service_id
= framebuffer
->service_id();
4758 framebuffer
->MarkAsValid();
4760 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4762 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4763 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4766 // vmiura: This looks like dup code
4767 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4768 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4771 framebuffer_state_
.clear_state_dirty
= true;
4773 // If we are rendering to the backbuffer get the FBO id for any simulated
4775 if (framebuffer
== NULL
) {
4776 service_id
= GetBackbufferServiceId();
4779 glBindFramebufferEXT(target
, service_id
);
4783 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4784 Renderbuffer
* renderbuffer
= NULL
;
4785 GLuint service_id
= 0;
4786 if (client_id
!= 0) {
4787 renderbuffer
= GetRenderbuffer(client_id
);
4788 if (!renderbuffer
) {
4789 if (!group_
->bind_generates_resource()) {
4790 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4791 "glBindRenderbuffer",
4792 "id not generated by glGenRenderbuffers");
4796 // It's a new id so make a renderbuffer for it.
4797 glGenRenderbuffersEXT(1, &service_id
);
4798 CreateRenderbuffer(client_id
, service_id
);
4799 renderbuffer
= GetRenderbuffer(client_id
);
4801 service_id
= renderbuffer
->service_id();
4803 renderbuffer
->MarkAsValid();
4805 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4806 state_
.bound_renderbuffer
= renderbuffer
;
4807 state_
.bound_renderbuffer_valid
= true;
4808 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4811 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4812 TextureRef
* texture_ref
= NULL
;
4813 GLuint service_id
= 0;
4814 if (client_id
!= 0) {
4815 texture_ref
= GetTexture(client_id
);
4817 if (!group_
->bind_generates_resource()) {
4818 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4820 "id not generated by glGenTextures");
4824 // It's a new id so make a texture texture for it.
4825 glGenTextures(1, &service_id
);
4826 DCHECK_NE(0u, service_id
);
4827 CreateTexture(client_id
, service_id
);
4828 texture_ref
= GetTexture(client_id
);
4831 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4834 // Check the texture exists
4836 Texture
* texture
= texture_ref
->texture();
4837 // Check that we are not trying to bind it to a different target.
4838 if (texture
->target() != 0 && texture
->target() != target
) {
4839 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4841 "texture bound to more than 1 target.");
4844 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4845 if (texture
->target() == 0) {
4846 texture_manager()->SetTarget(texture_ref
, target
);
4848 glBindTexture(target
, texture
->service_id());
4850 glBindTexture(target
, 0);
4853 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4854 unit
.bind_target
= target
;
4857 unit
.bound_texture_2d
= texture_ref
;
4859 case GL_TEXTURE_CUBE_MAP
:
4860 unit
.bound_texture_cube_map
= texture_ref
;
4862 case GL_TEXTURE_EXTERNAL_OES
:
4863 unit
.bound_texture_external_oes
= texture_ref
;
4865 case GL_TEXTURE_RECTANGLE_ARB
:
4866 unit
.bound_texture_rectangle_arb
= texture_ref
;
4869 unit
.bound_texture_3d
= texture_ref
;
4871 case GL_TEXTURE_2D_ARRAY
:
4872 unit
.bound_texture_2d_array
= texture_ref
;
4875 NOTREACHED(); // Validation should prevent us getting here.
4880 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4881 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4883 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4884 glDisableVertexAttribArray(index
);
4889 "glDisableVertexAttribArray", "index out of range");
4893 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4894 GLsizei numAttachments
,
4895 const GLenum
* attachments
) {
4896 if (workarounds().disable_discard_framebuffer
)
4899 Framebuffer
* framebuffer
=
4900 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4902 // Validates the attachments. If one of them fails
4903 // the whole command fails.
4904 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4906 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4908 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4909 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4910 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4915 // Marks each one of them as not cleared
4916 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4918 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4923 switch (attachments
[i
]) {
4925 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4928 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4929 case GL_STENCIL_EXT
:
4930 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4939 // If the default framebuffer is bound but we are still rendering to an
4940 // FBO, translate attachment names that refer to default framebuffer
4941 // channels to corresponding framebuffer attachments.
4942 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4943 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4944 GLenum attachment
= attachments
[i
];
4945 if (!framebuffer
&& GetBackbufferServiceId()) {
4946 switch (attachment
) {
4948 attachment
= GL_COLOR_ATTACHMENT0
;
4951 attachment
= GL_DEPTH_ATTACHMENT
;
4953 case GL_STENCIL_EXT
:
4954 attachment
= GL_STENCIL_ATTACHMENT
;
4961 translated_attachments
[i
] = attachment
;
4964 ScopedRenderTo
do_render(framebuffer
);
4965 if (feature_info_
->gl_version_info().is_es3
) {
4966 glInvalidateFramebuffer(
4967 target
, numAttachments
, translated_attachments
.get());
4969 glDiscardFramebufferEXT(
4970 target
, numAttachments
, translated_attachments
.get());
4974 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4975 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4976 glEnableVertexAttribArray(index
);
4979 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4983 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4984 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4987 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4989 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4993 if (target
== GL_TEXTURE_CUBE_MAP
) {
4994 for (int i
= 0; i
< 6; ++i
) {
4995 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4996 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
4998 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
5003 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
5005 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
5010 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
5011 // Workaround for Mac driver bug. In the large scheme of things setting
5012 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
5013 // hit so there's probably no need to make this conditional. The bug appears
5014 // to be that if the filtering mode is set to something that doesn't require
5015 // mipmaps for rendering, or is never set to something other than the default,
5016 // then glGenerateMipmap misbehaves.
5017 if (workarounds().set_texture_filter_before_generating_mipmap
) {
5018 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
5020 glGenerateMipmapEXT(target
);
5021 if (workarounds().set_texture_filter_before_generating_mipmap
) {
5022 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
5023 texture_ref
->texture()->min_filter());
5025 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
5026 if (error
== GL_NO_ERROR
) {
5027 texture_manager()->MarkMipmapsGenerated(texture_ref
);
5031 bool GLES2DecoderImpl::GetHelper(
5032 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
5033 DCHECK(num_written
);
5034 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
5036 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
5038 // Return the GL implementation's preferred format and (see below type)
5039 // if we have the GL extension that exposes this. This allows the GPU
5040 // client to use the implementation's preferred format for glReadPixels
5041 // for optimisation.
5043 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
5044 // case when requested on integer/floating point buffers but which is
5045 // acceptable on GLES2 and with the GL_OES_read_format extension.
5047 // Therefore if an error occurs we swallow the error and use the
5048 // internal implementation.
5050 if (context_
->HasExtension("GL_OES_read_format")) {
5051 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
5053 glGetIntegerv(pname
, params
);
5054 if (glGetError() == GL_NO_ERROR
)
5057 *params
= GLES2Util::GetGLReadPixelsImplementationFormat(
5058 GetBoundReadFrameBufferInternalFormat());
5061 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
5064 if (context_
->HasExtension("GL_OES_read_format")) {
5065 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
5067 glGetIntegerv(pname
, params
);
5068 if (glGetError() == GL_NO_ERROR
)
5071 *params
= GLES2Util::GetGLReadPixelsImplementationType(
5072 GetBoundReadFrameBufferInternalFormat(),
5073 GetBoundReadFrameBufferTextureType());
5076 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
5079 *params
= group_
->max_fragment_uniform_vectors();
5082 case GL_MAX_VARYING_VECTORS
:
5085 *params
= group_
->max_varying_vectors();
5088 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
5091 *params
= group_
->max_vertex_uniform_vectors();
5096 if (unsafe_es3_apis_enabled()) {
5098 case GL_MAX_VARYING_COMPONENTS
: {
5099 if (feature_info_
->gl_version_info().is_es
) {
5100 // We can just delegate this query to the driver.
5104 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5105 // OpenGL core profile, so for simplicity, just compute it
5106 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5108 GLint max_varying_vectors
= 0;
5109 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5112 *params
= max_varying_vectors
* 4;
5116 case GL_READ_BUFFER
:
5119 Framebuffer
* framebuffer
=
5120 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5123 read_buffer
= framebuffer
->read_buffer();
5125 read_buffer
= back_buffer_read_buffer_
;
5127 *params
= static_cast<GLint
>(read_buffer
);
5133 case GL_MAX_VIEWPORT_DIMS
:
5134 if (offscreen_target_frame_buffer_
.get()) {
5137 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5138 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5143 case GL_MAX_SAMPLES
:
5146 params
[0] = renderbuffer_manager()->max_samples();
5149 case GL_MAX_RENDERBUFFER_SIZE
:
5152 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5155 case GL_MAX_TEXTURE_SIZE
:
5158 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5161 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5164 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5167 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5170 params
[0] = group_
->max_color_attachments();
5173 case GL_MAX_DRAW_BUFFERS_ARB
:
5176 params
[0] = group_
->max_draw_buffers();
5183 Framebuffer
* framebuffer
=
5184 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5186 if (framebuffer
->HasAlphaMRT() &&
5187 framebuffer
->HasSameInternalFormatsMRT()) {
5188 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5189 glGetFramebufferAttachmentParameterivEXT(
5190 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5191 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5193 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5197 v
= (BackBufferHasAlpha() ? 8 : 0);
5206 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5207 Framebuffer
* framebuffer
=
5208 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5210 glGetFramebufferAttachmentParameterivEXT(
5211 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5212 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5214 v
= (back_buffer_has_depth_
? 24 : 0);
5217 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5219 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5228 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5229 Framebuffer
* framebuffer
=
5230 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5232 GLenum framebuffer_enum
= 0;
5235 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5238 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5241 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5244 glGetFramebufferAttachmentParameterivEXT(
5245 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5250 glGetIntegerv(pname
, &v
);
5255 case GL_STENCIL_BITS
:
5259 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5260 Framebuffer
* framebuffer
=
5261 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5263 glGetFramebufferAttachmentParameterivEXT(
5264 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5265 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5267 v
= (back_buffer_has_stencil_
? 8 : 0);
5270 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5272 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5275 case GL_COMPRESSED_TEXTURE_FORMATS
:
5276 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5278 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5279 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5283 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5286 *params
= validators_
->compressed_texture_format
.GetValues().size();
5289 case GL_NUM_SHADER_BINARY_FORMATS
:
5292 *params
= validators_
->shader_binary_format
.GetValues().size();
5295 case GL_SHADER_BINARY_FORMATS
:
5296 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5298 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5299 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5303 case GL_SHADER_COMPILER
:
5309 case GL_ARRAY_BUFFER_BINDING
:
5312 *params
= GetClientId(
5313 buffer_manager(), state_
.bound_array_buffer
.get());
5316 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5319 *params
= GetClientId(
5321 state_
.vertex_attrib_manager
->element_array_buffer());
5324 case GL_COPY_READ_BUFFER_BINDING
:
5327 *params
= GetClientId(
5328 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5331 case GL_COPY_WRITE_BUFFER_BINDING
:
5334 *params
= GetClientId(
5335 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5338 case GL_PIXEL_PACK_BUFFER_BINDING
:
5341 *params
= GetClientId(
5342 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5345 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5348 *params
= GetClientId(
5349 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5352 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5355 *params
= GetClientId(
5356 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5359 case GL_UNIFORM_BUFFER_BINDING
:
5362 *params
= GetClientId(
5363 buffer_manager(), state_
.bound_uniform_buffer
.get());
5366 case GL_FRAMEBUFFER_BINDING
:
5367 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5370 *params
= GetClientId(
5371 framebuffer_manager(),
5372 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5375 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5378 *params
= GetClientId(
5379 framebuffer_manager(),
5380 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5383 case GL_RENDERBUFFER_BINDING
:
5386 Renderbuffer
* renderbuffer
=
5387 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5389 *params
= renderbuffer
->client_id();
5395 case GL_CURRENT_PROGRAM
:
5398 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5401 case GL_VERTEX_ARRAY_BINDING_OES
:
5404 if (state_
.vertex_attrib_manager
.get() !=
5405 state_
.default_vertex_attrib_manager
.get()) {
5406 GLuint client_id
= 0;
5407 vertex_array_manager_
->GetClientId(
5408 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5409 *params
= client_id
;
5415 case GL_TEXTURE_BINDING_2D
:
5418 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5419 if (unit
.bound_texture_2d
.get()) {
5420 *params
= unit
.bound_texture_2d
->client_id();
5426 case GL_TEXTURE_BINDING_CUBE_MAP
:
5429 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5430 if (unit
.bound_texture_cube_map
.get()) {
5431 *params
= unit
.bound_texture_cube_map
->client_id();
5437 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5440 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5441 if (unit
.bound_texture_external_oes
.get()) {
5442 *params
= unit
.bound_texture_external_oes
->client_id();
5448 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5451 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5452 if (unit
.bound_texture_rectangle_arb
.get()) {
5453 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5459 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5462 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5466 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5467 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5470 Framebuffer
* framebuffer
=
5471 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5473 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5474 } else { // backbuffer
5475 if (pname
== GL_DRAW_BUFFER0_ARB
)
5476 params
[0] = back_buffer_draw_buffer_
;
5478 params
[0] = GL_NONE
;
5483 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5488 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5489 GLenum pname
, GLsizei
* num_values
) {
5490 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5493 return GetHelper(pname
, NULL
, num_values
);
5496 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5497 if (GL_MAX_SAMPLES
== pname
&&
5498 features().use_img_for_multisampled_render_to_texture
) {
5499 return GL_MAX_SAMPLES_IMG
;
5504 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5506 GLsizei num_written
= 0;
5507 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5508 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5509 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5510 GetHelper(pname
, values
.get(), &num_written
);
5512 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5513 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5516 pname
= AdjustGetPname(pname
);
5517 glGetBooleanv(pname
, params
);
5521 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5523 GLsizei num_written
= 0;
5524 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5525 if (GetHelper(pname
, NULL
, &num_written
)) {
5526 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5527 GetHelper(pname
, values
.get(), &num_written
);
5528 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5529 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5532 pname
= AdjustGetPname(pname
);
5533 glGetFloatv(pname
, params
);
5538 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5540 if (unsafe_es3_apis_enabled()) {
5542 case GL_MAX_ELEMENT_INDEX
: {
5543 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5544 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5545 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5547 // Assume that desktop GL implementations can generally support
5550 *params
= std::numeric_limits
<unsigned int>::max();
5557 pname
= AdjustGetPname(pname
);
5558 glGetInteger64v(pname
, params
);
5561 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5563 GLsizei num_written
;
5564 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5565 !GetHelper(pname
, params
, &num_written
)) {
5566 pname
= AdjustGetPname(pname
);
5567 glGetIntegerv(pname
, params
);
5571 void GLES2DecoderImpl::DoGetProgramiv(
5572 GLuint program_id
, GLenum pname
, GLint
* params
) {
5573 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5577 program
->GetProgramiv(pname
, params
);
5580 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5581 GLenum target
, GLenum pname
, GLint64
* params
) {
5582 // Just delegate it. Some validation is actually done before this.
5583 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5584 &state_
, target
, pname
, params
);
5587 void GLES2DecoderImpl::DoGetBufferParameteriv(
5588 GLenum target
, GLenum pname
, GLint
* params
) {
5589 // Just delegate it. Some validation is actually done before this.
5590 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5591 &state_
, target
, pname
, params
);
5594 void GLES2DecoderImpl::DoBindAttribLocation(
5595 GLuint program_id
, GLuint index
, const char* name
) {
5596 if (!StringIsValidForGLES(name
)) {
5598 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5601 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5603 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5606 if (index
>= group_
->max_vertex_attribs()) {
5608 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5611 Program
* program
= GetProgramInfoNotShader(
5612 program_id
, "glBindAttribLocation");
5616 // At this point, the program's shaders may not be translated yet,
5617 // therefore, we may not find the hashed attribute name.
5618 // glBindAttribLocation call with original name is useless.
5619 // So instead, we should simply cache the binding, and then call
5620 // Program::ExecuteBindAttribLocationCalls() right before link.
5621 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5622 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5623 glBindAttribLocation(program
->service_id(), index
, name
);
5626 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5627 uint32 immediate_data_size
,
5628 const void* cmd_data
) {
5629 const gles2::cmds::BindAttribLocationBucket
& c
=
5630 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5631 GLuint program
= static_cast<GLuint
>(c
.program
);
5632 GLuint index
= static_cast<GLuint
>(c
.index
);
5633 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5634 if (!bucket
|| bucket
->size() == 0) {
5635 return error::kInvalidArguments
;
5637 std::string name_str
;
5638 if (!bucket
->GetAsString(&name_str
)) {
5639 return error::kInvalidArguments
;
5641 DoBindAttribLocation(program
, index
, name_str
.c_str());
5642 return error::kNoError
;
5645 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5646 GLuint program_id
, GLint location
, const char* name
) {
5647 if (!StringIsValidForGLES(name
)) {
5650 "glBindUniformLocationCHROMIUM", "Invalid character");
5653 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5655 GL_INVALID_OPERATION
,
5656 "glBindUniformLocationCHROMIUM", "reserved prefix");
5659 if (location
< 0 || static_cast<uint32
>(location
) >=
5660 (group_
->max_fragment_uniform_vectors() +
5661 group_
->max_vertex_uniform_vectors()) * 4) {
5664 "glBindUniformLocationCHROMIUM", "location out of range");
5667 Program
* program
= GetProgramInfoNotShader(
5668 program_id
, "glBindUniformLocationCHROMIUM");
5672 if (!program
->SetUniformLocationBinding(name
, location
)) {
5675 "glBindUniformLocationCHROMIUM", "location out of range");
5679 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5680 uint32 immediate_data_size
,
5681 const void* cmd_data
) {
5682 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5683 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5685 GLuint program
= static_cast<GLuint
>(c
.program
);
5686 GLint location
= static_cast<GLint
>(c
.location
);
5687 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5688 if (!bucket
|| bucket
->size() == 0) {
5689 return error::kInvalidArguments
;
5691 std::string name_str
;
5692 if (!bucket
->GetAsString(&name_str
)) {
5693 return error::kInvalidArguments
;
5695 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5696 return error::kNoError
;
5699 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5700 const void* cmd_data
) {
5701 const gles2::cmds::DeleteShader
& c
=
5702 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5703 GLuint client_id
= c
.shader
;
5705 Shader
* shader
= GetShader(client_id
);
5707 if (!shader
->IsDeleted()) {
5708 shader_manager()->Delete(shader
);
5711 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5714 return error::kNoError
;
5717 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5718 const void* cmd_data
) {
5719 const gles2::cmds::DeleteProgram
& c
=
5720 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5721 GLuint client_id
= c
.program
;
5723 Program
* program
= GetProgram(client_id
);
5725 if (!program
->IsDeleted()) {
5726 program_manager()->MarkAsDeleted(shader_manager(), program
);
5730 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5733 return error::kNoError
;
5736 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5737 DCHECK(!ShouldDeferDraws());
5738 if (CheckBoundFramebuffersValid("glClear")) {
5740 // TODO(zmo): Filter out INTEGER/SIGNED INTEGER images to avoid
5741 // undefined results.
5742 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5743 if (workarounds().gl_clear_broken
) {
5744 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5746 if (!BoundFramebufferHasDepthAttachment())
5747 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5748 if (!BoundFramebufferHasStencilAttachment())
5749 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5750 clear_framebuffer_blit_
->ClearFramebuffer(
5751 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5752 state_
.color_clear_green
, state_
.color_clear_blue
,
5753 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5754 return error::kNoError
;
5758 return error::kNoError
;
5761 void GLES2DecoderImpl::DoClearBufferiv(
5762 GLenum buffer
, GLint drawbuffer
, const GLint
* value
) {
5763 if (!CheckBoundDrawFramebufferValid("glClearBufferiv"))
5773 GL_INVALID_ENUM
, "glClearBufferiv", "invalid buffer");
5776 GLenum attachment
= 0;
5777 if (buffer
== GL_COLOR
) {
5778 if (drawbuffer
< 0 ||
5779 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5781 GL_INVALID_VALUE
, "glClearBufferiv", "invalid drawBuffer");
5784 GLenum internal_format
=
5785 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5786 if (!GLES2Util::IsSignedIntegerFormat(internal_format
)) {
5787 // To avoid undefined results, return without calling the gl function.
5790 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5792 DCHECK(buffer
== GL_STENCIL
);
5793 if (drawbuffer
!= 0) {
5795 GL_INVALID_VALUE
, "glClearBufferiv", "invalid drawBuffer");
5798 if (!BoundFramebufferHasStencilAttachment()) {
5801 attachment
= GL_STENCIL_ATTACHMENT
;
5803 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5805 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5807 glClearBufferiv(buffer
, drawbuffer
, value
);
5811 void GLES2DecoderImpl::DoClearBufferuiv(
5812 GLenum buffer
, GLint drawbuffer
, const GLuint
* value
) {
5813 if (!CheckBoundDrawFramebufferValid("glClearBufferuiv"))
5822 GL_INVALID_ENUM
, "glClearBufferuiv", "invalid buffer");
5825 if (drawbuffer
< 0 ||
5826 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5828 GL_INVALID_VALUE
, "glClearBufferuiv", "invalid drawBuffer");
5831 GLenum internal_format
=
5832 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5833 if (!GLES2Util::IsUnsignedIntegerFormat(internal_format
)) {
5834 // To avoid undefined results, return without calling the gl function.
5837 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5838 GLenum attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5840 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5842 glClearBufferuiv(buffer
, drawbuffer
, value
);
5846 void GLES2DecoderImpl::DoClearBufferfv(
5847 GLenum buffer
, GLint drawbuffer
, const GLfloat
* value
) {
5848 if (!CheckBoundDrawFramebufferValid("glClearBufferfv"))
5858 GL_INVALID_ENUM
, "glClearBufferfv", "invalid buffer");
5861 GLenum attachment
= 0;
5862 if (buffer
== GL_COLOR
) {
5863 if (drawbuffer
< 0 ||
5864 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5866 GL_INVALID_VALUE
, "glClearBufferfv", "invalid drawBuffer");
5869 GLenum internal_format
=
5870 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5871 if (GLES2Util::IsIntegerFormat(internal_format
)) {
5872 // To avoid undefined results, return without calling the gl function.
5875 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5877 DCHECK(buffer
== GL_DEPTH
);
5878 if (drawbuffer
!= 0) {
5880 GL_INVALID_VALUE
, "glClearBufferfv", "invalid drawBuffer");
5883 if (!BoundFramebufferHasDepthAttachment()) {
5886 attachment
= GL_DEPTH_ATTACHMENT
;
5888 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5890 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5892 glClearBufferfv(buffer
, drawbuffer
, value
);
5896 void GLES2DecoderImpl::DoClearBufferfi(
5897 GLenum buffer
, GLint drawbuffer
, GLfloat depth
, GLint stencil
) {
5898 if (!CheckBoundDrawFramebufferValid("glClearBufferfi"))
5903 case GL_DEPTH_STENCIL
:
5907 GL_INVALID_ENUM
, "glClearBufferfi", "invalid buffer");
5910 if (drawbuffer
!= 0) {
5912 GL_INVALID_VALUE
, "glClearBufferfi", "invalid drawBuffer");
5915 if (!BoundFramebufferHasDepthAttachment() &&
5916 !BoundFramebufferHasStencilAttachment()) {
5919 MarkDrawBufferAsCleared(GL_DEPTH
, drawbuffer
);
5920 MarkDrawBufferAsCleared(GL_STENCIL
, drawbuffer
);
5922 ScopedRenderTo
do_render_depth(
5923 framebuffer_state_
.bound_draw_framebuffer
.get(),
5924 GL_DEPTH_ATTACHMENT
);
5925 ScopedRenderTo
do_render_stencil(
5926 framebuffer_state_
.bound_draw_framebuffer
.get(),
5927 GL_STENCIL_ATTACHMENT
);
5928 glClearBufferfi(buffer
, drawbuffer
, depth
, stencil
);
5932 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5933 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5934 GLuint client_renderbuffer_id
) {
5935 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5938 GL_INVALID_OPERATION
,
5939 "glFramebufferRenderbuffer", "no framebuffer bound");
5942 GLuint service_id
= 0;
5943 Renderbuffer
* renderbuffer
= NULL
;
5944 if (client_renderbuffer_id
) {
5945 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5946 if (!renderbuffer
) {
5948 GL_INVALID_OPERATION
,
5949 "glFramebufferRenderbuffer", "unknown renderbuffer");
5952 service_id
= renderbuffer
->service_id();
5954 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5955 glFramebufferRenderbufferEXT(
5956 target
, attachment
, renderbuffertarget
, service_id
);
5957 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5958 if (error
== GL_NO_ERROR
) {
5959 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5961 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5962 framebuffer_state_
.clear_state_dirty
= true;
5967 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5968 if (SetCapabilityState(cap
, false)) {
5973 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5974 if (SetCapabilityState(cap
, true)) {
5979 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5980 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5981 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5982 glDepthRange(znear
, zfar
);
5985 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5986 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5987 state_
.sample_coverage_invert
= (invert
!= 0);
5988 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5991 // Assumes framebuffer is complete.
5992 void GLES2DecoderImpl::ClearUnclearedAttachments(
5993 GLenum target
, Framebuffer
* framebuffer
) {
5994 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5995 // bind this to the DRAW point, clear then bind back to READ
5996 // TODO(gman): I don't think there is any guarantee that an FBO that
5997 // is complete on the READ attachment will be complete as a DRAW
5999 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
6000 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
6002 GLbitfield clear_bits
= 0;
6003 if (framebuffer
->HasUnclearedColorAttachments()) {
6004 // We should always use alpha == 0 here, because 1) some draw buffers may
6005 // have alpha and some may not; 2) we won't have the same situation as the
6006 // back buffer where alpha channel exists but is not requested.
6007 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
6008 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6009 clear_bits
|= GL_COLOR_BUFFER_BIT
;
6010 if (feature_info_
->feature_flags().ext_draw_buffers
||
6011 feature_info_
->IsES3Enabled()) {
6012 framebuffer
->PrepareDrawBuffersForClear();
6016 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
6017 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
6019 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
6020 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
6021 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
6024 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
6025 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
6027 state_
.SetDeviceDepthMask(GL_TRUE
);
6028 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
6031 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6032 glClear(clear_bits
);
6034 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
6035 (feature_info_
->feature_flags().ext_draw_buffers
||
6036 feature_info_
->IsES3Enabled())) {
6037 framebuffer
->RestoreDrawBuffersAfterClear();
6040 if (feature_info_
->IsES3Enabled()) {
6041 // TODO(zmo): track more state to know whether there are any integer
6042 // buffers attached to the current framebuffer.
6043 framebuffer
->ClearIntegerBuffers();
6046 framebuffer_manager()->MarkAttachmentsAsCleared(
6047 framebuffer
, renderbuffer_manager(), texture_manager());
6049 RestoreClearState();
6051 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
6052 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
6053 Framebuffer
* draw_framebuffer
=
6054 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
6055 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
6056 GetBackbufferServiceId();
6057 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
6061 void GLES2DecoderImpl::RestoreClearState() {
6062 framebuffer_state_
.clear_state_dirty
= true;
6064 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
6065 state_
.color_clear_alpha
);
6066 glClearStencil(state_
.stencil_clear
);
6067 glClearDepth(state_
.depth_clear
);
6068 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6069 state_
.enable_flags
.scissor_test
);
6070 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
6071 state_
.scissor_height
);
6074 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
6075 Framebuffer
* framebuffer
=
6076 GetFramebufferInfoForTarget(target
);
6078 return GL_FRAMEBUFFER_COMPLETE
;
6080 GLenum completeness
= framebuffer
->IsPossiblyComplete();
6081 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
6082 return completeness
;
6084 return framebuffer
->GetStatus(texture_manager(), target
);
6087 void GLES2DecoderImpl::DoFramebufferTexture2D(
6088 GLenum target
, GLenum attachment
, GLenum textarget
,
6089 GLuint client_texture_id
, GLint level
) {
6090 DoFramebufferTexture2DCommon(
6091 "glFramebufferTexture2D", target
, attachment
,
6092 textarget
, client_texture_id
, level
, 0);
6095 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
6096 GLenum target
, GLenum attachment
, GLenum textarget
,
6097 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
6098 DoFramebufferTexture2DCommon(
6099 "glFramebufferTexture2DMultisample", target
, attachment
,
6100 textarget
, client_texture_id
, level
, samples
);
6103 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
6104 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
6105 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
6106 if (samples
> renderbuffer_manager()->max_samples()) {
6109 "glFramebufferTexture2DMultisample", "samples too large");
6112 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
6115 GL_INVALID_OPERATION
,
6116 name
, "no framebuffer bound.");
6119 GLuint service_id
= 0;
6120 TextureRef
* texture_ref
= NULL
;
6121 if (client_texture_id
) {
6122 texture_ref
= GetTexture(client_texture_id
);
6125 GL_INVALID_OPERATION
,
6126 name
, "unknown texture_ref");
6129 service_id
= texture_ref
->service_id();
6132 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
6135 name
, "level out of range");
6140 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
6142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
6144 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
6146 if (features().use_img_for_multisampled_render_to_texture
) {
6147 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
6148 service_id
, level
, samples
);
6150 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
6151 service_id
, level
, samples
);
6154 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
6155 if (error
== GL_NO_ERROR
) {
6156 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
6159 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
6160 framebuffer_state_
.clear_state_dirty
= true;
6164 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
6169 void GLES2DecoderImpl::DoFramebufferTextureLayer(
6170 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
6171 GLint level
, GLint layer
) {
6172 // TODO(zmo): Unsafe ES3 API, missing states update.
6173 GLuint service_id
= 0;
6174 TextureRef
* texture_ref
= NULL
;
6175 if (client_texture_id
) {
6176 texture_ref
= GetTexture(client_texture_id
);
6179 GL_INVALID_OPERATION
,
6180 "glFramebufferTextureLayer", "unknown texture_ref");
6183 service_id
= texture_ref
->service_id();
6185 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
6188 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
6189 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
6190 const char kFunctionName
[] = "glGetFramebufferAttachmentParameteriv";
6191 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
6193 if (!unsafe_es3_apis_enabled()) {
6194 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
6195 "no framebuffer bound");
6198 if (!validators_
->backbuffer_attachment
.IsValid(attachment
)) {
6199 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
6200 "invalid attachment for backbuffer");
6204 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
:
6205 *params
= static_cast<GLint
>(GL_FRAMEBUFFER_DEFAULT
);
6207 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
:
6208 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
:
6209 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
:
6210 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
:
6211 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
:
6212 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
:
6213 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE
:
6214 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
:
6215 // Delegate to underlying driver.
6218 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
,
6219 "invalid pname for backbuffer");
6222 if (GetBackbufferServiceId() != 0) { // Emulated backbuffer.
6223 switch (attachment
) {
6225 attachment
= GL_COLOR_ATTACHMENT0
;
6228 attachment
= GL_DEPTH_ATTACHMENT
;
6231 attachment
= GL_STENCIL_ATTACHMENT
;
6239 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
6240 features().use_img_for_multisampled_render_to_texture
) {
6241 pname
= GL_TEXTURE_SAMPLES_IMG
;
6243 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
6244 DCHECK(framebuffer
);
6245 // If we query from the driver, it will be service ID; however, we need to
6246 // return the client ID here.
6247 const Framebuffer::Attachment
* attachment_object
=
6248 framebuffer
->GetAttachment(attachment
);
6249 *params
= attachment_object
? attachment_object
->object_name() : 0;
6253 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
6254 // We didn't perform a full error check before gl call.
6255 LOCAL_PEEK_GL_ERROR(kFunctionName
);
6258 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
6259 GLenum target
, GLenum pname
, GLint
* params
) {
6260 Renderbuffer
* renderbuffer
=
6261 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6262 if (!renderbuffer
) {
6264 GL_INVALID_OPERATION
,
6265 "glGetRenderbufferParameteriv", "no renderbuffer bound");
6269 EnsureRenderbufferBound();
6271 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
6272 *params
= renderbuffer
->internal_format();
6274 case GL_RENDERBUFFER_WIDTH
:
6275 *params
= renderbuffer
->width();
6277 case GL_RENDERBUFFER_HEIGHT
:
6278 *params
= renderbuffer
->height();
6280 case GL_RENDERBUFFER_SAMPLES_EXT
:
6281 if (features().use_img_for_multisampled_render_to_texture
) {
6282 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
6285 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
6289 glGetRenderbufferParameterivEXT(target
, pname
, params
);
6294 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
6295 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
6296 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
6297 GLbitfield mask
, GLenum filter
) {
6298 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
6300 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
6304 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6305 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6306 BlitFramebufferHelper(
6307 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6308 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6309 state_
.enable_flags
.scissor_test
);
6312 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6313 if (!state_
.bound_renderbuffer_valid
) {
6314 state_
.bound_renderbuffer_valid
= true;
6315 glBindRenderbufferEXT(GL_RENDERBUFFER
,
6316 state_
.bound_renderbuffer
.get()
6317 ? state_
.bound_renderbuffer
->service_id()
6322 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6323 const FeatureInfo
* feature_info
,
6326 GLenum internal_format
,
6329 // TODO(sievers): This could be resolved at the GL binding level, but the
6330 // binding process is currently a bit too 'brute force'.
6331 if (feature_info
->gl_version_info().is_angle
) {
6332 glRenderbufferStorageMultisampleANGLE(
6333 target
, samples
, internal_format
, width
, height
);
6334 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6335 glRenderbufferStorageMultisample(
6336 target
, samples
, internal_format
, width
, height
);
6338 glRenderbufferStorageMultisampleEXT(
6339 target
, samples
, internal_format
, width
, height
);
6343 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6353 // TODO(sievers): This could be resolved at the GL binding level, but the
6354 // binding process is currently a bit too 'brute force'.
6355 if (feature_info_
->gl_version_info().is_angle
) {
6356 glBlitFramebufferANGLE(
6357 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6358 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6360 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6362 glBlitFramebufferEXT(
6363 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6367 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6369 GLenum internalformat
,
6372 if (samples
> renderbuffer_manager()->max_samples()) {
6375 "glRenderbufferStorageMultisample", "samples too large");
6379 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6380 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6383 "glRenderbufferStorageMultisample", "dimensions too large");
6387 uint32 estimated_size
= 0;
6388 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6389 width
, height
, samples
, internalformat
, &estimated_size
)) {
6392 "glRenderbufferStorageMultisample", "dimensions too large");
6396 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6399 "glRenderbufferStorageMultisample", "out of memory");
6406 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6407 GLenum target
, GLsizei samples
, GLenum internalformat
,
6408 GLsizei width
, GLsizei height
) {
6409 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6410 if (!renderbuffer
) {
6411 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6412 "glRenderbufferStorageMultisampleCHROMIUM",
6413 "no renderbuffer bound");
6417 if (!ValidateRenderbufferStorageMultisample(
6418 samples
, internalformat
, width
, height
)) {
6422 EnsureRenderbufferBound();
6423 GLenum impl_format
=
6424 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6426 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6427 "glRenderbufferStorageMultisampleCHROMIUM");
6428 RenderbufferStorageMultisampleHelper(
6429 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6431 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6432 if (error
== GL_NO_ERROR
) {
6433 if (workarounds().validate_multisample_buffer_allocation
) {
6434 if (!VerifyMultisampleRenderbufferIntegrity(
6435 renderbuffer
->service_id(), impl_format
)) {
6438 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6443 // TODO(gman): If renderbuffers tracked which framebuffers they were
6444 // attached to we could just mark those framebuffers as not complete.
6445 framebuffer_manager()->IncFramebufferStateChangeCount();
6446 renderbuffer_manager()->SetInfo(
6447 renderbuffer
, samples
, internalformat
, width
, height
);
6451 // This is the handler for multisampled_render_to_texture extensions.
6452 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6453 GLenum target
, GLsizei samples
, GLenum internalformat
,
6454 GLsizei width
, GLsizei height
) {
6455 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6456 if (!renderbuffer
) {
6457 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6458 "glRenderbufferStorageMultisampleEXT",
6459 "no renderbuffer bound");
6463 if (!ValidateRenderbufferStorageMultisample(
6464 samples
, internalformat
, width
, height
)) {
6468 EnsureRenderbufferBound();
6469 GLenum impl_format
=
6470 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6472 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6473 if (features().use_img_for_multisampled_render_to_texture
) {
6474 glRenderbufferStorageMultisampleIMG(
6475 target
, samples
, impl_format
, width
, height
);
6477 glRenderbufferStorageMultisampleEXT(
6478 target
, samples
, impl_format
, width
, height
);
6480 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6481 if (error
== GL_NO_ERROR
) {
6482 // TODO(gman): If renderbuffers tracked which framebuffers they were
6483 // attached to we could just mark those framebuffers as not complete.
6484 framebuffer_manager()->IncFramebufferStateChangeCount();
6485 renderbuffer_manager()->SetInfo(
6486 renderbuffer
, samples
, internalformat
, width
, height
);
6490 // This function validates the allocation of a multisampled renderbuffer
6491 // by clearing it to a key color, blitting the contents to a texture, and
6492 // reading back the color to ensure it matches the key.
6493 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6494 GLuint renderbuffer
, GLenum format
) {
6496 // Only validate color buffers.
6497 // These formats have been selected because they are very common or are known
6498 // to be used by the WebGL backbuffer. If problems are observed with other
6499 // color formats they can be added here.
6510 GLint draw_framebuffer
, read_framebuffer
;
6512 // Cache framebuffer and texture bindings.
6513 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6514 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6516 if (!validation_texture_
) {
6517 GLint bound_texture
;
6518 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6520 // Create additional resources needed for the verification.
6521 glGenTextures(1, &validation_texture_
);
6522 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6523 glGenFramebuffersEXT(1, &validation_fbo_
);
6525 // Texture only needs to be 1x1.
6526 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6527 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6528 // multisample will fail if the color format of the source and destination
6529 // do not match. Here, we assume that the source is GL_RGBA, and make the
6530 // destination GL_RGBA. http://crbug.com/484203
6531 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6532 GL_UNSIGNED_BYTE
, NULL
);
6534 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6535 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6536 GL_TEXTURE_2D
, validation_texture_
, 0);
6538 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6541 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6542 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6543 GL_RENDERBUFFER
, renderbuffer
);
6545 // Cache current state and reset it to the values we require.
6546 GLboolean scissor_enabled
= false;
6547 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6548 if (scissor_enabled
)
6549 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6551 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6552 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6553 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6555 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6556 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6557 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6559 // Clear the buffer to the desired key color.
6560 glClear(GL_COLOR_BUFFER_BIT
);
6562 // Blit from the multisample buffer to a standard texture.
6563 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6564 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6566 BlitFramebufferHelper(
6567 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6569 // Read a pixel from the buffer.
6570 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6572 unsigned char pixel
[3] = {0, 0, 0};
6573 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6575 // Detach the renderbuffer.
6576 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6577 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6578 GL_RENDERBUFFER
, 0);
6580 // Restore cached state.
6581 if (scissor_enabled
)
6582 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6584 state_
.SetDeviceColorMask(
6585 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6586 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6587 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6588 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6590 // Return true if the pixel matched the desired key color.
6591 return (pixel
[0] == 0xFF &&
6596 void GLES2DecoderImpl::DoRenderbufferStorage(
6597 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6598 Renderbuffer
* renderbuffer
=
6599 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6600 if (!renderbuffer
) {
6602 GL_INVALID_OPERATION
,
6603 "glRenderbufferStorage", "no renderbuffer bound");
6607 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6608 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6610 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6614 uint32 estimated_size
= 0;
6615 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6616 width
, height
, 1, internalformat
, &estimated_size
)) {
6618 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6622 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6624 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6628 EnsureRenderbufferBound();
6629 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6630 glRenderbufferStorageEXT(
6632 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6636 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6637 if (error
== GL_NO_ERROR
) {
6638 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6639 // we could just mark those framebuffers as not complete.
6640 framebuffer_manager()->IncFramebufferStateChangeCount();
6641 renderbuffer_manager()->SetInfo(
6642 renderbuffer
, 1, internalformat
, width
, height
);
6646 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6647 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6648 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6649 Program
* program
= GetProgramInfoNotShader(
6650 program_id
, "glLinkProgram");
6655 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6656 if (program
->Link(shader_manager(),
6657 workarounds().count_all_in_varyings_packing
?
6658 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6659 shader_cache_callback_
)) {
6660 if (program
== state_
.current_program
.get()) {
6661 if (workarounds().use_current_program_after_successful_link
)
6662 glUseProgram(program
->service_id());
6663 if (workarounds().clear_uniforms_before_first_program_use
)
6664 program_manager()->ClearUniforms(program
);
6668 // LinkProgram can be very slow. Exit command processing to allow for
6669 // context preemption and GPU watchdog checks.
6670 ExitCommandProcessingEarly();
6673 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6680 GLenum upper_limit
= static_cast<GLenum
>(
6681 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6682 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6684 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6691 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6693 if (src
== GL_BACK
) {
6695 GL_INVALID_ENUM
, "glReadBuffer",
6696 "invalid src for a named framebuffer");
6699 framebuffer
->set_read_buffer(src
);
6701 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6703 GL_INVALID_ENUM
, "glReadBuffer",
6704 "invalid src for the default framebuffer");
6707 back_buffer_read_buffer_
= src
;
6708 if (GetBackbufferServiceId() && src
== GL_BACK
)
6709 src
= GL_COLOR_ATTACHMENT0
;
6714 void GLES2DecoderImpl::DoSamplerParameterfv(
6715 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6717 glSamplerParameterf(sampler
, pname
, params
[0]);
6720 void GLES2DecoderImpl::DoSamplerParameteriv(
6721 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6723 glSamplerParameteri(sampler
, pname
, params
[0]);
6726 void GLES2DecoderImpl::DoTexParameterf(
6727 GLenum target
, GLenum pname
, GLfloat param
) {
6728 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6731 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6735 texture_manager()->SetParameterf(
6736 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6739 void GLES2DecoderImpl::DoTexParameteri(
6740 GLenum target
, GLenum pname
, GLint param
) {
6741 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6744 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6748 texture_manager()->SetParameteri(
6749 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6752 void GLES2DecoderImpl::DoTexParameterfv(
6753 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6754 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6757 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6761 texture_manager()->SetParameterf(
6762 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6765 void GLES2DecoderImpl::DoTexParameteriv(
6766 GLenum target
, GLenum pname
, const GLint
* params
) {
6767 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6771 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6775 texture_manager()->SetParameteri(
6776 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6779 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6780 if (!state_
.bound_valuebuffer
.get()) {
6781 // There is no valuebuffer bound
6782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6783 "no valuebuffer in use");
6789 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6790 GLenum subscription
,
6791 const char* function_name
) {
6792 if (!CheckCurrentValuebuffer(function_name
)) {
6795 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6796 // The valuebuffer is not subscribed to the target
6797 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6798 "valuebuffer is not subscribed");
6804 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6805 GLenum subscription
,
6806 const char* function_name
) {
6807 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6810 GLint real_location
= -1;
6811 GLint array_index
= -1;
6812 const Program::UniformInfo
* info
=
6813 state_
.current_program
->GetUniformInfoByFakeLocation(
6814 location
, &real_location
, &array_index
);
6816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6819 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6820 info
->accepts_api_type
) == 0) {
6821 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6822 "wrong type for subscription");
6828 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6829 if (!state_
.current_program
.get()) {
6830 // The program does not exist.
6832 GL_INVALID_OPERATION
, function_name
, "no program in use");
6835 if (!state_
.current_program
->InUse()) {
6837 GL_INVALID_OPERATION
, function_name
, "program not linked");
6843 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6844 GLint location
, const char* function_name
) {
6845 if (!CheckCurrentProgram(function_name
)) {
6848 return location
!= -1;
6851 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6852 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6855 const Framebuffer::Attachment
* attachment
=
6856 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6860 DCHECK(state_
.current_program
.get());
6861 const Program::SamplerIndices
& sampler_indices
=
6862 state_
.current_program
->sampler_indices();
6863 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6864 const Program::UniformInfo
* uniform_info
=
6865 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6866 DCHECK(uniform_info
);
6867 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6869 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6870 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6871 if (texture_unit_index
>= state_
.texture_units
.size())
6873 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6874 TextureRef
* texture_ref
=
6875 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6876 if (attachment
->IsTexture(texture_ref
))
6883 bool GLES2DecoderImpl::CheckUniformForApiType(
6884 const Program::UniformInfo
* info
,
6885 const char* function_name
,
6886 Program::UniformApiType api_type
) {
6888 if ((api_type
& info
->accepts_api_type
) == 0) {
6889 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6890 "wrong uniform function for type");
6896 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6897 GLint fake_location
,
6898 const char* function_name
,
6899 Program::UniformApiType api_type
,
6900 GLint
* real_location
,
6905 DCHECK(real_location
);
6907 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6910 GLint array_index
= -1;
6911 const Program::UniformInfo
* info
=
6912 state_
.current_program
->GetUniformInfoByFakeLocation(
6913 fake_location
, real_location
, &array_index
);
6916 GL_INVALID_OPERATION
, function_name
, "unknown location");
6919 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6922 if (*count
> 1 && !info
->is_array
) {
6924 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6927 *count
= std::min(info
->size
- array_index
, *count
);
6935 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6938 GLint real_location
= -1;
6939 if (!PrepForSetUniformByLocation(fake_location
,
6941 Program::kUniform1i
,
6947 if (!state_
.current_program
->SetSamplers(
6948 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6950 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6953 glUniform1i(real_location
, v0
);
6956 void GLES2DecoderImpl::DoUniform1iv(
6957 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6959 GLint real_location
= -1;
6960 if (!PrepForSetUniformByLocation(fake_location
,
6962 Program::kUniform1i
,
6968 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6969 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6970 if (!state_
.current_program
->SetSamplers(
6971 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6973 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6977 glUniform1iv(real_location
, count
, value
);
6980 void GLES2DecoderImpl::DoUniform1uiv(
6981 GLint fake_location
, GLsizei count
, const GLuint
*value
) {
6983 GLint real_location
= -1;
6984 if (!PrepForSetUniformByLocation(fake_location
,
6986 Program::kUniform1ui
,
6992 glUniform1uiv(real_location
, count
, value
);
6995 void GLES2DecoderImpl::DoUniform1fv(
6996 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
6998 GLint real_location
= -1;
6999 if (!PrepForSetUniformByLocation(fake_location
,
7001 Program::kUniform1f
,
7007 if (type
== GL_BOOL
) {
7008 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
7009 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7010 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7012 DoUniform1iv(real_location
, count
, temp
.get());
7014 glUniform1fv(real_location
, count
, value
);
7018 void GLES2DecoderImpl::DoUniform2fv(
7019 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7021 GLint real_location
= -1;
7022 if (!PrepForSetUniformByLocation(fake_location
,
7024 Program::kUniform2f
,
7030 if (type
== GL_BOOL_VEC2
) {
7031 GLsizei num_values
= count
* 2;
7032 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7033 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7034 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7036 glUniform2iv(real_location
, count
, temp
.get());
7038 glUniform2fv(real_location
, count
, value
);
7042 void GLES2DecoderImpl::DoUniform3fv(
7043 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7045 GLint real_location
= -1;
7046 if (!PrepForSetUniformByLocation(fake_location
,
7048 Program::kUniform3f
,
7054 if (type
== GL_BOOL_VEC3
) {
7055 GLsizei num_values
= count
* 3;
7056 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7057 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7058 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7060 glUniform3iv(real_location
, count
, temp
.get());
7062 glUniform3fv(real_location
, count
, value
);
7066 void GLES2DecoderImpl::DoUniform4fv(
7067 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7069 GLint real_location
= -1;
7070 if (!PrepForSetUniformByLocation(fake_location
,
7072 Program::kUniform4f
,
7078 if (type
== GL_BOOL_VEC4
) {
7079 GLsizei num_values
= count
* 4;
7080 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7081 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7082 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7084 glUniform4iv(real_location
, count
, temp
.get());
7086 glUniform4fv(real_location
, count
, value
);
7090 void GLES2DecoderImpl::DoUniform2iv(
7091 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7093 GLint real_location
= -1;
7094 if (!PrepForSetUniformByLocation(fake_location
,
7096 Program::kUniform2i
,
7102 glUniform2iv(real_location
, count
, value
);
7105 void GLES2DecoderImpl::DoUniform2uiv(
7106 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7108 GLint real_location
= -1;
7109 if (!PrepForSetUniformByLocation(fake_location
,
7111 Program::kUniform2ui
,
7117 glUniform2uiv(real_location
, count
, value
);
7120 void GLES2DecoderImpl::DoUniform3iv(
7121 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7123 GLint real_location
= -1;
7124 if (!PrepForSetUniformByLocation(fake_location
,
7126 Program::kUniform3i
,
7132 glUniform3iv(real_location
, count
, value
);
7135 void GLES2DecoderImpl::DoUniform3uiv(
7136 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7138 GLint real_location
= -1;
7139 if (!PrepForSetUniformByLocation(fake_location
,
7141 Program::kUniform3ui
,
7147 glUniform3uiv(real_location
, count
, value
);
7150 void GLES2DecoderImpl::DoUniform4iv(
7151 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7153 GLint real_location
= -1;
7154 if (!PrepForSetUniformByLocation(fake_location
,
7156 Program::kUniform4i
,
7162 glUniform4iv(real_location
, count
, value
);
7165 void GLES2DecoderImpl::DoUniform4uiv(
7166 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7168 GLint real_location
= -1;
7169 if (!PrepForSetUniformByLocation(fake_location
,
7171 Program::kUniform4ui
,
7177 glUniform4uiv(real_location
, count
, value
);
7180 void GLES2DecoderImpl::DoUniformMatrix2fv(
7181 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7182 const GLfloat
* value
) {
7184 GLint real_location
= -1;
7185 if (!PrepForSetUniformByLocation(fake_location
,
7186 "glUniformMatrix2fv",
7187 Program::kUniformMatrix2f
,
7193 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
7196 void GLES2DecoderImpl::DoUniformMatrix3fv(
7197 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7198 const GLfloat
* value
) {
7200 GLint real_location
= -1;
7201 if (!PrepForSetUniformByLocation(fake_location
,
7202 "glUniformMatrix3fv",
7203 Program::kUniformMatrix3f
,
7209 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
7212 void GLES2DecoderImpl::DoUniformMatrix4fv(
7213 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7214 const GLfloat
* value
) {
7216 GLint real_location
= -1;
7217 if (!PrepForSetUniformByLocation(fake_location
,
7218 "glUniformMatrix4fv",
7219 Program::kUniformMatrix4f
,
7225 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
7228 void GLES2DecoderImpl::DoUniformMatrix2x3fv(
7229 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7230 const GLfloat
* value
) {
7232 GLint real_location
= -1;
7233 if (!PrepForSetUniformByLocation(fake_location
,
7234 "glUniformMatrix2x3fv",
7235 Program::kUniformMatrix2x3f
,
7241 glUniformMatrix2x3fv(real_location
, count
, transpose
, value
);
7244 void GLES2DecoderImpl::DoUniformMatrix2x4fv(
7245 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7246 const GLfloat
* value
) {
7248 GLint real_location
= -1;
7249 if (!PrepForSetUniformByLocation(fake_location
,
7250 "glUniformMatrix2x4fv",
7251 Program::kUniformMatrix2x4f
,
7257 glUniformMatrix2x4fv(real_location
, count
, transpose
, value
);
7260 void GLES2DecoderImpl::DoUniformMatrix3x2fv(
7261 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7262 const GLfloat
* value
) {
7264 GLint real_location
= -1;
7265 if (!PrepForSetUniformByLocation(fake_location
,
7266 "glUniformMatrix3x2fv",
7267 Program::kUniformMatrix3x2f
,
7273 glUniformMatrix3x2fv(real_location
, count
, transpose
, value
);
7276 void GLES2DecoderImpl::DoUniformMatrix3x4fv(
7277 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7278 const GLfloat
* value
) {
7280 GLint real_location
= -1;
7281 if (!PrepForSetUniformByLocation(fake_location
,
7282 "glUniformMatrix3x4fv",
7283 Program::kUniformMatrix3x4f
,
7289 glUniformMatrix3x4fv(real_location
, count
, transpose
, value
);
7292 void GLES2DecoderImpl::DoUniformMatrix4x2fv(
7293 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7294 const GLfloat
* value
) {
7296 GLint real_location
= -1;
7297 if (!PrepForSetUniformByLocation(fake_location
,
7298 "glUniformMatrix4x2fv",
7299 Program::kUniformMatrix4x2f
,
7305 glUniformMatrix4x2fv(real_location
, count
, transpose
, value
);
7308 void GLES2DecoderImpl::DoUniformMatrix4x3fv(
7309 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7310 const GLfloat
* value
) {
7312 GLint real_location
= -1;
7313 if (!PrepForSetUniformByLocation(fake_location
,
7314 "glUniformMatrix4x3fv",
7315 Program::kUniformMatrix4x3f
,
7321 glUniformMatrix4x3fv(real_location
, count
, transpose
, value
);
7324 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
7325 GLuint service_id
= 0;
7326 Program
* program
= NULL
;
7328 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
7332 if (!program
->IsValid()) {
7333 // Program was not linked successfully. (ie, glLinkProgram)
7335 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
7338 service_id
= program
->service_id();
7340 if (state_
.current_program
.get()) {
7341 program_manager()->UnuseProgram(shader_manager(),
7342 state_
.current_program
.get());
7344 state_
.current_program
= program
;
7345 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
7346 glUseProgram(service_id
);
7347 if (state_
.current_program
.get()) {
7348 program_manager()->UseProgram(state_
.current_program
.get());
7349 if (workarounds().clear_uniforms_before_first_program_use
)
7350 program_manager()->ClearUniforms(program
);
7354 void GLES2DecoderImpl::RenderWarning(
7355 const char* filename
, int line
, const std::string
& msg
) {
7356 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
7359 void GLES2DecoderImpl::PerformanceWarning(
7360 const char* filename
, int line
, const std::string
& msg
) {
7361 logger_
.LogMessage(filename
, line
,
7362 std::string("PERFORMANCE WARNING: ") + msg
);
7365 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
7366 Texture
* texture
, GLenum textarget
) {
7367 // Image is already in use if texture is attached to a framebuffer.
7368 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
7369 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7371 ScopedGLErrorSuppressor
suppressor(
7372 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
7374 glBindTexture(textarget
, texture
->service_id());
7375 image
->WillUseTexImage();
7376 RestoreCurrentTextureBindings(&state_
, textarget
);
7381 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
7382 Texture
* texture
, GLenum textarget
) {
7383 // Image is still in use if texture is attached to a framebuffer.
7384 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
7385 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7387 ScopedGLErrorSuppressor
suppressor(
7388 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
7390 glBindTexture(textarget
, texture
->service_id());
7391 image
->DidUseTexImage();
7392 RestoreCurrentTextureBindings(&state_
, textarget
);
7397 bool GLES2DecoderImpl::PrepareTexturesForRender() {
7398 DCHECK(state_
.current_program
.get());
7399 if (!texture_manager()->HaveUnrenderableTextures() &&
7400 !texture_manager()->HaveImages()) {
7403 bool textures_set
= false;
7404 const Program::SamplerIndices
& sampler_indices
=
7405 state_
.current_program
->sampler_indices();
7406 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7407 const Program::UniformInfo
* uniform_info
=
7408 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7409 DCHECK(uniform_info
);
7410 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7411 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7412 if (texture_unit_index
< state_
.texture_units
.size()) {
7413 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7414 TextureRef
* texture_ref
=
7415 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7416 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
7417 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7418 textures_set
= true;
7419 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7422 texture_manager()->black_texture_id(uniform_info
->type
));
7424 LOCAL_RENDER_WARNING(
7425 std::string("there is no texture bound to the unit ") +
7426 base::UintToString(texture_unit_index
));
7428 LOCAL_RENDER_WARNING(
7429 std::string("texture bound to texture unit ") +
7430 base::UintToString(texture_unit_index
) +
7431 " is not renderable. It maybe non-power-of-2 and have"
7432 " incompatible texture filtering.");
7437 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
7438 Texture
* texture
= texture_ref
->texture();
7439 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7440 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7441 ScopedGLErrorSuppressor
suppressor(
7442 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
7443 textures_set
= true;
7444 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7445 image
->WillUseTexImage();
7450 // else: should this be an error?
7453 return !textures_set
;
7456 void GLES2DecoderImpl::RestoreStateForTextures() {
7457 DCHECK(state_
.current_program
.get());
7458 const Program::SamplerIndices
& sampler_indices
=
7459 state_
.current_program
->sampler_indices();
7460 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7461 const Program::UniformInfo
* uniform_info
=
7462 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7463 DCHECK(uniform_info
);
7464 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7465 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7466 if (texture_unit_index
< state_
.texture_units
.size()) {
7467 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7468 TextureRef
* texture_ref
=
7469 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7470 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7471 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7472 // Get the texture_ref info that was previously bound here.
7473 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
7474 ? texture_unit
.bound_texture_2d
.get()
7475 : texture_unit
.bound_texture_cube_map
.get();
7476 glBindTexture(texture_unit
.bind_target
,
7477 texture_ref
? texture_ref
->service_id() : 0);
7481 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7482 Texture
* texture
= texture_ref
->texture();
7483 gfx::GLImage
* image
=
7484 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7485 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7486 ScopedGLErrorSuppressor
suppressor(
7487 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7488 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7489 image
->DidUseTexImage();
7496 // Set the active texture back to whatever the user had it as.
7497 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7500 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7501 // Only check if there are some uncleared textures.
7502 if (!texture_manager()->HaveUnsafeTextures()) {
7506 // 1: Check all textures we are about to render with.
7507 if (state_
.current_program
.get()) {
7508 const Program::SamplerIndices
& sampler_indices
=
7509 state_
.current_program
->sampler_indices();
7510 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7511 const Program::UniformInfo
* uniform_info
=
7512 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7513 DCHECK(uniform_info
);
7514 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7515 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7516 if (texture_unit_index
< state_
.texture_units
.size()) {
7517 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7518 TextureRef
* texture_ref
=
7519 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7520 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7521 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7532 bool GLES2DecoderImpl::IsDrawValid(
7533 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7534 GLsizei primcount
) {
7535 DCHECK(instanced
|| primcount
== 1);
7537 // NOTE: We specifically do not check current_program->IsValid() because
7538 // it could never be invalid since glUseProgram would have failed. While
7539 // glLinkProgram could later mark the program as invalid the previous
7540 // valid program will still function if it is still the current program.
7541 if (!state_
.current_program
.get()) {
7542 // The program does not exist.
7543 // But GL says no ERROR.
7544 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7548 if (CheckDrawingFeedbackLoops()) {
7550 GL_INVALID_OPERATION
, function_name
,
7551 "Source and destination textures of the draw are the same.");
7555 return state_
.vertex_attrib_manager
7556 ->ValidateBindings(function_name
,
7558 feature_info_
.get(),
7559 state_
.current_program
.get(),
7560 max_vertex_accessed
,
7565 bool GLES2DecoderImpl::SimulateAttrib0(
7566 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7570 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7573 const VertexAttrib
* attrib
=
7574 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7575 // If it's enabled or it's not used then we don't need to do anything.
7576 bool attrib_0_used
=
7577 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7578 if (attrib
->enabled() && attrib_0_used
) {
7582 // Make a buffer with a single repeated vec4 value enough to
7583 // simulate the constant value that is supposed to be here.
7584 // This is required to emulate GLES2 on GL.
7585 GLuint num_vertices
= max_vertex_accessed
+ 1;
7586 uint32 size_needed
= 0;
7588 if (num_vertices
== 0 ||
7589 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7590 size_needed
> 0x7FFFFFFFU
) {
7591 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7595 LOCAL_PERFORMANCE_WARNING(
7596 "Attribute 0 is disabled. This has signficant performance penalty");
7598 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7599 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7601 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7603 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7604 GLenum error
= glGetError();
7605 if (error
!= GL_NO_ERROR
) {
7607 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7612 const Vec4
& value
= state_
.attrib_values
[0];
7615 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7616 // TODO(zmo): This is not 100% correct because we might lose data when
7617 // casting to float type, but it is a corner case and once we migrate to
7618 // core profiles on desktop GL, it is no longer relevant.
7619 Vec4f
fvalue(value
);
7620 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7621 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7622 attrib_0_buffer_matches_value_
= true;
7623 attrib_0_value_
= value
;
7624 attrib_0_size_
= size_needed
;
7627 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7629 if (attrib
->divisor())
7630 glVertexAttribDivisorANGLE(0, 0);
7636 void GLES2DecoderImpl::RestoreStateForAttrib(
7637 GLuint attrib_index
, bool restore_array_binding
) {
7638 const VertexAttrib
* attrib
=
7639 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7640 if (restore_array_binding
) {
7641 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7642 Buffer
* buffer
= attrib
->buffer();
7643 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7644 glVertexAttribPointer(
7645 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7646 attrib
->gl_stride(), ptr
);
7648 if (attrib
->divisor())
7649 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7651 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7652 state_
.bound_array_buffer
->service_id() : 0);
7654 // Never touch vertex attribute 0's state (in particular, never
7655 // disable it) when running on desktop GL because it will never be
7657 if (attrib_index
!= 0 ||
7658 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7659 if (attrib
->enabled()) {
7660 glEnableVertexAttribArray(attrib_index
);
7662 glDisableVertexAttribArray(attrib_index
);
7667 bool GLES2DecoderImpl::SimulateFixedAttribs(
7668 const char* function_name
,
7669 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7672 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7675 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7679 LOCAL_PERFORMANCE_WARNING(
7680 "GL_FIXED attributes have a signficant performance penalty");
7682 // NOTE: we could be smart and try to check if a buffer is used
7683 // twice in 2 different attribs, find the overlapping parts and therefore
7684 // duplicate the minimum amount of data but this whole code path is not meant
7685 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7686 // tests so we just add to the buffer attrib used.
7688 GLuint elements_needed
= 0;
7689 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7690 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7691 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7692 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7693 const VertexAttrib
* attrib
= *it
;
7694 const Program::VertexAttrib
* attrib_info
=
7695 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7696 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7697 max_vertex_accessed
);
7698 GLuint num_vertices
= max_accessed
+ 1;
7699 if (num_vertices
== 0) {
7701 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7705 attrib
->CanAccess(max_accessed
) &&
7706 attrib
->type() == GL_FIXED
) {
7707 uint32 elements_used
= 0;
7708 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7709 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7711 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7717 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7718 uint32 size_needed
= 0;
7719 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7720 size_needed
> 0x7FFFFFFFU
) {
7722 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7726 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7728 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7729 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7730 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7731 GLenum error
= glGetError();
7732 if (error
!= GL_NO_ERROR
) {
7734 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7739 // Copy the elements and convert to float
7740 GLintptr offset
= 0;
7741 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7742 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7743 const VertexAttrib
* attrib
= *it
;
7744 const Program::VertexAttrib
* attrib_info
=
7745 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7746 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7747 max_vertex_accessed
);
7748 GLuint num_vertices
= max_accessed
+ 1;
7749 if (num_vertices
== 0) {
7751 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7755 attrib
->CanAccess(max_accessed
) &&
7756 attrib
->type() == GL_FIXED
) {
7757 int num_elements
= attrib
->size() * num_vertices
;
7758 const int src_size
= num_elements
* sizeof(int32
);
7759 const int dst_size
= num_elements
* sizeof(float);
7760 scoped_ptr
<float[]> data(new float[num_elements
]);
7761 const int32
* src
= reinterpret_cast<const int32
*>(
7762 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7763 const int32
* end
= src
+ num_elements
;
7764 float* dst
= data
.get();
7765 while (src
!= end
) {
7766 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7768 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7769 glVertexAttribPointer(
7770 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7771 reinterpret_cast<GLvoid
*>(offset
));
7779 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7780 // There's no need to call glVertexAttribPointer because we shadow all the
7781 // settings and passing GL_FIXED to it will not work.
7784 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7788 error::Error
GLES2DecoderImpl::DoDrawArrays(
7789 const char* function_name
,
7794 GLsizei primcount
) {
7795 error::Error error
= WillAccessBoundFramebufferForDraw();
7796 if (error
!= error::kNoError
)
7798 if (!validators_
->draw_mode
.IsValid(mode
)) {
7799 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7800 return error::kNoError
;
7803 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7804 return error::kNoError
;
7806 if (primcount
< 0) {
7807 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7808 return error::kNoError
;
7810 if (!CheckBoundFramebuffersValid(function_name
)) {
7811 return error::kNoError
;
7813 // We have to check this here because the prototype for glDrawArrays
7814 // is GLint not GLsizei.
7816 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7817 return error::kNoError
;
7820 if (count
== 0 || primcount
== 0) {
7821 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7822 return error::kNoError
;
7825 GLuint max_vertex_accessed
= first
+ count
- 1;
7826 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7827 if (!ClearUnclearedTextures()) {
7828 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7829 return error::kNoError
;
7831 bool simulated_attrib_0
= false;
7832 if (!SimulateAttrib0(
7833 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7834 return error::kNoError
;
7836 bool simulated_fixed_attribs
= false;
7837 if (SimulateFixedAttribs(
7838 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7840 bool textures_set
= !PrepareTexturesForRender();
7842 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7844 glDrawArrays(mode
, first
, count
);
7846 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7849 RestoreStateForTextures();
7851 if (simulated_fixed_attribs
) {
7852 RestoreStateForSimulatedFixedAttribs();
7855 if (simulated_attrib_0
) {
7856 // We don't have to restore attrib 0 generic data at the end of this
7857 // function even if it is simulated. This is because we will simulate
7858 // it in each draw call, and attrib 0 generic data queries use cached
7859 // values instead of passing down to the underlying driver.
7860 RestoreStateForAttrib(0, false);
7863 return error::kNoError
;
7866 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7867 const void* cmd_data
) {
7868 // TODO(zmo): crbug.com/481184
7869 // On Desktop GL with versions lower than 4.3, we need to emulate
7870 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7871 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7872 return DoDrawArrays("glDrawArrays",
7874 static_cast<GLenum
>(c
.mode
),
7875 static_cast<GLint
>(c
.first
),
7876 static_cast<GLsizei
>(c
.count
),
7880 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7881 uint32 immediate_data_size
,
7882 const void* cmd_data
) {
7883 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7884 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7885 if (!features().angle_instanced_arrays
) {
7887 GL_INVALID_OPERATION
,
7888 "glDrawArraysInstancedANGLE", "function not available");
7889 return error::kNoError
;
7891 return DoDrawArrays("glDrawArraysIntancedANGLE",
7893 static_cast<GLenum
>(c
.mode
),
7894 static_cast<GLint
>(c
.first
),
7895 static_cast<GLsizei
>(c
.count
),
7896 static_cast<GLsizei
>(c
.primcount
));
7899 error::Error
GLES2DecoderImpl::DoDrawElements(
7900 const char* function_name
,
7906 GLsizei primcount
) {
7907 error::Error error
= WillAccessBoundFramebufferForDraw();
7908 if (error
!= error::kNoError
)
7910 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7912 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7913 return error::kNoError
;
7917 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7918 return error::kNoError
;
7921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7922 return error::kNoError
;
7924 if (!validators_
->draw_mode
.IsValid(mode
)) {
7925 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7926 return error::kNoError
;
7928 if (!validators_
->index_type
.IsValid(type
)) {
7929 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7930 return error::kNoError
;
7932 if (primcount
< 0) {
7933 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7934 return error::kNoError
;
7937 if (!CheckBoundFramebuffersValid(function_name
)) {
7938 return error::kNoError
;
7941 if (count
== 0 || primcount
== 0) {
7942 return error::kNoError
;
7945 GLuint max_vertex_accessed
;
7946 Buffer
* element_array_buffer
=
7947 state_
.vertex_attrib_manager
->element_array_buffer();
7949 if (!element_array_buffer
->GetMaxValueForRange(
7950 offset
, count
, type
, &max_vertex_accessed
)) {
7952 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7953 return error::kNoError
;
7956 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7957 if (!ClearUnclearedTextures()) {
7958 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7959 return error::kNoError
;
7961 bool simulated_attrib_0
= false;
7962 if (!SimulateAttrib0(
7963 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7964 return error::kNoError
;
7966 bool simulated_fixed_attribs
= false;
7967 if (SimulateFixedAttribs(
7968 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7970 bool textures_set
= !PrepareTexturesForRender();
7972 // TODO(gman): Refactor to hide these details in BufferManager or
7973 // VertexAttribManager.
7974 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7975 bool used_client_side_array
= false;
7976 if (element_array_buffer
->IsClientSideArray()) {
7977 used_client_side_array
= true;
7978 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7979 indices
= element_array_buffer
->GetRange(offset
, 0);
7982 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7984 glDrawElements(mode
, count
, type
, indices
);
7986 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7989 if (used_client_side_array
) {
7990 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7991 element_array_buffer
->service_id());
7995 RestoreStateForTextures();
7997 if (simulated_fixed_attribs
) {
7998 RestoreStateForSimulatedFixedAttribs();
8001 if (simulated_attrib_0
) {
8002 // We don't have to restore attrib 0 generic data at the end of this
8003 // function even if it is simulated. This is because we will simulate
8004 // it in each draw call, and attrib 0 generic data queries use cached
8005 // values instead of passing down to the underlying driver.
8006 RestoreStateForAttrib(0, false);
8009 return error::kNoError
;
8012 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
8013 const void* cmd_data
) {
8014 // TODO(zmo): crbug.com/481184
8015 // On Desktop GL with versions lower than 4.3, we need to emulate
8016 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
8017 const gles2::cmds::DrawElements
& c
=
8018 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
8019 return DoDrawElements("glDrawElements",
8021 static_cast<GLenum
>(c
.mode
),
8022 static_cast<GLsizei
>(c
.count
),
8023 static_cast<GLenum
>(c
.type
),
8024 static_cast<int32
>(c
.index_offset
),
8028 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
8029 uint32 immediate_data_size
,
8030 const void* cmd_data
) {
8031 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
8032 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
8033 if (!features().angle_instanced_arrays
) {
8035 GL_INVALID_OPERATION
,
8036 "glDrawElementsInstancedANGLE", "function not available");
8037 return error::kNoError
;
8039 return DoDrawElements("glDrawElementsInstancedANGLE",
8041 static_cast<GLenum
>(c
.mode
),
8042 static_cast<GLsizei
>(c
.count
),
8043 static_cast<GLenum
>(c
.type
),
8044 static_cast<int32
>(c
.index_offset
),
8045 static_cast<GLsizei
>(c
.primcount
));
8048 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
8049 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
8050 GLuint max_vertex_accessed
= 0;
8051 Buffer
* buffer
= GetBuffer(buffer_id
);
8053 // TODO(gman): Should this be a GL error or a command buffer error?
8055 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
8057 if (!buffer
->GetMaxValueForRange(
8058 offset
, count
, type
, &max_vertex_accessed
)) {
8059 // TODO(gman): Should this be a GL error or a command buffer error?
8061 GL_INVALID_OPERATION
,
8062 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
8065 return max_vertex_accessed
;
8068 void GLES2DecoderImpl::DoShaderSource(
8069 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
8071 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
8072 if (length
&& length
[ii
] > 0)
8073 str
.append(data
[ii
], length
[ii
]);
8075 str
.append(data
[ii
]);
8077 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
8081 // Note: We don't actually call glShaderSource here. We wait until
8082 // we actually compile the shader.
8083 shader
->set_source(str
);
8086 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
8087 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
8088 GLenum buffer_mode
) {
8089 Program
* program
= GetProgramInfoNotShader(
8090 client_program_id
, "glTransformFeedbackVaryings");
8094 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
8097 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
8098 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
8099 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
8104 scoped_refptr
<ShaderTranslatorInterface
> translator
;
8105 if (!feature_info_
->disable_shader_translator()) {
8106 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
8107 vertex_translator_
: fragment_translator_
;
8110 const Shader::TranslatedShaderSourceType source_type
=
8111 feature_info_
->feature_flags().angle_translated_shader_source
?
8112 Shader::kANGLE
: Shader::kGL
;
8113 shader
->RequestCompile(translator
, source_type
);
8116 void GLES2DecoderImpl::DoGetShaderiv(
8117 GLuint shader_id
, GLenum pname
, GLint
* params
) {
8118 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
8123 // Compile now for statuses that require it.
8125 case GL_COMPILE_STATUS
:
8126 case GL_INFO_LOG_LENGTH
:
8127 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
8128 shader
->DoCompile();
8136 case GL_SHADER_SOURCE_LENGTH
:
8137 *params
= shader
->source().size();
8141 case GL_COMPILE_STATUS
:
8142 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
8144 case GL_INFO_LOG_LENGTH
:
8145 *params
= shader
->log_info().size();
8149 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
8150 *params
= shader
->translated_source().size();
8157 glGetShaderiv(shader
->service_id(), pname
, params
);
8160 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
8161 const void* cmd_data
) {
8162 const gles2::cmds::GetShaderSource
& c
=
8163 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
8164 GLuint shader_id
= c
.shader
;
8165 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8166 Bucket
* bucket
= CreateBucket(bucket_id
);
8167 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
8168 if (!shader
|| shader
->source().empty()) {
8170 return error::kNoError
;
8172 bucket
->SetFromString(shader
->source().c_str());
8173 return error::kNoError
;
8176 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
8177 uint32 immediate_data_size
,
8178 const void* cmd_data
) {
8179 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
8180 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
8182 GLuint shader_id
= c
.shader
;
8183 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8184 Bucket
* bucket
= CreateBucket(bucket_id
);
8185 Shader
* shader
= GetShaderInfoNotProgram(
8186 shader_id
, "glGetTranslatedShaderSourceANGLE");
8189 return error::kNoError
;
8192 // Make sure translator has been utilized in compile.
8193 shader
->DoCompile();
8195 bucket
->SetFromString(shader
->translated_source().c_str());
8196 return error::kNoError
;
8199 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
8200 uint32 immediate_data_size
,
8201 const void* cmd_data
) {
8202 const gles2::cmds::GetProgramInfoLog
& c
=
8203 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
8204 GLuint program_id
= c
.program
;
8205 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8206 Bucket
* bucket
= CreateBucket(bucket_id
);
8207 Program
* program
= GetProgramInfoNotShader(
8208 program_id
, "glGetProgramInfoLog");
8209 if (!program
|| !program
->log_info()) {
8210 bucket
->SetFromString("");
8211 return error::kNoError
;
8213 bucket
->SetFromString(program
->log_info()->c_str());
8214 return error::kNoError
;
8217 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
8218 uint32 immediate_data_size
,
8219 const void* cmd_data
) {
8220 const gles2::cmds::GetShaderInfoLog
& c
=
8221 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
8222 GLuint shader_id
= c
.shader
;
8223 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8224 Bucket
* bucket
= CreateBucket(bucket_id
);
8225 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
8227 bucket
->SetFromString("");
8228 return error::kNoError
;
8231 // Shader must be compiled in order to get the info log.
8232 shader
->DoCompile();
8234 bucket
->SetFromString(shader
->log_info().c_str());
8235 return error::kNoError
;
8238 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
8239 return state_
.GetEnabled(cap
);
8242 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
8243 const Buffer
* buffer
= GetBuffer(client_id
);
8244 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
8247 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
8248 const Framebuffer
* framebuffer
=
8249 GetFramebuffer(client_id
);
8250 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
8253 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
8254 // IsProgram is true for programs as soon as they are created, until they are
8255 // deleted and no longer in use.
8256 const Program
* program
= GetProgram(client_id
);
8257 return program
!= NULL
&& !program
->IsDeleted();
8260 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
8261 const Renderbuffer
* renderbuffer
=
8262 GetRenderbuffer(client_id
);
8263 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
8266 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
8267 // IsShader is true for shaders as soon as they are created, until they
8268 // are deleted and not attached to any programs.
8269 const Shader
* shader
= GetShader(client_id
);
8270 return shader
!= NULL
&& !shader
->IsDeleted();
8273 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
8274 const TextureRef
* texture_ref
= GetTexture(client_id
);
8275 return texture_ref
&& texture_ref
->texture()->IsValid();
8278 void GLES2DecoderImpl::DoAttachShader(
8279 GLuint program_client_id
, GLint shader_client_id
) {
8280 Program
* program
= GetProgramInfoNotShader(
8281 program_client_id
, "glAttachShader");
8285 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
8289 if (!program
->AttachShader(shader_manager(), shader
)) {
8291 GL_INVALID_OPERATION
,
8293 "can not attach more than one shader of the same type.");
8296 glAttachShader(program
->service_id(), shader
->service_id());
8299 void GLES2DecoderImpl::DoDetachShader(
8300 GLuint program_client_id
, GLint shader_client_id
) {
8301 Program
* program
= GetProgramInfoNotShader(
8302 program_client_id
, "glDetachShader");
8306 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
8310 if (!program
->DetachShader(shader_manager(), shader
)) {
8312 GL_INVALID_OPERATION
,
8313 "glDetachShader", "shader not attached to program");
8316 glDetachShader(program
->service_id(), shader
->service_id());
8319 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
8320 Program
* program
= GetProgramInfoNotShader(
8321 program_client_id
, "glValidateProgram");
8325 program
->Validate();
8328 void GLES2DecoderImpl::GetVertexAttribHelper(
8329 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
8331 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
8333 Buffer
* buffer
= attrib
->buffer();
8334 if (buffer
&& !buffer
->IsDeleted()) {
8336 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
8337 *params
= client_id
;
8341 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
8342 *params
= attrib
->enabled();
8344 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
8345 *params
= attrib
->size();
8347 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
8348 *params
= attrib
->gl_stride();
8350 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
8351 *params
= attrib
->type();
8353 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
8354 *params
= attrib
->normalized();
8356 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
8357 *params
= attrib
->divisor();
8359 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
8360 *params
= attrib
->integer();
8368 void GLES2DecoderImpl::DoGetTexParameterfv(
8369 GLenum target
, GLenum pname
, GLfloat
* params
) {
8370 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
8371 glGetTexParameterfv(target
, pname
, params
);
8374 void GLES2DecoderImpl::DoGetTexParameteriv(
8375 GLenum target
, GLenum pname
, GLint
* params
) {
8376 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
8377 glGetTexParameteriv(target
, pname
, params
);
8380 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
8381 GLenum target
, GLenum pname
) {
8382 if (!workarounds().init_texture_max_anisotropy
)
8384 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
8385 !validators_
->texture_parameter
.IsValid(pname
)) {
8389 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8393 GL_INVALID_OPERATION
,
8394 "glGetTexParamter{fi}v", "unknown texture for target");
8397 Texture
* texture
= texture_ref
->texture();
8398 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
8401 template <typename T
>
8402 void GLES2DecoderImpl::DoGetVertexAttribImpl(
8403 GLuint index
, GLenum pname
, T
* params
) {
8404 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
8407 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
8411 case GL_CURRENT_VERTEX_ATTRIB
:
8412 state_
.attrib_values
[index
].GetValues(params
);
8416 GetVertexAttribHelper(attrib
, pname
, &value
);
8417 *params
= static_cast<T
>(value
);
8423 void GLES2DecoderImpl::DoGetVertexAttribfv(
8424 GLuint index
, GLenum pname
, GLfloat
* params
) {
8425 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
8428 void GLES2DecoderImpl::DoGetVertexAttribiv(
8429 GLuint index
, GLenum pname
, GLint
* params
) {
8430 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
8433 void GLES2DecoderImpl::DoGetVertexAttribIiv(
8434 GLuint index
, GLenum pname
, GLint
* params
) {
8435 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
8438 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
8439 GLuint index
, GLenum pname
, GLuint
* params
) {
8440 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
8443 template <typename T
>
8444 bool GLES2DecoderImpl::SetVertexAttribValue(
8445 const char* function_name
, GLuint index
, const T
* value
) {
8446 if (index
>= state_
.attrib_values
.size()) {
8447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
8450 state_
.attrib_values
[index
].SetValues(value
);
8454 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
8455 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
8456 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
8457 glVertexAttrib1f(index
, v0
);
8461 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
8462 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
8463 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
8464 glVertexAttrib2f(index
, v0
, v1
);
8468 void GLES2DecoderImpl::DoVertexAttrib3f(
8469 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
8470 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
8471 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
8472 glVertexAttrib3f(index
, v0
, v1
, v2
);
8476 void GLES2DecoderImpl::DoVertexAttrib4f(
8477 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
8478 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8479 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8480 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8484 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8485 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8486 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8487 glVertexAttrib1fv(index
, v
);
8491 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8492 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8493 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8494 glVertexAttrib2fv(index
, v
);
8498 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8499 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8500 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8501 glVertexAttrib3fv(index
, v
);
8505 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8506 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8507 glVertexAttrib4fv(index
, v
);
8511 void GLES2DecoderImpl::DoVertexAttribI4i(
8512 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8513 GLint v
[4] = { v0
, v1
, v2
, v3
};
8514 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8515 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8519 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8520 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8521 glVertexAttribI4iv(index
, v
);
8525 void GLES2DecoderImpl::DoVertexAttribI4ui(
8526 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8527 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8528 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8529 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8533 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8534 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8535 glVertexAttribI4uiv(index
, v
);
8539 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8540 uint32 immediate_data_size
,
8541 const void* cmd_data
) {
8542 if (!unsafe_es3_apis_enabled())
8543 return error::kUnknownCommand
;
8544 const gles2::cmds::VertexAttribIPointer
& c
=
8545 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8547 if (!state_
.bound_array_buffer
.get() ||
8548 state_
.bound_array_buffer
->IsDeleted()) {
8549 if (state_
.vertex_attrib_manager
.get() ==
8550 state_
.default_vertex_attrib_manager
.get()) {
8552 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8553 return error::kNoError
;
8554 } else if (c
.offset
!= 0) {
8557 "glVertexAttribIPointer", "client side arrays are not allowed");
8558 return error::kNoError
;
8562 GLuint indx
= c
.indx
;
8563 GLint size
= c
.size
;
8564 GLenum type
= c
.type
;
8565 GLsizei stride
= c
.stride
;
8566 GLsizei offset
= c
.offset
;
8567 const void* ptr
= reinterpret_cast<const void*>(offset
);
8568 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8569 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8570 return error::kNoError
;
8572 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8574 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8575 return error::kNoError
;
8577 if (indx
>= group_
->max_vertex_attribs()) {
8579 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8580 return error::kNoError
;
8584 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8585 return error::kNoError
;
8589 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8590 return error::kNoError
;
8594 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8595 return error::kNoError
;
8597 GLsizei component_size
=
8598 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8599 // component_size must be a power of two to use & as optimized modulo.
8600 DCHECK(GLES2Util::IsPOT(component_size
));
8601 if (offset
& (component_size
- 1)) {
8603 GL_INVALID_OPERATION
,
8604 "glVertexAttribIPointer", "offset not valid for type");
8605 return error::kNoError
;
8607 if (stride
& (component_size
- 1)) {
8609 GL_INVALID_OPERATION
,
8610 "glVertexAttribIPointer", "stride not valid for type");
8611 return error::kNoError
;
8613 state_
.vertex_attrib_manager
8614 ->SetAttribInfo(indx
,
8615 state_
.bound_array_buffer
.get(),
8620 stride
!= 0 ? stride
: component_size
* size
,
8623 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8624 return error::kNoError
;
8627 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8628 uint32 immediate_data_size
,
8629 const void* cmd_data
) {
8630 const gles2::cmds::VertexAttribPointer
& c
=
8631 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8633 if (!state_
.bound_array_buffer
.get() ||
8634 state_
.bound_array_buffer
->IsDeleted()) {
8635 if (state_
.vertex_attrib_manager
.get() ==
8636 state_
.default_vertex_attrib_manager
.get()) {
8638 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8639 return error::kNoError
;
8640 } else if (c
.offset
!= 0) {
8643 "glVertexAttribPointer", "client side arrays are not allowed");
8644 return error::kNoError
;
8648 GLuint indx
= c
.indx
;
8649 GLint size
= c
.size
;
8650 GLenum type
= c
.type
;
8651 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8652 GLsizei stride
= c
.stride
;
8653 GLsizei offset
= c
.offset
;
8654 const void* ptr
= reinterpret_cast<const void*>(offset
);
8655 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8656 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8657 return error::kNoError
;
8659 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8661 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8662 return error::kNoError
;
8664 if (indx
>= group_
->max_vertex_attribs()) {
8666 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8667 return error::kNoError
;
8671 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8672 return error::kNoError
;
8676 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8677 return error::kNoError
;
8681 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8682 return error::kNoError
;
8684 GLsizei component_size
=
8685 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8686 // component_size must be a power of two to use & as optimized modulo.
8687 DCHECK(GLES2Util::IsPOT(component_size
));
8688 if (offset
& (component_size
- 1)) {
8690 GL_INVALID_OPERATION
,
8691 "glVertexAttribPointer", "offset not valid for type");
8692 return error::kNoError
;
8694 if (stride
& (component_size
- 1)) {
8696 GL_INVALID_OPERATION
,
8697 "glVertexAttribPointer", "stride not valid for type");
8698 return error::kNoError
;
8700 state_
.vertex_attrib_manager
8701 ->SetAttribInfo(indx
,
8702 state_
.bound_array_buffer
.get(),
8707 stride
!= 0 ? stride
: component_size
* size
,
8710 // We support GL_FIXED natively on EGL/GLES2 implementations
8711 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8712 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8714 return error::kNoError
;
8717 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8719 state_
.viewport_x
= x
;
8720 state_
.viewport_y
= y
;
8721 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8722 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8723 glViewport(x
, y
, width
, height
);
8726 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8727 uint32 immediate_data_size
,
8728 const void* cmd_data
) {
8729 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8730 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8731 if (!features().angle_instanced_arrays
) {
8733 GL_INVALID_OPERATION
,
8734 "glVertexAttribDivisorANGLE", "function not available");
8735 return error::kNoError
;
8737 GLuint index
= c
.index
;
8738 GLuint divisor
= c
.divisor
;
8739 if (index
>= group_
->max_vertex_attribs()) {
8742 "glVertexAttribDivisorANGLE", "index out of range");
8743 return error::kNoError
;
8746 state_
.vertex_attrib_manager
->SetDivisor(
8749 glVertexAttribDivisorANGLE(index
, divisor
);
8750 return error::kNoError
;
8753 template <typename pixel_data_type
>
8754 static void WriteAlphaData(
8755 void* pixels
, uint32 row_count
, uint32 channel_count
,
8756 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8757 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8758 DCHECK_GT(channel_count
, 0U);
8759 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8760 uint32 unpadded_row_size_in_elements
=
8761 unpadded_row_size
/ sizeof(pixel_data_type
);
8762 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8763 uint32 padded_row_size_in_elements
=
8764 padded_row_size
/ sizeof(pixel_data_type
);
8765 pixel_data_type
* dst
=
8766 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8767 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8768 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8769 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8772 dst
+= padded_row_size_in_elements
;
8776 void GLES2DecoderImpl::FinishReadPixels(
8777 const cmds::ReadPixels
& c
,
8779 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8780 GLsizei width
= c
.width
;
8781 GLsizei height
= c
.height
;
8782 GLenum format
= c
.format
;
8783 GLenum type
= c
.type
;
8784 typedef cmds::ReadPixels::Result Result
;
8786 Result
* result
= NULL
;
8787 if (c
.result_shm_id
!= 0) {
8788 result
= GetSharedMemoryAs
<Result
*>(
8789 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8792 glDeleteBuffersARB(1, &buffer
);
8797 GLES2Util::ComputeImageDataSizes(
8798 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8800 void* pixels
= GetSharedMemoryAs
<void*>(
8801 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8804 glDeleteBuffersARB(1, &buffer
);
8810 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8812 if (features().map_buffer_range
) {
8813 data
= glMapBufferRange(
8814 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8816 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8819 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8820 "Unable to map memory for readback.");
8823 memcpy(pixels
, data
, pixels_size
);
8824 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8825 // have to restore the state.
8826 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8827 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8828 glDeleteBuffersARB(1, &buffer
);
8831 if (result
!= NULL
) {
8835 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8836 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8837 if ((channels_exist
& 0x0008) == 0 &&
8838 workarounds().clear_alpha_in_readpixels
) {
8839 // Set the alpha to 255 because some drivers are buggy in this regard.
8842 uint32 unpadded_row_size
;
8843 uint32 padded_row_size
;
8844 if (!GLES2Util::ComputeImageDataSizes(
8845 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8846 &unpadded_row_size
, &padded_row_size
)) {
8850 uint32 channel_count
= 0;
8851 uint32 alpha_channel
= 0;
8864 if (channel_count
> 0) {
8866 case GL_UNSIGNED_BYTE
:
8867 WriteAlphaData
<uint8
>(
8868 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8869 padded_row_size
, 0xFF);
8872 WriteAlphaData
<float>(
8873 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8874 padded_row_size
, 1.0f
);
8877 WriteAlphaData
<uint16
>(
8878 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8879 padded_row_size
, 0x3C00);
8886 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8887 const void* cmd_data
) {
8888 const gles2::cmds::ReadPixels
& c
=
8889 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8890 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8891 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8892 if (fbo_error
!= error::kNoError
)
8896 GLsizei width
= c
.width
;
8897 GLsizei height
= c
.height
;
8898 GLenum format
= c
.format
;
8899 GLenum type
= c
.type
;
8900 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8901 if (width
< 0 || height
< 0) {
8902 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8903 return error::kNoError
;
8905 typedef cmds::ReadPixels::Result Result
;
8907 if (!GLES2Util::ComputeImageDataSizes(
8908 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8910 return error::kOutOfBounds
;
8912 void* pixels
= GetSharedMemoryAs
<void*>(
8913 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8915 return error::kOutOfBounds
;
8917 Result
* result
= NULL
;
8918 if (c
.result_shm_id
!= 0) {
8919 result
= GetSharedMemoryAs
<Result
*>(
8920 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8922 return error::kOutOfBounds
;
8926 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8927 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8928 return error::kNoError
;
8930 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8931 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8932 return error::kNoError
;
8935 GLenum src_internal_format
= GetBoundReadFrameBufferInternalFormat();
8936 if (src_internal_format
== 0) {
8937 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels",
8938 "no valid read buffer source");
8939 return error::kNoError
;
8941 std::vector
<GLenum
> accepted_formats
;
8942 std::vector
<GLenum
> accepted_types
;
8943 switch (src_internal_format
) {
8950 // All the RGB_INTEGER formats are not renderable.
8955 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8956 accepted_types
.push_back(GL_UNSIGNED_INT
);
8967 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8968 accepted_types
.push_back(GL_INT
);
8971 accepted_formats
.push_back(GL_RGBA
);
8972 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8973 // Special case with an extra supported format/type.
8974 accepted_formats
.push_back(GL_RGBA
);
8975 accepted_types
.push_back(GL_UNSIGNED_INT_2_10_10_10_REV
);
8978 accepted_formats
.push_back(GL_RGBA
);
8980 GLenum src_type
= GetBoundReadFrameBufferTextureType();
8983 case GL_HALF_FLOAT_OES
:
8985 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
8986 if (!feature_info_
->IsES3Enabled()) {
8987 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8989 accepted_types
.push_back(GL_FLOAT
);
8993 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8999 if (!IsWebGLContext()) {
9000 accepted_formats
.push_back(GL_BGRA_EXT
);
9001 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
9003 DCHECK_EQ(accepted_formats
.size(), accepted_types
.size());
9004 bool format_type_acceptable
= false;
9005 for (size_t ii
= 0; ii
< accepted_formats
.size(); ++ii
) {
9006 if (format
== accepted_formats
[ii
] && type
== accepted_types
[ii
]) {
9007 format_type_acceptable
= true;
9011 if (!format_type_acceptable
) {
9012 // format and type are acceptable enums but not guaranteed to be supported
9013 // for this framebuffer. Have to ask gl if they are valid.
9014 GLint preferred_format
= 0;
9015 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
9016 GLint preferred_type
= 0;
9017 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
9018 if (format
== static_cast<GLenum
>(preferred_format
) &&
9019 type
== static_cast<GLenum
>(preferred_type
)) {
9020 format_type_acceptable
= true;
9023 if (!format_type_acceptable
) {
9024 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glReadPixels",
9025 "format and type incompatible with the current read framebuffer");
9026 return error::kNoError
;
9028 if (width
== 0 || height
== 0) {
9029 return error::kNoError
;
9032 // Get the size of the current fbo or backbuffer.
9033 gfx::Size max_size
= GetBoundReadFrameBufferSize();
9037 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
9039 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9040 return error::kNoError
;
9043 if (!CheckBoundFramebuffersValid("glReadPixels")) {
9044 return error::kNoError
;
9047 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
9049 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9051 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
9052 // The user requested an out of range area. Get the results 1 line
9055 uint32 unpadded_row_size
;
9056 uint32 padded_row_size
;
9057 if (!GLES2Util::ComputeImageDataSizes(
9058 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
9059 &unpadded_row_size
, &padded_row_size
)) {
9061 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9062 return error::kNoError
;
9065 GLint dest_x_offset
= std::max(-x
, 0);
9066 uint32 dest_row_offset
;
9067 if (!GLES2Util::ComputeImageDataSizes(
9068 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
9069 &dest_row_offset
, NULL
, NULL
)) {
9071 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9072 return error::kNoError
;
9075 // Copy each row into the larger dest rect.
9076 int8
* dst
= static_cast<int8
*>(pixels
);
9077 GLint read_x
= std::max(0, x
);
9078 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
9079 GLint read_width
= read_end_x
- read_x
;
9080 for (GLint yy
= 0; yy
< height
; ++yy
) {
9084 memset(dst
, 0, unpadded_row_size
);
9086 // If the row is in range, copy it.
9087 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
9089 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
9091 dst
+= padded_row_size
;
9094 if (async
&& features().use_async_readpixels
) {
9096 glGenBuffersARB(1, &buffer
);
9097 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
9098 // For ANGLE client version 2, GL_STREAM_READ is not available.
9099 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
9100 GL_STATIC_DRAW
: GL_STREAM_READ
;
9101 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
9102 GLenum error
= glGetError();
9103 if (error
== GL_NO_ERROR
) {
9104 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
9105 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
9106 new FenceCallback()));
9107 WaitForReadPixels(base::Bind(
9108 &GLES2DecoderImpl::FinishReadPixels
,
9109 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
9110 <GLES2DecoderImpl
>(this),
9112 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
9113 return error::kNoError
;
9115 // On error, unbind pack buffer and fall through to sync readpixels
9116 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
9117 glDeleteBuffersARB(1, &buffer
);
9120 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
9122 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
9123 if (error
== GL_NO_ERROR
) {
9124 if (result
!= NULL
) {
9127 FinishReadPixels(c
, 0);
9130 return error::kNoError
;
9133 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
9134 const void* cmd_data
) {
9135 const gles2::cmds::PixelStorei
& c
=
9136 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
9137 GLenum pname
= c
.pname
;
9138 GLenum param
= c
.param
;
9139 if (!validators_
->pixel_store
.IsValid(pname
)) {
9140 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
9141 return error::kNoError
;
9144 case GL_PACK_ALIGNMENT
:
9145 case GL_UNPACK_ALIGNMENT
:
9146 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
9148 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
9149 return error::kNoError
;
9155 glPixelStorei(pname
, param
);
9157 case GL_PACK_ALIGNMENT
:
9158 state_
.pack_alignment
= param
;
9160 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
9161 state_
.pack_reverse_row_order
= (param
!= 0);
9163 case GL_UNPACK_ALIGNMENT
:
9164 state_
.unpack_alignment
= param
;
9167 // Validation should have prevented us from getting here.
9171 return error::kNoError
;
9174 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
9175 uint32 immediate_data_size
,
9176 const void* cmd_data
) {
9177 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
9178 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
9179 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
9181 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9183 if (!supports_post_sub_buffer_
) {
9185 GL_INVALID_OPERATION
,
9186 "glPostSubBufferCHROMIUM", "command not supported by surface");
9187 return error::kNoError
;
9190 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9193 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9194 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9195 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9196 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9198 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
9199 gfx::SwapResult::SWAP_FAILED
) {
9200 return error::kNoError
;
9202 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
9203 return error::kLostContext
;
9207 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
9208 uint32 immediate_data_size
,
9209 const void* cmd_data
) {
9210 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
9211 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
9212 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
9214 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9215 "glScheduleOverlayPlaneCHROMIUM",
9217 return error::kNoError
;
9219 gfx::GLImage
* image
=
9220 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
9222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9223 "glScheduleOverlayPlaneCHROMIUM",
9224 "unsupported texture format");
9225 return error::kNoError
;
9227 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
9228 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
9229 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
9230 "glScheduleOverlayPlaneCHROMIUM",
9231 "invalid transform enum");
9232 return error::kNoError
;
9234 if (!surface_
->ScheduleOverlayPlane(
9238 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
9239 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
9240 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9241 "glScheduleOverlayPlaneCHROMIUM",
9242 "failed to schedule overlay");
9244 return error::kNoError
;
9247 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
9248 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9249 const std::string
& name_str
) {
9250 if (!StringIsValidForGLES(name_str
.c_str())) {
9252 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
9253 return error::kNoError
;
9255 Program
* program
= GetProgramInfoNotShader(
9256 client_id
, "glGetAttribLocation");
9258 return error::kNoError
;
9260 if (!program
->IsValid()) {
9262 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
9263 return error::kNoError
;
9265 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9266 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9268 return error::kOutOfBounds
;
9270 // Require the client to init this incase the context is lost and we are no
9271 // longer executing commands.
9272 if (*location
!= -1) {
9273 return error::kGenericError
;
9275 *location
= program
->GetAttribLocation(name_str
);
9276 return error::kNoError
;
9279 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
9280 uint32 immediate_data_size
,
9281 const void* cmd_data
) {
9282 const gles2::cmds::GetAttribLocation
& c
=
9283 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
9284 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9286 return error::kInvalidArguments
;
9288 std::string name_str
;
9289 if (!bucket
->GetAsString(&name_str
)) {
9290 return error::kInvalidArguments
;
9292 return GetAttribLocationHelper(
9293 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9296 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
9297 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9298 const std::string
& name_str
) {
9299 if (!StringIsValidForGLES(name_str
.c_str())) {
9301 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
9302 return error::kNoError
;
9304 Program
* program
= GetProgramInfoNotShader(
9305 client_id
, "glGetUniformLocation");
9307 return error::kNoError
;
9309 if (!program
->IsValid()) {
9311 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
9312 return error::kNoError
;
9314 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9315 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9317 return error::kOutOfBounds
;
9319 // Require the client to init this incase the context is lost an we are no
9320 // longer executing commands.
9321 if (*location
!= -1) {
9322 return error::kGenericError
;
9324 *location
= program
->GetUniformFakeLocation(name_str
);
9325 return error::kNoError
;
9328 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
9329 uint32 immediate_data_size
,
9330 const void* cmd_data
) {
9331 const gles2::cmds::GetUniformLocation
& c
=
9332 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
9333 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9335 return error::kInvalidArguments
;
9337 std::string name_str
;
9338 if (!bucket
->GetAsString(&name_str
)) {
9339 return error::kInvalidArguments
;
9341 return GetUniformLocationHelper(
9342 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9345 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
9346 uint32 immediate_data_size
,
9347 const void* cmd_data
) {
9348 if (!unsafe_es3_apis_enabled())
9349 return error::kUnknownCommand
;
9350 const gles2::cmds::GetUniformIndices
& c
=
9351 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
9352 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
9354 return error::kInvalidArguments
;
9357 std::vector
<char*> names
;
9358 std::vector
<GLint
> len
;
9359 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
9360 return error::kInvalidArguments
;
9362 typedef cmds::GetUniformIndices::Result Result
;
9363 Result
* result
= GetSharedMemoryAs
<Result
*>(
9364 c
.indices_shm_id
, c
.indices_shm_offset
,
9365 Result::ComputeSize(static_cast<size_t>(count
)));
9366 GLuint
* indices
= result
? result
->GetData() : NULL
;
9367 if (indices
== NULL
) {
9368 return error::kOutOfBounds
;
9370 // Check that the client initialized the result.
9371 if (result
->size
!= 0) {
9372 return error::kInvalidArguments
;
9374 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
9376 return error::kNoError
;
9378 GLuint service_id
= program
->service_id();
9379 GLint link_status
= GL_FALSE
;
9380 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9381 if (link_status
!= GL_TRUE
) {
9382 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9383 "glGetUniformIndices", "program not linked");
9384 return error::kNoError
;
9386 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
9387 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
9388 GLenum error
= glGetError();
9389 if (error
== GL_NO_ERROR
) {
9390 result
->SetNumResults(count
);
9392 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
9394 return error::kNoError
;
9397 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
9398 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9399 const std::string
& name_str
) {
9400 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9401 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9403 return error::kOutOfBounds
;
9405 // Require the client to init this incase the context is lost and we are no
9406 // longer executing commands.
9407 if (*location
!= -1) {
9408 return error::kGenericError
;
9410 Program
* program
= GetProgramInfoNotShader(
9411 client_id
, "glGetFragDataLocation");
9413 return error::kNoError
;
9415 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
9416 return error::kNoError
;
9419 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
9420 uint32 immediate_data_size
,
9421 const void* cmd_data
) {
9422 if (!unsafe_es3_apis_enabled())
9423 return error::kUnknownCommand
;
9424 const gles2::cmds::GetFragDataLocation
& c
=
9425 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
9426 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9428 return error::kInvalidArguments
;
9430 std::string name_str
;
9431 if (!bucket
->GetAsString(&name_str
)) {
9432 return error::kInvalidArguments
;
9434 return GetFragDataLocationHelper(
9435 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9438 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
9439 uint32 immediate_data_size
, const void* cmd_data
) {
9440 if (!unsafe_es3_apis_enabled())
9441 return error::kUnknownCommand
;
9442 const gles2::cmds::GetUniformBlockIndex
& c
=
9443 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
9444 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9446 return error::kInvalidArguments
;
9448 std::string name_str
;
9449 if (!bucket
->GetAsString(&name_str
)) {
9450 return error::kInvalidArguments
;
9452 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
9453 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
9455 return error::kOutOfBounds
;
9457 // Require the client to init this in case the context is lost and we are no
9458 // longer executing commands.
9459 if (*index
!= GL_INVALID_INDEX
) {
9460 return error::kGenericError
;
9462 Program
* program
= GetProgramInfoNotShader(
9463 c
.program
, "glGetUniformBlockIndex");
9465 return error::kNoError
;
9467 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
9468 return error::kNoError
;
9471 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
9472 const void* cmd_data
) {
9473 const gles2::cmds::GetString
& c
=
9474 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
9475 GLenum name
= static_cast<GLenum
>(c
.name
);
9476 if (!validators_
->string_type
.IsValid(name
)) {
9477 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
9478 return error::kNoError
;
9481 const char* str
= nullptr;
9482 std::string extensions
;
9485 if (unsafe_es3_apis_enabled())
9486 str
= "OpenGL ES 3.0 Chromium";
9488 str
= "OpenGL ES 2.0 Chromium";
9490 case GL_SHADING_LANGUAGE_VERSION
:
9491 if (unsafe_es3_apis_enabled())
9492 str
= "OpenGL ES GLSL ES 3.0 Chromium";
9494 str
= "OpenGL ES GLSL ES 1.0 Chromium";
9498 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9499 // They are used by WEBGL_debug_renderer_info.
9500 if (!IsWebGLContext())
9503 str
= reinterpret_cast<const char*>(glGetString(name
));
9507 // For WebGL contexts, strip out the OES derivatives and
9508 // EXT frag depth extensions if they have not been enabled.
9509 if (IsWebGLContext()) {
9510 extensions
= feature_info_
->extensions();
9511 if (!derivatives_explicitly_enabled_
) {
9512 size_t offset
= extensions
.find(kOESDerivativeExtension
);
9513 if (std::string::npos
!= offset
) {
9514 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
9518 if (!frag_depth_explicitly_enabled_
) {
9519 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
9520 if (std::string::npos
!= offset
) {
9521 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
9525 if (!draw_buffers_explicitly_enabled_
) {
9526 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
9527 if (std::string::npos
!= offset
) {
9528 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
9532 if (!shader_texture_lod_explicitly_enabled_
) {
9533 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
9534 if (std::string::npos
!= offset
) {
9535 extensions
.replace(offset
,
9536 arraysize(kEXTShaderTextureLodExtension
),
9541 extensions
= feature_info_
->extensions().c_str();
9543 if (supports_post_sub_buffer_
)
9544 extensions
+= " GL_CHROMIUM_post_sub_buffer";
9545 str
= extensions
.c_str();
9549 str
= reinterpret_cast<const char*>(glGetString(name
));
9552 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9553 bucket
->SetFromString(str
);
9554 return error::kNoError
;
9557 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9558 const void* cmd_data
) {
9559 const gles2::cmds::BufferData
& c
=
9560 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9561 GLenum target
= static_cast<GLenum
>(c
.target
);
9562 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9563 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9564 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9565 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9566 const void* data
= NULL
;
9567 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9568 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9570 return error::kOutOfBounds
;
9573 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9574 return error::kNoError
;
9577 void GLES2DecoderImpl::DoBufferSubData(
9578 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9579 // Just delegate it. Some validation is actually done before this.
9580 buffer_manager()->ValidateAndDoBufferSubData(
9581 &state_
, target
, offset
, size
, data
);
9584 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9593 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9594 if ((feature_info_
->feature_flags().angle_depth_texture
||
9595 feature_info_
->IsES3Enabled())
9596 && (channels
& GLES2Util::kDepth
) != 0) {
9597 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9598 // on depth formats.
9600 glGenFramebuffersEXT(1, &fb
);
9601 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9603 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9604 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9605 GL_DEPTH_ATTACHMENT
;
9607 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9608 texture
->service_id(), level
);
9609 // ANGLE promises a depth only attachment ok.
9610 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9611 GL_FRAMEBUFFER_COMPLETE
) {
9615 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9616 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9618 state_
.SetDeviceDepthMask(GL_TRUE
);
9619 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9620 glScissor(xoffset
, yoffset
, width
, height
);
9621 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9623 RestoreClearState();
9625 glDeleteFramebuffersEXT(1, &fb
);
9626 Framebuffer
* framebuffer
=
9627 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9628 GLuint fb_service_id
=
9629 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9630 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9634 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9637 uint32 padded_row_size
;
9638 if (!GLES2Util::ComputeImageDataSizes(
9639 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9640 NULL
, &padded_row_size
)) {
9644 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9648 if (size
> kMaxZeroSize
) {
9649 if (kMaxZeroSize
< padded_row_size
) {
9650 // That'd be an awfully large texture.
9653 // We should never have a large total size with a zero row size.
9654 DCHECK_GT(padded_row_size
, 0U);
9655 tile_height
= kMaxZeroSize
/ padded_row_size
;
9656 if (!GLES2Util::ComputeImageDataSizes(
9657 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9662 tile_height
= height
;
9665 // Assumes the size has already been checked.
9666 scoped_ptr
<char[]> zero(new char[size
]);
9667 memset(zero
.get(), 0, size
);
9668 glBindTexture(texture
->target(), texture
->service_id());
9671 while (y
< height
) {
9672 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9673 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9677 TextureRef
* bound_texture
=
9678 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9679 glBindTexture(texture
->target(),
9680 bound_texture
? bound_texture
->service_id() : 0);
9686 const int kASTCBlockSize
= 16;
9687 const int kS3TCBlockWidth
= 4;
9688 const int kS3TCBlockHeight
= 4;
9689 const int kS3TCDXT1BlockSize
= 8;
9690 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9691 const int kEACAndETC2BlockSize
= 4;
9698 const ASTCBlockArray kASTCBlockArray
[] = {
9699 {4, 4}, /* GL_COMPRESSED_RGBA_ASTC_4x4_KHR */
9700 {5, 4}, /* and GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */
9714 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9715 return (size
== 1) ||
9716 (size
== 2) || !(size
% kS3TCBlockWidth
);
9719 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9720 return GLES2Util::IsPOT(size
);
9723 } // anonymous namespace.
9725 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9726 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9727 GLenum format
, GLsizei
* size_in_bytes
) {
9728 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9731 case GL_ATC_RGB_AMD
:
9732 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9733 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9734 case GL_ETC1_RGB8_OES
:
9736 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9738 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9739 bytes_required
*= kS3TCDXT1BlockSize
;
9741 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR
:
9742 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR
:
9743 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR
:
9744 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR
:
9745 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR
:
9746 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR
:
9747 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR
:
9748 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR
:
9749 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR
:
9750 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR
:
9751 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR
:
9752 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR
:
9753 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR
:
9754 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR
:
9755 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
:
9756 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
:
9757 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
:
9758 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
:
9759 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
:
9760 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
:
9761 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
:
9762 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
:
9763 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
:
9764 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
:
9765 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
:
9766 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
:
9767 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
:
9768 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
: {
9769 const int index
= (format
< GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
) ?
9770 static_cast<int>(format
- GL_COMPRESSED_RGBA_ASTC_4x4_KHR
) :
9771 static_cast<int>(format
- GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
);
9773 const int kBlockWidth
= kASTCBlockArray
[index
].blockWidth
;
9774 const int kBlockHeight
= kASTCBlockArray
[index
].blockHeight
;
9777 (width
+ kBlockWidth
- 1) / kBlockWidth
;
9779 (height
+ kBlockHeight
- 1) / kBlockHeight
;
9781 bytes_required
*= kASTCBlockSize
;
9784 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9785 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9786 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9787 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9789 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9791 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9792 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9794 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9795 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9796 bytes_required
= std::max(width
, 8);
9797 bytes_required
*= std::max(height
, 8);
9798 bytes_required
*= 4;
9799 bytes_required
+= 7;
9800 bytes_required
/= 8;
9802 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9803 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9804 bytes_required
= std::max(width
, 16);
9805 bytes_required
*= std::max(height
, 8);
9806 bytes_required
*= 2;
9807 bytes_required
+= 7;
9808 bytes_required
/= 8;
9812 case GL_COMPRESSED_R11_EAC
:
9813 case GL_COMPRESSED_SIGNED_R11_EAC
:
9814 case GL_COMPRESSED_RGB8_ETC2
:
9815 case GL_COMPRESSED_SRGB8_ETC2
:
9816 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9817 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9819 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9821 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9822 bytes_required
*= 8;
9823 bytes_required
*= depth
;
9825 case GL_COMPRESSED_RG11_EAC
:
9826 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9827 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9828 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9830 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9832 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9833 bytes_required
*= 16;
9834 bytes_required
*= depth
;
9837 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9841 if (!bytes_required
.IsValid()) {
9842 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9846 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9850 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9851 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9852 GLenum format
, GLsizei size
) {
9853 GLsizei bytes_required
= 0;
9854 if (!GetCompressedTexSizeInBytes(
9855 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9859 if (size
!= bytes_required
) {
9861 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9868 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9869 const char* function_name
, GLenum target
, GLint level
,
9870 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9872 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9873 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9874 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9875 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9876 DCHECK_EQ(1, depth
); // 2D formats.
9877 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9879 GL_INVALID_OPERATION
, function_name
,
9880 "width or height invalid for level");
9884 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR
:
9885 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR
:
9886 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR
:
9887 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR
:
9888 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR
:
9889 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR
:
9890 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR
:
9891 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR
:
9892 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR
:
9893 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR
:
9894 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR
:
9895 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR
:
9896 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR
:
9897 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR
:
9898 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
:
9899 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
:
9900 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
:
9901 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
:
9902 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
:
9903 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
:
9904 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
:
9905 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
:
9906 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
:
9907 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
:
9908 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
:
9909 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
:
9910 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
:
9911 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
:
9912 case GL_ATC_RGB_AMD
:
9913 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9914 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9915 case GL_ETC1_RGB8_OES
:
9916 DCHECK_EQ(1, depth
); // 2D formats.
9917 if (width
<= 0 || height
<= 0) {
9919 GL_INVALID_OPERATION
, function_name
,
9920 "width or height invalid for level");
9924 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9925 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9926 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9927 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9928 DCHECK_EQ(1, depth
); // 2D formats.
9929 if (!IsValidPVRTCSize(level
, width
) ||
9930 !IsValidPVRTCSize(level
, height
)) {
9932 GL_INVALID_OPERATION
, function_name
,
9933 "width or height invalid for level");
9939 case GL_COMPRESSED_R11_EAC
:
9940 case GL_COMPRESSED_SIGNED_R11_EAC
:
9941 case GL_COMPRESSED_RG11_EAC
:
9942 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9943 case GL_COMPRESSED_RGB8_ETC2
:
9944 case GL_COMPRESSED_SRGB8_ETC2
:
9945 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9946 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9947 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9948 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9949 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9951 GL_INVALID_OPERATION
, function_name
,
9952 "width, height, or depth invalid");
9955 if (target
== GL_TEXTURE_3D
) {
9957 GL_INVALID_OPERATION
, function_name
,
9958 "target invalid for format");
9967 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9968 const char* function_name
,
9969 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9970 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9972 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9974 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9979 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9980 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9981 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9982 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9983 const int kBlockWidth
= 4;
9984 const int kBlockHeight
= 4;
9985 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9987 GL_INVALID_OPERATION
, function_name
,
9988 "xoffset or yoffset not multiple of 4");
9991 GLsizei tex_width
= 0;
9992 GLsizei tex_height
= 0;
9993 if (!texture
->GetLevelSize(target
, level
,
9994 &tex_width
, &tex_height
, nullptr) ||
9995 width
- xoffset
> tex_width
||
9996 height
- yoffset
> tex_height
) {
9998 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
10001 return ValidateCompressedTexDimensions(
10002 function_name
, target
, level
, width
, height
, 1, format
);
10004 case GL_ATC_RGB_AMD
:
10005 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
10006 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
10007 LOCAL_SET_GL_ERROR(
10008 GL_INVALID_OPERATION
, function_name
,
10009 "not supported for ATC textures");
10012 case GL_ETC1_RGB8_OES
: {
10013 LOCAL_SET_GL_ERROR(
10014 GL_INVALID_OPERATION
, function_name
,
10015 "not supported for ECT1_RGB8_OES textures");
10018 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
10019 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
10020 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
10021 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
10022 if ((xoffset
!= 0) || (yoffset
!= 0)) {
10023 LOCAL_SET_GL_ERROR(
10024 GL_INVALID_OPERATION
, function_name
,
10025 "xoffset and yoffset must be zero");
10028 GLsizei tex_width
= 0;
10029 GLsizei tex_height
= 0;
10030 if (!texture
->GetLevelSize(target
, level
,
10031 &tex_width
, &tex_height
, nullptr) ||
10032 width
!= tex_width
||
10033 height
!= tex_height
) {
10034 LOCAL_SET_GL_ERROR(
10035 GL_INVALID_OPERATION
, function_name
,
10036 "dimensions must match existing texture level dimensions");
10039 return ValidateCompressedTexDimensions(
10040 function_name
, target
, level
, width
, height
, 1, format
);
10044 case GL_COMPRESSED_R11_EAC
:
10045 case GL_COMPRESSED_SIGNED_R11_EAC
:
10046 case GL_COMPRESSED_RG11_EAC
:
10047 case GL_COMPRESSED_SIGNED_RG11_EAC
:
10048 case GL_COMPRESSED_RGB8_ETC2
:
10049 case GL_COMPRESSED_SRGB8_ETC2
:
10050 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
10051 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
10052 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
10053 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
10055 const int kBlockSize
= 4;
10056 GLsizei tex_width
, tex_height
;
10057 if (target
== GL_TEXTURE_3D
||
10058 !texture
->GetLevelSize(target
, level
,
10059 &tex_width
, &tex_height
, nullptr) ||
10060 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
10061 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
10062 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
10063 LOCAL_SET_GL_ERROR(
10064 GL_INVALID_OPERATION
, function_name
,
10065 "dimensions must match existing texture level dimensions");
10075 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
10078 GLenum internal_format
,
10082 GLsizei image_size
,
10083 const void* data
) {
10084 if (!validators_
->texture_target
.IsValid(target
)) {
10085 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10086 "glCompressedTexImage2D", target
, "target");
10087 return error::kNoError
;
10089 if (!validators_
->compressed_texture_format
.IsValid(
10090 internal_format
)) {
10091 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10092 "glCompressedTexImage2D", internal_format
, "internal_format");
10093 return error::kNoError
;
10095 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10097 LOCAL_SET_GL_ERROR(
10099 "glCompressedTexImage2D", "dimensions out of range");
10100 return error::kNoError
;
10102 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10104 if (!texture_ref
) {
10105 LOCAL_SET_GL_ERROR(
10107 "glCompressedTexImage2D", "unknown texture target");
10108 return error::kNoError
;
10110 Texture
* texture
= texture_ref
->texture();
10111 if (texture
->IsImmutable()) {
10112 LOCAL_SET_GL_ERROR(
10113 GL_INVALID_OPERATION
,
10114 "glCompressedTexImage2D", "texture is immutable");
10115 return error::kNoError
;
10117 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
10118 width
, height
, 1, internal_format
) ||
10119 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
10120 1, internal_format
, image_size
)) {
10121 return error::kNoError
;
10124 if (!EnsureGPUMemoryAvailable(image_size
)) {
10125 LOCAL_SET_GL_ERROR(
10126 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
10127 return error::kNoError
;
10130 if (texture
->IsAttachedToFramebuffer()) {
10131 framebuffer_state_
.clear_state_dirty
= true;
10134 scoped_ptr
<int8
[]> zero
;
10136 zero
.reset(new int8
[image_size
]);
10137 memset(zero
.get(), 0, image_size
);
10140 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
10141 glCompressedTexImage2D(
10142 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
10143 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
10144 if (error
== GL_NO_ERROR
) {
10145 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10146 width
, height
, 1, border
, 0, 0,
10147 gfx::Rect(width
, height
));
10150 // This may be a slow command. Exit command processing to allow for
10151 // context preemption and GPU watchdog checks.
10152 ExitCommandProcessingEarly();
10153 return error::kNoError
;
10156 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
10157 uint32 immediate_data_size
,
10158 const void* cmd_data
) {
10159 const gles2::cmds::CompressedTexImage2D
& c
=
10160 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
10161 GLenum target
= static_cast<GLenum
>(c
.target
);
10162 GLint level
= static_cast<GLint
>(c
.level
);
10163 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10164 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10165 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10166 GLint border
= static_cast<GLint
>(c
.border
);
10167 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
10168 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
10169 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
10170 const void* data
= NULL
;
10171 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
10172 data
= GetSharedMemoryAs
<const void*>(
10173 data_shm_id
, data_shm_offset
, image_size
);
10175 return error::kOutOfBounds
;
10178 return DoCompressedTexImage2D(
10179 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
10182 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
10183 uint32 immediate_data_size
,
10184 const void* cmd_data
) {
10185 const gles2::cmds::CompressedTexImage2DBucket
& c
=
10186 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
10187 GLenum target
= static_cast<GLenum
>(c
.target
);
10188 GLint level
= static_cast<GLint
>(c
.level
);
10189 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10190 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10191 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10192 GLint border
= static_cast<GLint
>(c
.border
);
10193 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10195 return error::kInvalidArguments
;
10197 uint32 data_size
= bucket
->size();
10198 GLsizei imageSize
= data_size
;
10199 const void* data
= bucket
->GetData(0, data_size
);
10201 return error::kInvalidArguments
;
10203 return DoCompressedTexImage2D(
10204 target
, level
, internal_format
, width
, height
, border
,
10208 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
10209 uint32 immediate_data_size
,
10210 const void* cmd_data
) {
10211 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
10212 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
10213 GLenum target
= static_cast<GLenum
>(c
.target
);
10214 GLint level
= static_cast<GLint
>(c
.level
);
10215 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10216 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10217 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10218 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10219 GLenum format
= static_cast<GLenum
>(c
.format
);
10220 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10222 return error::kInvalidArguments
;
10224 uint32 data_size
= bucket
->size();
10225 GLsizei imageSize
= data_size
;
10226 const void* data
= bucket
->GetData(0, data_size
);
10228 return error::kInvalidArguments
;
10230 if (!validators_
->texture_target
.IsValid(target
)) {
10231 LOCAL_SET_GL_ERROR(
10232 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
10233 return error::kNoError
;
10235 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
10236 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10237 "glCompressedTexSubImage2D", format
, "format");
10238 return error::kNoError
;
10241 LOCAL_SET_GL_ERROR(
10242 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
10243 return error::kNoError
;
10246 LOCAL_SET_GL_ERROR(
10247 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
10248 return error::kNoError
;
10250 if (imageSize
< 0) {
10251 LOCAL_SET_GL_ERROR(
10252 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
10253 return error::kNoError
;
10255 DoCompressedTexSubImage2D(
10256 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
10257 return error::kNoError
;
10260 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
10263 GLenum internal_format
,
10268 GLsizei image_size
,
10269 const void* data
) {
10270 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
10271 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10272 "glCompressedTexImage3D", target
, "target");
10273 return error::kNoError
;
10275 if (!validators_
->compressed_texture_format
.IsValid(
10276 internal_format
)) {
10277 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10278 "glCompressedTexImage3D", internal_format
, "internal_format");
10279 return error::kNoError
;
10281 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
10283 LOCAL_SET_GL_ERROR(
10285 "glCompressedTexImage3D", "dimensions out of range");
10286 return error::kNoError
;
10288 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10290 if (!texture_ref
) {
10291 LOCAL_SET_GL_ERROR(
10293 "glCompressedTexImage3D", "unknown texture target");
10294 return error::kNoError
;
10296 Texture
* texture
= texture_ref
->texture();
10297 if (texture
->IsImmutable()) {
10298 LOCAL_SET_GL_ERROR(
10299 GL_INVALID_OPERATION
,
10300 "glCompressedTexImage3D", "texture is immutable");
10301 return error::kNoError
;
10304 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
10305 width
, height
, depth
, internal_format
) ||
10306 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
10307 depth
, internal_format
, image_size
)) {
10308 return error::kNoError
;
10311 if (!EnsureGPUMemoryAvailable(image_size
)) {
10312 LOCAL_SET_GL_ERROR(
10313 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
10314 return error::kNoError
;
10317 if (texture
->IsAttachedToFramebuffer()) {
10318 framebuffer_state_
.clear_state_dirty
= true;
10321 scoped_ptr
<int8
[]> zero
;
10323 zero
.reset(new int8
[image_size
]);
10324 memset(zero
.get(), 0, image_size
);
10327 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
10328 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
10329 border
, image_size
, data
);
10330 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
10331 if (error
== GL_NO_ERROR
) {
10332 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10333 width
, height
, depth
, border
, 0, 0,
10334 gfx::Rect(width
, height
));
10337 // This may be a slow command. Exit command processing to allow for
10338 // context preemption and GPU watchdog checks.
10339 ExitCommandProcessingEarly();
10340 return error::kNoError
;
10343 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
10344 uint32 immediate_data_size
, const void* cmd_data
) {
10345 if (!unsafe_es3_apis_enabled())
10346 return error::kUnknownCommand
;
10348 const gles2::cmds::CompressedTexImage3D
& c
=
10349 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
10350 GLenum target
= static_cast<GLenum
>(c
.target
);
10351 GLint level
= static_cast<GLint
>(c
.level
);
10352 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10353 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10354 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10355 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10356 GLint border
= static_cast<GLint
>(c
.border
);
10357 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
10358 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
10359 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
10360 const void* data
= NULL
;
10361 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
10362 data
= GetSharedMemoryAs
<const void*>(
10363 data_shm_id
, data_shm_offset
, image_size
);
10365 return error::kOutOfBounds
;
10368 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
10369 depth
, border
, image_size
, data
);
10372 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
10373 uint32 immediate_data_size
, const void* cmd_data
) {
10374 if (!unsafe_es3_apis_enabled())
10375 return error::kUnknownCommand
;
10377 const gles2::cmds::CompressedTexImage3DBucket
& c
=
10378 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
10379 GLenum target
= static_cast<GLenum
>(c
.target
);
10380 GLint level
= static_cast<GLint
>(c
.level
);
10381 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10382 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10383 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10384 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10385 GLint border
= static_cast<GLint
>(c
.border
);
10386 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10388 return error::kInvalidArguments
;
10390 uint32 data_size
= bucket
->size();
10391 GLsizei imageSize
= data_size
;
10392 const void* data
= bucket
->GetData(0, data_size
);
10394 return error::kInvalidArguments
;
10396 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
10397 depth
, border
, imageSize
, data
);
10400 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
10401 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
10402 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
10403 GLsizei image_size
, const void* data
) {
10404 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
10405 LOCAL_SET_GL_ERROR(
10406 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
10409 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
10410 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10411 "glCompressedTexSubImage3D", format
, "format");
10414 if (width
< 0 || height
< 0 || depth
< 0) {
10415 LOCAL_SET_GL_ERROR(
10416 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
10419 if (image_size
< 0) {
10420 LOCAL_SET_GL_ERROR(
10421 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
10424 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10426 if (!texture_ref
) {
10427 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10428 "unknown texture for target");
10431 Texture
* texture
= texture_ref
->texture();
10432 GLenum type
= 0, internal_format
= 0;
10433 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10434 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10435 "level does not exist");
10438 if (internal_format
!= format
) {
10439 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10440 "format does not match internal format");
10443 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
10444 width
, height
, depth
)) {
10445 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
10449 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
10450 width
, height
, depth
, format
,
10452 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
10453 target
, level
, xoffset
, yoffset
,
10454 zoffset
, width
, height
, depth
,
10455 format
, texture
)) {
10459 // Note: There is no need to deal with texture cleared tracking here
10460 // because the validation above means you can only get here if the level
10461 // is already a matching compressed format and in that case
10462 // CompressedTexImage3D already cleared the texture.
10463 glCompressedTexSubImage3D(
10464 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
10467 // This may be a slow command. Exit command processing to allow for
10468 // context preemption and GPU watchdog checks.
10469 ExitCommandProcessingEarly();
10472 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
10473 uint32 immediate_data_size
, const void* cmd_data
) {
10474 if (!unsafe_es3_apis_enabled())
10475 return error::kUnknownCommand
;
10476 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
10477 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
10478 GLenum target
= static_cast<GLenum
>(c
.target
);
10479 GLint level
= static_cast<GLint
>(c
.level
);
10480 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10481 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10482 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10483 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10484 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10485 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10486 GLenum format
= static_cast<GLenum
>(c
.format
);
10487 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10489 return error::kInvalidArguments
;
10491 uint32 data_size
= bucket
->size();
10492 GLsizei image_size
= data_size
;
10493 const void* data
= bucket
->GetData(0, data_size
);
10495 return error::kInvalidArguments
;
10497 DoCompressedTexSubImage3D(
10498 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
10500 return error::kNoError
;
10503 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
10504 const void* cmd_data
) {
10505 const gles2::cmds::TexImage2D
& c
=
10506 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
10507 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
10508 "width", c
.width
, "height", c
.height
);
10509 // Set as failed for now, but if it successed, this will be set to not failed.
10510 texture_state_
.tex_image_failed
= true;
10511 GLenum target
= static_cast<GLenum
>(c
.target
);
10512 GLint level
= static_cast<GLint
>(c
.level
);
10513 // TODO(kloveless): Change TexImage2D command to use unsigned integer
10514 // for internalformat.
10515 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10516 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10517 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10518 GLint border
= static_cast<GLint
>(c
.border
);
10519 GLenum format
= static_cast<GLenum
>(c
.format
);
10520 GLenum type
= static_cast<GLenum
>(c
.type
);
10521 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10522 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10523 uint32 pixels_size
;
10524 if (!GLES2Util::ComputeImageDataSizes(
10525 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10527 return error::kOutOfBounds
;
10529 const void* pixels
= NULL
;
10530 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10531 pixels
= GetSharedMemoryAs
<const void*>(
10532 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10534 return error::kOutOfBounds
;
10538 // For testing only. Allows us to stress the ability to respond to OOM errors.
10539 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10540 (width
* height
>= 4096 * 4096)) {
10541 LOCAL_SET_GL_ERROR(
10543 "glTexImage2D", "synthetic out of memory");
10544 return error::kNoError
;
10547 TextureManager::DoTexImageArguments args
= {
10548 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
10549 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
10550 texture_manager()->ValidateAndDoTexImage(
10551 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
10553 // This may be a slow command. Exit command processing to allow for
10554 // context preemption and GPU watchdog checks.
10555 ExitCommandProcessingEarly();
10556 return error::kNoError
;
10559 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
10560 const void* cmd_data
) {
10561 if (!unsafe_es3_apis_enabled())
10562 return error::kUnknownCommand
;
10564 const gles2::cmds::TexImage3D
& c
=
10565 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
10566 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10567 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10568 // Set as failed for now, but if it successed, this will be set to not failed.
10569 texture_state_
.tex_image_failed
= true;
10570 GLenum target
= static_cast<GLenum
>(c
.target
);
10571 GLint level
= static_cast<GLint
>(c
.level
);
10572 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10573 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10574 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10575 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10576 GLint border
= static_cast<GLint
>(c
.border
);
10577 GLenum format
= static_cast<GLenum
>(c
.format
);
10578 GLenum type
= static_cast<GLenum
>(c
.type
);
10579 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10580 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10581 uint32 pixels_size
;
10582 if (!GLES2Util::ComputeImageDataSizes(
10583 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10585 return error::kOutOfBounds
;
10587 const void* pixels
= NULL
;
10588 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10589 pixels
= GetSharedMemoryAs
<const void*>(
10590 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10592 return error::kOutOfBounds
;
10596 // For testing only. Allows us to stress the ability to respond to OOM errors.
10597 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10598 (width
* height
* depth
>= 4096 * 4096)) {
10599 LOCAL_SET_GL_ERROR(
10601 "glTexImage3D", "synthetic out of memory");
10602 return error::kNoError
;
10605 TextureManager::DoTexImageArguments args
= {
10606 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
10607 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
10608 texture_manager()->ValidateAndDoTexImage(
10609 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
10611 // This may be a slow command. Exit command processing to allow for
10612 // context preemption and GPU watchdog checks.
10613 ExitCommandProcessingEarly();
10614 return error::kNoError
;
10617 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10625 GLsizei image_size
,
10626 const void * data
) {
10627 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10629 if (!texture_ref
) {
10630 LOCAL_SET_GL_ERROR(
10631 GL_INVALID_OPERATION
,
10632 "glCompressedTexSubImage2D", "unknown texture for target");
10635 Texture
* texture
= texture_ref
->texture();
10637 GLenum internal_format
= 0;
10638 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10639 LOCAL_SET_GL_ERROR(
10640 GL_INVALID_OPERATION
,
10641 "glCompressedTexSubImage2D", "level does not exist.");
10644 if (internal_format
!= format
) {
10645 LOCAL_SET_GL_ERROR(
10646 GL_INVALID_OPERATION
,
10647 "glCompressedTexSubImage2D", "format does not match internal format.");
10650 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10652 LOCAL_SET_GL_ERROR(
10653 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10657 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10658 width
, height
, 1, format
, image_size
) ||
10659 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10660 target
, level
, xoffset
, yoffset
, 0,
10661 width
, height
, 1, format
, texture
)) {
10666 // Note: There is no need to deal with texture cleared tracking here
10667 // because the validation above means you can only get here if the level
10668 // is already a matching compressed format and in that case
10669 // CompressedTexImage2D already cleared the texture.
10670 glCompressedTexSubImage2D(
10671 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10673 // This may be a slow command. Exit command processing to allow for
10674 // context preemption and GPU watchdog checks.
10675 ExitCommandProcessingEarly();
10679 GLint start
, GLint range
, GLint sourceRange
,
10680 GLint
* out_start
, GLint
* out_range
) {
10687 GLint end
= start
+ range
;
10688 if (end
> sourceRange
) {
10689 range
-= end
- sourceRange
;
10691 *out_start
= start
;
10692 *out_range
= range
;
10695 void GLES2DecoderImpl::DoCopyTexImage2D(
10698 GLenum internal_format
,
10704 DCHECK(!ShouldDeferReads());
10705 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10707 if (!texture_ref
) {
10708 LOCAL_SET_GL_ERROR(
10709 GL_INVALID_OPERATION
,
10710 "glCopyTexImage2D", "unknown texture for target");
10713 Texture
* texture
= texture_ref
->texture();
10714 if (texture
->IsImmutable()) {
10715 LOCAL_SET_GL_ERROR(
10716 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10719 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10721 LOCAL_SET_GL_ERROR(
10722 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10725 if (!texture_manager()->ValidateFormatAndTypeCombination(
10726 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10727 GL_UNSIGNED_BYTE
)) {
10731 // Check we have compatible formats.
10732 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10733 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10734 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10736 if ((channels_needed
& channels_exist
) != channels_needed
) {
10737 LOCAL_SET_GL_ERROR(
10738 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10742 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10743 LOCAL_SET_GL_ERROR(
10744 GL_INVALID_OPERATION
,
10745 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10749 uint32 estimated_size
= 0;
10750 if (!GLES2Util::ComputeImageDataSizes(
10751 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10752 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10753 LOCAL_SET_GL_ERROR(
10754 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10758 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10759 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10763 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10767 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10768 LOCAL_SET_GL_ERROR(
10769 GL_INVALID_OPERATION
,
10770 "glCopyTexImage2D", "source and destination textures are the same");
10774 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10778 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10779 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10780 gfx::Size size
= GetBoundReadFrameBufferSize();
10782 if (texture
->IsAttachedToFramebuffer()) {
10783 framebuffer_state_
.clear_state_dirty
= true;
10786 // Clip to size to source dimensions
10789 GLint copyWidth
= 0;
10790 GLint copyHeight
= 0;
10791 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10792 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10796 copyWidth
!= width
||
10797 copyHeight
!= height
) {
10798 // some part was clipped so clear the rect.
10799 uint32 pixels_size
= 0;
10800 if (!GLES2Util::ComputeImageDataSizes(
10801 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10802 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10803 LOCAL_SET_GL_ERROR(
10804 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10807 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10808 memset(zero
.get(), 0, pixels_size
);
10809 ScopedModifyPixels
modify(texture_ref
);
10810 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10811 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10812 if (copyHeight
> 0 && copyWidth
> 0) {
10813 GLint dx
= copyX
- x
;
10814 GLint dy
= copyY
- y
;
10817 glCopyTexSubImage2D(target
, level
,
10818 destX
, destY
, copyX
, copyY
,
10819 copyWidth
, copyHeight
);
10822 ScopedModifyPixels
modify(texture_ref
);
10823 glCopyTexImage2D(target
, level
, internal_format
,
10824 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10826 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10827 if (error
== GL_NO_ERROR
) {
10828 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10829 width
, height
, 1, border
, internal_format
,
10830 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10833 // This may be a slow command. Exit command processing to allow for
10834 // context preemption and GPU watchdog checks.
10835 ExitCommandProcessingEarly();
10838 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10847 DCHECK(!ShouldDeferReads());
10848 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10850 if (!texture_ref
) {
10851 LOCAL_SET_GL_ERROR(
10852 GL_INVALID_OPERATION
,
10853 "glCopyTexSubImage2D", "unknown texture for target");
10856 Texture
* texture
= texture_ref
->texture();
10859 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10860 !texture
->ValidForTexture(
10861 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1)) {
10862 LOCAL_SET_GL_ERROR(
10863 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10867 // Check we have compatible formats.
10868 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10869 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10870 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10872 if (!channels_needed
||
10873 (channels_needed
& channels_exist
) != channels_needed
) {
10874 LOCAL_SET_GL_ERROR(
10875 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10879 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10880 LOCAL_SET_GL_ERROR(
10881 GL_INVALID_OPERATION
,
10882 "glCopySubImage2D", "can not be used with depth or stencil textures");
10886 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10890 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10891 LOCAL_SET_GL_ERROR(
10892 GL_INVALID_OPERATION
,
10893 "glCopyTexSubImage2D", "source and destination textures are the same");
10897 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10901 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10902 gfx::Size size
= GetBoundReadFrameBufferSize();
10905 GLint copyWidth
= 0;
10906 GLint copyHeight
= 0;
10907 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10908 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10910 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10911 height
!= size
.height()) {
10912 gfx::Rect cleared_rect
;
10913 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10914 gfx::Rect(xoffset
, yoffset
, width
, height
),
10916 DCHECK_GE(cleared_rect
.size().GetArea(),
10917 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10918 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10921 // Otherwise clear part of texture level that is not already cleared.
10922 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10924 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10925 "dimensions too big");
10930 // Write all pixels in below.
10931 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10936 copyWidth
!= width
||
10937 copyHeight
!= height
) {
10938 // some part was clipped so clear the sub rect.
10939 uint32 pixels_size
= 0;
10940 if (!GLES2Util::ComputeImageDataSizes(
10941 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10943 LOCAL_SET_GL_ERROR(
10944 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10947 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10948 memset(zero
.get(), 0, pixels_size
);
10949 ScopedModifyPixels
modify(texture_ref
);
10951 target
, level
, xoffset
, yoffset
, width
, height
,
10952 format
, type
, zero
.get());
10955 if (copyHeight
> 0 && copyWidth
> 0) {
10956 GLint dx
= copyX
- x
;
10957 GLint dy
= copyY
- y
;
10958 GLint destX
= xoffset
+ dx
;
10959 GLint destY
= yoffset
+ dy
;
10960 ScopedModifyPixels
modify(texture_ref
);
10961 glCopyTexSubImage2D(target
, level
,
10962 destX
, destY
, copyX
, copyY
,
10963 copyWidth
, copyHeight
);
10966 // This may be a slow command. Exit command processing to allow for
10967 // context preemption and GPU watchdog checks.
10968 ExitCommandProcessingEarly();
10971 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10972 error::Error
* error
,
10973 const char* function_name
,
10982 const void * data
) {
10983 (*error
) = error::kNoError
;
10984 if (!validators_
->texture_target
.IsValid(target
)) {
10985 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10989 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10993 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10996 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10998 if (!texture_ref
) {
10999 LOCAL_SET_GL_ERROR(
11000 GL_INVALID_OPERATION
,
11001 function_name
, "unknown texture for target");
11004 Texture
* texture
= texture_ref
->texture();
11005 GLenum current_type
= 0;
11006 GLenum internal_format
= 0;
11007 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
11008 LOCAL_SET_GL_ERROR(
11009 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
11012 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
11013 function_name
, format
, type
, internal_format
, level
)) {
11016 if (type
!= current_type
&& !feature_info_
->IsES3Enabled()) {
11017 LOCAL_SET_GL_ERROR(
11018 GL_INVALID_OPERATION
,
11019 function_name
, "type does not match type of texture.");
11022 if (!texture
->ValidForTexture(
11023 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1)) {
11024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
11027 if ((GLES2Util::GetChannelsForFormat(format
) &
11028 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
11029 && !feature_info_
->IsES3Enabled()) {
11030 LOCAL_SET_GL_ERROR(
11031 GL_INVALID_OPERATION
,
11032 function_name
, "can not supply data for depth or stencil textures");
11035 if (data
== NULL
) {
11036 (*error
) = error::kOutOfBounds
;
11042 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
11051 const void * data
) {
11052 error::Error error
= error::kNoError
;
11053 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
11054 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
11057 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11059 Texture
* texture
= texture_ref
->texture();
11060 GLsizei tex_width
= 0;
11061 GLsizei tex_height
= 0;
11062 bool ok
= texture
->GetLevelSize(
11063 target
, level
, &tex_width
, &tex_height
, nullptr);
11065 if (xoffset
!= 0 || yoffset
!= 0 ||
11066 width
!= tex_width
|| height
!= tex_height
) {
11067 gfx::Rect cleared_rect
;
11068 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
11069 gfx::Rect(xoffset
, yoffset
, width
, height
),
11071 DCHECK_GE(cleared_rect
.size().GetArea(),
11072 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
11073 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
11076 // Otherwise clear part of texture level that is not already cleared.
11077 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
11079 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
11080 "dimensions too big");
11081 return error::kNoError
;
11084 ScopedTextureUploadTimer
timer(&texture_state_
);
11086 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
11087 return error::kNoError
;
11090 if (!texture_state_
.texsubimage_faster_than_teximage
&&
11091 !texture
->IsImmutable() &&
11092 !texture
->HasImages()) {
11093 ScopedTextureUploadTimer
timer(&texture_state_
);
11094 GLenum internal_format
;
11096 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
11097 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
11100 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
11102 ScopedTextureUploadTimer
timer(&texture_state_
);
11104 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
11106 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
11108 // This may be a slow command. Exit command processing to allow for
11109 // context preemption and GPU watchdog checks.
11110 ExitCommandProcessingEarly();
11111 return error::kNoError
;
11114 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
11115 const void* cmd_data
) {
11116 const gles2::cmds::TexSubImage2D
& c
=
11117 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
11118 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
11119 "width", c
.width
, "height", c
.height
);
11120 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
11121 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
11122 return error::kNoError
;
11124 GLenum target
= static_cast<GLenum
>(c
.target
);
11125 GLint level
= static_cast<GLint
>(c
.level
);
11126 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11127 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11128 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11129 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11130 GLenum format
= static_cast<GLenum
>(c
.format
);
11131 GLenum type
= static_cast<GLenum
>(c
.type
);
11133 if (!GLES2Util::ComputeImageDataSizes(
11134 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
11136 return error::kOutOfBounds
;
11138 const void* pixels
= GetSharedMemoryAs
<const void*>(
11139 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
11140 return DoTexSubImage2D(
11141 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
11144 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
11155 const void * data
) {
11156 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11158 if (!texture_ref
) {
11159 LOCAL_SET_GL_ERROR(
11160 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
11163 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
11164 ScopedTextureUploadTimer
timer(&texture_state_
);
11165 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
11166 depth
, format
, type
, data
);
11167 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
11168 if (error
== GL_NO_ERROR
) {
11169 // TODO(zmo): This is not 100% correct because only part of the level
11170 // image is cleared.
11171 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
11174 // This may be a slow command. Exit command processing to allow for
11175 // context preemption and GPU watchdog checks.
11176 ExitCommandProcessingEarly();
11177 return error::kNoError
;
11180 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
11181 const void* cmd_data
) {
11182 if (!unsafe_es3_apis_enabled())
11183 return error::kUnknownCommand
;
11185 const gles2::cmds::TexSubImage3D
& c
=
11186 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
11187 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
11188 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
11189 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
11190 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
11191 return error::kNoError
;
11193 GLenum target
= static_cast<GLenum
>(c
.target
);
11194 GLint level
= static_cast<GLint
>(c
.level
);
11195 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11196 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11197 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
11198 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11199 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11200 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
11201 GLenum format
= static_cast<GLenum
>(c
.format
);
11202 GLenum type
= static_cast<GLenum
>(c
.type
);
11204 if (!GLES2Util::ComputeImageDataSizes(
11205 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
11207 return error::kOutOfBounds
;
11209 const void* pixels
= GetSharedMemoryAs
<const void*>(
11210 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
11211 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
11212 height
, depth
, format
, type
, pixels
);
11215 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
11216 uint32 immediate_data_size
,
11217 const void* cmd_data
) {
11218 const gles2::cmds::GetVertexAttribPointerv
& c
=
11219 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
11220 GLuint index
= static_cast<GLuint
>(c
.index
);
11221 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11222 typedef cmds::GetVertexAttribPointerv::Result Result
;
11223 Result
* result
= GetSharedMemoryAs
<Result
*>(
11224 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
11226 return error::kOutOfBounds
;
11228 // Check that the client initialized the result.
11229 if (result
->size
!= 0) {
11230 return error::kInvalidArguments
;
11232 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
11233 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11234 "glGetVertexAttribPointerv", pname
, "pname");
11235 return error::kNoError
;
11237 if (index
>= group_
->max_vertex_attribs()) {
11238 LOCAL_SET_GL_ERROR(
11239 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
11240 return error::kNoError
;
11242 result
->SetNumResults(1);
11243 *result
->GetData() =
11244 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
11245 return error::kNoError
;
11249 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
11250 GLint fake_location
,
11253 error::Error
* error
,
11254 GLint
* real_location
,
11255 GLuint
* service_id
,
11256 SizedResult
<T
>** result_pointer
,
11257 GLenum
* result_type
,
11258 GLsizei
* result_size
) {
11260 DCHECK(service_id
);
11261 DCHECK(result_pointer
);
11262 DCHECK(result_type
);
11263 DCHECK(result_size
);
11264 DCHECK(real_location
);
11265 *error
= error::kNoError
;
11266 // Make sure we have enough room for the result on failure.
11267 SizedResult
<T
>* result
;
11268 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
11269 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
11271 *error
= error::kOutOfBounds
;
11274 *result_pointer
= result
;
11275 // Set the result size to 0 so the client does not have to check for success.
11276 result
->SetNumResults(0);
11277 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
11281 if (!program
->IsValid()) {
11282 // Program was not linked successfully. (ie, glLinkProgram)
11283 LOCAL_SET_GL_ERROR(
11284 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
11287 *service_id
= program
->service_id();
11288 GLint array_index
= -1;
11289 const Program::UniformInfo
* uniform_info
=
11290 program
->GetUniformInfoByFakeLocation(
11291 fake_location
, real_location
, &array_index
);
11292 if (!uniform_info
) {
11293 // No such location.
11294 LOCAL_SET_GL_ERROR(
11295 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
11298 GLenum type
= uniform_info
->type
;
11299 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
11300 if (num_elements
== 0) {
11301 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
11304 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
11305 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
11307 *error
= error::kOutOfBounds
;
11310 result
->SetNumResults(num_elements
);
11311 *result_size
= num_elements
* sizeof(T
);
11312 *result_type
= type
;
11316 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
11317 const void* cmd_data
) {
11318 const gles2::cmds::GetUniformiv
& c
=
11319 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
11320 GLuint program
= c
.program
;
11321 GLint fake_location
= c
.location
;
11323 GLenum result_type
;
11324 GLsizei result_size
;
11325 GLint real_location
= -1;
11327 cmds::GetUniformiv::Result
* result
;
11328 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
11329 c
.params_shm_offset
, &error
, &real_location
,
11330 &service_id
, &result
, &result_type
,
11333 service_id
, real_location
, result
->GetData());
11338 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
11339 const void* cmd_data
) {
11340 if (!unsafe_es3_apis_enabled())
11341 return error::kUnknownCommand
;
11343 const gles2::cmds::GetUniformuiv
& c
=
11344 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
11345 GLuint program
= c
.program
;
11346 GLint fake_location
= c
.location
;
11348 GLenum result_type
;
11349 GLsizei result_size
;
11350 GLint real_location
= -1;
11352 cmds::GetUniformuiv::Result
* result
;
11353 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
11354 c
.params_shm_offset
, &error
, &real_location
,
11355 &service_id
, &result
, &result_type
,
11358 service_id
, real_location
, result
->GetData());
11363 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
11364 const void* cmd_data
) {
11365 const gles2::cmds::GetUniformfv
& c
=
11366 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
11367 GLuint program
= c
.program
;
11368 GLint fake_location
= c
.location
;
11370 GLint real_location
= -1;
11372 cmds::GetUniformfv::Result
* result
;
11373 GLenum result_type
;
11374 GLsizei result_size
;
11375 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
11376 c
.params_shm_offset
, &error
, &real_location
,
11377 &service_id
, &result
, &result_type
,
11379 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
11380 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
11381 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
11382 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
11383 glGetUniformiv(service_id
, real_location
, temp
.get());
11384 GLfloat
* dst
= result
->GetData();
11385 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
11386 dst
[ii
] = (temp
[ii
] != 0);
11389 glGetUniformfv(service_id
, real_location
, result
->GetData());
11395 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
11396 uint32 immediate_data_size
,
11397 const void* cmd_data
) {
11398 const gles2::cmds::GetShaderPrecisionFormat
& c
=
11399 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
11400 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
11401 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
11402 typedef cmds::GetShaderPrecisionFormat::Result Result
;
11403 Result
* result
= GetSharedMemoryAs
<Result
*>(
11404 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11406 return error::kOutOfBounds
;
11408 // Check that the client initialized the result.
11409 if (result
->success
!= 0) {
11410 return error::kInvalidArguments
;
11412 if (!validators_
->shader_type
.IsValid(shader_type
)) {
11413 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11414 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
11415 return error::kNoError
;
11417 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
11418 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11419 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
11420 return error::kNoError
;
11423 result
->success
= 1; // true
11425 GLint range
[2] = { 0, 0 };
11426 GLint precision
= 0;
11427 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
11429 result
->min_range
= range
[0];
11430 result
->max_range
= range
[1];
11431 result
->precision
= precision
;
11433 return error::kNoError
;
11436 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
11437 uint32 immediate_data_size
,
11438 const void* cmd_data
) {
11439 const gles2::cmds::GetAttachedShaders
& c
=
11440 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
11441 uint32 result_size
= c
.result_size
;
11442 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11443 Program
* program
= GetProgramInfoNotShader(
11444 program_id
, "glGetAttachedShaders");
11446 return error::kNoError
;
11448 typedef cmds::GetAttachedShaders::Result Result
;
11449 uint32 max_count
= Result::ComputeMaxResults(result_size
);
11450 Result
* result
= GetSharedMemoryAs
<Result
*>(
11451 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
11453 return error::kOutOfBounds
;
11455 // Check that the client initialized the result.
11456 if (result
->size
!= 0) {
11457 return error::kInvalidArguments
;
11460 glGetAttachedShaders(
11461 program
->service_id(), max_count
, &count
, result
->GetData());
11462 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
11463 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
11464 &result
->GetData()[ii
])) {
11466 return error::kGenericError
;
11469 result
->SetNumResults(count
);
11470 return error::kNoError
;
11473 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
11474 uint32 immediate_data_size
,
11475 const void* cmd_data
) {
11476 const gles2::cmds::GetActiveUniform
& c
=
11477 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
11478 GLuint program_id
= c
.program
;
11479 GLuint index
= c
.index
;
11480 uint32 name_bucket_id
= c
.name_bucket_id
;
11481 typedef cmds::GetActiveUniform::Result Result
;
11482 Result
* result
= GetSharedMemoryAs
<Result
*>(
11483 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11485 return error::kOutOfBounds
;
11487 // Check that the client initialized the result.
11488 if (result
->success
!= 0) {
11489 return error::kInvalidArguments
;
11491 Program
* program
= GetProgramInfoNotShader(
11492 program_id
, "glGetActiveUniform");
11494 return error::kNoError
;
11496 const Program::UniformInfo
* uniform_info
=
11497 program
->GetUniformInfo(index
);
11498 if (!uniform_info
) {
11499 LOCAL_SET_GL_ERROR(
11500 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
11501 return error::kNoError
;
11503 result
->success
= 1; // true.
11504 result
->size
= uniform_info
->size
;
11505 result
->type
= uniform_info
->type
;
11506 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11507 bucket
->SetFromString(uniform_info
->name
.c_str());
11508 return error::kNoError
;
11511 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
11512 uint32 immediate_data_size
, const void* cmd_data
) {
11513 if (!unsafe_es3_apis_enabled())
11514 return error::kUnknownCommand
;
11515 const gles2::cmds::GetActiveUniformBlockiv
& c
=
11516 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
11517 GLuint program_id
= c
.program
;
11518 GLuint index
= static_cast<GLuint
>(c
.index
);
11519 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11520 Program
* program
= GetProgramInfoNotShader(
11521 program_id
, "glGetActiveUniformBlockiv");
11523 return error::kNoError
;
11525 GLuint service_id
= program
->service_id();
11526 GLint link_status
= GL_FALSE
;
11527 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11528 if (link_status
!= GL_TRUE
) {
11529 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11530 "glGetActiveActiveUniformBlockiv", "program not linked");
11531 return error::kNoError
;
11533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
11534 GLsizei num_values
= 1;
11535 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
11537 glGetActiveUniformBlockiv(
11538 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
11539 GLenum error
= glGetError();
11540 if (error
!= GL_NO_ERROR
) {
11541 // Assume this will the same error if calling with pname.
11542 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11543 return error::kNoError
;
11545 num_values
= static_cast<GLsizei
>(num
);
11547 typedef cmds::GetActiveUniformBlockiv::Result Result
;
11548 Result
* result
= GetSharedMemoryAs
<Result
*>(
11549 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
11550 GLint
* params
= result
? result
->GetData() : NULL
;
11551 if (params
== NULL
) {
11552 return error::kOutOfBounds
;
11554 // Check that the client initialized the result.
11555 if (result
->size
!= 0) {
11556 return error::kInvalidArguments
;
11558 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
11559 GLenum error
= glGetError();
11560 if (error
== GL_NO_ERROR
) {
11561 result
->SetNumResults(num_values
);
11563 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11565 return error::kNoError
;
11568 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11569 uint32 immediate_data_size
, const void* cmd_data
) {
11570 if (!unsafe_es3_apis_enabled())
11571 return error::kUnknownCommand
;
11572 const gles2::cmds::GetActiveUniformBlockName
& c
=
11573 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
11574 GLuint program_id
= c
.program
;
11575 GLuint index
= c
.index
;
11576 uint32 name_bucket_id
= c
.name_bucket_id
;
11577 typedef cmds::GetActiveUniformBlockName::Result Result
;
11578 Result
* result
= GetSharedMemoryAs
<Result
*>(
11579 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11581 return error::kOutOfBounds
;
11583 // Check that the client initialized the result.
11584 if (*result
!= 0) {
11585 return error::kInvalidArguments
;
11587 Program
* program
= GetProgramInfoNotShader(
11588 program_id
, "glGetActiveUniformBlockName");
11590 return error::kNoError
;
11592 GLuint service_id
= program
->service_id();
11593 GLint link_status
= GL_FALSE
;
11594 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11595 if (link_status
!= GL_TRUE
) {
11596 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11597 "glGetActiveActiveUniformBlockName", "program not linked");
11598 return error::kNoError
;
11600 GLint max_length
= 0;
11602 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
11603 // Increase one so &buffer[0] is always valid.
11604 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
11605 std::vector
<char> buffer(buf_size
);
11606 GLsizei length
= 0;
11607 glGetActiveUniformBlockName(
11608 service_id
, index
, buf_size
, &length
, &buffer
[0]);
11611 return error::kNoError
;
11614 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11615 DCHECK_GT(buf_size
, length
);
11616 DCHECK_EQ(0, buffer
[length
]);
11617 bucket
->SetFromString(&buffer
[0]);
11618 return error::kNoError
;
11621 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
11622 uint32 immediate_data_size
, const void* cmd_data
) {
11623 if (!unsafe_es3_apis_enabled())
11624 return error::kUnknownCommand
;
11625 const gles2::cmds::GetActiveUniformsiv
& c
=
11626 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
11627 GLuint program_id
= c
.program
;
11628 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11629 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
11631 return error::kInvalidArguments
;
11633 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11634 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11635 typedef cmds::GetActiveUniformsiv::Result Result
;
11636 Result
* result
= GetSharedMemoryAs
<Result
*>(
11637 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11638 GLint
* params
= result
? result
->GetData() : NULL
;
11639 if (params
== NULL
) {
11640 return error::kOutOfBounds
;
11642 // Check that the client initialized the result.
11643 if (result
->size
!= 0) {
11644 return error::kInvalidArguments
;
11646 Program
* program
= GetProgramInfoNotShader(
11647 program_id
, "glGetActiveUniformsiv");
11649 return error::kNoError
;
11651 GLuint service_id
= program
->service_id();
11652 GLint link_status
= GL_FALSE
;
11653 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11654 if (link_status
!= GL_TRUE
) {
11655 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11656 "glGetActiveUniformsiv", "program not linked");
11657 return error::kNoError
;
11659 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11660 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11661 GLenum error
= glGetError();
11662 if (error
== GL_NO_ERROR
) {
11663 result
->SetNumResults(count
);
11665 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11667 return error::kNoError
;
11670 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11671 const void* cmd_data
) {
11672 const gles2::cmds::GetActiveAttrib
& c
=
11673 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11674 GLuint program_id
= c
.program
;
11675 GLuint index
= c
.index
;
11676 uint32 name_bucket_id
= c
.name_bucket_id
;
11677 typedef cmds::GetActiveAttrib::Result Result
;
11678 Result
* result
= GetSharedMemoryAs
<Result
*>(
11679 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11681 return error::kOutOfBounds
;
11683 // Check that the client initialized the result.
11684 if (result
->success
!= 0) {
11685 return error::kInvalidArguments
;
11687 Program
* program
= GetProgramInfoNotShader(
11688 program_id
, "glGetActiveAttrib");
11690 return error::kNoError
;
11692 const Program::VertexAttrib
* attrib_info
=
11693 program
->GetAttribInfo(index
);
11694 if (!attrib_info
) {
11695 LOCAL_SET_GL_ERROR(
11696 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11697 return error::kNoError
;
11699 result
->success
= 1; // true.
11700 result
->size
= attrib_info
->size
;
11701 result
->type
= attrib_info
->type
;
11702 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11703 bucket
->SetFromString(attrib_info
->name
.c_str());
11704 return error::kNoError
;
11707 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11708 const void* cmd_data
) {
11709 #if 1 // No binary shader support.
11710 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11711 return error::kNoError
;
11713 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11715 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11716 return error::kNoError
;
11718 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11720 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11721 return error::kNoError
;
11724 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11725 return error::kOutOfBounds
;
11727 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11728 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11729 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11730 const void* binary
= GetSharedMemoryAs
<const void*>(
11731 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11732 if (shaders
== NULL
|| binary
== NULL
) {
11733 return error::kOutOfBounds
;
11735 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11736 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11737 Shader
* shader
= GetShader(shaders
[ii
]);
11739 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11740 return error::kNoError
;
11742 service_ids
[ii
] = shader
->service_id();
11744 // TODO(gman): call glShaderBinary
11745 return error::kNoError
;
11749 void GLES2DecoderImpl::DoSwapBuffers() {
11750 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11752 int this_frame_number
= frame_number_
++;
11753 // TRACE_EVENT for gpu tests:
11754 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11755 TRACE_EVENT_SCOPE_THREAD
,
11756 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11757 "width", (is_offscreen
? offscreen_size_
.width() :
11758 surface_
->GetSize().width()));
11759 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11760 "offscreen", is_offscreen
,
11761 "frame", this_frame_number
);
11763 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11766 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11767 "GLES2Decoder", "SwapBuffer");
11770 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11773 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11774 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11775 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11778 // If offscreen then don't actually SwapBuffers to the display. Just copy
11779 // the rendered frame to another frame buffer.
11780 if (is_offscreen
) {
11781 TRACE_EVENT2("gpu", "Offscreen",
11782 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11783 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11784 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11785 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11787 if (workarounds().needs_offscreen_buffer_workaround
) {
11788 offscreen_saved_frame_buffer_
->Create();
11792 // Allocate the offscreen saved color texture.
11793 DCHECK(offscreen_saved_color_format_
);
11794 offscreen_saved_color_texture_
->AllocateStorage(
11795 offscreen_size_
, offscreen_saved_color_format_
, false);
11797 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11798 offscreen_saved_color_texture_
.get());
11799 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11800 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11801 GL_FRAMEBUFFER_COMPLETE
) {
11802 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11803 << "because offscreen saved FBO was incomplete.";
11804 MarkContextLost(error::kUnknown
);
11805 group_
->LoseContexts(error::kUnknown
);
11809 // Clear the offscreen color texture.
11810 // TODO(piman): Is this still necessary?
11812 ScopedFrameBufferBinder
binder(this,
11813 offscreen_saved_frame_buffer_
->id());
11814 glClearColor(0, 0, 0, 0);
11815 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11816 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11817 glClear(GL_COLOR_BUFFER_BIT
);
11818 RestoreClearState();
11822 UpdateParentTextureInfo();
11825 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11827 ScopedGLErrorSuppressor
suppressor(
11828 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11830 if (IsOffscreenBufferMultisampled()) {
11831 // For multisampled buffers, resolve the frame buffer.
11832 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11834 ScopedFrameBufferBinder
binder(this,
11835 offscreen_target_frame_buffer_
->id());
11837 if (offscreen_target_buffer_preserved_
) {
11838 // Copy the target frame buffer to the saved offscreen texture.
11839 offscreen_saved_color_texture_
->Copy(
11840 offscreen_saved_color_texture_
->size(),
11841 offscreen_saved_color_format_
);
11843 // Flip the textures in the parent context via the texture manager.
11844 if (!!offscreen_saved_color_texture_info_
.get())
11845 offscreen_saved_color_texture_info_
->texture()->
11846 SetServiceId(offscreen_target_color_texture_
->id());
11848 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11849 offscreen_target_frame_buffer_
->AttachRenderTexture(
11850 offscreen_target_color_texture_
.get());
11853 // Ensure the side effects of the copy are visible to the parent
11854 // context. There is no need to do this for ANGLE because it uses a
11855 // single D3D device for all contexts.
11856 if (!feature_info_
->gl_version_info().is_angle
)
11860 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11861 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11862 if (!CheckResetStatus()) {
11863 MarkContextLost(error::kUnknown
);
11864 group_
->LoseContexts(error::kUnknown
);
11869 // This may be a slow command. Exit command processing to allow for
11870 // context preemption and GPU watchdog checks.
11871 ExitCommandProcessingEarly();
11874 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11875 context_
->SetSwapInterval(interval
);
11878 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11879 uint32 immediate_data_size
,
11880 const void* cmd_data
) {
11881 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11882 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11883 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11884 if (!bucket
|| bucket
->size() == 0) {
11885 return error::kInvalidArguments
;
11887 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11888 Result
* result
= GetSharedMemoryAs
<Result
*>(
11889 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11891 return error::kOutOfBounds
;
11893 // Check that the client initialized the result.
11894 if (*result
!= 0) {
11895 return error::kInvalidArguments
;
11897 std::string feature_str
;
11898 if (!bucket
->GetAsString(&feature_str
)) {
11899 return error::kInvalidArguments
;
11902 // TODO(gman): make this some kind of table to function pointer thingy.
11903 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11904 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11905 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11906 buffer_manager()->set_allow_fixed_attribs(true);
11907 // TODO(gman): decide how to remove the need for this const_cast.
11908 // I could make validators_ non const but that seems bad as this is the only
11909 // place it is needed. I could make some special friend class of validators
11910 // just to allow this to set them. That seems silly. I could refactor this
11911 // code to use the extension mechanism or the initialization attributes to
11912 // turn this feature on. Given that the only real point of this is to make
11913 // the conformance tests pass and given that there is lots of real work that
11914 // needs to be done it seems like refactoring for one to one of those
11915 // methods is a very low priority.
11916 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11918 return error::kNoError
;
11921 *result
= 1; // true.
11922 return error::kNoError
;
11925 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11926 uint32 immediate_data_size
,
11927 const void* cmd_data
) {
11928 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11929 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11931 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11932 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11933 info
->Initialize(disallowed_features_
);
11934 bucket
->SetFromString(info
->extensions().c_str());
11935 return error::kNoError
;
11938 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11939 uint32 immediate_data_size
,
11940 const void* cmd_data
) {
11941 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11942 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11943 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11944 if (!bucket
|| bucket
->size() == 0) {
11945 return error::kInvalidArguments
;
11947 std::string feature_str
;
11948 if (!bucket
->GetAsString(&feature_str
)) {
11949 return error::kInvalidArguments
;
11952 bool desire_standard_derivatives
= false;
11953 bool desire_frag_depth
= false;
11954 bool desire_draw_buffers
= false;
11955 bool desire_shader_texture_lod
= false;
11956 if (IsWebGLContext()) {
11957 desire_standard_derivatives
=
11958 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11959 desire_frag_depth
=
11960 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11961 desire_draw_buffers
=
11962 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11963 desire_shader_texture_lod
=
11964 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11967 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11968 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11969 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11970 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11971 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11972 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11973 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11974 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11975 InitializeShaderTranslator();
11978 UpdateCapabilities();
11980 return error::kNoError
;
11983 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11984 uint32 immediate_data_size
,
11985 const void* cmd_data
) {
11986 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11987 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11988 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11989 uint32 bucket_id
= c
.bucket_id
;
11990 Bucket
* bucket
= CreateBucket(bucket_id
);
11991 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11992 Program
* program
= NULL
;
11993 program
= GetProgram(program_id
);
11994 if (!program
|| !program
->IsValid()) {
11995 return error::kNoError
;
11997 program
->GetProgramInfo(program_manager(), bucket
);
11998 return error::kNoError
;
12001 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
12002 uint32 immediate_data_size
, const void* cmd_data
) {
12003 if (!unsafe_es3_apis_enabled())
12004 return error::kUnknownCommand
;
12005 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
12006 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
12007 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12008 uint32 bucket_id
= c
.bucket_id
;
12009 Bucket
* bucket
= CreateBucket(bucket_id
);
12010 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
12011 Program
* program
= NULL
;
12012 program
= GetProgram(program_id
);
12013 if (!program
|| !program
->IsValid()) {
12014 return error::kNoError
;
12016 program
->GetUniformBlocks(bucket
);
12017 return error::kNoError
;
12020 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
12021 uint32 immediate_data_size
, const void* cmd_data
) {
12022 if (!unsafe_es3_apis_enabled())
12023 return error::kUnknownCommand
;
12024 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
12025 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
12026 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12027 uint32 bucket_id
= c
.bucket_id
;
12028 Bucket
* bucket
= CreateBucket(bucket_id
);
12029 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
12030 Program
* program
= NULL
;
12031 program
= GetProgram(program_id
);
12032 if (!program
|| !program
->IsValid()) {
12033 return error::kNoError
;
12035 program
->GetUniformsES3(bucket
);
12036 return error::kNoError
;
12039 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
12040 uint32 immediate_data_size
,
12041 const void* cmd_data
) {
12042 if (!unsafe_es3_apis_enabled())
12043 return error::kUnknownCommand
;
12044 const gles2::cmds::GetTransformFeedbackVarying
& c
=
12045 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
12046 GLuint program_id
= c
.program
;
12047 GLuint index
= c
.index
;
12048 uint32 name_bucket_id
= c
.name_bucket_id
;
12049 typedef cmds::GetTransformFeedbackVarying::Result Result
;
12050 Result
* result
= GetSharedMemoryAs
<Result
*>(
12051 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
12053 return error::kOutOfBounds
;
12055 // Check that the client initialized the result.
12056 if (result
->success
!= 0) {
12057 return error::kInvalidArguments
;
12059 Program
* program
= GetProgramInfoNotShader(
12060 program_id
, "glGetTransformFeedbackVarying");
12062 return error::kNoError
;
12064 GLuint service_id
= program
->service_id();
12065 GLint link_status
= GL_FALSE
;
12066 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
12067 if (link_status
!= GL_TRUE
) {
12068 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12069 "glGetTransformFeedbackVarying", "program not linked");
12070 return error::kNoError
;
12072 GLint max_length
= 0;
12074 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
12075 max_length
= std::max(1, max_length
);
12076 std::vector
<char> buffer(max_length
);
12077 GLsizei length
= 0;
12080 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
12081 glGetTransformFeedbackVarying(
12082 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
12083 GLenum error
= glGetError();
12084 if (error
!= GL_NO_ERROR
) {
12085 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
12086 return error::kNoError
;
12088 result
->success
= 1; // true.
12089 result
->size
= static_cast<int32_t>(size
);
12090 result
->type
= static_cast<uint32_t>(type
);
12091 Bucket
* bucket
= CreateBucket(name_bucket_id
);
12092 DCHECK(length
>= 0 && length
< max_length
);
12093 buffer
[length
] = '\0'; // Just to be safe.
12094 bucket
->SetFromString(&buffer
[0]);
12095 return error::kNoError
;
12098 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
12099 uint32 immediate_data_size
, const void* cmd_data
) {
12100 if (!unsafe_es3_apis_enabled())
12101 return error::kUnknownCommand
;
12102 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
12103 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
12105 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12106 uint32 bucket_id
= c
.bucket_id
;
12107 Bucket
* bucket
= CreateBucket(bucket_id
);
12108 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
12109 Program
* program
= NULL
;
12110 program
= GetProgram(program_id
);
12111 if (!program
|| !program
->IsValid()) {
12112 return error::kNoError
;
12114 program
->GetTransformFeedbackVaryings(bucket
);
12115 return error::kNoError
;
12118 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
12119 return context_lost_reason_
;
12122 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
12123 GLenum reset_status
) const {
12124 switch (reset_status
) {
12126 // TODO(kbr): improve the precision of the error code in this case.
12127 // Consider delegating to context for error code if MakeCurrent fails.
12128 return error::kUnknown
;
12129 case GL_GUILTY_CONTEXT_RESET_ARB
:
12130 return error::kGuilty
;
12131 case GL_INNOCENT_CONTEXT_RESET_ARB
:
12132 return error::kInnocent
;
12133 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
12134 return error::kUnknown
;
12138 return error::kUnknown
;
12141 bool GLES2DecoderImpl::WasContextLost() const {
12142 return context_was_lost_
;
12145 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
12146 return WasContextLost() && reset_by_robustness_extension_
;
12149 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
12150 // Only lose the context once.
12151 if (WasContextLost())
12154 // Don't make GL calls in here, the context might not be current.
12155 context_lost_reason_
= reason
;
12156 current_decoder_error_
= error::kLostContext
;
12157 context_was_lost_
= true;
12160 bool GLES2DecoderImpl::CheckResetStatus() {
12161 DCHECK(!WasContextLost());
12162 DCHECK(context_
->IsCurrent(NULL
));
12164 if (IsRobustnessSupported()) {
12165 // If the reason for the call was a GL error, we can try to determine the
12166 // reset status more accurately.
12167 GLenum driver_status
= glGetGraphicsResetStatusARB();
12168 if (driver_status
== GL_NO_ERROR
)
12171 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
12172 << " context lost via ARB/EXT_robustness. Reset status = "
12173 << GLES2Util::GetStringEnum(driver_status
);
12175 // Don't pretend we know which client was responsible.
12176 if (workarounds().use_virtualized_gl_contexts
)
12177 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
12179 switch (driver_status
) {
12180 case GL_GUILTY_CONTEXT_RESET_ARB
:
12181 MarkContextLost(error::kGuilty
);
12183 case GL_INNOCENT_CONTEXT_RESET_ARB
:
12184 MarkContextLost(error::kInnocent
);
12186 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
12187 MarkContextLost(error::kUnknown
);
12193 reset_by_robustness_extension_
= true;
12199 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
12200 uint32 immediate_data_size
,
12201 const void* cmd_data
) {
12202 return error::kUnknownCommand
;
12205 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
12206 uint32 immediate_data_size
,
12207 const void* cmd_data
) {
12208 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
12209 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
12210 uint32 sync_point
= c
.sync_point
;
12211 if (wait_sync_point_callback_
.is_null())
12212 return error::kNoError
;
12214 return wait_sync_point_callback_
.Run(sync_point
) ?
12215 error::kNoError
: error::kDeferCommandUntilLater
;
12218 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
12219 uint32 immediate_data_size
,
12220 const void* cmd_data
) {
12221 if (surface_
->DeferDraws())
12222 return error::kDeferCommandUntilLater
;
12223 if (!surface_
->SetBackbufferAllocation(false))
12224 return error::kLostContext
;
12225 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
12226 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
12227 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
12228 return error::kNoError
;
12231 bool GLES2DecoderImpl::GenQueriesEXTHelper(
12232 GLsizei n
, const GLuint
* client_ids
) {
12233 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12234 if (query_manager_
->GetQuery(client_ids
[ii
])) {
12238 query_manager_
->GenQueries(n
, client_ids
);
12242 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
12243 GLsizei n
, const GLuint
* client_ids
) {
12244 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12245 query_manager_
->RemoveQuery(client_ids
[ii
]);
12249 bool GLES2DecoderImpl::HasPendingQueries() const {
12250 return query_manager_
.get() && query_manager_
->HavePendingQueries();
12253 void GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
12254 if (!query_manager_
.get())
12256 if (!query_manager_
->ProcessPendingQueries(did_finish
))
12257 current_decoder_error_
= error::kOutOfBounds
;
12260 // Note that if there are no pending readpixels right now,
12261 // this function will call the callback immediately.
12262 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
12263 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
12264 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
12270 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
12271 // Note: |did_finish| guarantees that the GPU has passed the fence but
12272 // we cannot assume that GLFence::HasCompleted() will return true yet as
12273 // that's not guaranteed by all GLFence implementations.
12274 while (!pending_readpixel_fences_
.empty() &&
12276 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
12277 std::vector
<base::Closure
> callbacks
=
12278 pending_readpixel_fences_
.front()->callbacks
;
12279 pending_readpixel_fences_
.pop();
12280 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
12281 callbacks
[i
].Run();
12286 bool GLES2DecoderImpl::HasMoreIdleWork() const {
12287 return !pending_readpixel_fences_
.empty() ||
12288 gpu_tracer_
->HasTracesToProcess();
12291 void GLES2DecoderImpl::PerformIdleWork() {
12292 gpu_tracer_
->ProcessTraces();
12293 ProcessPendingReadPixels(false);
12296 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
12297 const void* cmd_data
) {
12298 const gles2::cmds::BeginQueryEXT
& c
=
12299 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
12300 GLenum target
= static_cast<GLenum
>(c
.target
);
12301 GLuint client_id
= static_cast<GLuint
>(c
.id
);
12302 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12303 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12306 case GL_COMMANDS_ISSUED_CHROMIUM
:
12307 case GL_LATENCY_QUERY_CHROMIUM
:
12308 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
12309 case GL_GET_ERROR_QUERY_CHROMIUM
:
12311 case GL_COMMANDS_COMPLETED_CHROMIUM
:
12312 if (!features().chromium_sync_query
) {
12313 LOCAL_SET_GL_ERROR(
12314 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12315 "not enabled for commands completed queries");
12316 return error::kNoError
;
12319 case GL_SAMPLES_PASSED
:
12320 case GL_ANY_SAMPLES_PASSED
:
12321 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
12322 if (!features().occlusion_query_boolean
) {
12323 LOCAL_SET_GL_ERROR(
12324 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12325 "not enabled for occlusion queries");
12326 return error::kNoError
;
12329 case GL_TIME_ELAPSED
:
12330 if (!query_manager_
->GPUTimingAvailable()) {
12331 LOCAL_SET_GL_ERROR(
12332 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12333 "not enabled for timing queries");
12334 return error::kNoError
;
12337 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
12338 if (feature_info_
->IsES3Enabled()) {
12343 LOCAL_SET_GL_ERROR(
12344 GL_INVALID_ENUM
, "glBeginQueryEXT",
12345 "unknown query target");
12346 return error::kNoError
;
12349 if (query_manager_
->GetActiveQuery(target
)) {
12350 LOCAL_SET_GL_ERROR(
12351 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
12352 return error::kNoError
;
12355 if (client_id
== 0) {
12356 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
12357 return error::kNoError
;
12360 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
12362 if (!query_manager_
->IsValidQuery(client_id
)) {
12363 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12365 "id not made by glGenQueriesEXT");
12366 return error::kNoError
;
12368 query
= query_manager_
->CreateQuery(
12369 target
, client_id
, sync_shm_id
, sync_shm_offset
);
12372 if (query
->target() != target
) {
12373 LOCAL_SET_GL_ERROR(
12374 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
12375 return error::kNoError
;
12376 } else if (query
->shm_id() != sync_shm_id
||
12377 query
->shm_offset() != sync_shm_offset
) {
12378 DLOG(ERROR
) << "Shared memory used by query not the same as before";
12379 return error::kInvalidArguments
;
12382 if (!query_manager_
->BeginQuery(query
)) {
12383 return error::kOutOfBounds
;
12386 return error::kNoError
;
12389 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
12390 const void* cmd_data
) {
12391 const gles2::cmds::EndQueryEXT
& c
=
12392 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
12393 GLenum target
= static_cast<GLenum
>(c
.target
);
12394 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
12396 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
12398 LOCAL_SET_GL_ERROR(
12399 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
12400 return error::kNoError
;
12403 if (!query_manager_
->EndQuery(query
, submit_count
)) {
12404 return error::kOutOfBounds
;
12407 query_manager_
->ProcessPendingTransferQueries();
12409 return error::kNoError
;
12412 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
12413 const void* cmd_data
) {
12414 const gles2::cmds::QueryCounterEXT
& c
=
12415 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
12416 GLuint client_id
= static_cast<GLuint
>(c
.id
);
12417 GLenum target
= static_cast<GLenum
>(c
.target
);
12418 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12419 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12420 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
12424 if (!query_manager_
->GPUTimingAvailable()) {
12425 LOCAL_SET_GL_ERROR(
12426 GL_INVALID_OPERATION
, "glQueryCounterEXT",
12427 "not enabled for timing queries");
12428 return error::kNoError
;
12432 LOCAL_SET_GL_ERROR(
12433 GL_INVALID_ENUM
, "glQueryCounterEXT",
12434 "unknown query target");
12435 return error::kNoError
;
12438 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
12440 if (!query_manager_
->IsValidQuery(client_id
)) {
12441 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12442 "glQueryCounterEXT",
12443 "id not made by glGenQueriesEXT");
12444 return error::kNoError
;
12446 query
= query_manager_
->CreateQuery(
12447 target
, client_id
, sync_shm_id
, sync_shm_offset
);
12449 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
12450 return error::kOutOfBounds
;
12453 return error::kNoError
;
12456 error::Error
GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
12457 uint32 immediate_data_size
, const void* cmd_data
) {
12458 const gles2::cmds::SetDisjointValueSyncCHROMIUM
& c
=
12459 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM
*>(cmd_data
);
12460 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12461 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12463 query_manager_
->SetDisjointSync(sync_shm_id
, sync_shm_offset
);
12464 return error::kNoError
;
12467 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
12468 GLsizei n
, const GLuint
* client_ids
) {
12469 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12470 if (GetVertexAttribManager(client_ids
[ii
])) {
12475 if (!features().native_vertex_array_object
) {
12477 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12478 CreateVertexAttribManager(client_ids
[ii
], 0, true);
12481 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
12483 glGenVertexArraysOES(n
, service_ids
.get());
12484 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12485 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
12492 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
12493 GLsizei n
, const GLuint
* client_ids
) {
12494 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12495 VertexAttribManager
* vao
=
12496 GetVertexAttribManager(client_ids
[ii
]);
12497 if (vao
&& !vao
->IsDeleted()) {
12498 if (state_
.vertex_attrib_manager
.get() == vao
) {
12499 DoBindVertexArrayOES(0);
12501 RemoveVertexAttribManager(client_ids
[ii
]);
12506 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
12507 VertexAttribManager
* vao
= NULL
;
12508 if (client_id
!= 0) {
12509 vao
= GetVertexAttribManager(client_id
);
12511 // Unlike most Bind* methods, the spec explicitly states that VertexArray
12512 // only allows names that have been previously generated. As such, we do
12513 // not generate new names here.
12514 LOCAL_SET_GL_ERROR(
12515 GL_INVALID_OPERATION
,
12516 "glBindVertexArrayOES", "bad vertex array id.");
12517 current_decoder_error_
= error::kNoError
;
12521 vao
= state_
.default_vertex_attrib_manager
.get();
12524 // Only set the VAO state if it's changed
12525 if (state_
.vertex_attrib_manager
.get() != vao
) {
12526 state_
.vertex_attrib_manager
= vao
;
12527 if (!features().native_vertex_array_object
) {
12528 EmulateVertexArrayState();
12530 GLuint service_id
= vao
->service_id();
12531 glBindVertexArrayOES(service_id
);
12536 // Used when OES_vertex_array_object isn't natively supported
12537 void GLES2DecoderImpl::EmulateVertexArrayState() {
12538 // Setup the Vertex attribute state
12539 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
12540 RestoreStateForAttrib(vv
, true);
12543 // Setup the element buffer
12544 Buffer
* element_array_buffer
=
12545 state_
.vertex_attrib_manager
->element_array_buffer();
12546 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
12547 element_array_buffer
? element_array_buffer
->service_id() : 0);
12550 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
12551 const VertexAttribManager
* vao
=
12552 GetVertexAttribManager(client_id
);
12553 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
12556 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
12557 GLuint service_id
= 0;
12558 return path_manager()->GetPath(client_id
, &service_id
) &&
12559 glIsPathNV(service_id
) == GL_TRUE
;
12562 #if defined(OS_MACOSX)
12563 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
12564 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
12566 if (it
!= texture_to_io_surface_map_
.end()) {
12567 // Found a previous IOSurface bound to this texture; release it.
12568 IOSurfaceRef surface
= it
->second
;
12569 CFRelease(surface
);
12570 texture_to_io_surface_map_
.erase(it
);
12575 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12576 GLenum target
, GLsizei width
, GLsizei height
,
12577 GLuint io_surface_id
, GLuint plane
) {
12578 #if defined(OS_MACOSX)
12579 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
12580 LOCAL_SET_GL_ERROR(
12581 GL_INVALID_OPERATION
,
12582 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12586 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
12587 // This might be supported in the future, and if we could require
12588 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12589 // could delete a lot of code. For now, perform strict validation so we
12590 // know what's going on.
12591 LOCAL_SET_GL_ERROR(
12592 GL_INVALID_OPERATION
,
12593 "glTexImageIOSurface2DCHROMIUM",
12594 "requires TEXTURE_RECTANGLE_ARB target");
12598 // Default target might be conceptually valid, but disallow it to avoid
12600 TextureRef
* texture_ref
=
12601 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12602 if (!texture_ref
) {
12603 LOCAL_SET_GL_ERROR(
12604 GL_INVALID_OPERATION
,
12605 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12609 // Look up the new IOSurface. Note that because of asynchrony
12610 // between processes this might fail; during live resizing the
12611 // plugin process might allocate and release an IOSurface before
12612 // this process gets a chance to look it up. Hold on to any old
12613 // IOSurface in this case.
12614 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
12616 LOCAL_SET_GL_ERROR(
12617 GL_INVALID_OPERATION
,
12618 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12622 // Release any IOSurface previously bound to this texture.
12623 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
12625 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12626 texture_to_io_surface_map_
.insert(
12627 std::make_pair(texture_ref
->service_id(), surface
));
12629 CGLContextObj context
=
12630 static_cast<CGLContextObj
>(context_
->GetHandle());
12632 CGLError err
= CGLTexImageIOSurface2D(
12639 GL_UNSIGNED_INT_8_8_8_8_REV
,
12643 if (err
!= kCGLNoError
) {
12644 LOCAL_SET_GL_ERROR(
12645 GL_INVALID_OPERATION
,
12646 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12650 texture_manager()->SetLevelInfo(
12651 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12652 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12655 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12656 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12660 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12661 switch (internalformat
) {
12673 return GL_RED_INTEGER
;
12685 return GL_RG_INTEGER
;
12686 case GL_ATC_RGB_AMD
:
12687 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12688 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12689 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12690 case GL_ETC1_RGB8_OES
:
12692 case GL_R11F_G11F_B10F
:
12694 case GL_RGB8_SNORM
:
12705 return GL_RGB_INTEGER
;
12706 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12707 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12708 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12709 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12710 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12711 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12712 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12714 case GL_SRGB8_ALPHA8
:
12715 case GL_RGBA8_SNORM
:
12724 case GL_RGB10_A2UI
:
12729 return GL_RGBA_INTEGER
;
12730 case GL_DEPTH_COMPONENT16
:
12731 case GL_DEPTH_COMPONENT24
:
12732 case GL_DEPTH_COMPONENT32F
:
12733 return GL_DEPTH_COMPONENT
;
12734 case GL_DEPTH24_STENCIL8
:
12735 case GL_DEPTH32F_STENCIL8
:
12736 return GL_DEPTH_STENCIL
;
12737 case GL_LUMINANCE8_ALPHA8_EXT
:
12738 return GL_LUMINANCE_ALPHA
;
12739 case GL_LUMINANCE8_EXT
:
12740 return GL_LUMINANCE
;
12741 case GL_ALPHA8_EXT
:
12743 case GL_ALPHA32F_EXT
:
12745 case GL_LUMINANCE32F_EXT
:
12746 return GL_LUMINANCE
;
12747 case GL_LUMINANCE_ALPHA32F_EXT
:
12748 return GL_LUMINANCE_ALPHA
;
12749 case GL_ALPHA16F_EXT
:
12751 case GL_LUMINANCE16F_EXT
:
12752 return GL_LUMINANCE
;
12753 case GL_LUMINANCE_ALPHA16F_EXT
:
12754 return GL_LUMINANCE_ALPHA
;
12756 return GL_BGRA_EXT
;
12762 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12763 const char* function_name
,
12765 TextureRef
* source_texture_ref
,
12766 TextureRef
* dest_texture_ref
,
12767 GLenum dest_internal_format
) {
12768 if (!source_texture_ref
|| !dest_texture_ref
) {
12769 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12773 if (GL_TEXTURE_2D
!= target
) {
12774 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12775 "invalid texture target");
12779 Texture
* source_texture
= source_texture_ref
->texture();
12780 Texture
* dest_texture
= dest_texture_ref
->texture();
12781 if (source_texture
== dest_texture
) {
12782 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12783 "source and destination textures are the same");
12787 if (dest_texture
->target() != GL_TEXTURE_2D
||
12788 (source_texture
->target() != GL_TEXTURE_2D
&&
12789 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12790 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12791 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12792 "invalid texture target binding");
12796 GLenum source_type
= 0;
12797 GLenum source_internal_format
= 0;
12798 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12799 &source_internal_format
);
12801 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12802 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12803 // renderable on some platforms.
12804 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12805 dest_internal_format
== GL_RGBA
||
12806 dest_internal_format
== GL_BGRA_EXT
;
12807 bool valid_source_format
=
12808 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12809 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12810 source_internal_format
== GL_LUMINANCE
||
12811 source_internal_format
== GL_LUMINANCE_ALPHA
||
12812 source_internal_format
== GL_BGRA_EXT
||
12813 source_internal_format
== GL_RGB_YCBCR_422_CHROMIUM
;
12814 if (!valid_source_format
|| !valid_dest_format
) {
12815 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12816 "invalid internal format");
12822 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12823 const char* function_name
,
12825 TextureRef
* source_texture_ref
,
12826 TextureRef
* dest_texture_ref
) {
12827 if (!source_texture_ref
|| !dest_texture_ref
) {
12828 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12832 if (GL_TEXTURE_2D
!= target
) {
12833 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12834 "invalid texture target");
12838 Texture
* source_texture
= source_texture_ref
->texture();
12839 Texture
* dest_texture
= dest_texture_ref
->texture();
12840 if (source_texture
== dest_texture
) {
12841 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12842 "source and destination textures are the same");
12846 if (dest_texture
->target() != GL_TEXTURE_2D
||
12847 (source_texture
->target() != GL_TEXTURE_2D
&&
12848 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12849 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12850 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12851 "invalid texture target binding");
12855 GLenum source_type
= 0;
12856 GLenum source_internal_format
= 0;
12857 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12858 &source_internal_format
);
12860 bool valid_format
=
12861 source_internal_format
== GL_ATC_RGB_AMD
||
12862 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12863 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12864 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12865 source_internal_format
== GL_ETC1_RGB8_OES
;
12867 if (!valid_format
) {
12868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12869 "invalid internal format");
12876 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12880 GLenum internal_format
,
12882 GLboolean unpack_flip_y
,
12883 GLboolean unpack_premultiply_alpha
,
12884 GLboolean unpack_unmultiply_alpha
) {
12885 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12887 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12888 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12889 Texture
* source_texture
= source_texture_ref
->texture();
12890 Texture
* dest_texture
= dest_texture_ref
->texture();
12891 int source_width
= 0;
12892 int source_height
= 0;
12893 gfx::GLImage
* image
=
12894 source_texture
->GetLevelImage(source_texture
->target(), 0);
12896 gfx::Size size
= image
->GetSize();
12897 source_width
= size
.width();
12898 source_height
= size
.height();
12899 if (source_width
<= 0 || source_height
<= 0) {
12900 LOCAL_SET_GL_ERROR(
12902 "glCopyTextureChromium", "invalid image size");
12906 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12907 &source_width
, &source_height
, nullptr)) {
12908 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12909 "glCopyTextureChromium",
12910 "source texture has no level 0");
12914 // Check that this type of texture is allowed.
12915 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12916 source_width
, source_height
, 1)) {
12917 LOCAL_SET_GL_ERROR(
12918 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12923 GLenum source_type
= 0;
12924 GLenum source_internal_format
= 0;
12925 source_texture
->GetLevelType(
12926 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12928 if (dest_texture
->IsImmutable()) {
12929 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12930 "texture is immutable");
12934 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12935 source_texture_ref
, dest_texture_ref
,
12936 internal_format
)) {
12940 // Clear the source texture if necessary.
12941 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12942 source_texture
->target(), 0)) {
12943 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12944 "dimensions too big");
12948 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12949 // needed because it takes 10s of milliseconds to initialize.
12950 if (!copy_texture_CHROMIUM_
.get()) {
12951 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12952 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12953 copy_texture_CHROMIUM_
->Initialize(this);
12954 RestoreCurrentFramebufferBindings();
12955 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12959 GLenum dest_type_previous
= dest_type
;
12960 GLenum dest_internal_format
= internal_format
;
12961 int dest_width
= 0;
12962 int dest_height
= 0;
12963 bool dest_level_defined
= dest_texture
->GetLevelSize(
12964 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12966 if (dest_level_defined
) {
12967 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12968 &dest_internal_format
);
12971 // Resize the destination texture to the dimensions of the source texture.
12972 if (!dest_level_defined
|| dest_width
!= source_width
||
12973 dest_height
!= source_height
||
12974 dest_internal_format
!= internal_format
||
12975 dest_type_previous
!= dest_type
) {
12976 // Ensure that the glTexImage2D succeeds.
12977 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12978 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12979 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12980 0, internal_format
, dest_type
, NULL
);
12981 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12982 if (error
!= GL_NO_ERROR
) {
12983 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12987 texture_manager()->SetLevelInfo(
12988 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12989 source_height
, 1, 0, internal_format
, dest_type
,
12990 gfx::Rect(source_width
, source_height
));
12992 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12996 ScopedModifyPixels
modify(dest_texture_ref
);
12998 // Try using GLImage::CopyTexSubImage when possible.
12999 bool unpack_premultiply_alpha_change
=
13000 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
13001 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
13002 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13003 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
13004 gfx::Rect(0, 0, source_width
, source_height
))) {
13009 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13011 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13012 // before presenting.
13013 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
13014 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13015 // instead of using kIdentityMatrix crbug.com/226218.
13016 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
13017 this, source_texture
->target(), source_texture
->service_id(),
13018 dest_texture
->service_id(), source_width
, source_height
,
13019 unpack_flip_y
== GL_TRUE
,
13020 unpack_premultiply_alpha
== GL_TRUE
,
13021 unpack_unmultiply_alpha
== GL_TRUE
,
13024 copy_texture_CHROMIUM_
->DoCopyTexture(
13025 this, source_texture
->target(), source_texture
->service_id(),
13026 source_internal_format
, dest_texture
->service_id(), internal_format
,
13027 source_width
, source_height
,
13028 unpack_flip_y
== GL_TRUE
,
13029 unpack_premultiply_alpha
== GL_TRUE
,
13030 unpack_unmultiply_alpha
== GL_TRUE
);
13033 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13036 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
13046 GLboolean unpack_flip_y
,
13047 GLboolean unpack_premultiply_alpha
,
13048 GLboolean unpack_unmultiply_alpha
) {
13049 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
13051 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13052 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13053 Texture
* source_texture
= source_texture_ref
->texture();
13054 Texture
* dest_texture
= dest_texture_ref
->texture();
13055 int source_width
= 0;
13056 int source_height
= 0;
13057 gfx::GLImage
* image
=
13058 source_texture
->GetLevelImage(source_texture
->target(), 0);
13060 gfx::Size size
= image
->GetSize();
13061 source_width
= size
.width();
13062 source_height
= size
.height();
13063 if (source_width
<= 0 || source_height
<= 0) {
13064 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13065 "invalid image size");
13069 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13070 &source_width
, &source_height
, nullptr)) {
13071 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13072 "source texture has no level 0");
13076 // Check that this type of texture is allowed.
13077 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13078 source_width
, source_height
, 1)) {
13079 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13080 "source texture bad dimensions");
13085 GLenum source_type
= 0;
13086 GLenum source_internal_format
= 0;
13087 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
13088 &source_internal_format
);
13089 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
13090 width
, height
, 1)) {
13091 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13092 "source texture bad dimensions.");
13096 GLenum dest_type
= 0;
13097 GLenum dest_internal_format
= 0;
13098 bool dest_level_defined
= dest_texture
->GetLevelType(
13099 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
13100 if (!dest_level_defined
) {
13101 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
13102 "destination texture is not defined");
13105 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
13106 yoffset
, 0, width
, height
, 1)) {
13107 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13108 "destination texture bad dimensions.");
13112 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
13113 source_texture_ref
, dest_texture_ref
,
13114 dest_internal_format
)) {
13118 // Clear the source texture if necessary.
13119 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13120 source_texture
->target(), 0)) {
13121 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
13122 "source texture dimensions too big");
13126 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13127 // needed because it takes 10s of milliseconds to initialize.
13128 if (!copy_texture_CHROMIUM_
.get()) {
13129 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
13130 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13131 copy_texture_CHROMIUM_
->Initialize(this);
13132 RestoreCurrentFramebufferBindings();
13133 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
13137 int dest_width
= 0;
13138 int dest_height
= 0;
13139 bool ok
= dest_texture
->GetLevelSize(
13140 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13142 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
13143 height
!= dest_height
) {
13144 gfx::Rect cleared_rect
;
13145 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
13146 gfx::Rect(xoffset
, yoffset
, width
, height
),
13148 DCHECK_GE(cleared_rect
.size().GetArea(),
13149 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
13150 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
13153 // Otherwise clear part of texture level that is not already cleared.
13154 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
13156 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
13157 "destination texture dimensions too big");
13162 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13166 ScopedModifyPixels
modify(dest_texture_ref
);
13168 // Try using GLImage::CopyTexSubImage when possible.
13169 bool unpack_premultiply_alpha_change
=
13170 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
13171 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
13172 ScopedTextureBinder
binder(
13173 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13174 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
13175 gfx::Rect(x
, y
, width
, height
))) {
13180 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13182 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13183 // crbug.com/226218.
13184 copy_texture_CHROMIUM_
->DoCopySubTexture(
13185 this, source_texture
->target(), source_texture
->service_id(),
13186 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
13187 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13188 source_width
, source_height
,
13189 unpack_flip_y
== GL_TRUE
,
13190 unpack_premultiply_alpha
== GL_TRUE
,
13191 unpack_unmultiply_alpha
== GL_TRUE
);
13193 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13196 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
13199 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
13201 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13202 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13203 Texture
* source_texture
= source_texture_ref
->texture();
13204 Texture
* dest_texture
= dest_texture_ref
->texture();
13205 int source_width
= 0;
13206 int source_height
= 0;
13207 gfx::GLImage
* image
=
13208 source_texture
->GetLevelImage(source_texture
->target(), 0);
13210 gfx::Size size
= image
->GetSize();
13211 source_width
= size
.width();
13212 source_height
= size
.height();
13213 if (source_width
<= 0 || source_height
<= 0) {
13214 LOCAL_SET_GL_ERROR(
13216 "glCompressedCopyTextureCHROMIUM", "invalid image size");
13220 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13221 &source_width
, &source_height
, nullptr)) {
13222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
13223 "glCompressedCopyTextureCHROMIUM",
13224 "source texture has no level 0");
13228 // Check that this type of texture is allowed.
13229 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13230 source_width
, source_height
, 1)) {
13231 LOCAL_SET_GL_ERROR(
13232 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
13238 GLenum source_type
= 0;
13239 GLenum source_internal_format
= 0;
13240 source_texture
->GetLevelType(
13241 source_texture
->target(), 0, &source_type
, &source_internal_format
);
13243 if (dest_texture
->IsImmutable()) {
13244 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13245 "glCompressedCopyTextureCHROMIUM",
13246 "texture is immutable");
13250 if (!ValidateCompressedCopyTextureCHROMIUM(
13251 "glCompressedCopyTextureCHROMIUM",
13253 source_texture_ref
, dest_texture_ref
)) {
13257 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13258 // needed because it takes 10s of milliseconds to initialize.
13259 if (!copy_texture_CHROMIUM_
.get()) {
13260 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
13261 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13262 copy_texture_CHROMIUM_
->Initialize(this);
13263 RestoreCurrentFramebufferBindings();
13264 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
13268 // Clear the source texture if necessary.
13269 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13270 source_texture
->target(), 0)) {
13271 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
13272 "dimensions too big");
13276 ScopedTextureBinder
binder(
13277 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13279 ScopedModifyPixels
modify(dest_texture_ref
);
13281 // Try using GLImage::CopyTexImage when possible.
13283 GLenum dest_type
= 0;
13284 GLenum dest_internal_format
= 0;
13285 int dest_width
= 0;
13286 int dest_height
= 0;
13287 bool dest_level_defined
= dest_texture
->GetLevelSize(
13288 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13290 if (dest_level_defined
) {
13291 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
13292 &dest_internal_format
);
13295 // Resize the destination texture to the dimensions of the source texture.
13296 if (!dest_level_defined
|| dest_width
!= source_width
||
13297 dest_height
!= source_height
||
13298 dest_internal_format
!= source_internal_format
) {
13299 GLsizei source_size
= 0;
13301 bool did_get_size
= GetCompressedTexSizeInBytes(
13302 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
13303 1, source_internal_format
, &source_size
);
13304 DCHECK(did_get_size
);
13306 // Ensure that the glCompressedTexImage2D succeeds.
13307 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13308 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
13309 source_width
, source_height
, 0, source_size
,
13311 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13312 if (error
!= GL_NO_ERROR
) {
13313 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
13317 texture_manager()->SetLevelInfo(
13318 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
13319 source_width
, source_height
, 1, 0, source_internal_format
,
13320 source_type
, gfx::Rect(source_width
, source_height
));
13322 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13326 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
13327 gfx::Rect(0, 0, source_width
, source_height
))) {
13334 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
13336 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13338 // As a fallback, copy into a non-compressed GL_RGBA texture.
13339 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13340 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
13341 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
13342 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13343 if (error
!= GL_NO_ERROR
) {
13344 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
13348 texture_manager()->SetLevelInfo(
13349 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
13350 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
13351 gfx::Rect(source_width
, source_height
));
13353 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13354 // before presenting.
13355 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
13356 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13357 // instead of using kIdentityMatrix crbug.com/226218.
13358 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
13359 this, source_texture
->target(), source_texture
->service_id(),
13360 dest_texture
->service_id(), source_width
, source_height
,
13361 false, false, false, kIdentityMatrix
);
13363 copy_texture_CHROMIUM_
->DoCopyTexture(
13364 this, source_texture
->target(), source_texture
->service_id(),
13365 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13366 source_width
, source_height
, false, false, false);
13369 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13372 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target
,
13381 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
13383 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13384 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13385 Texture
* source_texture
= source_texture_ref
->texture();
13386 Texture
* dest_texture
= dest_texture_ref
->texture();
13387 int source_width
= 0;
13388 int source_height
= 0;
13389 gfx::GLImage
* image
=
13390 source_texture
->GetLevelImage(source_texture
->target(), 0);
13392 gfx::Size size
= image
->GetSize();
13393 source_width
= size
.width();
13394 source_height
= size
.height();
13395 if (source_width
<= 0 || source_height
<= 0) {
13396 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13397 "invalid image size");
13401 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13402 &source_width
, &source_height
, nullptr)) {
13403 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13404 "source texture has no level 0");
13408 // Check that this type of texture is allowed.
13409 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13410 source_width
, source_height
, 1)) {
13411 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13412 "source texture bad dimensions");
13417 GLenum source_type
= 0;
13418 GLenum source_internal_format
= 0;
13419 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
13420 &source_internal_format
);
13421 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
13422 width
, height
, 1)) {
13423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13424 "source texture bad dimensions.");
13428 GLenum dest_type
= 0;
13429 GLenum dest_internal_format
= 0;
13430 bool dest_level_defined
= dest_texture
->GetLevelType(
13431 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
13432 if (!dest_level_defined
) {
13433 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13434 "glCompressedCopySubTextureCHROMIUM",
13435 "destination texture is not defined");
13438 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
13439 yoffset
, 0, width
, height
, 1)) {
13440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13441 "destination texture bad dimensions.");
13445 if (!ValidateCompressedCopyTextureCHROMIUM(
13446 "glCompressedCopySubTextureCHROMIUM", target
, source_texture_ref
,
13447 dest_texture_ref
)) {
13451 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13452 source_texture
->target(), 0, x
, y
, 0,
13454 source_internal_format
,
13456 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13457 dest_texture
->target(), 0,
13458 xoffset
, yoffset
, 0, width
, height
, 1,
13459 dest_internal_format
,
13464 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13465 // needed because it takes 10s of milliseconds to initialize.
13466 if (!copy_texture_CHROMIUM_
.get()) {
13467 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
13468 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13469 copy_texture_CHROMIUM_
->Initialize(this);
13470 RestoreCurrentFramebufferBindings();
13471 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
13477 // Clear the source texture if necessary.
13478 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13479 source_texture
->target(), 0)) {
13480 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopySubTextureCHROMIUM",
13481 "source texture dimensions too big");
13485 int dest_width
= 0;
13486 int dest_height
= 0;
13487 bool ok
= dest_texture
->GetLevelSize(
13488 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13490 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
13491 height
!= dest_height
) {
13492 gfx::Rect cleared_rect
;
13493 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
13494 gfx::Rect(xoffset
, yoffset
, width
, height
),
13496 DCHECK_GE(cleared_rect
.size().GetArea(),
13497 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
13498 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
13501 // Otherwise clear part of texture level that is not already cleared.
13502 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
13504 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
,
13505 "glCompressedCopySubTextureCHROMIUM",
13506 "destination texture dimensions too big");
13511 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13515 ScopedTextureBinder
binder(
13516 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13518 ScopedModifyPixels
modify(dest_texture_ref
);
13520 // Try using GLImage::CopyTexSubImage when possible.
13522 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
13523 gfx::Rect(x
, y
, width
, height
))) {
13530 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
13532 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13534 // As a fallback, copy into a non-compressed GL_RGBA texture.
13535 if (dest_internal_format
!= GL_RGBA
) {
13536 // To preserve the contents of the original destination texture we must
13537 // first copy the original destination texture to a temporary storage, then
13538 // copy it back to the original destination texture.
13539 GLuint tmp_service_id
;
13540 glGenTextures(1, &tmp_service_id
);
13541 DCHECK_NE(0u, tmp_service_id
);
13543 glBindTexture(GL_TEXTURE_2D
, tmp_service_id
);
13545 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13546 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13547 GL_UNSIGNED_BYTE
, NULL
);
13548 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13549 if (error
!= GL_NO_ERROR
)
13552 copy_texture_CHROMIUM_
->DoCopyTexture(
13553 this, dest_texture
->target(), dest_texture
->service_id(),
13554 dest_internal_format
, tmp_service_id
, GL_RGBA
,
13555 dest_width
, dest_height
, false, false, false);
13557 // Redefine destination texture to use RGBA.
13558 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13559 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13560 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13561 GL_UNSIGNED_BYTE
, NULL
);
13562 error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13563 if (error
!= GL_NO_ERROR
)
13566 texture_manager()->SetLevelInfo(
13567 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
,
13568 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(dest_width
, dest_height
));
13570 copy_texture_CHROMIUM_
->DoCopyTexture(
13571 this, GL_TEXTURE_2D
, tmp_service_id
, GL_RGBA
,
13572 dest_texture
->service_id(), GL_RGBA
,
13573 dest_width
, dest_height
, false, false, false);
13575 glDeleteTextures(1, &tmp_service_id
);
13578 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13579 // crbug.com/226218.
13580 copy_texture_CHROMIUM_
->DoCopySubTexture(
13581 this, source_texture
->target(), source_texture
->service_id(),
13582 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13583 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13584 source_width
, source_height
, false, false, false);
13586 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13589 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
13590 switch (internalformat
) {
13592 return GL_UNSIGNED_BYTE
;
13596 return GL_HALF_FLOAT
;
13600 return GL_UNSIGNED_BYTE
;
13604 return GL_UNSIGNED_SHORT
;
13608 return GL_UNSIGNED_INT
;
13612 return GL_UNSIGNED_BYTE
;
13616 return GL_HALF_FLOAT
;
13620 return GL_UNSIGNED_BYTE
;
13624 return GL_UNSIGNED_SHORT
;
13628 return GL_UNSIGNED_INT
;
13633 return GL_UNSIGNED_BYTE
;
13634 case GL_R11F_G11F_B10F
:
13635 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
13637 return GL_UNSIGNED_SHORT_5_6_5
;
13638 case GL_RGB8_SNORM
:
13641 return GL_UNSIGNED_INT_5_9_9_9_REV
;
13643 return GL_HALF_FLOAT
;
13647 return GL_UNSIGNED_BYTE
;
13651 return GL_UNSIGNED_SHORT
;
13655 return GL_UNSIGNED_INT
;
13659 return GL_UNSIGNED_BYTE
;
13660 case GL_SRGB8_ALPHA8
:
13661 return GL_UNSIGNED_BYTE
;
13662 case GL_RGBA8_SNORM
:
13665 return GL_UNSIGNED_SHORT_4_4_4_4
;
13667 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13669 return GL_UNSIGNED_SHORT_5_5_5_1
;
13671 return GL_HALF_FLOAT
;
13675 return GL_UNSIGNED_BYTE
;
13678 case GL_RGB10_A2UI
:
13679 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13681 return GL_UNSIGNED_SHORT
;
13687 return GL_UNSIGNED_INT
;
13688 case GL_DEPTH_COMPONENT16
:
13689 return GL_UNSIGNED_SHORT
;
13690 case GL_DEPTH_COMPONENT24
:
13691 return GL_UNSIGNED_INT
;
13692 case GL_DEPTH_COMPONENT32F
:
13694 case GL_DEPTH24_STENCIL8
:
13695 return GL_UNSIGNED_INT_24_8
;
13696 case GL_DEPTH32F_STENCIL8
:
13697 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
13698 case GL_LUMINANCE8_ALPHA8_EXT
:
13699 return GL_UNSIGNED_BYTE
;
13700 case GL_LUMINANCE8_EXT
:
13701 return GL_UNSIGNED_BYTE
;
13702 case GL_ALPHA8_EXT
:
13703 return GL_UNSIGNED_BYTE
;
13704 case GL_ALPHA32F_EXT
:
13706 case GL_LUMINANCE32F_EXT
:
13708 case GL_LUMINANCE_ALPHA32F_EXT
:
13710 case GL_ALPHA16F_EXT
:
13711 return GL_HALF_FLOAT_OES
;
13712 case GL_LUMINANCE16F_EXT
:
13713 return GL_HALF_FLOAT_OES
;
13714 case GL_LUMINANCE_ALPHA16F_EXT
:
13715 return GL_HALF_FLOAT_OES
;
13717 return GL_UNSIGNED_BYTE
;
13723 void GLES2DecoderImpl::DoTexStorage2DEXT(
13726 GLenum internal_format
,
13729 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13730 "width", width
, "height", height
);
13731 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
13732 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
13733 LOCAL_SET_GL_ERROR(
13734 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
13737 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13739 if (!texture_ref
) {
13740 LOCAL_SET_GL_ERROR(
13741 GL_INVALID_OPERATION
,
13742 "glTexStorage2DEXT", "unknown texture for target");
13745 Texture
* texture
= texture_ref
->texture();
13746 if (texture
->IsAttachedToFramebuffer()) {
13747 framebuffer_state_
.clear_state_dirty
= true;
13749 if (texture
->IsImmutable()) {
13750 LOCAL_SET_GL_ERROR(
13751 GL_INVALID_OPERATION
,
13752 "glTexStorage2DEXT", "texture is immutable");
13756 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
13757 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
13760 GLsizei level_width
= width
;
13761 GLsizei level_height
= height
;
13762 uint32 estimated_size
= 0;
13763 for (int ii
= 0; ii
< levels
; ++ii
) {
13764 uint32 level_size
= 0;
13765 if (!GLES2Util::ComputeImageDataSizes(
13766 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
13767 &estimated_size
, NULL
, NULL
) ||
13768 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
13769 LOCAL_SET_GL_ERROR(
13770 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
13773 level_width
= std::max(1, level_width
>> 1);
13774 level_height
= std::max(1, level_height
>> 1);
13776 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
13777 LOCAL_SET_GL_ERROR(
13778 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
13783 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13784 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
13785 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13786 if (error
== GL_NO_ERROR
) {
13787 GLsizei level_width
= width
;
13788 GLsizei level_height
= height
;
13790 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
13791 internal_format
: format
;
13792 for (int ii
= 0; ii
< levels
; ++ii
) {
13793 if (target
== GL_TEXTURE_CUBE_MAP
) {
13794 for (int jj
= 0; jj
< 6; ++jj
) {
13795 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
13796 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
13797 level_width
, level_height
, 1, 0,
13798 format
, type
, gfx::Rect());
13801 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
13802 level_width
, level_height
, 1, 0,
13803 format
, type
, gfx::Rect());
13805 level_width
= std::max(1, level_width
>> 1);
13806 level_height
= std::max(1, level_height
>> 1);
13808 texture
->SetImmutable(true);
13812 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13813 uint32 immediate_data_size
,
13814 const void* cmd_data
) {
13815 return error::kUnknownCommand
;
13818 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
13819 const GLbyte
* data
) {
13820 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13821 "context", logger_
.GetLogPrefix(),
13822 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13824 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13826 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
13829 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
13830 GLenum target
, const GLbyte
* data
) {
13831 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13832 "context", logger_
.GetLogPrefix(),
13833 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13835 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
13839 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name
,
13840 TextureRef
* texture_ref
, GLenum target
, const GLbyte
* data
) {
13841 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13842 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
13843 "mailbox that was not generated by "
13844 "GenMailboxCHROMIUM.";
13846 if (!texture_ref
) {
13847 LOCAL_SET_GL_ERROR(
13848 GL_INVALID_OPERATION
, func_name
.c_str(), "unknown texture for target");
13852 Texture
* produced
= texture_manager()->Produce(texture_ref
);
13854 LOCAL_SET_GL_ERROR(
13855 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid texture");
13859 if (produced
->target() != target
) {
13860 LOCAL_SET_GL_ERROR(
13861 GL_INVALID_OPERATION
, func_name
.c_str(), "invalid target");
13865 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13868 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13869 const GLbyte
* data
) {
13870 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13871 "context", logger_
.GetLogPrefix(),
13872 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13873 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13874 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13875 "mailbox that was not generated by "
13876 "GenMailboxCHROMIUM.";
13878 scoped_refptr
<TextureRef
> texture_ref
=
13879 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13880 if (!texture_ref
.get()) {
13881 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13882 "glConsumeTextureCHROMIUM",
13883 "unknown texture for target");
13886 GLuint client_id
= texture_ref
->client_id();
13888 LOCAL_SET_GL_ERROR(
13889 GL_INVALID_OPERATION
,
13890 "glConsumeTextureCHROMIUM", "unknown texture for target");
13893 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13895 LOCAL_SET_GL_ERROR(
13896 GL_INVALID_OPERATION
,
13897 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13900 if (texture
->target() != target
) {
13901 LOCAL_SET_GL_ERROR(
13902 GL_INVALID_OPERATION
,
13903 "glConsumeTextureCHROMIUM", "invalid target");
13907 DeleteTexturesHelper(1, &client_id
);
13908 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13909 glBindTexture(target
, texture_ref
->service_id());
13911 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13912 unit
.bind_target
= target
;
13914 case GL_TEXTURE_2D
:
13915 unit
.bound_texture_2d
= texture_ref
;
13917 case GL_TEXTURE_CUBE_MAP
:
13918 unit
.bound_texture_cube_map
= texture_ref
;
13920 case GL_TEXTURE_EXTERNAL_OES
:
13921 unit
.bound_texture_external_oes
= texture_ref
;
13923 case GL_TEXTURE_RECTANGLE_ARB
:
13924 unit
.bound_texture_rectangle_arb
= texture_ref
;
13927 NOTREACHED(); // Validation should prevent us getting here.
13932 void GLES2DecoderImpl::EnsureTextureForClientId(
13934 GLuint client_id
) {
13935 TextureRef
* texture_ref
= GetTexture(client_id
);
13936 if (!texture_ref
) {
13938 glGenTextures(1, &service_id
);
13939 DCHECK_NE(0u, service_id
);
13940 texture_ref
= CreateTexture(client_id
, service_id
);
13941 texture_manager()->SetTarget(texture_ref
, target
);
13942 glBindTexture(target
, service_id
);
13943 RestoreCurrentTextureBindings(&state_
, target
);
13947 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13948 // provided is associated with a service_id/TextureRef for consistency, even if
13949 // the resulting texture is incomplete.
13950 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13951 uint32_t immediate_data_size
,
13952 const void* cmd_data
) {
13953 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13955 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13957 GLenum target
= static_cast<GLenum
>(c
.target
);
13958 uint32_t data_size
;
13959 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13960 return error::kOutOfBounds
;
13962 if (data_size
> immediate_data_size
) {
13963 return error::kOutOfBounds
;
13965 const GLbyte
* mailbox
=
13966 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13967 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13968 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13969 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13970 return error::kNoError
;
13972 if (mailbox
== NULL
) {
13973 return error::kOutOfBounds
;
13975 uint32_t client_id
= c
.client_id
;
13976 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13977 return error::kNoError
;
13980 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13981 const GLbyte
* data
, GLuint client_id
) {
13982 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13983 "context", logger_
.GetLogPrefix(),
13984 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13985 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13986 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13987 "passed a mailbox that was not "
13988 "generated by GenMailboxCHROMIUM.";
13990 TextureRef
* texture_ref
= GetTexture(client_id
);
13992 // No need to call EnsureTextureForClientId here, the client_id already has
13993 // an associated texture.
13994 LOCAL_SET_GL_ERROR(
13995 GL_INVALID_OPERATION
,
13996 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13999 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
14001 EnsureTextureForClientId(target
, client_id
);
14002 LOCAL_SET_GL_ERROR(
14003 GL_INVALID_OPERATION
,
14004 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
14008 if (texture
->target() != target
) {
14009 EnsureTextureForClientId(target
, client_id
);
14010 LOCAL_SET_GL_ERROR(
14011 GL_INVALID_OPERATION
,
14012 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
14016 texture_ref
= texture_manager()->Consume(client_id
, texture
);
14019 void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() {
14020 // Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the
14021 // color attachments of currently bound draw framebuffer.
14022 // Reference GL_INTEL_framebuffer_CMAA for details.
14023 glApplyFramebufferAttachmentCMAAINTEL();
14026 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
14027 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
14028 return valuebuffer
&& valuebuffer
->IsValid();
14031 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
14032 GLuint client_id
) {
14033 Valuebuffer
* valuebuffer
= NULL
;
14034 if (client_id
!= 0) {
14035 valuebuffer
= GetValuebuffer(client_id
);
14036 if (!valuebuffer
) {
14037 if (!group_
->bind_generates_resource()) {
14038 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
14039 "id not generated by glBindValuebufferCHROMIUM");
14043 // It's a new id so make a valuebuffer for it.
14044 CreateValuebuffer(client_id
);
14045 valuebuffer
= GetValuebuffer(client_id
);
14047 valuebuffer
->MarkAsValid();
14049 state_
.bound_valuebuffer
= valuebuffer
;
14052 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
14053 GLenum subscription
) {
14054 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
14057 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
14060 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
14061 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
14064 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
14067 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
14069 GLenum subscription
) {
14070 if (!CheckCurrentValuebufferForSubscription(
14071 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
14074 if (!CheckSubscriptionTarget(location
, subscription
,
14075 "glPopulateSubscribedValuesCHROMIUM")) {
14078 const ValueState
* state
=
14079 state_
.bound_valuebuffer
.get()->GetState(subscription
);
14081 switch (subscription
) {
14082 case GL_MOUSE_POSITION_CHROMIUM
:
14083 DoUniform2iv(location
, 1, state
->int_value
);
14086 NOTREACHED() << "Unhandled uniform subscription target "
14093 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
14094 GLsizei length
, const GLchar
* marker
) {
14098 debug_marker_manager_
.SetMarker(
14099 length
? std::string(marker
, length
) : std::string(marker
));
14102 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
14103 GLsizei
/*length*/, const GLchar
* /*marker*/) {
14106 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
14109 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
14110 GLenum target
, GLint image_id
) {
14111 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
14113 if (target
== GL_TEXTURE_CUBE_MAP
) {
14114 LOCAL_SET_GL_ERROR(
14116 "glBindTexImage2DCHROMIUM", "invalid target");
14120 // Default target might be conceptually valid, but disallow it to avoid
14122 TextureRef
* texture_ref
=
14123 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
14124 if (!texture_ref
) {
14125 LOCAL_SET_GL_ERROR(
14126 GL_INVALID_OPERATION
,
14127 "glBindTexImage2DCHROMIUM", "no texture bound");
14131 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
14133 LOCAL_SET_GL_ERROR(
14134 GL_INVALID_OPERATION
,
14135 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
14140 ScopedGLErrorSuppressor
suppressor(
14141 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
14142 if (!gl_image
->BindTexImage(target
)) {
14143 LOCAL_SET_GL_ERROR(
14144 GL_INVALID_OPERATION
,
14145 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
14150 gfx::Size size
= gl_image
->GetSize();
14151 texture_manager()->SetLevelInfo(
14152 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
14153 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
14155 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
14158 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
14159 GLenum target
, GLint image_id
) {
14160 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
14162 // Default target might be conceptually valid, but disallow it to avoid
14164 TextureRef
* texture_ref
=
14165 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
14166 if (!texture_ref
) {
14167 LOCAL_SET_GL_ERROR(
14168 GL_INVALID_OPERATION
,
14169 "glReleaseTexImage2DCHROMIUM", "no texture bound");
14173 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
14175 LOCAL_SET_GL_ERROR(
14176 GL_INVALID_OPERATION
,
14177 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
14181 // Do nothing when image is not currently bound.
14182 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
14186 ScopedGLErrorSuppressor
suppressor(
14187 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
14188 gl_image
->ReleaseTexImage(target
);
14191 texture_manager()->SetLevelInfo(
14192 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
14193 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
14196 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
14197 uint32 immediate_data_size
,
14198 const void* cmd_data
) {
14199 const gles2::cmds::TraceBeginCHROMIUM
& c
=
14200 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
14201 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
14202 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
14203 if (!category_bucket
|| category_bucket
->size() == 0 ||
14204 !name_bucket
|| name_bucket
->size() == 0) {
14205 return error::kInvalidArguments
;
14208 std::string category_name
;
14209 std::string trace_name
;
14210 if (!category_bucket
->GetAsString(&category_name
) ||
14211 !name_bucket
->GetAsString(&trace_name
)) {
14212 return error::kInvalidArguments
;
14215 debug_marker_manager_
.PushGroup(trace_name
);
14216 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
14217 LOCAL_SET_GL_ERROR(
14218 GL_INVALID_OPERATION
,
14219 "glTraceBeginCHROMIUM", "unable to create begin trace");
14220 return error::kNoError
;
14222 return error::kNoError
;
14225 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
14226 debug_marker_manager_
.PopGroup();
14227 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
14228 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14229 "glTraceEndCHROMIUM", "no trace begin found");
14234 void GLES2DecoderImpl::DoDrawBuffersEXT(
14235 GLsizei count
, const GLenum
* bufs
) {
14236 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
14237 LOCAL_SET_GL_ERROR(
14239 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
14243 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
14245 for (GLsizei i
= 0; i
< count
; ++i
) {
14246 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
14247 bufs
[i
] != GL_NONE
) {
14248 LOCAL_SET_GL_ERROR(
14249 GL_INVALID_OPERATION
,
14250 "glDrawBuffersEXT",
14251 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
14255 glDrawBuffersARB(count
, bufs
);
14256 framebuffer
->SetDrawBuffers(count
, bufs
);
14257 } else { // backbuffer
14259 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
14260 LOCAL_SET_GL_ERROR(
14261 GL_INVALID_OPERATION
,
14262 "glDrawBuffersEXT",
14263 "more than one buffer or bufs not GL_NONE or GL_BACK");
14266 GLenum mapped_buf
= bufs
[0];
14267 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
14268 bufs
[0] == GL_BACK
) {
14269 mapped_buf
= GL_COLOR_ATTACHMENT0
;
14271 glDrawBuffersARB(count
, &mapped_buf
);
14272 back_buffer_draw_buffer_
= bufs
[0];
14276 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
14277 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
14278 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
14279 reset_by_robustness_extension_
= true;
14282 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
14283 // On Adreno Android devices we need to use a workaround to force caches to
14285 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
14286 context_
->ReleaseCurrent(nullptr);
14287 context_
->MakeCurrent(surface_
.get());
14291 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
14292 const GLfloat
* matrix
) {
14293 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
14294 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
14295 if (!features().chromium_path_rendering
) {
14296 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14297 "glMatrixLoadfCHROMIUM",
14298 "function not available");
14302 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
14303 ? state_
.projection_matrix
14304 : state_
.modelview_matrix
;
14305 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
14306 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14307 // since the values of the _NV and _CHROMIUM tokens match.
14308 glMatrixLoadfEXT(matrix_mode
, matrix
);
14311 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
14312 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
14313 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
14315 if (!features().chromium_path_rendering
) {
14316 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14317 "glMatrixLoadIdentityCHROMIUM",
14318 "function not available");
14322 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
14323 ? state_
.projection_matrix
14324 : state_
.modelview_matrix
;
14325 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
14326 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14327 // since the values of the _NV and _CHROMIUM tokens match.
14328 glMatrixLoadIdentityEXT(matrix_mode
);
14331 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
14332 uint32_t immediate_data_size
, const void* cmd_data
) {
14333 if (!unsafe_es3_apis_enabled())
14334 return error::kUnknownCommand
;
14335 const gles2::cmds::UniformBlockBinding
& c
=
14336 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
14337 GLuint client_id
= c
.program
;
14338 GLuint index
= static_cast<GLuint
>(c
.index
);
14339 GLuint binding
= static_cast<GLuint
>(c
.binding
);
14340 Program
* program
= GetProgramInfoNotShader(
14341 client_id
, "glUniformBlockBinding");
14343 return error::kNoError
;
14345 GLuint service_id
= program
->service_id();
14346 glUniformBlockBinding(service_id
, index
, binding
);
14347 return error::kNoError
;
14350 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
14351 uint32_t immediate_data_size
, const void* cmd_data
) {
14352 if (!unsafe_es3_apis_enabled())
14353 return error::kUnknownCommand
;
14354 const gles2::cmds::ClientWaitSync
& c
=
14355 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
14356 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14357 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14358 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14359 typedef cmds::ClientWaitSync::Result Result
;
14360 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
14361 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
14363 return error::kOutOfBounds
;
14365 if (*result_dst
!= GL_WAIT_FAILED
) {
14366 return error::kInvalidArguments
;
14368 GLsync service_sync
= 0;
14369 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14370 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
14371 return error::kNoError
;
14373 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
14374 return error::kNoError
;
14377 error::Error
GLES2DecoderImpl::HandleWaitSync(
14378 uint32_t immediate_data_size
, const void* cmd_data
) {
14379 if (!unsafe_es3_apis_enabled())
14380 return error::kUnknownCommand
;
14381 const gles2::cmds::WaitSync
& c
=
14382 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
14383 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14384 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14385 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14386 GLsync service_sync
= 0;
14387 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14388 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
14389 return error::kNoError
;
14391 glWaitSync(service_sync
, flags
, timeout
);
14392 return error::kNoError
;
14395 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
14396 uint32_t immediate_data_size
, const void* cmd_data
) {
14397 if (!unsafe_es3_apis_enabled())
14398 return error::kUnknownCommand
;
14399 const gles2::cmds::GetInternalformativ
& c
=
14400 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
14401 GLenum target
= static_cast<GLenum
>(c
.target
);
14402 GLenum format
= static_cast<GLenum
>(c
.format
);
14403 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14404 if (!validators_
->render_buffer_target
.IsValid(target
)) {
14405 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
14406 return error::kNoError
;
14408 if (!validators_
->render_buffer_format
.IsValid(format
)) {
14409 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
14410 return error::kNoError
;
14412 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
14413 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
14414 return error::kNoError
;
14416 typedef cmds::GetInternalformativ::Result Result
;
14417 GLsizei num_values
= 0;
14419 case GL_NUM_SAMPLE_COUNTS
:
14425 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
14426 num_values
= static_cast<GLsizei
>(value
);
14433 Result
* result
= GetSharedMemoryAs
<Result
*>(
14434 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
14435 GLint
* params
= result
? result
->GetData() : NULL
;
14436 if (params
== NULL
) {
14437 return error::kOutOfBounds
;
14439 // Check that the client initialized the result.
14440 if (result
->size
!= 0) {
14441 return error::kInvalidArguments
;
14443 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
14444 result
->SetNumResults(num_values
);
14445 return error::kNoError
;
14448 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
14449 uint32_t immediate_data_size
, const void* cmd_data
) {
14450 if (!unsafe_es3_apis_enabled()) {
14451 return error::kUnknownCommand
;
14453 const gles2::cmds::MapBufferRange
& c
=
14454 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
14455 GLenum target
= static_cast<GLenum
>(c
.target
);
14456 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
14457 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
14458 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
14460 typedef cmds::MapBufferRange::Result Result
;
14461 Result
* result
= GetSharedMemoryAs
<Result
*>(
14462 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
14464 return error::kOutOfBounds
;
14466 if (*result
!= 0) {
14468 return error::kInvalidArguments
;
14471 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
14473 return error::kOutOfBounds
;
14476 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
14477 if ((access
& mask
) == mask
) {
14478 // TODO(zmo): To be on the safe side, always map
14479 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14480 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
14481 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
14483 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14484 // undefined behaviors.
14485 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
14486 if ((access
& mask
) == mask
) {
14487 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
14488 "incompatible access bits");
14489 return error::kNoError
;
14491 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
14492 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
14493 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14494 access
= (access
| GL_MAP_READ_BIT
);
14496 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
14497 if (ptr
== nullptr) {
14498 return error::kNoError
;
14500 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14502 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
14503 GetSharedMemoryBuffer(c
.data_shm_id
));
14504 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14505 memcpy(mem
, ptr
, size
);
14508 return error::kNoError
;
14511 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
14512 uint32_t immediate_data_size
, const void* cmd_data
) {
14513 if (!unsafe_es3_apis_enabled()) {
14514 return error::kUnknownCommand
;
14516 const gles2::cmds::UnmapBuffer
& c
=
14517 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
14518 GLenum target
= static_cast<GLenum
>(c
.target
);
14520 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
14523 return error::kNoError
;
14525 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
14526 if (!mapped_range
) {
14527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
14528 "buffer is unmapped");
14529 return error::kNoError
;
14531 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
14532 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
14533 GL_MAP_FLUSH_EXPLICIT_BIT
) {
14534 // If we don't need to write back, or explict flush is required, no copying
14537 void* mem
= mapped_range
->GetShmPointer();
14539 return error::kOutOfBounds
;
14541 DCHECK(mapped_range
->pointer
);
14542 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
14544 buffer
->RemoveMappedRange();
14545 GLboolean rt
= glUnmapBuffer(target
);
14546 if (rt
== GL_FALSE
) {
14547 // At this point, we have already done the necessary validation, so
14548 // GL_FALSE indicates data corruption.
14549 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14550 // the second unmap could still return GL_FALSE. For now, we simply lose
14551 // the contexts in the share group.
14552 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14553 // Need to lose current context before broadcasting!
14554 MarkContextLost(error::kGuilty
);
14555 group_
->LoseContexts(error::kInnocent
);
14556 return error::kLostContext
;
14558 return error::kNoError
;
14561 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14562 TextureRef
* texture_ref
) {
14563 Texture
* texture
= texture_ref
->texture();
14564 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14567 // Note that GL_LOST_CONTEXT is specific to GLES.
14568 // For desktop GL we have to query the reset status proactively.
14569 void GLES2DecoderImpl::OnContextLostError() {
14570 if (!WasContextLost()) {
14571 // Need to lose current context before broadcasting!
14572 CheckResetStatus();
14573 group_
->LoseContexts(error::kUnknown
);
14574 reset_by_robustness_extension_
= true;
14578 void GLES2DecoderImpl::OnOutOfMemoryError() {
14579 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14580 error::ContextLostReason other
= error::kOutOfMemory
;
14581 if (CheckResetStatus()) {
14582 other
= error::kUnknown
;
14584 // Need to lose current context before broadcasting!
14585 MarkContextLost(error::kOutOfMemory
);
14587 group_
->LoseContexts(other
);
14591 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14592 uint32 immediate_data_size
,
14593 const void* cmd_data
) {
14594 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14595 const gles2::cmds::GenPathsCHROMIUM
& c
=
14596 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14597 if (!features().chromium_path_rendering
) {
14598 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14599 "function not available");
14600 return error::kNoError
;
14603 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14605 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14606 return error::kNoError
;
14609 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14610 if (first_client_id
== 0)
14611 return error::kInvalidArguments
;
14614 return error::kNoError
;
14616 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14617 return error::kInvalidArguments
;
14619 return error::kNoError
;
14621 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14622 uint32_t immediate_data_size
,
14623 const void* cmd_data
) {
14624 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14625 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14626 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14627 if (!features().chromium_path_rendering
) {
14628 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14629 "function not available");
14630 return error::kNoError
;
14633 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14636 return error::kNoError
;
14640 return error::kNoError
;
14642 GLuint first_client_id
= c
.first_client_id
;
14643 // first_client_id can be 0, because non-existing path ids are skipped.
14645 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14646 return error::kInvalidArguments
;
14648 return error::kNoError
;
14651 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14652 uint32 immediate_data_size
,
14653 const void* cmd_data
) {
14654 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14655 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14656 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14657 if (!features().chromium_path_rendering
) {
14658 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14659 "function not available");
14660 return error::kNoError
;
14663 GLuint service_id
= 0;
14664 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14665 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14666 "invalid path name");
14667 return error::kNoError
;
14670 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14671 if (num_commands
< 0) {
14672 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14673 return error::kNoError
;
14676 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14677 if (num_coords
< 0) {
14678 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14679 return error::kNoError
;
14682 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14683 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14684 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14685 return error::kNoError
;
14688 const GLubyte
* commands
= NULL
;
14689 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14691 if (num_commands
> 0) {
14692 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14693 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14694 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14695 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14696 commands_shm_id
, commands_shm_offset
, num_commands
);
14699 return error::kOutOfBounds
;
14701 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14702 switch (commands
[i
]) {
14703 case GL_CLOSE_PATH_CHROMIUM
:
14704 // Close has no coords.
14706 case GL_MOVE_TO_CHROMIUM
:
14708 case GL_LINE_TO_CHROMIUM
:
14709 num_coords_expected
+= 2;
14711 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14712 num_coords_expected
+= 4;
14714 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14715 num_coords_expected
+= 6;
14717 case GL_CONIC_CURVE_TO_CHROMIUM
:
14718 num_coords_expected
+= 5;
14721 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14722 return error::kNoError
;
14727 if (!num_coords_expected
.IsValid() ||
14728 num_coords
!= num_coords_expected
.ValueOrDie()) {
14729 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14730 "numCoords does not match commands");
14731 return error::kNoError
;
14734 const void* coords
= NULL
;
14736 if (num_coords
> 0) {
14737 uint32 coords_size
= 0;
14738 uint32 coord_type_size
=
14739 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14740 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14741 return error::kOutOfBounds
;
14743 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14744 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14745 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14746 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14750 return error::kOutOfBounds
;
14753 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14756 return error::kNoError
;
14759 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14760 uint32 immediate_data_size
,
14761 const void* cmd_data
) {
14762 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14763 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14764 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14765 if (!features().chromium_path_rendering
) {
14766 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14767 "function not available");
14768 return error::kNoError
;
14770 GLuint service_id
= 0;
14771 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14772 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14773 "invalid path name");
14774 return error::kNoError
;
14777 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14778 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14779 bool hasValueError
= false;
14782 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14783 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14784 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14786 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14787 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14789 case GL_PATH_END_CAPS_CHROMIUM
:
14790 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14791 static_cast<GLint
>(value
));
14793 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14794 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14795 static_cast<GLint
>(value
));
14798 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14799 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14800 return error::kNoError
;
14802 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14804 if (hasValueError
) {
14805 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14806 return error::kNoError
;
14809 glPathParameterfNV(service_id
, pname
, value
);
14810 return error::kNoError
;
14813 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14814 uint32 immediate_data_size
,
14815 const void* cmd_data
) {
14816 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14817 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14818 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14819 if (!features().chromium_path_rendering
) {
14820 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14821 "function not available");
14822 return error::kNoError
;
14824 GLuint service_id
= 0;
14825 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14826 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14827 "invalid path name");
14828 return error::kNoError
;
14831 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14832 GLint value
= static_cast<GLint
>(c
.value
);
14833 bool hasValueError
= false;
14836 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14837 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14838 hasValueError
= value
< 0;
14840 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14841 value
= std::max(std::min(1, value
), 0);
14843 case GL_PATH_END_CAPS_CHROMIUM
:
14844 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14846 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14847 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14850 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14851 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14852 return error::kNoError
;
14854 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14856 if (hasValueError
) {
14857 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14858 return error::kNoError
;
14861 glPathParameteriNV(service_id
, pname
, value
);
14862 return error::kNoError
;
14865 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14866 uint32 immediate_data_size
,
14867 const void* cmd_data
) {
14868 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14869 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14870 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14871 if (!features().chromium_path_rendering
) {
14872 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14873 "function not available");
14874 return error::kNoError
;
14876 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14877 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14878 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14879 return error::kNoError
;
14881 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14882 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14883 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14884 GLES2Util::IsNPOT(mask
+ 1)) {
14885 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14886 "mask + 1 is not power of two");
14887 return error::kNoError
;
14889 GLuint service_id
= 0;
14890 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14891 // "If /path/ does not name an existing path object, the command does
14892 // nothing (and no error is generated)."
14893 // This holds for other rendering functions, too.
14894 return error::kNoError
;
14897 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14898 return error::kNoError
;
14901 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14902 uint32 immediate_data_size
,
14903 const void* cmd_data
) {
14904 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14905 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14906 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14907 if (!features().chromium_path_rendering
) {
14908 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14909 "function not available");
14910 return error::kNoError
;
14912 GLuint service_id
= 0;
14913 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14914 return error::kNoError
;
14916 GLint reference
= static_cast<GLint
>(c
.reference
);
14917 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14919 glStencilStrokePathNV(service_id
, reference
, mask
);
14920 return error::kNoError
;
14923 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14924 uint32 immediate_data_size
,
14925 const void* cmd_data
) {
14926 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14927 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14928 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14929 if (!features().chromium_path_rendering
) {
14930 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14931 "function not available");
14932 return error::kNoError
;
14934 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14935 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14936 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14937 return error::kNoError
;
14939 GLuint service_id
= 0;
14940 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14941 return error::kNoError
;
14944 glCoverFillPathNV(service_id
, cover_mode
);
14945 return error::kNoError
;
14948 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14949 uint32 immediate_data_size
,
14950 const void* cmd_data
) {
14951 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14952 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14953 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14954 if (!features().chromium_path_rendering
) {
14955 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14956 "function not available");
14957 return error::kNoError
;
14959 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14960 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14961 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14962 return error::kNoError
;
14964 GLuint service_id
= 0;
14965 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14966 return error::kNoError
;
14969 glCoverStrokePathNV(service_id
, cover_mode
);
14970 return error::kNoError
;
14973 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14974 uint32 immediate_data_size
,
14975 const void* cmd_data
) {
14976 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14977 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14978 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14980 if (!features().chromium_path_rendering
) {
14981 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14982 "function not available");
14983 return error::kNoError
;
14985 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14986 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14987 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14988 return error::kNoError
;
14990 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14991 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14992 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14993 GLES2Util::IsNPOT(mask
+ 1)) {
14994 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14995 "mask + 1 is not power of two");
14996 return error::kNoError
;
14998 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14999 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
15000 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
15001 return error::kNoError
;
15003 GLuint service_id
= 0;
15004 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
15005 return error::kNoError
;
15008 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
15009 return error::kNoError
;
15012 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
15013 uint32 immediate_data_size
,
15014 const void* cmd_data
) {
15015 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
15016 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
15017 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
15019 if (!features().chromium_path_rendering
) {
15020 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
15021 "function not available");
15022 return error::kNoError
;
15024 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
15025 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
15026 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
15027 return error::kNoError
;
15029 GLuint service_id
= 0;
15030 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
15031 return error::kNoError
;
15033 GLint reference
= static_cast<GLint
>(c
.reference
);
15034 GLuint mask
= static_cast<GLuint
>(c
.mask
);
15036 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
15037 return error::kNoError
;
15040 // Include the auto-generated part of this file. We split this because it means
15041 // we can easily edit the non-auto generated parts right here in this file
15042 // instead of having to edit some template or the code generator.
15043 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
15045 } // namespace gles2