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(const char* func_name
,
1058 TextureRef
* texture_ref
,
1060 const GLbyte
* data
);
1062 void EnsureTextureForClientId(GLenum target
, GLuint client_id
);
1063 void DoConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
);
1064 void DoCreateAndConsumeTextureCHROMIUM(GLenum target
, const GLbyte
* key
,
1066 void DoApplyScreenSpaceAntialiasingCHROMIUM();
1068 bool DoIsValuebufferCHROMIUM(GLuint client_id
);
1069 void DoBindValueBufferCHROMIUM(GLenum target
, GLuint valuebuffer
);
1070 void DoSubscribeValueCHROMIUM(GLenum target
, GLenum subscription
);
1071 void DoPopulateSubscribedValuesCHROMIUM(GLenum target
);
1072 void DoUniformValueBufferCHROMIUM(GLint location
,
1074 GLenum subscription
);
1076 void DoBindTexImage2DCHROMIUM(
1079 void DoReleaseTexImage2DCHROMIUM(
1083 void DoTraceEndCHROMIUM(void);
1085 void DoDrawBuffersEXT(GLsizei count
, const GLenum
* bufs
);
1087 void DoLoseContextCHROMIUM(GLenum current
, GLenum other
);
1089 void DoFlushDriverCachesCHROMIUM(void);
1091 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode
, const GLfloat
* matrix
);
1092 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
);
1094 // Creates a Program for the given program.
1095 Program
* CreateProgram(
1096 GLuint client_id
, GLuint service_id
) {
1097 return program_manager()->CreateProgram(client_id
, service_id
);
1100 // Gets the program info for the given program. Returns NULL if none exists.
1101 Program
* GetProgram(GLuint client_id
) {
1102 return program_manager()->GetProgram(client_id
);
1106 void LogClientServiceMapping(
1107 const char* /* function_name */,
1108 GLuint
/* client_id */,
1109 GLuint
/* service_id */) {
1111 template<typename T
>
1112 void LogClientServiceForInfo(
1113 T
* /* info */, GLuint
/* client_id */, const char* /* function_name */) {
1116 void LogClientServiceMapping(
1117 const char* function_name
, GLuint client_id
, GLuint service_id
) {
1118 if (service_logging_
) {
1119 VLOG(1) << "[" << logger_
.GetLogPrefix() << "] " << function_name
1120 << ": client_id = " << client_id
1121 << ", service_id = " << service_id
;
1124 template<typename T
>
1125 void LogClientServiceForInfo(
1126 T
* info
, GLuint client_id
, const char* function_name
) {
1128 LogClientServiceMapping(function_name
, client_id
, info
->service_id());
1133 // Gets the program info for the given program. If it's not a program
1134 // generates a GL error. Returns NULL if not program.
1135 Program
* GetProgramInfoNotShader(
1136 GLuint client_id
, const char* function_name
) {
1137 Program
* program
= GetProgram(client_id
);
1139 if (GetShader(client_id
)) {
1141 GL_INVALID_OPERATION
, function_name
, "shader passed for program");
1143 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown program");
1146 LogClientServiceForInfo(program
, client_id
, function_name
);
1151 // Creates a Shader for the given shader.
1152 Shader
* CreateShader(
1155 GLenum shader_type
) {
1156 return shader_manager()->CreateShader(
1157 client_id
, service_id
, shader_type
);
1160 // Gets the shader info for the given shader. Returns NULL if none exists.
1161 Shader
* GetShader(GLuint client_id
) {
1162 return shader_manager()->GetShader(client_id
);
1165 // Gets the shader info for the given shader. If it's not a shader generates a
1166 // GL error. Returns NULL if not shader.
1167 Shader
* GetShaderInfoNotProgram(
1168 GLuint client_id
, const char* function_name
) {
1169 Shader
* shader
= GetShader(client_id
);
1171 if (GetProgram(client_id
)) {
1173 GL_INVALID_OPERATION
, function_name
, "program passed for shader");
1176 GL_INVALID_VALUE
, function_name
, "unknown shader");
1179 LogClientServiceForInfo(shader
, client_id
, function_name
);
1183 // Creates a buffer info for the given buffer.
1184 void CreateBuffer(GLuint client_id
, GLuint service_id
) {
1185 return buffer_manager()->CreateBuffer(client_id
, service_id
);
1188 // Gets the buffer info for the given buffer.
1189 Buffer
* GetBuffer(GLuint client_id
) {
1190 Buffer
* buffer
= buffer_manager()->GetBuffer(client_id
);
1194 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1195 // on glDeleteBuffers so we can make sure the user does not try to render
1196 // with deleted buffers.
1197 void RemoveBuffer(GLuint client_id
);
1199 // Creates a framebuffer info for the given framebuffer.
1200 void CreateFramebuffer(GLuint client_id
, GLuint service_id
) {
1201 return framebuffer_manager()->CreateFramebuffer(client_id
, service_id
);
1204 // Gets the framebuffer info for the given framebuffer.
1205 Framebuffer
* GetFramebuffer(GLuint client_id
) {
1206 return framebuffer_manager()->GetFramebuffer(client_id
);
1209 // Removes the framebuffer info for the given framebuffer.
1210 void RemoveFramebuffer(GLuint client_id
) {
1211 framebuffer_manager()->RemoveFramebuffer(client_id
);
1214 // Creates a renderbuffer info for the given renderbuffer.
1215 void CreateRenderbuffer(GLuint client_id
, GLuint service_id
) {
1216 return renderbuffer_manager()->CreateRenderbuffer(
1217 client_id
, service_id
);
1220 // Gets the renderbuffer info for the given renderbuffer.
1221 Renderbuffer
* GetRenderbuffer(GLuint client_id
) {
1222 return renderbuffer_manager()->GetRenderbuffer(client_id
);
1225 // Removes the renderbuffer info for the given renderbuffer.
1226 void RemoveRenderbuffer(GLuint client_id
) {
1227 renderbuffer_manager()->RemoveRenderbuffer(client_id
);
1230 // Creates a valuebuffer info for the given valuebuffer.
1231 void CreateValuebuffer(GLuint client_id
) {
1232 return valuebuffer_manager()->CreateValuebuffer(client_id
);
1235 // Gets the valuebuffer info for a given valuebuffer.
1236 Valuebuffer
* GetValuebuffer(GLuint client_id
) {
1237 return valuebuffer_manager()->GetValuebuffer(client_id
);
1240 // Removes the valuebuffer info for the given valuebuffer.
1241 void RemoveValuebuffer(GLuint client_id
) {
1242 valuebuffer_manager()->RemoveValuebuffer(client_id
);
1245 // Gets the vertex attrib manager for the given vertex array.
1246 VertexAttribManager
* GetVertexAttribManager(GLuint client_id
) {
1247 VertexAttribManager
* info
=
1248 vertex_array_manager()->GetVertexAttribManager(client_id
);
1252 // Removes the vertex attrib manager for the given vertex array.
1253 void RemoveVertexAttribManager(GLuint client_id
) {
1254 vertex_array_manager()->RemoveVertexAttribManager(client_id
);
1257 // Creates a vertex attrib manager for the given vertex array.
1258 scoped_refptr
<VertexAttribManager
> CreateVertexAttribManager(
1261 bool client_visible
) {
1262 return vertex_array_manager()->CreateVertexAttribManager(
1263 client_id
, service_id
, group_
->max_vertex_attribs(), client_visible
);
1266 void DoBindAttribLocation(GLuint client_id
, GLuint index
, const char* name
);
1267 void DoBindUniformLocationCHROMIUM(
1268 GLuint client_id
, GLint location
, const char* name
);
1270 error::Error
GetAttribLocationHelper(
1271 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1272 const std::string
& name_str
);
1274 error::Error
GetUniformLocationHelper(
1275 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1276 const std::string
& name_str
);
1278 error::Error
GetFragDataLocationHelper(
1279 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
1280 const std::string
& name_str
);
1282 // Wrapper for glShaderSource.
1283 void DoShaderSource(
1284 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
);
1286 // Wrapper for glTransformFeedbackVaryings.
1287 void DoTransformFeedbackVaryings(
1288 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
1289 GLenum buffer_mode
);
1291 // Clear any textures used by the current program.
1292 bool ClearUnclearedTextures();
1294 // Clears any uncleared attachments attached to the given frame buffer.
1295 // Returns false if there was a generated GL error.
1296 void ClearUnclearedAttachments(GLenum target
, Framebuffer
* framebuffer
);
1298 // overridden from GLES2Decoder
1299 bool ClearLevel(Texture
* texture
,
1307 int height
) override
;
1309 // Restore all GL state that affects clearing.
1310 void RestoreClearState();
1312 // Remembers the state of some capabilities.
1313 // Returns: true if glEnable/glDisable should actually be called.
1314 bool SetCapabilityState(GLenum cap
, bool enabled
);
1316 // Check that the currently bound framebuffers are valid.
1317 // Generates GL error if not.
1318 bool CheckBoundFramebuffersValid(const char* func_name
);
1320 // Check that the currently bound read framebuffer has a color image
1321 // attached. Generates GL error if not.
1322 bool CheckBoundReadFramebufferColorAttachment(const char* func_name
);
1324 // Check that the currently bound read framebuffer's color image
1325 // isn't the target texture of the glCopyTex{Sub}Image2D.
1326 bool FormsTextureCopyingFeedbackLoop(TextureRef
* texture
, GLint level
);
1328 // Check if a framebuffer meets our requirements.
1329 bool CheckFramebufferValid(
1330 Framebuffer
* framebuffer
,
1332 const char* func_name
);
1334 bool CheckBoundDrawFramebufferValid(const char* func_name
);
1336 // Check if the current valuebuffer exists and is valid. If not generates
1337 // the appropriate GL error. Returns true if the current valuebuffer is in
1339 bool CheckCurrentValuebuffer(const char* function_name
);
1341 // Check if the current valuebuffer exists and is valiud and that the
1342 // value buffer is actually subscribed to the given subscription
1343 bool CheckCurrentValuebufferForSubscription(GLenum subscription
,
1344 const char* function_name
);
1346 // Check if the location can be used for the given subscription target. If not
1347 // generates the appropriate GL error. Returns true if the location is usable
1348 bool CheckSubscriptionTarget(GLint location
,
1349 GLenum subscription
,
1350 const char* function_name
);
1352 // Checks if the current program exists and is valid. If not generates the
1353 // appropriate GL error. Returns true if the current program is in a usable
1355 bool CheckCurrentProgram(const char* function_name
);
1357 // Checks if the current program exists and is valid and that location is not
1358 // -1. If the current program is not valid generates the appropriate GL
1359 // error. Returns true if the current program is in a usable state and
1360 // location is not -1.
1361 bool CheckCurrentProgramForUniform(GLint location
, const char* function_name
);
1363 // Checks if the current program samples a texture that is also the color
1364 // image of the current bound framebuffer, i.e., the source and destination
1365 // of the draw operation are the same.
1366 bool CheckDrawingFeedbackLoops();
1368 // Checks if |api_type| is valid for the given uniform
1369 // If the api type is not valid generates the appropriate GL
1370 // error. Returns true if |api_type| is valid for the uniform
1371 bool CheckUniformForApiType(const Program::UniformInfo
* info
,
1372 const char* function_name
,
1373 Program::UniformApiType api_type
);
1375 // Gets the type of a uniform for a location in the current program. Sets GL
1376 // errors if the current program is not valid. Returns true if the current
1377 // program is valid and the location exists. Adjusts count so it
1378 // does not overflow the uniform.
1379 bool PrepForSetUniformByLocation(GLint fake_location
,
1380 const char* function_name
,
1381 Program::UniformApiType api_type
,
1382 GLint
* real_location
,
1386 // Gets the service id for any simulated backbuffer fbo.
1387 GLuint
GetBackbufferServiceId() const;
1389 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1390 bool GetHelper(GLenum pname
, GLint
* params
, GLsizei
* num_written
);
1392 // Helper for glGetVertexAttrib
1393 void GetVertexAttribHelper(
1394 const VertexAttrib
* attrib
, GLenum pname
, GLint
* param
);
1396 // Wrapper for glActiveTexture
1397 void DoActiveTexture(GLenum texture_unit
);
1399 // Wrapper for glAttachShader
1400 void DoAttachShader(GLuint client_program_id
, GLint client_shader_id
);
1402 // Wrapper for glBindBuffer since we need to track the current targets.
1403 void DoBindBuffer(GLenum target
, GLuint buffer
);
1405 // Wrapper for glBindBufferBase since we need to track the current targets.
1406 void DoBindBufferBase(GLenum target
, GLuint index
, GLuint buffer
);
1408 // Wrapper for glBindBufferRange since we need to track the current targets.
1409 void DoBindBufferRange(GLenum target
, GLuint index
, GLuint buffer
,
1410 GLintptr offset
, GLsizeiptr size
);
1412 // Wrapper for glBindFramebuffer since we need to track the current targets.
1413 void DoBindFramebuffer(GLenum target
, GLuint framebuffer
);
1415 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1416 void DoBindRenderbuffer(GLenum target
, GLuint renderbuffer
);
1418 // Wrapper for glBindTexture since we need to track the current targets.
1419 void DoBindTexture(GLenum target
, GLuint texture
);
1421 // Wrapper for glBindVertexArrayOES
1422 void DoBindVertexArrayOES(GLuint array
);
1423 void EmulateVertexArrayState();
1425 // Wrapper for glBlitFramebufferCHROMIUM.
1426 void DoBlitFramebufferCHROMIUM(
1427 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
1428 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
1429 GLbitfield mask
, GLenum filter
);
1431 // Wrapper for glBufferSubData.
1432 void DoBufferSubData(
1433 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
);
1435 // Wrapper for glCheckFramebufferStatus
1436 GLenum
DoCheckFramebufferStatus(GLenum target
);
1438 // Wrapper for glClear*()
1439 error::Error
DoClear(GLbitfield mask
);
1440 void DoClearBufferiv(
1441 GLenum buffer
, GLint drawbuffer
, const GLint
* value
);
1442 void DoClearBufferuiv(
1443 GLenum buffer
, GLint drawbuffer
, const GLuint
* value
);
1444 void DoClearBufferfv(
1445 GLenum buffer
, GLint drawbuffer
, const GLfloat
* value
);
1446 void DoClearBufferfi(
1447 GLenum buffer
, GLint drawbuffer
, GLfloat depth
, GLint stencil
);
1449 // Wrappers for various state.
1450 void DoDepthRangef(GLclampf znear
, GLclampf zfar
);
1451 void DoSampleCoverage(GLclampf value
, GLboolean invert
);
1453 // Wrapper for glCompileShader.
1454 void DoCompileShader(GLuint shader
);
1456 // Wrapper for glDetachShader
1457 void DoDetachShader(GLuint client_program_id
, GLint client_shader_id
);
1459 // Wrapper for glDisable
1460 void DoDisable(GLenum cap
);
1462 // Wrapper for glDisableVertexAttribArray.
1463 void DoDisableVertexAttribArray(GLuint index
);
1465 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1467 void DoDiscardFramebufferEXT(GLenum target
,
1468 GLsizei numAttachments
,
1469 const GLenum
* attachments
);
1471 // Wrapper for glEnable
1472 void DoEnable(GLenum cap
);
1474 // Wrapper for glEnableVertexAttribArray.
1475 void DoEnableVertexAttribArray(GLuint index
);
1477 // Wrapper for glFinish.
1480 // Wrapper for glFlush.
1483 // Wrapper for glFramebufferRenderbufffer.
1484 void DoFramebufferRenderbuffer(
1485 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
1486 GLuint renderbuffer
);
1488 // Wrapper for glFramebufferTexture2D.
1489 void DoFramebufferTexture2D(
1490 GLenum target
, GLenum attachment
, GLenum textarget
, GLuint texture
,
1493 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1494 void DoFramebufferTexture2DMultisample(
1495 GLenum target
, GLenum attachment
, GLenum textarget
,
1496 GLuint texture
, GLint level
, GLsizei samples
);
1498 // Common implementation for both DoFramebufferTexture2D wrappers.
1499 void DoFramebufferTexture2DCommon(const char* name
,
1500 GLenum target
, GLenum attachment
, GLenum textarget
,
1501 GLuint texture
, GLint level
, GLsizei samples
);
1503 // Wrapper for glFramebufferTextureLayer.
1504 void DoFramebufferTextureLayer(
1505 GLenum target
, GLenum attachment
, GLuint texture
, GLint level
,
1508 // Wrapper for glGenerateMipmap
1509 void DoGenerateMipmap(GLenum target
);
1511 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1512 // to account for different pname values defined in different extension
1514 GLenum
AdjustGetPname(GLenum pname
);
1516 // Wrapper for DoGetBooleanv.
1517 void DoGetBooleanv(GLenum pname
, GLboolean
* params
);
1519 // Wrapper for DoGetFloatv.
1520 void DoGetFloatv(GLenum pname
, GLfloat
* params
);
1522 // Wrapper for glGetFramebufferAttachmentParameteriv.
1523 void DoGetFramebufferAttachmentParameteriv(
1524 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
);
1526 // Wrapper for glGetInteger64v.
1527 void DoGetInteger64v(GLenum pname
, GLint64
* params
);
1529 // Wrapper for glGetIntegerv.
1530 void DoGetIntegerv(GLenum pname
, GLint
* params
);
1532 // Gets the max value in a range in a buffer.
1533 GLuint
DoGetMaxValueInBufferCHROMIUM(
1534 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
);
1536 // Wrapper for glGetBufferParameteri64v.
1537 void DoGetBufferParameteri64v(
1538 GLenum target
, GLenum pname
, GLint64
* params
);
1540 // Wrapper for glGetBufferParameteriv.
1541 void DoGetBufferParameteriv(
1542 GLenum target
, GLenum pname
, GLint
* params
);
1544 // Wrapper for glGetProgramiv.
1545 void DoGetProgramiv(
1546 GLuint program_id
, GLenum pname
, GLint
* params
);
1548 // Wrapper for glRenderbufferParameteriv.
1549 void DoGetRenderbufferParameteriv(
1550 GLenum target
, GLenum pname
, GLint
* params
);
1552 // Wrapper for glGetShaderiv
1553 void DoGetShaderiv(GLuint shader
, GLenum pname
, GLint
* params
);
1555 // Wrappers for glGetTexParameter.
1556 void DoGetTexParameterfv(GLenum target
, GLenum pname
, GLfloat
* params
);
1557 void DoGetTexParameteriv(GLenum target
, GLenum pname
, GLint
* params
);
1558 void InitTextureMaxAnisotropyIfNeeded(GLenum target
, GLenum pname
);
1560 // Wrappers for glGetVertexAttrib.
1561 template <typename T
>
1562 void DoGetVertexAttribImpl(GLuint index
, GLenum pname
, T
* params
);
1563 void DoGetVertexAttribfv(GLuint index
, GLenum pname
, GLfloat
* params
);
1564 void DoGetVertexAttribiv(GLuint index
, GLenum pname
, GLint
* params
);
1565 void DoGetVertexAttribIiv(GLuint index
, GLenum pname
, GLint
* params
);
1566 void DoGetVertexAttribIuiv(GLuint index
, GLenum pname
, GLuint
* params
);
1568 // Wrappers for glIsXXX functions.
1569 bool DoIsEnabled(GLenum cap
);
1570 bool DoIsBuffer(GLuint client_id
);
1571 bool DoIsFramebuffer(GLuint client_id
);
1572 bool DoIsProgram(GLuint client_id
);
1573 bool DoIsRenderbuffer(GLuint client_id
);
1574 bool DoIsShader(GLuint client_id
);
1575 bool DoIsTexture(GLuint client_id
);
1576 bool DoIsVertexArrayOES(GLuint client_id
);
1577 bool DoIsPathCHROMIUM(GLuint client_id
);
1579 // Wrapper for glLinkProgram
1580 void DoLinkProgram(GLuint program
);
1582 // Wrapper for glReadBuffer
1583 void DoReadBuffer(GLenum src
);
1585 // Wrapper for glRenderbufferStorage.
1586 void DoRenderbufferStorage(
1587 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
);
1589 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1590 void DoRenderbufferStorageMultisampleCHROMIUM(
1591 GLenum target
, GLsizei samples
, GLenum internalformat
,
1592 GLsizei width
, GLsizei height
);
1594 // Handler for glRenderbufferStorageMultisampleEXT
1595 // (multisampled_render_to_texture).
1596 void DoRenderbufferStorageMultisampleEXT(
1597 GLenum target
, GLsizei samples
, GLenum internalformat
,
1598 GLsizei width
, GLsizei height
);
1600 // Common validation for multisample extensions.
1601 bool ValidateRenderbufferStorageMultisample(GLsizei samples
,
1602 GLenum internalformat
,
1606 // Verifies that the currently bound multisample renderbuffer is valid
1607 // Very slow! Only done on platforms with driver bugs that return invalid
1608 // buffers under memory pressure
1609 bool VerifyMultisampleRenderbufferIntegrity(
1610 GLuint renderbuffer
, GLenum format
);
1612 // Wrapper for glReleaseShaderCompiler.
1613 void DoReleaseShaderCompiler() { }
1615 // Wrappers for glSamplerParameter*v functions.
1616 void DoSamplerParameterfv(
1617 GLuint sampler
, GLenum pname
, const GLfloat
* params
);
1618 void DoSamplerParameteriv(GLuint sampler
, GLenum pname
, const GLint
* params
);
1620 // Wrappers for glTexParameter functions.
1621 void DoTexParameterf(GLenum target
, GLenum pname
, GLfloat param
);
1622 void DoTexParameteri(GLenum target
, GLenum pname
, GLint param
);
1623 void DoTexParameterfv(GLenum target
, GLenum pname
, const GLfloat
* params
);
1624 void DoTexParameteriv(GLenum target
, GLenum pname
, const GLint
* params
);
1626 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1627 // spec only these 2 functions can be used to set sampler uniforms.
1628 void DoUniform1i(GLint fake_location
, GLint v0
);
1629 void DoUniform1iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1630 void DoUniform2iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1631 void DoUniform3iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1632 void DoUniform4iv(GLint fake_location
, GLsizei count
, const GLint
* value
);
1634 void DoUniform1ui(GLint fake_location
, GLuint v0
);
1635 void DoUniform1uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1636 void DoUniform2uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1637 void DoUniform3uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1638 void DoUniform4uiv(GLint fake_location
, GLsizei count
, const GLuint
* value
);
1640 // Wrappers for glUniformfv because some drivers don't correctly accept
1642 void DoUniform1fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1643 void DoUniform2fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1644 void DoUniform3fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1645 void DoUniform4fv(GLint fake_location
, GLsizei count
, const GLfloat
* value
);
1647 void DoUniformMatrix2fv(
1648 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1649 const GLfloat
* value
);
1650 void DoUniformMatrix3fv(
1651 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1652 const GLfloat
* value
);
1653 void DoUniformMatrix4fv(
1654 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1655 const GLfloat
* value
);
1656 void DoUniformMatrix2x3fv(
1657 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1658 const GLfloat
* value
);
1659 void DoUniformMatrix2x4fv(
1660 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1661 const GLfloat
* value
);
1662 void DoUniformMatrix3x2fv(
1663 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1664 const GLfloat
* value
);
1665 void DoUniformMatrix3x4fv(
1666 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1667 const GLfloat
* value
);
1668 void DoUniformMatrix4x2fv(
1669 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1670 const GLfloat
* value
);
1671 void DoUniformMatrix4x3fv(
1672 GLint fake_location
, GLsizei count
, GLboolean transpose
,
1673 const GLfloat
* value
);
1675 template <typename T
>
1676 bool SetVertexAttribValue(
1677 const char* function_name
, GLuint index
, const T
* value
);
1679 // Wrappers for glVertexAttrib??
1680 void DoVertexAttrib1f(GLuint index
, GLfloat v0
);
1681 void DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
);
1682 void DoVertexAttrib3f(GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
);
1683 void DoVertexAttrib4f(
1684 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
);
1685 void DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
);
1686 void DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
);
1687 void DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
);
1688 void DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
);
1689 void DoVertexAttribI4i(GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
);
1690 void DoVertexAttribI4iv(GLuint index
, const GLint
* v
);
1691 void DoVertexAttribI4ui(
1692 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
);
1693 void DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
);
1695 // Wrapper for glViewport
1696 void DoViewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
);
1698 // Wrapper for glUseProgram
1699 void DoUseProgram(GLuint program
);
1701 // Wrapper for glValidateProgram.
1702 void DoValidateProgram(GLuint program_client_id
);
1704 void DoInsertEventMarkerEXT(GLsizei length
, const GLchar
* marker
);
1705 void DoPushGroupMarkerEXT(GLsizei length
, const GLchar
* group
);
1706 void DoPopGroupMarkerEXT(void);
1708 // Gets the number of values that will be returned by glGetXXX. Returns
1709 // false if pname is unknown.
1710 bool GetNumValuesReturnedForGLGet(GLenum pname
, GLsizei
* num_values
);
1712 // Checks if the current program and vertex attributes are valid for drawing.
1714 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
1717 // Returns true if successful, simulated will be true if attrib0 was
1719 bool SimulateAttrib0(
1720 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
);
1721 void RestoreStateForAttrib(GLuint attrib
, bool restore_array_binding
);
1723 // If an image is bound to texture, this will call Will/DidUseTexImage
1725 void DoWillUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1726 void DoDidUseTexImageIfNeeded(Texture
* texture
, GLenum textarget
);
1728 // Returns false if textures were replaced.
1729 bool PrepareTexturesForRender();
1730 void RestoreStateForTextures();
1732 // Returns true if GL_FIXED attribs were simulated.
1733 bool SimulateFixedAttribs(
1734 const char* function_name
,
1735 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
);
1736 void RestoreStateForSimulatedFixedAttribs();
1738 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1739 // cases (primcount is always 1 for non-instanced).
1740 error::Error
DoDrawArrays(
1741 const char* function_name
,
1742 bool instanced
, GLenum mode
, GLint first
, GLsizei count
,
1744 error::Error
DoDrawElements(
1745 const char* function_name
,
1746 bool instanced
, GLenum mode
, GLsizei count
, GLenum type
,
1747 int32 offset
, GLsizei primcount
);
1749 GLenum
GetBindTargetForSamplerType(GLenum type
) {
1750 DCHECK(type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_CUBE
||
1751 type
== GL_SAMPLER_EXTERNAL_OES
|| type
== GL_SAMPLER_2D_RECT_ARB
);
1754 return GL_TEXTURE_2D
;
1755 case GL_SAMPLER_CUBE
:
1756 return GL_TEXTURE_CUBE_MAP
;
1757 case GL_SAMPLER_EXTERNAL_OES
:
1758 return GL_TEXTURE_EXTERNAL_OES
;
1759 case GL_SAMPLER_2D_RECT_ARB
:
1760 return GL_TEXTURE_RECTANGLE_ARB
;
1767 // Gets the framebuffer info for a particular target.
1768 Framebuffer
* GetFramebufferInfoForTarget(GLenum target
) {
1769 Framebuffer
* framebuffer
= NULL
;
1771 case GL_FRAMEBUFFER
:
1772 case GL_DRAW_FRAMEBUFFER_EXT
:
1773 framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
1775 case GL_READ_FRAMEBUFFER_EXT
:
1776 framebuffer
= framebuffer_state_
.bound_read_framebuffer
.get();
1785 Renderbuffer
* GetRenderbufferInfoForTarget(
1787 Renderbuffer
* renderbuffer
= NULL
;
1789 case GL_RENDERBUFFER
:
1790 renderbuffer
= state_
.bound_renderbuffer
.get();
1796 return renderbuffer
;
1799 // Validates the program and location for a glGetUniform call and returns
1800 // a SizeResult setup to receive the result. Returns true if glGetUniform
1801 // should be called.
1803 bool GetUniformSetup(GLuint program
,
1804 GLint fake_location
,
1807 error::Error
* error
,
1808 GLint
* real_location
,
1810 SizedResult
<T
>** result
,
1811 GLenum
* result_type
,
1812 GLsizei
* result_size
);
1814 bool WasContextLost() const override
;
1815 bool WasContextLostByRobustnessExtension() const override
;
1816 void MarkContextLost(error::ContextLostReason reason
) override
;
1817 bool CheckResetStatus();
1819 #if defined(OS_MACOSX)
1820 void ReleaseIOSurfaceForTexture(GLuint texture_id
);
1823 bool GetCompressedTexSizeInBytes(
1824 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1825 GLenum format
, GLsizei
* size_in_bytes
);
1827 bool ValidateCompressedTexDimensions(
1828 const char* function_name
, GLenum target
, GLint level
,
1829 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
);
1830 bool ValidateCompressedTexFuncData(
1831 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
1832 GLenum format
, GLsizei size
);
1833 bool ValidateCompressedTexSubDimensions(
1834 const char* function_name
,
1835 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
1836 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
1838 bool ValidateCopyTextureCHROMIUM(const char* function_name
,
1840 TextureRef
* source_texture_ref
,
1841 TextureRef
* dest_texture_ref
,
1842 GLenum dest_internal_format
);
1843 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name
,
1845 TextureRef
* source_texture_ref
,
1846 TextureRef
* dest_texture_ref
);
1848 void RenderWarning(const char* filename
, int line
, const std::string
& msg
);
1849 void PerformanceWarning(
1850 const char* filename
, int line
, const std::string
& msg
);
1852 const FeatureInfo::FeatureFlags
& features() const {
1853 return feature_info_
->feature_flags();
1856 const FeatureInfo::Workarounds
& workarounds() const {
1857 return feature_info_
->workarounds();
1860 bool ShouldDeferDraws() {
1861 return !offscreen_target_frame_buffer_
.get() &&
1862 framebuffer_state_
.bound_draw_framebuffer
.get() == NULL
&&
1863 surface_
->DeferDraws();
1866 bool ShouldDeferReads() {
1867 return !offscreen_target_frame_buffer_
.get() &&
1868 framebuffer_state_
.bound_read_framebuffer
.get() == NULL
&&
1869 surface_
->DeferDraws();
1872 bool IsRobustnessSupported() {
1873 return has_robustness_extension_
&&
1874 context_
->WasAllocatedUsingRobustnessExtension();
1877 error::Error
WillAccessBoundFramebufferForDraw() {
1878 if (ShouldDeferDraws())
1879 return error::kDeferCommandUntilLater
;
1880 if (!offscreen_target_frame_buffer_
.get() &&
1881 !framebuffer_state_
.bound_draw_framebuffer
.get() &&
1882 !surface_
->SetBackbufferAllocation(true))
1883 return error::kLostContext
;
1884 return error::kNoError
;
1887 error::Error
WillAccessBoundFramebufferForRead() {
1888 if (ShouldDeferReads())
1889 return error::kDeferCommandUntilLater
;
1890 if (!offscreen_target_frame_buffer_
.get() &&
1891 !framebuffer_state_
.bound_read_framebuffer
.get() &&
1892 !surface_
->SetBackbufferAllocation(true))
1893 return error::kLostContext
;
1894 return error::kNoError
;
1897 bool BackBufferHasAlpha() const {
1898 if (back_buffer_draw_buffer_
== GL_NONE
)
1900 if (offscreen_target_frame_buffer_
.get()) {
1901 return (offscreen_target_color_format_
== GL_RGBA
||
1902 offscreen_target_color_format_
== GL_RGBA8
);
1904 return (back_buffer_color_format_
== GL_RGBA
||
1905 back_buffer_color_format_
== GL_RGBA8
);
1908 // Set remaining commands to process to 0 to force DoCommands to return
1909 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1910 void ExitCommandProcessingEarly() { commands_to_process_
= 0; }
1912 void ProcessPendingReadPixels(bool did_finish
);
1913 void FinishReadPixels(const cmds::ReadPixels
& c
, GLuint buffer
);
1915 // Generate a member function prototype for each command in an automated and
1917 #define GLES2_CMD_OP(name) \
1918 Error Handle##name(uint32 immediate_data_size, const void* data);
1920 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
1924 // The GL context this decoder renders to on behalf of the client.
1925 scoped_refptr
<gfx::GLSurface
> surface_
;
1926 scoped_refptr
<gfx::GLContext
> context_
;
1928 // The ContextGroup for this decoder uses to track resources.
1929 scoped_refptr
<ContextGroup
> group_
;
1931 DebugMarkerManager debug_marker_manager_
;
1934 // All the state for this context.
1935 ContextState state_
;
1937 // Current width and height of the offscreen frame buffer.
1938 gfx::Size offscreen_size_
;
1940 // Util to help with GL.
1943 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1944 GLuint attrib_0_buffer_id_
;
1946 // The value currently in attrib_0.
1947 Vec4 attrib_0_value_
;
1949 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1950 bool attrib_0_buffer_matches_value_
;
1952 // The size of attrib 0.
1953 GLsizei attrib_0_size_
;
1955 // The buffer used to simulate GL_FIXED attribs.
1956 GLuint fixed_attrib_buffer_id_
;
1958 // The size of fiixed attrib buffer.
1959 GLsizei fixed_attrib_buffer_size_
;
1961 // The offscreen frame buffer that the client renders to. With EGL, the
1962 // depth and stencil buffers are separate. With regular GL there is a single
1963 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1964 // offscreen_target_stencil_render_buffer_ is unused.
1965 scoped_ptr
<BackFramebuffer
> offscreen_target_frame_buffer_
;
1966 scoped_ptr
<BackTexture
> offscreen_target_color_texture_
;
1967 scoped_ptr
<BackRenderbuffer
> offscreen_target_color_render_buffer_
;
1968 scoped_ptr
<BackRenderbuffer
> offscreen_target_depth_render_buffer_
;
1969 scoped_ptr
<BackRenderbuffer
> offscreen_target_stencil_render_buffer_
;
1970 GLenum offscreen_target_color_format_
;
1971 GLenum offscreen_target_depth_format_
;
1972 GLenum offscreen_target_stencil_format_
;
1973 GLsizei offscreen_target_samples_
;
1974 GLboolean offscreen_target_buffer_preserved_
;
1976 // The copy that is saved when SwapBuffers is called.
1977 scoped_ptr
<BackFramebuffer
> offscreen_saved_frame_buffer_
;
1978 scoped_ptr
<BackTexture
> offscreen_saved_color_texture_
;
1979 scoped_refptr
<TextureRef
>
1980 offscreen_saved_color_texture_info_
;
1982 // The copy that is used as the destination for multi-sample resolves.
1983 scoped_ptr
<BackFramebuffer
> offscreen_resolved_frame_buffer_
;
1984 scoped_ptr
<BackTexture
> offscreen_resolved_color_texture_
;
1985 GLenum offscreen_saved_color_format_
;
1987 scoped_ptr
<QueryManager
> query_manager_
;
1989 scoped_ptr
<VertexArrayManager
> vertex_array_manager_
;
1991 scoped_ptr
<ImageManager
> image_manager_
;
1993 base::Callback
<void(gfx::Size
, float)> resize_callback_
;
1995 WaitSyncPointCallback wait_sync_point_callback_
;
1997 ShaderCacheCallback shader_cache_callback_
;
1999 // The format of the back buffer_
2000 GLenum back_buffer_color_format_
;
2001 bool back_buffer_has_depth_
;
2002 bool back_buffer_has_stencil_
;
2004 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
2006 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
2007 // setting is set correctly when SwapBuffers().
2008 GLenum back_buffer_read_buffer_
;
2009 GLenum back_buffer_draw_buffer_
;
2013 // Backbuffer attachments that are currently undefined.
2014 uint32 backbuffer_needs_clear_bits_
;
2016 // The current decoder error communicates the decoder error through command
2017 // processing functions that do not return the error value. Should be set only
2018 // if not returning an error.
2019 error::Error current_decoder_error_
;
2021 scoped_refptr
<ShaderTranslatorInterface
> vertex_translator_
;
2022 scoped_refptr
<ShaderTranslatorInterface
> fragment_translator_
;
2024 DisallowedFeatures disallowed_features_
;
2026 // Cached from ContextGroup
2027 const Validators
* validators_
;
2028 scoped_refptr
<FeatureInfo
> feature_info_
;
2032 // Number of commands remaining to be processed in DoCommands().
2033 int commands_to_process_
;
2035 bool has_robustness_extension_
;
2036 error::ContextLostReason context_lost_reason_
;
2037 bool context_was_lost_
;
2038 bool reset_by_robustness_extension_
;
2039 bool supports_post_sub_buffer_
;
2041 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2045 unsigned webgl_version_
;
2047 // These flags are used to override the state of the shared feature_info_
2048 // member. Because the same FeatureInfo instance may be shared among many
2049 // contexts, the assumptions on the availablity of extensions in WebGL
2050 // contexts may be broken. These flags override the shared state to preserve
2052 bool derivatives_explicitly_enabled_
;
2053 bool frag_depth_explicitly_enabled_
;
2054 bool draw_buffers_explicitly_enabled_
;
2055 bool shader_texture_lod_explicitly_enabled_
;
2057 bool compile_shader_always_succeeds_
;
2059 // An optional behaviour to lose the context and group when OOM.
2060 bool lose_context_when_out_of_memory_
;
2063 bool service_logging_
;
2065 #if defined(OS_MACOSX)
2066 typedef std::map
<GLuint
, IOSurfaceRef
> TextureToIOSurfaceMap
;
2067 TextureToIOSurfaceMap texture_to_io_surface_map_
;
2070 scoped_ptr
<CopyTextureCHROMIUMResourceManager
> copy_texture_CHROMIUM_
;
2071 scoped_ptr
<ClearFramebufferResourceManager
> clear_framebuffer_blit_
;
2073 // Cached values of the currently assigned viewport dimensions.
2074 GLsizei viewport_max_width_
;
2075 GLsizei viewport_max_height_
;
2077 // Command buffer stats.
2078 base::TimeDelta total_processing_commands_time_
;
2080 // States related to each manager.
2081 DecoderTextureState texture_state_
;
2082 DecoderFramebufferState framebuffer_state_
;
2084 scoped_ptr
<GPUTracer
> gpu_tracer_
;
2085 scoped_ptr
<GPUStateTracer
> gpu_state_tracer_
;
2086 const unsigned char* gpu_decoder_category_
;
2087 int gpu_trace_level_
;
2088 bool gpu_trace_commands_
;
2089 bool gpu_debug_commands_
;
2091 std::queue
<linked_ptr
<FenceCallback
> > pending_readpixel_fences_
;
2093 // Used to validate multisample renderbuffers if needed
2094 GLuint validation_texture_
;
2095 GLuint validation_fbo_multisample_
;
2096 GLuint validation_fbo_
;
2098 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler
)(
2099 uint32 immediate_data_size
,
2102 // A struct to hold info about each command.
2103 struct CommandInfo
{
2104 CmdHandler cmd_handler
;
2105 uint8 arg_flags
; // How to handle the arguments for this command
2106 uint8 cmd_flags
; // How to handle this command
2107 uint16 arg_count
; // How many arguments are expected for this command.
2110 // A table of CommandInfo for all the commands.
2111 static const CommandInfo command_info
[kNumCommands
- kStartPoint
];
2113 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl
);
2116 const GLES2DecoderImpl::CommandInfo
GLES2DecoderImpl::command_info
[] = {
2117 #define GLES2_CMD_OP(name) \
2119 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2120 cmds::name::cmd_flags, \
2121 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2124 GLES2_COMMAND_LIST(GLES2_CMD_OP
)
2128 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2129 const char* function_name
, ErrorState
* error_state
)
2130 : function_name_(function_name
),
2131 error_state_(error_state
) {
2132 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_
, function_name_
);
2135 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2136 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_
, function_name_
);
2139 static void RestoreCurrentTextureBindings(ContextState
* state
, GLenum target
) {
2140 TextureUnit
& info
= state
->texture_units
[0];
2142 scoped_refptr
<TextureRef
> texture_ref
;
2145 texture_ref
= info
.bound_texture_2d
;
2147 case GL_TEXTURE_CUBE_MAP
:
2148 texture_ref
= info
.bound_texture_cube_map
;
2150 case GL_TEXTURE_EXTERNAL_OES
:
2151 texture_ref
= info
.bound_texture_external_oes
;
2153 case GL_TEXTURE_RECTANGLE_ARB
:
2154 texture_ref
= info
.bound_texture_rectangle_arb
;
2160 if (texture_ref
.get()) {
2161 last_id
= texture_ref
->service_id();
2166 glBindTexture(target
, last_id
);
2167 glActiveTexture(GL_TEXTURE0
+ state
->active_texture_unit
);
2170 ScopedTextureBinder::ScopedTextureBinder(ContextState
* state
,
2175 ScopedGLErrorSuppressor
suppressor(
2176 "ScopedTextureBinder::ctor", state_
->GetErrorState());
2178 // TODO(apatrick): Check if there are any other states that need to be reset
2179 // before binding a new texture.
2180 glActiveTexture(GL_TEXTURE0
);
2181 glBindTexture(target
, id
);
2184 ScopedTextureBinder::~ScopedTextureBinder() {
2185 ScopedGLErrorSuppressor
suppressor(
2186 "ScopedTextureBinder::dtor", state_
->GetErrorState());
2187 RestoreCurrentTextureBindings(state_
, target_
);
2190 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState
* state
,
2193 ScopedGLErrorSuppressor
suppressor(
2194 "ScopedRenderBufferBinder::ctor", state_
->GetErrorState());
2195 glBindRenderbufferEXT(GL_RENDERBUFFER
, id
);
2198 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2199 ScopedGLErrorSuppressor
suppressor(
2200 "ScopedRenderBufferBinder::dtor", state_
->GetErrorState());
2201 state_
->RestoreRenderbufferBindings();
2204 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl
* decoder
,
2206 : decoder_(decoder
) {
2207 ScopedGLErrorSuppressor
suppressor(
2208 "ScopedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2209 glBindFramebufferEXT(GL_FRAMEBUFFER
, id
);
2210 decoder
->OnFboChanged();
2213 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2214 ScopedGLErrorSuppressor
suppressor(
2215 "ScopedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2216 decoder_
->RestoreCurrentFramebufferBindings();
2219 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2220 GLES2DecoderImpl
* decoder
, bool enforce_internal_framebuffer
, bool internal
)
2221 : decoder_(decoder
) {
2222 resolve_and_bind_
= (
2223 decoder_
->offscreen_target_frame_buffer_
.get() &&
2224 decoder_
->IsOffscreenBufferMultisampled() &&
2225 (!decoder_
->framebuffer_state_
.bound_read_framebuffer
.get() ||
2226 enforce_internal_framebuffer
));
2227 if (!resolve_and_bind_
)
2230 ScopedGLErrorSuppressor
suppressor(
2231 "ScopedResolvedFrameBufferBinder::ctor", decoder_
->GetErrorState());
2232 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
,
2233 decoder_
->offscreen_target_frame_buffer_
->id());
2236 if (!decoder_
->offscreen_resolved_frame_buffer_
.get()) {
2237 decoder_
->offscreen_resolved_frame_buffer_
.reset(
2238 new BackFramebuffer(decoder_
));
2239 decoder_
->offscreen_resolved_frame_buffer_
->Create();
2240 decoder_
->offscreen_resolved_color_texture_
.reset(
2241 new BackTexture(decoder
->memory_tracker(), &decoder
->state_
));
2242 decoder_
->offscreen_resolved_color_texture_
->Create();
2244 DCHECK(decoder_
->offscreen_saved_color_format_
);
2245 decoder_
->offscreen_resolved_color_texture_
->AllocateStorage(
2246 decoder_
->offscreen_size_
, decoder_
->offscreen_saved_color_format_
,
2248 decoder_
->offscreen_resolved_frame_buffer_
->AttachRenderTexture(
2249 decoder_
->offscreen_resolved_color_texture_
.get());
2250 if (decoder_
->offscreen_resolved_frame_buffer_
->CheckStatus() !=
2251 GL_FRAMEBUFFER_COMPLETE
) {
2252 LOG(ERROR
) << "ScopedResolvedFrameBufferBinder failed "
2253 << "because offscreen resolved FBO was incomplete.";
2257 targetid
= decoder_
->offscreen_resolved_frame_buffer_
->id();
2259 targetid
= decoder_
->offscreen_saved_frame_buffer_
->id();
2261 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, targetid
);
2262 const int width
= decoder_
->offscreen_size_
.width();
2263 const int height
= decoder_
->offscreen_size_
.height();
2264 decoder
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
2265 decoder
->BlitFramebufferHelper(0,
2273 GL_COLOR_BUFFER_BIT
,
2275 glBindFramebufferEXT(GL_FRAMEBUFFER
, targetid
);
2278 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2279 if (!resolve_and_bind_
)
2282 ScopedGLErrorSuppressor
suppressor(
2283 "ScopedResolvedFrameBufferBinder::dtor", decoder_
->GetErrorState());
2284 decoder_
->RestoreCurrentFramebufferBindings();
2285 if (decoder_
->state_
.enable_flags
.scissor_test
) {
2286 decoder_
->state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
2290 BackTexture::BackTexture(
2291 MemoryTracker
* memory_tracker
,
2292 ContextState
* state
)
2293 : memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2295 bytes_allocated_(0),
2299 BackTexture::~BackTexture() {
2300 // This does not destroy the render texture because that would require that
2301 // the associated GL context was current. Just check that it was explicitly
2306 void BackTexture::Create() {
2307 ScopedGLErrorSuppressor
suppressor("BackTexture::Create",
2308 state_
->GetErrorState());
2310 glGenTextures(1, &id_
);
2311 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2312 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
2313 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
2314 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
2315 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
2317 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2318 // never called on an offscreen context, no data will ever be uploaded to the
2319 // saved offscreen color texture (it is deferred until to when SwapBuffers
2320 // is called). My idea is that some nvidia drivers might have a bug where
2321 // deleting a texture that has never been populated might cause a
2324 GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
2326 bytes_allocated_
= 16u * 16u * 4u;
2327 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2330 bool BackTexture::AllocateStorage(
2331 const gfx::Size
& size
, GLenum format
, bool zero
) {
2333 ScopedGLErrorSuppressor
suppressor("BackTexture::AllocateStorage",
2334 state_
->GetErrorState());
2335 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2336 uint32 image_size
= 0;
2337 GLES2Util::ComputeImageDataSizes(
2338 size
.width(), size
.height(), 1, format
, GL_UNSIGNED_BYTE
, 8, &image_size
,
2341 if (!memory_tracker_
.EnsureGPUMemoryAvailable(image_size
)) {
2345 scoped_ptr
<char[]> zero_data
;
2347 zero_data
.reset(new char[image_size
]);
2348 memset(zero_data
.get(), 0, image_size
);
2351 glTexImage2D(GL_TEXTURE_2D
,
2363 bool success
= glGetError() == GL_NO_ERROR
;
2365 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2366 bytes_allocated_
= image_size
;
2367 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2372 void BackTexture::Copy(const gfx::Size
& size
, GLenum format
) {
2374 ScopedGLErrorSuppressor
suppressor("BackTexture::Copy",
2375 state_
->GetErrorState());
2376 ScopedTextureBinder
binder(state_
, id_
, GL_TEXTURE_2D
);
2377 glCopyTexImage2D(GL_TEXTURE_2D
,
2386 void BackTexture::Destroy() {
2388 ScopedGLErrorSuppressor
suppressor("BackTexture::Destroy",
2389 state_
->GetErrorState());
2390 glDeleteTextures(1, &id_
);
2393 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2394 bytes_allocated_
= 0;
2397 void BackTexture::Invalidate() {
2401 BackRenderbuffer::BackRenderbuffer(
2402 RenderbufferManager
* renderbuffer_manager
,
2403 MemoryTracker
* memory_tracker
,
2404 ContextState
* state
)
2405 : renderbuffer_manager_(renderbuffer_manager
),
2406 memory_tracker_(memory_tracker
, MemoryTracker::kUnmanaged
),
2408 bytes_allocated_(0),
2412 BackRenderbuffer::~BackRenderbuffer() {
2413 // This does not destroy the render buffer because that would require that
2414 // the associated GL context was current. Just check that it was explicitly
2419 void BackRenderbuffer::Create() {
2420 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Create",
2421 state_
->GetErrorState());
2423 glGenRenderbuffersEXT(1, &id_
);
2426 bool BackRenderbuffer::AllocateStorage(const FeatureInfo
* feature_info
,
2427 const gfx::Size
& size
,
2430 ScopedGLErrorSuppressor
suppressor(
2431 "BackRenderbuffer::AllocateStorage", state_
->GetErrorState());
2432 ScopedRenderBufferBinder
binder(state_
, id_
);
2434 uint32 estimated_size
= 0;
2435 if (!renderbuffer_manager_
->ComputeEstimatedRenderbufferSize(
2436 size
.width(), size
.height(), samples
, format
, &estimated_size
)) {
2440 if (!memory_tracker_
.EnsureGPUMemoryAvailable(estimated_size
)) {
2445 glRenderbufferStorageEXT(GL_RENDERBUFFER
,
2450 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info
,
2457 bool success
= glGetError() == GL_NO_ERROR
;
2459 // Mark the previously allocated bytes as free.
2460 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2461 bytes_allocated_
= estimated_size
;
2462 // Track the newly allocated bytes.
2463 memory_tracker_
.TrackMemAlloc(bytes_allocated_
);
2468 void BackRenderbuffer::Destroy() {
2470 ScopedGLErrorSuppressor
suppressor("BackRenderbuffer::Destroy",
2471 state_
->GetErrorState());
2472 glDeleteRenderbuffersEXT(1, &id_
);
2475 memory_tracker_
.TrackMemFree(bytes_allocated_
);
2476 bytes_allocated_
= 0;
2479 void BackRenderbuffer::Invalidate() {
2483 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl
* decoder
)
2484 : decoder_(decoder
),
2488 BackFramebuffer::~BackFramebuffer() {
2489 // This does not destroy the frame buffer because that would require that
2490 // the associated GL context was current. Just check that it was explicitly
2495 void BackFramebuffer::Create() {
2496 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Create",
2497 decoder_
->GetErrorState());
2499 glGenFramebuffersEXT(1, &id_
);
2502 void BackFramebuffer::AttachRenderTexture(BackTexture
* texture
) {
2504 ScopedGLErrorSuppressor
suppressor(
2505 "BackFramebuffer::AttachRenderTexture", decoder_
->GetErrorState());
2506 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2507 GLuint attach_id
= texture
? texture
->id() : 0;
2508 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
,
2509 GL_COLOR_ATTACHMENT0
,
2515 void BackFramebuffer::AttachRenderBuffer(GLenum target
,
2516 BackRenderbuffer
* render_buffer
) {
2518 ScopedGLErrorSuppressor
suppressor(
2519 "BackFramebuffer::AttachRenderBuffer", decoder_
->GetErrorState());
2520 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2521 GLuint attach_id
= render_buffer
? render_buffer
->id() : 0;
2522 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
,
2528 void BackFramebuffer::Destroy() {
2530 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::Destroy",
2531 decoder_
->GetErrorState());
2532 glDeleteFramebuffersEXT(1, &id_
);
2537 void BackFramebuffer::Invalidate() {
2541 GLenum
BackFramebuffer::CheckStatus() {
2543 ScopedGLErrorSuppressor
suppressor("BackFramebuffer::CheckStatus",
2544 decoder_
->GetErrorState());
2545 ScopedFrameBufferBinder
binder(decoder_
, id_
);
2546 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER
);
2549 GLES2Decoder
* GLES2Decoder::Create(ContextGroup
* group
) {
2550 return new GLES2DecoderImpl(group
);
2553 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup
* group
)
2556 logger_(&debug_marker_manager_
),
2557 state_(group_
->feature_info(), this, &logger_
),
2558 attrib_0_buffer_id_(0),
2559 attrib_0_buffer_matches_value_(true),
2561 fixed_attrib_buffer_id_(0),
2562 fixed_attrib_buffer_size_(0),
2563 offscreen_target_color_format_(0),
2564 offscreen_target_depth_format_(0),
2565 offscreen_target_stencil_format_(0),
2566 offscreen_target_samples_(0),
2567 offscreen_target_buffer_preserved_(true),
2568 offscreen_saved_color_format_(0),
2569 back_buffer_color_format_(0),
2570 back_buffer_has_depth_(false),
2571 back_buffer_has_stencil_(false),
2572 back_buffer_read_buffer_(GL_BACK
),
2573 back_buffer_draw_buffer_(GL_BACK
),
2574 surfaceless_(false),
2575 backbuffer_needs_clear_bits_(0),
2576 current_decoder_error_(error::kNoError
),
2577 validators_(group_
->feature_info()->validators()),
2578 feature_info_(group_
->feature_info()),
2580 has_robustness_extension_(false),
2581 context_lost_reason_(error::kUnknown
),
2582 context_was_lost_(false),
2583 reset_by_robustness_extension_(false),
2584 supports_post_sub_buffer_(false),
2586 derivatives_explicitly_enabled_(false),
2587 frag_depth_explicitly_enabled_(false),
2588 draw_buffers_explicitly_enabled_(false),
2589 shader_texture_lod_explicitly_enabled_(false),
2590 compile_shader_always_succeeds_(false),
2591 lose_context_when_out_of_memory_(false),
2592 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2593 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2594 switches::kEnableGPUServiceLoggingGPU
)
2596 viewport_max_width_(0),
2597 viewport_max_height_(0),
2598 texture_state_(group_
->feature_info()->workarounds()),
2599 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2600 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2601 gpu_trace_level_(2),
2602 gpu_trace_commands_(false),
2603 gpu_debug_commands_(false),
2604 validation_texture_(0),
2605 validation_fbo_multisample_(0),
2606 validation_fbo_(0) {
2610 GLES2DecoderImpl::~GLES2DecoderImpl() {
2613 bool GLES2DecoderImpl::Initialize(
2614 const scoped_refptr
<gfx::GLSurface
>& surface
,
2615 const scoped_refptr
<gfx::GLContext
>& context
,
2617 const gfx::Size
& offscreen_size
,
2618 const DisallowedFeatures
& disallowed_features
,
2619 const std::vector
<int32
>& attribs
) {
2620 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2621 DCHECK(context
->IsCurrent(surface
.get()));
2622 DCHECK(!context_
.get());
2623 DCHECK(!offscreen
|| !offscreen_size
.IsEmpty());
2625 ContextCreationAttribHelper attrib_parser
;
2626 if (!attrib_parser
.Parse(attribs
))
2628 webgl_version_
= attrib_parser
.webgl_version
;
2630 surfaceless_
= surface
->IsSurfaceless() && !offscreen
;
2633 gpu_state_tracer_
= GPUStateTracer::Create(&state_
);
2635 if (base::CommandLine::InitializedForCurrentProcess()) {
2636 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2637 switches::kEnableGPUDebugging
)) {
2641 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2642 switches::kEnableGPUCommandLogging
)) {
2643 set_log_commands(true);
2646 compile_shader_always_succeeds_
=
2647 base::CommandLine::ForCurrentProcess()->HasSwitch(
2648 switches::kCompileShaderAlwaysSucceeds
);
2651 // Take ownership of the context and surface. The surface can be replaced with
2656 // Create GPU Tracer for timing values.
2657 gpu_tracer_
.reset(new GPUTracer(this));
2659 if (feature_info_
->workarounds().disable_timestamp_queries
) {
2660 // Forcing time elapsed query for any GPU Timing Client forces it for all
2661 // clients in the context.
2662 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2665 // Save the loseContextWhenOutOfMemory context creation attribute.
2666 lose_context_when_out_of_memory_
=
2667 attrib_parser
.lose_context_when_out_of_memory
;
2669 // If the failIfMajorPerformanceCaveat context creation attribute was true
2670 // and we are using a software renderer, fail.
2671 if (attrib_parser
.fail_if_major_perf_caveat
&&
2672 feature_info_
->feature_flags().is_swiftshader
) {
2673 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2678 disallowed_features_
= disallowed_features
;
2679 if (webgl_version_
== 1) {
2680 disallowed_features_
.npot_support
= true;
2683 if (!group_
->Initialize(this,
2684 ContextGroup::GetContextType(webgl_version_
),
2685 disallowed_features_
)) {
2686 group_
= NULL
; // Must not destroy ContextGroup if it is not initialized.
2692 if (webgl_version_
== 2) {
2693 if (!feature_info_
->IsES3Capable()) {
2694 LOG(ERROR
) << "Underlying driver does not support ES3.";
2698 feature_info_
->EnableES3Validators();
2699 set_unsafe_es3_apis_enabled(true);
2701 frag_depth_explicitly_enabled_
= true;
2702 draw_buffers_explicitly_enabled_
= true;
2703 // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation.
2706 state_
.attrib_values
.resize(group_
->max_vertex_attribs());
2707 vertex_array_manager_
.reset(new VertexArrayManager());
2709 GLuint default_vertex_attrib_service_id
= 0;
2710 if (features().native_vertex_array_object
) {
2711 glGenVertexArraysOES(1, &default_vertex_attrib_service_id
);
2712 glBindVertexArrayOES(default_vertex_attrib_service_id
);
2715 state_
.default_vertex_attrib_manager
=
2716 CreateVertexAttribManager(0, default_vertex_attrib_service_id
, false);
2718 state_
.default_vertex_attrib_manager
->Initialize(
2719 group_
->max_vertex_attribs(),
2720 feature_info_
->workarounds().init_vertex_attributes
);
2722 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2723 DoBindVertexArrayOES(0);
2725 query_manager_
.reset(new QueryManager(this, feature_info_
.get()));
2727 image_manager_
.reset(new ImageManager
);
2729 util_
.set_num_compressed_texture_formats(
2730 validators_
->compressed_texture_format
.GetValues().size());
2732 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
2733 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2734 // OpenGL ES 2.0 does not have this issue.
2735 glEnableVertexAttribArray(0);
2737 glGenBuffersARB(1, &attrib_0_buffer_id_
);
2738 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
2739 glVertexAttribPointer(0, 1, GL_FLOAT
, GL_FALSE
, 0, NULL
);
2740 glBindBuffer(GL_ARRAY_BUFFER
, 0);
2741 glGenBuffersARB(1, &fixed_attrib_buffer_id_
);
2743 state_
.texture_units
.resize(group_
->max_texture_units());
2744 for (uint32 tt
= 0; tt
< state_
.texture_units
.size(); ++tt
) {
2745 glActiveTexture(GL_TEXTURE0
+ tt
);
2746 // We want the last bind to be 2D.
2748 if (features().oes_egl_image_external
) {
2749 ref
= texture_manager()->GetDefaultTextureInfo(
2750 GL_TEXTURE_EXTERNAL_OES
);
2751 state_
.texture_units
[tt
].bound_texture_external_oes
= ref
;
2752 glBindTexture(GL_TEXTURE_EXTERNAL_OES
, ref
? ref
->service_id() : 0);
2754 if (features().arb_texture_rectangle
) {
2755 ref
= texture_manager()->GetDefaultTextureInfo(
2756 GL_TEXTURE_RECTANGLE_ARB
);
2757 state_
.texture_units
[tt
].bound_texture_rectangle_arb
= ref
;
2758 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, ref
? ref
->service_id() : 0);
2760 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP
);
2761 state_
.texture_units
[tt
].bound_texture_cube_map
= ref
;
2762 glBindTexture(GL_TEXTURE_CUBE_MAP
, ref
? ref
->service_id() : 0);
2763 ref
= texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D
);
2764 state_
.texture_units
[tt
].bound_texture_2d
= ref
;
2765 glBindTexture(GL_TEXTURE_2D
, ref
? ref
->service_id() : 0);
2767 glActiveTexture(GL_TEXTURE0
);
2770 // cache ALPHA_BITS result for re-use with clear behaviour
2771 GLint alpha_bits
= 0;
2774 if (attrib_parser
.samples
> 0 && attrib_parser
.sample_buffers
> 0 &&
2775 features().chromium_framebuffer_multisample
) {
2776 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2777 // max_sample_count must be initialized to a sane value. If
2778 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2779 GLint max_sample_count
= 1;
2780 glGetIntegerv(GL_MAX_SAMPLES_EXT
, &max_sample_count
);
2781 offscreen_target_samples_
= std::min(attrib_parser
.samples
,
2784 offscreen_target_samples_
= 1;
2786 offscreen_target_buffer_preserved_
= attrib_parser
.buffer_preserved
;
2788 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
2789 const bool rgb8_supported
=
2790 context_
->HasExtension("GL_OES_rgb8_rgba8");
2791 // The only available default render buffer formats in GLES2 have very
2792 // little precision. Don't enable multisampling unless 8-bit render
2793 // buffer formats are available--instead fall back to 8-bit textures.
2794 if (rgb8_supported
&& offscreen_target_samples_
> 1) {
2795 offscreen_target_color_format_
= attrib_parser
.alpha_size
> 0 ?
2798 offscreen_target_samples_
= 1;
2799 offscreen_target_color_format_
=
2800 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2805 // ANGLE only supports packed depth/stencil formats, so use it if it is
2807 const bool depth24_stencil8_supported
=
2808 feature_info_
->feature_flags().packed_depth24_stencil8
;
2809 VLOG(1) << "GL_OES_packed_depth_stencil "
2810 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2811 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2812 depth24_stencil8_supported
) {
2813 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2814 offscreen_target_stencil_format_
= 0;
2816 // It may be the case that this depth/stencil combination is not
2817 // supported, but this will be checked later by CheckFramebufferStatus.
2818 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2819 GL_DEPTH_COMPONENT16
: 0;
2820 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2821 GL_STENCIL_INDEX8
: 0;
2824 offscreen_target_color_format_
=
2825 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2829 // If depth is requested at all, use the packed depth stencil format if
2830 // it's available, as some desktop GL drivers don't support any non-packed
2831 // formats for depth attachments.
2832 const bool depth24_stencil8_supported
=
2833 feature_info_
->feature_flags().packed_depth24_stencil8
;
2834 VLOG(1) << "GL_EXT_packed_depth_stencil "
2835 << (depth24_stencil8_supported
? "" : "not ") << "supported.";
2837 if ((attrib_parser
.depth_size
> 0 || attrib_parser
.stencil_size
> 0) &&
2838 depth24_stencil8_supported
) {
2839 offscreen_target_depth_format_
= GL_DEPTH24_STENCIL8
;
2840 offscreen_target_stencil_format_
= 0;
2842 offscreen_target_depth_format_
= attrib_parser
.depth_size
> 0 ?
2843 GL_DEPTH_COMPONENT
: 0;
2844 offscreen_target_stencil_format_
= attrib_parser
.stencil_size
> 0 ?
2845 GL_STENCIL_INDEX
: 0;
2849 offscreen_saved_color_format_
=
2850 attrib_parser
.alpha_size
> 0 || workarounds().disable_gl_rgb_format
2854 // Create the target frame buffer. This is the one that the client renders
2856 offscreen_target_frame_buffer_
.reset(new BackFramebuffer(this));
2857 offscreen_target_frame_buffer_
->Create();
2858 // Due to GLES2 format limitations, either the color texture (for
2859 // non-multisampling) or the color render buffer (for multisampling) will be
2860 // attached to the offscreen frame buffer. The render buffer has more
2861 // limited formats available to it, but the texture can't do multisampling.
2862 if (IsOffscreenBufferMultisampled()) {
2863 offscreen_target_color_render_buffer_
.reset(new BackRenderbuffer(
2864 renderbuffer_manager(), memory_tracker(), &state_
));
2865 offscreen_target_color_render_buffer_
->Create();
2867 offscreen_target_color_texture_
.reset(new BackTexture(
2868 memory_tracker(), &state_
));
2869 offscreen_target_color_texture_
->Create();
2871 offscreen_target_depth_render_buffer_
.reset(new BackRenderbuffer(
2872 renderbuffer_manager(), memory_tracker(), &state_
));
2873 offscreen_target_depth_render_buffer_
->Create();
2874 offscreen_target_stencil_render_buffer_
.reset(new BackRenderbuffer(
2875 renderbuffer_manager(), memory_tracker(), &state_
));
2876 offscreen_target_stencil_render_buffer_
->Create();
2878 // Create the saved offscreen texture. The target frame buffer is copied
2879 // here when SwapBuffers is called.
2880 offscreen_saved_frame_buffer_
.reset(new BackFramebuffer(this));
2881 offscreen_saved_frame_buffer_
->Create();
2883 offscreen_saved_color_texture_
.reset(new BackTexture(
2884 memory_tracker(), &state_
));
2885 offscreen_saved_color_texture_
->Create();
2887 // Allocate the render buffers at their initial size and check the status
2888 // of the frame buffers is okay.
2889 if (!ResizeOffscreenFrameBuffer(offscreen_size
)) {
2890 LOG(ERROR
) << "Could not allocate offscreen buffer storage.";
2895 state_
.viewport_width
= offscreen_size
.width();
2896 state_
.viewport_height
= offscreen_size
.height();
2898 // Allocate the offscreen saved color texture.
2899 DCHECK(offscreen_saved_color_format_
);
2900 offscreen_saved_color_texture_
->AllocateStorage(
2901 gfx::Size(1, 1), offscreen_saved_color_format_
, true);
2903 offscreen_saved_frame_buffer_
->AttachRenderTexture(
2904 offscreen_saved_color_texture_
.get());
2905 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
2906 GL_FRAMEBUFFER_COMPLETE
) {
2907 LOG(ERROR
) << "Offscreen saved FBO was incomplete.";
2912 // Bind to the new default frame buffer (the offscreen target frame buffer).
2913 // This should now be associated with ID zero.
2914 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2916 glBindFramebufferEXT(GL_FRAMEBUFFER
, GetBackbufferServiceId());
2917 // These are NOT if the back buffer has these proprorties. They are
2918 // if we want the command buffer to enforce them regardless of what
2919 // the real backbuffer is assuming the real back buffer gives us more than
2920 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2921 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2922 // can't do anything about that.
2924 if (!surfaceless_
) {
2925 GLint depth_bits
= 0;
2926 GLint stencil_bits
= 0;
2928 bool default_fb
= (GetBackbufferServiceId() == 0);
2930 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
2931 glGetFramebufferAttachmentParameterivEXT(
2933 default_fb
? GL_BACK_LEFT
: GL_COLOR_ATTACHMENT0
,
2934 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &alpha_bits
);
2935 glGetFramebufferAttachmentParameterivEXT(
2937 default_fb
? GL_DEPTH
: GL_DEPTH_ATTACHMENT
,
2938 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &depth_bits
);
2939 glGetFramebufferAttachmentParameterivEXT(
2941 default_fb
? GL_STENCIL
: GL_STENCIL_ATTACHMENT
,
2942 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &stencil_bits
);
2944 glGetIntegerv(GL_ALPHA_BITS
, &alpha_bits
);
2945 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
2946 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
2949 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2950 // the user requested RGB then RGB. If the user did not specify a
2951 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2952 back_buffer_color_format_
=
2953 (attrib_parser
.alpha_size
!= 0 && alpha_bits
> 0) ? GL_RGBA
: GL_RGB
;
2954 back_buffer_has_depth_
= attrib_parser
.depth_size
!= 0 && depth_bits
> 0;
2955 back_buffer_has_stencil_
=
2956 attrib_parser
.stencil_size
!= 0 && stencil_bits
> 0;
2959 state_
.viewport_width
= surface
->GetSize().width();
2960 state_
.viewport_height
= surface
->GetSize().height();
2963 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2964 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2965 // isn't well documented; it was discovered in the Khronos OpenGL ES
2966 // mailing list archives. It also implicitly enables the desktop GL
2967 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2968 // variable in fragment shaders.
2969 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
2970 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE
);
2971 glEnable(GL_POINT_SPRITE
);
2974 has_robustness_extension_
=
2975 context
->HasExtension("GL_ARB_robustness") ||
2976 context
->HasExtension("GL_KHR_robustness") ||
2977 context
->HasExtension("GL_EXT_robustness");
2979 if (!InitializeShaderTranslator()) {
2983 GLint viewport_params
[4] = { 0 };
2984 glGetIntegerv(GL_MAX_VIEWPORT_DIMS
, viewport_params
);
2985 viewport_max_width_
= viewport_params
[0];
2986 viewport_max_height_
= viewport_params
[1];
2988 state_
.scissor_width
= state_
.viewport_width
;
2989 state_
.scissor_height
= state_
.viewport_height
;
2991 // Set all the default state because some GL drivers get it wrong.
2992 state_
.InitCapabilities(NULL
);
2993 state_
.InitState(NULL
);
2994 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
2996 DoBindBuffer(GL_ARRAY_BUFFER
, 0);
2997 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
2998 DoBindFramebuffer(GL_FRAMEBUFFER
, 0);
2999 DoBindRenderbuffer(GL_RENDERBUFFER
, 0);
3000 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM
, 0);
3002 bool call_gl_clear
= !surfaceless_
;
3003 #if defined(OS_ANDROID)
3004 // Temporary workaround for Android WebView because this clear ignores the
3005 // clip and corrupts that external UI of the App. Not calling glClear is ok
3006 // because the system already clears the buffer before each draw. Proper
3007 // fix might be setting the scissor clip properly before initialize. See
3008 // crbug.com/259023 for details.
3009 call_gl_clear
= surface_
->GetHandle();
3011 if (call_gl_clear
) {
3012 // On configs where we report no alpha, if the underlying surface has
3013 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3014 bool clear_alpha
= back_buffer_color_format_
== GL_RGB
&& alpha_bits
> 0;
3016 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
3019 // Clear the backbuffer.
3020 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3022 // Restore alpha clear value if we changed it.
3024 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
3028 supports_post_sub_buffer_
= surface
->SupportsPostSubBuffer();
3029 if (feature_info_
->workarounds()
3030 .disable_post_sub_buffers_for_onscreen_surfaces
&&
3031 !surface
->IsOffscreen())
3032 supports_post_sub_buffer_
= false;
3034 if (feature_info_
->workarounds().reverse_point_sprite_coord_origin
) {
3035 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN
, GL_LOWER_LEFT
);
3038 if (feature_info_
->workarounds().unbind_fbo_on_context_switch
) {
3039 context_
->SetUnbindFboOnMakeCurrent();
3042 // Only compositor contexts are known to use only the subset of GL
3043 // that can be safely migrated between the iGPU and the dGPU. Mark
3044 // those contexts as safe to forcibly transition between the GPUs.
3045 // http://crbug.com/180876, http://crbug.com/227228
3047 context_
->SetSafeToForceGpuSwitch();
3049 if (workarounds().gl_clear_broken
) {
3050 DCHECK(!clear_framebuffer_blit_
.get());
3051 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3052 clear_framebuffer_blit_
.reset(new ClearFramebufferResourceManager(this));
3053 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR
)
3057 framebuffer_manager()->AddObserver(this);
3062 Capabilities
GLES2DecoderImpl::GetCapabilities() {
3063 DCHECK(initialized());
3065 caps
.VisitPrecisions([](GLenum shader
, GLenum type
,
3066 Capabilities::ShaderPrecision
* shader_precision
) {
3067 GLint range
[2] = {0, 0};
3068 GLint precision
= 0;
3069 GetShaderPrecisionFormatImpl(shader
, type
, range
, &precision
);
3070 shader_precision
->min_range
= range
[0];
3071 shader_precision
->max_range
= range
[1];
3072 shader_precision
->precision
= precision
;
3074 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
3075 &caps
.max_combined_texture_image_units
);
3076 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &caps
.max_cube_map_texture_size
);
3077 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
3078 &caps
.max_fragment_uniform_vectors
);
3079 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE
, &caps
.max_renderbuffer_size
);
3080 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &caps
.max_texture_image_units
);
3081 DoGetIntegerv(GL_MAX_TEXTURE_SIZE
, &caps
.max_texture_size
);
3082 DoGetIntegerv(GL_MAX_VARYING_VECTORS
, &caps
.max_varying_vectors
);
3083 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS
, &caps
.max_vertex_attribs
);
3084 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
3085 &caps
.max_vertex_texture_image_units
);
3086 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
,
3087 &caps
.max_vertex_uniform_vectors
);
3088 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS
,
3089 &caps
.num_compressed_texture_formats
);
3090 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS
, &caps
.num_shader_binary_formats
);
3091 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM
,
3092 &caps
.bind_generates_resource_chromium
);
3093 if (unsafe_es3_apis_enabled()) {
3094 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3095 // but for now we clamp them to 32-bit max.
3096 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE
, &caps
.max_3d_texture_size
);
3097 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS
, &caps
.max_array_texture_layers
);
3098 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS
, &caps
.max_color_attachments
);
3099 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS
,
3100 &caps
.max_combined_fragment_uniform_components
);
3101 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS
,
3102 &caps
.max_combined_uniform_blocks
);
3103 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS
,
3104 &caps
.max_combined_vertex_uniform_components
);
3105 DoGetIntegerv(GL_MAX_DRAW_BUFFERS
, &caps
.max_draw_buffers
);
3106 DoGetInteger64v(GL_MAX_ELEMENT_INDEX
, &caps
.max_element_index
);
3107 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES
, &caps
.max_elements_indices
);
3108 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES
, &caps
.max_elements_vertices
);
3109 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
3110 &caps
.max_fragment_input_components
);
3111 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS
,
3112 &caps
.max_fragment_uniform_blocks
);
3113 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
,
3114 &caps
.max_fragment_uniform_components
);
3115 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET
,
3116 &caps
.max_program_texel_offset
);
3117 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT
, &caps
.max_server_wait_timeout
);
3118 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3120 if (caps
.max_server_wait_timeout
< 0)
3121 caps
.max_server_wait_timeout
= 0;
3122 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS
, &caps
.max_texture_lod_bias
);
3123 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS
,
3124 &caps
.max_transform_feedback_interleaved_components
);
3125 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
3126 &caps
.max_transform_feedback_separate_attribs
);
3127 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS
,
3128 &caps
.max_transform_feedback_separate_components
);
3129 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE
, &caps
.max_uniform_block_size
);
3130 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS
,
3131 &caps
.max_uniform_buffer_bindings
);
3132 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS
, &caps
.max_varying_components
);
3133 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
3134 &caps
.max_vertex_output_components
);
3135 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS
,
3136 &caps
.max_vertex_uniform_blocks
);
3137 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
,
3138 &caps
.max_vertex_uniform_components
);
3139 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET
, &caps
.min_program_texel_offset
);
3140 DoGetIntegerv(GL_NUM_EXTENSIONS
, &caps
.num_extensions
);
3141 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS
,
3142 &caps
.num_program_binary_formats
);
3143 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
3144 &caps
.uniform_buffer_offset_alignment
);
3145 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3146 caps
.major_version
= 3;
3147 caps
.minor_version
= 0;
3149 if (feature_info_
->feature_flags().multisampled_render_to_texture
||
3150 feature_info_
->feature_flags().chromium_framebuffer_multisample
||
3151 unsafe_es3_apis_enabled()) {
3152 DoGetIntegerv(GL_MAX_SAMPLES
, &caps
.max_samples
);
3155 caps
.egl_image_external
=
3156 feature_info_
->feature_flags().oes_egl_image_external
;
3157 caps
.texture_format_astc
=
3158 feature_info_
->feature_flags().ext_texture_format_astc
;
3159 caps
.texture_format_atc
=
3160 feature_info_
->feature_flags().ext_texture_format_atc
;
3161 caps
.texture_format_bgra8888
=
3162 feature_info_
->feature_flags().ext_texture_format_bgra8888
;
3163 caps
.texture_format_dxt1
=
3164 feature_info_
->feature_flags().ext_texture_format_dxt1
;
3165 caps
.texture_format_dxt5
=
3166 feature_info_
->feature_flags().ext_texture_format_dxt5
;
3167 caps
.texture_format_etc1
=
3168 feature_info_
->feature_flags().oes_compressed_etc1_rgb8_texture
;
3169 caps
.texture_format_etc1_npot
=
3170 caps
.texture_format_etc1
&& !workarounds().etc1_power_of_two_only
;
3171 caps
.texture_rectangle
= feature_info_
->feature_flags().arb_texture_rectangle
;
3172 caps
.texture_usage
= feature_info_
->feature_flags().angle_texture_usage
;
3173 caps
.texture_storage
= feature_info_
->feature_flags().ext_texture_storage
;
3174 caps
.discard_framebuffer
=
3175 feature_info_
->feature_flags().ext_discard_framebuffer
;
3176 caps
.sync_query
= feature_info_
->feature_flags().chromium_sync_query
;
3178 #if defined(OS_MACOSX)
3179 // This is unconditionally true on mac, no need to test for it at runtime.
3180 caps
.iosurface
= true;
3183 caps
.post_sub_buffer
= supports_post_sub_buffer_
;
3185 caps
.surfaceless
= surfaceless_
;
3187 caps
.blend_equation_advanced
=
3188 feature_info_
->feature_flags().blend_equation_advanced
;
3189 caps
.blend_equation_advanced_coherent
=
3190 feature_info_
->feature_flags().blend_equation_advanced_coherent
;
3191 caps
.texture_rg
= feature_info_
->feature_flags().ext_texture_rg
;
3192 caps
.image_ycbcr_422
=
3193 feature_info_
->feature_flags().chromium_image_ycbcr_422
;
3194 caps
.max_copy_texture_chromium_size
=
3195 feature_info_
->workarounds().max_copy_texture_chromium_size
;
3196 caps
.render_buffer_format_bgra8888
=
3197 feature_info_
->feature_flags().ext_render_buffer_format_bgra8888
;
3198 caps
.occlusion_query_boolean
=
3199 feature_info_
->feature_flags().occlusion_query_boolean
;
3200 caps
.timer_queries
=
3201 query_manager_
->GPUTimingAvailable();
3205 void GLES2DecoderImpl::UpdateCapabilities() {
3206 util_
.set_num_compressed_texture_formats(
3207 validators_
->compressed_texture_format
.GetValues().size());
3208 util_
.set_num_shader_binary_formats(
3209 validators_
->shader_binary_format
.GetValues().size());
3212 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3213 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3214 if (feature_info_
->disable_shader_translator()) {
3217 ShBuiltInResources resources
;
3218 ShInitBuiltInResources(&resources
);
3219 resources
.MaxVertexAttribs
= group_
->max_vertex_attribs();
3220 resources
.MaxVertexUniformVectors
=
3221 group_
->max_vertex_uniform_vectors();
3222 resources
.MaxVaryingVectors
= group_
->max_varying_vectors();
3223 resources
.MaxVertexTextureImageUnits
=
3224 group_
->max_vertex_texture_image_units();
3225 resources
.MaxCombinedTextureImageUnits
= group_
->max_texture_units();
3226 resources
.MaxTextureImageUnits
= group_
->max_texture_image_units();
3227 resources
.MaxFragmentUniformVectors
=
3228 group_
->max_fragment_uniform_vectors();
3229 resources
.MaxDrawBuffers
= group_
->max_draw_buffers();
3230 resources
.MaxExpressionComplexity
= 256;
3231 resources
.MaxCallStackDepth
= 256;
3233 GLint range
[2] = { 0, 0 };
3234 GLint precision
= 0;
3235 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER
, GL_HIGH_FLOAT
,
3237 resources
.FragmentPrecisionHigh
=
3238 PrecisionMeetsSpecForHighpFloat(range
[0], range
[1], precision
);
3240 if (IsWebGLContext()) {
3241 resources
.OES_standard_derivatives
= derivatives_explicitly_enabled_
;
3242 resources
.EXT_frag_depth
= frag_depth_explicitly_enabled_
;
3243 resources
.EXT_draw_buffers
= draw_buffers_explicitly_enabled_
;
3244 if (!draw_buffers_explicitly_enabled_
)
3245 resources
.MaxDrawBuffers
= 1;
3246 resources
.EXT_shader_texture_lod
= shader_texture_lod_explicitly_enabled_
;
3247 resources
.NV_draw_buffers
=
3248 draw_buffers_explicitly_enabled_
&& features().nv_draw_buffers
;
3250 resources
.OES_standard_derivatives
=
3251 features().oes_standard_derivatives
? 1 : 0;
3252 resources
.ARB_texture_rectangle
=
3253 features().arb_texture_rectangle
? 1 : 0;
3254 resources
.OES_EGL_image_external
=
3255 features().oes_egl_image_external
? 1 : 0;
3256 resources
.EXT_draw_buffers
=
3257 features().ext_draw_buffers
? 1 : 0;
3258 resources
.EXT_frag_depth
=
3259 features().ext_frag_depth
? 1 : 0;
3260 resources
.EXT_shader_texture_lod
=
3261 features().ext_shader_texture_lod
? 1 : 0;
3262 resources
.NV_draw_buffers
=
3263 features().nv_draw_buffers
? 1 : 0;
3266 ShShaderSpec shader_spec
;
3267 if (IsWebGLContext()) {
3268 shader_spec
= webgl_version_
== 2 ? SH_WEBGL2_SPEC
: SH_WEBGL_SPEC
;
3270 shader_spec
= unsafe_es3_apis_enabled() ? SH_GLES3_SPEC
: SH_GLES2_SPEC
;
3273 if ((shader_spec
== SH_WEBGL_SPEC
|| shader_spec
== SH_WEBGL2_SPEC
) &&
3274 features().enable_shader_name_hashing
)
3275 resources
.HashFunction
= &CityHash64
;
3277 resources
.HashFunction
= NULL
;
3279 int driver_bug_workarounds
= 0;
3280 if (workarounds().needs_glsl_built_in_function_emulation
)
3281 driver_bug_workarounds
|= SH_EMULATE_BUILT_IN_FUNCTIONS
;
3282 if (workarounds().init_gl_position_in_vertex_shader
)
3283 driver_bug_workarounds
|= SH_INIT_GL_POSITION
;
3284 if (workarounds().unfold_short_circuit_as_ternary_operation
)
3285 driver_bug_workarounds
|= SH_UNFOLD_SHORT_CIRCUIT
;
3286 if (workarounds().init_varyings_without_static_use
)
3287 driver_bug_workarounds
|= SH_INIT_VARYINGS_WITHOUT_STATIC_USE
;
3288 if (workarounds().unroll_for_loop_with_sampler_array_index
)
3289 driver_bug_workarounds
|= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX
;
3290 if (workarounds().scalarize_vec_and_mat_constructor_args
)
3291 driver_bug_workarounds
|= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS
;
3292 if (workarounds().regenerate_struct_names
)
3293 driver_bug_workarounds
|= SH_REGENERATE_STRUCT_NAMES
;
3294 if (workarounds().remove_pow_with_constant_exponent
)
3295 driver_bug_workarounds
|= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT
;
3297 if (base::CommandLine::InitializedForCurrentProcess() &&
3298 base::CommandLine::ForCurrentProcess()->HasSwitch(
3299 switches::kEmulateShaderPrecision
))
3300 resources
.WEBGL_debug_shader_precision
= true;
3302 ShShaderOutput shader_output_language
=
3303 ShaderTranslator::GetShaderOutputLanguageForContext(
3304 feature_info_
->gl_version_info());
3306 vertex_translator_
= shader_translator_cache()->GetTranslator(
3307 GL_VERTEX_SHADER
, shader_spec
, &resources
, shader_output_language
,
3308 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3309 if (!vertex_translator_
.get()) {
3310 LOG(ERROR
) << "Could not initialize vertex shader translator.";
3315 fragment_translator_
= shader_translator_cache()->GetTranslator(
3316 GL_FRAGMENT_SHADER
, shader_spec
, &resources
, shader_output_language
,
3317 static_cast<ShCompileOptions
>(driver_bug_workarounds
));
3318 if (!fragment_translator_
.get()) {
3319 LOG(ERROR
) << "Could not initialize fragment shader translator.";
3326 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n
, const GLuint
* client_ids
) {
3327 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3328 if (GetBuffer(client_ids
[ii
])) {
3332 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3333 glGenBuffersARB(n
, service_ids
.get());
3334 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3335 CreateBuffer(client_ids
[ii
], service_ids
[ii
]);
3340 bool GLES2DecoderImpl::GenFramebuffersHelper(
3341 GLsizei n
, const GLuint
* client_ids
) {
3342 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3343 if (GetFramebuffer(client_ids
[ii
])) {
3347 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3348 glGenFramebuffersEXT(n
, service_ids
.get());
3349 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3350 CreateFramebuffer(client_ids
[ii
], service_ids
[ii
]);
3355 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3356 GLsizei n
, const GLuint
* client_ids
) {
3357 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3358 if (GetRenderbuffer(client_ids
[ii
])) {
3362 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3363 glGenRenderbuffersEXT(n
, service_ids
.get());
3364 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3365 CreateRenderbuffer(client_ids
[ii
], service_ids
[ii
]);
3370 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n
,
3371 const GLuint
* client_ids
) {
3372 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3373 if (GetValuebuffer(client_ids
[ii
])) {
3377 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3378 CreateValuebuffer(client_ids
[ii
]);
3383 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n
, const GLuint
* client_ids
) {
3384 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3385 if (GetTexture(client_ids
[ii
])) {
3389 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
3390 glGenTextures(n
, service_ids
.get());
3391 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3392 CreateTexture(client_ids
[ii
], service_ids
[ii
]);
3397 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id
,
3399 GLuint last_client_id
;
3400 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3403 if (path_manager()->HasPathsInRange(first_client_id
, last_client_id
))
3406 GLuint first_service_id
= glGenPathsNV(range
);
3407 if (first_service_id
== 0) {
3408 // We have to fail the connection here, because client has already
3409 // succeeded in allocating the ids. This happens if we allocate
3410 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3414 // GenPathsNV does not wrap.
3415 DCHECK(first_service_id
+ range
- 1 >= first_service_id
);
3417 path_manager()->CreatePathRange(first_client_id
, last_client_id
,
3423 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id
,
3425 GLuint last_client_id
;
3426 if (!SafeAddUint32(first_client_id
, range
- 1, &last_client_id
))
3429 path_manager()->RemovePaths(first_client_id
, last_client_id
);
3433 void GLES2DecoderImpl::DeleteBuffersHelper(
3434 GLsizei n
, const GLuint
* client_ids
) {
3435 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3436 Buffer
* buffer
= GetBuffer(client_ids
[ii
]);
3437 if (buffer
&& !buffer
->IsDeleted()) {
3438 buffer
->RemoveMappedRange();
3439 state_
.RemoveBoundBuffer(buffer
);
3440 RemoveBuffer(client_ids
[ii
]);
3445 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3446 GLsizei n
, const GLuint
* client_ids
) {
3447 bool supports_separate_framebuffer_binds
=
3448 features().chromium_framebuffer_multisample
;
3450 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3451 Framebuffer
* framebuffer
=
3452 GetFramebuffer(client_ids
[ii
]);
3453 if (framebuffer
&& !framebuffer
->IsDeleted()) {
3454 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
3455 GLenum target
= supports_separate_framebuffer_binds
?
3456 GL_DRAW_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3458 // Unbind attachments on FBO before deletion.
3459 if (workarounds().unbind_attachments_on_bound_render_fbo_delete
)
3460 framebuffer
->DoUnbindGLAttachmentsForWorkaround(target
);
3462 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3463 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
3464 framebuffer_state_
.clear_state_dirty
= true;
3466 if (framebuffer
== framebuffer_state_
.bound_read_framebuffer
.get()) {
3467 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3468 GLenum target
= supports_separate_framebuffer_binds
?
3469 GL_READ_FRAMEBUFFER_EXT
: GL_FRAMEBUFFER
;
3470 glBindFramebufferEXT(target
, GetBackbufferServiceId());
3473 RemoveFramebuffer(client_ids
[ii
]);
3478 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3479 GLsizei n
, const GLuint
* client_ids
) {
3480 bool supports_separate_framebuffer_binds
=
3481 features().chromium_framebuffer_multisample
;
3482 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3483 Renderbuffer
* renderbuffer
=
3484 GetRenderbuffer(client_ids
[ii
]);
3485 if (renderbuffer
&& !renderbuffer
->IsDeleted()) {
3486 if (state_
.bound_renderbuffer
.get() == renderbuffer
) {
3487 state_
.bound_renderbuffer
= NULL
;
3489 // Unbind from current framebuffers.
3490 if (supports_separate_framebuffer_binds
) {
3491 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3492 framebuffer_state_
.bound_read_framebuffer
3493 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT
, renderbuffer
);
3495 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3496 framebuffer_state_
.bound_draw_framebuffer
3497 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT
, renderbuffer
);
3500 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3501 framebuffer_state_
.bound_draw_framebuffer
3502 ->UnbindRenderbuffer(GL_FRAMEBUFFER
, renderbuffer
);
3505 framebuffer_state_
.clear_state_dirty
= true;
3506 RemoveRenderbuffer(client_ids
[ii
]);
3511 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3513 const GLuint
* client_ids
) {
3514 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3515 Valuebuffer
* valuebuffer
= GetValuebuffer(client_ids
[ii
]);
3517 if (state_
.bound_valuebuffer
.get() == valuebuffer
) {
3518 state_
.bound_valuebuffer
= NULL
;
3520 RemoveValuebuffer(client_ids
[ii
]);
3525 void GLES2DecoderImpl::DeleteTexturesHelper(
3526 GLsizei n
, const GLuint
* client_ids
) {
3527 bool supports_separate_framebuffer_binds
=
3528 features().chromium_framebuffer_multisample
;
3529 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
3530 TextureRef
* texture_ref
= GetTexture(client_ids
[ii
]);
3532 Texture
* texture
= texture_ref
->texture();
3533 if (texture
->IsAttachedToFramebuffer()) {
3534 framebuffer_state_
.clear_state_dirty
= true;
3536 // Unbind texture_ref from texture_ref units.
3537 state_
.UnbindTexture(texture_ref
);
3539 // Unbind from current framebuffers.
3540 if (supports_separate_framebuffer_binds
) {
3541 if (framebuffer_state_
.bound_read_framebuffer
.get()) {
3542 framebuffer_state_
.bound_read_framebuffer
3543 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT
, texture_ref
);
3545 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3546 framebuffer_state_
.bound_draw_framebuffer
3547 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT
, texture_ref
);
3550 if (framebuffer_state_
.bound_draw_framebuffer
.get()) {
3551 framebuffer_state_
.bound_draw_framebuffer
3552 ->UnbindTexture(GL_FRAMEBUFFER
, texture_ref
);
3555 #if defined(OS_MACOSX)
3556 GLuint service_id
= texture
->service_id();
3557 if (texture
->target() == GL_TEXTURE_RECTANGLE_ARB
) {
3558 ReleaseIOSurfaceForTexture(service_id
);
3561 RemoveTexture(client_ids
[ii
]);
3566 // } // anonymous namespace
3568 bool GLES2DecoderImpl::MakeCurrent() {
3569 if (!context_
.get())
3572 if (WasContextLost()) {
3573 LOG(ERROR
) << " GLES2DecoderImpl: Trying to make lost context current.";
3577 if (!context_
->MakeCurrent(surface_
.get())) {
3578 LOG(ERROR
) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3579 MarkContextLost(error::kMakeCurrentFailed
);
3580 group_
->LoseContexts(error::kUnknown
);
3584 if (CheckResetStatus()) {
3586 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3587 group_
->LoseContexts(error::kUnknown
);
3591 ProcessFinishedAsyncTransfers();
3593 // Rebind the FBO if it was unbound by the context.
3594 if (workarounds().unbind_fbo_on_context_switch
)
3595 RestoreFramebufferBindings();
3597 framebuffer_state_
.clear_state_dirty
= true;
3602 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3603 ProcessPendingReadPixels(false);
3604 if (engine() && query_manager_
.get())
3605 query_manager_
->ProcessPendingTransferQueries();
3608 static void RebindCurrentFramebuffer(
3610 Framebuffer
* framebuffer
,
3611 GLuint back_buffer_service_id
) {
3612 GLuint framebuffer_id
= framebuffer
? framebuffer
->service_id() : 0;
3614 if (framebuffer_id
== 0) {
3615 framebuffer_id
= back_buffer_service_id
;
3618 glBindFramebufferEXT(target
, framebuffer_id
);
3621 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3622 framebuffer_state_
.clear_state_dirty
= true;
3624 if (!features().chromium_framebuffer_multisample
) {
3625 RebindCurrentFramebuffer(
3627 framebuffer_state_
.bound_draw_framebuffer
.get(),
3628 GetBackbufferServiceId());
3630 RebindCurrentFramebuffer(
3631 GL_READ_FRAMEBUFFER_EXT
,
3632 framebuffer_state_
.bound_read_framebuffer
.get(),
3633 GetBackbufferServiceId());
3634 RebindCurrentFramebuffer(
3635 GL_DRAW_FRAMEBUFFER_EXT
,
3636 framebuffer_state_
.bound_draw_framebuffer
.get(),
3637 GetBackbufferServiceId());
3642 bool GLES2DecoderImpl::CheckFramebufferValid(
3643 Framebuffer
* framebuffer
,
3644 GLenum target
, const char* func_name
) {
3648 if (backbuffer_needs_clear_bits_
) {
3649 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3650 offscreen_target_color_format_
) & 0x0008) != 0 ? 0 : 1.f
);
3651 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
3653 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
3654 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
3656 state_
.SetDeviceDepthMask(GL_TRUE
);
3657 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
3658 bool reset_draw_buffer
= false;
3659 if ((backbuffer_needs_clear_bits_
& GL_COLOR_BUFFER_BIT
) != 0 &&
3660 back_buffer_draw_buffer_
== GL_NONE
) {
3661 reset_draw_buffer
= true;
3662 GLenum buf
= GL_BACK
;
3663 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3664 buf
= GL_COLOR_ATTACHMENT0
;
3665 glDrawBuffersARB(1, &buf
);
3667 glClear(backbuffer_needs_clear_bits_
);
3668 if (reset_draw_buffer
) {
3669 GLenum buf
= GL_NONE
;
3670 glDrawBuffersARB(1, &buf
);
3672 backbuffer_needs_clear_bits_
= 0;
3673 RestoreClearState();
3678 if (framebuffer_manager()->IsComplete(framebuffer
)) {
3682 GLenum completeness
= framebuffer
->IsPossiblyComplete();
3683 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
3685 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
, "framebuffer incomplete");
3689 // Are all the attachments cleared?
3690 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3691 texture_manager()->HaveUnclearedMips()) {
3692 if (!framebuffer
->IsCleared()) {
3693 // Can we clear them?
3694 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3695 GL_FRAMEBUFFER_COMPLETE
) {
3697 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3698 "framebuffer incomplete (clear)");
3701 ClearUnclearedAttachments(target
, framebuffer
);
3705 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3706 if (framebuffer
->GetStatus(texture_manager(), target
) !=
3707 GL_FRAMEBUFFER_COMPLETE
) {
3709 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3710 "framebuffer incomplete (check)");
3713 framebuffer_manager()->MarkAsComplete(framebuffer
);
3716 // NOTE: At this point we don't know if the framebuffer is complete but
3717 // we DO know that everything that needs to be cleared has been cleared.
3721 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name
) {
3722 if (!features().chromium_framebuffer_multisample
) {
3723 bool valid
= CheckFramebufferValid(
3724 framebuffer_state_
.bound_draw_framebuffer
.get(), GL_FRAMEBUFFER_EXT
,
3732 return CheckFramebufferValid(framebuffer_state_
.bound_draw_framebuffer
.get(),
3733 GL_DRAW_FRAMEBUFFER_EXT
,
3735 CheckFramebufferValid(framebuffer_state_
.bound_read_framebuffer
.get(),
3736 GL_READ_FRAMEBUFFER_EXT
,
3740 bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid(const char* func_name
) {
3741 Framebuffer
* framebuffer
= framebuffer_state_
.bound_draw_framebuffer
.get();
3743 // Assume the default back buffer is always complete.
3746 if (!framebuffer_manager()->IsComplete(framebuffer
)) {
3747 if (framebuffer
->GetStatus(texture_manager(), GL_DRAW_FRAMEBUFFER
) !=
3748 GL_FRAMEBUFFER_COMPLETE
) {
3750 GL_INVALID_FRAMEBUFFER_OPERATION
, func_name
,
3751 "framebuffer incomplete (check)");
3754 framebuffer_manager()->MarkAsComplete(framebuffer
);
3759 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3760 const char* func_name
) {
3761 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3762 framebuffer_state_
.bound_read_framebuffer
.get() :
3763 framebuffer_state_
.bound_draw_framebuffer
.get();
3766 if (framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
) == NULL
) {
3768 GL_INVALID_OPERATION
, func_name
, "no color image attached");
3774 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3775 TextureRef
* texture
, GLint level
) {
3776 Framebuffer
* framebuffer
= features().chromium_framebuffer_multisample
?
3777 framebuffer_state_
.bound_read_framebuffer
.get() :
3778 framebuffer_state_
.bound_draw_framebuffer
.get();
3781 const Framebuffer::Attachment
* attachment
= framebuffer
->GetAttachment(
3782 GL_COLOR_ATTACHMENT0
);
3785 return attachment
->FormsFeedbackLoop(texture
, level
);
3788 gfx::Size
GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3789 Framebuffer
* framebuffer
=
3790 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3791 if (framebuffer
!= NULL
) {
3792 const Framebuffer::Attachment
* attachment
=
3793 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
3795 return gfx::Size(attachment
->width(), attachment
->height());
3797 return gfx::Size(0, 0);
3798 } else if (offscreen_target_frame_buffer_
.get()) {
3799 return offscreen_size_
;
3801 return surface_
->GetSize();
3805 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3806 Framebuffer
* framebuffer
=
3807 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3809 return framebuffer
->GetReadBufferTextureType();
3810 } else { // Back buffer.
3811 if (back_buffer_read_buffer_
== GL_NONE
)
3813 return GL_UNSIGNED_BYTE
;
3817 GLenum
GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3818 Framebuffer
* framebuffer
=
3819 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
);
3821 return framebuffer
->GetReadBufferInternalFormat();
3822 } else { // Back buffer.
3823 if (back_buffer_read_buffer_
== GL_NONE
)
3825 if (offscreen_target_frame_buffer_
.get()) {
3826 return offscreen_target_color_format_
;
3828 return back_buffer_color_format_
;
3832 GLenum
GLES2DecoderImpl::GetBoundColorDrawBufferInternalFormat(
3833 GLint drawbuffer_i
) {
3834 DCHECK(drawbuffer_i
>= 0 &&
3835 drawbuffer_i
< static_cast<GLint
>(group_
->max_draw_buffers()));
3836 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER
);
3840 GLenum drawbuffer
= static_cast<GLenum
>(GL_DRAW_BUFFER0
+ drawbuffer_i
);
3841 if (framebuffer
->GetDrawBuffer(drawbuffer
) == GL_NONE
) {
3844 GLenum attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer_i
);
3845 const Framebuffer::Attachment
* buffer
=
3846 framebuffer
->GetAttachment(attachment
);
3850 return buffer
->internal_format();
3853 void GLES2DecoderImpl::MarkDrawBufferAsCleared(
3854 GLenum buffer
, GLint drawbuffer_i
) {
3855 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER
);
3858 GLenum attachment
= 0;
3861 DCHECK(drawbuffer_i
>= 0 &&
3862 drawbuffer_i
< static_cast<GLint
>(group_
->max_draw_buffers()));
3863 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer_i
);
3866 attachment
= GL_DEPTH
;
3869 attachment
= GL_STENCIL
;
3872 // Caller is responsible for breaking GL_DEPTH_STENCIL into GL_DEPTH and
3876 framebuffer
->MarkAttachmentAsCleared(
3877 renderbuffer_manager(), texture_manager(), attachment
, true);
3880 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3881 if (!offscreen_saved_color_texture_info_
.get())
3883 GLenum target
= offscreen_saved_color_texture_info_
->texture()->target();
3884 glBindTexture(target
, offscreen_saved_color_texture_info_
->service_id());
3885 texture_manager()->SetLevelInfo(
3886 offscreen_saved_color_texture_info_
.get(), GL_TEXTURE_2D
,
3888 GL_RGBA
, offscreen_size_
.width(), offscreen_size_
.height(),
3891 GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(offscreen_size_
));
3892 texture_manager()->SetParameteri(
3893 "UpdateParentTextureInfo",
3895 offscreen_saved_color_texture_info_
.get(),
3896 GL_TEXTURE_MAG_FILTER
,
3898 texture_manager()->SetParameteri(
3899 "UpdateParentTextureInfo",
3901 offscreen_saved_color_texture_info_
.get(),
3902 GL_TEXTURE_MIN_FILTER
,
3904 texture_manager()->SetParameteri(
3905 "UpdateParentTextureInfo",
3907 offscreen_saved_color_texture_info_
.get(),
3910 texture_manager()->SetParameteri(
3911 "UpdateParentTextureInfo",
3913 offscreen_saved_color_texture_info_
.get(),
3916 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
3918 glBindTexture(target
, texture_ref
? texture_ref
->service_id() : 0);
3921 void GLES2DecoderImpl::SetResizeCallback(
3922 const base::Callback
<void(gfx::Size
, float)>& callback
) {
3923 resize_callback_
= callback
;
3926 Logger
* GLES2DecoderImpl::GetLogger() {
3930 void GLES2DecoderImpl::BeginDecoding() {
3931 gpu_tracer_
->BeginDecoding();
3932 gpu_trace_commands_
= gpu_tracer_
->IsTracing() && *gpu_decoder_category_
;
3933 gpu_debug_commands_
= log_commands() || debug() || gpu_trace_commands_
;
3934 query_manager_
->ProcessFrameBeginUpdates();
3937 void GLES2DecoderImpl::EndDecoding() {
3938 gpu_tracer_
->EndDecoding();
3941 ErrorState
* GLES2DecoderImpl::GetErrorState() {
3942 return state_
.GetErrorState();
3945 void GLES2DecoderImpl::SetShaderCacheCallback(
3946 const ShaderCacheCallback
& callback
) {
3947 shader_cache_callback_
= callback
;
3950 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3951 const WaitSyncPointCallback
& callback
) {
3952 wait_sync_point_callback_
= callback
;
3955 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id
,
3956 uint32
* service_texture_id
) {
3957 TextureRef
* texture_ref
= texture_manager()->GetTexture(client_texture_id
);
3959 *service_texture_id
= texture_ref
->service_id();
3965 uint32
GLES2DecoderImpl::GetTextureUploadCount() {
3966 return texture_state_
.texture_upload_count
;
3969 base::TimeDelta
GLES2DecoderImpl::GetTotalTextureUploadTime() {
3970 return texture_state_
.total_texture_upload_time
;
3973 base::TimeDelta
GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3974 return total_processing_commands_time_
;
3977 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time
) {
3978 total_processing_commands_time_
+= time
;
3981 void GLES2DecoderImpl::Destroy(bool have_context
) {
3985 DCHECK(!have_context
|| context_
->IsCurrent(NULL
));
3987 // Unbind everything.
3988 state_
.vertex_attrib_manager
= NULL
;
3989 state_
.default_vertex_attrib_manager
= NULL
;
3990 state_
.texture_units
.clear();
3991 state_
.bound_array_buffer
= NULL
;
3992 state_
.bound_copy_read_buffer
= NULL
;
3993 state_
.bound_copy_write_buffer
= NULL
;
3994 state_
.bound_pixel_pack_buffer
= NULL
;
3995 state_
.bound_pixel_unpack_buffer
= NULL
;
3996 state_
.bound_transform_feedback_buffer
= NULL
;
3997 state_
.bound_uniform_buffer
= NULL
;
3998 framebuffer_state_
.bound_read_framebuffer
= NULL
;
3999 framebuffer_state_
.bound_draw_framebuffer
= NULL
;
4000 state_
.bound_renderbuffer
= NULL
;
4001 state_
.bound_valuebuffer
= NULL
;
4003 if (offscreen_saved_color_texture_info_
.get()) {
4004 DCHECK(offscreen_target_color_texture_
);
4005 DCHECK_EQ(offscreen_saved_color_texture_info_
->service_id(),
4006 offscreen_saved_color_texture_
->id());
4007 offscreen_saved_color_texture_
->Invalidate();
4008 offscreen_saved_color_texture_info_
= NULL
;
4011 if (copy_texture_CHROMIUM_
.get()) {
4012 copy_texture_CHROMIUM_
->Destroy();
4013 copy_texture_CHROMIUM_
.reset();
4016 clear_framebuffer_blit_
.reset();
4018 if (state_
.current_program
.get()) {
4019 program_manager()->UnuseProgram(shader_manager(),
4020 state_
.current_program
.get());
4023 if (attrib_0_buffer_id_
) {
4024 glDeleteBuffersARB(1, &attrib_0_buffer_id_
);
4026 if (fixed_attrib_buffer_id_
) {
4027 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_
);
4030 if (validation_texture_
) {
4031 glDeleteTextures(1, &validation_texture_
);
4032 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_
);
4033 glDeleteFramebuffersEXT(1, &validation_fbo_
);
4036 if (offscreen_target_frame_buffer_
.get())
4037 offscreen_target_frame_buffer_
->Destroy();
4038 if (offscreen_target_color_texture_
.get())
4039 offscreen_target_color_texture_
->Destroy();
4040 if (offscreen_target_color_render_buffer_
.get())
4041 offscreen_target_color_render_buffer_
->Destroy();
4042 if (offscreen_target_depth_render_buffer_
.get())
4043 offscreen_target_depth_render_buffer_
->Destroy();
4044 if (offscreen_target_stencil_render_buffer_
.get())
4045 offscreen_target_stencil_render_buffer_
->Destroy();
4046 if (offscreen_saved_frame_buffer_
.get())
4047 offscreen_saved_frame_buffer_
->Destroy();
4048 if (offscreen_saved_color_texture_
.get())
4049 offscreen_saved_color_texture_
->Destroy();
4050 if (offscreen_resolved_frame_buffer_
.get())
4051 offscreen_resolved_frame_buffer_
->Destroy();
4052 if (offscreen_resolved_color_texture_
.get())
4053 offscreen_resolved_color_texture_
->Destroy();
4055 if (offscreen_target_frame_buffer_
.get())
4056 offscreen_target_frame_buffer_
->Invalidate();
4057 if (offscreen_target_color_texture_
.get())
4058 offscreen_target_color_texture_
->Invalidate();
4059 if (offscreen_target_color_render_buffer_
.get())
4060 offscreen_target_color_render_buffer_
->Invalidate();
4061 if (offscreen_target_depth_render_buffer_
.get())
4062 offscreen_target_depth_render_buffer_
->Invalidate();
4063 if (offscreen_target_stencil_render_buffer_
.get())
4064 offscreen_target_stencil_render_buffer_
->Invalidate();
4065 if (offscreen_saved_frame_buffer_
.get())
4066 offscreen_saved_frame_buffer_
->Invalidate();
4067 if (offscreen_saved_color_texture_
.get())
4068 offscreen_saved_color_texture_
->Invalidate();
4069 if (offscreen_resolved_frame_buffer_
.get())
4070 offscreen_resolved_frame_buffer_
->Invalidate();
4071 if (offscreen_resolved_color_texture_
.get())
4072 offscreen_resolved_color_texture_
->Invalidate();
4075 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4076 // Otherwise, we can leak objects. http://crbug.com/258772.
4077 // state_.current_program must be reset before group_ is reset because
4078 // the later deletes the ProgramManager object that referred by
4079 // state_.current_program object.
4080 state_
.current_program
= NULL
;
4082 copy_texture_CHROMIUM_
.reset();
4083 clear_framebuffer_blit_
.reset();
4085 if (query_manager_
.get()) {
4086 query_manager_
->Destroy(have_context
);
4087 query_manager_
.reset();
4090 if (vertex_array_manager_
.get()) {
4091 vertex_array_manager_
->Destroy(have_context
);
4092 vertex_array_manager_
.reset();
4095 if (image_manager_
.get()) {
4096 image_manager_
->Destroy(have_context
);
4097 image_manager_
.reset();
4100 offscreen_target_frame_buffer_
.reset();
4101 offscreen_target_color_texture_
.reset();
4102 offscreen_target_color_render_buffer_
.reset();
4103 offscreen_target_depth_render_buffer_
.reset();
4104 offscreen_target_stencil_render_buffer_
.reset();
4105 offscreen_saved_frame_buffer_
.reset();
4106 offscreen_saved_color_texture_
.reset();
4107 offscreen_resolved_frame_buffer_
.reset();
4108 offscreen_resolved_color_texture_
.reset();
4110 // Need to release these before releasing |group_| which may own the
4111 // ShaderTranslatorCache.
4112 fragment_translator_
= NULL
;
4113 vertex_translator_
= NULL
;
4115 // Destroy the GPU Tracer which may own some in process GPU Timings.
4117 gpu_tracer_
->Destroy(have_context
);
4118 gpu_tracer_
.reset();
4122 framebuffer_manager()->RemoveObserver(this);
4123 group_
->Destroy(this, have_context
);
4127 if (context_
.get()) {
4128 context_
->ReleaseCurrent(NULL
);
4132 #if defined(OS_MACOSX)
4133 for (TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.begin();
4134 it
!= texture_to_io_surface_map_
.end(); ++it
) {
4135 CFRelease(it
->second
);
4137 texture_to_io_surface_map_
.clear();
4141 void GLES2DecoderImpl::SetSurface(
4142 const scoped_refptr
<gfx::GLSurface
>& surface
) {
4143 DCHECK(context_
->IsCurrent(NULL
));
4144 DCHECK(surface_
.get());
4146 RestoreCurrentFramebufferBindings();
4149 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox
& mailbox
) {
4150 if (!offscreen_saved_color_texture_
.get()) {
4151 LOG(ERROR
) << "Called ProduceFrontBuffer on a non-offscreen context";
4154 if (!offscreen_saved_color_texture_info_
.get()) {
4155 GLuint service_id
= offscreen_saved_color_texture_
->id();
4156 offscreen_saved_color_texture_info_
= TextureRef::Create(
4157 texture_manager(), 0, service_id
);
4158 texture_manager()->SetTarget(offscreen_saved_color_texture_info_
.get(),
4160 UpdateParentTextureInfo();
4162 mailbox_manager()->ProduceTexture(
4163 mailbox
, offscreen_saved_color_texture_info_
->texture());
4166 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size
& size
) {
4167 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4168 if (!is_offscreen
) {
4169 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4170 << " with an onscreen framebuffer.";
4174 if (offscreen_size_
== size
)
4177 offscreen_size_
= size
;
4178 int w
= offscreen_size_
.width();
4179 int h
= offscreen_size_
.height();
4180 if (w
< 0 || h
< 0 || h
>= (INT_MAX
/ 4) / (w
? w
: 1)) {
4181 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4182 << "to allocate storage due to excessive dimensions.";
4186 // Reallocate the offscreen target buffers.
4187 DCHECK(offscreen_target_color_format_
);
4188 if (IsOffscreenBufferMultisampled()) {
4189 if (!offscreen_target_color_render_buffer_
->AllocateStorage(
4190 feature_info_
.get(),
4192 offscreen_target_color_format_
,
4193 offscreen_target_samples_
)) {
4194 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4195 << "to allocate storage for offscreen target color buffer.";
4199 if (!offscreen_target_color_texture_
->AllocateStorage(
4200 offscreen_size_
, offscreen_target_color_format_
, false)) {
4201 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4202 << "to allocate storage for offscreen target color texture.";
4206 if (offscreen_target_depth_format_
&&
4207 !offscreen_target_depth_render_buffer_
->AllocateStorage(
4208 feature_info_
.get(),
4210 offscreen_target_depth_format_
,
4211 offscreen_target_samples_
)) {
4212 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4213 << "to allocate storage for offscreen target depth buffer.";
4216 if (offscreen_target_stencil_format_
&&
4217 !offscreen_target_stencil_render_buffer_
->AllocateStorage(
4218 feature_info_
.get(),
4220 offscreen_target_stencil_format_
,
4221 offscreen_target_samples_
)) {
4222 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4223 << "to allocate storage for offscreen target stencil buffer.";
4227 // Attach the offscreen target buffers to the target frame buffer.
4228 if (IsOffscreenBufferMultisampled()) {
4229 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4230 GL_COLOR_ATTACHMENT0
,
4231 offscreen_target_color_render_buffer_
.get());
4233 offscreen_target_frame_buffer_
->AttachRenderTexture(
4234 offscreen_target_color_texture_
.get());
4236 if (offscreen_target_depth_format_
) {
4237 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4238 GL_DEPTH_ATTACHMENT
,
4239 offscreen_target_depth_render_buffer_
.get());
4241 const bool packed_depth_stencil
=
4242 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4243 if (packed_depth_stencil
) {
4244 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4245 GL_STENCIL_ATTACHMENT
,
4246 offscreen_target_depth_render_buffer_
.get());
4247 } else if (offscreen_target_stencil_format_
) {
4248 offscreen_target_frame_buffer_
->AttachRenderBuffer(
4249 GL_STENCIL_ATTACHMENT
,
4250 offscreen_target_stencil_render_buffer_
.get());
4253 if (offscreen_target_frame_buffer_
->CheckStatus() !=
4254 GL_FRAMEBUFFER_COMPLETE
) {
4255 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4256 << "because offscreen FBO was incomplete.";
4260 // Clear the target frame buffer.
4262 ScopedFrameBufferBinder
binder(this, offscreen_target_frame_buffer_
->id());
4263 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f
);
4264 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4266 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
4267 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
4269 state_
.SetDeviceDepthMask(GL_TRUE
);
4270 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
4271 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
4272 RestoreClearState();
4275 // Destroy the offscreen resolved framebuffers.
4276 if (offscreen_resolved_frame_buffer_
.get())
4277 offscreen_resolved_frame_buffer_
->Destroy();
4278 if (offscreen_resolved_color_texture_
.get())
4279 offscreen_resolved_color_texture_
->Destroy();
4280 offscreen_resolved_color_texture_
.reset();
4281 offscreen_resolved_frame_buffer_
.reset();
4286 error::Error
GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size
,
4287 const void* cmd_data
) {
4288 const gles2::cmds::ResizeCHROMIUM
& c
=
4289 *static_cast<const gles2::cmds::ResizeCHROMIUM
*>(cmd_data
);
4290 if (!offscreen_target_frame_buffer_
.get() && surface_
->DeferDraws())
4291 return error::kDeferCommandUntilLater
;
4293 GLuint width
= static_cast<GLuint
>(c
.width
);
4294 GLuint height
= static_cast<GLuint
>(c
.height
);
4295 GLfloat scale_factor
= c
.scale_factor
;
4296 TRACE_EVENT2("gpu", "glResizeChromium", "width", width
, "height", height
);
4298 width
= std::max(1U, width
);
4299 height
= std::max(1U, height
);
4301 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4302 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4303 // Make sure that we are done drawing to the back buffer before resizing.
4306 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
4308 if (!ResizeOffscreenFrameBuffer(gfx::Size(width
, height
))) {
4309 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because "
4310 << "ResizeOffscreenFrameBuffer failed.";
4311 return error::kLostContext
;
4315 if (!resize_callback_
.is_null()) {
4316 resize_callback_
.Run(gfx::Size(width
, height
), scale_factor
);
4317 DCHECK(context_
->IsCurrent(surface_
.get()));
4318 if (!context_
->IsCurrent(surface_
.get())) {
4319 LOG(ERROR
) << "GLES2DecoderImpl: Context lost because context no longer "
4320 << "current after resize callback.";
4321 return error::kLostContext
;
4325 return error::kNoError
;
4328 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id
) const {
4329 if (command_id
> kStartPoint
&& command_id
< kNumCommands
) {
4330 return gles2::GetCommandName(static_cast<CommandId
>(command_id
));
4332 return GetCommonCommandName(static_cast<cmd::CommandId
>(command_id
));
4335 // Decode a command, and call the corresponding GL functions.
4336 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4337 // of commands at once, and is now only used for tests that need to track
4338 // individual commands.
4339 error::Error
GLES2DecoderImpl::DoCommand(unsigned int command
,
4340 unsigned int arg_count
,
4341 const void* cmd_data
) {
4342 return DoCommands(1, cmd_data
, arg_count
+ 1, 0);
4345 // Decode multiple commands, and call the corresponding GL functions.
4346 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4347 // changed by a (malicious) client at any time, so if validation has to happen,
4348 // it should operate on a copy of them.
4349 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4350 // interest of performance in this critical execution loop.
4351 template <bool DebugImpl
>
4352 error::Error
GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands
,
4355 int* entries_processed
) {
4356 commands_to_process_
= num_commands
;
4357 error::Error result
= error::kNoError
;
4358 const CommandBufferEntry
* cmd_data
=
4359 static_cast<const CommandBufferEntry
*>(buffer
);
4360 int process_pos
= 0;
4361 unsigned int command
= 0;
4363 while (process_pos
< num_entries
&& result
== error::kNoError
&&
4364 commands_to_process_
--) {
4365 const unsigned int size
= cmd_data
->value_header
.size
;
4366 command
= cmd_data
->value_header
.command
;
4369 result
= error::kInvalidSize
;
4373 if (static_cast<int>(size
) + process_pos
> num_entries
) {
4374 result
= error::kOutOfBounds
;
4378 if (DebugImpl
&& log_commands()) {
4379 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "]"
4380 << "cmd: " << GetCommandName(command
);
4383 const unsigned int arg_count
= size
- 1;
4384 unsigned int command_index
= command
- kStartPoint
- 1;
4385 if (command_index
< arraysize(command_info
)) {
4386 const CommandInfo
& info
= command_info
[command_index
];
4387 unsigned int info_arg_count
= static_cast<unsigned int>(info
.arg_count
);
4388 if ((info
.arg_flags
== cmd::kFixed
&& arg_count
== info_arg_count
) ||
4389 (info
.arg_flags
== cmd::kAtLeastN
&& arg_count
>= info_arg_count
)) {
4390 bool doing_gpu_trace
= false;
4391 if (DebugImpl
&& gpu_trace_commands_
) {
4392 if (CMD_FLAG_GET_TRACE_LEVEL(info
.cmd_flags
) <= gpu_trace_level_
) {
4393 doing_gpu_trace
= true;
4394 gpu_tracer_
->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4395 GetCommandName(command
),
4400 uint32 immediate_data_size
= (arg_count
- info_arg_count
) *
4401 sizeof(CommandBufferEntry
); // NOLINT
4403 result
= (this->*info
.cmd_handler
)(immediate_data_size
, cmd_data
);
4405 if (DebugImpl
&& doing_gpu_trace
)
4406 gpu_tracer_
->End(kTraceDecoder
);
4408 if (DebugImpl
&& debug()) {
4410 while ((error
= glGetError()) != GL_NO_ERROR
) {
4411 LOG(ERROR
) << "[" << logger_
.GetLogPrefix() << "] "
4412 << "GL ERROR: " << GLES2Util::GetStringEnum(error
)
4413 << " : " << GetCommandName(command
);
4414 LOCAL_SET_GL_ERROR(error
, "DoCommand", "GL error from driver");
4418 result
= error::kInvalidArguments
;
4421 result
= DoCommonCommand(command
, arg_count
, cmd_data
);
4424 if (result
== error::kNoError
&&
4425 current_decoder_error_
!= error::kNoError
) {
4426 result
= current_decoder_error_
;
4427 current_decoder_error_
= error::kNoError
;
4430 if (result
!= error::kDeferCommandUntilLater
) {
4431 process_pos
+= size
;
4436 if (entries_processed
)
4437 *entries_processed
= process_pos
;
4439 if (error::IsError(result
)) {
4440 LOG(ERROR
) << "Error: " << result
<< " for Command "
4441 << GetCommandName(command
);
4447 error::Error
GLES2DecoderImpl::DoCommands(unsigned int num_commands
,
4450 int* entries_processed
) {
4451 if (gpu_debug_commands_
) {
4452 return DoCommandsImpl
<true>(
4453 num_commands
, buffer
, num_entries
, entries_processed
);
4455 return DoCommandsImpl
<false>(
4456 num_commands
, buffer
, num_entries
, entries_processed
);
4460 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id
) {
4461 buffer_manager()->RemoveBuffer(client_id
);
4464 void GLES2DecoderImpl::DoFinish() {
4466 ProcessPendingReadPixels(true);
4467 ProcessPendingQueries(true);
4470 void GLES2DecoderImpl::DoFlush() {
4472 ProcessPendingQueries(false);
4475 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit
) {
4476 GLuint texture_index
= texture_unit
- GL_TEXTURE0
;
4477 if (texture_index
>= state_
.texture_units
.size()) {
4478 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4479 "glActiveTexture", texture_unit
, "texture_unit");
4482 state_
.active_texture_unit
= texture_index
;
4483 glActiveTexture(texture_unit
);
4486 void GLES2DecoderImpl::DoBindBuffer(GLenum target
, GLuint client_id
) {
4487 Buffer
* buffer
= NULL
;
4488 GLuint service_id
= 0;
4489 if (client_id
!= 0) {
4490 buffer
= GetBuffer(client_id
);
4492 if (!group_
->bind_generates_resource()) {
4493 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4495 "id not generated by glGenBuffers");
4499 // It's a new id so make a buffer buffer for it.
4500 glGenBuffersARB(1, &service_id
);
4501 CreateBuffer(client_id
, service_id
);
4502 buffer
= GetBuffer(client_id
);
4505 LogClientServiceForInfo(buffer
, client_id
, "glBindBuffer");
4507 if (!buffer_manager()->SetTarget(buffer
, target
)) {
4509 GL_INVALID_OPERATION
,
4510 "glBindBuffer", "buffer bound to more than 1 target");
4513 service_id
= buffer
->service_id();
4515 state_
.SetBoundBuffer(target
, buffer
);
4516 glBindBuffer(target
, service_id
);
4519 void GLES2DecoderImpl::DoBindBufferBase(GLenum target
, GLuint index
,
4521 Buffer
* buffer
= NULL
;
4522 GLuint service_id
= 0;
4523 if (client_id
!= 0) {
4524 buffer
= GetBuffer(client_id
);
4526 if (!group_
->bind_generates_resource()) {
4527 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4529 "id not generated by glGenBuffers");
4533 // It's a new id so make a buffer for it.
4534 glGenBuffersARB(1, &service_id
);
4535 CreateBuffer(client_id
, service_id
);
4536 buffer
= GetBuffer(client_id
);
4539 LogClientServiceForInfo(buffer
, client_id
, "glBindBufferBase");
4541 // TODO(kbr): track indexed bound buffers.
4542 service_id
= buffer
->service_id();
4544 glBindBufferBase(target
, index
, service_id
);
4547 void GLES2DecoderImpl::DoBindBufferRange(GLenum target
, GLuint index
,
4551 Buffer
* buffer
= NULL
;
4552 GLuint service_id
= 0;
4553 if (client_id
!= 0) {
4554 buffer
= GetBuffer(client_id
);
4556 if (!group_
->bind_generates_resource()) {
4557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4558 "glBindBufferRange",
4559 "id not generated by glGenBuffers");
4563 // It's a new id so make a buffer for it.
4564 glGenBuffersARB(1, &service_id
);
4565 CreateBuffer(client_id
, service_id
);
4566 buffer
= GetBuffer(client_id
);
4569 LogClientServiceForInfo(buffer
, client_id
, "glBindBufferRange");
4571 // TODO(kbr): track indexed bound buffers.
4572 service_id
= buffer
->service_id();
4574 glBindBufferRange(target
, index
, service_id
, offset
, size
);
4577 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4578 Framebuffer
* framebuffer
=
4579 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4581 return framebuffer
->HasAlphaMRT();
4582 return BackBufferHasAlpha();
4585 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4586 Framebuffer
* framebuffer
=
4587 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4589 return framebuffer
->HasDepthAttachment();
4591 if (offscreen_target_frame_buffer_
.get()) {
4592 return offscreen_target_depth_format_
!= 0;
4594 return back_buffer_has_depth_
;
4597 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4598 Framebuffer
* framebuffer
=
4599 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
4601 return framebuffer
->HasStencilAttachment();
4603 if (offscreen_target_frame_buffer_
.get()) {
4604 return offscreen_target_stencil_format_
!= 0 ||
4605 offscreen_target_depth_format_
== GL_DEPTH24_STENCIL8
;
4607 return back_buffer_has_stencil_
;
4610 void GLES2DecoderImpl::ApplyDirtyState() {
4611 if (framebuffer_state_
.clear_state_dirty
) {
4612 bool have_alpha
= BoundFramebufferHasColorAttachmentWithAlpha();
4613 state_
.SetDeviceColorMask(state_
.color_mask_red
,
4614 state_
.color_mask_green
,
4615 state_
.color_mask_blue
,
4616 state_
.color_mask_alpha
&& have_alpha
);
4618 bool have_depth
= BoundFramebufferHasDepthAttachment();
4619 state_
.SetDeviceDepthMask(state_
.depth_mask
&& have_depth
);
4621 bool have_stencil
= BoundFramebufferHasStencilAttachment();
4622 state_
.SetDeviceStencilMaskSeparate(
4623 GL_FRONT
, have_stencil
? state_
.stencil_front_writemask
: 0);
4624 state_
.SetDeviceStencilMaskSeparate(
4625 GL_BACK
, have_stencil
? state_
.stencil_back_writemask
: 0);
4627 state_
.SetDeviceCapabilityState(
4628 GL_DEPTH_TEST
, state_
.enable_flags
.depth_test
&& have_depth
);
4629 state_
.SetDeviceCapabilityState(
4630 GL_STENCIL_TEST
, state_
.enable_flags
.stencil_test
&& have_stencil
);
4631 framebuffer_state_
.clear_state_dirty
= false;
4635 GLuint
GLES2DecoderImpl::GetBackbufferServiceId() const {
4636 return (offscreen_target_frame_buffer_
.get())
4637 ? offscreen_target_frame_buffer_
->id()
4638 : (surface_
.get() ? surface_
->GetBackingFrameBufferObject() : 0);
4641 void GLES2DecoderImpl::RestoreState(const ContextState
* prev_state
) {
4642 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4643 "context", logger_
.GetLogPrefix());
4644 // Restore the Framebuffer first because of bugs in Intel drivers.
4645 // Intel drivers incorrectly clip the viewport settings to
4646 // the size of the current framebuffer object.
4647 RestoreFramebufferBindings();
4648 state_
.RestoreState(prev_state
);
4651 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4653 framebuffer_state_
.bound_draw_framebuffer
.get()
4654 ? framebuffer_state_
.bound_draw_framebuffer
->service_id()
4655 : GetBackbufferServiceId();
4656 if (!features().chromium_framebuffer_multisample
) {
4657 glBindFramebufferEXT(GL_FRAMEBUFFER
, service_id
);
4659 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, service_id
);
4660 service_id
= framebuffer_state_
.bound_read_framebuffer
.get()
4661 ? framebuffer_state_
.bound_read_framebuffer
->service_id()
4662 : GetBackbufferServiceId();
4663 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, service_id
);
4668 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4669 state_
.RestoreRenderbufferBindings();
4672 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id
) const {
4673 Texture
* texture
= texture_manager()->GetTextureForServiceId(service_id
);
4675 GLenum target
= texture
->target();
4676 glBindTexture(target
, service_id
);
4678 target
, GL_TEXTURE_WRAP_S
, texture
->wrap_s());
4680 target
, GL_TEXTURE_WRAP_T
, texture
->wrap_t());
4682 target
, GL_TEXTURE_MIN_FILTER
, texture
->min_filter());
4684 target
, GL_TEXTURE_MAG_FILTER
, texture
->mag_filter());
4685 RestoreTextureUnitBindings(state_
.active_texture_unit
);
4689 void GLES2DecoderImpl::ClearAllAttributes() const {
4690 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4692 if (feature_info_
->feature_flags().native_vertex_array_object
)
4693 glBindVertexArrayOES(0);
4695 for (uint32 i
= 0; i
< group_
->max_vertex_attribs(); ++i
) {
4696 if (i
!= 0) // Never disable attribute 0
4697 glDisableVertexAttribArray(i
);
4698 if (features().angle_instanced_arrays
)
4699 glVertexAttribDivisorANGLE(i
, 0);
4703 void GLES2DecoderImpl::RestoreAllAttributes() const {
4704 state_
.RestoreVertexAttribs();
4707 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore
) {
4708 state_
.SetIgnoreCachedStateForTest(ignore
);
4711 void GLES2DecoderImpl::OnFboChanged() const {
4712 if (workarounds().restore_scissor_on_fbo_change
)
4713 state_
.fbo_binding_for_scissor_workaround_dirty
= true;
4715 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer
) {
4716 GLint bound_fbo_unsigned
= -1;
4717 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, &bound_fbo_unsigned
);
4718 GLuint bound_fbo
= static_cast<GLuint
>(bound_fbo_unsigned
);
4719 if (surface_
&& surface_
->GetBackingFrameBufferObject() == bound_fbo
)
4720 surface_
->NotifyWasBound();
4724 // Called after the FBO is checked for completeness.
4725 void GLES2DecoderImpl::OnUseFramebuffer() const {
4726 if (state_
.fbo_binding_for_scissor_workaround_dirty
) {
4727 state_
.fbo_binding_for_scissor_workaround_dirty
= false;
4728 // The driver forgets the correct scissor when modifying the FBO binding.
4729 glScissor(state_
.scissor_x
,
4731 state_
.scissor_width
,
4732 state_
.scissor_height
);
4734 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4735 // it's unclear how this bug works.
4740 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target
, GLuint client_id
) {
4741 Framebuffer
* framebuffer
= NULL
;
4742 GLuint service_id
= 0;
4743 if (client_id
!= 0) {
4744 framebuffer
= GetFramebuffer(client_id
);
4746 if (!group_
->bind_generates_resource()) {
4747 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4748 "glBindFramebuffer",
4749 "id not generated by glGenFramebuffers");
4753 // It's a new id so make a framebuffer framebuffer for it.
4754 glGenFramebuffersEXT(1, &service_id
);
4755 CreateFramebuffer(client_id
, service_id
);
4756 framebuffer
= GetFramebuffer(client_id
);
4758 service_id
= framebuffer
->service_id();
4760 framebuffer
->MarkAsValid();
4762 LogClientServiceForInfo(framebuffer
, client_id
, "glBindFramebuffer");
4764 if (target
== GL_FRAMEBUFFER
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
4765 framebuffer_state_
.bound_draw_framebuffer
= framebuffer
;
4768 // vmiura: This looks like dup code
4769 if (target
== GL_FRAMEBUFFER
|| target
== GL_READ_FRAMEBUFFER_EXT
) {
4770 framebuffer_state_
.bound_read_framebuffer
= framebuffer
;
4773 framebuffer_state_
.clear_state_dirty
= true;
4775 // If we are rendering to the backbuffer get the FBO id for any simulated
4777 if (framebuffer
== NULL
) {
4778 service_id
= GetBackbufferServiceId();
4781 glBindFramebufferEXT(target
, service_id
);
4785 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target
, GLuint client_id
) {
4786 Renderbuffer
* renderbuffer
= NULL
;
4787 GLuint service_id
= 0;
4788 if (client_id
!= 0) {
4789 renderbuffer
= GetRenderbuffer(client_id
);
4790 if (!renderbuffer
) {
4791 if (!group_
->bind_generates_resource()) {
4792 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4793 "glBindRenderbuffer",
4794 "id not generated by glGenRenderbuffers");
4798 // It's a new id so make a renderbuffer for it.
4799 glGenRenderbuffersEXT(1, &service_id
);
4800 CreateRenderbuffer(client_id
, service_id
);
4801 renderbuffer
= GetRenderbuffer(client_id
);
4803 service_id
= renderbuffer
->service_id();
4805 renderbuffer
->MarkAsValid();
4807 LogClientServiceForInfo(renderbuffer
, client_id
, "glBindRenderbuffer");
4808 state_
.bound_renderbuffer
= renderbuffer
;
4809 state_
.bound_renderbuffer_valid
= true;
4810 glBindRenderbufferEXT(GL_RENDERBUFFER
, service_id
);
4813 void GLES2DecoderImpl::DoBindTexture(GLenum target
, GLuint client_id
) {
4814 TextureRef
* texture_ref
= NULL
;
4815 GLuint service_id
= 0;
4816 if (client_id
!= 0) {
4817 texture_ref
= GetTexture(client_id
);
4819 if (!group_
->bind_generates_resource()) {
4820 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4822 "id not generated by glGenTextures");
4826 // It's a new id so make a texture texture for it.
4827 glGenTextures(1, &service_id
);
4828 DCHECK_NE(0u, service_id
);
4829 CreateTexture(client_id
, service_id
);
4830 texture_ref
= GetTexture(client_id
);
4833 texture_ref
= texture_manager()->GetDefaultTextureInfo(target
);
4836 // Check the texture exists
4838 Texture
* texture
= texture_ref
->texture();
4839 // Check that we are not trying to bind it to a different target.
4840 if (texture
->target() != 0 && texture
->target() != target
) {
4841 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
4843 "texture bound to more than 1 target.");
4846 LogClientServiceForInfo(texture
, client_id
, "glBindTexture");
4847 if (texture
->target() == 0) {
4848 texture_manager()->SetTarget(texture_ref
, target
);
4850 glBindTexture(target
, texture
->service_id());
4852 glBindTexture(target
, 0);
4855 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
4856 unit
.bind_target
= target
;
4859 unit
.bound_texture_2d
= texture_ref
;
4861 case GL_TEXTURE_CUBE_MAP
:
4862 unit
.bound_texture_cube_map
= texture_ref
;
4864 case GL_TEXTURE_EXTERNAL_OES
:
4865 unit
.bound_texture_external_oes
= texture_ref
;
4867 case GL_TEXTURE_RECTANGLE_ARB
:
4868 unit
.bound_texture_rectangle_arb
= texture_ref
;
4871 unit
.bound_texture_3d
= texture_ref
;
4873 case GL_TEXTURE_2D_ARRAY
:
4874 unit
.bound_texture_2d_array
= texture_ref
;
4877 NOTREACHED(); // Validation should prevent us getting here.
4882 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index
) {
4883 if (state_
.vertex_attrib_manager
->Enable(index
, false)) {
4885 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
4886 glDisableVertexAttribArray(index
);
4891 "glDisableVertexAttribArray", "index out of range");
4895 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target
,
4896 GLsizei numAttachments
,
4897 const GLenum
* attachments
) {
4898 if (workarounds().disable_discard_framebuffer
)
4901 Framebuffer
* framebuffer
=
4902 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
4904 // Validates the attachments. If one of them fails
4905 // the whole command fails.
4906 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4908 !validators_
->attachment
.IsValid(attachments
[i
])) ||
4910 !validators_
->backbuffer_attachment
.IsValid(attachments
[i
]))) {
4911 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4912 "glDiscardFramebufferEXT", attachments
[i
], "attachments");
4917 // Marks each one of them as not cleared
4918 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4920 framebuffer
->MarkAttachmentAsCleared(renderbuffer_manager(),
4925 switch (attachments
[i
]) {
4927 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
4930 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
4931 case GL_STENCIL_EXT
:
4932 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
4941 // If the default framebuffer is bound but we are still rendering to an
4942 // FBO, translate attachment names that refer to default framebuffer
4943 // channels to corresponding framebuffer attachments.
4944 scoped_ptr
<GLenum
[]> translated_attachments(new GLenum
[numAttachments
]);
4945 for (GLsizei i
= 0; i
< numAttachments
; ++i
) {
4946 GLenum attachment
= attachments
[i
];
4947 if (!framebuffer
&& GetBackbufferServiceId()) {
4948 switch (attachment
) {
4950 attachment
= GL_COLOR_ATTACHMENT0
;
4953 attachment
= GL_DEPTH_ATTACHMENT
;
4955 case GL_STENCIL_EXT
:
4956 attachment
= GL_STENCIL_ATTACHMENT
;
4963 translated_attachments
[i
] = attachment
;
4966 ScopedRenderTo
do_render(framebuffer
);
4967 if (feature_info_
->gl_version_info().is_es3
) {
4968 glInvalidateFramebuffer(
4969 target
, numAttachments
, translated_attachments
.get());
4971 glDiscardFramebufferEXT(
4972 target
, numAttachments
, translated_attachments
.get());
4976 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index
) {
4977 if (state_
.vertex_attrib_manager
->Enable(index
, true)) {
4978 glEnableVertexAttribArray(index
);
4981 GL_INVALID_VALUE
, "glEnableVertexAttribArray", "index out of range");
4985 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target
) {
4986 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
4989 !texture_manager()->CanGenerateMipmaps(texture_ref
)) {
4991 GL_INVALID_OPERATION
, "glGenerateMipmap", "Can not generate mips");
4995 if (target
== GL_TEXTURE_CUBE_MAP
) {
4996 for (int i
= 0; i
< 6; ++i
) {
4997 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
;
4998 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, face
, 0)) {
5000 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
5005 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
, 0)) {
5007 GL_OUT_OF_MEMORY
, "glGenerateMipmap", "dimensions too big");
5012 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
5013 // Workaround for Mac driver bug. In the large scheme of things setting
5014 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
5015 // hit so there's probably no need to make this conditional. The bug appears
5016 // to be that if the filtering mode is set to something that doesn't require
5017 // mipmaps for rendering, or is never set to something other than the default,
5018 // then glGenerateMipmap misbehaves.
5019 if (workarounds().set_texture_filter_before_generating_mipmap
) {
5020 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
5022 glGenerateMipmapEXT(target
);
5023 if (workarounds().set_texture_filter_before_generating_mipmap
) {
5024 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
5025 texture_ref
->texture()->min_filter());
5027 GLenum error
= LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
5028 if (error
== GL_NO_ERROR
) {
5029 texture_manager()->MarkMipmapsGenerated(texture_ref
);
5033 bool GLES2DecoderImpl::GetHelper(
5034 GLenum pname
, GLint
* params
, GLsizei
* num_written
) {
5035 DCHECK(num_written
);
5036 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
5038 case GL_IMPLEMENTATION_COLOR_READ_FORMAT
:
5040 // Return the GL implementation's preferred format and (see below type)
5041 // if we have the GL extension that exposes this. This allows the GPU
5042 // client to use the implementation's preferred format for glReadPixels
5043 // for optimisation.
5045 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
5046 // case when requested on integer/floating point buffers but which is
5047 // acceptable on GLES2 and with the GL_OES_read_format extension.
5049 // Therefore if an error occurs we swallow the error and use the
5050 // internal implementation.
5052 if (context_
->HasExtension("GL_OES_read_format")) {
5053 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
5055 glGetIntegerv(pname
, params
);
5056 if (glGetError() == GL_NO_ERROR
)
5059 *params
= GLES2Util::GetGLReadPixelsImplementationFormat(
5060 GetBoundReadFrameBufferInternalFormat());
5063 case GL_IMPLEMENTATION_COLOR_READ_TYPE
:
5066 if (context_
->HasExtension("GL_OES_read_format")) {
5067 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::GetHelper",
5069 glGetIntegerv(pname
, params
);
5070 if (glGetError() == GL_NO_ERROR
)
5073 *params
= GLES2Util::GetGLReadPixelsImplementationType(
5074 GetBoundReadFrameBufferInternalFormat(),
5075 GetBoundReadFrameBufferTextureType());
5078 case GL_MAX_FRAGMENT_UNIFORM_VECTORS
:
5081 *params
= group_
->max_fragment_uniform_vectors();
5084 case GL_MAX_VARYING_VECTORS
:
5087 *params
= group_
->max_varying_vectors();
5090 case GL_MAX_VERTEX_UNIFORM_VECTORS
:
5093 *params
= group_
->max_vertex_uniform_vectors();
5098 if (unsafe_es3_apis_enabled()) {
5100 case GL_MAX_VARYING_COMPONENTS
: {
5101 if (feature_info_
->gl_version_info().is_es
) {
5102 // We can just delegate this query to the driver.
5106 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5107 // OpenGL core profile, so for simplicity, just compute it
5108 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5110 GLint max_varying_vectors
= 0;
5111 glGetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors
);
5114 *params
= max_varying_vectors
* 4;
5118 case GL_READ_BUFFER
:
5121 Framebuffer
* framebuffer
=
5122 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
5125 read_buffer
= framebuffer
->read_buffer();
5127 read_buffer
= back_buffer_read_buffer_
;
5129 *params
= static_cast<GLint
>(read_buffer
);
5135 case GL_MAX_VIEWPORT_DIMS
:
5136 if (offscreen_target_frame_buffer_
.get()) {
5139 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5140 params
[1] = renderbuffer_manager()->max_renderbuffer_size();
5145 case GL_MAX_SAMPLES
:
5148 params
[0] = renderbuffer_manager()->max_samples();
5151 case GL_MAX_RENDERBUFFER_SIZE
:
5154 params
[0] = renderbuffer_manager()->max_renderbuffer_size();
5157 case GL_MAX_TEXTURE_SIZE
:
5160 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D
);
5163 case GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
5166 params
[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP
);
5169 case GL_MAX_COLOR_ATTACHMENTS_EXT
:
5172 params
[0] = group_
->max_color_attachments();
5175 case GL_MAX_DRAW_BUFFERS_ARB
:
5178 params
[0] = group_
->max_draw_buffers();
5185 Framebuffer
* framebuffer
=
5186 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5188 if (framebuffer
->HasAlphaMRT() &&
5189 framebuffer
->HasSameInternalFormatsMRT()) {
5190 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5191 glGetFramebufferAttachmentParameterivEXT(
5192 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
5193 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &v
);
5195 glGetIntegerv(GL_ALPHA_BITS
, &v
);
5199 v
= (BackBufferHasAlpha() ? 8 : 0);
5208 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5209 Framebuffer
* framebuffer
=
5210 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5212 glGetFramebufferAttachmentParameterivEXT(
5213 GL_FRAMEBUFFER
, GL_DEPTH_ATTACHMENT
,
5214 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
, &v
);
5216 v
= (back_buffer_has_depth_
? 24 : 0);
5219 glGetIntegerv(GL_DEPTH_BITS
, &v
);
5221 params
[0] = BoundFramebufferHasDepthAttachment() ? v
: 0;
5230 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5231 Framebuffer
* framebuffer
=
5232 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5234 GLenum framebuffer_enum
= 0;
5237 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
;
5240 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
;
5243 framebuffer_enum
= GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
;
5246 glGetFramebufferAttachmentParameterivEXT(
5247 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, framebuffer_enum
, &v
);
5252 glGetIntegerv(pname
, &v
);
5257 case GL_STENCIL_BITS
:
5261 if (feature_info_
->gl_version_info().is_desktop_core_profile
) {
5262 Framebuffer
* framebuffer
=
5263 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
5265 glGetFramebufferAttachmentParameterivEXT(
5266 GL_FRAMEBUFFER
, GL_STENCIL_ATTACHMENT
,
5267 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
, &v
);
5269 v
= (back_buffer_has_stencil_
? 8 : 0);
5272 glGetIntegerv(GL_STENCIL_BITS
, &v
);
5274 params
[0] = BoundFramebufferHasStencilAttachment() ? v
: 0;
5277 case GL_COMPRESSED_TEXTURE_FORMATS
:
5278 *num_written
= validators_
->compressed_texture_format
.GetValues().size();
5280 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5281 params
[ii
] = validators_
->compressed_texture_format
.GetValues()[ii
];
5285 case GL_NUM_COMPRESSED_TEXTURE_FORMATS
:
5288 *params
= validators_
->compressed_texture_format
.GetValues().size();
5291 case GL_NUM_SHADER_BINARY_FORMATS
:
5294 *params
= validators_
->shader_binary_format
.GetValues().size();
5297 case GL_SHADER_BINARY_FORMATS
:
5298 *num_written
= validators_
->shader_binary_format
.GetValues().size();
5300 for (GLint ii
= 0; ii
< *num_written
; ++ii
) {
5301 params
[ii
] = validators_
->shader_binary_format
.GetValues()[ii
];
5305 case GL_SHADER_COMPILER
:
5311 case GL_ARRAY_BUFFER_BINDING
:
5314 *params
= GetClientId(
5315 buffer_manager(), state_
.bound_array_buffer
.get());
5318 case GL_ELEMENT_ARRAY_BUFFER_BINDING
:
5321 *params
= GetClientId(
5323 state_
.vertex_attrib_manager
->element_array_buffer());
5326 case GL_COPY_READ_BUFFER_BINDING
:
5329 *params
= GetClientId(
5330 buffer_manager(), state_
.bound_copy_read_buffer
.get());
5333 case GL_COPY_WRITE_BUFFER_BINDING
:
5336 *params
= GetClientId(
5337 buffer_manager(), state_
.bound_copy_write_buffer
.get());
5340 case GL_PIXEL_PACK_BUFFER_BINDING
:
5343 *params
= GetClientId(
5344 buffer_manager(), state_
.bound_pixel_pack_buffer
.get());
5347 case GL_PIXEL_UNPACK_BUFFER_BINDING
:
5350 *params
= GetClientId(
5351 buffer_manager(), state_
.bound_pixel_unpack_buffer
.get());
5354 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING
:
5357 *params
= GetClientId(
5358 buffer_manager(), state_
.bound_transform_feedback_buffer
.get());
5361 case GL_UNIFORM_BUFFER_BINDING
:
5364 *params
= GetClientId(
5365 buffer_manager(), state_
.bound_uniform_buffer
.get());
5368 case GL_FRAMEBUFFER_BINDING
:
5369 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5372 *params
= GetClientId(
5373 framebuffer_manager(),
5374 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
));
5377 case GL_READ_FRAMEBUFFER_BINDING_EXT
:
5380 *params
= GetClientId(
5381 framebuffer_manager(),
5382 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT
));
5385 case GL_RENDERBUFFER_BINDING
:
5388 Renderbuffer
* renderbuffer
=
5389 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
5391 *params
= renderbuffer
->client_id();
5397 case GL_CURRENT_PROGRAM
:
5400 *params
= GetClientId(program_manager(), state_
.current_program
.get());
5403 case GL_VERTEX_ARRAY_BINDING_OES
:
5406 if (state_
.vertex_attrib_manager
.get() !=
5407 state_
.default_vertex_attrib_manager
.get()) {
5408 GLuint client_id
= 0;
5409 vertex_array_manager_
->GetClientId(
5410 state_
.vertex_attrib_manager
->service_id(), &client_id
);
5411 *params
= client_id
;
5417 case GL_TEXTURE_BINDING_2D
:
5420 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5421 if (unit
.bound_texture_2d
.get()) {
5422 *params
= unit
.bound_texture_2d
->client_id();
5428 case GL_TEXTURE_BINDING_CUBE_MAP
:
5431 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5432 if (unit
.bound_texture_cube_map
.get()) {
5433 *params
= unit
.bound_texture_cube_map
->client_id();
5439 case GL_TEXTURE_BINDING_EXTERNAL_OES
:
5442 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5443 if (unit
.bound_texture_external_oes
.get()) {
5444 *params
= unit
.bound_texture_external_oes
->client_id();
5450 case GL_TEXTURE_BINDING_RECTANGLE_ARB
:
5453 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
5454 if (unit
.bound_texture_rectangle_arb
.get()) {
5455 *params
= unit
.bound_texture_rectangle_arb
->client_id();
5461 case GL_BIND_GENERATES_RESOURCE_CHROMIUM
:
5464 params
[0] = group_
->bind_generates_resource() ? 1 : 0;
5468 if (pname
>= GL_DRAW_BUFFER0_ARB
&&
5469 pname
< GL_DRAW_BUFFER0_ARB
+ group_
->max_draw_buffers()) {
5472 Framebuffer
* framebuffer
=
5473 GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
5475 params
[0] = framebuffer
->GetDrawBuffer(pname
);
5476 } else { // backbuffer
5477 if (pname
== GL_DRAW_BUFFER0_ARB
)
5478 params
[0] = back_buffer_draw_buffer_
;
5480 params
[0] = GL_NONE
;
5485 *num_written
= util_
.GLGetNumValuesReturned(pname
);
5490 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5491 GLenum pname
, GLsizei
* num_values
) {
5492 if (state_
.GetStateAsGLint(pname
, NULL
, num_values
)) {
5495 return GetHelper(pname
, NULL
, num_values
);
5498 GLenum
GLES2DecoderImpl::AdjustGetPname(GLenum pname
) {
5499 if (GL_MAX_SAMPLES
== pname
&&
5500 features().use_img_for_multisampled_render_to_texture
) {
5501 return GL_MAX_SAMPLES_IMG
;
5506 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname
, GLboolean
* params
) {
5508 GLsizei num_written
= 0;
5509 if (GetNumValuesReturnedForGLGet(pname
, &num_written
)) {
5510 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5511 if (!state_
.GetStateAsGLint(pname
, values
.get(), &num_written
)) {
5512 GetHelper(pname
, values
.get(), &num_written
);
5514 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5515 params
[ii
] = static_cast<GLboolean
>(values
[ii
]);
5518 pname
= AdjustGetPname(pname
);
5519 glGetBooleanv(pname
, params
);
5523 void GLES2DecoderImpl::DoGetFloatv(GLenum pname
, GLfloat
* params
) {
5525 GLsizei num_written
= 0;
5526 if (!state_
.GetStateAsGLfloat(pname
, params
, &num_written
)) {
5527 if (GetHelper(pname
, NULL
, &num_written
)) {
5528 scoped_ptr
<GLint
[]> values(new GLint
[num_written
]);
5529 GetHelper(pname
, values
.get(), &num_written
);
5530 for (GLsizei ii
= 0; ii
< num_written
; ++ii
) {
5531 params
[ii
] = static_cast<GLfloat
>(values
[ii
]);
5534 pname
= AdjustGetPname(pname
);
5535 glGetFloatv(pname
, params
);
5540 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname
, GLint64
* params
) {
5542 if (unsafe_es3_apis_enabled()) {
5544 case GL_MAX_ELEMENT_INDEX
: {
5545 if (feature_info_
->gl_version_info().IsAtLeastGLES(3, 0) ||
5546 feature_info_
->gl_version_info().IsAtLeastGL(4, 3)) {
5547 glGetInteger64v(GL_MAX_ELEMENT_INDEX
, params
);
5549 // Assume that desktop GL implementations can generally support
5552 *params
= std::numeric_limits
<unsigned int>::max();
5559 pname
= AdjustGetPname(pname
);
5560 glGetInteger64v(pname
, params
);
5563 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname
, GLint
* params
) {
5565 GLsizei num_written
;
5566 if (!state_
.GetStateAsGLint(pname
, params
, &num_written
) &&
5567 !GetHelper(pname
, params
, &num_written
)) {
5568 pname
= AdjustGetPname(pname
);
5569 glGetIntegerv(pname
, params
);
5573 void GLES2DecoderImpl::DoGetProgramiv(
5574 GLuint program_id
, GLenum pname
, GLint
* params
) {
5575 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetProgramiv");
5579 program
->GetProgramiv(pname
, params
);
5582 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5583 GLenum target
, GLenum pname
, GLint64
* params
) {
5584 // Just delegate it. Some validation is actually done before this.
5585 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5586 &state_
, target
, pname
, params
);
5589 void GLES2DecoderImpl::DoGetBufferParameteriv(
5590 GLenum target
, GLenum pname
, GLint
* params
) {
5591 // Just delegate it. Some validation is actually done before this.
5592 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5593 &state_
, target
, pname
, params
);
5596 void GLES2DecoderImpl::DoBindAttribLocation(
5597 GLuint program_id
, GLuint index
, const char* name
) {
5598 if (!StringIsValidForGLES(name
)) {
5600 GL_INVALID_VALUE
, "glBindAttribLocation", "Invalid character");
5603 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5605 GL_INVALID_OPERATION
, "glBindAttribLocation", "reserved prefix");
5608 if (index
>= group_
->max_vertex_attribs()) {
5610 GL_INVALID_VALUE
, "glBindAttribLocation", "index out of range");
5613 Program
* program
= GetProgramInfoNotShader(
5614 program_id
, "glBindAttribLocation");
5618 // At this point, the program's shaders may not be translated yet,
5619 // therefore, we may not find the hashed attribute name.
5620 // glBindAttribLocation call with original name is useless.
5621 // So instead, we should simply cache the binding, and then call
5622 // Program::ExecuteBindAttribLocationCalls() right before link.
5623 program
->SetAttribLocationBinding(name
, static_cast<GLint
>(index
));
5624 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5625 glBindAttribLocation(program
->service_id(), index
, name
);
5628 error::Error
GLES2DecoderImpl::HandleBindAttribLocationBucket(
5629 uint32 immediate_data_size
,
5630 const void* cmd_data
) {
5631 const gles2::cmds::BindAttribLocationBucket
& c
=
5632 *static_cast<const gles2::cmds::BindAttribLocationBucket
*>(cmd_data
);
5633 GLuint program
= static_cast<GLuint
>(c
.program
);
5634 GLuint index
= static_cast<GLuint
>(c
.index
);
5635 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5636 if (!bucket
|| bucket
->size() == 0) {
5637 return error::kInvalidArguments
;
5639 std::string name_str
;
5640 if (!bucket
->GetAsString(&name_str
)) {
5641 return error::kInvalidArguments
;
5643 DoBindAttribLocation(program
, index
, name_str
.c_str());
5644 return error::kNoError
;
5647 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5648 GLuint program_id
, GLint location
, const char* name
) {
5649 if (!StringIsValidForGLES(name
)) {
5652 "glBindUniformLocationCHROMIUM", "Invalid character");
5655 if (ProgramManager::IsInvalidPrefix(name
, strlen(name
))) {
5657 GL_INVALID_OPERATION
,
5658 "glBindUniformLocationCHROMIUM", "reserved prefix");
5661 if (location
< 0 || static_cast<uint32
>(location
) >=
5662 (group_
->max_fragment_uniform_vectors() +
5663 group_
->max_vertex_uniform_vectors()) * 4) {
5666 "glBindUniformLocationCHROMIUM", "location out of range");
5669 Program
* program
= GetProgramInfoNotShader(
5670 program_id
, "glBindUniformLocationCHROMIUM");
5674 if (!program
->SetUniformLocationBinding(name
, location
)) {
5677 "glBindUniformLocationCHROMIUM", "location out of range");
5681 error::Error
GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5682 uint32 immediate_data_size
,
5683 const void* cmd_data
) {
5684 const gles2::cmds::BindUniformLocationCHROMIUMBucket
& c
=
5685 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket
*>(
5687 GLuint program
= static_cast<GLuint
>(c
.program
);
5688 GLint location
= static_cast<GLint
>(c
.location
);
5689 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
5690 if (!bucket
|| bucket
->size() == 0) {
5691 return error::kInvalidArguments
;
5693 std::string name_str
;
5694 if (!bucket
->GetAsString(&name_str
)) {
5695 return error::kInvalidArguments
;
5697 DoBindUniformLocationCHROMIUM(program
, location
, name_str
.c_str());
5698 return error::kNoError
;
5701 error::Error
GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size
,
5702 const void* cmd_data
) {
5703 const gles2::cmds::DeleteShader
& c
=
5704 *static_cast<const gles2::cmds::DeleteShader
*>(cmd_data
);
5705 GLuint client_id
= c
.shader
;
5707 Shader
* shader
= GetShader(client_id
);
5709 if (!shader
->IsDeleted()) {
5710 shader_manager()->Delete(shader
);
5713 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glDeleteShader", "unknown shader");
5716 return error::kNoError
;
5719 error::Error
GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size
,
5720 const void* cmd_data
) {
5721 const gles2::cmds::DeleteProgram
& c
=
5722 *static_cast<const gles2::cmds::DeleteProgram
*>(cmd_data
);
5723 GLuint client_id
= c
.program
;
5725 Program
* program
= GetProgram(client_id
);
5727 if (!program
->IsDeleted()) {
5728 program_manager()->MarkAsDeleted(shader_manager(), program
);
5732 GL_INVALID_VALUE
, "glDeleteProgram", "unknown program");
5735 return error::kNoError
;
5738 error::Error
GLES2DecoderImpl::DoClear(GLbitfield mask
) {
5739 DCHECK(!ShouldDeferDraws());
5740 if (CheckBoundFramebuffersValid("glClear")) {
5742 // TODO(zmo): Filter out INTEGER/SIGNED INTEGER images to avoid
5743 // undefined results.
5744 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
5745 if (workarounds().gl_clear_broken
) {
5746 ScopedGLErrorSuppressor
suppressor("GLES2DecoderImpl::ClearWorkaround",
5748 if (!BoundFramebufferHasDepthAttachment())
5749 mask
&= ~GL_DEPTH_BUFFER_BIT
;
5750 if (!BoundFramebufferHasStencilAttachment())
5751 mask
&= ~GL_STENCIL_BUFFER_BIT
;
5752 clear_framebuffer_blit_
->ClearFramebuffer(
5753 this, GetBoundReadFrameBufferSize(), mask
, state_
.color_clear_red
,
5754 state_
.color_clear_green
, state_
.color_clear_blue
,
5755 state_
.color_clear_alpha
, state_
.depth_clear
, state_
.stencil_clear
);
5756 return error::kNoError
;
5760 return error::kNoError
;
5763 void GLES2DecoderImpl::DoClearBufferiv(
5764 GLenum buffer
, GLint drawbuffer
, const GLint
* value
) {
5765 if (!CheckBoundDrawFramebufferValid("glClearBufferiv"))
5775 GL_INVALID_ENUM
, "glClearBufferiv", "invalid buffer");
5778 GLenum attachment
= 0;
5779 if (buffer
== GL_COLOR
) {
5780 if (drawbuffer
< 0 ||
5781 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5783 GL_INVALID_VALUE
, "glClearBufferiv", "invalid drawBuffer");
5786 GLenum internal_format
=
5787 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5788 if (!GLES2Util::IsSignedIntegerFormat(internal_format
)) {
5789 // To avoid undefined results, return without calling the gl function.
5792 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5794 DCHECK(buffer
== GL_STENCIL
);
5795 if (drawbuffer
!= 0) {
5797 GL_INVALID_VALUE
, "glClearBufferiv", "invalid drawBuffer");
5800 if (!BoundFramebufferHasStencilAttachment()) {
5803 attachment
= GL_STENCIL_ATTACHMENT
;
5805 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5807 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5809 glClearBufferiv(buffer
, drawbuffer
, value
);
5813 void GLES2DecoderImpl::DoClearBufferuiv(
5814 GLenum buffer
, GLint drawbuffer
, const GLuint
* value
) {
5815 if (!CheckBoundDrawFramebufferValid("glClearBufferuiv"))
5824 GL_INVALID_ENUM
, "glClearBufferuiv", "invalid buffer");
5827 if (drawbuffer
< 0 ||
5828 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5830 GL_INVALID_VALUE
, "glClearBufferuiv", "invalid drawBuffer");
5833 GLenum internal_format
=
5834 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5835 if (!GLES2Util::IsUnsignedIntegerFormat(internal_format
)) {
5836 // To avoid undefined results, return without calling the gl function.
5839 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5840 GLenum attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5842 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5844 glClearBufferuiv(buffer
, drawbuffer
, value
);
5848 void GLES2DecoderImpl::DoClearBufferfv(
5849 GLenum buffer
, GLint drawbuffer
, const GLfloat
* value
) {
5850 if (!CheckBoundDrawFramebufferValid("glClearBufferfv"))
5860 GL_INVALID_ENUM
, "glClearBufferfv", "invalid buffer");
5863 GLenum attachment
= 0;
5864 if (buffer
== GL_COLOR
) {
5865 if (drawbuffer
< 0 ||
5866 drawbuffer
>= static_cast<GLint
>(group_
->max_draw_buffers())) {
5868 GL_INVALID_VALUE
, "glClearBufferfv", "invalid drawBuffer");
5871 GLenum internal_format
=
5872 GetBoundColorDrawBufferInternalFormat(drawbuffer
);
5873 if (GLES2Util::IsIntegerFormat(internal_format
)) {
5874 // To avoid undefined results, return without calling the gl function.
5877 attachment
= static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ drawbuffer
);
5879 DCHECK(buffer
== GL_DEPTH
);
5880 if (drawbuffer
!= 0) {
5882 GL_INVALID_VALUE
, "glClearBufferfv", "invalid drawBuffer");
5885 if (!BoundFramebufferHasDepthAttachment()) {
5888 attachment
= GL_DEPTH_ATTACHMENT
;
5890 MarkDrawBufferAsCleared(buffer
, drawbuffer
);
5892 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get(),
5894 glClearBufferfv(buffer
, drawbuffer
, value
);
5898 void GLES2DecoderImpl::DoClearBufferfi(
5899 GLenum buffer
, GLint drawbuffer
, GLfloat depth
, GLint stencil
) {
5900 if (!CheckBoundDrawFramebufferValid("glClearBufferfi"))
5905 case GL_DEPTH_STENCIL
:
5909 GL_INVALID_ENUM
, "glClearBufferfi", "invalid buffer");
5912 if (drawbuffer
!= 0) {
5914 GL_INVALID_VALUE
, "glClearBufferfi", "invalid drawBuffer");
5917 if (!BoundFramebufferHasDepthAttachment() &&
5918 !BoundFramebufferHasStencilAttachment()) {
5921 MarkDrawBufferAsCleared(GL_DEPTH
, drawbuffer
);
5922 MarkDrawBufferAsCleared(GL_STENCIL
, drawbuffer
);
5924 ScopedRenderTo
do_render_depth(
5925 framebuffer_state_
.bound_draw_framebuffer
.get(),
5926 GL_DEPTH_ATTACHMENT
);
5927 ScopedRenderTo
do_render_stencil(
5928 framebuffer_state_
.bound_draw_framebuffer
.get(),
5929 GL_STENCIL_ATTACHMENT
);
5930 glClearBufferfi(buffer
, drawbuffer
, depth
, stencil
);
5934 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5935 GLenum target
, GLenum attachment
, GLenum renderbuffertarget
,
5936 GLuint client_renderbuffer_id
) {
5937 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
5940 GL_INVALID_OPERATION
,
5941 "glFramebufferRenderbuffer", "no framebuffer bound");
5944 GLuint service_id
= 0;
5945 Renderbuffer
* renderbuffer
= NULL
;
5946 if (client_renderbuffer_id
) {
5947 renderbuffer
= GetRenderbuffer(client_renderbuffer_id
);
5948 if (!renderbuffer
) {
5950 GL_INVALID_OPERATION
,
5951 "glFramebufferRenderbuffer", "unknown renderbuffer");
5954 service_id
= renderbuffer
->service_id();
5956 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5957 glFramebufferRenderbufferEXT(
5958 target
, attachment
, renderbuffertarget
, service_id
);
5959 GLenum error
= LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5960 if (error
== GL_NO_ERROR
) {
5961 framebuffer
->AttachRenderbuffer(attachment
, renderbuffer
);
5963 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
5964 framebuffer_state_
.clear_state_dirty
= true;
5969 void GLES2DecoderImpl::DoDisable(GLenum cap
) {
5970 if (SetCapabilityState(cap
, false)) {
5975 void GLES2DecoderImpl::DoEnable(GLenum cap
) {
5976 if (SetCapabilityState(cap
, true)) {
5981 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear
, GLclampf zfar
) {
5982 state_
.z_near
= std::min(1.0f
, std::max(0.0f
, znear
));
5983 state_
.z_far
= std::min(1.0f
, std::max(0.0f
, zfar
));
5984 glDepthRange(znear
, zfar
);
5987 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value
, GLboolean invert
) {
5988 state_
.sample_coverage_value
= std::min(1.0f
, std::max(0.0f
, value
));
5989 state_
.sample_coverage_invert
= (invert
!= 0);
5990 glSampleCoverage(state_
.sample_coverage_value
, invert
);
5993 // Assumes framebuffer is complete.
5994 void GLES2DecoderImpl::ClearUnclearedAttachments(
5995 GLenum target
, Framebuffer
* framebuffer
) {
5996 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
5997 // bind this to the DRAW point, clear then bind back to READ
5998 // TODO(gman): I don't think there is any guarantee that an FBO that
5999 // is complete on the READ attachment will be complete as a DRAW
6001 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0);
6002 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, framebuffer
->service_id());
6004 GLbitfield clear_bits
= 0;
6005 if (framebuffer
->HasUnclearedColorAttachments()) {
6006 // We should always use alpha == 0 here, because 1) some draw buffers may
6007 // have alpha and some may not; 2) we won't have the same situation as the
6008 // back buffer where alpha channel exists but is not requested.
6009 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
6010 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6011 clear_bits
|= GL_COLOR_BUFFER_BIT
;
6012 if (feature_info_
->feature_flags().ext_draw_buffers
||
6013 feature_info_
->IsES3Enabled()) {
6014 framebuffer
->PrepareDrawBuffersForClear();
6018 if (framebuffer
->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT
) ||
6019 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
6021 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
6022 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
6023 clear_bits
|= GL_STENCIL_BUFFER_BIT
;
6026 if (framebuffer
->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT
) ||
6027 framebuffer
->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT
)) {
6029 state_
.SetDeviceDepthMask(GL_TRUE
);
6030 clear_bits
|= GL_DEPTH_BUFFER_BIT
;
6033 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6034 glClear(clear_bits
);
6036 if ((clear_bits
& GL_COLOR_BUFFER_BIT
) != 0 &&
6037 (feature_info_
->feature_flags().ext_draw_buffers
||
6038 feature_info_
->IsES3Enabled())) {
6039 framebuffer
->RestoreDrawBuffersAfterClear();
6042 if (feature_info_
->IsES3Enabled()) {
6043 // TODO(zmo): track more state to know whether there are any integer
6044 // buffers attached to the current framebuffer.
6045 framebuffer
->ClearIntegerBuffers();
6048 framebuffer_manager()->MarkAttachmentsAsCleared(
6049 framebuffer
, renderbuffer_manager(), texture_manager());
6051 RestoreClearState();
6053 if (target
== GL_READ_FRAMEBUFFER_EXT
) {
6054 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, framebuffer
->service_id());
6055 Framebuffer
* draw_framebuffer
=
6056 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
6057 GLuint service_id
= draw_framebuffer
? draw_framebuffer
->service_id() :
6058 GetBackbufferServiceId();
6059 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, service_id
);
6063 void GLES2DecoderImpl::RestoreClearState() {
6064 framebuffer_state_
.clear_state_dirty
= true;
6066 state_
.color_clear_red
, state_
.color_clear_green
, state_
.color_clear_blue
,
6067 state_
.color_clear_alpha
);
6068 glClearStencil(state_
.stencil_clear
);
6069 glClearDepth(state_
.depth_clear
);
6070 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6071 state_
.enable_flags
.scissor_test
);
6072 glScissor(state_
.scissor_x
, state_
.scissor_y
, state_
.scissor_width
,
6073 state_
.scissor_height
);
6076 GLenum
GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target
) {
6077 Framebuffer
* framebuffer
=
6078 GetFramebufferInfoForTarget(target
);
6080 return GL_FRAMEBUFFER_COMPLETE
;
6082 GLenum completeness
= framebuffer
->IsPossiblyComplete();
6083 if (completeness
!= GL_FRAMEBUFFER_COMPLETE
) {
6084 return completeness
;
6086 return framebuffer
->GetStatus(texture_manager(), target
);
6089 void GLES2DecoderImpl::DoFramebufferTexture2D(
6090 GLenum target
, GLenum attachment
, GLenum textarget
,
6091 GLuint client_texture_id
, GLint level
) {
6092 DoFramebufferTexture2DCommon(
6093 "glFramebufferTexture2D", target
, attachment
,
6094 textarget
, client_texture_id
, level
, 0);
6097 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
6098 GLenum target
, GLenum attachment
, GLenum textarget
,
6099 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
6100 DoFramebufferTexture2DCommon(
6101 "glFramebufferTexture2DMultisample", target
, attachment
,
6102 textarget
, client_texture_id
, level
, samples
);
6105 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
6106 const char* name
, GLenum target
, GLenum attachment
, GLenum textarget
,
6107 GLuint client_texture_id
, GLint level
, GLsizei samples
) {
6108 if (samples
> renderbuffer_manager()->max_samples()) {
6111 "glFramebufferTexture2DMultisample", "samples too large");
6114 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
6117 GL_INVALID_OPERATION
,
6118 name
, "no framebuffer bound.");
6121 GLuint service_id
= 0;
6122 TextureRef
* texture_ref
= NULL
;
6123 if (client_texture_id
) {
6124 texture_ref
= GetTexture(client_texture_id
);
6127 GL_INVALID_OPERATION
,
6128 name
, "unknown texture_ref");
6131 service_id
= texture_ref
->service_id();
6134 if (!texture_manager()->ValidForTarget(textarget
, level
, 0, 0, 1)) {
6137 name
, "level out of range");
6142 DoWillUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
6144 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name
);
6146 glFramebufferTexture2DEXT(target
, attachment
, textarget
, service_id
, level
);
6148 if (features().use_img_for_multisampled_render_to_texture
) {
6149 glFramebufferTexture2DMultisampleIMG(target
, attachment
, textarget
,
6150 service_id
, level
, samples
);
6152 glFramebufferTexture2DMultisampleEXT(target
, attachment
, textarget
,
6153 service_id
, level
, samples
);
6156 GLenum error
= LOCAL_PEEK_GL_ERROR(name
);
6157 if (error
== GL_NO_ERROR
) {
6158 framebuffer
->AttachTexture(attachment
, texture_ref
, textarget
, level
,
6161 if (framebuffer
== framebuffer_state_
.bound_draw_framebuffer
.get()) {
6162 framebuffer_state_
.clear_state_dirty
= true;
6166 DoDidUseTexImageIfNeeded(texture_ref
->texture(), textarget
);
6171 void GLES2DecoderImpl::DoFramebufferTextureLayer(
6172 GLenum target
, GLenum attachment
, GLuint client_texture_id
,
6173 GLint level
, GLint layer
) {
6174 // TODO(zmo): Unsafe ES3 API, missing states update.
6175 GLuint service_id
= 0;
6176 TextureRef
* texture_ref
= NULL
;
6177 if (client_texture_id
) {
6178 texture_ref
= GetTexture(client_texture_id
);
6181 GL_INVALID_OPERATION
,
6182 "glFramebufferTextureLayer", "unknown texture_ref");
6185 service_id
= texture_ref
->service_id();
6187 glFramebufferTextureLayer(target
, attachment
, service_id
, level
, layer
);
6190 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
6191 GLenum target
, GLenum attachment
, GLenum pname
, GLint
* params
) {
6192 const char kFunctionName
[] = "glGetFramebufferAttachmentParameteriv";
6193 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(target
);
6195 if (!unsafe_es3_apis_enabled()) {
6196 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
6197 "no framebuffer bound");
6200 if (!validators_
->backbuffer_attachment
.IsValid(attachment
)) {
6201 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
6202 "invalid attachment for backbuffer");
6206 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
:
6207 *params
= static_cast<GLint
>(GL_FRAMEBUFFER_DEFAULT
);
6209 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
:
6210 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
:
6211 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
:
6212 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
:
6213 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
:
6214 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
:
6215 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE
:
6216 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
:
6217 // Delegate to underlying driver.
6220 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
,
6221 "invalid pname for backbuffer");
6224 if (GetBackbufferServiceId() != 0) { // Emulated backbuffer.
6225 switch (attachment
) {
6227 attachment
= GL_COLOR_ATTACHMENT0
;
6230 attachment
= GL_DEPTH_ATTACHMENT
;
6233 attachment
= GL_STENCIL_ATTACHMENT
;
6241 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT
&&
6242 features().use_img_for_multisampled_render_to_texture
) {
6243 pname
= GL_TEXTURE_SAMPLES_IMG
;
6245 if (pname
== GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
) {
6246 DCHECK(framebuffer
);
6247 // If we query from the driver, it will be service ID; however, we need to
6248 // return the client ID here.
6249 const Framebuffer::Attachment
* attachment_object
=
6250 framebuffer
->GetAttachment(attachment
);
6251 *params
= attachment_object
? attachment_object
->object_name() : 0;
6255 glGetFramebufferAttachmentParameterivEXT(target
, attachment
, pname
, params
);
6256 // We didn't perform a full error check before gl call.
6257 LOCAL_PEEK_GL_ERROR(kFunctionName
);
6260 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
6261 GLenum target
, GLenum pname
, GLint
* params
) {
6262 Renderbuffer
* renderbuffer
=
6263 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6264 if (!renderbuffer
) {
6266 GL_INVALID_OPERATION
,
6267 "glGetRenderbufferParameteriv", "no renderbuffer bound");
6271 EnsureRenderbufferBound();
6273 case GL_RENDERBUFFER_INTERNAL_FORMAT
:
6274 *params
= renderbuffer
->internal_format();
6276 case GL_RENDERBUFFER_WIDTH
:
6277 *params
= renderbuffer
->width();
6279 case GL_RENDERBUFFER_HEIGHT
:
6280 *params
= renderbuffer
->height();
6282 case GL_RENDERBUFFER_SAMPLES_EXT
:
6283 if (features().use_img_for_multisampled_render_to_texture
) {
6284 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_IMG
,
6287 glGetRenderbufferParameterivEXT(target
, GL_RENDERBUFFER_SAMPLES_EXT
,
6291 glGetRenderbufferParameterivEXT(target
, pname
, params
);
6296 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
6297 GLint srcX0
, GLint srcY0
, GLint srcX1
, GLint srcY1
,
6298 GLint dstX0
, GLint dstY0
, GLint dstX1
, GLint dstY1
,
6299 GLbitfield mask
, GLenum filter
) {
6300 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
6302 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
6306 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6307 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
6308 BlitFramebufferHelper(
6309 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6310 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
,
6311 state_
.enable_flags
.scissor_test
);
6314 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6315 if (!state_
.bound_renderbuffer_valid
) {
6316 state_
.bound_renderbuffer_valid
= true;
6317 glBindRenderbufferEXT(GL_RENDERBUFFER
,
6318 state_
.bound_renderbuffer
.get()
6319 ? state_
.bound_renderbuffer
->service_id()
6324 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6325 const FeatureInfo
* feature_info
,
6328 GLenum internal_format
,
6331 // TODO(sievers): This could be resolved at the GL binding level, but the
6332 // binding process is currently a bit too 'brute force'.
6333 if (feature_info
->gl_version_info().is_angle
) {
6334 glRenderbufferStorageMultisampleANGLE(
6335 target
, samples
, internal_format
, width
, height
);
6336 } else if (feature_info
->feature_flags().use_core_framebuffer_multisample
) {
6337 glRenderbufferStorageMultisample(
6338 target
, samples
, internal_format
, width
, height
);
6340 glRenderbufferStorageMultisampleEXT(
6341 target
, samples
, internal_format
, width
, height
);
6345 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0
,
6355 // TODO(sievers): This could be resolved at the GL binding level, but the
6356 // binding process is currently a bit too 'brute force'.
6357 if (feature_info_
->gl_version_info().is_angle
) {
6358 glBlitFramebufferANGLE(
6359 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6360 } else if (feature_info_
->feature_flags().use_core_framebuffer_multisample
) {
6362 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6364 glBlitFramebufferEXT(
6365 srcX0
, srcY0
, srcX1
, srcY1
, dstX0
, dstY0
, dstX1
, dstY1
, mask
, filter
);
6369 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6371 GLenum internalformat
,
6374 if (samples
> renderbuffer_manager()->max_samples()) {
6377 "glRenderbufferStorageMultisample", "samples too large");
6381 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6382 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6385 "glRenderbufferStorageMultisample", "dimensions too large");
6389 uint32 estimated_size
= 0;
6390 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6391 width
, height
, samples
, internalformat
, &estimated_size
)) {
6394 "glRenderbufferStorageMultisample", "dimensions too large");
6398 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6401 "glRenderbufferStorageMultisample", "out of memory");
6408 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6409 GLenum target
, GLsizei samples
, GLenum internalformat
,
6410 GLsizei width
, GLsizei height
) {
6411 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6412 if (!renderbuffer
) {
6413 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6414 "glRenderbufferStorageMultisampleCHROMIUM",
6415 "no renderbuffer bound");
6419 if (!ValidateRenderbufferStorageMultisample(
6420 samples
, internalformat
, width
, height
)) {
6424 EnsureRenderbufferBound();
6425 GLenum impl_format
=
6426 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6428 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6429 "glRenderbufferStorageMultisampleCHROMIUM");
6430 RenderbufferStorageMultisampleHelper(
6431 feature_info_
.get(), target
, samples
, impl_format
, width
, height
);
6433 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6434 if (error
== GL_NO_ERROR
) {
6435 if (workarounds().validate_multisample_buffer_allocation
) {
6436 if (!VerifyMultisampleRenderbufferIntegrity(
6437 renderbuffer
->service_id(), impl_format
)) {
6440 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6445 // TODO(gman): If renderbuffers tracked which framebuffers they were
6446 // attached to we could just mark those framebuffers as not complete.
6447 framebuffer_manager()->IncFramebufferStateChangeCount();
6448 renderbuffer_manager()->SetInfo(
6449 renderbuffer
, samples
, internalformat
, width
, height
);
6453 // This is the handler for multisampled_render_to_texture extensions.
6454 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6455 GLenum target
, GLsizei samples
, GLenum internalformat
,
6456 GLsizei width
, GLsizei height
) {
6457 Renderbuffer
* renderbuffer
= GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6458 if (!renderbuffer
) {
6459 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
6460 "glRenderbufferStorageMultisampleEXT",
6461 "no renderbuffer bound");
6465 if (!ValidateRenderbufferStorageMultisample(
6466 samples
, internalformat
, width
, height
)) {
6470 EnsureRenderbufferBound();
6471 GLenum impl_format
=
6472 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6474 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6475 if (features().use_img_for_multisampled_render_to_texture
) {
6476 glRenderbufferStorageMultisampleIMG(
6477 target
, samples
, impl_format
, width
, height
);
6479 glRenderbufferStorageMultisampleEXT(
6480 target
, samples
, impl_format
, width
, height
);
6482 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6483 if (error
== GL_NO_ERROR
) {
6484 // TODO(gman): If renderbuffers tracked which framebuffers they were
6485 // attached to we could just mark those framebuffers as not complete.
6486 framebuffer_manager()->IncFramebufferStateChangeCount();
6487 renderbuffer_manager()->SetInfo(
6488 renderbuffer
, samples
, internalformat
, width
, height
);
6492 // This function validates the allocation of a multisampled renderbuffer
6493 // by clearing it to a key color, blitting the contents to a texture, and
6494 // reading back the color to ensure it matches the key.
6495 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6496 GLuint renderbuffer
, GLenum format
) {
6498 // Only validate color buffers.
6499 // These formats have been selected because they are very common or are known
6500 // to be used by the WebGL backbuffer. If problems are observed with other
6501 // color formats they can be added here.
6512 GLint draw_framebuffer
, read_framebuffer
;
6514 // Cache framebuffer and texture bindings.
6515 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING
, &draw_framebuffer
);
6516 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING
, &read_framebuffer
);
6518 if (!validation_texture_
) {
6519 GLint bound_texture
;
6520 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &bound_texture
);
6522 // Create additional resources needed for the verification.
6523 glGenTextures(1, &validation_texture_
);
6524 glGenFramebuffersEXT(1, &validation_fbo_multisample_
);
6525 glGenFramebuffersEXT(1, &validation_fbo_
);
6527 // Texture only needs to be 1x1.
6528 glBindTexture(GL_TEXTURE_2D
, validation_texture_
);
6529 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6530 // multisample will fail if the color format of the source and destination
6531 // do not match. Here, we assume that the source is GL_RGBA, and make the
6532 // destination GL_RGBA. http://crbug.com/484203
6533 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
6534 GL_UNSIGNED_BYTE
, NULL
);
6536 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6537 glFramebufferTexture2DEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6538 GL_TEXTURE_2D
, validation_texture_
, 0);
6540 glBindTexture(GL_TEXTURE_2D
, bound_texture
);
6543 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6544 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6545 GL_RENDERBUFFER
, renderbuffer
);
6547 // Cache current state and reset it to the values we require.
6548 GLboolean scissor_enabled
= false;
6549 glGetBooleanv(GL_SCISSOR_TEST
, &scissor_enabled
);
6550 if (scissor_enabled
)
6551 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
6553 GLboolean color_mask
[4] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
6554 glGetBooleanv(GL_COLOR_WRITEMASK
, color_mask
);
6555 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6557 GLfloat clear_color
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
6558 glGetFloatv(GL_COLOR_CLEAR_VALUE
, clear_color
);
6559 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
6561 // Clear the buffer to the desired key color.
6562 glClear(GL_COLOR_BUFFER_BIT
);
6564 // Blit from the multisample buffer to a standard texture.
6565 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, validation_fbo_multisample_
);
6566 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, validation_fbo_
);
6568 BlitFramebufferHelper(
6569 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
6571 // Read a pixel from the buffer.
6572 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_
);
6574 unsigned char pixel
[3] = {0, 0, 0};
6575 glReadPixels(0, 0, 1, 1, GL_RGB
, GL_UNSIGNED_BYTE
, &pixel
);
6577 // Detach the renderbuffer.
6578 glBindFramebufferEXT(GL_FRAMEBUFFER
, validation_fbo_multisample_
);
6579 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
6580 GL_RENDERBUFFER
, 0);
6582 // Restore cached state.
6583 if (scissor_enabled
)
6584 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
6586 state_
.SetDeviceColorMask(
6587 color_mask
[0], color_mask
[1], color_mask
[2], color_mask
[3]);
6588 glClearColor(clear_color
[0], clear_color
[1], clear_color
[2], clear_color
[3]);
6589 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, draw_framebuffer
);
6590 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, read_framebuffer
);
6592 // Return true if the pixel matched the desired key color.
6593 return (pixel
[0] == 0xFF &&
6598 void GLES2DecoderImpl::DoRenderbufferStorage(
6599 GLenum target
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
6600 Renderbuffer
* renderbuffer
=
6601 GetRenderbufferInfoForTarget(GL_RENDERBUFFER
);
6602 if (!renderbuffer
) {
6604 GL_INVALID_OPERATION
,
6605 "glRenderbufferStorage", "no renderbuffer bound");
6609 if (width
> renderbuffer_manager()->max_renderbuffer_size() ||
6610 height
> renderbuffer_manager()->max_renderbuffer_size()) {
6612 GL_INVALID_VALUE
, "glRenderbufferStorage", "dimensions too large");
6616 uint32 estimated_size
= 0;
6617 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6618 width
, height
, 1, internalformat
, &estimated_size
)) {
6620 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "dimensions too large");
6624 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
6626 GL_OUT_OF_MEMORY
, "glRenderbufferStorage", "out of memory");
6630 EnsureRenderbufferBound();
6631 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6632 glRenderbufferStorageEXT(
6634 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6638 GLenum error
= LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6639 if (error
== GL_NO_ERROR
) {
6640 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6641 // we could just mark those framebuffers as not complete.
6642 framebuffer_manager()->IncFramebufferStateChangeCount();
6643 renderbuffer_manager()->SetInfo(
6644 renderbuffer
, 1, internalformat
, width
, height
);
6648 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id
) {
6649 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6650 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6651 Program
* program
= GetProgramInfoNotShader(
6652 program_id
, "glLinkProgram");
6657 LogClientServiceForInfo(program
, program_id
, "glLinkProgram");
6658 if (program
->Link(shader_manager(),
6659 workarounds().count_all_in_varyings_packing
?
6660 Program::kCountAll
: Program::kCountOnlyStaticallyUsed
,
6661 shader_cache_callback_
)) {
6662 if (program
== state_
.current_program
.get()) {
6663 if (workarounds().use_current_program_after_successful_link
)
6664 glUseProgram(program
->service_id());
6665 if (workarounds().clear_uniforms_before_first_program_use
)
6666 program_manager()->ClearUniforms(program
);
6670 // LinkProgram can be very slow. Exit command processing to allow for
6671 // context preemption and GPU watchdog checks.
6672 ExitCommandProcessingEarly();
6675 void GLES2DecoderImpl::DoReadBuffer(GLenum src
) {
6682 GLenum upper_limit
= static_cast<GLenum
>(
6683 group_
->max_color_attachments() + GL_COLOR_ATTACHMENT0
);
6684 if (src
< GL_COLOR_ATTACHMENT0
|| src
>= upper_limit
) {
6686 GL_INVALID_ENUM
, "glReadBuffer", "invalid enum for src");
6693 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER
);
6695 if (src
== GL_BACK
) {
6697 GL_INVALID_ENUM
, "glReadBuffer",
6698 "invalid src for a named framebuffer");
6701 framebuffer
->set_read_buffer(src
);
6703 if (src
!= GL_NONE
&& src
!= GL_BACK
) {
6705 GL_INVALID_ENUM
, "glReadBuffer",
6706 "invalid src for the default framebuffer");
6709 back_buffer_read_buffer_
= src
;
6710 if (GetBackbufferServiceId() && src
== GL_BACK
)
6711 src
= GL_COLOR_ATTACHMENT0
;
6716 void GLES2DecoderImpl::DoSamplerParameterfv(
6717 GLuint sampler
, GLenum pname
, const GLfloat
* params
) {
6719 glSamplerParameterf(sampler
, pname
, params
[0]);
6722 void GLES2DecoderImpl::DoSamplerParameteriv(
6723 GLuint sampler
, GLenum pname
, const GLint
* params
) {
6725 glSamplerParameteri(sampler
, pname
, params
[0]);
6728 void GLES2DecoderImpl::DoTexParameterf(
6729 GLenum target
, GLenum pname
, GLfloat param
) {
6730 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6733 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterf", "unknown texture");
6737 texture_manager()->SetParameterf(
6738 "glTexParameterf", GetErrorState(), texture
, pname
, param
);
6741 void GLES2DecoderImpl::DoTexParameteri(
6742 GLenum target
, GLenum pname
, GLint param
) {
6743 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6746 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameteri", "unknown texture");
6750 texture_manager()->SetParameteri(
6751 "glTexParameteri", GetErrorState(), texture
, pname
, param
);
6754 void GLES2DecoderImpl::DoTexParameterfv(
6755 GLenum target
, GLenum pname
, const GLfloat
* params
) {
6756 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glTexParameterfv", "unknown texture");
6763 texture_manager()->SetParameterf(
6764 "glTexParameterfv", GetErrorState(), texture
, pname
, *params
);
6767 void GLES2DecoderImpl::DoTexParameteriv(
6768 GLenum target
, GLenum pname
, const GLint
* params
) {
6769 TextureRef
* texture
= texture_manager()->GetTextureInfoForTarget(
6773 GL_INVALID_VALUE
, "glTexParameteriv", "unknown texture");
6777 texture_manager()->SetParameteri(
6778 "glTexParameteriv", GetErrorState(), texture
, pname
, *params
);
6781 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name
) {
6782 if (!state_
.bound_valuebuffer
.get()) {
6783 // There is no valuebuffer bound
6784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6785 "no valuebuffer in use");
6791 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6792 GLenum subscription
,
6793 const char* function_name
) {
6794 if (!CheckCurrentValuebuffer(function_name
)) {
6797 if (!state_
.bound_valuebuffer
.get()->IsSubscribed(subscription
)) {
6798 // The valuebuffer is not subscribed to the target
6799 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6800 "valuebuffer is not subscribed");
6806 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location
,
6807 GLenum subscription
,
6808 const char* function_name
) {
6809 if (!CheckCurrentProgramForUniform(location
, function_name
)) {
6812 GLint real_location
= -1;
6813 GLint array_index
= -1;
6814 const Program::UniformInfo
* info
=
6815 state_
.current_program
->GetUniformInfoByFakeLocation(
6816 location
, &real_location
, &array_index
);
6818 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
, "unknown location");
6821 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription
) &
6822 info
->accepts_api_type
) == 0) {
6823 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6824 "wrong type for subscription");
6830 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name
) {
6831 if (!state_
.current_program
.get()) {
6832 // The program does not exist.
6834 GL_INVALID_OPERATION
, function_name
, "no program in use");
6837 if (!state_
.current_program
->InUse()) {
6839 GL_INVALID_OPERATION
, function_name
, "program not linked");
6845 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6846 GLint location
, const char* function_name
) {
6847 if (!CheckCurrentProgram(function_name
)) {
6850 return location
!= -1;
6853 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6854 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
6857 const Framebuffer::Attachment
* attachment
=
6858 framebuffer
->GetAttachment(GL_COLOR_ATTACHMENT0
);
6862 DCHECK(state_
.current_program
.get());
6863 const Program::SamplerIndices
& sampler_indices
=
6864 state_
.current_program
->sampler_indices();
6865 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
6866 const Program::UniformInfo
* uniform_info
=
6867 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
6868 DCHECK(uniform_info
);
6869 if (uniform_info
->type
!= GL_SAMPLER_2D
)
6871 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
6872 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
6873 if (texture_unit_index
>= state_
.texture_units
.size())
6875 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
6876 TextureRef
* texture_ref
=
6877 texture_unit
.GetInfoForSamplerType(GL_SAMPLER_2D
).get();
6878 if (attachment
->IsTexture(texture_ref
))
6885 bool GLES2DecoderImpl::CheckUniformForApiType(
6886 const Program::UniformInfo
* info
,
6887 const char* function_name
,
6888 Program::UniformApiType api_type
) {
6890 if ((api_type
& info
->accepts_api_type
) == 0) {
6891 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
6892 "wrong uniform function for type");
6898 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6899 GLint fake_location
,
6900 const char* function_name
,
6901 Program::UniformApiType api_type
,
6902 GLint
* real_location
,
6907 DCHECK(real_location
);
6909 if (!CheckCurrentProgramForUniform(fake_location
, function_name
)) {
6912 GLint array_index
= -1;
6913 const Program::UniformInfo
* info
=
6914 state_
.current_program
->GetUniformInfoByFakeLocation(
6915 fake_location
, real_location
, &array_index
);
6918 GL_INVALID_OPERATION
, function_name
, "unknown location");
6921 if (!CheckUniformForApiType(info
, function_name
, api_type
)) {
6924 if (*count
> 1 && !info
->is_array
) {
6926 GL_INVALID_OPERATION
, function_name
, "count > 1 for non-array");
6929 *count
= std::min(info
->size
- array_index
, *count
);
6937 void GLES2DecoderImpl::DoUniform1i(GLint fake_location
, GLint v0
) {
6940 GLint real_location
= -1;
6941 if (!PrepForSetUniformByLocation(fake_location
,
6943 Program::kUniform1i
,
6949 if (!state_
.current_program
->SetSamplers(
6950 state_
.texture_units
.size(), fake_location
, 1, &v0
)) {
6952 GL_INVALID_VALUE
, "glUniform1i", "texture unit out of range");
6955 glUniform1i(real_location
, v0
);
6958 void GLES2DecoderImpl::DoUniform1iv(
6959 GLint fake_location
, GLsizei count
, const GLint
*value
) {
6961 GLint real_location
= -1;
6962 if (!PrepForSetUniformByLocation(fake_location
,
6964 Program::kUniform1i
,
6970 if (type
== GL_SAMPLER_2D
|| type
== GL_SAMPLER_2D_RECT_ARB
||
6971 type
== GL_SAMPLER_CUBE
|| type
== GL_SAMPLER_EXTERNAL_OES
) {
6972 if (!state_
.current_program
->SetSamplers(
6973 state_
.texture_units
.size(), fake_location
, count
, value
)) {
6975 GL_INVALID_VALUE
, "glUniform1iv", "texture unit out of range");
6979 glUniform1iv(real_location
, count
, value
);
6982 void GLES2DecoderImpl::DoUniform1uiv(
6983 GLint fake_location
, GLsizei count
, const GLuint
*value
) {
6985 GLint real_location
= -1;
6986 if (!PrepForSetUniformByLocation(fake_location
,
6988 Program::kUniform1ui
,
6994 glUniform1uiv(real_location
, count
, value
);
6997 void GLES2DecoderImpl::DoUniform1fv(
6998 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7000 GLint real_location
= -1;
7001 if (!PrepForSetUniformByLocation(fake_location
,
7003 Program::kUniform1f
,
7009 if (type
== GL_BOOL
) {
7010 scoped_ptr
<GLint
[]> temp(new GLint
[count
]);
7011 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
7012 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7014 DoUniform1iv(real_location
, count
, temp
.get());
7016 glUniform1fv(real_location
, count
, value
);
7020 void GLES2DecoderImpl::DoUniform2fv(
7021 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7023 GLint real_location
= -1;
7024 if (!PrepForSetUniformByLocation(fake_location
,
7026 Program::kUniform2f
,
7032 if (type
== GL_BOOL_VEC2
) {
7033 GLsizei num_values
= count
* 2;
7034 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7035 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7036 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7038 glUniform2iv(real_location
, count
, temp
.get());
7040 glUniform2fv(real_location
, count
, value
);
7044 void GLES2DecoderImpl::DoUniform3fv(
7045 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7047 GLint real_location
= -1;
7048 if (!PrepForSetUniformByLocation(fake_location
,
7050 Program::kUniform3f
,
7056 if (type
== GL_BOOL_VEC3
) {
7057 GLsizei num_values
= count
* 3;
7058 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7059 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7060 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7062 glUniform3iv(real_location
, count
, temp
.get());
7064 glUniform3fv(real_location
, count
, value
);
7068 void GLES2DecoderImpl::DoUniform4fv(
7069 GLint fake_location
, GLsizei count
, const GLfloat
* value
) {
7071 GLint real_location
= -1;
7072 if (!PrepForSetUniformByLocation(fake_location
,
7074 Program::kUniform4f
,
7080 if (type
== GL_BOOL_VEC4
) {
7081 GLsizei num_values
= count
* 4;
7082 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
7083 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
7084 temp
[ii
] = static_cast<GLint
>(value
[ii
] != 0.0f
);
7086 glUniform4iv(real_location
, count
, temp
.get());
7088 glUniform4fv(real_location
, count
, value
);
7092 void GLES2DecoderImpl::DoUniform2iv(
7093 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7095 GLint real_location
= -1;
7096 if (!PrepForSetUniformByLocation(fake_location
,
7098 Program::kUniform2i
,
7104 glUniform2iv(real_location
, count
, value
);
7107 void GLES2DecoderImpl::DoUniform2uiv(
7108 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7110 GLint real_location
= -1;
7111 if (!PrepForSetUniformByLocation(fake_location
,
7113 Program::kUniform2ui
,
7119 glUniform2uiv(real_location
, count
, value
);
7122 void GLES2DecoderImpl::DoUniform3iv(
7123 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7125 GLint real_location
= -1;
7126 if (!PrepForSetUniformByLocation(fake_location
,
7128 Program::kUniform3i
,
7134 glUniform3iv(real_location
, count
, value
);
7137 void GLES2DecoderImpl::DoUniform3uiv(
7138 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7140 GLint real_location
= -1;
7141 if (!PrepForSetUniformByLocation(fake_location
,
7143 Program::kUniform3ui
,
7149 glUniform3uiv(real_location
, count
, value
);
7152 void GLES2DecoderImpl::DoUniform4iv(
7153 GLint fake_location
, GLsizei count
, const GLint
* value
) {
7155 GLint real_location
= -1;
7156 if (!PrepForSetUniformByLocation(fake_location
,
7158 Program::kUniform4i
,
7164 glUniform4iv(real_location
, count
, value
);
7167 void GLES2DecoderImpl::DoUniform4uiv(
7168 GLint fake_location
, GLsizei count
, const GLuint
* value
) {
7170 GLint real_location
= -1;
7171 if (!PrepForSetUniformByLocation(fake_location
,
7173 Program::kUniform4ui
,
7179 glUniform4uiv(real_location
, count
, value
);
7182 void GLES2DecoderImpl::DoUniformMatrix2fv(
7183 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7184 const GLfloat
* value
) {
7186 GLint real_location
= -1;
7187 if (!PrepForSetUniformByLocation(fake_location
,
7188 "glUniformMatrix2fv",
7189 Program::kUniformMatrix2f
,
7195 glUniformMatrix2fv(real_location
, count
, transpose
, value
);
7198 void GLES2DecoderImpl::DoUniformMatrix3fv(
7199 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7200 const GLfloat
* value
) {
7202 GLint real_location
= -1;
7203 if (!PrepForSetUniformByLocation(fake_location
,
7204 "glUniformMatrix3fv",
7205 Program::kUniformMatrix3f
,
7211 glUniformMatrix3fv(real_location
, count
, transpose
, value
);
7214 void GLES2DecoderImpl::DoUniformMatrix4fv(
7215 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7216 const GLfloat
* value
) {
7218 GLint real_location
= -1;
7219 if (!PrepForSetUniformByLocation(fake_location
,
7220 "glUniformMatrix4fv",
7221 Program::kUniformMatrix4f
,
7227 glUniformMatrix4fv(real_location
, count
, transpose
, value
);
7230 void GLES2DecoderImpl::DoUniformMatrix2x3fv(
7231 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7232 const GLfloat
* value
) {
7234 GLint real_location
= -1;
7235 if (!PrepForSetUniformByLocation(fake_location
,
7236 "glUniformMatrix2x3fv",
7237 Program::kUniformMatrix2x3f
,
7243 glUniformMatrix2x3fv(real_location
, count
, transpose
, value
);
7246 void GLES2DecoderImpl::DoUniformMatrix2x4fv(
7247 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7248 const GLfloat
* value
) {
7250 GLint real_location
= -1;
7251 if (!PrepForSetUniformByLocation(fake_location
,
7252 "glUniformMatrix2x4fv",
7253 Program::kUniformMatrix2x4f
,
7259 glUniformMatrix2x4fv(real_location
, count
, transpose
, value
);
7262 void GLES2DecoderImpl::DoUniformMatrix3x2fv(
7263 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7264 const GLfloat
* value
) {
7266 GLint real_location
= -1;
7267 if (!PrepForSetUniformByLocation(fake_location
,
7268 "glUniformMatrix3x2fv",
7269 Program::kUniformMatrix3x2f
,
7275 glUniformMatrix3x2fv(real_location
, count
, transpose
, value
);
7278 void GLES2DecoderImpl::DoUniformMatrix3x4fv(
7279 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7280 const GLfloat
* value
) {
7282 GLint real_location
= -1;
7283 if (!PrepForSetUniformByLocation(fake_location
,
7284 "glUniformMatrix3x4fv",
7285 Program::kUniformMatrix3x4f
,
7291 glUniformMatrix3x4fv(real_location
, count
, transpose
, value
);
7294 void GLES2DecoderImpl::DoUniformMatrix4x2fv(
7295 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7296 const GLfloat
* value
) {
7298 GLint real_location
= -1;
7299 if (!PrepForSetUniformByLocation(fake_location
,
7300 "glUniformMatrix4x2fv",
7301 Program::kUniformMatrix4x2f
,
7307 glUniformMatrix4x2fv(real_location
, count
, transpose
, value
);
7310 void GLES2DecoderImpl::DoUniformMatrix4x3fv(
7311 GLint fake_location
, GLsizei count
, GLboolean transpose
,
7312 const GLfloat
* value
) {
7314 GLint real_location
= -1;
7315 if (!PrepForSetUniformByLocation(fake_location
,
7316 "glUniformMatrix4x3fv",
7317 Program::kUniformMatrix4x3f
,
7323 glUniformMatrix4x3fv(real_location
, count
, transpose
, value
);
7326 void GLES2DecoderImpl::DoUseProgram(GLuint program_id
) {
7327 GLuint service_id
= 0;
7328 Program
* program
= NULL
;
7330 program
= GetProgramInfoNotShader(program_id
, "glUseProgram");
7334 if (!program
->IsValid()) {
7335 // Program was not linked successfully. (ie, glLinkProgram)
7337 GL_INVALID_OPERATION
, "glUseProgram", "program not linked");
7340 service_id
= program
->service_id();
7342 if (state_
.current_program
.get()) {
7343 program_manager()->UnuseProgram(shader_manager(),
7344 state_
.current_program
.get());
7346 state_
.current_program
= program
;
7347 LogClientServiceMapping("glUseProgram", program_id
, service_id
);
7348 glUseProgram(service_id
);
7349 if (state_
.current_program
.get()) {
7350 program_manager()->UseProgram(state_
.current_program
.get());
7351 if (workarounds().clear_uniforms_before_first_program_use
)
7352 program_manager()->ClearUniforms(program
);
7356 void GLES2DecoderImpl::RenderWarning(
7357 const char* filename
, int line
, const std::string
& msg
) {
7358 logger_
.LogMessage(filename
, line
, std::string("RENDER WARNING: ") + msg
);
7361 void GLES2DecoderImpl::PerformanceWarning(
7362 const char* filename
, int line
, const std::string
& msg
) {
7363 logger_
.LogMessage(filename
, line
,
7364 std::string("PERFORMANCE WARNING: ") + msg
);
7367 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
7368 Texture
* texture
, GLenum textarget
) {
7369 // Image is already in use if texture is attached to a framebuffer.
7370 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
7371 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7373 ScopedGLErrorSuppressor
suppressor(
7374 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
7376 glBindTexture(textarget
, texture
->service_id());
7377 image
->WillUseTexImage();
7378 RestoreCurrentTextureBindings(&state_
, textarget
);
7383 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
7384 Texture
* texture
, GLenum textarget
) {
7385 // Image is still in use if texture is attached to a framebuffer.
7386 if (texture
&& !texture
->IsAttachedToFramebuffer()) {
7387 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7389 ScopedGLErrorSuppressor
suppressor(
7390 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
7392 glBindTexture(textarget
, texture
->service_id());
7393 image
->DidUseTexImage();
7394 RestoreCurrentTextureBindings(&state_
, textarget
);
7399 bool GLES2DecoderImpl::PrepareTexturesForRender() {
7400 DCHECK(state_
.current_program
.get());
7401 if (!texture_manager()->HaveUnrenderableTextures() &&
7402 !texture_manager()->HaveImages()) {
7405 bool textures_set
= false;
7406 const Program::SamplerIndices
& sampler_indices
=
7407 state_
.current_program
->sampler_indices();
7408 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7409 const Program::UniformInfo
* uniform_info
=
7410 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7411 DCHECK(uniform_info
);
7412 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7413 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7414 if (texture_unit_index
< state_
.texture_units
.size()) {
7415 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7416 TextureRef
* texture_ref
=
7417 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7418 GLenum textarget
= GetBindTargetForSamplerType(uniform_info
->type
);
7419 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7420 textures_set
= true;
7421 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7424 texture_manager()->black_texture_id(uniform_info
->type
));
7426 LOCAL_RENDER_WARNING(
7427 std::string("there is no texture bound to the unit ") +
7428 base::UintToString(texture_unit_index
));
7430 LOCAL_RENDER_WARNING(
7431 std::string("texture bound to texture unit ") +
7432 base::UintToString(texture_unit_index
) +
7433 " is not renderable. It maybe non-power-of-2 and have"
7434 " incompatible texture filtering.");
7439 if (textarget
!= GL_TEXTURE_CUBE_MAP
) {
7440 Texture
* texture
= texture_ref
->texture();
7441 gfx::GLImage
* image
= texture
->GetLevelImage(textarget
, 0);
7442 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7443 ScopedGLErrorSuppressor
suppressor(
7444 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
7445 textures_set
= true;
7446 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7447 image
->WillUseTexImage();
7452 // else: should this be an error?
7455 return !textures_set
;
7458 void GLES2DecoderImpl::RestoreStateForTextures() {
7459 DCHECK(state_
.current_program
.get());
7460 const Program::SamplerIndices
& sampler_indices
=
7461 state_
.current_program
->sampler_indices();
7462 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7463 const Program::UniformInfo
* uniform_info
=
7464 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7465 DCHECK(uniform_info
);
7466 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7467 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7468 if (texture_unit_index
< state_
.texture_units
.size()) {
7469 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7470 TextureRef
* texture_ref
=
7471 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7472 if (!texture_ref
|| !texture_manager()->CanRender(texture_ref
)) {
7473 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7474 // Get the texture_ref info that was previously bound here.
7475 texture_ref
= texture_unit
.bind_target
== GL_TEXTURE_2D
7476 ? texture_unit
.bound_texture_2d
.get()
7477 : texture_unit
.bound_texture_cube_map
.get();
7478 glBindTexture(texture_unit
.bind_target
,
7479 texture_ref
? texture_ref
->service_id() : 0);
7483 if (texture_unit
.bind_target
!= GL_TEXTURE_CUBE_MAP
) {
7484 Texture
* texture
= texture_ref
->texture();
7485 gfx::GLImage
* image
=
7486 texture
->GetLevelImage(texture_unit
.bind_target
, 0);
7487 if (image
&& !texture
->IsAttachedToFramebuffer()) {
7488 ScopedGLErrorSuppressor
suppressor(
7489 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7490 glActiveTexture(GL_TEXTURE0
+ texture_unit_index
);
7491 image
->DidUseTexImage();
7498 // Set the active texture back to whatever the user had it as.
7499 glActiveTexture(GL_TEXTURE0
+ state_
.active_texture_unit
);
7502 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7503 // Only check if there are some uncleared textures.
7504 if (!texture_manager()->HaveUnsafeTextures()) {
7508 // 1: Check all textures we are about to render with.
7509 if (state_
.current_program
.get()) {
7510 const Program::SamplerIndices
& sampler_indices
=
7511 state_
.current_program
->sampler_indices();
7512 for (size_t ii
= 0; ii
< sampler_indices
.size(); ++ii
) {
7513 const Program::UniformInfo
* uniform_info
=
7514 state_
.current_program
->GetUniformInfo(sampler_indices
[ii
]);
7515 DCHECK(uniform_info
);
7516 for (size_t jj
= 0; jj
< uniform_info
->texture_units
.size(); ++jj
) {
7517 GLuint texture_unit_index
= uniform_info
->texture_units
[jj
];
7518 if (texture_unit_index
< state_
.texture_units
.size()) {
7519 TextureUnit
& texture_unit
= state_
.texture_units
[texture_unit_index
];
7520 TextureRef
* texture_ref
=
7521 texture_unit
.GetInfoForSamplerType(uniform_info
->type
).get();
7522 if (texture_ref
&& !texture_ref
->texture()->SafeToRenderFrom()) {
7523 if (!texture_manager()->ClearRenderableLevels(this, texture_ref
)) {
7534 bool GLES2DecoderImpl::IsDrawValid(
7535 const char* function_name
, GLuint max_vertex_accessed
, bool instanced
,
7536 GLsizei primcount
) {
7537 DCHECK(instanced
|| primcount
== 1);
7539 // NOTE: We specifically do not check current_program->IsValid() because
7540 // it could never be invalid since glUseProgram would have failed. While
7541 // glLinkProgram could later mark the program as invalid the previous
7542 // valid program will still function if it is still the current program.
7543 if (!state_
.current_program
.get()) {
7544 // The program does not exist.
7545 // But GL says no ERROR.
7546 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7550 if (CheckDrawingFeedbackLoops()) {
7552 GL_INVALID_OPERATION
, function_name
,
7553 "Source and destination textures of the draw are the same.");
7557 return state_
.vertex_attrib_manager
7558 ->ValidateBindings(function_name
,
7560 feature_info_
.get(),
7561 state_
.current_program
.get(),
7562 max_vertex_accessed
,
7567 bool GLES2DecoderImpl::SimulateAttrib0(
7568 const char* function_name
, GLuint max_vertex_accessed
, bool* simulated
) {
7572 if (feature_info_
->gl_version_info().BehavesLikeGLES())
7575 const VertexAttrib
* attrib
=
7576 state_
.vertex_attrib_manager
->GetVertexAttrib(0);
7577 // If it's enabled or it's not used then we don't need to do anything.
7578 bool attrib_0_used
=
7579 state_
.current_program
->GetAttribInfoByLocation(0) != NULL
;
7580 if (attrib
->enabled() && attrib_0_used
) {
7584 // Make a buffer with a single repeated vec4 value enough to
7585 // simulate the constant value that is supposed to be here.
7586 // This is required to emulate GLES2 on GL.
7587 GLuint num_vertices
= max_vertex_accessed
+ 1;
7588 uint32 size_needed
= 0;
7590 if (num_vertices
== 0 ||
7591 !SafeMultiplyUint32(num_vertices
, sizeof(Vec4f
), &size_needed
) ||
7592 size_needed
> 0x7FFFFFFFU
) {
7593 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7597 LOCAL_PERFORMANCE_WARNING(
7598 "Attribute 0 is disabled. This has signficant performance penalty");
7600 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7601 glBindBuffer(GL_ARRAY_BUFFER
, attrib_0_buffer_id_
);
7603 bool new_buffer
= static_cast<GLsizei
>(size_needed
) > attrib_0_size_
;
7605 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7606 GLenum error
= glGetError();
7607 if (error
!= GL_NO_ERROR
) {
7609 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7614 const Vec4
& value
= state_
.attrib_values
[0];
7617 (!attrib_0_buffer_matches_value_
|| !value
.Equal(attrib_0_value_
)))){
7618 // TODO(zmo): This is not 100% correct because we might lose data when
7619 // casting to float type, but it is a corner case and once we migrate to
7620 // core profiles on desktop GL, it is no longer relevant.
7621 Vec4f
fvalue(value
);
7622 std::vector
<Vec4f
> temp(num_vertices
, fvalue
);
7623 glBufferSubData(GL_ARRAY_BUFFER
, 0, size_needed
, &temp
[0].v
[0]);
7624 attrib_0_buffer_matches_value_
= true;
7625 attrib_0_value_
= value
;
7626 attrib_0_size_
= size_needed
;
7629 glVertexAttribPointer(0, 4, GL_FLOAT
, GL_FALSE
, 0, NULL
);
7631 if (attrib
->divisor())
7632 glVertexAttribDivisorANGLE(0, 0);
7638 void GLES2DecoderImpl::RestoreStateForAttrib(
7639 GLuint attrib_index
, bool restore_array_binding
) {
7640 const VertexAttrib
* attrib
=
7641 state_
.vertex_attrib_manager
->GetVertexAttrib(attrib_index
);
7642 if (restore_array_binding
) {
7643 const void* ptr
= reinterpret_cast<const void*>(attrib
->offset());
7644 Buffer
* buffer
= attrib
->buffer();
7645 glBindBuffer(GL_ARRAY_BUFFER
, buffer
? buffer
->service_id() : 0);
7646 glVertexAttribPointer(
7647 attrib_index
, attrib
->size(), attrib
->type(), attrib
->normalized(),
7648 attrib
->gl_stride(), ptr
);
7650 if (attrib
->divisor())
7651 glVertexAttribDivisorANGLE(attrib_index
, attrib
->divisor());
7653 GL_ARRAY_BUFFER
, state_
.bound_array_buffer
.get() ?
7654 state_
.bound_array_buffer
->service_id() : 0);
7656 // Never touch vertex attribute 0's state (in particular, never
7657 // disable it) when running on desktop GL because it will never be
7659 if (attrib_index
!= 0 ||
7660 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
7661 if (attrib
->enabled()) {
7662 glEnableVertexAttribArray(attrib_index
);
7664 glDisableVertexAttribArray(attrib_index
);
7669 bool GLES2DecoderImpl::SimulateFixedAttribs(
7670 const char* function_name
,
7671 GLuint max_vertex_accessed
, bool* simulated
, GLsizei primcount
) {
7674 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
)
7677 if (!state_
.vertex_attrib_manager
->HaveFixedAttribs()) {
7681 LOCAL_PERFORMANCE_WARNING(
7682 "GL_FIXED attributes have a signficant performance penalty");
7684 // NOTE: we could be smart and try to check if a buffer is used
7685 // twice in 2 different attribs, find the overlapping parts and therefore
7686 // duplicate the minimum amount of data but this whole code path is not meant
7687 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7688 // tests so we just add to the buffer attrib used.
7690 GLuint elements_needed
= 0;
7691 const VertexAttribManager::VertexAttribList
& enabled_attribs
=
7692 state_
.vertex_attrib_manager
->GetEnabledVertexAttribs();
7693 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7694 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7695 const VertexAttrib
* attrib
= *it
;
7696 const Program::VertexAttrib
* attrib_info
=
7697 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7698 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7699 max_vertex_accessed
);
7700 GLuint num_vertices
= max_accessed
+ 1;
7701 if (num_vertices
== 0) {
7703 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7707 attrib
->CanAccess(max_accessed
) &&
7708 attrib
->type() == GL_FIXED
) {
7709 uint32 elements_used
= 0;
7710 if (!SafeMultiplyUint32(num_vertices
, attrib
->size(), &elements_used
) ||
7711 !SafeAddUint32(elements_needed
, elements_used
, &elements_needed
)) {
7713 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7719 const uint32 kSizeOfFloat
= sizeof(float); // NOLINT
7720 uint32 size_needed
= 0;
7721 if (!SafeMultiplyUint32(elements_needed
, kSizeOfFloat
, &size_needed
) ||
7722 size_needed
> 0x7FFFFFFFU
) {
7724 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7728 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name
);
7730 glBindBuffer(GL_ARRAY_BUFFER
, fixed_attrib_buffer_id_
);
7731 if (static_cast<GLsizei
>(size_needed
) > fixed_attrib_buffer_size_
) {
7732 glBufferData(GL_ARRAY_BUFFER
, size_needed
, NULL
, GL_DYNAMIC_DRAW
);
7733 GLenum error
= glGetError();
7734 if (error
!= GL_NO_ERROR
) {
7736 GL_OUT_OF_MEMORY
, function_name
, "simulating GL_FIXED attribs");
7741 // Copy the elements and convert to float
7742 GLintptr offset
= 0;
7743 for (VertexAttribManager::VertexAttribList::const_iterator it
=
7744 enabled_attribs
.begin(); it
!= enabled_attribs
.end(); ++it
) {
7745 const VertexAttrib
* attrib
= *it
;
7746 const Program::VertexAttrib
* attrib_info
=
7747 state_
.current_program
->GetAttribInfoByLocation(attrib
->index());
7748 GLuint max_accessed
= attrib
->MaxVertexAccessed(primcount
,
7749 max_vertex_accessed
);
7750 GLuint num_vertices
= max_accessed
+ 1;
7751 if (num_vertices
== 0) {
7753 GL_OUT_OF_MEMORY
, function_name
, "Simulating attrib 0");
7757 attrib
->CanAccess(max_accessed
) &&
7758 attrib
->type() == GL_FIXED
) {
7759 int num_elements
= attrib
->size() * num_vertices
;
7760 const int src_size
= num_elements
* sizeof(int32
);
7761 const int dst_size
= num_elements
* sizeof(float);
7762 scoped_ptr
<float[]> data(new float[num_elements
]);
7763 const int32
* src
= reinterpret_cast<const int32
*>(
7764 attrib
->buffer()->GetRange(attrib
->offset(), src_size
));
7765 const int32
* end
= src
+ num_elements
;
7766 float* dst
= data
.get();
7767 while (src
!= end
) {
7768 *dst
++ = static_cast<float>(*src
++) / 65536.0f
;
7770 glBufferSubData(GL_ARRAY_BUFFER
, offset
, dst_size
, data
.get());
7771 glVertexAttribPointer(
7772 attrib
->index(), attrib
->size(), GL_FLOAT
, false, 0,
7773 reinterpret_cast<GLvoid
*>(offset
));
7781 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7782 // There's no need to call glVertexAttribPointer because we shadow all the
7783 // settings and passing GL_FIXED to it will not work.
7786 state_
.bound_array_buffer
.get() ? state_
.bound_array_buffer
->service_id()
7790 error::Error
GLES2DecoderImpl::DoDrawArrays(
7791 const char* function_name
,
7796 GLsizei primcount
) {
7797 error::Error error
= WillAccessBoundFramebufferForDraw();
7798 if (error
!= error::kNoError
)
7800 if (!validators_
->draw_mode
.IsValid(mode
)) {
7801 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7802 return error::kNoError
;
7805 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7806 return error::kNoError
;
7808 if (primcount
< 0) {
7809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7810 return error::kNoError
;
7812 if (!CheckBoundFramebuffersValid(function_name
)) {
7813 return error::kNoError
;
7815 // We have to check this here because the prototype for glDrawArrays
7816 // is GLint not GLsizei.
7818 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "first < 0");
7819 return error::kNoError
;
7822 if (count
== 0 || primcount
== 0) {
7823 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7824 return error::kNoError
;
7827 GLuint max_vertex_accessed
= first
+ count
- 1;
7828 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7829 if (!ClearUnclearedTextures()) {
7830 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7831 return error::kNoError
;
7833 bool simulated_attrib_0
= false;
7834 if (!SimulateAttrib0(
7835 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7836 return error::kNoError
;
7838 bool simulated_fixed_attribs
= false;
7839 if (SimulateFixedAttribs(
7840 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7842 bool textures_set
= !PrepareTexturesForRender();
7844 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7846 glDrawArrays(mode
, first
, count
);
7848 glDrawArraysInstancedANGLE(mode
, first
, count
, primcount
);
7851 RestoreStateForTextures();
7853 if (simulated_fixed_attribs
) {
7854 RestoreStateForSimulatedFixedAttribs();
7857 if (simulated_attrib_0
) {
7858 // We don't have to restore attrib 0 generic data at the end of this
7859 // function even if it is simulated. This is because we will simulate
7860 // it in each draw call, and attrib 0 generic data queries use cached
7861 // values instead of passing down to the underlying driver.
7862 RestoreStateForAttrib(0, false);
7865 return error::kNoError
;
7868 error::Error
GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size
,
7869 const void* cmd_data
) {
7870 // TODO(zmo): crbug.com/481184
7871 // On Desktop GL with versions lower than 4.3, we need to emulate
7872 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7873 const cmds::DrawArrays
& c
= *static_cast<const cmds::DrawArrays
*>(cmd_data
);
7874 return DoDrawArrays("glDrawArrays",
7876 static_cast<GLenum
>(c
.mode
),
7877 static_cast<GLint
>(c
.first
),
7878 static_cast<GLsizei
>(c
.count
),
7882 error::Error
GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7883 uint32 immediate_data_size
,
7884 const void* cmd_data
) {
7885 const gles2::cmds::DrawArraysInstancedANGLE
& c
=
7886 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE
*>(cmd_data
);
7887 if (!features().angle_instanced_arrays
) {
7889 GL_INVALID_OPERATION
,
7890 "glDrawArraysInstancedANGLE", "function not available");
7891 return error::kNoError
;
7893 return DoDrawArrays("glDrawArraysIntancedANGLE",
7895 static_cast<GLenum
>(c
.mode
),
7896 static_cast<GLint
>(c
.first
),
7897 static_cast<GLsizei
>(c
.count
),
7898 static_cast<GLsizei
>(c
.primcount
));
7901 error::Error
GLES2DecoderImpl::DoDrawElements(
7902 const char* function_name
,
7908 GLsizei primcount
) {
7909 error::Error error
= WillAccessBoundFramebufferForDraw();
7910 if (error
!= error::kNoError
)
7912 if (!state_
.vertex_attrib_manager
->element_array_buffer()) {
7914 GL_INVALID_OPERATION
, function_name
, "No element array buffer bound");
7915 return error::kNoError
;
7919 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "count < 0");
7920 return error::kNoError
;
7923 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "offset < 0");
7924 return error::kNoError
;
7926 if (!validators_
->draw_mode
.IsValid(mode
)) {
7927 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, mode
, "mode");
7928 return error::kNoError
;
7930 if (!validators_
->index_type
.IsValid(type
)) {
7931 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, type
, "type");
7932 return error::kNoError
;
7934 if (primcount
< 0) {
7935 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "primcount < 0");
7936 return error::kNoError
;
7939 if (!CheckBoundFramebuffersValid(function_name
)) {
7940 return error::kNoError
;
7943 if (count
== 0 || primcount
== 0) {
7944 return error::kNoError
;
7947 GLuint max_vertex_accessed
;
7948 Buffer
* element_array_buffer
=
7949 state_
.vertex_attrib_manager
->element_array_buffer();
7951 if (!element_array_buffer
->GetMaxValueForRange(
7952 offset
, count
, type
, &max_vertex_accessed
)) {
7954 GL_INVALID_OPERATION
, function_name
, "range out of bounds for buffer");
7955 return error::kNoError
;
7958 if (IsDrawValid(function_name
, max_vertex_accessed
, instanced
, primcount
)) {
7959 if (!ClearUnclearedTextures()) {
7960 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "out of memory");
7961 return error::kNoError
;
7963 bool simulated_attrib_0
= false;
7964 if (!SimulateAttrib0(
7965 function_name
, max_vertex_accessed
, &simulated_attrib_0
)) {
7966 return error::kNoError
;
7968 bool simulated_fixed_attribs
= false;
7969 if (SimulateFixedAttribs(
7970 function_name
, max_vertex_accessed
, &simulated_fixed_attribs
,
7972 bool textures_set
= !PrepareTexturesForRender();
7974 // TODO(gman): Refactor to hide these details in BufferManager or
7975 // VertexAttribManager.
7976 const GLvoid
* indices
= reinterpret_cast<const GLvoid
*>(offset
);
7977 bool used_client_side_array
= false;
7978 if (element_array_buffer
->IsClientSideArray()) {
7979 used_client_side_array
= true;
7980 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, 0);
7981 indices
= element_array_buffer
->GetRange(offset
, 0);
7984 ScopedRenderTo
do_render(framebuffer_state_
.bound_draw_framebuffer
.get());
7986 glDrawElements(mode
, count
, type
, indices
);
7988 glDrawElementsInstancedANGLE(mode
, count
, type
, indices
, primcount
);
7991 if (used_client_side_array
) {
7992 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
7993 element_array_buffer
->service_id());
7997 RestoreStateForTextures();
7999 if (simulated_fixed_attribs
) {
8000 RestoreStateForSimulatedFixedAttribs();
8003 if (simulated_attrib_0
) {
8004 // We don't have to restore attrib 0 generic data at the end of this
8005 // function even if it is simulated. This is because we will simulate
8006 // it in each draw call, and attrib 0 generic data queries use cached
8007 // values instead of passing down to the underlying driver.
8008 RestoreStateForAttrib(0, false);
8011 return error::kNoError
;
8014 error::Error
GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size
,
8015 const void* cmd_data
) {
8016 // TODO(zmo): crbug.com/481184
8017 // On Desktop GL with versions lower than 4.3, we need to emulate
8018 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
8019 const gles2::cmds::DrawElements
& c
=
8020 *static_cast<const gles2::cmds::DrawElements
*>(cmd_data
);
8021 return DoDrawElements("glDrawElements",
8023 static_cast<GLenum
>(c
.mode
),
8024 static_cast<GLsizei
>(c
.count
),
8025 static_cast<GLenum
>(c
.type
),
8026 static_cast<int32
>(c
.index_offset
),
8030 error::Error
GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
8031 uint32 immediate_data_size
,
8032 const void* cmd_data
) {
8033 const gles2::cmds::DrawElementsInstancedANGLE
& c
=
8034 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE
*>(cmd_data
);
8035 if (!features().angle_instanced_arrays
) {
8037 GL_INVALID_OPERATION
,
8038 "glDrawElementsInstancedANGLE", "function not available");
8039 return error::kNoError
;
8041 return DoDrawElements("glDrawElementsInstancedANGLE",
8043 static_cast<GLenum
>(c
.mode
),
8044 static_cast<GLsizei
>(c
.count
),
8045 static_cast<GLenum
>(c
.type
),
8046 static_cast<int32
>(c
.index_offset
),
8047 static_cast<GLsizei
>(c
.primcount
));
8050 GLuint
GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
8051 GLuint buffer_id
, GLsizei count
, GLenum type
, GLuint offset
) {
8052 GLuint max_vertex_accessed
= 0;
8053 Buffer
* buffer
= GetBuffer(buffer_id
);
8055 // TODO(gman): Should this be a GL error or a command buffer error?
8057 GL_INVALID_VALUE
, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
8059 if (!buffer
->GetMaxValueForRange(
8060 offset
, count
, type
, &max_vertex_accessed
)) {
8061 // TODO(gman): Should this be a GL error or a command buffer error?
8063 GL_INVALID_OPERATION
,
8064 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
8067 return max_vertex_accessed
;
8070 void GLES2DecoderImpl::DoShaderSource(
8071 GLuint client_id
, GLsizei count
, const char** data
, const GLint
* length
) {
8073 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
8074 if (length
&& length
[ii
] > 0)
8075 str
.append(data
[ii
], length
[ii
]);
8077 str
.append(data
[ii
]);
8079 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glShaderSource");
8083 // Note: We don't actually call glShaderSource here. We wait until
8084 // we actually compile the shader.
8085 shader
->set_source(str
);
8088 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
8089 GLuint client_program_id
, GLsizei count
, const char* const* varyings
,
8090 GLenum buffer_mode
) {
8091 Program
* program
= GetProgramInfoNotShader(
8092 client_program_id
, "glTransformFeedbackVaryings");
8096 program
->TransformFeedbackVaryings(count
, varyings
, buffer_mode
);
8099 void GLES2DecoderImpl::DoCompileShader(GLuint client_id
) {
8100 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
8101 Shader
* shader
= GetShaderInfoNotProgram(client_id
, "glCompileShader");
8106 scoped_refptr
<ShaderTranslatorInterface
> translator
;
8107 if (!feature_info_
->disable_shader_translator()) {
8108 translator
= shader
->shader_type() == GL_VERTEX_SHADER
?
8109 vertex_translator_
: fragment_translator_
;
8112 const Shader::TranslatedShaderSourceType source_type
=
8113 feature_info_
->feature_flags().angle_translated_shader_source
?
8114 Shader::kANGLE
: Shader::kGL
;
8115 shader
->RequestCompile(translator
, source_type
);
8118 void GLES2DecoderImpl::DoGetShaderiv(
8119 GLuint shader_id
, GLenum pname
, GLint
* params
) {
8120 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderiv");
8125 // Compile now for statuses that require it.
8127 case GL_COMPILE_STATUS
:
8128 case GL_INFO_LOG_LENGTH
:
8129 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
8130 shader
->DoCompile();
8138 case GL_SHADER_SOURCE_LENGTH
:
8139 *params
= shader
->source().size();
8143 case GL_COMPILE_STATUS
:
8144 *params
= compile_shader_always_succeeds_
? true : shader
->valid();
8146 case GL_INFO_LOG_LENGTH
:
8147 *params
= shader
->log_info().size();
8151 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
:
8152 *params
= shader
->translated_source().size();
8159 glGetShaderiv(shader
->service_id(), pname
, params
);
8162 error::Error
GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size
,
8163 const void* cmd_data
) {
8164 const gles2::cmds::GetShaderSource
& c
=
8165 *static_cast<const gles2::cmds::GetShaderSource
*>(cmd_data
);
8166 GLuint shader_id
= c
.shader
;
8167 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8168 Bucket
* bucket
= CreateBucket(bucket_id
);
8169 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderSource");
8170 if (!shader
|| shader
->source().empty()) {
8172 return error::kNoError
;
8174 bucket
->SetFromString(shader
->source().c_str());
8175 return error::kNoError
;
8178 error::Error
GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
8179 uint32 immediate_data_size
,
8180 const void* cmd_data
) {
8181 const gles2::cmds::GetTranslatedShaderSourceANGLE
& c
=
8182 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE
*>(
8184 GLuint shader_id
= c
.shader
;
8185 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8186 Bucket
* bucket
= CreateBucket(bucket_id
);
8187 Shader
* shader
= GetShaderInfoNotProgram(
8188 shader_id
, "glGetTranslatedShaderSourceANGLE");
8191 return error::kNoError
;
8194 // Make sure translator has been utilized in compile.
8195 shader
->DoCompile();
8197 bucket
->SetFromString(shader
->translated_source().c_str());
8198 return error::kNoError
;
8201 error::Error
GLES2DecoderImpl::HandleGetProgramInfoLog(
8202 uint32 immediate_data_size
,
8203 const void* cmd_data
) {
8204 const gles2::cmds::GetProgramInfoLog
& c
=
8205 *static_cast<const gles2::cmds::GetProgramInfoLog
*>(cmd_data
);
8206 GLuint program_id
= c
.program
;
8207 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8208 Bucket
* bucket
= CreateBucket(bucket_id
);
8209 Program
* program
= GetProgramInfoNotShader(
8210 program_id
, "glGetProgramInfoLog");
8211 if (!program
|| !program
->log_info()) {
8212 bucket
->SetFromString("");
8213 return error::kNoError
;
8215 bucket
->SetFromString(program
->log_info()->c_str());
8216 return error::kNoError
;
8219 error::Error
GLES2DecoderImpl::HandleGetShaderInfoLog(
8220 uint32 immediate_data_size
,
8221 const void* cmd_data
) {
8222 const gles2::cmds::GetShaderInfoLog
& c
=
8223 *static_cast<const gles2::cmds::GetShaderInfoLog
*>(cmd_data
);
8224 GLuint shader_id
= c
.shader
;
8225 uint32 bucket_id
= static_cast<uint32
>(c
.bucket_id
);
8226 Bucket
* bucket
= CreateBucket(bucket_id
);
8227 Shader
* shader
= GetShaderInfoNotProgram(shader_id
, "glGetShaderInfoLog");
8229 bucket
->SetFromString("");
8230 return error::kNoError
;
8233 // Shader must be compiled in order to get the info log.
8234 shader
->DoCompile();
8236 bucket
->SetFromString(shader
->log_info().c_str());
8237 return error::kNoError
;
8240 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap
) {
8241 return state_
.GetEnabled(cap
);
8244 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id
) {
8245 const Buffer
* buffer
= GetBuffer(client_id
);
8246 return buffer
&& buffer
->IsValid() && !buffer
->IsDeleted();
8249 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id
) {
8250 const Framebuffer
* framebuffer
=
8251 GetFramebuffer(client_id
);
8252 return framebuffer
&& framebuffer
->IsValid() && !framebuffer
->IsDeleted();
8255 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id
) {
8256 // IsProgram is true for programs as soon as they are created, until they are
8257 // deleted and no longer in use.
8258 const Program
* program
= GetProgram(client_id
);
8259 return program
!= NULL
&& !program
->IsDeleted();
8262 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id
) {
8263 const Renderbuffer
* renderbuffer
=
8264 GetRenderbuffer(client_id
);
8265 return renderbuffer
&& renderbuffer
->IsValid() && !renderbuffer
->IsDeleted();
8268 bool GLES2DecoderImpl::DoIsShader(GLuint client_id
) {
8269 // IsShader is true for shaders as soon as they are created, until they
8270 // are deleted and not attached to any programs.
8271 const Shader
* shader
= GetShader(client_id
);
8272 return shader
!= NULL
&& !shader
->IsDeleted();
8275 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id
) {
8276 const TextureRef
* texture_ref
= GetTexture(client_id
);
8277 return texture_ref
&& texture_ref
->texture()->IsValid();
8280 void GLES2DecoderImpl::DoAttachShader(
8281 GLuint program_client_id
, GLint shader_client_id
) {
8282 Program
* program
= GetProgramInfoNotShader(
8283 program_client_id
, "glAttachShader");
8287 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glAttachShader");
8291 if (!program
->AttachShader(shader_manager(), shader
)) {
8293 GL_INVALID_OPERATION
,
8295 "can not attach more than one shader of the same type.");
8298 glAttachShader(program
->service_id(), shader
->service_id());
8301 void GLES2DecoderImpl::DoDetachShader(
8302 GLuint program_client_id
, GLint shader_client_id
) {
8303 Program
* program
= GetProgramInfoNotShader(
8304 program_client_id
, "glDetachShader");
8308 Shader
* shader
= GetShaderInfoNotProgram(shader_client_id
, "glDetachShader");
8312 if (!program
->DetachShader(shader_manager(), shader
)) {
8314 GL_INVALID_OPERATION
,
8315 "glDetachShader", "shader not attached to program");
8318 glDetachShader(program
->service_id(), shader
->service_id());
8321 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id
) {
8322 Program
* program
= GetProgramInfoNotShader(
8323 program_client_id
, "glValidateProgram");
8327 program
->Validate();
8330 void GLES2DecoderImpl::GetVertexAttribHelper(
8331 const VertexAttrib
* attrib
, GLenum pname
, GLint
* params
) {
8333 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
:
8335 Buffer
* buffer
= attrib
->buffer();
8336 if (buffer
&& !buffer
->IsDeleted()) {
8338 buffer_manager()->GetClientId(buffer
->service_id(), &client_id
);
8339 *params
= client_id
;
8343 case GL_VERTEX_ATTRIB_ARRAY_ENABLED
:
8344 *params
= attrib
->enabled();
8346 case GL_VERTEX_ATTRIB_ARRAY_SIZE
:
8347 *params
= attrib
->size();
8349 case GL_VERTEX_ATTRIB_ARRAY_STRIDE
:
8350 *params
= attrib
->gl_stride();
8352 case GL_VERTEX_ATTRIB_ARRAY_TYPE
:
8353 *params
= attrib
->type();
8355 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
:
8356 *params
= attrib
->normalized();
8358 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR
:
8359 *params
= attrib
->divisor();
8361 case GL_VERTEX_ATTRIB_ARRAY_INTEGER
:
8362 *params
= attrib
->integer();
8370 void GLES2DecoderImpl::DoGetTexParameterfv(
8371 GLenum target
, GLenum pname
, GLfloat
* params
) {
8372 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
8373 glGetTexParameterfv(target
, pname
, params
);
8376 void GLES2DecoderImpl::DoGetTexParameteriv(
8377 GLenum target
, GLenum pname
, GLint
* params
) {
8378 InitTextureMaxAnisotropyIfNeeded(target
, pname
);
8379 glGetTexParameteriv(target
, pname
, params
);
8382 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
8383 GLenum target
, GLenum pname
) {
8384 if (!workarounds().init_texture_max_anisotropy
)
8386 if (pname
!= GL_TEXTURE_MAX_ANISOTROPY_EXT
||
8387 !validators_
->texture_parameter
.IsValid(pname
)) {
8391 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
8395 GL_INVALID_OPERATION
,
8396 "glGetTexParamter{fi}v", "unknown texture for target");
8399 Texture
* texture
= texture_ref
->texture();
8400 texture
->InitTextureMaxAnisotropyIfNeeded(target
);
8403 template <typename T
>
8404 void GLES2DecoderImpl::DoGetVertexAttribImpl(
8405 GLuint index
, GLenum pname
, T
* params
) {
8406 VertexAttrib
* attrib
= state_
.vertex_attrib_manager
->GetVertexAttrib(index
);
8409 GL_INVALID_VALUE
, "glGetVertexAttrib", "index out of range");
8413 case GL_CURRENT_VERTEX_ATTRIB
:
8414 state_
.attrib_values
[index
].GetValues(params
);
8418 GetVertexAttribHelper(attrib
, pname
, &value
);
8419 *params
= static_cast<T
>(value
);
8425 void GLES2DecoderImpl::DoGetVertexAttribfv(
8426 GLuint index
, GLenum pname
, GLfloat
* params
) {
8427 DoGetVertexAttribImpl
<GLfloat
>(index
, pname
, params
);
8430 void GLES2DecoderImpl::DoGetVertexAttribiv(
8431 GLuint index
, GLenum pname
, GLint
* params
) {
8432 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
8435 void GLES2DecoderImpl::DoGetVertexAttribIiv(
8436 GLuint index
, GLenum pname
, GLint
* params
) {
8437 DoGetVertexAttribImpl
<GLint
>(index
, pname
, params
);
8440 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
8441 GLuint index
, GLenum pname
, GLuint
* params
) {
8442 DoGetVertexAttribImpl
<GLuint
>(index
, pname
, params
);
8445 template <typename T
>
8446 bool GLES2DecoderImpl::SetVertexAttribValue(
8447 const char* function_name
, GLuint index
, const T
* value
) {
8448 if (index
>= state_
.attrib_values
.size()) {
8449 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "index out of range");
8452 state_
.attrib_values
[index
].SetValues(value
);
8456 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index
, GLfloat v0
) {
8457 GLfloat v
[4] = { v0
, 0.0f
, 0.0f
, 1.0f
, };
8458 if (SetVertexAttribValue("glVertexAttrib1f", index
, v
)) {
8459 glVertexAttrib1f(index
, v0
);
8463 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index
, GLfloat v0
, GLfloat v1
) {
8464 GLfloat v
[4] = { v0
, v1
, 0.0f
, 1.0f
, };
8465 if (SetVertexAttribValue("glVertexAttrib2f", index
, v
)) {
8466 glVertexAttrib2f(index
, v0
, v1
);
8470 void GLES2DecoderImpl::DoVertexAttrib3f(
8471 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
) {
8472 GLfloat v
[4] = { v0
, v1
, v2
, 1.0f
, };
8473 if (SetVertexAttribValue("glVertexAttrib3f", index
, v
)) {
8474 glVertexAttrib3f(index
, v0
, v1
, v2
);
8478 void GLES2DecoderImpl::DoVertexAttrib4f(
8479 GLuint index
, GLfloat v0
, GLfloat v1
, GLfloat v2
, GLfloat v3
) {
8480 GLfloat v
[4] = { v0
, v1
, v2
, v3
, };
8481 if (SetVertexAttribValue("glVertexAttrib4f", index
, v
)) {
8482 glVertexAttrib4f(index
, v0
, v1
, v2
, v3
);
8486 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index
, const GLfloat
* v
) {
8487 GLfloat t
[4] = { v
[0], 0.0f
, 0.0f
, 1.0f
, };
8488 if (SetVertexAttribValue("glVertexAttrib1fv", index
, t
)) {
8489 glVertexAttrib1fv(index
, v
);
8493 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index
, const GLfloat
* v
) {
8494 GLfloat t
[4] = { v
[0], v
[1], 0.0f
, 1.0f
, };
8495 if (SetVertexAttribValue("glVertexAttrib2fv", index
, t
)) {
8496 glVertexAttrib2fv(index
, v
);
8500 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index
, const GLfloat
* v
) {
8501 GLfloat t
[4] = { v
[0], v
[1], v
[2], 1.0f
, };
8502 if (SetVertexAttribValue("glVertexAttrib3fv", index
, t
)) {
8503 glVertexAttrib3fv(index
, v
);
8507 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index
, const GLfloat
* v
) {
8508 if (SetVertexAttribValue("glVertexAttrib4fv", index
, v
)) {
8509 glVertexAttrib4fv(index
, v
);
8513 void GLES2DecoderImpl::DoVertexAttribI4i(
8514 GLuint index
, GLint v0
, GLint v1
, GLint v2
, GLint v3
) {
8515 GLint v
[4] = { v0
, v1
, v2
, v3
};
8516 if (SetVertexAttribValue("glVertexAttribI4i", index
, v
)) {
8517 glVertexAttribI4i(index
, v0
, v1
, v2
, v3
);
8521 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index
, const GLint
* v
) {
8522 if (SetVertexAttribValue("glVertexAttribI4iv", index
, v
)) {
8523 glVertexAttribI4iv(index
, v
);
8527 void GLES2DecoderImpl::DoVertexAttribI4ui(
8528 GLuint index
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
) {
8529 GLuint v
[4] = { v0
, v1
, v2
, v3
};
8530 if (SetVertexAttribValue("glVertexAttribI4ui", index
, v
)) {
8531 glVertexAttribI4ui(index
, v0
, v1
, v2
, v3
);
8535 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index
, const GLuint
* v
) {
8536 if (SetVertexAttribValue("glVertexAttribI4uiv", index
, v
)) {
8537 glVertexAttribI4uiv(index
, v
);
8541 error::Error
GLES2DecoderImpl::HandleVertexAttribIPointer(
8542 uint32 immediate_data_size
,
8543 const void* cmd_data
) {
8544 if (!unsafe_es3_apis_enabled())
8545 return error::kUnknownCommand
;
8546 const gles2::cmds::VertexAttribIPointer
& c
=
8547 *static_cast<const gles2::cmds::VertexAttribIPointer
*>(cmd_data
);
8549 if (!state_
.bound_array_buffer
.get() ||
8550 state_
.bound_array_buffer
->IsDeleted()) {
8551 if (state_
.vertex_attrib_manager
.get() ==
8552 state_
.default_vertex_attrib_manager
.get()) {
8554 GL_INVALID_VALUE
, "glVertexAttribIPointer", "no array buffer bound");
8555 return error::kNoError
;
8556 } else if (c
.offset
!= 0) {
8559 "glVertexAttribIPointer", "client side arrays are not allowed");
8560 return error::kNoError
;
8564 GLuint indx
= c
.indx
;
8565 GLint size
= c
.size
;
8566 GLenum type
= c
.type
;
8567 GLsizei stride
= c
.stride
;
8568 GLsizei offset
= c
.offset
;
8569 const void* ptr
= reinterpret_cast<const void*>(offset
);
8570 if (!validators_
->vertex_attrib_i_type
.IsValid(type
)) {
8571 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type
, "type");
8572 return error::kNoError
;
8574 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8576 GL_INVALID_VALUE
, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8577 return error::kNoError
;
8579 if (indx
>= group_
->max_vertex_attribs()) {
8581 GL_INVALID_VALUE
, "glVertexAttribIPointer", "index out of range");
8582 return error::kNoError
;
8586 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride < 0");
8587 return error::kNoError
;
8591 GL_INVALID_VALUE
, "glVertexAttribIPointer", "stride > 255");
8592 return error::kNoError
;
8596 GL_INVALID_VALUE
, "glVertexAttribIPointer", "offset < 0");
8597 return error::kNoError
;
8599 GLsizei component_size
=
8600 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8601 // component_size must be a power of two to use & as optimized modulo.
8602 DCHECK(GLES2Util::IsPOT(component_size
));
8603 if (offset
& (component_size
- 1)) {
8605 GL_INVALID_OPERATION
,
8606 "glVertexAttribIPointer", "offset not valid for type");
8607 return error::kNoError
;
8609 if (stride
& (component_size
- 1)) {
8611 GL_INVALID_OPERATION
,
8612 "glVertexAttribIPointer", "stride not valid for type");
8613 return error::kNoError
;
8615 state_
.vertex_attrib_manager
8616 ->SetAttribInfo(indx
,
8617 state_
.bound_array_buffer
.get(),
8622 stride
!= 0 ? stride
: component_size
* size
,
8625 glVertexAttribIPointer(indx
, size
, type
, stride
, ptr
);
8626 return error::kNoError
;
8629 error::Error
GLES2DecoderImpl::HandleVertexAttribPointer(
8630 uint32 immediate_data_size
,
8631 const void* cmd_data
) {
8632 const gles2::cmds::VertexAttribPointer
& c
=
8633 *static_cast<const gles2::cmds::VertexAttribPointer
*>(cmd_data
);
8635 if (!state_
.bound_array_buffer
.get() ||
8636 state_
.bound_array_buffer
->IsDeleted()) {
8637 if (state_
.vertex_attrib_manager
.get() ==
8638 state_
.default_vertex_attrib_manager
.get()) {
8640 GL_INVALID_VALUE
, "glVertexAttribPointer", "no array buffer bound");
8641 return error::kNoError
;
8642 } else if (c
.offset
!= 0) {
8645 "glVertexAttribPointer", "client side arrays are not allowed");
8646 return error::kNoError
;
8650 GLuint indx
= c
.indx
;
8651 GLint size
= c
.size
;
8652 GLenum type
= c
.type
;
8653 GLboolean normalized
= static_cast<GLboolean
>(c
.normalized
);
8654 GLsizei stride
= c
.stride
;
8655 GLsizei offset
= c
.offset
;
8656 const void* ptr
= reinterpret_cast<const void*>(offset
);
8657 if (!validators_
->vertex_attrib_type
.IsValid(type
)) {
8658 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type
, "type");
8659 return error::kNoError
;
8661 if (!validators_
->vertex_attrib_size
.IsValid(size
)) {
8663 GL_INVALID_VALUE
, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8664 return error::kNoError
;
8666 if (indx
>= group_
->max_vertex_attribs()) {
8668 GL_INVALID_VALUE
, "glVertexAttribPointer", "index out of range");
8669 return error::kNoError
;
8673 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride < 0");
8674 return error::kNoError
;
8678 GL_INVALID_VALUE
, "glVertexAttribPointer", "stride > 255");
8679 return error::kNoError
;
8683 GL_INVALID_VALUE
, "glVertexAttribPointer", "offset < 0");
8684 return error::kNoError
;
8686 GLsizei component_size
=
8687 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type
);
8688 // component_size must be a power of two to use & as optimized modulo.
8689 DCHECK(GLES2Util::IsPOT(component_size
));
8690 if (offset
& (component_size
- 1)) {
8692 GL_INVALID_OPERATION
,
8693 "glVertexAttribPointer", "offset not valid for type");
8694 return error::kNoError
;
8696 if (stride
& (component_size
- 1)) {
8698 GL_INVALID_OPERATION
,
8699 "glVertexAttribPointer", "stride not valid for type");
8700 return error::kNoError
;
8702 state_
.vertex_attrib_manager
8703 ->SetAttribInfo(indx
,
8704 state_
.bound_array_buffer
.get(),
8709 stride
!= 0 ? stride
: component_size
* size
,
8712 // We support GL_FIXED natively on EGL/GLES2 implementations
8713 if (type
!= GL_FIXED
|| feature_info_
->gl_version_info().is_es
) {
8714 glVertexAttribPointer(indx
, size
, type
, normalized
, stride
, ptr
);
8716 return error::kNoError
;
8719 void GLES2DecoderImpl::DoViewport(GLint x
, GLint y
, GLsizei width
,
8721 state_
.viewport_x
= x
;
8722 state_
.viewport_y
= y
;
8723 state_
.viewport_width
= std::min(width
, viewport_max_width_
);
8724 state_
.viewport_height
= std::min(height
, viewport_max_height_
);
8725 glViewport(x
, y
, width
, height
);
8728 error::Error
GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8729 uint32 immediate_data_size
,
8730 const void* cmd_data
) {
8731 const gles2::cmds::VertexAttribDivisorANGLE
& c
=
8732 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE
*>(cmd_data
);
8733 if (!features().angle_instanced_arrays
) {
8735 GL_INVALID_OPERATION
,
8736 "glVertexAttribDivisorANGLE", "function not available");
8737 return error::kNoError
;
8739 GLuint index
= c
.index
;
8740 GLuint divisor
= c
.divisor
;
8741 if (index
>= group_
->max_vertex_attribs()) {
8744 "glVertexAttribDivisorANGLE", "index out of range");
8745 return error::kNoError
;
8748 state_
.vertex_attrib_manager
->SetDivisor(
8751 glVertexAttribDivisorANGLE(index
, divisor
);
8752 return error::kNoError
;
8755 template <typename pixel_data_type
>
8756 static void WriteAlphaData(
8757 void* pixels
, uint32 row_count
, uint32 channel_count
,
8758 uint32 alpha_channel_index
, uint32 unpadded_row_size
,
8759 uint32 padded_row_size
, pixel_data_type alpha_value
) {
8760 DCHECK_GT(channel_count
, 0U);
8761 DCHECK_EQ(unpadded_row_size
% sizeof(pixel_data_type
), 0U);
8762 uint32 unpadded_row_size_in_elements
=
8763 unpadded_row_size
/ sizeof(pixel_data_type
);
8764 DCHECK_EQ(padded_row_size
% sizeof(pixel_data_type
), 0U);
8765 uint32 padded_row_size_in_elements
=
8766 padded_row_size
/ sizeof(pixel_data_type
);
8767 pixel_data_type
* dst
=
8768 static_cast<pixel_data_type
*>(pixels
) + alpha_channel_index
;
8769 for (uint32 yy
= 0; yy
< row_count
; ++yy
) {
8770 pixel_data_type
* end
= dst
+ unpadded_row_size_in_elements
;
8771 for (pixel_data_type
* d
= dst
; d
< end
; d
+= channel_count
) {
8774 dst
+= padded_row_size_in_elements
;
8778 void GLES2DecoderImpl::FinishReadPixels(
8779 const cmds::ReadPixels
& c
,
8781 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8782 GLsizei width
= c
.width
;
8783 GLsizei height
= c
.height
;
8784 GLenum format
= c
.format
;
8785 GLenum type
= c
.type
;
8786 typedef cmds::ReadPixels::Result Result
;
8788 Result
* result
= NULL
;
8789 if (c
.result_shm_id
!= 0) {
8790 result
= GetSharedMemoryAs
<Result
*>(
8791 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8794 glDeleteBuffersARB(1, &buffer
);
8799 GLES2Util::ComputeImageDataSizes(
8800 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8802 void* pixels
= GetSharedMemoryAs
<void*>(
8803 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8806 glDeleteBuffersARB(1, &buffer
);
8812 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
8814 if (features().map_buffer_range
) {
8815 data
= glMapBufferRange(
8816 GL_PIXEL_PACK_BUFFER_ARB
, 0, pixels_size
, GL_MAP_READ_BIT
);
8818 data
= glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB
, GL_READ_ONLY
);
8821 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glMapBuffer",
8822 "Unable to map memory for readback.");
8825 memcpy(pixels
, data
, pixels_size
);
8826 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8827 // have to restore the state.
8828 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB
);
8829 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
8830 glDeleteBuffersARB(1, &buffer
);
8833 if (result
!= NULL
) {
8837 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
8838 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
8839 if ((channels_exist
& 0x0008) == 0 &&
8840 workarounds().clear_alpha_in_readpixels
) {
8841 // Set the alpha to 255 because some drivers are buggy in this regard.
8844 uint32 unpadded_row_size
;
8845 uint32 padded_row_size
;
8846 if (!GLES2Util::ComputeImageDataSizes(
8847 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
8848 &unpadded_row_size
, &padded_row_size
)) {
8852 uint32 channel_count
= 0;
8853 uint32 alpha_channel
= 0;
8866 if (channel_count
> 0) {
8868 case GL_UNSIGNED_BYTE
:
8869 WriteAlphaData
<uint8
>(
8870 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8871 padded_row_size
, 0xFF);
8874 WriteAlphaData
<float>(
8875 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8876 padded_row_size
, 1.0f
);
8879 WriteAlphaData
<uint16
>(
8880 pixels
, height
, channel_count
, alpha_channel
, unpadded_row_size
,
8881 padded_row_size
, 0x3C00);
8888 error::Error
GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size
,
8889 const void* cmd_data
) {
8890 const gles2::cmds::ReadPixels
& c
=
8891 *static_cast<const gles2::cmds::ReadPixels
*>(cmd_data
);
8892 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8893 error::Error fbo_error
= WillAccessBoundFramebufferForRead();
8894 if (fbo_error
!= error::kNoError
)
8898 GLsizei width
= c
.width
;
8899 GLsizei height
= c
.height
;
8900 GLenum format
= c
.format
;
8901 GLenum type
= c
.type
;
8902 GLboolean async
= static_cast<GLboolean
>(c
.async
);
8903 if (width
< 0 || height
< 0) {
8904 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels", "dimensions < 0");
8905 return error::kNoError
;
8907 typedef cmds::ReadPixels::Result Result
;
8909 if (!GLES2Util::ComputeImageDataSizes(
8910 width
, height
, 1, format
, type
, state_
.pack_alignment
, &pixels_size
,
8912 return error::kOutOfBounds
;
8914 void* pixels
= GetSharedMemoryAs
<void*>(
8915 c
.pixels_shm_id
, c
.pixels_shm_offset
, pixels_size
);
8917 return error::kOutOfBounds
;
8919 Result
* result
= NULL
;
8920 if (c
.result_shm_id
!= 0) {
8921 result
= GetSharedMemoryAs
<Result
*>(
8922 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
8924 return error::kOutOfBounds
;
8928 if (!validators_
->read_pixel_format
.IsValid(format
)) {
8929 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format
, "format");
8930 return error::kNoError
;
8932 if (!validators_
->read_pixel_type
.IsValid(type
)) {
8933 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type
, "type");
8934 return error::kNoError
;
8937 GLenum src_internal_format
= GetBoundReadFrameBufferInternalFormat();
8938 if (src_internal_format
== 0) {
8939 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glReadPixels",
8940 "no valid read buffer source");
8941 return error::kNoError
;
8943 std::vector
<GLenum
> accepted_formats
;
8944 std::vector
<GLenum
> accepted_types
;
8945 switch (src_internal_format
) {
8952 // All the RGB_INTEGER formats are not renderable.
8957 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8958 accepted_types
.push_back(GL_UNSIGNED_INT
);
8969 accepted_formats
.push_back(GL_RGBA_INTEGER
);
8970 accepted_types
.push_back(GL_INT
);
8973 accepted_formats
.push_back(GL_RGBA
);
8974 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8975 // Special case with an extra supported format/type.
8976 accepted_formats
.push_back(GL_RGBA
);
8977 accepted_types
.push_back(GL_UNSIGNED_INT_2_10_10_10_REV
);
8980 accepted_formats
.push_back(GL_RGBA
);
8982 GLenum src_type
= GetBoundReadFrameBufferTextureType();
8985 case GL_HALF_FLOAT_OES
:
8987 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
8988 if (!feature_info_
->IsES3Enabled()) {
8989 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
8991 accepted_types
.push_back(GL_FLOAT
);
8995 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
9001 if (!IsWebGLContext()) {
9002 accepted_formats
.push_back(GL_BGRA_EXT
);
9003 accepted_types
.push_back(GL_UNSIGNED_BYTE
);
9005 DCHECK_EQ(accepted_formats
.size(), accepted_types
.size());
9006 bool format_type_acceptable
= false;
9007 for (size_t ii
= 0; ii
< accepted_formats
.size(); ++ii
) {
9008 if (format
== accepted_formats
[ii
] && type
== accepted_types
[ii
]) {
9009 format_type_acceptable
= true;
9013 if (!format_type_acceptable
) {
9014 // format and type are acceptable enums but not guaranteed to be supported
9015 // for this framebuffer. Have to ask gl if they are valid.
9016 GLint preferred_format
= 0;
9017 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &preferred_format
);
9018 GLint preferred_type
= 0;
9019 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &preferred_type
);
9020 if (format
== static_cast<GLenum
>(preferred_format
) &&
9021 type
== static_cast<GLenum
>(preferred_type
)) {
9022 format_type_acceptable
= true;
9025 if (!format_type_acceptable
) {
9026 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glReadPixels",
9027 "format and type incompatible with the current read framebuffer");
9028 return error::kNoError
;
9030 if (width
== 0 || height
== 0) {
9031 return error::kNoError
;
9034 // Get the size of the current fbo or backbuffer.
9035 gfx::Size max_size
= GetBoundReadFrameBufferSize();
9039 if (!SafeAddInt32(x
, width
, &max_x
) || !SafeAddInt32(y
, height
, &max_y
)) {
9041 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9042 return error::kNoError
;
9045 if (!CheckBoundFramebuffersValid("glReadPixels")) {
9046 return error::kNoError
;
9049 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
9051 ScopedResolvedFrameBufferBinder
binder(this, false, true);
9053 if (x
< 0 || y
< 0 || max_x
> max_size
.width() || max_y
> max_size
.height()) {
9054 // The user requested an out of range area. Get the results 1 line
9057 uint32 unpadded_row_size
;
9058 uint32 padded_row_size
;
9059 if (!GLES2Util::ComputeImageDataSizes(
9060 width
, 2, 1, format
, type
, state_
.pack_alignment
, &temp_size
,
9061 &unpadded_row_size
, &padded_row_size
)) {
9063 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9064 return error::kNoError
;
9067 GLint dest_x_offset
= std::max(-x
, 0);
9068 uint32 dest_row_offset
;
9069 if (!GLES2Util::ComputeImageDataSizes(
9070 dest_x_offset
, 1, 1, format
, type
, state_
.pack_alignment
,
9071 &dest_row_offset
, NULL
, NULL
)) {
9073 GL_INVALID_VALUE
, "glReadPixels", "dimensions out of range");
9074 return error::kNoError
;
9077 // Copy each row into the larger dest rect.
9078 int8
* dst
= static_cast<int8
*>(pixels
);
9079 GLint read_x
= std::max(0, x
);
9080 GLint read_end_x
= std::max(0, std::min(max_size
.width(), max_x
));
9081 GLint read_width
= read_end_x
- read_x
;
9082 for (GLint yy
= 0; yy
< height
; ++yy
) {
9086 memset(dst
, 0, unpadded_row_size
);
9088 // If the row is in range, copy it.
9089 if (ry
>= 0 && ry
< max_size
.height() && read_width
> 0) {
9091 read_x
, ry
, read_width
, 1, format
, type
, dst
+ dest_row_offset
);
9093 dst
+= padded_row_size
;
9096 if (async
&& features().use_async_readpixels
) {
9098 glGenBuffersARB(1, &buffer
);
9099 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, buffer
);
9100 // For ANGLE client version 2, GL_STREAM_READ is not available.
9101 const GLenum usage_hint
= feature_info_
->gl_version_info().is_angle
?
9102 GL_STATIC_DRAW
: GL_STREAM_READ
;
9103 glBufferData(GL_PIXEL_PACK_BUFFER_ARB
, pixels_size
, NULL
, usage_hint
);
9104 GLenum error
= glGetError();
9105 if (error
== GL_NO_ERROR
) {
9106 glReadPixels(x
, y
, width
, height
, format
, type
, 0);
9107 pending_readpixel_fences_
.push(linked_ptr
<FenceCallback
>(
9108 new FenceCallback()));
9109 WaitForReadPixels(base::Bind(
9110 &GLES2DecoderImpl::FinishReadPixels
,
9111 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
9112 <GLES2DecoderImpl
>(this),
9114 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
9115 return error::kNoError
;
9117 // On error, unbind pack buffer and fall through to sync readpixels
9118 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB
, 0);
9119 glDeleteBuffersARB(1, &buffer
);
9122 glReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
9124 GLenum error
= LOCAL_PEEK_GL_ERROR("glReadPixels");
9125 if (error
== GL_NO_ERROR
) {
9126 if (result
!= NULL
) {
9129 FinishReadPixels(c
, 0);
9132 return error::kNoError
;
9135 error::Error
GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size
,
9136 const void* cmd_data
) {
9137 const gles2::cmds::PixelStorei
& c
=
9138 *static_cast<const gles2::cmds::PixelStorei
*>(cmd_data
);
9139 GLenum pname
= c
.pname
;
9140 GLenum param
= c
.param
;
9141 if (!validators_
->pixel_store
.IsValid(pname
)) {
9142 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname
, "pname");
9143 return error::kNoError
;
9146 case GL_PACK_ALIGNMENT
:
9147 case GL_UNPACK_ALIGNMENT
:
9148 if (!validators_
->pixel_store_alignment
.IsValid(param
)) {
9150 GL_INVALID_VALUE
, "glPixelStorei", "param GL_INVALID_VALUE");
9151 return error::kNoError
;
9157 glPixelStorei(pname
, param
);
9159 case GL_PACK_ALIGNMENT
:
9160 state_
.pack_alignment
= param
;
9162 case GL_PACK_REVERSE_ROW_ORDER_ANGLE
:
9163 state_
.pack_reverse_row_order
= (param
!= 0);
9165 case GL_UNPACK_ALIGNMENT
:
9166 state_
.unpack_alignment
= param
;
9169 // Validation should have prevented us from getting here.
9173 return error::kNoError
;
9176 error::Error
GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
9177 uint32 immediate_data_size
,
9178 const void* cmd_data
) {
9179 const gles2::cmds::PostSubBufferCHROMIUM
& c
=
9180 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM
*>(cmd_data
);
9181 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
9183 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9185 if (!supports_post_sub_buffer_
) {
9187 GL_INVALID_OPERATION
,
9188 "glPostSubBufferCHROMIUM", "command not supported by surface");
9189 return error::kNoError
;
9192 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9195 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
9196 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
9197 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
9198 is_offscreen
? offscreen_size_
: surface_
->GetSize());
9200 if (surface_
->PostSubBuffer(c
.x
, c
.y
, c
.width
, c
.height
) !=
9201 gfx::SwapResult::SWAP_FAILED
) {
9202 return error::kNoError
;
9204 LOG(ERROR
) << "Context lost because PostSubBuffer failed.";
9205 return error::kLostContext
;
9209 error::Error
GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
9210 uint32 immediate_data_size
,
9211 const void* cmd_data
) {
9212 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
& c
=
9213 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM
*>(cmd_data
);
9214 TextureRef
* ref
= texture_manager()->GetTexture(c
.overlay_texture_id
);
9216 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9217 "glScheduleOverlayPlaneCHROMIUM",
9219 return error::kNoError
;
9221 gfx::GLImage
* image
=
9222 ref
->texture()->GetLevelImage(ref
->texture()->target(), 0);
9224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
9225 "glScheduleOverlayPlaneCHROMIUM",
9226 "unsupported texture format");
9227 return error::kNoError
;
9229 gfx::OverlayTransform transform
= GetGFXOverlayTransform(c
.plane_transform
);
9230 if (transform
== gfx::OVERLAY_TRANSFORM_INVALID
) {
9231 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
,
9232 "glScheduleOverlayPlaneCHROMIUM",
9233 "invalid transform enum");
9234 return error::kNoError
;
9236 if (!surface_
->ScheduleOverlayPlane(
9240 gfx::Rect(c
.bounds_x
, c
.bounds_y
, c
.bounds_width
, c
.bounds_height
),
9241 gfx::RectF(c
.uv_x
, c
.uv_y
, c
.uv_width
, c
.uv_height
))) {
9242 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9243 "glScheduleOverlayPlaneCHROMIUM",
9244 "failed to schedule overlay");
9246 return error::kNoError
;
9249 error::Error
GLES2DecoderImpl::GetAttribLocationHelper(
9250 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9251 const std::string
& name_str
) {
9252 if (!StringIsValidForGLES(name_str
.c_str())) {
9254 GL_INVALID_VALUE
, "glGetAttribLocation", "Invalid character");
9255 return error::kNoError
;
9257 Program
* program
= GetProgramInfoNotShader(
9258 client_id
, "glGetAttribLocation");
9260 return error::kNoError
;
9262 if (!program
->IsValid()) {
9264 GL_INVALID_OPERATION
, "glGetAttribLocation", "program not linked");
9265 return error::kNoError
;
9267 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9268 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9270 return error::kOutOfBounds
;
9272 // Require the client to init this incase the context is lost and we are no
9273 // longer executing commands.
9274 if (*location
!= -1) {
9275 return error::kGenericError
;
9277 *location
= program
->GetAttribLocation(name_str
);
9278 return error::kNoError
;
9281 error::Error
GLES2DecoderImpl::HandleGetAttribLocation(
9282 uint32 immediate_data_size
,
9283 const void* cmd_data
) {
9284 const gles2::cmds::GetAttribLocation
& c
=
9285 *static_cast<const gles2::cmds::GetAttribLocation
*>(cmd_data
);
9286 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9288 return error::kInvalidArguments
;
9290 std::string name_str
;
9291 if (!bucket
->GetAsString(&name_str
)) {
9292 return error::kInvalidArguments
;
9294 return GetAttribLocationHelper(
9295 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9298 error::Error
GLES2DecoderImpl::GetUniformLocationHelper(
9299 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9300 const std::string
& name_str
) {
9301 if (!StringIsValidForGLES(name_str
.c_str())) {
9303 GL_INVALID_VALUE
, "glGetUniformLocation", "Invalid character");
9304 return error::kNoError
;
9306 Program
* program
= GetProgramInfoNotShader(
9307 client_id
, "glGetUniformLocation");
9309 return error::kNoError
;
9311 if (!program
->IsValid()) {
9313 GL_INVALID_OPERATION
, "glGetUniformLocation", "program not linked");
9314 return error::kNoError
;
9316 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9317 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9319 return error::kOutOfBounds
;
9321 // Require the client to init this incase the context is lost an we are no
9322 // longer executing commands.
9323 if (*location
!= -1) {
9324 return error::kGenericError
;
9326 *location
= program
->GetUniformFakeLocation(name_str
);
9327 return error::kNoError
;
9330 error::Error
GLES2DecoderImpl::HandleGetUniformLocation(
9331 uint32 immediate_data_size
,
9332 const void* cmd_data
) {
9333 const gles2::cmds::GetUniformLocation
& c
=
9334 *static_cast<const gles2::cmds::GetUniformLocation
*>(cmd_data
);
9335 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9337 return error::kInvalidArguments
;
9339 std::string name_str
;
9340 if (!bucket
->GetAsString(&name_str
)) {
9341 return error::kInvalidArguments
;
9343 return GetUniformLocationHelper(
9344 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9347 error::Error
GLES2DecoderImpl::HandleGetUniformIndices(
9348 uint32 immediate_data_size
,
9349 const void* cmd_data
) {
9350 if (!unsafe_es3_apis_enabled())
9351 return error::kUnknownCommand
;
9352 const gles2::cmds::GetUniformIndices
& c
=
9353 *static_cast<const gles2::cmds::GetUniformIndices
*>(cmd_data
);
9354 Bucket
* bucket
= GetBucket(c
.names_bucket_id
);
9356 return error::kInvalidArguments
;
9359 std::vector
<char*> names
;
9360 std::vector
<GLint
> len
;
9361 if (!bucket
->GetAsStrings(&count
, &names
, &len
) || count
<= 0) {
9362 return error::kInvalidArguments
;
9364 typedef cmds::GetUniformIndices::Result Result
;
9365 Result
* result
= GetSharedMemoryAs
<Result
*>(
9366 c
.indices_shm_id
, c
.indices_shm_offset
,
9367 Result::ComputeSize(static_cast<size_t>(count
)));
9368 GLuint
* indices
= result
? result
->GetData() : NULL
;
9369 if (indices
== NULL
) {
9370 return error::kOutOfBounds
;
9372 // Check that the client initialized the result.
9373 if (result
->size
!= 0) {
9374 return error::kInvalidArguments
;
9376 Program
* program
= GetProgramInfoNotShader(c
.program
, "glGetUniformIndices");
9378 return error::kNoError
;
9380 GLuint service_id
= program
->service_id();
9381 GLint link_status
= GL_FALSE
;
9382 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
9383 if (link_status
!= GL_TRUE
) {
9384 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
9385 "glGetUniformIndices", "program not linked");
9386 return error::kNoError
;
9388 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
9389 glGetUniformIndices(service_id
, count
, &names
[0], indices
);
9390 GLenum error
= glGetError();
9391 if (error
== GL_NO_ERROR
) {
9392 result
->SetNumResults(count
);
9394 LOCAL_SET_GL_ERROR(error
, "GetUniformIndices", "");
9396 return error::kNoError
;
9399 error::Error
GLES2DecoderImpl::GetFragDataLocationHelper(
9400 GLuint client_id
, uint32 location_shm_id
, uint32 location_shm_offset
,
9401 const std::string
& name_str
) {
9402 GLint
* location
= GetSharedMemoryAs
<GLint
*>(
9403 location_shm_id
, location_shm_offset
, sizeof(GLint
));
9405 return error::kOutOfBounds
;
9407 // Require the client to init this incase the context is lost and we are no
9408 // longer executing commands.
9409 if (*location
!= -1) {
9410 return error::kGenericError
;
9412 Program
* program
= GetProgramInfoNotShader(
9413 client_id
, "glGetFragDataLocation");
9415 return error::kNoError
;
9417 *location
= glGetFragDataLocation(program
->service_id(), name_str
.c_str());
9418 return error::kNoError
;
9421 error::Error
GLES2DecoderImpl::HandleGetFragDataLocation(
9422 uint32 immediate_data_size
,
9423 const void* cmd_data
) {
9424 if (!unsafe_es3_apis_enabled())
9425 return error::kUnknownCommand
;
9426 const gles2::cmds::GetFragDataLocation
& c
=
9427 *static_cast<const gles2::cmds::GetFragDataLocation
*>(cmd_data
);
9428 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9430 return error::kInvalidArguments
;
9432 std::string name_str
;
9433 if (!bucket
->GetAsString(&name_str
)) {
9434 return error::kInvalidArguments
;
9436 return GetFragDataLocationHelper(
9437 c
.program
, c
.location_shm_id
, c
.location_shm_offset
, name_str
);
9440 error::Error
GLES2DecoderImpl::HandleGetUniformBlockIndex(
9441 uint32 immediate_data_size
, const void* cmd_data
) {
9442 if (!unsafe_es3_apis_enabled())
9443 return error::kUnknownCommand
;
9444 const gles2::cmds::GetUniformBlockIndex
& c
=
9445 *static_cast<const gles2::cmds::GetUniformBlockIndex
*>(cmd_data
);
9446 Bucket
* bucket
= GetBucket(c
.name_bucket_id
);
9448 return error::kInvalidArguments
;
9450 std::string name_str
;
9451 if (!bucket
->GetAsString(&name_str
)) {
9452 return error::kInvalidArguments
;
9454 GLuint
* index
= GetSharedMemoryAs
<GLuint
*>(
9455 c
.index_shm_id
, c
.index_shm_offset
, sizeof(GLuint
));
9457 return error::kOutOfBounds
;
9459 // Require the client to init this in case the context is lost and we are no
9460 // longer executing commands.
9461 if (*index
!= GL_INVALID_INDEX
) {
9462 return error::kGenericError
;
9464 Program
* program
= GetProgramInfoNotShader(
9465 c
.program
, "glGetUniformBlockIndex");
9467 return error::kNoError
;
9469 *index
= glGetUniformBlockIndex(program
->service_id(), name_str
.c_str());
9470 return error::kNoError
;
9473 error::Error
GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size
,
9474 const void* cmd_data
) {
9475 const gles2::cmds::GetString
& c
=
9476 *static_cast<const gles2::cmds::GetString
*>(cmd_data
);
9477 GLenum name
= static_cast<GLenum
>(c
.name
);
9478 if (!validators_
->string_type
.IsValid(name
)) {
9479 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name
, "name");
9480 return error::kNoError
;
9483 const char* str
= nullptr;
9484 std::string extensions
;
9487 if (unsafe_es3_apis_enabled())
9488 str
= "OpenGL ES 3.0 Chromium";
9490 str
= "OpenGL ES 2.0 Chromium";
9492 case GL_SHADING_LANGUAGE_VERSION
:
9493 if (unsafe_es3_apis_enabled())
9494 str
= "OpenGL ES GLSL ES 3.0 Chromium";
9496 str
= "OpenGL ES GLSL ES 1.0 Chromium";
9500 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9501 // They are used by WEBGL_debug_renderer_info.
9502 if (!IsWebGLContext())
9505 str
= reinterpret_cast<const char*>(glGetString(name
));
9509 // For WebGL contexts, strip out the OES derivatives and
9510 // EXT frag depth extensions if they have not been enabled.
9511 if (IsWebGLContext()) {
9512 extensions
= feature_info_
->extensions();
9513 if (!derivatives_explicitly_enabled_
) {
9514 size_t offset
= extensions
.find(kOESDerivativeExtension
);
9515 if (std::string::npos
!= offset
) {
9516 extensions
.replace(offset
, arraysize(kOESDerivativeExtension
),
9520 if (!frag_depth_explicitly_enabled_
) {
9521 size_t offset
= extensions
.find(kEXTFragDepthExtension
);
9522 if (std::string::npos
!= offset
) {
9523 extensions
.replace(offset
, arraysize(kEXTFragDepthExtension
),
9527 if (!draw_buffers_explicitly_enabled_
) {
9528 size_t offset
= extensions
.find(kEXTDrawBuffersExtension
);
9529 if (std::string::npos
!= offset
) {
9530 extensions
.replace(offset
, arraysize(kEXTDrawBuffersExtension
),
9534 if (!shader_texture_lod_explicitly_enabled_
) {
9535 size_t offset
= extensions
.find(kEXTShaderTextureLodExtension
);
9536 if (std::string::npos
!= offset
) {
9537 extensions
.replace(offset
,
9538 arraysize(kEXTShaderTextureLodExtension
),
9543 extensions
= feature_info_
->extensions().c_str();
9545 if (supports_post_sub_buffer_
)
9546 extensions
+= " GL_CHROMIUM_post_sub_buffer";
9547 str
= extensions
.c_str();
9551 str
= reinterpret_cast<const char*>(glGetString(name
));
9554 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
9555 bucket
->SetFromString(str
);
9556 return error::kNoError
;
9559 error::Error
GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size
,
9560 const void* cmd_data
) {
9561 const gles2::cmds::BufferData
& c
=
9562 *static_cast<const gles2::cmds::BufferData
*>(cmd_data
);
9563 GLenum target
= static_cast<GLenum
>(c
.target
);
9564 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
9565 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
9566 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
9567 GLenum usage
= static_cast<GLenum
>(c
.usage
);
9568 const void* data
= NULL
;
9569 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
9570 data
= GetSharedMemoryAs
<const void*>(data_shm_id
, data_shm_offset
, size
);
9572 return error::kOutOfBounds
;
9575 buffer_manager()->ValidateAndDoBufferData(&state_
, target
, size
, data
, usage
);
9576 return error::kNoError
;
9579 void GLES2DecoderImpl::DoBufferSubData(
9580 GLenum target
, GLintptr offset
, GLsizeiptr size
, const GLvoid
* data
) {
9581 // Just delegate it. Some validation is actually done before this.
9582 buffer_manager()->ValidateAndDoBufferSubData(
9583 &state_
, target
, offset
, size
, data
);
9586 bool GLES2DecoderImpl::ClearLevel(Texture
* texture
,
9595 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
9596 if ((feature_info_
->feature_flags().angle_depth_texture
||
9597 feature_info_
->IsES3Enabled())
9598 && (channels
& GLES2Util::kDepth
) != 0) {
9599 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9600 // on depth formats.
9602 glGenFramebuffersEXT(1, &fb
);
9603 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb
);
9605 bool have_stencil
= (channels
& GLES2Util::kStencil
) != 0;
9606 GLenum attachment
= have_stencil
? GL_DEPTH_STENCIL_ATTACHMENT
:
9607 GL_DEPTH_ATTACHMENT
;
9609 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT
, attachment
, target
,
9610 texture
->service_id(), level
);
9611 // ANGLE promises a depth only attachment ok.
9612 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT
) !=
9613 GL_FRAMEBUFFER_COMPLETE
) {
9617 state_
.SetDeviceStencilMaskSeparate(GL_FRONT
, kDefaultStencilMask
);
9618 state_
.SetDeviceStencilMaskSeparate(GL_BACK
, kDefaultStencilMask
);
9620 state_
.SetDeviceDepthMask(GL_TRUE
);
9621 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, true);
9622 glScissor(xoffset
, yoffset
, width
, height
);
9623 glClear(GL_DEPTH_BUFFER_BIT
| (have_stencil
? GL_STENCIL_BUFFER_BIT
: 0));
9625 RestoreClearState();
9627 glDeleteFramebuffersEXT(1, &fb
);
9628 Framebuffer
* framebuffer
=
9629 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT
);
9630 GLuint fb_service_id
=
9631 framebuffer
? framebuffer
->service_id() : GetBackbufferServiceId();
9632 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, fb_service_id
);
9636 static const uint32 kMaxZeroSize
= 1024 * 1024 * 4;
9639 uint32 padded_row_size
;
9640 if (!GLES2Util::ComputeImageDataSizes(
9641 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9642 NULL
, &padded_row_size
)) {
9646 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size
);
9650 if (size
> kMaxZeroSize
) {
9651 if (kMaxZeroSize
< padded_row_size
) {
9652 // That'd be an awfully large texture.
9655 // We should never have a large total size with a zero row size.
9656 DCHECK_GT(padded_row_size
, 0U);
9657 tile_height
= kMaxZeroSize
/ padded_row_size
;
9658 if (!GLES2Util::ComputeImageDataSizes(
9659 width
, tile_height
, 1, format
, type
, state_
.unpack_alignment
, &size
,
9664 tile_height
= height
;
9667 // Assumes the size has already been checked.
9668 scoped_ptr
<char[]> zero(new char[size
]);
9669 memset(zero
.get(), 0, size
);
9670 glBindTexture(texture
->target(), texture
->service_id());
9673 while (y
< height
) {
9674 GLint h
= y
+ tile_height
> height
? height
- y
: tile_height
;
9675 glTexSubImage2D(target
, level
, xoffset
, yoffset
+ y
, width
, h
, format
, type
,
9679 TextureRef
* bound_texture
=
9680 texture_manager()->GetTextureInfoForTarget(&state_
, texture
->target());
9681 glBindTexture(texture
->target(),
9682 bound_texture
? bound_texture
->service_id() : 0);
9688 const int kASTCBlockSize
= 16;
9689 const int kS3TCBlockWidth
= 4;
9690 const int kS3TCBlockHeight
= 4;
9691 const int kS3TCDXT1BlockSize
= 8;
9692 const int kS3TCDXT3AndDXT5BlockSize
= 16;
9693 const int kEACAndETC2BlockSize
= 4;
9700 const ASTCBlockArray kASTCBlockArray
[] = {
9701 {4, 4}, /* GL_COMPRESSED_RGBA_ASTC_4x4_KHR */
9702 {5, 4}, /* and GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR */
9716 bool IsValidDXTSize(GLint level
, GLsizei size
) {
9717 return (size
== 1) ||
9718 (size
== 2) || !(size
% kS3TCBlockWidth
);
9721 bool IsValidPVRTCSize(GLint level
, GLsizei size
) {
9722 return GLES2Util::IsPOT(size
);
9725 } // anonymous namespace.
9727 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9728 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9729 GLenum format
, GLsizei
* size_in_bytes
) {
9730 base::CheckedNumeric
<GLsizei
> bytes_required(0);
9733 case GL_ATC_RGB_AMD
:
9734 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9735 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9736 case GL_ETC1_RGB8_OES
:
9738 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9740 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9741 bytes_required
*= kS3TCDXT1BlockSize
;
9743 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR
:
9744 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR
:
9745 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR
:
9746 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR
:
9747 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR
:
9748 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR
:
9749 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR
:
9750 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR
:
9751 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR
:
9752 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR
:
9753 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR
:
9754 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR
:
9755 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR
:
9756 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR
:
9757 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
:
9758 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
:
9759 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
:
9760 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
:
9761 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
:
9762 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
:
9763 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
:
9764 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
:
9765 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
:
9766 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
:
9767 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
:
9768 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
:
9769 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
:
9770 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
: {
9771 const int index
= (format
< GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
) ?
9772 static_cast<int>(format
- GL_COMPRESSED_RGBA_ASTC_4x4_KHR
) :
9773 static_cast<int>(format
- GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
);
9775 const int kBlockWidth
= kASTCBlockArray
[index
].blockWidth
;
9776 const int kBlockHeight
= kASTCBlockArray
[index
].blockHeight
;
9779 (width
+ kBlockWidth
- 1) / kBlockWidth
;
9781 (height
+ kBlockHeight
- 1) / kBlockHeight
;
9783 bytes_required
*= kASTCBlockSize
;
9786 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9787 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9788 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9789 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9791 (width
+ kS3TCBlockWidth
- 1) / kS3TCBlockWidth
;
9793 (height
+ kS3TCBlockHeight
- 1) / kS3TCBlockHeight
;
9794 bytes_required
*= kS3TCDXT3AndDXT5BlockSize
;
9796 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9797 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9798 bytes_required
= std::max(width
, 8);
9799 bytes_required
*= std::max(height
, 8);
9800 bytes_required
*= 4;
9801 bytes_required
+= 7;
9802 bytes_required
/= 8;
9804 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9805 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9806 bytes_required
= std::max(width
, 16);
9807 bytes_required
*= std::max(height
, 8);
9808 bytes_required
*= 2;
9809 bytes_required
+= 7;
9810 bytes_required
/= 8;
9814 case GL_COMPRESSED_R11_EAC
:
9815 case GL_COMPRESSED_SIGNED_R11_EAC
:
9816 case GL_COMPRESSED_RGB8_ETC2
:
9817 case GL_COMPRESSED_SRGB8_ETC2
:
9818 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9819 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9821 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9823 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9824 bytes_required
*= 8;
9825 bytes_required
*= depth
;
9827 case GL_COMPRESSED_RG11_EAC
:
9828 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9829 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9830 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9832 (width
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9834 (height
+ kEACAndETC2BlockSize
- 1) / kEACAndETC2BlockSize
;
9835 bytes_required
*= 16;
9836 bytes_required
*= depth
;
9839 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, format
, "format");
9843 if (!bytes_required
.IsValid()) {
9844 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "invalid size");
9848 *size_in_bytes
= bytes_required
.ValueOrDefault(0);
9852 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9853 const char* function_name
, GLsizei width
, GLsizei height
, GLsizei depth
,
9854 GLenum format
, GLsizei size
) {
9855 GLsizei bytes_required
= 0;
9856 if (!GetCompressedTexSizeInBytes(
9857 function_name
, width
, height
, depth
, format
, &bytes_required
)) {
9861 if (size
!= bytes_required
) {
9863 GL_INVALID_VALUE
, function_name
, "size is not correct for dimensions");
9870 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9871 const char* function_name
, GLenum target
, GLint level
,
9872 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
) {
9874 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9875 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9876 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9877 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
9878 DCHECK_EQ(1, depth
); // 2D formats.
9879 if (!IsValidDXTSize(level
, width
) || !IsValidDXTSize(level
, height
)) {
9881 GL_INVALID_OPERATION
, function_name
,
9882 "width or height invalid for level");
9886 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR
:
9887 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR
:
9888 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR
:
9889 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR
:
9890 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR
:
9891 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR
:
9892 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR
:
9893 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR
:
9894 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR
:
9895 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR
:
9896 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR
:
9897 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR
:
9898 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR
:
9899 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR
:
9900 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
:
9901 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
:
9902 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
:
9903 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
:
9904 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
:
9905 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
:
9906 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
:
9907 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
:
9908 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
:
9909 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
:
9910 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
:
9911 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
:
9912 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
:
9913 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
:
9914 case GL_ATC_RGB_AMD
:
9915 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
9916 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
9917 case GL_ETC1_RGB8_OES
:
9918 DCHECK_EQ(1, depth
); // 2D formats.
9919 if (width
<= 0 || height
<= 0) {
9921 GL_INVALID_OPERATION
, function_name
,
9922 "width or height invalid for level");
9926 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
9927 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
9928 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
9929 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
9930 DCHECK_EQ(1, depth
); // 2D formats.
9931 if (!IsValidPVRTCSize(level
, width
) ||
9932 !IsValidPVRTCSize(level
, height
)) {
9934 GL_INVALID_OPERATION
, function_name
,
9935 "width or height invalid for level");
9941 case GL_COMPRESSED_R11_EAC
:
9942 case GL_COMPRESSED_SIGNED_R11_EAC
:
9943 case GL_COMPRESSED_RG11_EAC
:
9944 case GL_COMPRESSED_SIGNED_RG11_EAC
:
9945 case GL_COMPRESSED_RGB8_ETC2
:
9946 case GL_COMPRESSED_SRGB8_ETC2
:
9947 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9948 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
9949 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
9950 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
9951 if (width
<= 0 || height
<= 0 || depth
<= 0) {
9953 GL_INVALID_OPERATION
, function_name
,
9954 "width, height, or depth invalid");
9957 if (target
== GL_TEXTURE_3D
) {
9959 GL_INVALID_OPERATION
, function_name
,
9960 "target invalid for format");
9969 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9970 const char* function_name
,
9971 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
9972 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
9974 if (xoffset
< 0 || yoffset
< 0 || zoffset
< 0) {
9976 GL_INVALID_VALUE
, function_name
, "x/y/z offset < 0");
9981 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
9982 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
9983 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
9984 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: {
9985 const int kBlockWidth
= 4;
9986 const int kBlockHeight
= 4;
9987 if ((xoffset
% kBlockWidth
) || (yoffset
% kBlockHeight
)) {
9989 GL_INVALID_OPERATION
, function_name
,
9990 "xoffset or yoffset not multiple of 4");
9993 GLsizei tex_width
= 0;
9994 GLsizei tex_height
= 0;
9995 if (!texture
->GetLevelSize(target
, level
,
9996 &tex_width
, &tex_height
, nullptr) ||
9997 width
- xoffset
> tex_width
||
9998 height
- yoffset
> tex_height
) {
10000 GL_INVALID_OPERATION
, function_name
, "dimensions out of range");
10003 return ValidateCompressedTexDimensions(
10004 function_name
, target
, level
, width
, height
, 1, format
);
10006 case GL_ATC_RGB_AMD
:
10007 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
10008 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
: {
10009 LOCAL_SET_GL_ERROR(
10010 GL_INVALID_OPERATION
, function_name
,
10011 "not supported for ATC textures");
10014 case GL_ETC1_RGB8_OES
: {
10015 LOCAL_SET_GL_ERROR(
10016 GL_INVALID_OPERATION
, function_name
,
10017 "not supported for ECT1_RGB8_OES textures");
10020 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
10021 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
10022 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
10023 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
: {
10024 if ((xoffset
!= 0) || (yoffset
!= 0)) {
10025 LOCAL_SET_GL_ERROR(
10026 GL_INVALID_OPERATION
, function_name
,
10027 "xoffset and yoffset must be zero");
10030 GLsizei tex_width
= 0;
10031 GLsizei tex_height
= 0;
10032 if (!texture
->GetLevelSize(target
, level
,
10033 &tex_width
, &tex_height
, nullptr) ||
10034 width
!= tex_width
||
10035 height
!= tex_height
) {
10036 LOCAL_SET_GL_ERROR(
10037 GL_INVALID_OPERATION
, function_name
,
10038 "dimensions must match existing texture level dimensions");
10041 return ValidateCompressedTexDimensions(
10042 function_name
, target
, level
, width
, height
, 1, format
);
10046 case GL_COMPRESSED_R11_EAC
:
10047 case GL_COMPRESSED_SIGNED_R11_EAC
:
10048 case GL_COMPRESSED_RG11_EAC
:
10049 case GL_COMPRESSED_SIGNED_RG11_EAC
:
10050 case GL_COMPRESSED_RGB8_ETC2
:
10051 case GL_COMPRESSED_SRGB8_ETC2
:
10052 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
10053 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
:
10054 case GL_COMPRESSED_RGBA8_ETC2_EAC
:
10055 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
:
10057 const int kBlockSize
= 4;
10058 GLsizei tex_width
, tex_height
;
10059 if (target
== GL_TEXTURE_3D
||
10060 !texture
->GetLevelSize(target
, level
,
10061 &tex_width
, &tex_height
, nullptr) ||
10062 (xoffset
% kBlockSize
) || (yoffset
% kBlockSize
) ||
10063 ((width
% kBlockSize
) && xoffset
+ width
!= tex_width
) ||
10064 ((height
% kBlockSize
) && yoffset
+ height
!= tex_height
)) {
10065 LOCAL_SET_GL_ERROR(
10066 GL_INVALID_OPERATION
, function_name
,
10067 "dimensions must match existing texture level dimensions");
10077 error::Error
GLES2DecoderImpl::DoCompressedTexImage2D(
10080 GLenum internal_format
,
10084 GLsizei image_size
,
10085 const void* data
) {
10086 if (!validators_
->texture_target
.IsValid(target
)) {
10087 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10088 "glCompressedTexImage2D", target
, "target");
10089 return error::kNoError
;
10091 if (!validators_
->compressed_texture_format
.IsValid(
10092 internal_format
)) {
10093 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10094 "glCompressedTexImage2D", internal_format
, "internal_format");
10095 return error::kNoError
;
10097 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10099 LOCAL_SET_GL_ERROR(
10101 "glCompressedTexImage2D", "dimensions out of range");
10102 return error::kNoError
;
10104 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10106 if (!texture_ref
) {
10107 LOCAL_SET_GL_ERROR(
10109 "glCompressedTexImage2D", "unknown texture target");
10110 return error::kNoError
;
10112 Texture
* texture
= texture_ref
->texture();
10113 if (texture
->IsImmutable()) {
10114 LOCAL_SET_GL_ERROR(
10115 GL_INVALID_OPERATION
,
10116 "glCompressedTexImage2D", "texture is immutable");
10117 return error::kNoError
;
10119 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target
, level
,
10120 width
, height
, 1, internal_format
) ||
10121 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width
, height
,
10122 1, internal_format
, image_size
)) {
10123 return error::kNoError
;
10126 if (!EnsureGPUMemoryAvailable(image_size
)) {
10127 LOCAL_SET_GL_ERROR(
10128 GL_OUT_OF_MEMORY
, "glCompressedTexImage2D", "out of memory");
10129 return error::kNoError
;
10132 if (texture
->IsAttachedToFramebuffer()) {
10133 framebuffer_state_
.clear_state_dirty
= true;
10136 scoped_ptr
<int8
[]> zero
;
10138 zero
.reset(new int8
[image_size
]);
10139 memset(zero
.get(), 0, image_size
);
10142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
10143 glCompressedTexImage2D(
10144 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
10145 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
10146 if (error
== GL_NO_ERROR
) {
10147 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10148 width
, height
, 1, border
, 0, 0,
10149 gfx::Rect(width
, height
));
10152 // This may be a slow command. Exit command processing to allow for
10153 // context preemption and GPU watchdog checks.
10154 ExitCommandProcessingEarly();
10155 return error::kNoError
;
10158 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2D(
10159 uint32 immediate_data_size
,
10160 const void* cmd_data
) {
10161 const gles2::cmds::CompressedTexImage2D
& c
=
10162 *static_cast<const gles2::cmds::CompressedTexImage2D
*>(cmd_data
);
10163 GLenum target
= static_cast<GLenum
>(c
.target
);
10164 GLint level
= static_cast<GLint
>(c
.level
);
10165 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10166 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10167 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10168 GLint border
= static_cast<GLint
>(c
.border
);
10169 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
10170 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
10171 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
10172 const void* data
= NULL
;
10173 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
10174 data
= GetSharedMemoryAs
<const void*>(
10175 data_shm_id
, data_shm_offset
, image_size
);
10177 return error::kOutOfBounds
;
10180 return DoCompressedTexImage2D(
10181 target
, level
, internal_format
, width
, height
, border
, image_size
, data
);
10184 error::Error
GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
10185 uint32 immediate_data_size
,
10186 const void* cmd_data
) {
10187 const gles2::cmds::CompressedTexImage2DBucket
& c
=
10188 *static_cast<const gles2::cmds::CompressedTexImage2DBucket
*>(cmd_data
);
10189 GLenum target
= static_cast<GLenum
>(c
.target
);
10190 GLint level
= static_cast<GLint
>(c
.level
);
10191 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10192 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10193 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10194 GLint border
= static_cast<GLint
>(c
.border
);
10195 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10197 return error::kInvalidArguments
;
10199 uint32 data_size
= bucket
->size();
10200 GLsizei imageSize
= data_size
;
10201 const void* data
= bucket
->GetData(0, data_size
);
10203 return error::kInvalidArguments
;
10205 return DoCompressedTexImage2D(
10206 target
, level
, internal_format
, width
, height
, border
,
10210 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
10211 uint32 immediate_data_size
,
10212 const void* cmd_data
) {
10213 const gles2::cmds::CompressedTexSubImage2DBucket
& c
=
10214 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket
*>(cmd_data
);
10215 GLenum target
= static_cast<GLenum
>(c
.target
);
10216 GLint level
= static_cast<GLint
>(c
.level
);
10217 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10218 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10219 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10220 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10221 GLenum format
= static_cast<GLenum
>(c
.format
);
10222 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10224 return error::kInvalidArguments
;
10226 uint32 data_size
= bucket
->size();
10227 GLsizei imageSize
= data_size
;
10228 const void* data
= bucket
->GetData(0, data_size
);
10230 return error::kInvalidArguments
;
10232 if (!validators_
->texture_target
.IsValid(target
)) {
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_ENUM
, "glCompressedTexSubImage2D", "target");
10235 return error::kNoError
;
10237 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
10238 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10239 "glCompressedTexSubImage2D", format
, "format");
10240 return error::kNoError
;
10243 LOCAL_SET_GL_ERROR(
10244 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "width < 0");
10245 return error::kNoError
;
10248 LOCAL_SET_GL_ERROR(
10249 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "height < 0");
10250 return error::kNoError
;
10252 if (imageSize
< 0) {
10253 LOCAL_SET_GL_ERROR(
10254 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "imageSize < 0");
10255 return error::kNoError
;
10257 DoCompressedTexSubImage2D(
10258 target
, level
, xoffset
, yoffset
, width
, height
, format
, imageSize
, data
);
10259 return error::kNoError
;
10262 error::Error
GLES2DecoderImpl::DoCompressedTexImage3D(
10265 GLenum internal_format
,
10270 GLsizei image_size
,
10271 const void* data
) {
10272 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
10273 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10274 "glCompressedTexImage3D", target
, "target");
10275 return error::kNoError
;
10277 if (!validators_
->compressed_texture_format
.IsValid(
10278 internal_format
)) {
10279 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10280 "glCompressedTexImage3D", internal_format
, "internal_format");
10281 return error::kNoError
;
10283 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, depth
) ||
10285 LOCAL_SET_GL_ERROR(
10287 "glCompressedTexImage3D", "dimensions out of range");
10288 return error::kNoError
;
10290 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10292 if (!texture_ref
) {
10293 LOCAL_SET_GL_ERROR(
10295 "glCompressedTexImage3D", "unknown texture target");
10296 return error::kNoError
;
10298 Texture
* texture
= texture_ref
->texture();
10299 if (texture
->IsImmutable()) {
10300 LOCAL_SET_GL_ERROR(
10301 GL_INVALID_OPERATION
,
10302 "glCompressedTexImage3D", "texture is immutable");
10303 return error::kNoError
;
10306 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target
, level
,
10307 width
, height
, depth
, internal_format
) ||
10308 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width
, height
,
10309 depth
, internal_format
, image_size
)) {
10310 return error::kNoError
;
10313 if (!EnsureGPUMemoryAvailable(image_size
)) {
10314 LOCAL_SET_GL_ERROR(
10315 GL_OUT_OF_MEMORY
, "glCompressedTexImage3D", "out of memory");
10316 return error::kNoError
;
10319 if (texture
->IsAttachedToFramebuffer()) {
10320 framebuffer_state_
.clear_state_dirty
= true;
10323 scoped_ptr
<int8
[]> zero
;
10325 zero
.reset(new int8
[image_size
]);
10326 memset(zero
.get(), 0, image_size
);
10329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
10330 glCompressedTexImage3D(target
, level
, internal_format
, width
, height
, depth
,
10331 border
, image_size
, data
);
10332 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
10333 if (error
== GL_NO_ERROR
) {
10334 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10335 width
, height
, depth
, border
, 0, 0,
10336 gfx::Rect(width
, height
));
10339 // This may be a slow command. Exit command processing to allow for
10340 // context preemption and GPU watchdog checks.
10341 ExitCommandProcessingEarly();
10342 return error::kNoError
;
10345 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3D(
10346 uint32 immediate_data_size
, const void* cmd_data
) {
10347 if (!unsafe_es3_apis_enabled())
10348 return error::kUnknownCommand
;
10350 const gles2::cmds::CompressedTexImage3D
& c
=
10351 *static_cast<const gles2::cmds::CompressedTexImage3D
*>(cmd_data
);
10352 GLenum target
= static_cast<GLenum
>(c
.target
);
10353 GLint level
= static_cast<GLint
>(c
.level
);
10354 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10355 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10356 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10357 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10358 GLint border
= static_cast<GLint
>(c
.border
);
10359 GLsizei image_size
= static_cast<GLsizei
>(c
.imageSize
);
10360 uint32 data_shm_id
= static_cast<uint32
>(c
.data_shm_id
);
10361 uint32 data_shm_offset
= static_cast<uint32
>(c
.data_shm_offset
);
10362 const void* data
= NULL
;
10363 if (data_shm_id
!= 0 || data_shm_offset
!= 0) {
10364 data
= GetSharedMemoryAs
<const void*>(
10365 data_shm_id
, data_shm_offset
, image_size
);
10367 return error::kOutOfBounds
;
10370 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
10371 depth
, border
, image_size
, data
);
10374 error::Error
GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
10375 uint32 immediate_data_size
, const void* cmd_data
) {
10376 if (!unsafe_es3_apis_enabled())
10377 return error::kUnknownCommand
;
10379 const gles2::cmds::CompressedTexImage3DBucket
& c
=
10380 *static_cast<const gles2::cmds::CompressedTexImage3DBucket
*>(cmd_data
);
10381 GLenum target
= static_cast<GLenum
>(c
.target
);
10382 GLint level
= static_cast<GLint
>(c
.level
);
10383 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10384 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10385 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10386 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10387 GLint border
= static_cast<GLint
>(c
.border
);
10388 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10390 return error::kInvalidArguments
;
10392 uint32 data_size
= bucket
->size();
10393 GLsizei imageSize
= data_size
;
10394 const void* data
= bucket
->GetData(0, data_size
);
10396 return error::kInvalidArguments
;
10398 return DoCompressedTexImage3D(target
, level
, internal_format
, width
, height
,
10399 depth
, border
, imageSize
, data
);
10402 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
10403 GLenum target
, GLint level
, GLint xoffset
, GLint yoffset
, GLint zoffset
,
10404 GLsizei width
, GLsizei height
, GLsizei depth
, GLenum format
,
10405 GLsizei image_size
, const void* data
) {
10406 if (!validators_
->texture_3_d_target
.IsValid(target
)) {
10407 LOCAL_SET_GL_ERROR(
10408 GL_INVALID_ENUM
, "glCompressedTexSubImage3D", "target");
10411 if (!validators_
->compressed_texture_format
.IsValid(format
)) {
10412 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10413 "glCompressedTexSubImage3D", format
, "format");
10416 if (width
< 0 || height
< 0 || depth
< 0) {
10417 LOCAL_SET_GL_ERROR(
10418 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "size < 0");
10421 if (image_size
< 0) {
10422 LOCAL_SET_GL_ERROR(
10423 GL_INVALID_VALUE
, "glCompressedTexSubImage3D", "imageSize < 0");
10426 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10428 if (!texture_ref
) {
10429 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10430 "unknown texture for target");
10433 Texture
* texture
= texture_ref
->texture();
10434 GLenum type
= 0, internal_format
= 0;
10435 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10436 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10437 "level does not exist");
10440 if (internal_format
!= format
) {
10441 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCompressedTexSubImage3D",
10442 "format does not match internal format");
10445 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, zoffset
,
10446 width
, height
, depth
)) {
10447 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedTexSubImage3D",
10451 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
10452 width
, height
, depth
, format
,
10454 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
10455 target
, level
, xoffset
, yoffset
,
10456 zoffset
, width
, height
, depth
,
10457 format
, texture
)) {
10461 // Note: There is no need to deal with texture cleared tracking here
10462 // because the validation above means you can only get here if the level
10463 // is already a matching compressed format and in that case
10464 // CompressedTexImage3D already cleared the texture.
10465 glCompressedTexSubImage3D(
10466 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
10469 // This may be a slow command. Exit command processing to allow for
10470 // context preemption and GPU watchdog checks.
10471 ExitCommandProcessingEarly();
10474 error::Error
GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
10475 uint32 immediate_data_size
, const void* cmd_data
) {
10476 if (!unsafe_es3_apis_enabled())
10477 return error::kUnknownCommand
;
10478 const gles2::cmds::CompressedTexSubImage3DBucket
& c
=
10479 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket
*>(cmd_data
);
10480 GLenum target
= static_cast<GLenum
>(c
.target
);
10481 GLint level
= static_cast<GLint
>(c
.level
);
10482 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
10483 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
10484 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
10485 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10486 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10487 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10488 GLenum format
= static_cast<GLenum
>(c
.format
);
10489 Bucket
* bucket
= GetBucket(c
.bucket_id
);
10491 return error::kInvalidArguments
;
10493 uint32 data_size
= bucket
->size();
10494 GLsizei image_size
= data_size
;
10495 const void* data
= bucket
->GetData(0, data_size
);
10497 return error::kInvalidArguments
;
10499 DoCompressedTexSubImage3D(
10500 target
, level
, xoffset
, yoffset
, zoffset
, width
, height
, depth
, format
,
10502 return error::kNoError
;
10505 error::Error
GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size
,
10506 const void* cmd_data
) {
10507 const gles2::cmds::TexImage2D
& c
=
10508 *static_cast<const gles2::cmds::TexImage2D
*>(cmd_data
);
10509 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
10510 "width", c
.width
, "height", c
.height
);
10511 // Set as failed for now, but if it successed, this will be set to not failed.
10512 texture_state_
.tex_image_failed
= true;
10513 GLenum target
= static_cast<GLenum
>(c
.target
);
10514 GLint level
= static_cast<GLint
>(c
.level
);
10515 // TODO(kloveless): Change TexImage2D command to use unsigned integer
10516 // for internalformat.
10517 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10518 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10519 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10520 GLint border
= static_cast<GLint
>(c
.border
);
10521 GLenum format
= static_cast<GLenum
>(c
.format
);
10522 GLenum type
= static_cast<GLenum
>(c
.type
);
10523 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10524 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10525 uint32 pixels_size
;
10526 if (!GLES2Util::ComputeImageDataSizes(
10527 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10529 return error::kOutOfBounds
;
10531 const void* pixels
= NULL
;
10532 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10533 pixels
= GetSharedMemoryAs
<const void*>(
10534 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10536 return error::kOutOfBounds
;
10540 // For testing only. Allows us to stress the ability to respond to OOM errors.
10541 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10542 (width
* height
>= 4096 * 4096)) {
10543 LOCAL_SET_GL_ERROR(
10545 "glTexImage2D", "synthetic out of memory");
10546 return error::kNoError
;
10549 TextureManager::DoTexImageArguments args
= {
10550 target
, level
, internal_format
, width
, height
, 1, border
, format
, type
,
10551 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage2D
};
10552 texture_manager()->ValidateAndDoTexImage(
10553 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage2D", args
);
10555 // This may be a slow command. Exit command processing to allow for
10556 // context preemption and GPU watchdog checks.
10557 ExitCommandProcessingEarly();
10558 return error::kNoError
;
10561 error::Error
GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size
,
10562 const void* cmd_data
) {
10563 if (!unsafe_es3_apis_enabled())
10564 return error::kUnknownCommand
;
10566 const gles2::cmds::TexImage3D
& c
=
10567 *static_cast<const gles2::cmds::TexImage3D
*>(cmd_data
);
10568 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10569 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
10570 // Set as failed for now, but if it successed, this will be set to not failed.
10571 texture_state_
.tex_image_failed
= true;
10572 GLenum target
= static_cast<GLenum
>(c
.target
);
10573 GLint level
= static_cast<GLint
>(c
.level
);
10574 GLenum internal_format
= static_cast<GLenum
>(c
.internalformat
);
10575 GLsizei width
= static_cast<GLsizei
>(c
.width
);
10576 GLsizei height
= static_cast<GLsizei
>(c
.height
);
10577 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
10578 GLint border
= static_cast<GLint
>(c
.border
);
10579 GLenum format
= static_cast<GLenum
>(c
.format
);
10580 GLenum type
= static_cast<GLenum
>(c
.type
);
10581 uint32 pixels_shm_id
= static_cast<uint32
>(c
.pixels_shm_id
);
10582 uint32 pixels_shm_offset
= static_cast<uint32
>(c
.pixels_shm_offset
);
10583 uint32 pixels_size
;
10584 if (!GLES2Util::ComputeImageDataSizes(
10585 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10587 return error::kOutOfBounds
;
10589 const void* pixels
= NULL
;
10590 if (pixels_shm_id
!= 0 || pixels_shm_offset
!= 0) {
10591 pixels
= GetSharedMemoryAs
<const void*>(
10592 pixels_shm_id
, pixels_shm_offset
, pixels_size
);
10594 return error::kOutOfBounds
;
10598 // For testing only. Allows us to stress the ability to respond to OOM errors.
10599 if (workarounds().simulate_out_of_memory_on_large_textures
&&
10600 (width
* height
* depth
>= 4096 * 4096)) {
10601 LOCAL_SET_GL_ERROR(
10603 "glTexImage3D", "synthetic out of memory");
10604 return error::kNoError
;
10607 TextureManager::DoTexImageArguments args
= {
10608 target
, level
, internal_format
, width
, height
, depth
, border
, format
, type
,
10609 pixels
, pixels_size
, TextureManager::DoTexImageArguments::kTexImage3D
};
10610 texture_manager()->ValidateAndDoTexImage(
10611 &texture_state_
, &state_
, &framebuffer_state_
, "glTexImage3D", args
);
10613 // This may be a slow command. Exit command processing to allow for
10614 // context preemption and GPU watchdog checks.
10615 ExitCommandProcessingEarly();
10616 return error::kNoError
;
10619 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10627 GLsizei image_size
,
10628 const void * data
) {
10629 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10631 if (!texture_ref
) {
10632 LOCAL_SET_GL_ERROR(
10633 GL_INVALID_OPERATION
,
10634 "glCompressedTexSubImage2D", "unknown texture for target");
10637 Texture
* texture
= texture_ref
->texture();
10639 GLenum internal_format
= 0;
10640 if (!texture
->GetLevelType(target
, level
, &type
, &internal_format
)) {
10641 LOCAL_SET_GL_ERROR(
10642 GL_INVALID_OPERATION
,
10643 "glCompressedTexSubImage2D", "level does not exist.");
10646 if (internal_format
!= format
) {
10647 LOCAL_SET_GL_ERROR(
10648 GL_INVALID_OPERATION
,
10649 "glCompressedTexSubImage2D", "format does not match internal format.");
10652 if (!texture
->ValidForTexture(target
, level
, xoffset
, yoffset
, 0, width
,
10654 LOCAL_SET_GL_ERROR(
10655 GL_INVALID_VALUE
, "glCompressedTexSubImage2D", "bad dimensions.");
10659 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10660 width
, height
, 1, format
, image_size
) ||
10661 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10662 target
, level
, xoffset
, yoffset
, 0,
10663 width
, height
, 1, format
, texture
)) {
10668 // Note: There is no need to deal with texture cleared tracking here
10669 // because the validation above means you can only get here if the level
10670 // is already a matching compressed format and in that case
10671 // CompressedTexImage2D already cleared the texture.
10672 glCompressedTexSubImage2D(
10673 target
, level
, xoffset
, yoffset
, width
, height
, format
, image_size
, data
);
10675 // This may be a slow command. Exit command processing to allow for
10676 // context preemption and GPU watchdog checks.
10677 ExitCommandProcessingEarly();
10681 GLint start
, GLint range
, GLint sourceRange
,
10682 GLint
* out_start
, GLint
* out_range
) {
10689 GLint end
= start
+ range
;
10690 if (end
> sourceRange
) {
10691 range
-= end
- sourceRange
;
10693 *out_start
= start
;
10694 *out_range
= range
;
10697 void GLES2DecoderImpl::DoCopyTexImage2D(
10700 GLenum internal_format
,
10706 DCHECK(!ShouldDeferReads());
10707 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10709 if (!texture_ref
) {
10710 LOCAL_SET_GL_ERROR(
10711 GL_INVALID_OPERATION
,
10712 "glCopyTexImage2D", "unknown texture for target");
10715 Texture
* texture
= texture_ref
->texture();
10716 if (texture
->IsImmutable()) {
10717 LOCAL_SET_GL_ERROR(
10718 GL_INVALID_OPERATION
, "glCopyTexImage2D", "texture is immutable");
10721 if (!texture_manager()->ValidForTarget(target
, level
, width
, height
, 1) ||
10723 LOCAL_SET_GL_ERROR(
10724 GL_INVALID_VALUE
, "glCopyTexImage2D", "dimensions out of range");
10727 if (!texture_manager()->ValidateFormatAndTypeCombination(
10728 state_
.GetErrorState(), "glCopyTexImage2D", internal_format
,
10729 GL_UNSIGNED_BYTE
)) {
10733 // Check we have compatible formats.
10734 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10735 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10736 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(internal_format
);
10738 if ((channels_needed
& channels_exist
) != channels_needed
) {
10739 LOCAL_SET_GL_ERROR(
10740 GL_INVALID_OPERATION
, "glCopyTexImage2D", "incompatible format");
10744 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10745 LOCAL_SET_GL_ERROR(
10746 GL_INVALID_OPERATION
,
10747 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10751 uint32 estimated_size
= 0;
10752 if (!GLES2Util::ComputeImageDataSizes(
10753 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10754 state_
.unpack_alignment
, &estimated_size
, NULL
, NULL
)) {
10755 LOCAL_SET_GL_ERROR(
10756 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too large");
10760 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
10761 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "out of memory");
10765 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10769 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10770 LOCAL_SET_GL_ERROR(
10771 GL_INVALID_OPERATION
,
10772 "glCopyTexImage2D", "source and destination textures are the same");
10776 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10780 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10781 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10782 gfx::Size size
= GetBoundReadFrameBufferSize();
10784 if (texture
->IsAttachedToFramebuffer()) {
10785 framebuffer_state_
.clear_state_dirty
= true;
10788 // Clip to size to source dimensions
10791 GLint copyWidth
= 0;
10792 GLint copyHeight
= 0;
10793 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10794 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10798 copyWidth
!= width
||
10799 copyHeight
!= height
) {
10800 // some part was clipped so clear the rect.
10801 uint32 pixels_size
= 0;
10802 if (!GLES2Util::ComputeImageDataSizes(
10803 width
, height
, 1, internal_format
, GL_UNSIGNED_BYTE
,
10804 state_
.unpack_alignment
, &pixels_size
, NULL
, NULL
)) {
10805 LOCAL_SET_GL_ERROR(
10806 GL_OUT_OF_MEMORY
, "glCopyTexImage2D", "dimensions too big");
10809 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10810 memset(zero
.get(), 0, pixels_size
);
10811 ScopedModifyPixels
modify(texture_ref
);
10812 glTexImage2D(target
, level
, internal_format
, width
, height
, border
,
10813 internal_format
, GL_UNSIGNED_BYTE
, zero
.get());
10814 if (copyHeight
> 0 && copyWidth
> 0) {
10815 GLint dx
= copyX
- x
;
10816 GLint dy
= copyY
- y
;
10819 glCopyTexSubImage2D(target
, level
,
10820 destX
, destY
, copyX
, copyY
,
10821 copyWidth
, copyHeight
);
10824 ScopedModifyPixels
modify(texture_ref
);
10825 glCopyTexImage2D(target
, level
, internal_format
,
10826 copyX
, copyY
, copyWidth
, copyHeight
, border
);
10828 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10829 if (error
== GL_NO_ERROR
) {
10830 texture_manager()->SetLevelInfo(texture_ref
, target
, level
, internal_format
,
10831 width
, height
, 1, border
, internal_format
,
10832 GL_UNSIGNED_BYTE
, gfx::Rect(width
, height
));
10835 // This may be a slow command. Exit command processing to allow for
10836 // context preemption and GPU watchdog checks.
10837 ExitCommandProcessingEarly();
10840 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10849 DCHECK(!ShouldDeferReads());
10850 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
10852 if (!texture_ref
) {
10853 LOCAL_SET_GL_ERROR(
10854 GL_INVALID_OPERATION
,
10855 "glCopyTexSubImage2D", "unknown texture for target");
10858 Texture
* texture
= texture_ref
->texture();
10861 if (!texture
->GetLevelType(target
, level
, &type
, &format
) ||
10862 !texture
->ValidForTexture(
10863 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1)) {
10864 LOCAL_SET_GL_ERROR(
10865 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "bad dimensions.");
10869 // Check we have compatible formats.
10870 GLenum read_format
= GetBoundReadFrameBufferInternalFormat();
10871 uint32 channels_exist
= GLES2Util::GetChannelsForFormat(read_format
);
10872 uint32 channels_needed
= GLES2Util::GetChannelsForFormat(format
);
10874 if (!channels_needed
||
10875 (channels_needed
& channels_exist
) != channels_needed
) {
10876 LOCAL_SET_GL_ERROR(
10877 GL_INVALID_OPERATION
, "glCopyTexSubImage2D", "incompatible format");
10881 if ((channels_needed
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0) {
10882 LOCAL_SET_GL_ERROR(
10883 GL_INVALID_OPERATION
,
10884 "glCopySubImage2D", "can not be used with depth or stencil textures");
10888 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10892 if (FormsTextureCopyingFeedbackLoop(texture_ref
, level
)) {
10893 LOCAL_SET_GL_ERROR(
10894 GL_INVALID_OPERATION
,
10895 "glCopyTexSubImage2D", "source and destination textures are the same");
10899 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10903 ScopedResolvedFrameBufferBinder
binder(this, false, true);
10904 gfx::Size size
= GetBoundReadFrameBufferSize();
10907 GLint copyWidth
= 0;
10908 GLint copyHeight
= 0;
10909 Clip(x
, width
, size
.width(), ©X
, ©Width
);
10910 Clip(y
, height
, size
.height(), ©Y
, ©Height
);
10912 if (xoffset
!= 0 || yoffset
!= 0 || width
!= size
.width() ||
10913 height
!= size
.height()) {
10914 gfx::Rect cleared_rect
;
10915 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
10916 gfx::Rect(xoffset
, yoffset
, width
, height
),
10918 DCHECK_GE(cleared_rect
.size().GetArea(),
10919 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
10920 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
10923 // Otherwise clear part of texture level that is not already cleared.
10924 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
10926 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTexSubImage2D",
10927 "dimensions too big");
10932 // Write all pixels in below.
10933 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
10938 copyWidth
!= width
||
10939 copyHeight
!= height
) {
10940 // some part was clipped so clear the sub rect.
10941 uint32 pixels_size
= 0;
10942 if (!GLES2Util::ComputeImageDataSizes(
10943 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &pixels_size
,
10945 LOCAL_SET_GL_ERROR(
10946 GL_INVALID_VALUE
, "glCopyTexSubImage2D", "dimensions too large");
10949 scoped_ptr
<char[]> zero(new char[pixels_size
]);
10950 memset(zero
.get(), 0, pixels_size
);
10951 ScopedModifyPixels
modify(texture_ref
);
10953 target
, level
, xoffset
, yoffset
, width
, height
,
10954 format
, type
, zero
.get());
10957 if (copyHeight
> 0 && copyWidth
> 0) {
10958 GLint dx
= copyX
- x
;
10959 GLint dy
= copyY
- y
;
10960 GLint destX
= xoffset
+ dx
;
10961 GLint destY
= yoffset
+ dy
;
10962 ScopedModifyPixels
modify(texture_ref
);
10963 glCopyTexSubImage2D(target
, level
,
10964 destX
, destY
, copyX
, copyY
,
10965 copyWidth
, copyHeight
);
10968 // This may be a slow command. Exit command processing to allow for
10969 // context preemption and GPU watchdog checks.
10970 ExitCommandProcessingEarly();
10973 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10974 error::Error
* error
,
10975 const char* function_name
,
10984 const void * data
) {
10985 (*error
) = error::kNoError
;
10986 if (!validators_
->texture_target
.IsValid(target
)) {
10987 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name
, target
, "target");
10991 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "width < 0");
10995 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "height < 0");
10998 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11000 if (!texture_ref
) {
11001 LOCAL_SET_GL_ERROR(
11002 GL_INVALID_OPERATION
,
11003 function_name
, "unknown texture for target");
11006 Texture
* texture
= texture_ref
->texture();
11007 GLenum current_type
= 0;
11008 GLenum internal_format
= 0;
11009 if (!texture
->GetLevelType(target
, level
, ¤t_type
, &internal_format
)) {
11010 LOCAL_SET_GL_ERROR(
11011 GL_INVALID_OPERATION
, function_name
, "level does not exist.");
11014 if (!texture_manager()->ValidateTextureParameters(state_
.GetErrorState(),
11015 function_name
, format
, type
, internal_format
, level
)) {
11018 if (type
!= current_type
&& !feature_info_
->IsES3Enabled()) {
11019 LOCAL_SET_GL_ERROR(
11020 GL_INVALID_OPERATION
,
11021 function_name
, "type does not match type of texture.");
11024 if (!texture
->ValidForTexture(
11025 target
, level
, xoffset
, yoffset
, 0, width
, height
, 1)) {
11026 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "bad dimensions.");
11029 if ((GLES2Util::GetChannelsForFormat(format
) &
11030 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0
11031 && !feature_info_
->IsES3Enabled()) {
11032 LOCAL_SET_GL_ERROR(
11033 GL_INVALID_OPERATION
,
11034 function_name
, "can not supply data for depth or stencil textures");
11037 if (data
== NULL
) {
11038 (*error
) = error::kOutOfBounds
;
11044 error::Error
GLES2DecoderImpl::DoTexSubImage2D(
11053 const void * data
) {
11054 error::Error error
= error::kNoError
;
11055 if (!ValidateTexSubImage2D(&error
, "glTexSubImage2D", target
, level
,
11056 xoffset
, yoffset
, width
, height
, format
, type
, data
)) {
11059 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11061 Texture
* texture
= texture_ref
->texture();
11062 GLsizei tex_width
= 0;
11063 GLsizei tex_height
= 0;
11064 bool ok
= texture
->GetLevelSize(
11065 target
, level
, &tex_width
, &tex_height
, nullptr);
11067 if (xoffset
!= 0 || yoffset
!= 0 ||
11068 width
!= tex_width
|| height
!= tex_height
) {
11069 gfx::Rect cleared_rect
;
11070 if (CombineAdjacentRects(texture
->GetLevelClearedRect(target
, level
),
11071 gfx::Rect(xoffset
, yoffset
, width
, height
),
11073 DCHECK_GE(cleared_rect
.size().GetArea(),
11074 texture
->GetLevelClearedRect(target
, level
).size().GetArea());
11075 texture_manager()->SetLevelClearedRect(texture_ref
, target
, level
,
11078 // Otherwise clear part of texture level that is not already cleared.
11079 if (!texture_manager()->ClearTextureLevel(this, texture_ref
, target
,
11081 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glTexSubImage2D",
11082 "dimensions too big");
11083 return error::kNoError
;
11086 ScopedTextureUploadTimer
timer(&texture_state_
);
11088 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
11089 return error::kNoError
;
11092 if (!texture_state_
.texsubimage_faster_than_teximage
&&
11093 !texture
->IsImmutable() &&
11094 !texture
->HasImages()) {
11095 ScopedTextureUploadTimer
timer(&texture_state_
);
11096 GLenum internal_format
;
11098 texture
->GetLevelType(target
, level
, &tex_type
, &internal_format
);
11099 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
11102 target
, level
, internal_format
, width
, height
, 0, format
, type
, data
);
11104 ScopedTextureUploadTimer
timer(&texture_state_
);
11106 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, data
);
11108 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
11110 // This may be a slow command. Exit command processing to allow for
11111 // context preemption and GPU watchdog checks.
11112 ExitCommandProcessingEarly();
11113 return error::kNoError
;
11116 error::Error
GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size
,
11117 const void* cmd_data
) {
11118 const gles2::cmds::TexSubImage2D
& c
=
11119 *static_cast<const gles2::cmds::TexSubImage2D
*>(cmd_data
);
11120 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
11121 "width", c
.width
, "height", c
.height
);
11122 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
11123 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
11124 return error::kNoError
;
11126 GLenum target
= static_cast<GLenum
>(c
.target
);
11127 GLint level
= static_cast<GLint
>(c
.level
);
11128 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11129 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11130 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11131 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11132 GLenum format
= static_cast<GLenum
>(c
.format
);
11133 GLenum type
= static_cast<GLenum
>(c
.type
);
11135 if (!GLES2Util::ComputeImageDataSizes(
11136 width
, height
, 1, format
, type
, state_
.unpack_alignment
, &data_size
,
11138 return error::kOutOfBounds
;
11140 const void* pixels
= GetSharedMemoryAs
<const void*>(
11141 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
11142 return DoTexSubImage2D(
11143 target
, level
, xoffset
, yoffset
, width
, height
, format
, type
, pixels
);
11146 error::Error
GLES2DecoderImpl::DoTexSubImage3D(
11157 const void * data
) {
11158 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
11160 if (!texture_ref
) {
11161 LOCAL_SET_GL_ERROR(
11162 GL_INVALID_ENUM
, "glTexSubImage3D", "invalid target");
11165 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
11166 ScopedTextureUploadTimer
timer(&texture_state_
);
11167 glTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
, height
,
11168 depth
, format
, type
, data
);
11169 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
11170 if (error
== GL_NO_ERROR
) {
11171 // TODO(zmo): This is not 100% correct because only part of the level
11172 // image is cleared.
11173 texture_manager()->SetLevelCleared(texture_ref
, target
, level
, true);
11176 // This may be a slow command. Exit command processing to allow for
11177 // context preemption and GPU watchdog checks.
11178 ExitCommandProcessingEarly();
11179 return error::kNoError
;
11182 error::Error
GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size
,
11183 const void* cmd_data
) {
11184 if (!unsafe_es3_apis_enabled())
11185 return error::kUnknownCommand
;
11187 const gles2::cmds::TexSubImage3D
& c
=
11188 *static_cast<const gles2::cmds::TexSubImage3D
*>(cmd_data
);
11189 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
11190 "widthXheight", c
.width
* c
.height
, "depth", c
.depth
);
11191 GLboolean internal
= static_cast<GLboolean
>(c
.internal
);
11192 if (internal
== GL_TRUE
&& texture_state_
.tex_image_failed
)
11193 return error::kNoError
;
11195 GLenum target
= static_cast<GLenum
>(c
.target
);
11196 GLint level
= static_cast<GLint
>(c
.level
);
11197 GLint xoffset
= static_cast<GLint
>(c
.xoffset
);
11198 GLint yoffset
= static_cast<GLint
>(c
.yoffset
);
11199 GLint zoffset
= static_cast<GLint
>(c
.zoffset
);
11200 GLsizei width
= static_cast<GLsizei
>(c
.width
);
11201 GLsizei height
= static_cast<GLsizei
>(c
.height
);
11202 GLsizei depth
= static_cast<GLsizei
>(c
.depth
);
11203 GLenum format
= static_cast<GLenum
>(c
.format
);
11204 GLenum type
= static_cast<GLenum
>(c
.type
);
11206 if (!GLES2Util::ComputeImageDataSizes(
11207 width
, height
, depth
, format
, type
, state_
.unpack_alignment
, &data_size
,
11209 return error::kOutOfBounds
;
11211 const void* pixels
= GetSharedMemoryAs
<const void*>(
11212 c
.pixels_shm_id
, c
.pixels_shm_offset
, data_size
);
11213 return DoTexSubImage3D(target
, level
, xoffset
, yoffset
, zoffset
, width
,
11214 height
, depth
, format
, type
, pixels
);
11217 error::Error
GLES2DecoderImpl::HandleGetVertexAttribPointerv(
11218 uint32 immediate_data_size
,
11219 const void* cmd_data
) {
11220 const gles2::cmds::GetVertexAttribPointerv
& c
=
11221 *static_cast<const gles2::cmds::GetVertexAttribPointerv
*>(cmd_data
);
11222 GLuint index
= static_cast<GLuint
>(c
.index
);
11223 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11224 typedef cmds::GetVertexAttribPointerv::Result Result
;
11225 Result
* result
= GetSharedMemoryAs
<Result
*>(
11226 c
.pointer_shm_id
, c
.pointer_shm_offset
, Result::ComputeSize(1));
11228 return error::kOutOfBounds
;
11230 // Check that the client initialized the result.
11231 if (result
->size
!= 0) {
11232 return error::kInvalidArguments
;
11234 if (!validators_
->vertex_pointer
.IsValid(pname
)) {
11235 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11236 "glGetVertexAttribPointerv", pname
, "pname");
11237 return error::kNoError
;
11239 if (index
>= group_
->max_vertex_attribs()) {
11240 LOCAL_SET_GL_ERROR(
11241 GL_INVALID_VALUE
, "glGetVertexAttribPointerv", "index out of range.");
11242 return error::kNoError
;
11244 result
->SetNumResults(1);
11245 *result
->GetData() =
11246 state_
.vertex_attrib_manager
->GetVertexAttrib(index
)->offset();
11247 return error::kNoError
;
11251 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id
,
11252 GLint fake_location
,
11255 error::Error
* error
,
11256 GLint
* real_location
,
11257 GLuint
* service_id
,
11258 SizedResult
<T
>** result_pointer
,
11259 GLenum
* result_type
,
11260 GLsizei
* result_size
) {
11262 DCHECK(service_id
);
11263 DCHECK(result_pointer
);
11264 DCHECK(result_type
);
11265 DCHECK(result_size
);
11266 DCHECK(real_location
);
11267 *error
= error::kNoError
;
11268 // Make sure we have enough room for the result on failure.
11269 SizedResult
<T
>* result
;
11270 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
11271 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(0));
11273 *error
= error::kOutOfBounds
;
11276 *result_pointer
= result
;
11277 // Set the result size to 0 so the client does not have to check for success.
11278 result
->SetNumResults(0);
11279 Program
* program
= GetProgramInfoNotShader(program_id
, "glGetUniform");
11283 if (!program
->IsValid()) {
11284 // Program was not linked successfully. (ie, glLinkProgram)
11285 LOCAL_SET_GL_ERROR(
11286 GL_INVALID_OPERATION
, "glGetUniform", "program not linked");
11289 *service_id
= program
->service_id();
11290 GLint array_index
= -1;
11291 const Program::UniformInfo
* uniform_info
=
11292 program
->GetUniformInfoByFakeLocation(
11293 fake_location
, real_location
, &array_index
);
11294 if (!uniform_info
) {
11295 // No such location.
11296 LOCAL_SET_GL_ERROR(
11297 GL_INVALID_OPERATION
, "glGetUniform", "unknown location");
11300 GLenum type
= uniform_info
->type
;
11301 uint32 num_elements
= GLES2Util::GetElementCountForUniformType(type
);
11302 if (num_elements
== 0) {
11303 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glGetUniform", "unknown type");
11306 result
= GetSharedMemoryAs
<SizedResult
<T
>*>(
11307 shm_id
, shm_offset
, SizedResult
<T
>::ComputeSize(num_elements
));
11309 *error
= error::kOutOfBounds
;
11312 result
->SetNumResults(num_elements
);
11313 *result_size
= num_elements
* sizeof(T
);
11314 *result_type
= type
;
11318 error::Error
GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size
,
11319 const void* cmd_data
) {
11320 const gles2::cmds::GetUniformiv
& c
=
11321 *static_cast<const gles2::cmds::GetUniformiv
*>(cmd_data
);
11322 GLuint program
= c
.program
;
11323 GLint fake_location
= c
.location
;
11325 GLenum result_type
;
11326 GLsizei result_size
;
11327 GLint real_location
= -1;
11329 cmds::GetUniformiv::Result
* result
;
11330 if (GetUniformSetup
<GLint
>(program
, fake_location
, c
.params_shm_id
,
11331 c
.params_shm_offset
, &error
, &real_location
,
11332 &service_id
, &result
, &result_type
,
11335 service_id
, real_location
, result
->GetData());
11340 error::Error
GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size
,
11341 const void* cmd_data
) {
11342 if (!unsafe_es3_apis_enabled())
11343 return error::kUnknownCommand
;
11345 const gles2::cmds::GetUniformuiv
& c
=
11346 *static_cast<const gles2::cmds::GetUniformuiv
*>(cmd_data
);
11347 GLuint program
= c
.program
;
11348 GLint fake_location
= c
.location
;
11350 GLenum result_type
;
11351 GLsizei result_size
;
11352 GLint real_location
= -1;
11354 cmds::GetUniformuiv::Result
* result
;
11355 if (GetUniformSetup
<GLuint
>(program
, fake_location
, c
.params_shm_id
,
11356 c
.params_shm_offset
, &error
, &real_location
,
11357 &service_id
, &result
, &result_type
,
11360 service_id
, real_location
, result
->GetData());
11365 error::Error
GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size
,
11366 const void* cmd_data
) {
11367 const gles2::cmds::GetUniformfv
& c
=
11368 *static_cast<const gles2::cmds::GetUniformfv
*>(cmd_data
);
11369 GLuint program
= c
.program
;
11370 GLint fake_location
= c
.location
;
11372 GLint real_location
= -1;
11374 cmds::GetUniformfv::Result
* result
;
11375 GLenum result_type
;
11376 GLsizei result_size
;
11377 if (GetUniformSetup
<GLfloat
>(program
, fake_location
, c
.params_shm_id
,
11378 c
.params_shm_offset
, &error
, &real_location
,
11379 &service_id
, &result
, &result_type
,
11381 if (result_type
== GL_BOOL
|| result_type
== GL_BOOL_VEC2
||
11382 result_type
== GL_BOOL_VEC3
|| result_type
== GL_BOOL_VEC4
) {
11383 GLsizei num_values
= result_size
/ sizeof(GLfloat
);
11384 scoped_ptr
<GLint
[]> temp(new GLint
[num_values
]);
11385 glGetUniformiv(service_id
, real_location
, temp
.get());
11386 GLfloat
* dst
= result
->GetData();
11387 for (GLsizei ii
= 0; ii
< num_values
; ++ii
) {
11388 dst
[ii
] = (temp
[ii
] != 0);
11391 glGetUniformfv(service_id
, real_location
, result
->GetData());
11397 error::Error
GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
11398 uint32 immediate_data_size
,
11399 const void* cmd_data
) {
11400 const gles2::cmds::GetShaderPrecisionFormat
& c
=
11401 *static_cast<const gles2::cmds::GetShaderPrecisionFormat
*>(cmd_data
);
11402 GLenum shader_type
= static_cast<GLenum
>(c
.shadertype
);
11403 GLenum precision_type
= static_cast<GLenum
>(c
.precisiontype
);
11404 typedef cmds::GetShaderPrecisionFormat::Result Result
;
11405 Result
* result
= GetSharedMemoryAs
<Result
*>(
11406 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11408 return error::kOutOfBounds
;
11410 // Check that the client initialized the result.
11411 if (result
->success
!= 0) {
11412 return error::kInvalidArguments
;
11414 if (!validators_
->shader_type
.IsValid(shader_type
)) {
11415 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11416 "glGetShaderPrecisionFormat", shader_type
, "shader_type");
11417 return error::kNoError
;
11419 if (!validators_
->shader_precision
.IsValid(precision_type
)) {
11420 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11421 "glGetShaderPrecisionFormat", precision_type
, "precision_type");
11422 return error::kNoError
;
11425 result
->success
= 1; // true
11427 GLint range
[2] = { 0, 0 };
11428 GLint precision
= 0;
11429 GetShaderPrecisionFormatImpl(shader_type
, precision_type
, range
, &precision
);
11431 result
->min_range
= range
[0];
11432 result
->max_range
= range
[1];
11433 result
->precision
= precision
;
11435 return error::kNoError
;
11438 error::Error
GLES2DecoderImpl::HandleGetAttachedShaders(
11439 uint32 immediate_data_size
,
11440 const void* cmd_data
) {
11441 const gles2::cmds::GetAttachedShaders
& c
=
11442 *static_cast<const gles2::cmds::GetAttachedShaders
*>(cmd_data
);
11443 uint32 result_size
= c
.result_size
;
11444 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11445 Program
* program
= GetProgramInfoNotShader(
11446 program_id
, "glGetAttachedShaders");
11448 return error::kNoError
;
11450 typedef cmds::GetAttachedShaders::Result Result
;
11451 uint32 max_count
= Result::ComputeMaxResults(result_size
);
11452 Result
* result
= GetSharedMemoryAs
<Result
*>(
11453 c
.result_shm_id
, c
.result_shm_offset
, Result::ComputeSize(max_count
));
11455 return error::kOutOfBounds
;
11457 // Check that the client initialized the result.
11458 if (result
->size
!= 0) {
11459 return error::kInvalidArguments
;
11462 glGetAttachedShaders(
11463 program
->service_id(), max_count
, &count
, result
->GetData());
11464 for (GLsizei ii
= 0; ii
< count
; ++ii
) {
11465 if (!shader_manager()->GetClientId(result
->GetData()[ii
],
11466 &result
->GetData()[ii
])) {
11468 return error::kGenericError
;
11471 result
->SetNumResults(count
);
11472 return error::kNoError
;
11475 error::Error
GLES2DecoderImpl::HandleGetActiveUniform(
11476 uint32 immediate_data_size
,
11477 const void* cmd_data
) {
11478 const gles2::cmds::GetActiveUniform
& c
=
11479 *static_cast<const gles2::cmds::GetActiveUniform
*>(cmd_data
);
11480 GLuint program_id
= c
.program
;
11481 GLuint index
= c
.index
;
11482 uint32 name_bucket_id
= c
.name_bucket_id
;
11483 typedef cmds::GetActiveUniform::Result Result
;
11484 Result
* result
= GetSharedMemoryAs
<Result
*>(
11485 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11487 return error::kOutOfBounds
;
11489 // Check that the client initialized the result.
11490 if (result
->success
!= 0) {
11491 return error::kInvalidArguments
;
11493 Program
* program
= GetProgramInfoNotShader(
11494 program_id
, "glGetActiveUniform");
11496 return error::kNoError
;
11498 const Program::UniformInfo
* uniform_info
=
11499 program
->GetUniformInfo(index
);
11500 if (!uniform_info
) {
11501 LOCAL_SET_GL_ERROR(
11502 GL_INVALID_VALUE
, "glGetActiveUniform", "index out of range");
11503 return error::kNoError
;
11505 result
->success
= 1; // true.
11506 result
->size
= uniform_info
->size
;
11507 result
->type
= uniform_info
->type
;
11508 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11509 bucket
->SetFromString(uniform_info
->name
.c_str());
11510 return error::kNoError
;
11513 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
11514 uint32 immediate_data_size
, const void* cmd_data
) {
11515 if (!unsafe_es3_apis_enabled())
11516 return error::kUnknownCommand
;
11517 const gles2::cmds::GetActiveUniformBlockiv
& c
=
11518 *static_cast<const gles2::cmds::GetActiveUniformBlockiv
*>(cmd_data
);
11519 GLuint program_id
= c
.program
;
11520 GLuint index
= static_cast<GLuint
>(c
.index
);
11521 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11522 Program
* program
= GetProgramInfoNotShader(
11523 program_id
, "glGetActiveUniformBlockiv");
11525 return error::kNoError
;
11527 GLuint service_id
= program
->service_id();
11528 GLint link_status
= GL_FALSE
;
11529 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11530 if (link_status
!= GL_TRUE
) {
11531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11532 "glGetActiveActiveUniformBlockiv", "program not linked");
11533 return error::kNoError
;
11535 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
11536 GLsizei num_values
= 1;
11537 if (pname
== GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
) {
11539 glGetActiveUniformBlockiv(
11540 service_id
, index
, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS
, &num
);
11541 GLenum error
= glGetError();
11542 if (error
!= GL_NO_ERROR
) {
11543 // Assume this will the same error if calling with pname.
11544 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11545 return error::kNoError
;
11547 num_values
= static_cast<GLsizei
>(num
);
11549 typedef cmds::GetActiveUniformBlockiv::Result Result
;
11550 Result
* result
= GetSharedMemoryAs
<Result
*>(
11551 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
11552 GLint
* params
= result
? result
->GetData() : NULL
;
11553 if (params
== NULL
) {
11554 return error::kOutOfBounds
;
11556 // Check that the client initialized the result.
11557 if (result
->size
!= 0) {
11558 return error::kInvalidArguments
;
11560 glGetActiveUniformBlockiv(service_id
, index
, pname
, params
);
11561 GLenum error
= glGetError();
11562 if (error
== GL_NO_ERROR
) {
11563 result
->SetNumResults(num_values
);
11565 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformBlockiv", "");
11567 return error::kNoError
;
11570 error::Error
GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11571 uint32 immediate_data_size
, const void* cmd_data
) {
11572 if (!unsafe_es3_apis_enabled())
11573 return error::kUnknownCommand
;
11574 const gles2::cmds::GetActiveUniformBlockName
& c
=
11575 *static_cast<const gles2::cmds::GetActiveUniformBlockName
*>(cmd_data
);
11576 GLuint program_id
= c
.program
;
11577 GLuint index
= c
.index
;
11578 uint32 name_bucket_id
= c
.name_bucket_id
;
11579 typedef cmds::GetActiveUniformBlockName::Result Result
;
11580 Result
* result
= GetSharedMemoryAs
<Result
*>(
11581 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11583 return error::kOutOfBounds
;
11585 // Check that the client initialized the result.
11586 if (*result
!= 0) {
11587 return error::kInvalidArguments
;
11589 Program
* program
= GetProgramInfoNotShader(
11590 program_id
, "glGetActiveUniformBlockName");
11592 return error::kNoError
;
11594 GLuint service_id
= program
->service_id();
11595 GLint link_status
= GL_FALSE
;
11596 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11597 if (link_status
!= GL_TRUE
) {
11598 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11599 "glGetActiveActiveUniformBlockName", "program not linked");
11600 return error::kNoError
;
11602 GLint max_length
= 0;
11604 service_id
, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
, &max_length
);
11605 // Increase one so &buffer[0] is always valid.
11606 GLsizei buf_size
= static_cast<GLsizei
>(max_length
) + 1;
11607 std::vector
<char> buffer(buf_size
);
11608 GLsizei length
= 0;
11609 glGetActiveUniformBlockName(
11610 service_id
, index
, buf_size
, &length
, &buffer
[0]);
11613 return error::kNoError
;
11616 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11617 DCHECK_GT(buf_size
, length
);
11618 DCHECK_EQ(0, buffer
[length
]);
11619 bucket
->SetFromString(&buffer
[0]);
11620 return error::kNoError
;
11623 error::Error
GLES2DecoderImpl::HandleGetActiveUniformsiv(
11624 uint32 immediate_data_size
, const void* cmd_data
) {
11625 if (!unsafe_es3_apis_enabled())
11626 return error::kUnknownCommand
;
11627 const gles2::cmds::GetActiveUniformsiv
& c
=
11628 *static_cast<const gles2::cmds::GetActiveUniformsiv
*>(cmd_data
);
11629 GLuint program_id
= c
.program
;
11630 GLenum pname
= static_cast<GLenum
>(c
.pname
);
11631 Bucket
* bucket
= GetBucket(c
.indices_bucket_id
);
11633 return error::kInvalidArguments
;
11635 GLsizei count
= static_cast<GLsizei
>(bucket
->size() / sizeof(GLuint
));
11636 const GLuint
* indices
= bucket
->GetDataAs
<const GLuint
*>(0, bucket
->size());
11637 typedef cmds::GetActiveUniformsiv::Result Result
;
11638 Result
* result
= GetSharedMemoryAs
<Result
*>(
11639 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(count
));
11640 GLint
* params
= result
? result
->GetData() : NULL
;
11641 if (params
== NULL
) {
11642 return error::kOutOfBounds
;
11644 // Check that the client initialized the result.
11645 if (result
->size
!= 0) {
11646 return error::kInvalidArguments
;
11648 Program
* program
= GetProgramInfoNotShader(
11649 program_id
, "glGetActiveUniformsiv");
11651 return error::kNoError
;
11653 GLuint service_id
= program
->service_id();
11654 GLint link_status
= GL_FALSE
;
11655 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
11656 if (link_status
!= GL_TRUE
) {
11657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
11658 "glGetActiveUniformsiv", "program not linked");
11659 return error::kNoError
;
11661 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11662 glGetActiveUniformsiv(service_id
, count
, indices
, pname
, params
);
11663 GLenum error
= glGetError();
11664 if (error
== GL_NO_ERROR
) {
11665 result
->SetNumResults(count
);
11667 LOCAL_SET_GL_ERROR(error
, "GetActiveUniformsiv", "");
11669 return error::kNoError
;
11672 error::Error
GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size
,
11673 const void* cmd_data
) {
11674 const gles2::cmds::GetActiveAttrib
& c
=
11675 *static_cast<const gles2::cmds::GetActiveAttrib
*>(cmd_data
);
11676 GLuint program_id
= c
.program
;
11677 GLuint index
= c
.index
;
11678 uint32 name_bucket_id
= c
.name_bucket_id
;
11679 typedef cmds::GetActiveAttrib::Result Result
;
11680 Result
* result
= GetSharedMemoryAs
<Result
*>(
11681 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11683 return error::kOutOfBounds
;
11685 // Check that the client initialized the result.
11686 if (result
->success
!= 0) {
11687 return error::kInvalidArguments
;
11689 Program
* program
= GetProgramInfoNotShader(
11690 program_id
, "glGetActiveAttrib");
11692 return error::kNoError
;
11694 const Program::VertexAttrib
* attrib_info
=
11695 program
->GetAttribInfo(index
);
11696 if (!attrib_info
) {
11697 LOCAL_SET_GL_ERROR(
11698 GL_INVALID_VALUE
, "glGetActiveAttrib", "index out of range");
11699 return error::kNoError
;
11701 result
->success
= 1; // true.
11702 result
->size
= attrib_info
->size
;
11703 result
->type
= attrib_info
->type
;
11704 Bucket
* bucket
= CreateBucket(name_bucket_id
);
11705 bucket
->SetFromString(attrib_info
->name
.c_str());
11706 return error::kNoError
;
11709 error::Error
GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size
,
11710 const void* cmd_data
) {
11711 #if 1 // No binary shader support.
11712 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glShaderBinary", "not supported");
11713 return error::kNoError
;
11715 GLsizei n
= static_cast<GLsizei
>(c
.n
);
11717 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "n < 0");
11718 return error::kNoError
;
11720 GLsizei length
= static_cast<GLsizei
>(c
.length
);
11722 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "length < 0");
11723 return error::kNoError
;
11726 if (!SafeMultiplyUint32(n
, sizeof(GLuint
), &data_size
)) {
11727 return error::kOutOfBounds
;
11729 const GLuint
* shaders
= GetSharedMemoryAs
<const GLuint
*>(
11730 c
.shaders_shm_id
, c
.shaders_shm_offset
, data_size
);
11731 GLenum binaryformat
= static_cast<GLenum
>(c
.binaryformat
);
11732 const void* binary
= GetSharedMemoryAs
<const void*>(
11733 c
.binary_shm_id
, c
.binary_shm_offset
, length
);
11734 if (shaders
== NULL
|| binary
== NULL
) {
11735 return error::kOutOfBounds
;
11737 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
11738 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
11739 Shader
* shader
= GetShader(shaders
[ii
]);
11741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glShaderBinary", "unknown shader");
11742 return error::kNoError
;
11744 service_ids
[ii
] = shader
->service_id();
11746 // TODO(gman): call glShaderBinary
11747 return error::kNoError
;
11751 void GLES2DecoderImpl::DoSwapBuffers() {
11752 bool is_offscreen
= !!offscreen_target_frame_buffer_
.get();
11754 int this_frame_number
= frame_number_
++;
11755 // TRACE_EVENT for gpu tests:
11756 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11757 TRACE_EVENT_SCOPE_THREAD
,
11758 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11759 "width", (is_offscreen
? offscreen_size_
.width() :
11760 surface_
->GetSize().width()));
11761 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11762 "offscreen", is_offscreen
,
11763 "frame", this_frame_number
);
11765 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11768 ScopedGPUTrace
scoped_gpu_trace(gpu_tracer_
.get(), kTraceDecoder
,
11769 "GLES2Decoder", "SwapBuffer");
11772 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11775 ScopedFrameBufferBinder
binder(this, GetBackbufferServiceId());
11776 gpu_state_tracer_
->TakeSnapshotWithCurrentFramebuffer(
11777 is_offscreen
? offscreen_size_
: surface_
->GetSize());
11780 // If offscreen then don't actually SwapBuffers to the display. Just copy
11781 // the rendered frame to another frame buffer.
11782 if (is_offscreen
) {
11783 TRACE_EVENT2("gpu", "Offscreen",
11784 "width", offscreen_size_
.width(), "height", offscreen_size_
.height());
11785 if (offscreen_size_
!= offscreen_saved_color_texture_
->size()) {
11786 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11787 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11789 if (workarounds().needs_offscreen_buffer_workaround
) {
11790 offscreen_saved_frame_buffer_
->Create();
11794 // Allocate the offscreen saved color texture.
11795 DCHECK(offscreen_saved_color_format_
);
11796 offscreen_saved_color_texture_
->AllocateStorage(
11797 offscreen_size_
, offscreen_saved_color_format_
, false);
11799 offscreen_saved_frame_buffer_
->AttachRenderTexture(
11800 offscreen_saved_color_texture_
.get());
11801 if (offscreen_size_
.width() != 0 && offscreen_size_
.height() != 0) {
11802 if (offscreen_saved_frame_buffer_
->CheckStatus() !=
11803 GL_FRAMEBUFFER_COMPLETE
) {
11804 LOG(ERROR
) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11805 << "because offscreen saved FBO was incomplete.";
11806 MarkContextLost(error::kUnknown
);
11807 group_
->LoseContexts(error::kUnknown
);
11811 // Clear the offscreen color texture.
11812 // TODO(piman): Is this still necessary?
11814 ScopedFrameBufferBinder
binder(this,
11815 offscreen_saved_frame_buffer_
->id());
11816 glClearColor(0, 0, 0, 0);
11817 state_
.SetDeviceColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
11818 state_
.SetDeviceCapabilityState(GL_SCISSOR_TEST
, false);
11819 glClear(GL_COLOR_BUFFER_BIT
);
11820 RestoreClearState();
11824 UpdateParentTextureInfo();
11827 if (offscreen_size_
.width() == 0 || offscreen_size_
.height() == 0)
11829 ScopedGLErrorSuppressor
suppressor(
11830 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11832 if (IsOffscreenBufferMultisampled()) {
11833 // For multisampled buffers, resolve the frame buffer.
11834 ScopedResolvedFrameBufferBinder
binder(this, true, false);
11836 ScopedFrameBufferBinder
binder(this,
11837 offscreen_target_frame_buffer_
->id());
11839 if (offscreen_target_buffer_preserved_
) {
11840 // Copy the target frame buffer to the saved offscreen texture.
11841 offscreen_saved_color_texture_
->Copy(
11842 offscreen_saved_color_texture_
->size(),
11843 offscreen_saved_color_format_
);
11845 // Flip the textures in the parent context via the texture manager.
11846 if (!!offscreen_saved_color_texture_info_
.get())
11847 offscreen_saved_color_texture_info_
->texture()->
11848 SetServiceId(offscreen_target_color_texture_
->id());
11850 offscreen_saved_color_texture_
.swap(offscreen_target_color_texture_
);
11851 offscreen_target_frame_buffer_
->AttachRenderTexture(
11852 offscreen_target_color_texture_
.get());
11855 // Ensure the side effects of the copy are visible to the parent
11856 // context. There is no need to do this for ANGLE because it uses a
11857 // single D3D device for all contexts.
11858 if (!feature_info_
->gl_version_info().is_angle
)
11862 if (surface_
->SwapBuffers() == gfx::SwapResult::SWAP_FAILED
) {
11863 LOG(ERROR
) << "Context lost because SwapBuffers failed.";
11864 if (!CheckResetStatus()) {
11865 MarkContextLost(error::kUnknown
);
11866 group_
->LoseContexts(error::kUnknown
);
11871 // This may be a slow command. Exit command processing to allow for
11872 // context preemption and GPU watchdog checks.
11873 ExitCommandProcessingEarly();
11876 void GLES2DecoderImpl::DoSwapInterval(int interval
) {
11877 context_
->SetSwapInterval(interval
);
11880 error::Error
GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11881 uint32 immediate_data_size
,
11882 const void* cmd_data
) {
11883 const gles2::cmds::EnableFeatureCHROMIUM
& c
=
11884 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM
*>(cmd_data
);
11885 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11886 if (!bucket
|| bucket
->size() == 0) {
11887 return error::kInvalidArguments
;
11889 typedef cmds::EnableFeatureCHROMIUM::Result Result
;
11890 Result
* result
= GetSharedMemoryAs
<Result
*>(
11891 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
11893 return error::kOutOfBounds
;
11895 // Check that the client initialized the result.
11896 if (*result
!= 0) {
11897 return error::kInvalidArguments
;
11899 std::string feature_str
;
11900 if (!bucket
->GetAsString(&feature_str
)) {
11901 return error::kInvalidArguments
;
11904 // TODO(gman): make this some kind of table to function pointer thingy.
11905 if (feature_str
.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11906 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11907 } else if (feature_str
.compare("pepper3d_support_fixed_attribs") == 0) {
11908 buffer_manager()->set_allow_fixed_attribs(true);
11909 // TODO(gman): decide how to remove the need for this const_cast.
11910 // I could make validators_ non const but that seems bad as this is the only
11911 // place it is needed. I could make some special friend class of validators
11912 // just to allow this to set them. That seems silly. I could refactor this
11913 // code to use the extension mechanism or the initialization attributes to
11914 // turn this feature on. Given that the only real point of this is to make
11915 // the conformance tests pass and given that there is lots of real work that
11916 // needs to be done it seems like refactoring for one to one of those
11917 // methods is a very low priority.
11918 const_cast<Validators
*>(validators_
)->vertex_attrib_type
.AddValue(GL_FIXED
);
11920 return error::kNoError
;
11923 *result
= 1; // true.
11924 return error::kNoError
;
11927 error::Error
GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11928 uint32 immediate_data_size
,
11929 const void* cmd_data
) {
11930 const gles2::cmds::GetRequestableExtensionsCHROMIUM
& c
=
11931 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM
*>(
11933 Bucket
* bucket
= CreateBucket(c
.bucket_id
);
11934 scoped_refptr
<FeatureInfo
> info(new FeatureInfo());
11935 info
->Initialize(disallowed_features_
);
11936 bucket
->SetFromString(info
->extensions().c_str());
11937 return error::kNoError
;
11940 error::Error
GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11941 uint32 immediate_data_size
,
11942 const void* cmd_data
) {
11943 const gles2::cmds::RequestExtensionCHROMIUM
& c
=
11944 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM
*>(cmd_data
);
11945 Bucket
* bucket
= GetBucket(c
.bucket_id
);
11946 if (!bucket
|| bucket
->size() == 0) {
11947 return error::kInvalidArguments
;
11949 std::string feature_str
;
11950 if (!bucket
->GetAsString(&feature_str
)) {
11951 return error::kInvalidArguments
;
11954 bool desire_standard_derivatives
= false;
11955 bool desire_frag_depth
= false;
11956 bool desire_draw_buffers
= false;
11957 bool desire_shader_texture_lod
= false;
11958 if (IsWebGLContext()) {
11959 desire_standard_derivatives
=
11960 feature_str
.find("GL_OES_standard_derivatives") != std::string::npos
;
11961 desire_frag_depth
=
11962 feature_str
.find("GL_EXT_frag_depth") != std::string::npos
;
11963 desire_draw_buffers
=
11964 feature_str
.find("GL_EXT_draw_buffers") != std::string::npos
;
11965 desire_shader_texture_lod
=
11966 feature_str
.find("GL_EXT_shader_texture_lod") != std::string::npos
;
11969 if (desire_standard_derivatives
!= derivatives_explicitly_enabled_
||
11970 desire_frag_depth
!= frag_depth_explicitly_enabled_
||
11971 desire_draw_buffers
!= draw_buffers_explicitly_enabled_
||
11972 desire_shader_texture_lod
!= shader_texture_lod_explicitly_enabled_
) {
11973 derivatives_explicitly_enabled_
|= desire_standard_derivatives
;
11974 frag_depth_explicitly_enabled_
|= desire_frag_depth
;
11975 draw_buffers_explicitly_enabled_
|= desire_draw_buffers
;
11976 shader_texture_lod_explicitly_enabled_
|= desire_shader_texture_lod
;
11977 InitializeShaderTranslator();
11980 UpdateCapabilities();
11982 return error::kNoError
;
11985 error::Error
GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11986 uint32 immediate_data_size
,
11987 const void* cmd_data
) {
11988 const gles2::cmds::GetProgramInfoCHROMIUM
& c
=
11989 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM
*>(cmd_data
);
11990 GLuint program_id
= static_cast<GLuint
>(c
.program
);
11991 uint32 bucket_id
= c
.bucket_id
;
11992 Bucket
* bucket
= CreateBucket(bucket_id
);
11993 bucket
->SetSize(sizeof(ProgramInfoHeader
)); // in case we fail.
11994 Program
* program
= NULL
;
11995 program
= GetProgram(program_id
);
11996 if (!program
|| !program
->IsValid()) {
11997 return error::kNoError
;
11999 program
->GetProgramInfo(program_manager(), bucket
);
12000 return error::kNoError
;
12003 error::Error
GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
12004 uint32 immediate_data_size
, const void* cmd_data
) {
12005 if (!unsafe_es3_apis_enabled())
12006 return error::kUnknownCommand
;
12007 const gles2::cmds::GetUniformBlocksCHROMIUM
& c
=
12008 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM
*>(cmd_data
);
12009 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12010 uint32 bucket_id
= c
.bucket_id
;
12011 Bucket
* bucket
= CreateBucket(bucket_id
);
12012 bucket
->SetSize(sizeof(UniformBlocksHeader
)); // in case we fail.
12013 Program
* program
= NULL
;
12014 program
= GetProgram(program_id
);
12015 if (!program
|| !program
->IsValid()) {
12016 return error::kNoError
;
12018 program
->GetUniformBlocks(bucket
);
12019 return error::kNoError
;
12022 error::Error
GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
12023 uint32 immediate_data_size
, const void* cmd_data
) {
12024 if (!unsafe_es3_apis_enabled())
12025 return error::kUnknownCommand
;
12026 const gles2::cmds::GetUniformsES3CHROMIUM
& c
=
12027 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM
*>(cmd_data
);
12028 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12029 uint32 bucket_id
= c
.bucket_id
;
12030 Bucket
* bucket
= CreateBucket(bucket_id
);
12031 bucket
->SetSize(sizeof(UniformsES3Header
)); // in case we fail.
12032 Program
* program
= NULL
;
12033 program
= GetProgram(program_id
);
12034 if (!program
|| !program
->IsValid()) {
12035 return error::kNoError
;
12037 program
->GetUniformsES3(bucket
);
12038 return error::kNoError
;
12041 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
12042 uint32 immediate_data_size
,
12043 const void* cmd_data
) {
12044 if (!unsafe_es3_apis_enabled())
12045 return error::kUnknownCommand
;
12046 const gles2::cmds::GetTransformFeedbackVarying
& c
=
12047 *static_cast<const gles2::cmds::GetTransformFeedbackVarying
*>(cmd_data
);
12048 GLuint program_id
= c
.program
;
12049 GLuint index
= c
.index
;
12050 uint32 name_bucket_id
= c
.name_bucket_id
;
12051 typedef cmds::GetTransformFeedbackVarying::Result Result
;
12052 Result
* result
= GetSharedMemoryAs
<Result
*>(
12053 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
12055 return error::kOutOfBounds
;
12057 // Check that the client initialized the result.
12058 if (result
->success
!= 0) {
12059 return error::kInvalidArguments
;
12061 Program
* program
= GetProgramInfoNotShader(
12062 program_id
, "glGetTransformFeedbackVarying");
12064 return error::kNoError
;
12066 GLuint service_id
= program
->service_id();
12067 GLint link_status
= GL_FALSE
;
12068 glGetProgramiv(service_id
, GL_LINK_STATUS
, &link_status
);
12069 if (link_status
!= GL_TRUE
) {
12070 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12071 "glGetTransformFeedbackVarying", "program not linked");
12072 return error::kNoError
;
12074 GLint max_length
= 0;
12076 service_id
, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
, &max_length
);
12077 max_length
= std::max(1, max_length
);
12078 std::vector
<char> buffer(max_length
);
12079 GLsizei length
= 0;
12082 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
12083 glGetTransformFeedbackVarying(
12084 service_id
, index
, max_length
, &length
, &size
, &type
, &buffer
[0]);
12085 GLenum error
= glGetError();
12086 if (error
!= GL_NO_ERROR
) {
12087 LOCAL_SET_GL_ERROR(error
, "glGetTransformFeedbackVarying", "");
12088 return error::kNoError
;
12090 result
->success
= 1; // true.
12091 result
->size
= static_cast<int32_t>(size
);
12092 result
->type
= static_cast<uint32_t>(type
);
12093 Bucket
* bucket
= CreateBucket(name_bucket_id
);
12094 DCHECK(length
>= 0 && length
< max_length
);
12095 buffer
[length
] = '\0'; // Just to be safe.
12096 bucket
->SetFromString(&buffer
[0]);
12097 return error::kNoError
;
12100 error::Error
GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
12101 uint32 immediate_data_size
, const void* cmd_data
) {
12102 if (!unsafe_es3_apis_enabled())
12103 return error::kUnknownCommand
;
12104 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
& c
=
12105 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM
*>(
12107 GLuint program_id
= static_cast<GLuint
>(c
.program
);
12108 uint32 bucket_id
= c
.bucket_id
;
12109 Bucket
* bucket
= CreateBucket(bucket_id
);
12110 bucket
->SetSize(sizeof(TransformFeedbackVaryingsHeader
)); // in case we fail.
12111 Program
* program
= NULL
;
12112 program
= GetProgram(program_id
);
12113 if (!program
|| !program
->IsValid()) {
12114 return error::kNoError
;
12116 program
->GetTransformFeedbackVaryings(bucket
);
12117 return error::kNoError
;
12120 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReason() {
12121 return context_lost_reason_
;
12124 error::ContextLostReason
GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
12125 GLenum reset_status
) const {
12126 switch (reset_status
) {
12128 // TODO(kbr): improve the precision of the error code in this case.
12129 // Consider delegating to context for error code if MakeCurrent fails.
12130 return error::kUnknown
;
12131 case GL_GUILTY_CONTEXT_RESET_ARB
:
12132 return error::kGuilty
;
12133 case GL_INNOCENT_CONTEXT_RESET_ARB
:
12134 return error::kInnocent
;
12135 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
12136 return error::kUnknown
;
12140 return error::kUnknown
;
12143 bool GLES2DecoderImpl::WasContextLost() const {
12144 return context_was_lost_
;
12147 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
12148 return WasContextLost() && reset_by_robustness_extension_
;
12151 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason
) {
12152 // Only lose the context once.
12153 if (WasContextLost())
12156 // Don't make GL calls in here, the context might not be current.
12157 context_lost_reason_
= reason
;
12158 current_decoder_error_
= error::kLostContext
;
12159 context_was_lost_
= true;
12162 bool GLES2DecoderImpl::CheckResetStatus() {
12163 DCHECK(!WasContextLost());
12164 DCHECK(context_
->IsCurrent(NULL
));
12166 if (IsRobustnessSupported()) {
12167 // If the reason for the call was a GL error, we can try to determine the
12168 // reset status more accurately.
12169 GLenum driver_status
= glGetGraphicsResetStatusARB();
12170 if (driver_status
== GL_NO_ERROR
)
12173 LOG(ERROR
) << (surface_
->IsOffscreen() ? "Offscreen" : "Onscreen")
12174 << " context lost via ARB/EXT_robustness. Reset status = "
12175 << GLES2Util::GetStringEnum(driver_status
);
12177 // Don't pretend we know which client was responsible.
12178 if (workarounds().use_virtualized_gl_contexts
)
12179 driver_status
= GL_UNKNOWN_CONTEXT_RESET_ARB
;
12181 switch (driver_status
) {
12182 case GL_GUILTY_CONTEXT_RESET_ARB
:
12183 MarkContextLost(error::kGuilty
);
12185 case GL_INNOCENT_CONTEXT_RESET_ARB
:
12186 MarkContextLost(error::kInnocent
);
12188 case GL_UNKNOWN_CONTEXT_RESET_ARB
:
12189 MarkContextLost(error::kUnknown
);
12195 reset_by_robustness_extension_
= true;
12201 error::Error
GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
12202 uint32 immediate_data_size
,
12203 const void* cmd_data
) {
12204 return error::kUnknownCommand
;
12207 error::Error
GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
12208 uint32 immediate_data_size
,
12209 const void* cmd_data
) {
12210 const gles2::cmds::WaitSyncPointCHROMIUM
& c
=
12211 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM
*>(cmd_data
);
12212 uint32 sync_point
= c
.sync_point
;
12213 if (wait_sync_point_callback_
.is_null())
12214 return error::kNoError
;
12216 return wait_sync_point_callback_
.Run(sync_point
) ?
12217 error::kNoError
: error::kDeferCommandUntilLater
;
12220 error::Error
GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
12221 uint32 immediate_data_size
,
12222 const void* cmd_data
) {
12223 if (surface_
->DeferDraws())
12224 return error::kDeferCommandUntilLater
;
12225 if (!surface_
->SetBackbufferAllocation(false))
12226 return error::kLostContext
;
12227 backbuffer_needs_clear_bits_
|= GL_COLOR_BUFFER_BIT
;
12228 backbuffer_needs_clear_bits_
|= GL_DEPTH_BUFFER_BIT
;
12229 backbuffer_needs_clear_bits_
|= GL_STENCIL_BUFFER_BIT
;
12230 return error::kNoError
;
12233 bool GLES2DecoderImpl::GenQueriesEXTHelper(
12234 GLsizei n
, const GLuint
* client_ids
) {
12235 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12236 if (query_manager_
->GetQuery(client_ids
[ii
])) {
12240 query_manager_
->GenQueries(n
, client_ids
);
12244 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
12245 GLsizei n
, const GLuint
* client_ids
) {
12246 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12247 query_manager_
->RemoveQuery(client_ids
[ii
]);
12251 bool GLES2DecoderImpl::HasPendingQueries() const {
12252 return query_manager_
.get() && query_manager_
->HavePendingQueries();
12255 void GLES2DecoderImpl::ProcessPendingQueries(bool did_finish
) {
12256 if (!query_manager_
.get())
12258 if (!query_manager_
->ProcessPendingQueries(did_finish
))
12259 current_decoder_error_
= error::kOutOfBounds
;
12262 // Note that if there are no pending readpixels right now,
12263 // this function will call the callback immediately.
12264 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback
) {
12265 if (features().use_async_readpixels
&& !pending_readpixel_fences_
.empty()) {
12266 pending_readpixel_fences_
.back()->callbacks
.push_back(callback
);
12272 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish
) {
12273 // Note: |did_finish| guarantees that the GPU has passed the fence but
12274 // we cannot assume that GLFence::HasCompleted() will return true yet as
12275 // that's not guaranteed by all GLFence implementations.
12276 while (!pending_readpixel_fences_
.empty() &&
12278 pending_readpixel_fences_
.front()->fence
->HasCompleted())) {
12279 std::vector
<base::Closure
> callbacks
=
12280 pending_readpixel_fences_
.front()->callbacks
;
12281 pending_readpixel_fences_
.pop();
12282 for (size_t i
= 0; i
< callbacks
.size(); i
++) {
12283 callbacks
[i
].Run();
12288 bool GLES2DecoderImpl::HasMoreIdleWork() const {
12289 return !pending_readpixel_fences_
.empty() ||
12290 gpu_tracer_
->HasTracesToProcess();
12293 void GLES2DecoderImpl::PerformIdleWork() {
12294 gpu_tracer_
->ProcessTraces();
12295 ProcessPendingReadPixels(false);
12298 error::Error
GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size
,
12299 const void* cmd_data
) {
12300 const gles2::cmds::BeginQueryEXT
& c
=
12301 *static_cast<const gles2::cmds::BeginQueryEXT
*>(cmd_data
);
12302 GLenum target
= static_cast<GLenum
>(c
.target
);
12303 GLuint client_id
= static_cast<GLuint
>(c
.id
);
12304 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12305 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12308 case GL_COMMANDS_ISSUED_CHROMIUM
:
12309 case GL_LATENCY_QUERY_CHROMIUM
:
12310 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
:
12311 case GL_GET_ERROR_QUERY_CHROMIUM
:
12313 case GL_COMMANDS_COMPLETED_CHROMIUM
:
12314 if (!features().chromium_sync_query
) {
12315 LOCAL_SET_GL_ERROR(
12316 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12317 "not enabled for commands completed queries");
12318 return error::kNoError
;
12321 case GL_SAMPLES_PASSED
:
12322 case GL_ANY_SAMPLES_PASSED
:
12323 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE
:
12324 if (!features().occlusion_query_boolean
) {
12325 LOCAL_SET_GL_ERROR(
12326 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12327 "not enabled for occlusion queries");
12328 return error::kNoError
;
12331 case GL_TIME_ELAPSED
:
12332 if (!query_manager_
->GPUTimingAvailable()) {
12333 LOCAL_SET_GL_ERROR(
12334 GL_INVALID_OPERATION
, "glBeginQueryEXT",
12335 "not enabled for timing queries");
12336 return error::kNoError
;
12339 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
:
12340 if (feature_info_
->IsES3Enabled()) {
12345 LOCAL_SET_GL_ERROR(
12346 GL_INVALID_ENUM
, "glBeginQueryEXT",
12347 "unknown query target");
12348 return error::kNoError
;
12351 if (query_manager_
->GetActiveQuery(target
)) {
12352 LOCAL_SET_GL_ERROR(
12353 GL_INVALID_OPERATION
, "glBeginQueryEXT", "query already in progress");
12354 return error::kNoError
;
12357 if (client_id
== 0) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBeginQueryEXT", "id is 0");
12359 return error::kNoError
;
12362 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
12364 if (!query_manager_
->IsValidQuery(client_id
)) {
12365 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12367 "id not made by glGenQueriesEXT");
12368 return error::kNoError
;
12370 query
= query_manager_
->CreateQuery(
12371 target
, client_id
, sync_shm_id
, sync_shm_offset
);
12374 if (query
->target() != target
) {
12375 LOCAL_SET_GL_ERROR(
12376 GL_INVALID_OPERATION
, "glBeginQueryEXT", "target does not match");
12377 return error::kNoError
;
12378 } else if (query
->shm_id() != sync_shm_id
||
12379 query
->shm_offset() != sync_shm_offset
) {
12380 DLOG(ERROR
) << "Shared memory used by query not the same as before";
12381 return error::kInvalidArguments
;
12384 if (!query_manager_
->BeginQuery(query
)) {
12385 return error::kOutOfBounds
;
12388 return error::kNoError
;
12391 error::Error
GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size
,
12392 const void* cmd_data
) {
12393 const gles2::cmds::EndQueryEXT
& c
=
12394 *static_cast<const gles2::cmds::EndQueryEXT
*>(cmd_data
);
12395 GLenum target
= static_cast<GLenum
>(c
.target
);
12396 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
12398 QueryManager::Query
* query
= query_manager_
->GetActiveQuery(target
);
12400 LOCAL_SET_GL_ERROR(
12401 GL_INVALID_OPERATION
, "glEndQueryEXT", "No active query");
12402 return error::kNoError
;
12405 if (!query_manager_
->EndQuery(query
, submit_count
)) {
12406 return error::kOutOfBounds
;
12409 query_manager_
->ProcessPendingTransferQueries();
12411 return error::kNoError
;
12414 error::Error
GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size
,
12415 const void* cmd_data
) {
12416 const gles2::cmds::QueryCounterEXT
& c
=
12417 *static_cast<const gles2::cmds::QueryCounterEXT
*>(cmd_data
);
12418 GLuint client_id
= static_cast<GLuint
>(c
.id
);
12419 GLenum target
= static_cast<GLenum
>(c
.target
);
12420 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12421 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12422 uint32 submit_count
= static_cast<GLuint
>(c
.submit_count
);
12426 if (!query_manager_
->GPUTimingAvailable()) {
12427 LOCAL_SET_GL_ERROR(
12428 GL_INVALID_OPERATION
, "glQueryCounterEXT",
12429 "not enabled for timing queries");
12430 return error::kNoError
;
12434 LOCAL_SET_GL_ERROR(
12435 GL_INVALID_ENUM
, "glQueryCounterEXT",
12436 "unknown query target");
12437 return error::kNoError
;
12440 QueryManager::Query
* query
= query_manager_
->GetQuery(client_id
);
12442 if (!query_manager_
->IsValidQuery(client_id
)) {
12443 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12444 "glQueryCounterEXT",
12445 "id not made by glGenQueriesEXT");
12446 return error::kNoError
;
12448 query
= query_manager_
->CreateQuery(
12449 target
, client_id
, sync_shm_id
, sync_shm_offset
);
12451 if (!query_manager_
->QueryCounter(query
, submit_count
)) {
12452 return error::kOutOfBounds
;
12455 return error::kNoError
;
12458 error::Error
GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
12459 uint32 immediate_data_size
, const void* cmd_data
) {
12460 const gles2::cmds::SetDisjointValueSyncCHROMIUM
& c
=
12461 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM
*>(cmd_data
);
12462 int32 sync_shm_id
= static_cast<int32
>(c
.sync_data_shm_id
);
12463 uint32 sync_shm_offset
= static_cast<uint32
>(c
.sync_data_shm_offset
);
12465 query_manager_
->SetDisjointSync(sync_shm_id
, sync_shm_offset
);
12466 return error::kNoError
;
12469 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
12470 GLsizei n
, const GLuint
* client_ids
) {
12471 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12472 if (GetVertexAttribManager(client_ids
[ii
])) {
12477 if (!features().native_vertex_array_object
) {
12479 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12480 CreateVertexAttribManager(client_ids
[ii
], 0, true);
12483 scoped_ptr
<GLuint
[]> service_ids(new GLuint
[n
]);
12485 glGenVertexArraysOES(n
, service_ids
.get());
12486 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12487 CreateVertexAttribManager(client_ids
[ii
], service_ids
[ii
], true);
12494 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
12495 GLsizei n
, const GLuint
* client_ids
) {
12496 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
12497 VertexAttribManager
* vao
=
12498 GetVertexAttribManager(client_ids
[ii
]);
12499 if (vao
&& !vao
->IsDeleted()) {
12500 if (state_
.vertex_attrib_manager
.get() == vao
) {
12501 DoBindVertexArrayOES(0);
12503 RemoveVertexAttribManager(client_ids
[ii
]);
12508 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id
) {
12509 VertexAttribManager
* vao
= NULL
;
12510 if (client_id
!= 0) {
12511 vao
= GetVertexAttribManager(client_id
);
12513 // Unlike most Bind* methods, the spec explicitly states that VertexArray
12514 // only allows names that have been previously generated. As such, we do
12515 // not generate new names here.
12516 LOCAL_SET_GL_ERROR(
12517 GL_INVALID_OPERATION
,
12518 "glBindVertexArrayOES", "bad vertex array id.");
12519 current_decoder_error_
= error::kNoError
;
12523 vao
= state_
.default_vertex_attrib_manager
.get();
12526 // Only set the VAO state if it's changed
12527 if (state_
.vertex_attrib_manager
.get() != vao
) {
12528 state_
.vertex_attrib_manager
= vao
;
12529 if (!features().native_vertex_array_object
) {
12530 EmulateVertexArrayState();
12532 GLuint service_id
= vao
->service_id();
12533 glBindVertexArrayOES(service_id
);
12538 // Used when OES_vertex_array_object isn't natively supported
12539 void GLES2DecoderImpl::EmulateVertexArrayState() {
12540 // Setup the Vertex attribute state
12541 for (uint32 vv
= 0; vv
< group_
->max_vertex_attribs(); ++vv
) {
12542 RestoreStateForAttrib(vv
, true);
12545 // Setup the element buffer
12546 Buffer
* element_array_buffer
=
12547 state_
.vertex_attrib_manager
->element_array_buffer();
12548 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
,
12549 element_array_buffer
? element_array_buffer
->service_id() : 0);
12552 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id
) {
12553 const VertexAttribManager
* vao
=
12554 GetVertexAttribManager(client_id
);
12555 return vao
&& vao
->IsValid() && !vao
->IsDeleted();
12558 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id
) {
12559 GLuint service_id
= 0;
12560 return path_manager()->GetPath(client_id
, &service_id
) &&
12561 glIsPathNV(service_id
) == GL_TRUE
;
12564 #if defined(OS_MACOSX)
12565 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id
) {
12566 TextureToIOSurfaceMap::iterator it
= texture_to_io_surface_map_
.find(
12568 if (it
!= texture_to_io_surface_map_
.end()) {
12569 // Found a previous IOSurface bound to this texture; release it.
12570 IOSurfaceRef surface
= it
->second
;
12571 CFRelease(surface
);
12572 texture_to_io_surface_map_
.erase(it
);
12577 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12578 GLenum target
, GLsizei width
, GLsizei height
,
12579 GLuint io_surface_id
, GLuint plane
) {
12580 #if defined(OS_MACOSX)
12581 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL
) {
12582 LOCAL_SET_GL_ERROR(
12583 GL_INVALID_OPERATION
,
12584 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12588 if (target
!= GL_TEXTURE_RECTANGLE_ARB
) {
12589 // This might be supported in the future, and if we could require
12590 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12591 // could delete a lot of code. For now, perform strict validation so we
12592 // know what's going on.
12593 LOCAL_SET_GL_ERROR(
12594 GL_INVALID_OPERATION
,
12595 "glTexImageIOSurface2DCHROMIUM",
12596 "requires TEXTURE_RECTANGLE_ARB target");
12600 // Default target might be conceptually valid, but disallow it to avoid
12602 TextureRef
* texture_ref
=
12603 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
12604 if (!texture_ref
) {
12605 LOCAL_SET_GL_ERROR(
12606 GL_INVALID_OPERATION
,
12607 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12611 // Look up the new IOSurface. Note that because of asynchrony
12612 // between processes this might fail; during live resizing the
12613 // plugin process might allocate and release an IOSurface before
12614 // this process gets a chance to look it up. Hold on to any old
12615 // IOSurface in this case.
12616 IOSurfaceRef surface
= IOSurfaceLookup(io_surface_id
);
12618 LOCAL_SET_GL_ERROR(
12619 GL_INVALID_OPERATION
,
12620 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12624 // Release any IOSurface previously bound to this texture.
12625 ReleaseIOSurfaceForTexture(texture_ref
->service_id());
12627 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12628 texture_to_io_surface_map_
.insert(
12629 std::make_pair(texture_ref
->service_id(), surface
));
12631 CGLContextObj context
=
12632 static_cast<CGLContextObj
>(context_
->GetHandle());
12634 CGLError err
= CGLTexImageIOSurface2D(
12641 GL_UNSIGNED_INT_8_8_8_8_REV
,
12645 if (err
!= kCGLNoError
) {
12646 LOCAL_SET_GL_ERROR(
12647 GL_INVALID_OPERATION
,
12648 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12652 texture_manager()->SetLevelInfo(
12653 texture_ref
, target
, 0, GL_RGBA
, width
, height
, 1, 0, GL_BGRA
,
12654 GL_UNSIGNED_INT_8_8_8_8_REV
, gfx::Rect(width
, height
));
12657 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
12658 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12662 static GLenum
ExtractFormatFromStorageFormat(GLenum internalformat
) {
12663 switch (internalformat
) {
12675 return GL_RED_INTEGER
;
12687 return GL_RG_INTEGER
;
12688 case GL_ATC_RGB_AMD
:
12689 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG
:
12690 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
:
12691 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
12692 case GL_ETC1_RGB8_OES
:
12694 case GL_R11F_G11F_B10F
:
12696 case GL_RGB8_SNORM
:
12707 return GL_RGB_INTEGER
;
12708 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD
:
12709 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
:
12710 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
:
12711 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
:
12712 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
12713 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
12714 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
12716 case GL_SRGB8_ALPHA8
:
12717 case GL_RGBA8_SNORM
:
12726 case GL_RGB10_A2UI
:
12731 return GL_RGBA_INTEGER
;
12732 case GL_DEPTH_COMPONENT16
:
12733 case GL_DEPTH_COMPONENT24
:
12734 case GL_DEPTH_COMPONENT32F
:
12735 return GL_DEPTH_COMPONENT
;
12736 case GL_DEPTH24_STENCIL8
:
12737 case GL_DEPTH32F_STENCIL8
:
12738 return GL_DEPTH_STENCIL
;
12739 case GL_LUMINANCE8_ALPHA8_EXT
:
12740 return GL_LUMINANCE_ALPHA
;
12741 case GL_LUMINANCE8_EXT
:
12742 return GL_LUMINANCE
;
12743 case GL_ALPHA8_EXT
:
12745 case GL_ALPHA32F_EXT
:
12747 case GL_LUMINANCE32F_EXT
:
12748 return GL_LUMINANCE
;
12749 case GL_LUMINANCE_ALPHA32F_EXT
:
12750 return GL_LUMINANCE_ALPHA
;
12751 case GL_ALPHA16F_EXT
:
12753 case GL_LUMINANCE16F_EXT
:
12754 return GL_LUMINANCE
;
12755 case GL_LUMINANCE_ALPHA16F_EXT
:
12756 return GL_LUMINANCE_ALPHA
;
12758 return GL_BGRA_EXT
;
12764 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12765 const char* function_name
,
12767 TextureRef
* source_texture_ref
,
12768 TextureRef
* dest_texture_ref
,
12769 GLenum dest_internal_format
) {
12770 if (!source_texture_ref
|| !dest_texture_ref
) {
12771 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12775 if (GL_TEXTURE_2D
!= target
) {
12776 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12777 "invalid texture target");
12781 Texture
* source_texture
= source_texture_ref
->texture();
12782 Texture
* dest_texture
= dest_texture_ref
->texture();
12783 if (source_texture
== dest_texture
) {
12784 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12785 "source and destination textures are the same");
12789 if (dest_texture
->target() != GL_TEXTURE_2D
||
12790 (source_texture
->target() != GL_TEXTURE_2D
&&
12791 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12792 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12793 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12794 "invalid texture target binding");
12798 GLenum source_type
= 0;
12799 GLenum source_internal_format
= 0;
12800 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12801 &source_internal_format
);
12803 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12804 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12805 // renderable on some platforms.
12806 bool valid_dest_format
= dest_internal_format
== GL_RGB
||
12807 dest_internal_format
== GL_RGBA
||
12808 dest_internal_format
== GL_BGRA_EXT
;
12809 bool valid_source_format
=
12810 source_internal_format
== GL_R8
|| source_internal_format
== GL_ALPHA
||
12811 source_internal_format
== GL_RGB
|| source_internal_format
== GL_RGBA
||
12812 source_internal_format
== GL_LUMINANCE
||
12813 source_internal_format
== GL_LUMINANCE_ALPHA
||
12814 source_internal_format
== GL_BGRA_EXT
||
12815 source_internal_format
== GL_RGB_YCBCR_422_CHROMIUM
;
12816 if (!valid_source_format
|| !valid_dest_format
) {
12817 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12818 "invalid internal format");
12824 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12825 const char* function_name
,
12827 TextureRef
* source_texture_ref
,
12828 TextureRef
* dest_texture_ref
) {
12829 if (!source_texture_ref
|| !dest_texture_ref
) {
12830 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
, "unknown texture id");
12834 if (GL_TEXTURE_2D
!= target
) {
12835 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12836 "invalid texture target");
12840 Texture
* source_texture
= source_texture_ref
->texture();
12841 Texture
* dest_texture
= dest_texture_ref
->texture();
12842 if (source_texture
== dest_texture
) {
12843 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12844 "source and destination textures are the same");
12848 if (dest_texture
->target() != GL_TEXTURE_2D
||
12849 (source_texture
->target() != GL_TEXTURE_2D
&&
12850 source_texture
->target() != GL_TEXTURE_RECTANGLE_ARB
&&
12851 source_texture
->target() != GL_TEXTURE_EXTERNAL_OES
)) {
12852 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, function_name
,
12853 "invalid texture target binding");
12857 GLenum source_type
= 0;
12858 GLenum source_internal_format
= 0;
12859 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
12860 &source_internal_format
);
12862 bool valid_format
=
12863 source_internal_format
== GL_ATC_RGB_AMD
||
12864 source_internal_format
== GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD
||
12865 source_internal_format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
12866 source_internal_format
== GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
||
12867 source_internal_format
== GL_ETC1_RGB8_OES
;
12869 if (!valid_format
) {
12870 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, function_name
,
12871 "invalid internal format");
12878 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12882 GLenum internal_format
,
12884 GLboolean unpack_flip_y
,
12885 GLboolean unpack_premultiply_alpha
,
12886 GLboolean unpack_unmultiply_alpha
) {
12887 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12889 TextureRef
* source_texture_ref
= GetTexture(source_id
);
12890 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
12891 Texture
* source_texture
= source_texture_ref
->texture();
12892 Texture
* dest_texture
= dest_texture_ref
->texture();
12893 int source_width
= 0;
12894 int source_height
= 0;
12895 gfx::GLImage
* image
=
12896 source_texture
->GetLevelImage(source_texture
->target(), 0);
12898 gfx::Size size
= image
->GetSize();
12899 source_width
= size
.width();
12900 source_height
= size
.height();
12901 if (source_width
<= 0 || source_height
<= 0) {
12902 LOCAL_SET_GL_ERROR(
12904 "glCopyTextureChromium", "invalid image size");
12908 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
12909 &source_width
, &source_height
, nullptr)) {
12910 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
12911 "glCopyTextureChromium",
12912 "source texture has no level 0");
12916 // Check that this type of texture is allowed.
12917 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
12918 source_width
, source_height
, 1)) {
12919 LOCAL_SET_GL_ERROR(
12920 GL_INVALID_VALUE
, "glCopyTextureCHROMIUM", "Bad dimensions");
12925 GLenum source_type
= 0;
12926 GLenum source_internal_format
= 0;
12927 source_texture
->GetLevelType(
12928 source_texture
->target(), 0, &source_type
, &source_internal_format
);
12930 if (dest_texture
->IsImmutable()) {
12931 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopyTextureCHROMIUM",
12932 "texture is immutable");
12936 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target
,
12937 source_texture_ref
, dest_texture_ref
,
12938 internal_format
)) {
12942 // Clear the source texture if necessary.
12943 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
12944 source_texture
->target(), 0)) {
12945 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopyTextureCHROMIUM",
12946 "dimensions too big");
12950 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12951 // needed because it takes 10s of milliseconds to initialize.
12952 if (!copy_texture_CHROMIUM_
.get()) {
12953 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12954 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
12955 copy_texture_CHROMIUM_
->Initialize(this);
12956 RestoreCurrentFramebufferBindings();
12957 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
12961 GLenum dest_type_previous
= dest_type
;
12962 GLenum dest_internal_format
= internal_format
;
12963 int dest_width
= 0;
12964 int dest_height
= 0;
12965 bool dest_level_defined
= dest_texture
->GetLevelSize(
12966 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
12968 if (dest_level_defined
) {
12969 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type_previous
,
12970 &dest_internal_format
);
12973 // Resize the destination texture to the dimensions of the source texture.
12974 if (!dest_level_defined
|| dest_width
!= source_width
||
12975 dest_height
!= source_height
||
12976 dest_internal_format
!= internal_format
||
12977 dest_type_previous
!= dest_type
) {
12978 // Ensure that the glTexImage2D succeeds.
12979 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12980 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
12981 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format
, source_width
, source_height
,
12982 0, internal_format
, dest_type
, NULL
);
12983 GLenum error
= LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12984 if (error
!= GL_NO_ERROR
) {
12985 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
12989 texture_manager()->SetLevelInfo(
12990 dest_texture_ref
, GL_TEXTURE_2D
, 0, internal_format
, source_width
,
12991 source_height
, 1, 0, internal_format
, dest_type
,
12992 gfx::Rect(source_width
, source_height
));
12994 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
12998 ScopedModifyPixels
modify(dest_texture_ref
);
13000 // Try using GLImage::CopyTexSubImage when possible.
13001 bool unpack_premultiply_alpha_change
=
13002 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
13003 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
13004 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13005 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
13006 gfx::Rect(0, 0, source_width
, source_height
))) {
13011 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13013 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13014 // before presenting.
13015 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
13016 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13017 // instead of using kIdentityMatrix crbug.com/226218.
13018 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
13019 this, source_texture
->target(), source_texture
->service_id(),
13020 dest_texture
->service_id(), source_width
, source_height
,
13021 unpack_flip_y
== GL_TRUE
,
13022 unpack_premultiply_alpha
== GL_TRUE
,
13023 unpack_unmultiply_alpha
== GL_TRUE
,
13026 copy_texture_CHROMIUM_
->DoCopyTexture(
13027 this, source_texture
->target(), source_texture
->service_id(),
13028 source_internal_format
, dest_texture
->service_id(), internal_format
,
13029 source_width
, source_height
,
13030 unpack_flip_y
== GL_TRUE
,
13031 unpack_premultiply_alpha
== GL_TRUE
,
13032 unpack_unmultiply_alpha
== GL_TRUE
);
13035 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13038 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
13048 GLboolean unpack_flip_y
,
13049 GLboolean unpack_premultiply_alpha
,
13050 GLboolean unpack_unmultiply_alpha
) {
13051 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
13053 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13054 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13055 Texture
* source_texture
= source_texture_ref
->texture();
13056 Texture
* dest_texture
= dest_texture_ref
->texture();
13057 int source_width
= 0;
13058 int source_height
= 0;
13059 gfx::GLImage
* image
=
13060 source_texture
->GetLevelImage(source_texture
->target(), 0);
13062 gfx::Size size
= image
->GetSize();
13063 source_width
= size
.width();
13064 source_height
= size
.height();
13065 if (source_width
<= 0 || source_height
<= 0) {
13066 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13067 "invalid image size");
13071 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13072 &source_width
, &source_height
, nullptr)) {
13073 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13074 "source texture has no level 0");
13078 // Check that this type of texture is allowed.
13079 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13080 source_width
, source_height
, 1)) {
13081 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13082 "source texture bad dimensions");
13087 GLenum source_type
= 0;
13088 GLenum source_internal_format
= 0;
13089 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
13090 &source_internal_format
);
13091 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
13092 width
, height
, 1)) {
13093 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13094 "source texture bad dimensions.");
13098 GLenum dest_type
= 0;
13099 GLenum dest_internal_format
= 0;
13100 bool dest_level_defined
= dest_texture
->GetLevelType(
13101 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
13102 if (!dest_level_defined
) {
13103 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glCopySubTextureCHROMIUM",
13104 "destination texture is not defined");
13107 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
13108 yoffset
, 0, width
, height
, 1)) {
13109 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCopySubTextureCHROMIUM",
13110 "destination texture bad dimensions.");
13114 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target
,
13115 source_texture_ref
, dest_texture_ref
,
13116 dest_internal_format
)) {
13120 // Clear the source texture if necessary.
13121 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13122 source_texture
->target(), 0)) {
13123 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
13124 "source texture dimensions too big");
13128 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13129 // needed because it takes 10s of milliseconds to initialize.
13130 if (!copy_texture_CHROMIUM_
.get()) {
13131 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
13132 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13133 copy_texture_CHROMIUM_
->Initialize(this);
13134 RestoreCurrentFramebufferBindings();
13135 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR
)
13139 int dest_width
= 0;
13140 int dest_height
= 0;
13141 bool ok
= dest_texture
->GetLevelSize(
13142 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13144 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
13145 height
!= dest_height
) {
13146 gfx::Rect cleared_rect
;
13147 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
13148 gfx::Rect(xoffset
, yoffset
, width
, height
),
13150 DCHECK_GE(cleared_rect
.size().GetArea(),
13151 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
13152 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
13155 // Otherwise clear part of texture level that is not already cleared.
13156 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
13158 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCopySubTextureCHROMIUM",
13159 "destination texture dimensions too big");
13164 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13168 ScopedModifyPixels
modify(dest_texture_ref
);
13170 // Try using GLImage::CopyTexSubImage when possible.
13171 bool unpack_premultiply_alpha_change
=
13172 (unpack_premultiply_alpha
^ unpack_unmultiply_alpha
) != 0;
13173 if (image
&& !unpack_flip_y
&& !unpack_premultiply_alpha_change
) {
13174 ScopedTextureBinder
binder(
13175 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13176 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
13177 gfx::Rect(x
, y
, width
, height
))) {
13182 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13184 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13185 // crbug.com/226218.
13186 copy_texture_CHROMIUM_
->DoCopySubTexture(
13187 this, source_texture
->target(), source_texture
->service_id(),
13188 source_internal_format
, dest_texture
->service_id(), dest_internal_format
,
13189 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13190 source_width
, source_height
,
13191 unpack_flip_y
== GL_TRUE
,
13192 unpack_premultiply_alpha
== GL_TRUE
,
13193 unpack_unmultiply_alpha
== GL_TRUE
);
13195 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13198 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target
,
13201 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
13203 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13204 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13205 Texture
* source_texture
= source_texture_ref
->texture();
13206 Texture
* dest_texture
= dest_texture_ref
->texture();
13207 int source_width
= 0;
13208 int source_height
= 0;
13209 gfx::GLImage
* image
=
13210 source_texture
->GetLevelImage(source_texture
->target(), 0);
13212 gfx::Size size
= image
->GetSize();
13213 source_width
= size
.width();
13214 source_height
= size
.height();
13215 if (source_width
<= 0 || source_height
<= 0) {
13216 LOCAL_SET_GL_ERROR(
13218 "glCompressedCopyTextureCHROMIUM", "invalid image size");
13222 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13223 &source_width
, &source_height
, nullptr)) {
13224 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
,
13225 "glCompressedCopyTextureCHROMIUM",
13226 "source texture has no level 0");
13230 // Check that this type of texture is allowed.
13231 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13232 source_width
, source_height
, 1)) {
13233 LOCAL_SET_GL_ERROR(
13234 GL_INVALID_VALUE
, "glCompressedCopyTextureCHROMIUM",
13240 GLenum source_type
= 0;
13241 GLenum source_internal_format
= 0;
13242 source_texture
->GetLevelType(
13243 source_texture
->target(), 0, &source_type
, &source_internal_format
);
13245 if (dest_texture
->IsImmutable()) {
13246 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13247 "glCompressedCopyTextureCHROMIUM",
13248 "texture is immutable");
13252 if (!ValidateCompressedCopyTextureCHROMIUM(
13253 "glCompressedCopyTextureCHROMIUM",
13255 source_texture_ref
, dest_texture_ref
)) {
13259 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13260 // needed because it takes 10s of milliseconds to initialize.
13261 if (!copy_texture_CHROMIUM_
.get()) {
13262 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
13263 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13264 copy_texture_CHROMIUM_
->Initialize(this);
13265 RestoreCurrentFramebufferBindings();
13266 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR
)
13270 // Clear the source texture if necessary.
13271 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13272 source_texture
->target(), 0)) {
13273 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopyTextureCHROMIUM",
13274 "dimensions too big");
13278 ScopedTextureBinder
binder(
13279 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13281 ScopedModifyPixels
modify(dest_texture_ref
);
13283 // Try using GLImage::CopyTexImage when possible.
13285 GLenum dest_type
= 0;
13286 GLenum dest_internal_format
= 0;
13287 int dest_width
= 0;
13288 int dest_height
= 0;
13289 bool dest_level_defined
= dest_texture
->GetLevelSize(
13290 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13292 if (dest_level_defined
) {
13293 dest_texture
->GetLevelType(GL_TEXTURE_2D
, 0, &dest_type
,
13294 &dest_internal_format
);
13297 // Resize the destination texture to the dimensions of the source texture.
13298 if (!dest_level_defined
|| dest_width
!= source_width
||
13299 dest_height
!= source_height
||
13300 dest_internal_format
!= source_internal_format
) {
13301 GLsizei source_size
= 0;
13303 bool did_get_size
= GetCompressedTexSizeInBytes(
13304 "glCompressedCopyTextureCHROMIUM", source_width
, source_height
,
13305 1, source_internal_format
, &source_size
);
13306 DCHECK(did_get_size
);
13308 // Ensure that the glCompressedTexImage2D succeeds.
13309 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13310 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, source_internal_format
,
13311 source_width
, source_height
, 0, source_size
,
13313 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13314 if (error
!= GL_NO_ERROR
) {
13315 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
13319 texture_manager()->SetLevelInfo(
13320 dest_texture_ref
, GL_TEXTURE_2D
, 0, source_internal_format
,
13321 source_width
, source_height
, 1, 0, source_internal_format
,
13322 source_type
, gfx::Rect(source_width
, source_height
));
13324 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13328 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(0, 0),
13329 gfx::Rect(0, 0, source_width
, source_height
))) {
13336 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
13338 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13340 // As a fallback, copy into a non-compressed GL_RGBA texture.
13341 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13342 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
, source_height
,
13343 0, GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
13344 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
13345 if (error
!= GL_NO_ERROR
) {
13346 RestoreCurrentTextureBindings(&state_
, GL_TEXTURE_2D
);
13350 texture_manager()->SetLevelInfo(
13351 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, source_width
,
13352 source_height
, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
13353 gfx::Rect(source_width
, source_height
));
13355 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
13356 // before presenting.
13357 if (source_texture
->target() == GL_TEXTURE_EXTERNAL_OES
) {
13358 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
13359 // instead of using kIdentityMatrix crbug.com/226218.
13360 copy_texture_CHROMIUM_
->DoCopyTextureWithTransform(
13361 this, source_texture
->target(), source_texture
->service_id(),
13362 dest_texture
->service_id(), source_width
, source_height
,
13363 false, false, false, kIdentityMatrix
);
13365 copy_texture_CHROMIUM_
->DoCopyTexture(
13366 this, source_texture
->target(), source_texture
->service_id(),
13367 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13368 source_width
, source_height
, false, false, false);
13371 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13374 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target
,
13383 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
13385 TextureRef
* source_texture_ref
= GetTexture(source_id
);
13386 TextureRef
* dest_texture_ref
= GetTexture(dest_id
);
13387 Texture
* source_texture
= source_texture_ref
->texture();
13388 Texture
* dest_texture
= dest_texture_ref
->texture();
13389 int source_width
= 0;
13390 int source_height
= 0;
13391 gfx::GLImage
* image
=
13392 source_texture
->GetLevelImage(source_texture
->target(), 0);
13394 gfx::Size size
= image
->GetSize();
13395 source_width
= size
.width();
13396 source_height
= size
.height();
13397 if (source_width
<= 0 || source_height
<= 0) {
13398 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13399 "invalid image size");
13403 if (!source_texture
->GetLevelSize(source_texture
->target(), 0,
13404 &source_width
, &source_height
, nullptr)) {
13405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13406 "source texture has no level 0");
13410 // Check that this type of texture is allowed.
13411 if (!texture_manager()->ValidForTarget(source_texture
->target(), 0,
13412 source_width
, source_height
, 1)) {
13413 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13414 "source texture bad dimensions");
13419 GLenum source_type
= 0;
13420 GLenum source_internal_format
= 0;
13421 source_texture
->GetLevelType(source_texture
->target(), 0, &source_type
,
13422 &source_internal_format
);
13423 if (!source_texture
->ValidForTexture(source_texture
->target(), 0, x
, y
, 0,
13424 width
, height
, 1)) {
13425 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13426 "source texture bad dimensions.");
13430 GLenum dest_type
= 0;
13431 GLenum dest_internal_format
= 0;
13432 bool dest_level_defined
= dest_texture
->GetLevelType(
13433 dest_texture
->target(), 0, &dest_type
, &dest_internal_format
);
13434 if (!dest_level_defined
) {
13435 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13436 "glCompressedCopySubTextureCHROMIUM",
13437 "destination texture is not defined");
13440 if (!dest_texture
->ValidForTexture(dest_texture
->target(), 0, xoffset
,
13441 yoffset
, 0, width
, height
, 1)) {
13442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "glCompressedCopySubTextureCHROMIUM",
13443 "destination texture bad dimensions.");
13447 if (!ValidateCompressedCopyTextureCHROMIUM(
13448 "glCompressedCopySubTextureCHROMIUM", target
, source_texture_ref
,
13449 dest_texture_ref
)) {
13453 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13454 source_texture
->target(), 0, x
, y
, 0,
13456 source_internal_format
,
13458 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
13459 dest_texture
->target(), 0,
13460 xoffset
, yoffset
, 0, width
, height
, 1,
13461 dest_internal_format
,
13466 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
13467 // needed because it takes 10s of milliseconds to initialize.
13468 if (!copy_texture_CHROMIUM_
.get()) {
13469 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
13470 copy_texture_CHROMIUM_
.reset(new CopyTextureCHROMIUMResourceManager());
13471 copy_texture_CHROMIUM_
->Initialize(this);
13472 RestoreCurrentFramebufferBindings();
13473 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
13479 // Clear the source texture if necessary.
13480 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref
,
13481 source_texture
->target(), 0)) {
13482 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
, "glCompressedCopySubTextureCHROMIUM",
13483 "source texture dimensions too big");
13487 int dest_width
= 0;
13488 int dest_height
= 0;
13489 bool ok
= dest_texture
->GetLevelSize(
13490 GL_TEXTURE_2D
, 0, &dest_width
, &dest_height
, nullptr);
13492 if (xoffset
!= 0 || yoffset
!= 0 || width
!= dest_width
||
13493 height
!= dest_height
) {
13494 gfx::Rect cleared_rect
;
13495 if (CombineAdjacentRects(dest_texture
->GetLevelClearedRect(target
, 0),
13496 gfx::Rect(xoffset
, yoffset
, width
, height
),
13498 DCHECK_GE(cleared_rect
.size().GetArea(),
13499 dest_texture
->GetLevelClearedRect(target
, 0).size().GetArea());
13500 texture_manager()->SetLevelClearedRect(dest_texture_ref
, target
, 0,
13503 // Otherwise clear part of texture level that is not already cleared.
13504 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref
, target
,
13506 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY
,
13507 "glCompressedCopySubTextureCHROMIUM",
13508 "destination texture dimensions too big");
13513 texture_manager()->SetLevelCleared(dest_texture_ref
, GL_TEXTURE_2D
, 0,
13517 ScopedTextureBinder
binder(
13518 &state_
, dest_texture
->service_id(), GL_TEXTURE_2D
);
13520 ScopedModifyPixels
modify(dest_texture_ref
);
13522 // Try using GLImage::CopyTexSubImage when possible.
13524 if (image
->CopyTexSubImage(GL_TEXTURE_2D
, gfx::Point(xoffset
, yoffset
),
13525 gfx::Rect(x
, y
, width
, height
))) {
13532 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
13534 DoWillUseTexImageIfNeeded(source_texture
, source_texture
->target());
13536 // As a fallback, copy into a non-compressed GL_RGBA texture.
13537 if (dest_internal_format
!= GL_RGBA
) {
13538 // To preserve the contents of the original destination texture we must
13539 // first copy the original destination texture to a temporary storage, then
13540 // copy it back to the original destination texture.
13541 GLuint tmp_service_id
;
13542 glGenTextures(1, &tmp_service_id
);
13543 DCHECK_NE(0u, tmp_service_id
);
13545 glBindTexture(GL_TEXTURE_2D
, tmp_service_id
);
13547 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13548 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13549 GL_UNSIGNED_BYTE
, NULL
);
13550 GLenum error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13551 if (error
!= GL_NO_ERROR
)
13554 copy_texture_CHROMIUM_
->DoCopyTexture(
13555 this, dest_texture
->target(), dest_texture
->service_id(),
13556 dest_internal_format
, tmp_service_id
, GL_RGBA
,
13557 dest_width
, dest_height
, false, false, false);
13559 // Redefine destination texture to use RGBA.
13560 glBindTexture(GL_TEXTURE_2D
, dest_texture
->service_id());
13561 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13562 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
, 0, GL_RGBA
,
13563 GL_UNSIGNED_BYTE
, NULL
);
13564 error
= LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13565 if (error
!= GL_NO_ERROR
)
13568 texture_manager()->SetLevelInfo(
13569 dest_texture_ref
, GL_TEXTURE_2D
, 0, GL_RGBA
, dest_width
, dest_height
,
13570 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(dest_width
, dest_height
));
13572 copy_texture_CHROMIUM_
->DoCopyTexture(
13573 this, GL_TEXTURE_2D
, tmp_service_id
, GL_RGBA
,
13574 dest_texture
->service_id(), GL_RGBA
,
13575 dest_width
, dest_height
, false, false, false);
13577 glDeleteTextures(1, &tmp_service_id
);
13580 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13581 // crbug.com/226218.
13582 copy_texture_CHROMIUM_
->DoCopySubTexture(
13583 this, source_texture
->target(), source_texture
->service_id(),
13584 source_internal_format
, dest_texture
->service_id(), GL_RGBA
,
13585 xoffset
, yoffset
, x
, y
, width
, height
, dest_width
, dest_height
,
13586 source_width
, source_height
, false, false, false);
13588 DoDidUseTexImageIfNeeded(source_texture
, source_texture
->target());
13591 static GLenum
ExtractTypeFromStorageFormat(GLenum internalformat
) {
13592 switch (internalformat
) {
13594 return GL_UNSIGNED_BYTE
;
13598 return GL_HALF_FLOAT
;
13602 return GL_UNSIGNED_BYTE
;
13606 return GL_UNSIGNED_SHORT
;
13610 return GL_UNSIGNED_INT
;
13614 return GL_UNSIGNED_BYTE
;
13618 return GL_HALF_FLOAT
;
13622 return GL_UNSIGNED_BYTE
;
13626 return GL_UNSIGNED_SHORT
;
13630 return GL_UNSIGNED_INT
;
13635 return GL_UNSIGNED_BYTE
;
13636 case GL_R11F_G11F_B10F
:
13637 return GL_UNSIGNED_INT_10F_11F_11F_REV
;
13639 return GL_UNSIGNED_SHORT_5_6_5
;
13640 case GL_RGB8_SNORM
:
13643 return GL_UNSIGNED_INT_5_9_9_9_REV
;
13645 return GL_HALF_FLOAT
;
13649 return GL_UNSIGNED_BYTE
;
13653 return GL_UNSIGNED_SHORT
;
13657 return GL_UNSIGNED_INT
;
13661 return GL_UNSIGNED_BYTE
;
13662 case GL_SRGB8_ALPHA8
:
13663 return GL_UNSIGNED_BYTE
;
13664 case GL_RGBA8_SNORM
:
13667 return GL_UNSIGNED_SHORT_4_4_4_4
;
13669 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13671 return GL_UNSIGNED_SHORT_5_5_5_1
;
13673 return GL_HALF_FLOAT
;
13677 return GL_UNSIGNED_BYTE
;
13680 case GL_RGB10_A2UI
:
13681 return GL_UNSIGNED_INT_2_10_10_10_REV
;
13683 return GL_UNSIGNED_SHORT
;
13689 return GL_UNSIGNED_INT
;
13690 case GL_DEPTH_COMPONENT16
:
13691 return GL_UNSIGNED_SHORT
;
13692 case GL_DEPTH_COMPONENT24
:
13693 return GL_UNSIGNED_INT
;
13694 case GL_DEPTH_COMPONENT32F
:
13696 case GL_DEPTH24_STENCIL8
:
13697 return GL_UNSIGNED_INT_24_8
;
13698 case GL_DEPTH32F_STENCIL8
:
13699 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV
;
13700 case GL_LUMINANCE8_ALPHA8_EXT
:
13701 return GL_UNSIGNED_BYTE
;
13702 case GL_LUMINANCE8_EXT
:
13703 return GL_UNSIGNED_BYTE
;
13704 case GL_ALPHA8_EXT
:
13705 return GL_UNSIGNED_BYTE
;
13706 case GL_ALPHA32F_EXT
:
13708 case GL_LUMINANCE32F_EXT
:
13710 case GL_LUMINANCE_ALPHA32F_EXT
:
13712 case GL_ALPHA16F_EXT
:
13713 return GL_HALF_FLOAT_OES
;
13714 case GL_LUMINANCE16F_EXT
:
13715 return GL_HALF_FLOAT_OES
;
13716 case GL_LUMINANCE_ALPHA16F_EXT
:
13717 return GL_HALF_FLOAT_OES
;
13719 return GL_UNSIGNED_BYTE
;
13725 void GLES2DecoderImpl::DoTexStorage2DEXT(
13728 GLenum internal_format
,
13731 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13732 "width", width
, "height", height
);
13733 if (!texture_manager()->ValidForTarget(target
, 0, width
, height
, 1) ||
13734 TextureManager::ComputeMipMapCount(target
, width
, height
, 1) < levels
) {
13735 LOCAL_SET_GL_ERROR(
13736 GL_INVALID_VALUE
, "glTexStorage2DEXT", "dimensions out of range");
13739 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13741 if (!texture_ref
) {
13742 LOCAL_SET_GL_ERROR(
13743 GL_INVALID_OPERATION
,
13744 "glTexStorage2DEXT", "unknown texture for target");
13747 Texture
* texture
= texture_ref
->texture();
13748 if (texture
->IsAttachedToFramebuffer()) {
13749 framebuffer_state_
.clear_state_dirty
= true;
13751 if (texture
->IsImmutable()) {
13752 LOCAL_SET_GL_ERROR(
13753 GL_INVALID_OPERATION
,
13754 "glTexStorage2DEXT", "texture is immutable");
13758 GLenum format
= ExtractFormatFromStorageFormat(internal_format
);
13759 GLenum type
= ExtractTypeFromStorageFormat(internal_format
);
13762 GLsizei level_width
= width
;
13763 GLsizei level_height
= height
;
13764 uint32 estimated_size
= 0;
13765 for (int ii
= 0; ii
< levels
; ++ii
) {
13766 uint32 level_size
= 0;
13767 if (!GLES2Util::ComputeImageDataSizes(
13768 level_width
, level_height
, 1, format
, type
, state_
.unpack_alignment
,
13769 &estimated_size
, NULL
, NULL
) ||
13770 !SafeAddUint32(estimated_size
, level_size
, &estimated_size
)) {
13771 LOCAL_SET_GL_ERROR(
13772 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "dimensions too large");
13775 level_width
= std::max(1, level_width
>> 1);
13776 level_height
= std::max(1, level_height
>> 1);
13778 if (!EnsureGPUMemoryAvailable(estimated_size
)) {
13779 LOCAL_SET_GL_ERROR(
13780 GL_OUT_OF_MEMORY
, "glTexStorage2DEXT", "out of memory");
13785 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13786 glTexStorage2DEXT(target
, levels
, internal_format
, width
, height
);
13787 GLenum error
= LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13788 if (error
== GL_NO_ERROR
) {
13789 GLsizei level_width
= width
;
13790 GLsizei level_height
= height
;
13792 GLenum cur_format
= feature_info_
->IsES3Enabled() ?
13793 internal_format
: format
;
13794 for (int ii
= 0; ii
< levels
; ++ii
) {
13795 if (target
== GL_TEXTURE_CUBE_MAP
) {
13796 for (int jj
= 0; jj
< 6; ++jj
) {
13797 GLenum face
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ jj
;
13798 texture_manager()->SetLevelInfo(texture_ref
, face
, ii
, cur_format
,
13799 level_width
, level_height
, 1, 0,
13800 format
, type
, gfx::Rect());
13803 texture_manager()->SetLevelInfo(texture_ref
, target
, ii
, cur_format
,
13804 level_width
, level_height
, 1, 0,
13805 format
, type
, gfx::Rect());
13807 level_width
= std::max(1, level_width
>> 1);
13808 level_height
= std::max(1, level_height
>> 1);
13810 texture
->SetImmutable(true);
13814 error::Error
GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13815 uint32 immediate_data_size
,
13816 const void* cmd_data
) {
13817 return error::kUnknownCommand
;
13820 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target
,
13821 const GLbyte
* data
) {
13822 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13823 "context", logger_
.GetLogPrefix(),
13824 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13826 TextureRef
* texture_ref
= texture_manager()->GetTextureInfoForTarget(
13828 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref
, target
, data
);
13831 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id
,
13832 GLenum target
, const GLbyte
* data
) {
13833 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13834 "context", logger_
.GetLogPrefix(),
13835 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13837 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id
),
13841 void GLES2DecoderImpl::ProduceTextureRef(const char* func_name
,
13842 TextureRef
* texture_ref
,
13844 const GLbyte
* data
) {
13845 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13846 DLOG_IF(ERROR
, !mailbox
.Verify()) << func_name
<< " was passed a "
13847 "mailbox that was not generated by "
13848 "GenMailboxCHROMIUM.";
13850 if (!texture_ref
) {
13851 LOCAL_SET_GL_ERROR(
13852 GL_INVALID_OPERATION
, func_name
, "unknown texture for target");
13856 Texture
* produced
= texture_manager()->Produce(texture_ref
);
13858 LOCAL_SET_GL_ERROR(
13859 GL_INVALID_OPERATION
, func_name
, "invalid texture");
13863 if (produced
->target() != target
) {
13864 LOCAL_SET_GL_ERROR(
13865 GL_INVALID_OPERATION
, func_name
, "invalid target");
13869 group_
->mailbox_manager()->ProduceTexture(mailbox
, produced
);
13872 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target
,
13873 const GLbyte
* data
) {
13874 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13875 "context", logger_
.GetLogPrefix(),
13876 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13877 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13878 DLOG_IF(ERROR
, !mailbox
.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13879 "mailbox that was not generated by "
13880 "GenMailboxCHROMIUM.";
13882 scoped_refptr
<TextureRef
> texture_ref
=
13883 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
13884 if (!texture_ref
.get()) {
13885 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
13886 "glConsumeTextureCHROMIUM",
13887 "unknown texture for target");
13890 GLuint client_id
= texture_ref
->client_id();
13892 LOCAL_SET_GL_ERROR(
13893 GL_INVALID_OPERATION
,
13894 "glConsumeTextureCHROMIUM", "unknown texture for target");
13897 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
13899 LOCAL_SET_GL_ERROR(
13900 GL_INVALID_OPERATION
,
13901 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13904 if (texture
->target() != target
) {
13905 LOCAL_SET_GL_ERROR(
13906 GL_INVALID_OPERATION
,
13907 "glConsumeTextureCHROMIUM", "invalid target");
13911 DeleteTexturesHelper(1, &client_id
);
13912 texture_ref
= texture_manager()->Consume(client_id
, texture
);
13913 glBindTexture(target
, texture_ref
->service_id());
13915 TextureUnit
& unit
= state_
.texture_units
[state_
.active_texture_unit
];
13916 unit
.bind_target
= target
;
13918 case GL_TEXTURE_2D
:
13919 unit
.bound_texture_2d
= texture_ref
;
13921 case GL_TEXTURE_CUBE_MAP
:
13922 unit
.bound_texture_cube_map
= texture_ref
;
13924 case GL_TEXTURE_EXTERNAL_OES
:
13925 unit
.bound_texture_external_oes
= texture_ref
;
13927 case GL_TEXTURE_RECTANGLE_ARB
:
13928 unit
.bound_texture_rectangle_arb
= texture_ref
;
13931 NOTREACHED(); // Validation should prevent us getting here.
13936 void GLES2DecoderImpl::EnsureTextureForClientId(
13938 GLuint client_id
) {
13939 TextureRef
* texture_ref
= GetTexture(client_id
);
13940 if (!texture_ref
) {
13942 glGenTextures(1, &service_id
);
13943 DCHECK_NE(0u, service_id
);
13944 texture_ref
= CreateTexture(client_id
, service_id
);
13945 texture_manager()->SetTarget(texture_ref
, target
);
13946 glBindTexture(target
, service_id
);
13947 RestoreCurrentTextureBindings(&state_
, target
);
13951 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13952 // provided is associated with a service_id/TextureRef for consistency, even if
13953 // the resulting texture is incomplete.
13954 error::Error
GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13955 uint32_t immediate_data_size
,
13956 const void* cmd_data
) {
13957 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
& c
=
13959 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate
*>(
13961 GLenum target
= static_cast<GLenum
>(c
.target
);
13962 uint32_t data_size
;
13963 if (!ComputeDataSize(1, sizeof(GLbyte
), 64, &data_size
)) {
13964 return error::kOutOfBounds
;
13966 if (data_size
> immediate_data_size
) {
13967 return error::kOutOfBounds
;
13969 const GLbyte
* mailbox
=
13970 GetImmediateDataAs
<const GLbyte
*>(c
, data_size
, immediate_data_size
);
13971 if (!validators_
->texture_bind_target
.IsValid(target
)) {
13972 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13973 "glCreateAndConsumeTextureCHROMIUM", target
, "target");
13974 return error::kNoError
;
13976 if (mailbox
== NULL
) {
13977 return error::kOutOfBounds
;
13979 uint32_t client_id
= c
.client_id
;
13980 DoCreateAndConsumeTextureCHROMIUM(target
, mailbox
, client_id
);
13981 return error::kNoError
;
13984 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target
,
13985 const GLbyte
* data
, GLuint client_id
) {
13986 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13987 "context", logger_
.GetLogPrefix(),
13988 "mailbox[0]", static_cast<unsigned char>(data
[0]));
13989 const Mailbox
& mailbox
= *reinterpret_cast<const Mailbox
*>(data
);
13990 DLOG_IF(ERROR
, !mailbox
.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13991 "passed a mailbox that was not "
13992 "generated by GenMailboxCHROMIUM.";
13994 TextureRef
* texture_ref
= GetTexture(client_id
);
13996 // No need to call EnsureTextureForClientId here, the client_id already has
13997 // an associated texture.
13998 LOCAL_SET_GL_ERROR(
13999 GL_INVALID_OPERATION
,
14000 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
14003 Texture
* texture
= group_
->mailbox_manager()->ConsumeTexture(mailbox
);
14005 EnsureTextureForClientId(target
, client_id
);
14006 LOCAL_SET_GL_ERROR(
14007 GL_INVALID_OPERATION
,
14008 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
14012 if (texture
->target() != target
) {
14013 EnsureTextureForClientId(target
, client_id
);
14014 LOCAL_SET_GL_ERROR(
14015 GL_INVALID_OPERATION
,
14016 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
14020 texture_ref
= texture_manager()->Consume(client_id
, texture
);
14023 void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() {
14024 // Apply CMAA(Conservative Morphological Anti-Aliasing) algorithm to the
14025 // color attachments of currently bound draw framebuffer.
14026 // Reference GL_INTEL_framebuffer_CMAA for details.
14027 glApplyFramebufferAttachmentCMAAINTEL();
14030 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id
) {
14031 const Valuebuffer
* valuebuffer
= GetValuebuffer(client_id
);
14032 return valuebuffer
&& valuebuffer
->IsValid();
14035 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target
,
14036 GLuint client_id
) {
14037 Valuebuffer
* valuebuffer
= NULL
;
14038 if (client_id
!= 0) {
14039 valuebuffer
= GetValuebuffer(client_id
);
14040 if (!valuebuffer
) {
14041 if (!group_
->bind_generates_resource()) {
14042 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "glBindValuebufferCHROMIUM",
14043 "id not generated by glBindValuebufferCHROMIUM");
14047 // It's a new id so make a valuebuffer for it.
14048 CreateValuebuffer(client_id
);
14049 valuebuffer
= GetValuebuffer(client_id
);
14051 valuebuffer
->MarkAsValid();
14053 state_
.bound_valuebuffer
= valuebuffer
;
14056 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target
,
14057 GLenum subscription
) {
14058 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
14061 state_
.bound_valuebuffer
.get()->AddSubscription(subscription
);
14064 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target
) {
14065 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
14068 valuebuffer_manager()->UpdateValuebufferState(state_
.bound_valuebuffer
.get());
14071 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location
,
14073 GLenum subscription
) {
14074 if (!CheckCurrentValuebufferForSubscription(
14075 subscription
, "glPopulateSubscribedValuesCHROMIUM")) {
14078 if (!CheckSubscriptionTarget(location
, subscription
,
14079 "glPopulateSubscribedValuesCHROMIUM")) {
14082 const ValueState
* state
=
14083 state_
.bound_valuebuffer
.get()->GetState(subscription
);
14085 switch (subscription
) {
14086 case GL_MOUSE_POSITION_CHROMIUM
:
14087 DoUniform2iv(location
, 1, state
->int_value
);
14090 NOTREACHED() << "Unhandled uniform subscription target "
14097 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
14098 GLsizei length
, const GLchar
* marker
) {
14102 debug_marker_manager_
.SetMarker(
14103 length
? std::string(marker
, length
) : std::string(marker
));
14106 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
14107 GLsizei
/*length*/, const GLchar
* /*marker*/) {
14110 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
14113 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
14114 GLenum target
, GLint image_id
) {
14115 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
14117 if (target
== GL_TEXTURE_CUBE_MAP
) {
14118 LOCAL_SET_GL_ERROR(
14120 "glBindTexImage2DCHROMIUM", "invalid target");
14124 // Default target might be conceptually valid, but disallow it to avoid
14126 TextureRef
* texture_ref
=
14127 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
14128 if (!texture_ref
) {
14129 LOCAL_SET_GL_ERROR(
14130 GL_INVALID_OPERATION
,
14131 "glBindTexImage2DCHROMIUM", "no texture bound");
14135 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
14137 LOCAL_SET_GL_ERROR(
14138 GL_INVALID_OPERATION
,
14139 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
14144 ScopedGLErrorSuppressor
suppressor(
14145 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
14146 if (!gl_image
->BindTexImage(target
)) {
14147 LOCAL_SET_GL_ERROR(
14148 GL_INVALID_OPERATION
,
14149 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
14154 gfx::Size size
= gl_image
->GetSize();
14155 texture_manager()->SetLevelInfo(
14156 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), size
.width(),
14157 size
.height(), 1, 0, gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
,
14159 texture_manager()->SetLevelImage(texture_ref
, target
, 0, gl_image
);
14162 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
14163 GLenum target
, GLint image_id
) {
14164 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
14166 // Default target might be conceptually valid, but disallow it to avoid
14168 TextureRef
* texture_ref
=
14169 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_
, target
);
14170 if (!texture_ref
) {
14171 LOCAL_SET_GL_ERROR(
14172 GL_INVALID_OPERATION
,
14173 "glReleaseTexImage2DCHROMIUM", "no texture bound");
14177 gfx::GLImage
* gl_image
= image_manager()->LookupImage(image_id
);
14179 LOCAL_SET_GL_ERROR(
14180 GL_INVALID_OPERATION
,
14181 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
14185 // Do nothing when image is not currently bound.
14186 if (texture_ref
->texture()->GetLevelImage(target
, 0) != gl_image
)
14190 ScopedGLErrorSuppressor
suppressor(
14191 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
14192 gl_image
->ReleaseTexImage(target
);
14195 texture_manager()->SetLevelInfo(
14196 texture_ref
, target
, 0, gl_image
->GetInternalFormat(), 0, 0, 1, 0,
14197 gl_image
->GetInternalFormat(), GL_UNSIGNED_BYTE
, gfx::Rect());
14200 error::Error
GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
14201 uint32 immediate_data_size
,
14202 const void* cmd_data
) {
14203 const gles2::cmds::TraceBeginCHROMIUM
& c
=
14204 *static_cast<const gles2::cmds::TraceBeginCHROMIUM
*>(cmd_data
);
14205 Bucket
* category_bucket
= GetBucket(c
.category_bucket_id
);
14206 Bucket
* name_bucket
= GetBucket(c
.name_bucket_id
);
14207 if (!category_bucket
|| category_bucket
->size() == 0 ||
14208 !name_bucket
|| name_bucket
->size() == 0) {
14209 return error::kInvalidArguments
;
14212 std::string category_name
;
14213 std::string trace_name
;
14214 if (!category_bucket
->GetAsString(&category_name
) ||
14215 !name_bucket
->GetAsString(&trace_name
)) {
14216 return error::kInvalidArguments
;
14219 debug_marker_manager_
.PushGroup(trace_name
);
14220 if (!gpu_tracer_
->Begin(category_name
, trace_name
, kTraceCHROMIUM
)) {
14221 LOCAL_SET_GL_ERROR(
14222 GL_INVALID_OPERATION
,
14223 "glTraceBeginCHROMIUM", "unable to create begin trace");
14224 return error::kNoError
;
14226 return error::kNoError
;
14229 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
14230 debug_marker_manager_
.PopGroup();
14231 if (!gpu_tracer_
->End(kTraceCHROMIUM
)) {
14232 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14233 "glTraceEndCHROMIUM", "no trace begin found");
14238 void GLES2DecoderImpl::DoDrawBuffersEXT(
14239 GLsizei count
, const GLenum
* bufs
) {
14240 if (count
> static_cast<GLsizei
>(group_
->max_draw_buffers())) {
14241 LOCAL_SET_GL_ERROR(
14243 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
14247 Framebuffer
* framebuffer
= GetFramebufferInfoForTarget(GL_FRAMEBUFFER
);
14249 for (GLsizei i
= 0; i
< count
; ++i
) {
14250 if (bufs
[i
] != static_cast<GLenum
>(GL_COLOR_ATTACHMENT0
+ i
) &&
14251 bufs
[i
] != GL_NONE
) {
14252 LOCAL_SET_GL_ERROR(
14253 GL_INVALID_OPERATION
,
14254 "glDrawBuffersEXT",
14255 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
14259 glDrawBuffersARB(count
, bufs
);
14260 framebuffer
->SetDrawBuffers(count
, bufs
);
14261 } else { // backbuffer
14263 (bufs
[0] != GL_BACK
&& bufs
[0] != GL_NONE
)) {
14264 LOCAL_SET_GL_ERROR(
14265 GL_INVALID_OPERATION
,
14266 "glDrawBuffersEXT",
14267 "more than one buffer or bufs not GL_NONE or GL_BACK");
14270 GLenum mapped_buf
= bufs
[0];
14271 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
14272 bufs
[0] == GL_BACK
) {
14273 mapped_buf
= GL_COLOR_ATTACHMENT0
;
14275 glDrawBuffersARB(count
, &mapped_buf
);
14276 back_buffer_draw_buffer_
= bufs
[0];
14280 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current
, GLenum other
) {
14281 MarkContextLost(GetContextLostReasonFromResetStatus(current
));
14282 group_
->LoseContexts(GetContextLostReasonFromResetStatus(other
));
14283 reset_by_robustness_extension_
= true;
14286 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
14287 // On Adreno Android devices we need to use a workaround to force caches to
14289 if (feature_info_
->workarounds().unbind_egl_context_to_flush_driver_caches
) {
14290 context_
->ReleaseCurrent(nullptr);
14291 context_
->MakeCurrent(surface_
.get());
14295 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode
,
14296 const GLfloat
* matrix
) {
14297 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
14298 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
14299 if (!features().chromium_path_rendering
) {
14300 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14301 "glMatrixLoadfCHROMIUM",
14302 "function not available");
14306 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
14307 ? state_
.projection_matrix
14308 : state_
.modelview_matrix
;
14309 memcpy(target_matrix
, matrix
, sizeof(GLfloat
) * 16);
14310 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14311 // since the values of the _NV and _CHROMIUM tokens match.
14312 glMatrixLoadfEXT(matrix_mode
, matrix
);
14315 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode
) {
14316 DCHECK(matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
||
14317 matrix_mode
== GL_PATH_MODELVIEW_CHROMIUM
);
14319 if (!features().chromium_path_rendering
) {
14320 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
,
14321 "glMatrixLoadIdentityCHROMIUM",
14322 "function not available");
14326 GLfloat
* target_matrix
= matrix_mode
== GL_PATH_PROJECTION_CHROMIUM
14327 ? state_
.projection_matrix
14328 : state_
.modelview_matrix
;
14329 memcpy(target_matrix
, kIdentityMatrix
, sizeof(kIdentityMatrix
));
14330 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
14331 // since the values of the _NV and _CHROMIUM tokens match.
14332 glMatrixLoadIdentityEXT(matrix_mode
);
14335 error::Error
GLES2DecoderImpl::HandleUniformBlockBinding(
14336 uint32_t immediate_data_size
, const void* cmd_data
) {
14337 if (!unsafe_es3_apis_enabled())
14338 return error::kUnknownCommand
;
14339 const gles2::cmds::UniformBlockBinding
& c
=
14340 *static_cast<const gles2::cmds::UniformBlockBinding
*>(cmd_data
);
14341 GLuint client_id
= c
.program
;
14342 GLuint index
= static_cast<GLuint
>(c
.index
);
14343 GLuint binding
= static_cast<GLuint
>(c
.binding
);
14344 Program
* program
= GetProgramInfoNotShader(
14345 client_id
, "glUniformBlockBinding");
14347 return error::kNoError
;
14349 GLuint service_id
= program
->service_id();
14350 glUniformBlockBinding(service_id
, index
, binding
);
14351 return error::kNoError
;
14354 error::Error
GLES2DecoderImpl::HandleClientWaitSync(
14355 uint32_t immediate_data_size
, const void* cmd_data
) {
14356 if (!unsafe_es3_apis_enabled())
14357 return error::kUnknownCommand
;
14358 const gles2::cmds::ClientWaitSync
& c
=
14359 *static_cast<const gles2::cmds::ClientWaitSync
*>(cmd_data
);
14360 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14361 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14362 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14363 typedef cmds::ClientWaitSync::Result Result
;
14364 Result
* result_dst
= GetSharedMemoryAs
<Result
*>(
14365 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result_dst
));
14367 return error::kOutOfBounds
;
14369 if (*result_dst
!= GL_WAIT_FAILED
) {
14370 return error::kInvalidArguments
;
14372 GLsync service_sync
= 0;
14373 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14374 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "ClientWaitSync", "invalid sync");
14375 return error::kNoError
;
14377 *result_dst
= glClientWaitSync(service_sync
, flags
, timeout
);
14378 return error::kNoError
;
14381 error::Error
GLES2DecoderImpl::HandleWaitSync(
14382 uint32_t immediate_data_size
, const void* cmd_data
) {
14383 if (!unsafe_es3_apis_enabled())
14384 return error::kUnknownCommand
;
14385 const gles2::cmds::WaitSync
& c
=
14386 *static_cast<const gles2::cmds::WaitSync
*>(cmd_data
);
14387 GLuint sync
= static_cast<GLuint
>(c
.sync
);
14388 GLbitfield flags
= static_cast<GLbitfield
>(c
.flags
);
14389 GLuint64 timeout
= GLES2Util::MapTwoUint32ToUint64(c
.timeout_0
, c
.timeout_1
);
14390 GLsync service_sync
= 0;
14391 if (!group_
->GetSyncServiceId(sync
, &service_sync
)) {
14392 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, "WaitSync", "invalid sync");
14393 return error::kNoError
;
14395 glWaitSync(service_sync
, flags
, timeout
);
14396 return error::kNoError
;
14399 error::Error
GLES2DecoderImpl::HandleGetInternalformativ(
14400 uint32_t immediate_data_size
, const void* cmd_data
) {
14401 if (!unsafe_es3_apis_enabled())
14402 return error::kUnknownCommand
;
14403 const gles2::cmds::GetInternalformativ
& c
=
14404 *static_cast<const gles2::cmds::GetInternalformativ
*>(cmd_data
);
14405 GLenum target
= static_cast<GLenum
>(c
.target
);
14406 GLenum format
= static_cast<GLenum
>(c
.format
);
14407 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14408 if (!validators_
->render_buffer_target
.IsValid(target
)) {
14409 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target
, "target");
14410 return error::kNoError
;
14412 if (!validators_
->render_buffer_format
.IsValid(format
)) {
14413 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format
, "format");
14414 return error::kNoError
;
14416 if (!validators_
->internal_format_parameter
.IsValid(pname
)) {
14417 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname
, "pname");
14418 return error::kNoError
;
14420 typedef cmds::GetInternalformativ::Result Result
;
14421 GLsizei num_values
= 0;
14423 case GL_NUM_SAMPLE_COUNTS
:
14429 glGetInternalformativ(target
, format
, GL_NUM_SAMPLE_COUNTS
, 1, &value
);
14430 num_values
= static_cast<GLsizei
>(value
);
14437 Result
* result
= GetSharedMemoryAs
<Result
*>(
14438 c
.params_shm_id
, c
.params_shm_offset
, Result::ComputeSize(num_values
));
14439 GLint
* params
= result
? result
->GetData() : NULL
;
14440 if (params
== NULL
) {
14441 return error::kOutOfBounds
;
14443 // Check that the client initialized the result.
14444 if (result
->size
!= 0) {
14445 return error::kInvalidArguments
;
14447 glGetInternalformativ(target
, format
, pname
, num_values
, params
);
14448 result
->SetNumResults(num_values
);
14449 return error::kNoError
;
14452 error::Error
GLES2DecoderImpl::HandleMapBufferRange(
14453 uint32_t immediate_data_size
, const void* cmd_data
) {
14454 if (!unsafe_es3_apis_enabled()) {
14455 return error::kUnknownCommand
;
14457 const gles2::cmds::MapBufferRange
& c
=
14458 *static_cast<const gles2::cmds::MapBufferRange
*>(cmd_data
);
14459 GLenum target
= static_cast<GLenum
>(c
.target
);
14460 GLbitfield access
= static_cast<GLbitfield
>(c
.access
);
14461 GLintptr offset
= static_cast<GLintptr
>(c
.offset
);
14462 GLsizeiptr size
= static_cast<GLsizeiptr
>(c
.size
);
14464 typedef cmds::MapBufferRange::Result Result
;
14465 Result
* result
= GetSharedMemoryAs
<Result
*>(
14466 c
.result_shm_id
, c
.result_shm_offset
, sizeof(*result
));
14468 return error::kOutOfBounds
;
14470 if (*result
!= 0) {
14472 return error::kInvalidArguments
;
14475 GetSharedMemoryAs
<int8_t*>(c
.data_shm_id
, c
.data_shm_offset
, size
);
14477 return error::kOutOfBounds
;
14480 GLbitfield mask
= GL_MAP_INVALIDATE_BUFFER_BIT
;
14481 if ((access
& mask
) == mask
) {
14482 // TODO(zmo): To be on the safe side, always map
14483 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14484 access
= (access
& ~GL_MAP_INVALIDATE_BUFFER_BIT
);
14485 access
= (access
| GL_MAP_INVALIDATE_RANGE_BIT
);
14487 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14488 // undefined behaviors.
14489 mask
= GL_MAP_READ_BIT
| GL_MAP_UNSYNCHRONIZED_BIT
;
14490 if ((access
& mask
) == mask
) {
14491 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "MapBufferRange",
14492 "incompatible access bits");
14493 return error::kNoError
;
14495 access
= (access
& ~GL_MAP_UNSYNCHRONIZED_BIT
);
14496 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
&&
14497 (access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14498 access
= (access
| GL_MAP_READ_BIT
);
14500 void* ptr
= glMapBufferRange(target
, offset
, size
, access
);
14501 if (ptr
== nullptr) {
14502 return error::kNoError
;
14504 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14506 buffer
->SetMappedRange(offset
, size
, access
, ptr
,
14507 GetSharedMemoryBuffer(c
.data_shm_id
));
14508 if ((access
& GL_MAP_INVALIDATE_RANGE_BIT
) == 0) {
14509 memcpy(mem
, ptr
, size
);
14512 return error::kNoError
;
14515 error::Error
GLES2DecoderImpl::HandleUnmapBuffer(
14516 uint32_t immediate_data_size
, const void* cmd_data
) {
14517 if (!unsafe_es3_apis_enabled()) {
14518 return error::kUnknownCommand
;
14520 const gles2::cmds::UnmapBuffer
& c
=
14521 *static_cast<const gles2::cmds::UnmapBuffer
*>(cmd_data
);
14522 GLenum target
= static_cast<GLenum
>(c
.target
);
14524 Buffer
* buffer
= buffer_manager()->GetBufferInfoForTarget(&state_
, target
);
14526 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer", "no buffer bound");
14527 return error::kNoError
;
14529 const Buffer::MappedRange
* mapped_range
= buffer
->GetMappedRange();
14530 if (!mapped_range
) {
14531 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, "UnmapBuffer",
14532 "buffer is unmapped");
14533 return error::kNoError
;
14535 if ((mapped_range
->access
& GL_MAP_WRITE_BIT
) == 0 ||
14536 (mapped_range
->access
& GL_MAP_FLUSH_EXPLICIT_BIT
) ==
14537 GL_MAP_FLUSH_EXPLICIT_BIT
) {
14538 // If we don't need to write back, or explict flush is required, no copying
14541 void* mem
= mapped_range
->GetShmPointer();
14543 return error::kOutOfBounds
;
14545 DCHECK(mapped_range
->pointer
);
14546 memcpy(mapped_range
->pointer
, mem
, mapped_range
->size
);
14548 buffer
->RemoveMappedRange();
14549 GLboolean rt
= glUnmapBuffer(target
);
14550 if (rt
== GL_FALSE
) {
14551 // At this point, we have already done the necessary validation, so
14552 // GL_FALSE indicates data corruption.
14553 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14554 // the second unmap could still return GL_FALSE. For now, we simply lose
14555 // the contexts in the share group.
14556 LOG(ERROR
) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14557 // Need to lose current context before broadcasting!
14558 MarkContextLost(error::kGuilty
);
14559 group_
->LoseContexts(error::kInnocent
);
14560 return error::kLostContext
;
14562 return error::kNoError
;
14565 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14566 TextureRef
* texture_ref
) {
14567 Texture
* texture
= texture_ref
->texture();
14568 DoDidUseTexImageIfNeeded(texture
, texture
->target());
14571 // Note that GL_LOST_CONTEXT is specific to GLES.
14572 // For desktop GL we have to query the reset status proactively.
14573 void GLES2DecoderImpl::OnContextLostError() {
14574 if (!WasContextLost()) {
14575 // Need to lose current context before broadcasting!
14576 CheckResetStatus();
14577 group_
->LoseContexts(error::kUnknown
);
14578 reset_by_robustness_extension_
= true;
14582 void GLES2DecoderImpl::OnOutOfMemoryError() {
14583 if (lose_context_when_out_of_memory_
&& !WasContextLost()) {
14584 error::ContextLostReason other
= error::kOutOfMemory
;
14585 if (CheckResetStatus()) {
14586 other
= error::kUnknown
;
14588 // Need to lose current context before broadcasting!
14589 MarkContextLost(error::kOutOfMemory
);
14591 group_
->LoseContexts(other
);
14595 error::Error
GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14596 uint32 immediate_data_size
,
14597 const void* cmd_data
) {
14598 static const char kFunctionName
[] = "glGenPathsCHROMIUM";
14599 const gles2::cmds::GenPathsCHROMIUM
& c
=
14600 *static_cast<const gles2::cmds::GenPathsCHROMIUM
*>(cmd_data
);
14601 if (!features().chromium_path_rendering
) {
14602 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14603 "function not available");
14604 return error::kNoError
;
14607 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14609 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14610 return error::kNoError
;
14613 GLuint first_client_id
= static_cast<GLuint
>(c
.first_client_id
);
14614 if (first_client_id
== 0)
14615 return error::kInvalidArguments
;
14618 return error::kNoError
;
14620 if (!GenPathsCHROMIUMHelper(first_client_id
, range
))
14621 return error::kInvalidArguments
;
14623 return error::kNoError
;
14625 error::Error
GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14626 uint32_t immediate_data_size
,
14627 const void* cmd_data
) {
14628 static const char kFunctionName
[] = "glDeletePathsCHROMIUM";
14629 const gles2::cmds::DeletePathsCHROMIUM
& c
=
14630 *static_cast<const gles2::cmds::DeletePathsCHROMIUM
*>(cmd_data
);
14631 if (!features().chromium_path_rendering
) {
14632 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14633 "function not available");
14634 return error::kNoError
;
14637 GLsizei range
= static_cast<GLsizei
>(c
.range
);
14639 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "range < 0");
14640 return error::kNoError
;
14644 return error::kNoError
;
14646 GLuint first_client_id
= c
.first_client_id
;
14647 // first_client_id can be 0, because non-existing path ids are skipped.
14649 if (!DeletePathsCHROMIUMHelper(first_client_id
, range
))
14650 return error::kInvalidArguments
;
14652 return error::kNoError
;
14655 error::Error
GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14656 uint32 immediate_data_size
,
14657 const void* cmd_data
) {
14658 static const char kFunctionName
[] = "glPathCommandsCHROMIUM";
14659 const gles2::cmds::PathCommandsCHROMIUM
& c
=
14660 *static_cast<const gles2::cmds::PathCommandsCHROMIUM
*>(cmd_data
);
14661 if (!features().chromium_path_rendering
) {
14662 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14663 "function not available");
14664 return error::kNoError
;
14667 GLuint service_id
= 0;
14668 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14670 "invalid path name");
14671 return error::kNoError
;
14674 GLsizei num_commands
= static_cast<GLsizei
>(c
.numCommands
);
14675 if (num_commands
< 0) {
14676 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCommands < 0");
14677 return error::kNoError
;
14680 GLsizei num_coords
= static_cast<uint32
>(c
.numCoords
);
14681 if (num_coords
< 0) {
14682 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "numCoords < 0");
14683 return error::kNoError
;
14686 GLenum coord_type
= static_cast<uint32
>(c
.coordType
);
14687 if (!validators_
->path_coord_type
.IsValid(static_cast<GLint
>(coord_type
))) {
14688 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid coordType");
14689 return error::kNoError
;
14692 const GLubyte
* commands
= NULL
;
14693 base::CheckedNumeric
<GLsizei
> num_coords_expected
= 0;
14695 if (num_commands
> 0) {
14696 uint32 commands_shm_id
= static_cast<uint32
>(c
.commands_shm_id
);
14697 uint32 commands_shm_offset
= static_cast<uint32
>(c
.commands_shm_offset
);
14698 if (commands_shm_id
!= 0 || commands_shm_offset
!= 0)
14699 commands
= GetSharedMemoryAs
<const GLubyte
*>(
14700 commands_shm_id
, commands_shm_offset
, num_commands
);
14703 return error::kOutOfBounds
;
14705 for (GLsizei i
= 0; i
< num_commands
; ++i
) {
14706 switch (commands
[i
]) {
14707 case GL_CLOSE_PATH_CHROMIUM
:
14708 // Close has no coords.
14710 case GL_MOVE_TO_CHROMIUM
:
14712 case GL_LINE_TO_CHROMIUM
:
14713 num_coords_expected
+= 2;
14715 case GL_QUADRATIC_CURVE_TO_CHROMIUM
:
14716 num_coords_expected
+= 4;
14718 case GL_CUBIC_CURVE_TO_CHROMIUM
:
14719 num_coords_expected
+= 6;
14721 case GL_CONIC_CURVE_TO_CHROMIUM
:
14722 num_coords_expected
+= 5;
14725 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM
, kFunctionName
, "invalid command");
14726 return error::kNoError
;
14731 if (!num_coords_expected
.IsValid() ||
14732 num_coords
!= num_coords_expected
.ValueOrDie()) {
14733 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14734 "numCoords does not match commands");
14735 return error::kNoError
;
14738 const void* coords
= NULL
;
14740 if (num_coords
> 0) {
14741 uint32 coords_size
= 0;
14742 uint32 coord_type_size
=
14743 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type
);
14744 if (!SafeMultiplyUint32(num_coords
, coord_type_size
, &coords_size
))
14745 return error::kOutOfBounds
;
14747 uint32 coords_shm_id
= static_cast<uint32
>(c
.coords_shm_id
);
14748 uint32 coords_shm_offset
= static_cast<uint32
>(c
.coords_shm_offset
);
14749 if (coords_shm_id
!= 0 || coords_shm_offset
!= 0)
14750 coords
= GetSharedMemoryAs
<const void*>(coords_shm_id
, coords_shm_offset
,
14754 return error::kOutOfBounds
;
14757 glPathCommandsNV(service_id
, num_commands
, commands
, num_coords
, coord_type
,
14760 return error::kNoError
;
14763 error::Error
GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14764 uint32 immediate_data_size
,
14765 const void* cmd_data
) {
14766 static const char kFunctionName
[] = "glPathParameterfCHROMIUM";
14767 const gles2::cmds::PathParameterfCHROMIUM
& c
=
14768 *static_cast<const gles2::cmds::PathParameterfCHROMIUM
*>(cmd_data
);
14769 if (!features().chromium_path_rendering
) {
14770 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14771 "function not available");
14772 return error::kNoError
;
14774 GLuint service_id
= 0;
14775 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14776 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14777 "invalid path name");
14778 return error::kNoError
;
14781 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14782 GLfloat value
= static_cast<GLfloat
>(c
.value
);
14783 bool hasValueError
= false;
14786 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14787 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14788 hasValueError
= std::isnan(value
) || !std::isfinite(value
) || value
< 0;
14790 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14791 value
= std::max(std::min(1.0f
, value
), 0.0f
);
14793 case GL_PATH_END_CAPS_CHROMIUM
:
14794 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(
14795 static_cast<GLint
>(value
));
14797 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14798 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(
14799 static_cast<GLint
>(value
));
14802 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14803 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14804 return error::kNoError
;
14806 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14808 if (hasValueError
) {
14809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14810 return error::kNoError
;
14813 glPathParameterfNV(service_id
, pname
, value
);
14814 return error::kNoError
;
14817 error::Error
GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14818 uint32 immediate_data_size
,
14819 const void* cmd_data
) {
14820 static const char kFunctionName
[] = "glPathParameteriCHROMIUM";
14821 const gles2::cmds::PathParameteriCHROMIUM
& c
=
14822 *static_cast<const gles2::cmds::PathParameteriCHROMIUM
*>(cmd_data
);
14823 if (!features().chromium_path_rendering
) {
14824 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14825 "function not available");
14826 return error::kNoError
;
14828 GLuint service_id
= 0;
14829 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14830 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14831 "invalid path name");
14832 return error::kNoError
;
14835 GLenum pname
= static_cast<GLenum
>(c
.pname
);
14836 GLint value
= static_cast<GLint
>(c
.value
);
14837 bool hasValueError
= false;
14840 case GL_PATH_STROKE_WIDTH_CHROMIUM
:
14841 case GL_PATH_MITER_LIMIT_CHROMIUM
:
14842 hasValueError
= value
< 0;
14844 case GL_PATH_STROKE_BOUND_CHROMIUM
:
14845 value
= std::max(std::min(1, value
), 0);
14847 case GL_PATH_END_CAPS_CHROMIUM
:
14848 hasValueError
= !validators_
->path_parameter_cap_values
.IsValid(value
);
14850 case GL_PATH_JOIN_STYLE_CHROMIUM
:
14851 hasValueError
= !validators_
->path_parameter_join_values
.IsValid(value
);
14854 DCHECK(!validators_
->path_parameter
.IsValid(pname
));
14855 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, pname
, "pname");
14856 return error::kNoError
;
14858 DCHECK(validators_
->path_parameter
.IsValid(pname
));
14860 if (hasValueError
) {
14861 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
, "value not correct");
14862 return error::kNoError
;
14865 glPathParameteriNV(service_id
, pname
, value
);
14866 return error::kNoError
;
14869 error::Error
GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14870 uint32 immediate_data_size
,
14871 const void* cmd_data
) {
14872 static const char kFunctionName
[] = "glStencilFillPathCHROMIUM";
14873 const gles2::cmds::StencilFillPathCHROMIUM
& c
=
14874 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM
*>(cmd_data
);
14875 if (!features().chromium_path_rendering
) {
14876 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14877 "function not available");
14878 return error::kNoError
;
14880 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14881 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14882 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14883 return error::kNoError
;
14885 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14886 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14887 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14888 GLES2Util::IsNPOT(mask
+ 1)) {
14889 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14890 "mask + 1 is not power of two");
14891 return error::kNoError
;
14893 GLuint service_id
= 0;
14894 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14895 // "If /path/ does not name an existing path object, the command does
14896 // nothing (and no error is generated)."
14897 // This holds for other rendering functions, too.
14898 return error::kNoError
;
14901 glStencilFillPathNV(service_id
, fill_mode
, mask
);
14902 return error::kNoError
;
14905 error::Error
GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14906 uint32 immediate_data_size
,
14907 const void* cmd_data
) {
14908 static const char kFunctionName
[] = "glStencilStrokePathCHROMIUM";
14909 const gles2::cmds::StencilStrokePathCHROMIUM
& c
=
14910 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM
*>(cmd_data
);
14911 if (!features().chromium_path_rendering
) {
14912 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14913 "function not available");
14914 return error::kNoError
;
14916 GLuint service_id
= 0;
14917 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
)) {
14918 return error::kNoError
;
14920 GLint reference
= static_cast<GLint
>(c
.reference
);
14921 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14923 glStencilStrokePathNV(service_id
, reference
, mask
);
14924 return error::kNoError
;
14927 error::Error
GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14928 uint32 immediate_data_size
,
14929 const void* cmd_data
) {
14930 static const char kFunctionName
[] = "glCoverFillPathCHROMIUM";
14931 const gles2::cmds::CoverFillPathCHROMIUM
& c
=
14932 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM
*>(cmd_data
);
14933 if (!features().chromium_path_rendering
) {
14934 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14935 "function not available");
14936 return error::kNoError
;
14938 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14939 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14940 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14941 return error::kNoError
;
14943 GLuint service_id
= 0;
14944 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14945 return error::kNoError
;
14948 glCoverFillPathNV(service_id
, cover_mode
);
14949 return error::kNoError
;
14952 error::Error
GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14953 uint32 immediate_data_size
,
14954 const void* cmd_data
) {
14955 static const char kFunctionName
[] = "glCoverStrokePathCHROMIUM";
14956 const gles2::cmds::CoverStrokePathCHROMIUM
& c
=
14957 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM
*>(cmd_data
);
14958 if (!features().chromium_path_rendering
) {
14959 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14960 "function not available");
14961 return error::kNoError
;
14963 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
14964 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
14965 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
14966 return error::kNoError
;
14968 GLuint service_id
= 0;
14969 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
14970 return error::kNoError
;
14973 glCoverStrokePathNV(service_id
, cover_mode
);
14974 return error::kNoError
;
14977 error::Error
GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14978 uint32 immediate_data_size
,
14979 const void* cmd_data
) {
14980 static const char kFunctionName
[] = "glStencilThenCoverFillPathCHROMIUM";
14981 const gles2::cmds::StencilThenCoverFillPathCHROMIUM
& c
=
14982 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM
*>(
14984 if (!features().chromium_path_rendering
) {
14985 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
14986 "function not available");
14987 return error::kNoError
;
14989 GLenum fill_mode
= static_cast<GLenum
>(c
.fillMode
);
14990 if (!validators_
->path_fill_mode
.IsValid(fill_mode
)) {
14991 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, fill_mode
, "fillMode");
14992 return error::kNoError
;
14994 GLuint mask
= static_cast<GLuint
>(c
.mask
);
14995 if ((fill_mode
== GL_COUNT_UP_CHROMIUM
||
14996 fill_mode
== GL_COUNT_DOWN_CHROMIUM
) &&
14997 GLES2Util::IsNPOT(mask
+ 1)) {
14998 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE
, kFunctionName
,
14999 "mask + 1 is not power of two");
15000 return error::kNoError
;
15002 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
15003 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
15004 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
15005 return error::kNoError
;
15007 GLuint service_id
= 0;
15008 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
15009 return error::kNoError
;
15012 glStencilThenCoverFillPathNV(service_id
, fill_mode
, mask
, cover_mode
);
15013 return error::kNoError
;
15016 error::Error
GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
15017 uint32 immediate_data_size
,
15018 const void* cmd_data
) {
15019 static const char kFunctionName
[] = "glStencilThenCoverStrokePathCHROMIUM";
15020 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
& c
=
15021 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM
*>(
15023 if (!features().chromium_path_rendering
) {
15024 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION
, kFunctionName
,
15025 "function not available");
15026 return error::kNoError
;
15028 GLenum cover_mode
= static_cast<GLenum
>(c
.coverMode
);
15029 if (!validators_
->path_cover_mode
.IsValid(cover_mode
)) {
15030 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName
, cover_mode
, "coverMode");
15031 return error::kNoError
;
15033 GLuint service_id
= 0;
15034 if (!path_manager()->GetPath(static_cast<GLuint
>(c
.path
), &service_id
))
15035 return error::kNoError
;
15037 GLint reference
= static_cast<GLint
>(c
.reference
);
15038 GLuint mask
= static_cast<GLuint
>(c
.mask
);
15040 glStencilThenCoverStrokePathNV(service_id
, reference
, mask
, cover_mode
);
15041 return error::kNoError
;
15044 // Include the auto-generated part of this file. We split this because it means
15045 // we can easily edit the non-auto generated parts right here in this file
15046 // instead of having to edit some template or the code generator.
15047 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
15049 } // namespace gles2